From: Jordan Rose Date: Wed, 17 Jul 2013 17:16:38 +0000 (+0000) Subject: [analyzer] Handle C string default values for const char * arguments. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=df70700f5aa5744d7f70fb3e6610ff434f643a71;p=clang [analyzer] Handle C string default values for const char * arguments. Previously, SValBuilder knew how to evaluate StringLiterals, but couldn't handle an array-to-pointer decay for constant values. Additionally, RegionStore was being too strict about loading from an array, refusing to return a 'char' value from a 'const char' array. Both of these have been fixed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186520 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 00a6f71190..2a3319bc04 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1497,7 +1497,7 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B, // FIXME: Handle loads from strings where the literal is treated as // an integer, e.g., *((unsigned int*)"hello") QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType(); - if (T != Ctx.getCanonicalType(R->getElementType())) + if (!Ctx.hasSameUnqualifiedType(T, R->getElementType())) return UnknownVal(); const StringLiteral *Str = StrR->getStringLiteral(); diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index ecfceaa0f3..1992abbf4c 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -266,6 +266,17 @@ Optional SValBuilder::getConstantVal(const Expr *E) { case Stmt::CXXNullPtrLiteralExprClass: return makeNull(); + case Stmt::ImplicitCastExprClass: { + const CastExpr *CE = cast(E); + if (CE->getCastKind() == CK_ArrayToPointerDecay) { + Optional ArrayVal = getConstantVal(CE->getSubExpr()); + if (!ArrayVal) + return None; + return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType()); + } + // FALLTHROUGH + } + // If we don't have a special case, fall back to the AST's constant evaluator. default: { // Don't try to come up with a value for materialized temporaries. diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp index fad77b3bee..ca126ddf7f 100644 --- a/test/Analysis/inline.cpp +++ b/test/Analysis/inline.cpp @@ -290,6 +290,15 @@ namespace DefaultArgs { clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}} clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}} } + + char defaultString(const char *s = "abc") { + return s[1]; + } + + void testString() { + clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}} + clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}} + } } namespace OperatorNew {