[cfe-commits] r120562 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/Type.cpp

John McCall rjmccall at apple.com
Wed Dec 1 00:12:46 PST 2010


Author: rjmccall
Date: Wed Dec  1 02:12:46 2010
New Revision: 120562

URL: http://llvm.org/viewvc/llvm-project?rev=120562&view=rev
Log:
Eliminate vtables from the Type hierarchy.


Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/Type.cpp

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=120562&r1=120561&r2=120562&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Dec  1 02:12:46 2010
@@ -789,6 +789,7 @@
   /// Bitfields required by the Type class.
   class TypeBitfields {
     friend class Type;
+    template <class T> friend class TypePropertyCache;
 
     /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
     unsigned TC : 8;
@@ -954,36 +955,9 @@
     TypeBits.FromAST = V;
   }
 
-  void ensureCachedProperties() const;
+  template <class T> friend class TypePropertyCache;
 
 protected:
-  /// \brief Compute the cached properties of this type.
-  class CachedProperties {
-    char linkage;
-    char visibility;
-    bool local;
-
-  public:
-    CachedProperties(Linkage linkage, Visibility visibility, bool local)
-      : linkage(linkage), visibility(visibility), local(local) {}
-
-    Linkage getLinkage() const { return (Linkage) linkage; }
-    Visibility getVisibility() const { return (Visibility) visibility; }
-    bool hasLocalOrUnnamedType() const { return local; }
-
-    friend CachedProperties merge(CachedProperties L, CachedProperties R) {
-      return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()),
-                         minVisibility(L.getVisibility(), R.getVisibility()),
-                      L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
-    }
-  };
-
-  virtual CachedProperties getCachedProperties() const;
-  static CachedProperties getCachedProperties(QualType T) {
-    return getCachedProperties(T.getTypePtr());
-  }
-  static CachedProperties getCachedProperties(const Type *T);
-
   // silence VC++ warning C4355: 'this' : used in base member initializer list
   Type *this_() { return this; }
   Type(TypeClass tc, QualType Canonical, bool Dependent, bool VariablyModified)
@@ -996,7 +970,6 @@
     TypeBits.CachedLinkage = NoLinkage;
     TypeBits.FromAST = false;
   }
-  virtual ~Type();
   friend class ASTContext;
 
   void setDependent(bool D = true) { TypeBits.Dependent = D; }
@@ -1336,9 +1309,6 @@
     ObjCSel    // This represents the ObjC 'SEL' type.
   };
 
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   BuiltinType(Kind K)
     : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
@@ -1392,9 +1362,6 @@
   }
   friend class ASTContext;  // ASTContext creates these.
 
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   QualType getElementType() const { return ElementType; }
 
@@ -1424,9 +1391,6 @@
   }
   friend class ASTContext;  // ASTContext creates these.
 
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
 
   QualType getPointeeType() const { return PointeeType; }
@@ -1458,9 +1422,6 @@
   }
   friend class ASTContext;  // ASTContext creates these.
   
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
 
   // Get the pointee type. Pointee is required to always be a function type.
@@ -1496,8 +1457,6 @@
     ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
   }
   
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; }
   bool isInnerRef() const { return ReferenceTypeBits.InnerRef; }
@@ -1579,9 +1538,6 @@
   }
   friend class ASTContext; // ASTContext creates these.
   
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   QualType getPointeeType() const { return PointeeType; }
 
@@ -1649,8 +1605,6 @@
 
   friend class ASTContext;  // ASTContext creates these.
 
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   QualType getElementType() const { return ElementType; }
   ArraySizeModifier getSizeModifier() const {
@@ -1954,8 +1908,6 @@
   }
   friend class ASTContext;  // ASTContext creates these.
   
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
 
   QualType getElementType() const { return ElementType; }
