diff options
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 55 | ||||
-rw-r--r-- | test/Analysis/blocks-no-inline.c | 27 |
2 files changed, 61 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 9572f64865..354b55119b 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1497,6 +1497,26 @@ SVal RegionStoreManager::getBindingForObjCIvar(RegionBindingsConstRef B, return getBindingForLazySymbol(R); } +static Optional<SVal> getConstValue(SValBuilder &SVB, const VarDecl *VD) { + ASTContext &Ctx = SVB.getContext(); + if (!VD->getType().isConstQualified()) + return Optional<SVal>(); + + const Expr *Init = VD->getInit(); + if (!Init) + return Optional<SVal>(); + + llvm::APSInt Result; + if (Init->EvaluateAsInt(Result, Ctx)) + return SVB.makeIntVal(Result); + + if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)) + return SVB.makeNull(); + + // FIXME: Handle other possible constant expressions. + return Optional<SVal>(); +} + SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B, const VarRegion *R) { @@ -1506,37 +1526,30 @@ SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B, // Lazily derive a value for the VarRegion. const VarDecl *VD = R->getDecl(); - QualType T = VD->getType(); const MemSpaceRegion *MS = R->getMemorySpace(); - if (isa<UnknownSpaceRegion>(MS) || - isa<StackArgumentsSpaceRegion>(MS)) + // Arguments are always symbolic. + if (isa<StackArgumentsSpaceRegion>(MS)) + return svalBuilder.getRegionValueSymbolVal(R); + + // Is 'VD' declared constant? If so, retrieve the constant value. + if (Optional<SVal> V = getConstValue(svalBuilder, VD)) + return *V; + + // This must come after the check for constants because closure-captured + // constant variables may appear in UnknownSpaceRegion. + if (isa<UnknownSpaceRegion>(MS)) return svalBuilder.getRegionValueSymbolVal(R); if (isa<GlobalsSpaceRegion>(MS)) { + QualType T = VD->getType(); + // Function-scoped static variables are default-initialized to 0; if they // have an initializer, it would have been processed by now. if (isa<StaticGlobalSpaceRegion>(MS)) return svalBuilder.makeZeroVal(T); - // Other globals - // Is 'VD' declared constant? If so, retrieve the constant value. - QualType CT = Ctx.getCanonicalType(T); - if (CT.isConstQualified()) { - if (const Expr *Init = VD->getInit()) { - llvm::APSInt Result; - if (Init->EvaluateAsInt(Result, Ctx)) - return svalBuilder.makeIntVal(Result); - - if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)) - return svalBuilder.makeNull(); - - // FIXME: Handle other possible constant expressions. - } - } - - if (const Optional<SVal> &V - = getBindingForDerivedDefaultValue(B, MS, R, CT)) + if (Optional<SVal> V = getBindingForDerivedDefaultValue(B, MS, R, T)) return V.getValue(); return svalBuilder.getRegionValueSymbolVal(R); diff --git a/test/Analysis/blocks-no-inline.c b/test/Analysis/blocks-no-inline.c index 88f96acce1..de6f959b9d 100644 --- a/test/Analysis/blocks-no-inline.c +++ b/test/Analysis/blocks-no-inline.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -fblocks -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -fblocks -verify -x c++ %s void clang_analyzer_eval(int); @@ -11,3 +12,29 @@ void testInvalidation() { // Under inlining, we will know that i == 1. clang_analyzer_eval(i == 0); // expected-warning{{UNKNOWN}} } + + +const int globalConstant = 1; +void testCapturedConstants() { + const int localConstant = 2; + static const int staticConstant = 3; + + ^{ + clang_analyzer_eval(globalConstant == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(localConstant == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(staticConstant == 3); // expected-warning{{TRUE}} + }(); +} + +typedef const int constInt; +constInt anotherGlobalConstant = 1; +void testCapturedConstantsTypedef() { + constInt localConstant = 2; + static constInt staticConstant = 3; + + ^{ + clang_analyzer_eval(anotherGlobalConstant == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(localConstant == 2); // expected-warning{{TRUE}} + clang_analyzer_eval(staticConstant == 3); // expected-warning{{TRUE}} + }(); +} |