Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
daddb9e
[analyzer] Handle `[[assume(cond)]]` as `__builtin_assume(cond)`
vinay-deshmukh Nov 15, 2024
7f1e341
NFC Simplify ExprEngine::VisitAttributedStmt
steakhal Nov 18, 2024
f4307e9
NFC Simplify AttributedStmt handling in clang CFG
steakhal Nov 18, 2024
c2b5e71
NFC Clarify test comment
steakhal Nov 18, 2024
3d4953f
NFC De-indent some tests
steakhal Nov 18, 2024
57751d1
NFC Mention the size of the array in its name
steakhal Nov 18, 2024
75e964a
Add broken test about sideeffects
steakhal Nov 18, 2024
d55851b
[clang] Generalize getSpecificAttr for const attributes
steakhal Nov 18, 2024
c288bdc
Ignore assumptions with side-effects
vinay-deshmukh Nov 29, 2024
f79ad87
Merge remote-tracking branch 'upstream/main' into vinay-issue-100762
vinay-deshmukh Nov 29, 2024
b4e278a
Merge branch 'main' into vinay-issue-100762
vinay-deshmukh Nov 29, 2024
8b877d1
Merge branch 'main' into vinay-issue-100762
vinay-deshmukh Dec 9, 2024
eabbef2
Add ternary test for assumption
vinay-deshmukh Dec 10, 2024
ae2038f
Merge remote-tracking branch 'upstream/main' into vinay-issue-100762
vinay-deshmukh Dec 17, 2024
c3d1c1a
clean
vinay-deshmukh Dec 17, 2024
e71023b
Merge branch 'main' into vinay-issue-100762
vinay-deshmukh Dec 18, 2024
02c009d
Merge branch 'main' into vinay-issue-100762
vinay-deshmukh Dec 18, 2024
3736854
Cleanup
steakhal Dec 19, 2024
d4c4e14
Merge remote-tracking branch 'llvm' into vinay-issue-100762
steakhal Dec 19, 2024
342ef04
Update clang/test/Analysis/cxx23-assume-attribute.cpp
steakhal Dec 19, 2024
670b358
Fix test
steakhal Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions clang/include/clang/AST/AttrIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
#define LLVM_CLANG_AST_ATTRITERATOR_H

#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ADL.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <type_traits>

namespace clang {

Expand Down Expand Up @@ -113,13 +115,13 @@ inline bool hasSpecificAttr(const Container& container) {
specific_attr_end<SpecificAttr>(container);
}
template <typename SpecificAttr, typename Container>
inline SpecificAttr *getSpecificAttr(const Container& container) {
specific_attr_iterator<SpecificAttr, Container> i =
specific_attr_begin<SpecificAttr>(container);
if (i != specific_attr_end<SpecificAttr>(container))
return *i;
else
return nullptr;
inline auto *getSpecificAttr(const Container &container) {
using ValueTy = llvm::detail::ValueOfRange<Container>;
using ValuePointeeTy = std::remove_pointer_t<ValueTy>;
using IterTy = std::conditional_t<std::is_const_v<ValuePointeeTy>,
const SpecificAttr, SpecificAttr>;
auto It = specific_attr_begin<IterTy>(container);
return It != specific_attr_end<IterTy>(container) ? *It : nullptr;
}

} // namespace clang
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,10 @@ class ExprEngine {
void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
ExplodedNodeSet &Dst);

/// VisitAttributedStmt - Transfer function logic for AttributedStmt
void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred,
ExplodedNodeSet &Dst);

/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
Expand Down
25 changes: 25 additions & 0 deletions clang/lib/Analysis/CFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,18 @@ reverse_children::reverse_children(Stmt *S) {
IE->getNumInits());
return;
}
case Stmt::AttributedStmtClass: {
auto Attrs = cast<AttributedStmt>(S)->getAttrs();

// We only handle `[[assume(...)]]` attributes for now.
if (const auto *A = getSpecificAttr<CXXAssumeAttr>(Attrs)) {
childrenBuf.push_back(A->getAssumption());
llvm::append_range(childrenBuf, S->children());
children = childrenBuf;
return;
}
break;
}
default:
break;
}
Expand Down Expand Up @@ -2475,6 +2487,14 @@ static bool isFallthroughStatement(const AttributedStmt *A) {
return isFallthrough;
}

