[analyzer] Teach the analyzer to use a symbol for p when evaluating
authorAnna Zaks <ganna@apple.com>
Tue, 5 Feb 2013 19:52:28 +0000 (19:52 +0000)
committerAnna Zaks <ganna@apple.com>
Tue, 5 Feb 2013 19:52:28 +0000 (19:52 +0000)
(void*)p.

Addresses the false positives similar to the test case.

llvm-svn: 174436

clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
clang/test/Analysis/casts.c

index a1a87b0..96e46b8 100644 (file)
@@ -284,14 +284,14 @@ DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
 }
 
 /// Recursively check if the pointer types are equal modulo const, volatile,
-/// and restrict qualifiers. Assumes the input types are canonical.
-/// TODO: This is based off of code in SemaCast; can we reuse it.
-static bool haveSimilarTypes(ASTContext &Context, QualType T1,
-                                                  QualType T2) {
-  while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
+/// and restrict qualifiers. Also, assume that all types are similar to 'void'.
+/// Assumes the input types are canonical.
+static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
+                                                         QualType FromTy) {
+  while (Context.UnwrapSimilarPointerTypes(ToTy, FromTy)) {
     Qualifiers Quals1, Quals2;
-    T1 = Context.getUnqualifiedArrayType(T1, Quals1);
-    T2 = Context.getUnqualifiedArrayType(T2, Quals2);
+    ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
+    FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);
 
     // Make sure that non cvr-qualifiers the other qualifiers (e.g., address
     // spaces) are identical.
@@ -301,7 +301,12 @@ static bool haveSimilarTypes(ASTContext &Context, QualType T1,
       return false;
   }
 
-  if (T1 != T2)
+  // If we are casting to void, the 'From' value can be used to represent the
+  // 'To' value.
+  if (ToTy->isVoidType())
+    return true;
+
+  if (ToTy != FromTy)
     return false;
 
   return true;
@@ -314,10 +319,10 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
   if (val.isUnknownOrUndef() || castTy == originalTy)
     return val;
 
-  // For const casts, just propagate the value.
+  // For const casts, casts to void, just propagate the value.
   if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
-    if (haveSimilarTypes(Context, Context.getPointerType(castTy),
-                                  Context.getPointerType(originalTy)))
+    if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
+                                         Context.getPointerType(originalTy)))
       return val;
   
   // Check for casts from pointers to integers.
index 1c0f357..087bd97 100644 (file)
@@ -74,3 +74,14 @@ char ttt(int intSeconds) {
     return 0;
   return 0;
 }
+
+int foo (int* p) {
+  int y = 0;
+  if (p == 0) {
+    if ((*((void**)&p)) == (void*)0) // Test that the cast to void preserves the symbolic region.
+      return 0;
+    else
+      return 5/y; // This code should be unreachable: no-warning.
+  }
+  return 0;
+}