[cfe-commits] r81057 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/AST/Type.h include/clang/AST/TypeNodes.def include/clang/Frontend/PCHBitCodes.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/CodeGen/CGDebugInfo.cpp lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Sema/TreeTransform.h

John McCall rjmccall at apple.com
Fri Sep 4 17:15:47 PDT 2009


Author: rjmccall
Date: Fri Sep  4 19:15:47 2009
New Revision: 81057

URL: http://llvm.org/viewvc/llvm-project?rev=81057&view=rev
Log:
Basic support for representing elaborated type specifiers
directly in the AST.  The current thinking is to create these
only in C++ mode for efficiency.  But for now, they're not being
created at all; patch to follow.

This will let us do things like verify that tags match during
template instantation, as well as signal that an elaborated type
specifier was used for clients that actually care.

Optimally, the TypeLoc hierarchy should be adjusted to carry tag
location information as well.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeNodes.def
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Sep  4 19:15:47 2009
@@ -86,6 +86,7 @@
   llvm::FoldingSet<TypenameType> TypenameTypes;
   llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;
   llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+  llvm::FoldingSet<ElaboratedType> ElaboratedTypes;
   
   llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
   llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -471,6 +472,8 @@
   QualType getTypenameType(NestedNameSpecifier *NNS, 
                            const TemplateSpecializationType *TemplateId,
                            QualType Canon = QualType());
+  QualType getElaboratedType(QualType UnderlyingType,
+                             ElaboratedType::TagKind Tag);
 
   QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
                                 ObjCProtocolDecl **Protocols = 0, 

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Sep  4 19:15:47 2009
@@ -1267,12 +1267,12 @@
 class TagDecl 
   : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
 public:
-  enum TagKind {
-    TK_struct,
-    TK_union,
-    TK_class,
-    TK_enum
-  };
+  // This is really ugly.
+  typedef ElaboratedType::TagKind TagKind;
+  static const TagKind TK_struct = ElaboratedType::TK_struct;
+  static const TagKind TK_union = ElaboratedType::TK_union;
+  static const TagKind TK_class = ElaboratedType::TK_class;
+  static const TagKind TK_enum = ElaboratedType::TK_enum;
 
 private:
   // FIXME: This can be packed into the bitfields in Decl.
@@ -1354,13 +1354,7 @@
   TagDecl* getDefinition(ASTContext& C) const;
   
   const char *getKindName() const {
-    switch (getTagKind()) {
-    default: assert(0 && "Unknown TagKind!");
-    case TK_struct: return "struct";
-    case TK_union:  return "union";
-    case TK_class:  return "class";
-    case TK_enum:   return "enum";
-    }
+    return ElaboratedType::getNameForTagKind(getTagKind());
   }
 
   /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST)

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Sep  4 19:15:47 2009
@@ -1770,6 +1770,65 @@
   static bool classof(const EnumType *) { return true; }
 };
 
+/// ElaboratedType - A non-canonical type used to represents uses of
+/// elaborated type specifiers in C++.  For example:
+///
+///   void foo(union MyUnion);
+///            ^^^^^^^^^^^^^
+///
+/// At the moment, for efficiency we do not create elaborated types in
+/// C, since outside of typedefs all references to structs would
+/// necessarily be elaborated.
+class ElaboratedType : public Type, public llvm::FoldingSetNode {
+public:
+  enum TagKind {
+    TK_struct,
+    TK_union,
+    TK_class,
+    TK_enum
+  };
+
+private:
+  /// The tag that was used in this elaborated type specifier.
+  TagKind Tag;
+
+  /// The underlying type.
+  QualType UnderlyingType;
+
+  explicit ElaboratedType(QualType Ty, TagKind Tag, QualType Canon)
+    : Type(Elaborated, Canon, Canon->isDependentType()),
+      Tag(Tag), UnderlyingType(Ty) { }
+  friend class ASTContext;   // ASTContext creates these.
+
+public:
+  TagKind getTagKind() const { return Tag; }
+  QualType getUnderlyingType() const { return UnderlyingType; }
+
+  static const char *getNameForTagKind(TagKind Kind) {
+    switch (Kind) {
+    default: assert(0 && "Unknown TagKind!");
+    case TK_struct: return "struct";
+    case TK_union:  return "union";
+    case TK_class:  return "class";
+    case TK_enum:   return "enum";
+    }
+  }
+
+  virtual void getAsStringInternal(std::string &InnerString, 
+                                   const PrintingPolicy &Policy) const;
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, getUnderlyingType(), getTagKind());
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType T, TagKind Tag) {
+    ID.AddPointer(T.getAsOpaquePtr());
+    ID.AddInteger(Tag);
+  }
+
+  static bool classof(const ElaboratedType*) { return true; }
+  static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; }
+};
+
 class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
   unsigned Depth : 15;
   unsigned Index : 16;

Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Fri Sep  4 19:15:47 2009
@@ -75,6 +75,7 @@
 ABSTRACT_TYPE(Tag, Type)
 TYPE(Record, TagType)
 TYPE(Enum, TagType)
