]> granicus.if.org Git - clang/commitdiff
Make the type associated with a ClassTemplateSpecializationDecl be a
authorDouglas Gregor <dgregor@apple.com>
Thu, 26 Feb 2009 22:19:44 +0000 (22:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 26 Feb 2009 22:19:44 +0000 (22:19 +0000)
nicely sugared type that shows how the user wrote the actual
specialization. This sugared type won't actually show up until we
start doing instantiations.

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

include/clang/AST/Decl.h
include/clang/AST/DeclTemplate.h
include/clang/AST/Type.h
lib/AST/ASTContext.cpp
lib/AST/Decl.cpp
lib/AST/DeclBase.cpp
lib/AST/DeclTemplate.cpp
lib/AST/Type.cpp
lib/Sema/SemaTemplate.cpp

index aa009c8b4c0d9061a57049a7e9040cb5b3b5e5a8..9536eca300ca7db949689f25d49e38db0af2b6bb 100644 (file)
@@ -814,6 +814,7 @@ class TypeDecl : public NamedDecl {
   friend class DeclContext;
   friend class TagDecl;
   friend class TemplateTypeParmDecl;
+  friend class ClassTemplateSpecializationDecl;
 
 protected:
   TypeDecl(Kind DK, DeclContext *DC, SourceLocation L,
index a075d74e610f6eb13b8dcdcab45e1e4987331ceb..92c2d6b8f67a24cc765aa4d15139a7c236468b26 100644 (file)
@@ -606,6 +606,12 @@ public:
     Profile(ID, template_arg_begin(), getNumTemplateArgs());
   }
 
+  /// \brief Sets the type of this specialization as it was written by
+  /// the user. This will be a class template specialization type.
+  void setTypeAsWritten(QualType T) {
+    TypeForDecl = T.getTypePtr();
+  }
+
   static void 
   Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, 
           unsigned NumTemplateArgs) {
index f5bd5f19f0ffd46d98fe6f14ba22b10e94caa745..3ee513b17f4038535633b0646e6736f7eef94798 100644 (file)
@@ -407,6 +407,7 @@ public:
   const BlockPointerType *getAsBlockPointerType() const;
   const ReferenceType *getAsReferenceType() const;
   const MemberPointerType *getAsMemberPointerType() const;
+  const TagType *getAsTagType() const;
   const RecordType *getAsRecordType() const;
   const RecordType *getAsStructureType() const;
   /// NOTE: getAs*ArrayType are methods on ASTContext.
@@ -1309,7 +1310,7 @@ class TagType : public Type {
   /// definition in progress), if there is such a definition. The
   /// single-bit value will be non-zero when this tag is in the
   /// process of being defined.
-  llvm::PointerIntPair<TagDecl *, 1> decl;
+  mutable llvm::PointerIntPair<TagDecl *, 1> decl;
   friend class ASTContext;
   friend class TagDecl;
 
index 60d8b8be8015331076f4be4bab8ff0339a0d306c..2b4bc89aacef7eca8638b12bcbaa27c25f4f3da2 100644 (file)
@@ -1307,6 +1307,8 @@ ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
                                                unsigned NumArgs,
                                                uintptr_t *Args, bool *ArgIsType,
                                                QualType Canon) {
+  Canon = getCanonicalType(Canon);
+
   llvm::FoldingSetNodeID ID;
   ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args, 
                                            ArgIsType);
index 2732bf93c1864131219203eae8a93f03a164fe40..ab654920238735badf9e3a56f62ecd8798ec93ff 100644 (file)
@@ -374,22 +374,24 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
 //===----------------------------------------------------------------------===//
 
 void TagDecl::startDefinition() {
-  cast<TagType>(TypeForDecl)->decl.setPointer(this);
-  cast<TagType>(TypeForDecl)->decl.setInt(1);
+  TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
+  TagT->decl.setPointer(this);
+  TagT->getAsTagType()->decl.setInt(1);
 }
 
 void TagDecl::completeDefinition() {
   assert((!TypeForDecl || 
-          cast<TagType>(TypeForDecl)->decl.getPointer() == this) &&
+          TypeForDecl->getAsTagType()->decl.getPointer() == this) &&
          "Attempt to redefine a tag definition?");
   IsDefinition = true;
-  cast<TagType>(TypeForDecl)->decl.setPointer(this);
-  cast<TagType>(TypeForDecl)->decl.setInt(0);
+  TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType());
+  TagT->decl.setPointer(this);
+  TagT->decl.setInt(0);
 }
 
 TagDecl* TagDecl::getDefinition(ASTContext& C) const {
   QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));
