diff options
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 19 | ||||
-rw-r--r-- | clang/test/SemaTemplate/array-to-pointer-decay.cpp | 12 |
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); +} |