r175716 - [analyzer] Record whether a base object region represents a virtual base.

Jordan Rose jordan_rose at apple.com
Wed Feb 20 19:12:33 PST 2013


Author: jrose
Date: Wed Feb 20 21:12:32 2013
New Revision: 175716

URL: http://llvm.org/viewvc/llvm-project?rev=175716&view=rev
Log:
[analyzer] Record whether a base object region represents a virtual base.

This allows MemRegion and MemRegionManager to avoid asking over and over
again whether an class is a virtual base or a non-virtual base.

Minor optimization/cleanup; no functionality change.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Wed Feb 20 21:12:32 2013
@@ -1055,16 +1055,18 @@ public:
 class CXXBaseObjectRegion : public TypedValueRegion {
   friend class MemRegionManager;
 
-  const CXXRecordDecl *decl;
+  llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
 
-  CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg)
-    : TypedValueRegion(sReg, CXXBaseObjectRegionKind), decl(d) {}
+  CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
+                      const MemRegion *SReg)
+    : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {}
 
-  static void ProfileRegion(llvm::FoldingSetNodeID &ID,
-                            const CXXRecordDecl *decl, const MemRegion *sReg);
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+                            bool IsVirtual, const MemRegion *SReg);
 
 public:
-  const CXXRecordDecl *getDecl() const { return decl; }
+  const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
+  bool isVirtual() const { return Data.getInt(); }
 
   QualType getValueType() const;
 
@@ -1214,15 +1216,21 @@ public:
   const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
                                                     LocationContext const *LC);
 
-  const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
-                                                  const MemRegion *superRegion);
+  /// Create a CXXBaseObjectRegion with the given base class for region
+  /// \p Super.
+  ///
+  /// The type of \p Super is assumed be a class deriving from \p BaseClass.
+  const CXXBaseObjectRegion *
+  getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super,
+                         bool IsVirtual);
 
   /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
   /// super region.
   const CXXBaseObjectRegion *
   getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg, 
                                   const MemRegion *superRegion) {
-    return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
+    return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
+                                  baseReg->isVirtual());
   }
 
   const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Wed Feb 20 21:12:32 2013
@@ -136,7 +136,8 @@ public:
   SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
 
   /// Evaluates a derived-to-base cast through a single level of derivation.
-  SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType);
+  SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
+                         bool IsVirtual);
 
   /// \brief Evaluates C++ dynamic_cast cast.
   /// The callback may result in the following 3 scenarios:

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Feb 20 21:12:32 2013
@@ -487,8 +487,10 @@ void ExprEngine::ProcessBaseDtor(const C
   SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
 
   // Create the base object region.
-  QualType BaseTy = D.getBaseSpecifier()->getType();
-  SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
+  const CXXBaseSpecifier *Base = D.getBaseSpecifier();
+  QualType BaseTy = Base->getType();
+  SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
+                                                     Base->isVirtual());
 
   VisitCXXDestructor(BaseTy, BaseVal.castAs<loc::MemRegionVal>().getRegion(),
                      CurDtor->getBody(), /*IsBase=*/ true, Pred, Dst);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Feb 20 21:12:32 2013
@@ -161,8 +161,10 @@ void ExprEngine::VisitCXXConstructExpr(c
       Target = ThisVal.getAsRegion();
     } else {
       // Cast to the base type.
-      QualType BaseTy = CE->getType();
-      SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
+      bool IsVirtual =
+        (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase);
+      SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(),
+                                                         IsVirtual);
       Target = BaseVal.getAsRegion();
     }
     break;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Wed Feb 20 21:12:32 2013
@@ -234,7 +234,7 @@ QualType ObjCIvarRegion::getValueType()
 }
 
 QualType CXXBaseObjectRegion::getValueType() const {
-  return QualType(decl->getTypeForDecl(), 0);
+  return QualType(getDecl()->getTypeForDecl(), 0);
 }
 
 //===----------------------------------------------------------------------===//
@@ -402,14 +402,16 @@ void CXXTempObjectRegion::Profile(llvm::
 }
 
 void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
-                                        const CXXRecordDecl *decl,
-                                        const MemRegion *sReg) {
-  ID.AddPointer(decl);
-  ID.AddPointer(sReg);
+                                        const CXXRecordDecl *RD,
+                                        bool IsVirtual,
+                                        const MemRegion *SReg) {
+  ID.AddPointer(RD);
+  ID.AddBoolean(IsVirtual);
+  ID.AddPointer(SReg);
 }
 
 void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
-  ProfileRegion(ID, decl, superRegion);
+  ProfileRegion(ID, getDecl(), isVirtual(), superRegion);
 }
 
 //===----------------------------------------------------------------------===//
@@ -472,7 +474,7 @@ void CXXTempObjectRegion::dumpToStream(r
 }
 
 void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
