]> granicus.if.org Git - clang/commitdiff
[analyzer] Handle C string default values for const char * arguments.
authorJordan Rose <jordan_rose@apple.com>
Wed, 17 Jul 2013 17:16:38 +0000 (17:16 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 17 Jul 2013 17:16:38 +0000 (17:16 +0000)
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

lib/StaticAnalyzer/Core/RegionStore.cpp
lib/StaticAnalyzer/Core/SValBuilder.cpp
test/Analysis/inline.cpp

index 00a6f7119042043ce3eeb9b0cd1919aac5e13900..2a3319bc0424e79de625fb85885c049deb1597a0 100644 (file)
@@ -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();
index ecfceaa0f3cf403a0eb26e50021cdafd7be47a4a..1992abbf4c3e6bb0ed613474cd4293c2ba16af02 100644 (file)
@@ -266,6 +266,17 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
   case Stmt::CXXNullPtrLiteralExprClass:
     return makeNull();
 
+  case Stmt::ImplicitCastExprClass: {
+    const CastExpr *CE = cast<CastExpr>(E);
+    if (CE->getCastKind() == CK_ArrayToPointerDecay) {
+      Optional<SVal> 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.
index fad77b3bee436e7de2086fd0f476eb46706c5744..ca126ddf7f389d76b306fc241f746542c0132ef7 100644 (file)
@@ -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 {