Reapply "[analyzer] Handle inlined constructors for rvalue temporaries correctly."
authorJordan Rose <jordan_rose@apple.com>
Mon, 1 Oct 2012 17:51:35 +0000 (17:51 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 1 Oct 2012 17:51:35 +0000 (17:51 +0000)
This is related to but not blocked by <rdar://problem/12137950>
("Return-by-value structs do not have associated regions")

This reverts r164875 / 3278d41e17749dbedb204a81ef373499f10251d7.

llvm-svn: 164952

clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
clang/test/Analysis/array-struct-region.cpp
clang/test/Analysis/ctor-inlining.mm

index eb5395e..2e460b7 100644 (file)
@@ -160,7 +160,14 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
         svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);
       SVal ThisV = state->getSVal(This);
 
-      // Always bind the region to the CXXConstructExpr.
+      // If the constructed object is a prvalue, get its bindings.
+      // Note that we have to be careful here because constructors embedded
+      // in DeclStmts are not marked as lvalues.
+      if (!CCE->isGLValue())
+        if (const MemRegion *MR = ThisV.getAsRegion())
+          if (isa<CXXTempObjectRegion>(MR))
+            ThisV = state->getSVal(cast<Loc>(ThisV));
+
       state = state->BindExpr(CCE, callerCtx, ThisV);
     }
   }
index f610fbb..3581566 100644 (file)
@@ -52,12 +52,6 @@ int getAssignedField(struct S s) {
 
 void testArgument() {
   clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
-#if __cplusplus
-  // FIXME: Passing the struct by value seems to be confusing C++.
-  // Possibly related to <rdar://problem/12137950>.
-  // expected-warning@-4{{UNKNOWN}}
-#endif
-
   clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
 }
 
index 918de0a..ac963e5 100644 (file)
@@ -103,3 +103,17 @@ namespace TemporaryConstructor {
       return;
   }
 }
+
+
+namespace ConstructorUsedAsRValue {
+  using TemporaryConstructor::BoolWrapper;
+
+  bool extractValue(BoolWrapper b) {
+    return b.value;
+  }
+
+  void test() {
+    bool result = extractValue(BoolWrapper());
+    clang_analyzer_eval(result); // expected-warning{{TRUE}}
+  }
+}