]> granicus.if.org Git - clang/commitdiff
[analyzer] Handle reference parameters with default values.
authorJordan Rose <jordan_rose@apple.com>
Mon, 25 Feb 2013 19:45:34 +0000 (19:45 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 25 Feb 2013 19:45:34 +0000 (19:45 +0000)
r175026 added support for default values, but didn't take reference
parameters into account, which expect the default argument to be an
lvalue. Use createTemporaryRegionIfNeeded if we can evaluate the default
expr as an rvalue but the expected result is an lvalue.

Fixes the most recent report of PR12915. The original report predates
default argument support, so that can't be it.

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

lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/global_region_invalidation.mm
test/Analysis/inline.cpp

index eb83e202b77bc070330ae92aa3a6787c0e9e5ca6..8b6de1324972400d665631e9dbcd4fc7c4baaff3 100644 (file)
@@ -685,7 +685,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
 
       const LocationContext *LCtx = Pred->getLocationContext();
-      const Expr *ArgE = cast<CXXDefaultArgExpr>(S)->getExpr();
+      const CXXDefaultArgExpr *DefaultE = cast<CXXDefaultArgExpr>(S);
+      const Expr *ArgE = DefaultE->getExpr();
 
       // Avoid creating and destroying a lot of APSInts.
       SVal V;
@@ -700,7 +701,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
         else
           V = State->getSVal(ArgE, LCtx);
 
-        State = State->BindExpr(S, LCtx, V);
+        State = State->BindExpr(DefaultE, LCtx, V);
+        if (DefaultE->isGLValue())
+          State = createTemporaryRegionIfNeeded(State, LCtx, DefaultE);
         Bldr2.generateNode(S, *I, State);
       }
 
index 310c080fafbe1b5f418c6bd98e3acfd053882a59..acda9e0af321d8efd1db717f5980c41bc43c629d 100644 (file)
@@ -1578,7 +1578,7 @@ static Optional<SVal> getConstValue(SValBuilder &SVB, const VarDecl *VD) {
     return None;
 
   llvm::APSInt Result;
-  if (Init->EvaluateAsInt(Result, Ctx))
+  if (!Init->isGLValue() && Init->EvaluateAsInt(Result, Ctx))
     return SVB.makeIntVal(Result);
 
   if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
index 0d7f172b3f30135f538f15b82b6f3470838f16fa..be337edab11adfd0228f0ef6a675ed92b069ea00 100644 (file)
@@ -9,4 +9,11 @@ id foo(int x) {
   static id p = foo(1); 
     clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
   return p;
-}
\ No newline at end of file
+}
+
+const int &globalInt = 42;
+
+void testGlobal() {
+  // FIXME: Should be TRUE, but should at least not crash.
+  clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}}
+}
index f0e69ddfc22e18897132993796d48ae424182127..27853dc2aafcdda41ee8c8bdb695e56a81b6c4e6 100644 (file)
@@ -260,6 +260,15 @@ namespace DefaultArgs {
     clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}}
     clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}}
   }
+
+  int defaultReference(const int &input = 42) {
+    return input;
+  }
+
+  void testReference() {
+    clang_analyzer_eval(defaultReference(1) == 1); // expected-warning{{TRUE}}
+    clang_analyzer_eval(defaultReference() == 42); // expected-warning{{TRUE}}
+  }
 }
 
 namespace OperatorNew {