-  TagDecl* D = cast<TagDecl>(cast<TagType>(T)->getDecl());  
+  TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl());
   return D->isDefinition() ? D : 0;
 }
 
index d6a0c35d92897d7cb65c470c14bf930ee1e2152b..574de1675f49ccd29b0d589960fdd033f253f16a 100644 (file)
@@ -446,8 +446,7 @@ DeclContext *DeclContext::getPrimaryContext() {
     if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
       // If this is a tag type that has a definition or is currently
       // being defined, that definition is our primary context.
-      if (TagType *TagT 
-            = cast_or_null<TagType>(cast<TagDecl>(this)->TypeForDecl))
+      if (const TagType *TagT = cast<TagDecl>(this)->TypeForDecl->getAsTagType())
         if (TagT->isBeingDefined() || 
             (TagT->getDecl() && TagT->getDecl()->isDefinition()))
           return TagT->getDecl();
index 3ed4435bb379959e1db608c193c8dcfdc5fadf50..ed4fd44e707b7541bcf211d1cc5f649ad226af8b 100644 (file)
@@ -179,7 +179,6 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context,
   ClassTemplateSpecializationDecl *Result
     = new (Mem) ClassTemplateSpecializationDecl(DC, L, SpecializedTemplate,
                                                 TemplateArgs, NumTemplateArgs);
-  // FIXME: Do we want a prettier type here?
   Context.getTypeDeclType(Result, PrevDecl);
   return Result;
 }
index 210be03fa83ecd65f6732ef52da11a42f0661d85..327e623aafdb0bf2dbf6c1d7ed2ef2b99871bb49 100644 (file)
@@ -331,7 +331,7 @@ bool Type::isVariablyModifiedType() const {
 }
 
 const RecordType *Type::getAsRecordType() const {
-  // If this is directly a reference type, return it.
+  // If this is directly a record type, return it.
   if (const RecordType *RTy = dyn_cast<RecordType>(this))
     return RTy;
   
@@ -348,6 +348,24 @@ const RecordType *Type::getAsRecordType() const {
   return getDesugaredType()->getAsRecordType();
 }
 
+const TagType *Type::getAsTagType() const {
+  // If this is directly a tag type, return it.
+  if (const TagType *TagTy = dyn_cast<TagType>(this))
+    return TagTy;
+  
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<TagType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<TagType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsTagType();
+    return 0;
+  }
+
+  // If this is a typedef for a tag type, strip the typedef off without
+  // losing all typedef information.
+  return getDesugaredType()->getAsTagType();
+}
+
 const RecordType *Type::getAsStructureType() const {
   // If this is directly a structure type, return it.
   if (const RecordType *RT = dyn_cast<RecordType>(this)) {
index f69f546177cbd2f4e8612d23f171ab0af69764c1..97eb9be36ccce275ff1659bfb1539e3d83732142 100644 (file)
@@ -1727,8 +1727,20 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
     }
   }
 
-  // FIXME: We want to create a nicely sugared type to use as the
-  // type of this explicit specialization.
+  // Build the fully-sugared type for this class template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  Specialization->setTypeAsWritten(
+    Context.getClassTemplateSpecializationType(ClassTemplate, 
+                                               TemplateArgs.size(),
+                  reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()), 
+                                               TemplateArgs.getArgIsType(),
+                                  Context.getTypeDeclType(Specialization)));
+  TemplateArgs.release();
 
   // C++ [temp.expl.spec]p9:
   //   A template explicit specialization is in the scope of the