@@ -2057,8 +2009,6 @@
 /// class of FunctionNoProtoType and FunctionProtoType.
 ///
 class FunctionType : public Type {
-  virtual void ANCHOR(); // Key function for FunctionType.
-
   // The type returned by the function.
   QualType ResultType;
 
@@ -2183,9 +2133,6 @@
                    Info) {}
   friend class ASTContext;  // ASTContext creates these.
   
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   // No additional state past what FunctionType provides.
 
@@ -2239,9 +2186,6 @@
 
   friend class ASTContext;  // ASTContext creates these.
 
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   unsigned getNumArgs() const { return NumArgs; }
   QualType getArgType(unsigned i) const {
@@ -2482,8 +2426,6 @@
 protected:
   TagType(TypeClass TC, const TagDecl *D, QualType can);
 
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   TagDecl *getDecl() const;
 
@@ -2857,8 +2799,6 @@
   }
 
 public:
-  virtual ~TypeWithKeyword(); // pin vtable to Type.cpp
-
   ElaboratedTypeKeyword getKeyword() const {
     return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
   }
@@ -2983,8 +2923,6 @@
   friend class ASTContext;  // ASTContext creates these
 
 public:
-  virtual ~DependentNameType();
-
   /// \brief Retrieve the qualification on this type.
   NestedNameSpecifier *getQualifier() const { return NNS; }
 
@@ -3051,8 +2989,6 @@
   friend class ASTContext;  // ASTContext creates these
 
 public:
-  virtual ~DependentTemplateSpecializationType();
-
   NestedNameSpecifier *getQualifier() const { return NNS; }
   const IdentifierInfo *getIdentifier() const { return Name; }
 
@@ -3144,9 +3080,6 @@
     ObjCObjectTypeBits.NumProtocols = 0;
   }
 
-protected:
-  CachedProperties getCachedProperties() const; // key function
-  
 public:
   /// getBaseType - Gets the base type of this object type.  This is
   /// always (possibly sugar for) one of:
@@ -3254,9 +3187,6 @@
       Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
   friend class ASTContext;  // ASTContext creates these.
 
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   /// getDecl - Get the declaration of this interface.
   ObjCInterfaceDecl *getDecl() const { return Decl; }
@@ -3306,9 +3236,6 @@
       PointeeType(Pointee) {}
   friend class ASTContext;  // ASTContext creates these.
 
-protected:
-  virtual CachedProperties getCachedProperties() const;
-  
 public:
   /// getPointeeType - Gets the type pointed to by this ObjC pointer.
   /// The result will always be an ObjCObjectType or sugar thereof.

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=120562&r1=120561&r2=120562&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Dec  1 02:12:46 2010
@@ -19,6 +19,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/raw_ostream.h"
@@ -35,8 +36,6 @@
   return false;
 }
 
-Type::~Type() { }
-
 unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context,
                                                  QualType ElementType,
                                                const llvm::APInt &NumElements) {
@@ -827,9 +826,6 @@
   }
 }
 
-TypeWithKeyword::~TypeWithKeyword() {
-}
-
 ElaboratedTypeKeyword
 TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) {
   switch (TypeSpec) {
@@ -910,10 +906,6 @@
   return "";
 }
 
-ElaboratedType::~ElaboratedType() {}
-DependentNameType::~DependentNameType() {}
-DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {}
-
 DependentTemplateSpecializationType::DependentTemplateSpecializationType(
                          ElaboratedTypeKeyword Keyword,
                          NestedNameSpecifier *NNS, const IdentifierInfo *Name,
@@ -1006,8 +998,6 @@
   return 0;
 }
 
-void FunctionType::ANCHOR() {} // Key function for FunctionType.
-
 QualType QualType::getNonLValueExprType(ASTContext &Context) const {
   if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>())
     return RefType->getPointeeType();
@@ -1318,154 +1308,194 @@
   Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
 }
 
