Index: lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp +++ lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp @@ -25,7 +25,9 @@ namespace { class AnalysisOrderChecker : public Checker< check::PreStmt, - check::PostStmt> { + check::PostStmt, + check::PreStmt, + check::PostStmt> { bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions(); return Opts.getBooleanOption("*", false, this) || @@ -44,6 +46,16 @@ llvm::errs() << "PostStmt (Kind : " << CE->getCastKindName() << ")\n"; } + + void checkPreStmt(const ArraySubscriptExpr *SubExpr, CheckerContext &C) const { + if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr")) + llvm::errs() << "PreStmt\n"; + } + + void checkPostStmt(const ArraySubscriptExpr *SubExpr, CheckerContext &C) const { + if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr")) + llvm::errs() << "PostStmt\n"; + } }; } Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1968,16 +1968,17 @@ const Expr *Base = A->getBase()->IgnoreParens(); const Expr *Idx = A->getIdx()->IgnoreParens(); - ExplodedNodeSet checkerPreStmt; - getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this); - - StmtNodeBuilder Bldr(checkerPreStmt, Dst, *currBldrCtx); + ExplodedNodeSet CheckedSet; + getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, A, *this); + + ExplodedNodeSet EvalSet; + StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); assert(A->isGLValue() || (!AMgr.getLangOpts().CPlusPlus && A->getType().isCForbiddenLValueType())); - for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(), - ei = checkerPreStmt.end(); it != ei; ++it) { + for (ExplodedNodeSet::iterator it = CheckedSet.begin(), + ei = CheckedSet.end(); it != ei; ++it) { const LocationContext *LCtx = (*it)->getLocationContext(); ProgramStateRef state = (*it)->getState(); SVal V = state->getLValue(A->getType(), @@ -1986,6 +1987,9 @@ Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr, ProgramPoint::PostLValueKind); } + + getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this); + } /// VisitMemberExpr - Transfer function for member expressions. Index: test/Analysis/arraysubscriptexpr-callback.c =================================================================== --- /dev/null +++ test/Analysis/arraysubscriptexpr-callback.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtArraySubscriptExpr=true,debug.AnalysisOrder:PostStmtArraySubscriptExpr=true %s 2>&1 | FileCheck %s + + +char x[1]; +void test(char c) { + x[0] = c; +} + +// CHECK: PreStmt +// CHECK-NEXT: PostStmt