summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp19
-rw-r--r--clang/test/SemaTemplate/array-to-pointer-decay.cpp12
2 files changed, 30 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 627e0107b86..7a0ba648d93 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1724,7 +1724,24 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
FieldDecl *field = cast<FieldDecl>(Member);
SVal L = state->getLValue(field, baseExprVal);
- if (M->isGLValue()) {
+
+ if (M->isGLValue() || M->getType()->isArrayType()) {
+
+ // We special case rvalue of array type because the analyzer cannot reason
+ // about it, since we expect all regions to be wrapped in Locs. So we will
+ // treat these as lvalues assuming that they will decay to pointers as soon
+ // as they are used. Below
+ if (!M->isGLValue()) {
+ assert(M->getType()->isArrayType());
+ const ImplicitCastExpr *PE =
+ dyn_cast<ImplicitCastExpr>(Pred->getParentMap().getParent(M));
+ if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
+ assert(false &&
+ "We assume that array is always wrapped in ArrayToPointerDecay");
+ L = UnknownVal();
+ }
+ }
+
if (field->getType()->isReferenceType()) {
if (const MemRegion *R = L.getAsRegion())
L = state->getSVal(R);
diff --git a/clang/test/SemaTemplate/array-to-pointer-decay.cpp b/clang/test/SemaTemplate/array-to-pointer-decay.cpp
index 26d277d7dc0..dcf09016104 100644
--- a/clang/test/SemaTemplate/array-to-pointer-decay.cpp
+++ b/clang/test/SemaTemplate/array-to-pointer-decay.cpp
@@ -24,3 +24,15 @@ template <typename Type> static bool sanitize() {
return !c->start;
}
bool closure = sanitize<int>();
+
+// PR16206
+typedef struct {
+ char x[4];
+} chars;
+
+chars getChars();
+void use(char *);
+
+void test() {
+ use(getChars().x);
+}
OpenPOWER on IntegriCloud