-void Type::ensureCachedProperties() const {
-  if (!TypeBits.isCacheValid()) {
-    CachedProperties Result = getCachedProperties();
-    TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U;
-    assert(TypeBits.isCacheValid() &&
-           TypeBits.getVisibility() == Result.getVisibility());
-    TypeBits.CachedLinkage = Result.getLinkage();
-    TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType();
-  }  
+namespace {
+
+/// \brief The cached properties of a type.
+class CachedProperties {
+  char linkage;
+  char visibility;
+  bool local;
+  
+public:
+  CachedProperties(Linkage linkage, Visibility visibility, bool local)
+    : linkage(linkage), visibility(visibility), local(local) {}
+  
+  Linkage getLinkage() const { return (Linkage) linkage; }
+  Visibility getVisibility() const { return (Visibility) visibility; }
+  bool hasLocalOrUnnamedType() const { return local; }
+  
+  friend CachedProperties merge(CachedProperties L, CachedProperties R) {
+    return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()),
+                            minVisibility(L.getVisibility(), R.getVisibility()),
+                         L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
+  }
+};
+}
+
+static CachedProperties computeCachedProperties(const Type *T);
+
+namespace clang {
+/// The type-property cache.  This is templated so as to be
+/// instantiated at an internal type to prevent unnecessary symbol
+/// leakage.
+template <class Private> class TypePropertyCache {
+public:
+  static CachedProperties get(QualType T) {
+    return get(T.getTypePtr());
+  }
+
+  static CachedProperties get(const Type *T) {
+    ensure(T);
+    return CachedProperties(T->TypeBits.getLinkage(),
+                            T->TypeBits.getVisibility(),
+                            T->TypeBits.hasLocalOrUnnamedType());
+  }
+
+  static void ensure(const Type *T) {
+    // If the cache is valid, we're okay.
+    if (T->TypeBits.isCacheValid()) return;
+
+    // If this type is non-canonical, ask its canonical type for the
+    // relevant information.
+    if (QualType(T, 0) != T->CanonicalType) {
+      const Type *CT = T->CanonicalType.getTypePtr();
+      ensure(CT);
+      T->TypeBits.CacheValidAndVisibility =
+        CT->TypeBits.CacheValidAndVisibility;
+      T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage;
+      T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed;
+      return;
+    }
+
+    // Compute the cached properties and then set the cache.
+    CachedProperties Result = computeCachedProperties(T);
+    T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U;
+    assert(T->TypeBits.isCacheValid() &&
+           T->TypeBits.getVisibility() == Result.getVisibility());
+    T->TypeBits.CachedLinkage = Result.getLinkage();
+    T->TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType();
+  }
+};
+}
+
+// Instantiate the friend template at a private class.  In a
+// reasonable implementation, these symbols will be internal.
+// It is terrible that this is the best way to accomplish this.
+namespace { class Private {}; }
+typedef TypePropertyCache<Private> Cache;
+
+static CachedProperties computeCachedProperties(const Type *T) {
+  switch (T->getTypeClass()) {
+#define TYPE(Class,Base)
+#define NON_CANONICAL_TYPE(Class,Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+    llvm_unreachable("didn't expect a non-canonical type here");
+
+#define TYPE(Class,Base)
+#define DEPENDENT_TYPE(Class,Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+    // Treat dependent types as external.
+    assert(T->isDependentType());
+    return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+
+  case Type::Builtin:
+    // C++ [basic.link]p8:
+    //   A type is said to have linkage if and only if:
+    //     - it is a fundamental type (3.9.1); or
+    return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+
+  case Type::Record:
+  case Type::Enum: {
+    const TagDecl *Tag = cast<TagType>(T)->getDecl();
+
+    // C++ [basic.link]p8:
+    //     - it is a class or enumeration type that is named (or has a name
+    //       for linkage purposes (7.1.3)) and the name has linkage; or
+    //     -  it is a specialization of a class template (14); or
+    NamedDecl::LinkageInfo LV = Tag->getLinkageAndVisibility();
+    bool IsLocalOrUnnamed =
+      Tag->getDeclContext()->isFunctionOrMethod() ||
+      (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl());
+    return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed);
+  }
+
+    // C++ [basic.link]p8:
+    //   - it is a compound type (3.9.2) other than a class or enumeration, 
+    //     compounded exclusively from types that have linkage; or
+  case Type::Complex:
+    return Cache::get(cast<ComplexType>(T)->getElementType());
+  case Type::Pointer:
+    return Cache::get(cast<PointerType>(T)->getPointeeType());
+  case Type::BlockPointer:
+    return Cache::get(cast<BlockPointerType>(T)->getPointeeType());
+  case Type::LValueReference:
+  case Type::RValueReference:
+    return Cache::get(cast<ReferenceType>(T)->getPointeeType());
+  case Type::MemberPointer: {
+    const MemberPointerType *MPT = cast<MemberPointerType>(T);
+    return merge(Cache::get(MPT->getClass()),
+                 Cache::get(MPT->getPointeeType()));
+  }
+  case Type::ConstantArray:
+  case Type::IncompleteArray:
+  case Type::VariableArray:
+    return Cache::get(cast<ArrayType>(T)->getElementType());
+  case Type::Vector:
+  case Type::ExtVector:
+    return Cache::get(cast<VectorType>(T)->getElementType());
+  case Type::FunctionNoProto:
+    return Cache::get(cast<FunctionType>(T)->getResultType());
+  case Type::FunctionProto: {
+    const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+    CachedProperties result = Cache::get(FPT->getResultType());
+    for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(),
+           ae = FPT->arg_type_end(); ai != ae; ++ai)
+      result = merge(result, Cache::get(*ai));
+    return result;
+  }
+  case Type::ObjCInterface: {
+    NamedDecl::LinkageInfo LV =
+      cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility();
+    return CachedProperties(LV.linkage(), LV.visibility(), false);
+  }
+  case Type::ObjCObject:
+    return Cache::get(cast<ObjCObjectType>(T)->getBaseType());
+  case Type::ObjCObjectPointer:
+    return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
+  }
+
+  llvm_unreachable("unhandled type class");
+
+  // C++ [basic.link]p8:
+  //   Names not covered by these rules have no linkage.
+  return CachedProperties(NoLinkage, DefaultVisibility, false);
 }
 
 /// \brief Determine the linkage of this type.
 Linkage Type::getLinkage() const {
-  if (this != CanonicalType.getTypePtr())
-    return CanonicalType->getLinkage();
-
-  ensureCachedProperties();
+  Cache::ensure(this);
   return TypeBits.getLinkage();
 }
 
 /// \brief Determine the linkage of this type.
 Visibility Type::getVisibility() const {
-  if (this != CanonicalType.getTypePtr())
-    return CanonicalType->getVisibility();
-
-  ensureCachedProperties();
+  Cache::ensure(this);
   return TypeBits.getVisibility();
 }
 
 bool Type::hasUnnamedOrLocalType() const {
-  if (this != CanonicalType.getTypePtr())
-    return CanonicalType->hasUnnamedOrLocalType();
-
-  ensureCachedProperties();
+  Cache::ensure(this);
   return TypeBits.hasLocalOrUnnamedType();
 }
 
 std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const {
-  if (this != CanonicalType.getTypePtr())
-    return CanonicalType->getLinkageAndVisibility();
-
-  ensureCachedProperties();
+  Cache::ensure(this);
   return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility());
 }
 
