[cfe-commits] r164828 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/fields.c test/Analysis/reference.cpp
Jordan Rose
jordan_rose at apple.com
Fri Sep 28 10:15:12 PDT 2012
Author: jrose
Date: Fri Sep 28 12:15:12 2012
New Revision: 164828
URL: http://llvm.org/viewvc/llvm-project?rev=164828&view=rev
Log:
[analyzer] Create a temporary region for rvalue structs when accessing fields
Struct rvalues are represented in the analyzer by CompoundVals,
LazyCompoundVals, or plain ConjuredSymbols -- none of which have associated
regions. If the entire structure is going to persist, this is not a
problem -- either the rvalue will be assigned to an existing region, or
a MaterializeTemporaryExpr will be present to create a temporary region.
However, if we just need a field from the struct, we need to create the
temporary region ourselves.
This is inspired by the way CodeGen handles calls to temporaries;
support for that in the analyzer is coming next.
Part of <rdar://problem/12137950>
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/fields.c
cfe/trunk/test/Analysis/reference.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=164828&r1=164827&r2=164828&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Sep 28 12:15:12 2012
@@ -1505,17 +1505,17 @@
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
SVal baseExprVal = state->getSVal(baseExpr, Pred->getLocationContext());
- if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
- isa<nonloc::CompoundVal>(baseExprVal) ||
- // FIXME: This can originate by conjuring a symbol for an unknown
- // temporary struct object, see test/Analysis/fields.c:
- // (p = getit()).x
- isa<nonloc::SymbolVal>(baseExprVal)) {
- Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, UnknownVal()));
- return;
+
+ // If we're accessing a field of an rvalue, we need to treat it like a
+ // temporary object.
+ if (isa<NonLoc>(baseExprVal)) {
+ const MemRegion *R =
+ svalBuilder.getRegionManager().getCXXTempObjectRegion(baseExpr, LCtx);
+ SVal L = loc::MemRegionVal(R);
+ state = state->bindLoc(L, baseExprVal);
+ baseExprVal = L;
}
- // For all other cases, compute an lvalue.
SVal L = state->getLValue(field, baseExprVal);
if (M->isGLValue()) {
ExplodedNodeSet Tmp;
Modified: cfe/trunk/test/Analysis/fields.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/fields.c?rev=164828&r1=164827&r2=164828&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/fields.c (original)
+++ cfe/trunk/test/Analysis/fields.c Fri Sep 28 12:15:12 2012
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core %s -analyzer-store=region -verify
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection %s -analyzer-store=region -verify
+
+void clang_analyzer_eval(int);
unsigned foo();
typedef struct bf { unsigned x:2; } bf;
@@ -33,3 +35,10 @@
int *px = &p->x; // expected-warning{{Access to field 'x' results in a dereference of a null pointer (loaded from variable 'p')}}
*px = 1; // No warning because analysis stops at the previous line.
}
+
+void testLazyCompoundVal() {
+ Point p = {42, 0};
+ Point q;
+ clang_analyzer_eval((q = p).x == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(q.x == 42); // expected-warning{{TRUE}}
+}
Modified: cfe/trunk/test/Analysis/reference.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/reference.cpp?rev=164828&r1=164827&r2=164828&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/reference.cpp (original)
+++ cfe/trunk/test/Analysis/reference.cpp Fri Sep 28 12:15:12 2012
@@ -116,10 +116,8 @@
struct S { int &x; };
- // FIXME: Should be TRUE. Fields of return-by-value structs are not yet
- // symbolicated. Tracked by <rdar://problem/12137950>.
extern S getS();
- clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&getS().x != 0); // expected-warning{{TRUE}}
extern S *getSP();
clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{TRUE}}
More information about the cfe-commits
mailing list