]> granicus.if.org Git - clang/commitdiff
Fix crash in RegionStoreManager::evalDerivedToBase() due to not handling references
authorTed Kremenek <kremenek@apple.com>
Wed, 18 Jul 2012 05:57:33 +0000 (05:57 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 18 Jul 2012 05:57:33 +0000 (05:57 +0000)
(in uses of dynamic_cast<>).

Fixes <rdar://problem/11817693>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160427 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/misc-ps-cxx0x.cpp

index c084bd2ad0de8c03e3ea4c2282b5c6d57bba94f0..3dc7f7f58d090f42cd66f56009f27f884d28cb0c 100644 (file)
@@ -877,10 +877,22 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
   return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
 }
 
+// This mirrors Type::getCXXRecordDeclForPointerType(), but there doesn't
+// appear to be another need for this in the rest of the codebase.
+static const CXXRecordDecl *GetCXXRecordDeclForReferenceType(QualType Ty) {
+  if (const ReferenceType *RT = Ty->getAs<ReferenceType>())
+    if (const RecordType *RCT = RT->getPointeeType()->getAs<RecordType>())
+      return dyn_cast<CXXRecordDecl>(RCT->getDecl());
+  return 0;
+}
+
 SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) {
   const CXXRecordDecl *baseDecl;
+  
   if (baseType->isPointerType())
     baseDecl = baseType->getCXXRecordDeclForPointerType();
+  else if (baseType->isReferenceType())
+    baseDecl = GetCXXRecordDeclForReferenceType(baseType);
   else
     baseDecl = baseType->getAsCXXRecordDecl();
 
index b4dee3122e2ca1001edd389b8193d06d796666b6..7712bb8dc3b7ea6b32686a97d6d8d57d51b91b9b 100644 (file)
@@ -73,3 +73,18 @@ void test2() {
 struct RDar11178609 {
   ~RDar11178609() = delete;
 };
+
+// Tests that dynamic_cast handles references to C++ classes.  Previously
+// this crashed.
+class rdar11817693_BaseBase {};
+class rdar11817693_BaseInterface {};
+class rdar11817693_Base : public rdar11817693_BaseBase, public rdar11817693_BaseInterface {};
+class rdar11817693 : public rdar11817693_Base {
+  virtual void operator=(const rdar11817693_BaseBase& src);
+  void operator=(const rdar11817693& src);
+};
+void rdar11817693::operator=(const rdar11817693& src) {
+  operator=(dynamic_cast<const rdar11817693_BaseBase&>(src));
+}
+
+