static bool isCXXAssumeAttr(const AttributedStmt *A) {
bool hasAssumeAttr = hasSpecificAttr<CXXAssumeAttr>(A->getAttrs());

assert((!hasAssumeAttr || isa<NullStmt>(A->getSubStmt())) &&
"expected [[assume]] not to have children");
return hasAssumeAttr;
}

CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
AddStmtChoice asc) {
// AttributedStmts for [[likely]] can have arbitrary statements as children,
Expand All @@ -2490,6 +2510,11 @@ CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
appendStmt(Block, A);
}

if (isCXXAssumeAttr(A) && asc.alwaysAdd(*this, A)) {
autoCreateBlock();
appendStmt(Block, A);
}

return VisitChildren(A);
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGLoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
// Identify loop attribute 'code_align' from Attrs.
// For attribute code_align:
// n - 'llvm.loop.align i32 n' metadata will be emitted.
if (const auto *CodeAlign = getSpecificAttr<const CodeAlignAttr>(Attrs)) {
if (const auto *CodeAlign = getSpecificAttr<CodeAlignAttr>(Attrs)) {
const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
llvm::APSInt ArgVal = CE->getResultAsAPSInt();
setCodeAlign(ArgVal.getSExtValue());
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1946,7 +1946,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
// to be explicitly evaluated.
case Stmt::PredefinedExprClass:
case Stmt::AddrLabelExprClass:
case Stmt::AttributedStmtClass:
case Stmt::IntegerLiteralClass:
case Stmt::FixedPointLiteralClass:
case Stmt::CharacterLiteralClass:
Expand Down Expand Up @@ -1977,6 +1976,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break;
}

case Stmt::AttributedStmtClass: {
Bldr.takeNodes(Pred);
VisitAttributedStmt(cast<AttributedStmt>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
}

case Stmt::CXXDefaultArgExprClass:
case Stmt::CXXDefaultInitExprClass: {
Bldr.takeNodes(Pred);
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,3 +1200,20 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
// FIXME: Move all post/pre visits to ::Visit().
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this);
}

void ExprEngine::VisitAttributedStmt(const AttributedStmt *A,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
ExplodedNodeSet CheckerPreStmt;
getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);

ExplodedNodeSet EvalSet;
StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);

if (const auto *AssumeAttr = getSpecificAttr<CXXAssumeAttr>(A->getAttrs())) {
for (ExplodedNode *N : CheckerPreStmt) {
Visit(AssumeAttr->getAssumption(), N, EvalSet);
}
}

getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
}
30 changes: 29 additions & 1 deletion clang/test/Analysis/out-of-bounds-new.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
// RUN: %clang_analyze_cc1 -std=c++11 -Wno-array-bounds -analyzer-checker=unix,core,alpha.security.ArrayBoundV2 -verify %s
// RUN: %clang_analyze_cc1 -std=c++11 -Wno-array-bounds -verify %s \
// RUN: -analyzer-checker=unix,core,alpha.security.ArrayBoundV2,debug.ExprInspection

template <typename T> void clang_analyzer_dump(T);
template <typename T> void clang_analyzer_value(T);
void clang_analyzer_eval(bool);

// Tests doing an out-of-bounds access after the end of an array using:
// - constant integer index
Expand Down Expand Up @@ -180,3 +185,26 @@ int test_reference_that_might_be_after_the_end(int idx) {
return ref;
}

// From: https://github.com/llvm/llvm-project/issues/100762
extern int arrOf10[10];
void using_builtin(int x) {
__builtin_assume(x > 101); // CallExpr
arrOf10[x] = 404; // expected-warning{{Out of bound access to memory}}
}

void using_assume_attr(int ax) {
[[assume(ax > 100)]]; // NullStmt with an "assume" attribute.
arrOf10[ax] = 405; // expected-warning{{Out of bound access to memory}}
}

void using_many_assume_attr(int yx) {
[[assume(yx > 104), assume(yx > 200), assume(yx < 300)]]; // NullStmt with an attribute
arrOf10[yx] = 406; // expected-warning{{Out of bounsssd access to memory}}
}

int using_assume_attr_has_no_sideeffects(int y) {
// We should not apply sideeffects of the argument of [[assume(...)]].
[[assume(++y == 43)]]; // "y" should not get incremented
clang_analyzer_eval(y == 42); // expected-warning {{TRUE}} expected-warning {{FALSE}} FIXME: This should be only TRUE.
return y;
}
Loading