-  os << "base{" << superRegion << ',' << decl->getName() << '}';
+  os << "base{" << superRegion << ',' << getDecl()->getName() << '}';
 }
 
 void CXXThisRegion::dumpToStream(raw_ostream &os) const {
@@ -885,41 +887,49 @@ MemRegionManager::getCXXTempObjectRegion
   return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC));
 }
 
-const CXXBaseObjectRegion *
-MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *decl,
-                                         const MemRegion *superRegion) {
-  // Check that the base class is actually a direct base of this region.
-  if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(superRegion)) {
-    if (const CXXRecordDecl *Class = TVR->getValueType()->getAsCXXRecordDecl()){
-      if (Class->isVirtuallyDerivedFrom(decl)) {
-        // Virtual base regions should not be layered, since the layout rules
-        // are different.
-        while (const CXXBaseObjectRegion *Base =
-                 dyn_cast<CXXBaseObjectRegion>(superRegion)) {
-          superRegion = Base->getSuperRegion();
-        }
-        assert(superRegion && !isa<MemSpaceRegion>(superRegion));
+/// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
+/// class of the type of \p Super.
+static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
+                             const TypedValueRegion *Super,
+                             bool IsVirtual) {
+  const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl();
+  if (!Class)
+    return true;
+
+  if (IsVirtual)
+    return Class->isVirtuallyDerivedFrom(BaseClass);
+
+  for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
+                                                E = Class->bases_end();
+       I != E; ++I) {
+    if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
+      return true;
+  }
 
-      } else {
-        // Non-virtual bases should always be direct bases.
-#ifndef NDEBUG
-        bool FoundBase = false;
-        for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(),
-                                                      E = Class->bases_end();
-             I != E; ++I) {
-          if (I->getType()->getAsCXXRecordDecl() == decl) {
-            FoundBase = true;
-            break;
-          }
-        }
+  return false;
+}
+
+const CXXBaseObjectRegion *
+MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
+                                         const MemRegion *Super,
+                                         bool IsVirtual) {
+  RD = RD->getCanonicalDecl();
+  
+  if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(Super)) {
+    assert(isValidBaseClass(RD, TVR, IsVirtual));
 
-        assert(FoundBase && "Not a direct base class of this region");
-#endif
+    if (IsVirtual) {
+      // Virtual base regions should not be layered, since the layout rules
+      // are different.
+      while (const CXXBaseObjectRegion *Base =
+               dyn_cast<CXXBaseObjectRegion>(Super)) {
+        Super = Base->getSuperRegion();
       }
+      assert(Super && !isa<MemSpaceRegion>(Super));
     }
   }
 
-  return getSubRegion<CXXBaseObjectRegion>(decl, superRegion);
+  return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super);
 }
 
 const CXXThisRegion*
@@ -1146,14 +1156,12 @@ RegionOffset MemRegion::getAsOffset() co
       if (SymbolicOffsetBase)
         continue;
 
-      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);
-
       CharUnits BaseOffset;
-      const CXXRecordDecl *Base = BOR->getDecl();
-      if (Child->isVirtuallyDerivedFrom(Base))
-        BaseOffset = Layout.getVBaseClassOffset(Base);
+      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);
+      if (BOR->isVirtual())
+        BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl());
       else
-        BaseOffset = Layout.getBaseClassOffset(Base);
+        BaseOffset = Layout.getBaseClassOffset(BOR->getDecl());
 
       // The base offset is in chars, not in bits.
       Offset += BaseOffset.getQuantity() * getContext().getCharWidth();

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=175716&r1=175715&r2=175716&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Wed Feb 20 21:12:32 2013
@@ -254,7 +254,7 @@ SVal StoreManager::evalDerivedToBase(SVa
   for (CastExpr::path_const_iterator I = Cast->path_begin(),
                                      E = Cast->path_end();
        I != E; ++I) {
-    Result = evalDerivedToBase(Result, (*I)->getType());
+    Result = evalDerivedToBase(Result, (*I)->getType(), (*I)->isVirtual());
   }
   return Result;
 }
@@ -264,12 +264,14 @@ SVal StoreManager::evalDerivedToBase(SVa
   SVal Result = Derived;
   for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end();
        I != E; ++I) {
-    Result = evalDerivedToBase(Result, I->Base->getType());
+    Result = evalDerivedToBase(Result, I->Base->getType(),
+                               I->Base->isVirtual());
   }
   return Result;
 }
 
-SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) {
+SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType,
+                                     bool IsVirtual) {
   Optional<loc::MemRegionVal> DerivedRegVal =
       Derived.getAs<loc::MemRegionVal>();
   if (!DerivedRegVal)
@@ -281,7 +283,8 @@ SVal StoreManager::evalDerivedToBase(SVa
   assert(BaseDecl && "not a C++ object?");
 
   const MemRegion *BaseReg =
-    MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion());
+    MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(),
+                                 IsVirtual);
 
   return loc::MemRegionVal(BaseReg);
 }





More information about the cfe-commits mailing list