+NON_CANONICAL_TYPE(Elaborated, Type)
 DEPENDENT_TYPE(TemplateTypeParm, Type)
 TYPE(TemplateSpecialization, Type)
 NON_CANONICAL_TYPE(QualifiedName, Type)

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Fri Sep  4 19:15:47 2009
@@ -399,7 +399,9 @@
       /// \brief A ConstantArrayWithExprType record.
       TYPE_CONSTANT_ARRAY_WITH_EXPR = 24,
       /// \brief A ConstantArrayWithoutExprType record.
-      TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 25
+      TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 25,
+      /// \brief An ElaboratedType record.
+      TYPE_ELABORATED               = 26
     };
 
     /// \brief The type IDs for special types constructed by semantic

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Sep  4 19:15:47 2009
@@ -733,6 +733,10 @@
     break;
   }
 
+  case Type::Elaborated: {
+    return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr());
+  }
+
   case Type::Typedef: {
     const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
     if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
@@ -1901,6 +1905,25 @@
   return QualType(T, 0);    
 }
 
+QualType
+ASTContext::getElaboratedType(QualType UnderlyingType,
+                              ElaboratedType::TagKind Tag) {
+  llvm::FoldingSetNodeID ID;
+  ElaboratedType::Profile(ID, UnderlyingType, Tag);
+  
+  void *InsertPos = 0;
+  ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
+  if (T)
+    return QualType(T, 0);
+
+  QualType Canon = getCanonicalType(UnderlyingType);
+
+  T = new (*this) ElaboratedType(UnderlyingType, Tag, Canon);
+  Types.push_back(T);
+  ElaboratedTypes.InsertNode(T, InsertPos);
+  return QualType(T, 0);
+}
+
 /// CmpProtocolNames - Comparison predicate for sorting protocols
 /// alphabetically.
 static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Sep  4 19:15:47 2009
@@ -1674,6 +1674,16 @@
   InnerString = ObjCQIString + InnerString;
 }
 
+void ElaboratedType::getAsStringInternal(std::string &InnerString, 
+                                         const PrintingPolicy &Policy) const {
+  std::string TypeStr;
+  PrintingPolicy InnerPolicy(Policy);
+  InnerPolicy.SuppressTagKind = true;
+  UnderlyingType.getAsStringInternal(InnerString, InnerPolicy);
+
+  InnerString = std::string(getNameForTagKind(getTagKind())) + ' ' + InnerString;
+}
+
 void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
   if (Policy.SuppressTag)
     return;

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Sep  4 19:15:47 2009
@@ -792,6 +792,9 @@
   case Type::FunctionProto:
   case Type::FunctionNoProto:
     return Slot = CreateType(cast<FunctionType>(Ty), Unit);
+  case Type::Elaborated:
+    return Slot = getOrCreateType(cast<ElaboratedType>(Ty)->getUnderlyingType(),
+                                  Unit);
     
   case Type::ConstantArray:
   case Type::ConstantArrayWithExpr:

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Sep  4 19:15:47 2009
@@ -1941,6 +1941,13 @@
     assert(Record.size() == 1 && "incorrect encoding of enum type");
     return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
 
+  case pch::TYPE_ELABORATED: {
+    assert(Record.size() == 2 && "incorrect encoding of elaborated type");
+    unsigned Tag = Record[1];
+    return Context->getElaboratedType(GetType(Record[0]),
+                                      (ElaboratedType::TagKind) Tag);
+  }
+
   case pch::TYPE_OBJC_INTERFACE: {
     unsigned Idx = 0;
     ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Sep  4 19:15:47 2009
@@ -225,6 +225,12 @@
   Code = pch::TYPE_ENUM;
 }
 
+void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
+  Writer.AddTypeRef(T->getUnderlyingType(), Record);
+  Record.push_back(T->getTagKind());
+  Code = pch::TYPE_ELABORATED;
+}
+
 void 
 PCHTypeWriter::VisitTemplateSpecializationType(
                                        const TemplateSpecializationType *T) {

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=81057&r1=81056&r2=81057&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Sep  4 19:15:47 2009
@@ -441,6 +441,11 @@
   QualType RebuildEnumType(EnumDecl *Enum) {
     return SemaRef.Context.getTypeDeclType(Enum);
   }
+
+  /// \brief Build a new elaborated type.
+  QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag) {
+    return SemaRef.Context.getElaboratedType(T, Tag);
+  }
   
   /// \brief Build a new typeof(expr) type. 
   ///
@@ -2328,6 +2333,21 @@
   
   return getDerived().RebuildEnumType(Enum);
 }
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformElaboratedType(
+                                                    const ElaboratedType *T) {
+  QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
+  if (Underlying.isNull())
+    return QualType();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      Underlying == T->getUnderlyingType())
+    return QualType(T, 0);
+  
+  return getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+}
+                                                 
   
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateTypeParmType(





More information about the cfe-commits mailing list