-
-Type::CachedProperties Type::getCachedProperties(const Type *T) {
-  T = T->CanonicalType.getTypePtr();
-  T->ensureCachedProperties();
-  return CachedProperties(T->TypeBits.getLinkage(),
-                          T->TypeBits.getVisibility(),
-                          T->TypeBits.hasLocalOrUnnamedType());
-}
-
 void Type::ClearLinkageCache() {
-  if (this != CanonicalType.getTypePtr())
-    CanonicalType->ClearLinkageCache();
-  else
-    TypeBits.CacheValidAndVisibility = 0;
-}
-
-Type::CachedProperties Type::getCachedProperties() const { 
-  // Treat dependent types as external.
-  if (isDependentType())
-    return CachedProperties(ExternalLinkage, DefaultVisibility, false);
-
-  // C++ [basic.link]p8:
-  //   Names not covered by these rules have no linkage.
-  return CachedProperties(NoLinkage, DefaultVisibility, false);
-}
-
-Type::CachedProperties BuiltinType::getCachedProperties() const {
-  // C++ [basic.link]p8:
-  //   A type is said to have linkage if and only if:
-  //     - it is a fundamental type (3.9.1); or
-  return CachedProperties(ExternalLinkage, DefaultVisibility, false);
-}
-
-Type::CachedProperties TagType::getCachedProperties() const {
-  // C++ [basic.link]p8:
-  //     - it is a class or enumeration type that is named (or has a name for
-  //       linkage purposes (7.1.3)) and the name has linkage; or
-  //     -  it is a specialization of a class template (14); or
-
-  NamedDecl::LinkageInfo LV = getDecl()->getLinkageAndVisibility();
-  bool IsLocalOrUnnamed =
-    getDecl()->getDeclContext()->isFunctionOrMethod() ||
-                        (!getDecl()->getIdentifier() &&
-                         !getDecl()->getTypedefForAnonDecl());
-  return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed);
-}
-
-// C++ [basic.link]p8:
-//   - it is a compound type (3.9.2) other than a class or enumeration, 
-//     compounded exclusively from types that have linkage; or
-Type::CachedProperties ComplexType::getCachedProperties() const {
-  return Type::getCachedProperties(ElementType);
-}
-
-Type::CachedProperties PointerType::getCachedProperties() const {
-  return Type::getCachedProperties(PointeeType);
-}
-
-Type::CachedProperties BlockPointerType::getCachedProperties() const {
-  return Type::getCachedProperties(PointeeType);
-}
-
-Type::CachedProperties ReferenceType::getCachedProperties() const {
-  return Type::getCachedProperties(PointeeType);
-}
-
-Type::CachedProperties MemberPointerType::getCachedProperties() const {
-  return merge(Type::getCachedProperties(Class),
-               Type::getCachedProperties(PointeeType));
-}
-
-Type::CachedProperties ArrayType::getCachedProperties() const {
-  return Type::getCachedProperties(ElementType);
-}
-
-Type::CachedProperties VectorType::getCachedProperties() const {
-  return Type::getCachedProperties(ElementType);
-}
-
-Type::CachedProperties FunctionNoProtoType::getCachedProperties() const {
-  return Type::getCachedProperties(getResultType());
-}
-
-Type::CachedProperties FunctionProtoType::getCachedProperties() const {
-  CachedProperties Cached = Type::getCachedProperties(getResultType());
-  for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end();
-       A != AEnd; ++A) {
-    Cached = merge(Cached, Type::getCachedProperties(*A));
-  }
-  return Cached;
-}
-
-Type::CachedProperties ObjCInterfaceType::getCachedProperties() const {
-  NamedDecl::LinkageInfo LV = getDecl()->getLinkageAndVisibility();
-  return CachedProperties(LV.linkage(), LV.visibility(), false);
-}
-
-Type::CachedProperties ObjCObjectType::getCachedProperties() const {
-  if (const ObjCInterfaceType *T = getBaseType()->getAs<ObjCInterfaceType>())
-    return Type::getCachedProperties(T);
-  return CachedProperties(ExternalLinkage, DefaultVisibility, false);
-}
-
-Type::CachedProperties ObjCObjectPointerType::getCachedProperties() const {
-  return Type::getCachedProperties(PointeeType);
+  TypeBits.CacheValidAndVisibility = 0;
+  if (QualType(this, 0) != CanonicalType)
+    CanonicalType->TypeBits.CacheValidAndVisibility = 0;
 }





More information about the cfe-commits mailing list