r186521 - [analyzer] Handle C++11 member initializer expressions.

Jordan Rose jordan_rose at apple.com
Wed Jul 17 10:16:43 PDT 2013


Author: jrose
Date: Wed Jul 17 12:16:42 2013
New Revision: 186521

URL: http://llvm.org/viewvc/llvm-project?rev=186521&view=rev
Log:
[analyzer] Handle C++11 member initializer expressions.

Previously, we would simply abort the path when we saw a default member
initialization; now, we actually attempt to evaluate it. Like default
arguments, the contents of these expressions are not actually part of the
current function, so we fall back to constant evaluation.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Analysis/initializer.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=186521&r1=186520&r2=186521&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Jul 17 12:16:42 2013
@@ -612,7 +612,6 @@ void ExprEngine::Visit(const Stmt *S, Ex
   switch (S->getStmtClass()) {
     // C++ and ARC stuff we don't support yet.
     case Expr::ObjCIndirectCopyRestoreExprClass:
-    case Stmt::CXXDefaultInitExprClass:
     case Stmt::CXXDependentScopeMemberExprClass:
     case Stmt::CXXPseudoDestructorExprClass:
     case Stmt::CXXTryStmtClass:
@@ -737,7 +736,8 @@ void ExprEngine::Visit(const Stmt *S, Ex
       break;
     }
 
-    case Stmt::CXXDefaultArgExprClass: {
+    case Stmt::CXXDefaultArgExprClass:
+    case Stmt::CXXDefaultInitExprClass: {
       Bldr.takeNodes(Pred);
       ExplodedNodeSet PreVisit;
       getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
@@ -745,9 +745,13 @@ void ExprEngine::Visit(const Stmt *S, Ex
       ExplodedNodeSet Tmp;
       StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
 
-      const LocationContext *LCtx = Pred->getLocationContext();
-      const CXXDefaultArgExpr *DefaultE = cast<CXXDefaultArgExpr>(S);
-      const Expr *ArgE = DefaultE->getExpr();
+      const Expr *ArgE;
+      if (const CXXDefaultArgExpr *DefE = dyn_cast<CXXDefaultArgExpr>(S))
+        ArgE = DefE->getExpr();
+      else if (const CXXDefaultInitExpr *DefE = dyn_cast<CXXDefaultInitExpr>(S))
+        ArgE = DefE->getExpr();
+      else
+        llvm_unreachable("unknown constant wrapper kind");
 
       bool IsTemporary = false;
       if (const MaterializeTemporaryExpr *MTE =
@@ -760,13 +764,15 @@ void ExprEngine::Visit(const Stmt *S, Ex
       if (!ConstantVal)
         ConstantVal = UnknownVal();
 
+      const LocationContext *LCtx = Pred->getLocationContext();
       for (ExplodedNodeSet::iterator I = PreVisit.begin(), E = PreVisit.end();
            I != E; ++I) {
         ProgramStateRef State = (*I)->getState();
-        State = State->BindExpr(DefaultE, LCtx, *ConstantVal);
+        State = State->BindExpr(S, LCtx, *ConstantVal);
         if (IsTemporary)
-          State = createTemporaryRegionIfNeeded(State, LCtx, DefaultE,
-                                                DefaultE);
+          State = createTemporaryRegionIfNeeded(State, LCtx,
+                                                cast<Expr>(S),
+                                                cast<Expr>(S));
         Bldr2.generateNode(S, *I, State);
       }
 

Modified: cfe/trunk/test/Analysis/initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/initializer.cpp?rev=186521&r1=186520&r2=186521&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/initializer.cpp (original)
+++ cfe/trunk/test/Analysis/initializer.cpp Wed Jul 17 12:16:42 2013
@@ -109,3 +109,37 @@ namespace DefaultConstructorWithCleanups
     return w.arr[0].value; // no-warning
   }
 }
+
+namespace DefaultMemberInitializers {
+  struct Wrapper {
+    int value = 42;
+
+    Wrapper() {}
+    Wrapper(int x) : value(x) {}
+    Wrapper(bool) {}
+  };
+
+  void test() {
+    Wrapper w1;
+    clang_analyzer_eval(w1.value == 42); // expected-warning{{TRUE}}
+
+    Wrapper w2(50);
+    clang_analyzer_eval(w2.value == 50); // expected-warning{{TRUE}}
+
+    Wrapper w3(false);
+    clang_analyzer_eval(w3.value == 42); // expected-warning{{TRUE}}
+  }
+
+  struct StringWrapper {
+    const char s[4] = "abc";
+    const char *p = "xyz";
+
+    StringWrapper(bool) {}
+  };
+
+  void testString() {
+    StringWrapper w(true);
+    clang_analyzer_eval(w.s[1] == 'b'); // expected-warning{{TRUE}}
+    clang_analyzer_eval(w.p[1] == 'y'); // expected-warning{{TRUE}}
+  }
+}





More information about the cfe-commits mailing list