r175239 - [analyzer] Don't assert when mixing reinterpret_cast and derived-to-base casts.

Jordan Rose jordan_rose at apple.com
Thu Feb 14 17:23:25 PST 2013


Author: jrose
Date: Thu Feb 14 19:23:24 2013
New Revision: 175239

URL: http://llvm.org/viewvc/llvm-project?rev=175239&view=rev
Log:
[analyzer] Don't assert when mixing reinterpret_cast and derived-to-base casts.

This just adds a very simple check that if a DerivedToBase CastExpr is
operating on a value with known C++ object type, and that type is not the
base type specified in the AST, then the cast is invalid and we should
return UnknownVal.

In the future, perhaps we can have a checker that specifies that this is
illegal, but we still shouldn't assert even if the user turns that checker
off.

PR14872

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
    cfe/trunk/test/Analysis/reinterpret-cast.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=175239&r1=175238&r2=175239&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Thu Feb 14 19:23:24 2013
@@ -223,7 +223,32 @@ const MemRegion *StoreManager::castRegio
   llvm_unreachable("unreachable");
 }
 
+static bool regionMatchesCXXRecordType(SVal V, QualType Ty) {
+  const MemRegion *MR = V.getAsRegion();
+  if (!MR)
+    return true;
+
+  const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
+  if (!TVR)
+    return true;
+
+  const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl();
+  if (!RD)
+    return true;
+
+  const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl();
+  if (!Expected)
+    Expected = Ty->getAsCXXRecordDecl();
+
+  return Expected->getCanonicalDecl() == RD->getCanonicalDecl();
+}
+
 SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) {
+  // Sanity check to avoid doing the wrong thing in the face of
+  // reinterpret_cast.
+  if (!regionMatchesCXXRecordType(Derived, Cast->getSubExpr()->getType()))
+    return UnknownVal();
+
   // Walk through the cast path to create nested CXXBaseRegions.
   SVal Result = Derived;
   for (CastExpr::path_const_iterator I = Cast->path_begin(),

Modified: cfe/trunk/test/Analysis/reinterpret-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/reinterpret-cast.cpp?rev=175239&r1=175238&r2=175239&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/reinterpret-cast.cpp (original)
+++ cfe/trunk/test/Analysis/reinterpret-cast.cpp Thu Feb 14 19:23:24 2013
@@ -18,3 +18,31 @@ void test(Data data) {
   wrapper->set();
   clang_analyzer_eval(wrapper->x == 42); // expected-warning{{TRUE}}
 }
+
+namespace PR14872 {
+  class Base1 {};
+  class Derived1 : public Base1 {};
+
+  Derived1 *f1();
+
+  class Base2 {};
+  class Derived2 : public Base2 {};
+
+  void f2(Base2 *foo);
+
+  void f3(void** out)
+  {
+    Base1 *v;
+    v = f1();
+    *out = v;
+  }
+
+  void test()
+  {
+    Derived2 *p;
+    f3(reinterpret_cast<void**>(&p));
+    // Don't crash when upcasting here.
+    // In this case, 'p' actually refers to a Derived1.
+    f2(p);
+  }
+}





More information about the cfe-commits mailing list