r181213 - [analyzer] Handle CXXTemporaryObjectExprs in compound literals.
Jordan Rose
jordan_rose at apple.com
Mon May 6 09:48:20 PDT 2013
Author: jrose
Date: Mon May 6 11:48:20 2013
New Revision: 181213
URL: http://llvm.org/viewvc/llvm-project?rev=181213&view=rev
Log:
[analyzer] Handle CXXTemporaryObjectExprs in compound literals.
This occurs because in C++11 the compound literal syntax can trigger a
constructor call via list-initialization. That is, "Point{x, y}" and
"(Point){x, y}" end up being equivalent. If this occurs, the inner
CXXConstructExpr will have already handled the object construction; the
CompoundLiteralExpr just needs to propagate that value forwards.
<rdar://problem/13804098>
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
cfe/trunk/test/Analysis/temporaries.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=181213&r1=181212&r2=181213&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Mon May 6 11:48:20 2013
@@ -403,26 +403,32 @@ void ExprEngine::VisitCompoundLiteralExp
ExplodedNodeSet &Dst) {
StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
- const InitListExpr *ILE
- = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
+ ProgramStateRef State = Pred->getState();
+ const LocationContext *LCtx = Pred->getLocationContext();
+
+ const Expr *Init = CL->getInitializer();
+ SVal V = State->getSVal(CL->getInitializer(), LCtx);
- ProgramStateRef state = Pred->getState();
- SVal ILV = state->getSVal(ILE, Pred->getLocationContext());
- const LocationContext *LC = Pred->getLocationContext();
- state = state->bindCompoundLiteral(CL, LC, ILV);
+ if (isa<CXXConstructExpr>(Init)) {
+ // No work needed. Just pass the value up to this expression.
+ } else {
+ assert(isa<InitListExpr>(Init));
+ Loc CLLoc = State->getLValue(CL, LCtx);
+ State = State->bindLoc(CLLoc, V);
+
+ // Compound literal expressions are a GNU extension in C++.
+ // Unlike in C, where CLs are lvalues, in C++ CLs are prvalues,
+ // and like temporary objects created by the functional notation T()
+ // CLs are destroyed at the end of the containing full-expression.
+ // HOWEVER, an rvalue of array type is not something the analyzer can
+ // reason about, since we expect all regions to be wrapped in Locs.
+ // So we treat array CLs as lvalues as well, knowing that they will decay
+ // to pointers as soon as they are used.
+ if (CL->isGLValue() || CL->getType()->isArrayType())
+ V = CLLoc;
+ }
- // Compound literal expressions are a GNU extension in C++.
- // Unlike in C, where CLs are lvalues, in C++ CLs are prvalues,
- // and like temporary objects created by the functional notation T()
- // CLs are destroyed at the end of the containing full-expression.
- // HOWEVER, an rvalue of array type is not something the analyzer can
- // reason about, since we expect all regions to be wrapped in Locs.
- // So we treat array CLs as lvalues as well, knowing that they will decay
- // to pointers as soon as they are used.
- if (CL->isGLValue() || CL->getType()->isArrayType())
- B.generateNode(CL, Pred, state->BindExpr(CL, LC, state->getLValue(CL, LC)));
- else
- B.generateNode(CL, Pred, state->BindExpr(CL, LC, ILV));
+ B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V));
}
void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
Modified: cfe/trunk/test/Analysis/temporaries.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temporaries.cpp?rev=181213&r1=181212&r2=181213&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/temporaries.cpp (original)
+++ cfe/trunk/test/Analysis/temporaries.cpp Mon May 6 11:48:20 2013
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
extern bool clang_analyzer_eval(bool);
@@ -76,3 +77,35 @@ namespace rdar13281951 {
}
}
+namespace compound_literals {
+ struct POD {
+ int x, y;
+ };
+ struct HasCtor {
+ HasCtor(int x, int y) : x(x), y(y) {}
+ int x, y;
+ };
+ struct HasDtor {
+ int x, y;
+ ~HasDtor();
+ };
+ struct HasCtorDtor {
+ HasCtorDtor(int x, int y) : x(x), y(y) {}
+ ~HasCtorDtor();
+ int x, y;
+ };
+
+ void test() {
+ clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
+
+#if __cplusplus >= 201103L
+ clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
+
+ // FIXME: should be TRUE, but we don't inline the constructors of
+ // temporaries because we can't model their destructors yet.
+ clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
+#endif
+ }
+}
+
More information about the cfe-commits
mailing list