]> granicus.if.org Git - clang/commitdiff
[analyzer] Don't treat lambda-captures float constexprs as undefined
authorDevin Coughlin <dcoughlin@apple.com>
Mon, 4 Dec 2017 04:46:47 +0000 (04:46 +0000)
committerDevin Coughlin <dcoughlin@apple.com>
Mon, 4 Dec 2017 04:46:47 +0000 (04:46 +0000)
RegionStore has special logic to evaluate captured constexpr variables.
However, if the constexpr initializer cannot be evaluated as an integer, the
value is treated as undefined. This leads to false positives when, for example,
a constexpr float is captured by a lambda.

To fix this, treat a constexpr capture that cannot be evaluated as unknown
rather than undefined.

rdar://problem/35784662

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319638 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/lambdas.cpp

index 39b92ee3a18dcc602a994798f82fb07398bf89f2..ecb32cc378d0a7b2b7c52c91dd1241fdc1a6d272 100644 (file)
@@ -1864,11 +1864,18 @@ SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
     return svalBuilder.getRegionValueSymbolVal(R);
 
   // Is 'VD' declared constant?  If so, retrieve the constant value.
-  if (VD->getType().isConstQualified())
-    if (const Expr *Init = VD->getInit())
+  if (VD->getType().isConstQualified()) {
+    if (const Expr *Init = VD->getInit()) {
       if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
         return *V;
 
+      // If the variable is const qualified and has an initializer but
+      // we couldn't evaluate initializer to a value, treat the value as
+      // unknown.
+      return UnknownVal();
+    }
+  }
+
   // This must come after the check for constants because closure-captured
   // constant variables may appear in UnknownSpaceRegion.
   if (isa<UnknownSpaceRegion>(MS))
index f3ff9b9539383a96304890836dab417ac019f583..38a2e3a84fb1b66dc62b283d1ff6bb8c1e5e654c 100644 (file)
@@ -337,6 +337,16 @@ void captureByReference() {
   lambda2();
 }
 
+void testCapturedConstExprFloat() {
+  constexpr float localConstant = 4.0;
+  auto lambda = []{
+    // Don't treat localConstant as containing a garbage value
+    float copy = localConstant; // no-warning
+    (void)copy;
+  };
+
+  lambda();
+}
 
 // CHECK: [B2 (ENTRY)]
 // CHECK:   Succs (1): B1