aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h1
-rw-r--r--include/clang/AST/DeclTemplate.h6
-rw-r--r--include/clang/AST/Type.h3
-rw-r--r--lib/AST/ASTContext.cpp2
-rw-r--r--lib/AST/Decl.cpp14
-rw-r--r--lib/AST/DeclBase.cpp3
-rw-r--r--lib/AST/DeclTemplate.cpp1
-rw-r--r--lib/AST/Type.cpp20
-rw-r--r--lib/Sema/SemaTemplate.cpp16
9 files changed, 53 insertions, 13 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index aa009c8b4c..9536eca300 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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,
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index a075d74e61..92c2d6b8f6 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -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) {
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index f5bd5f19f0..3ee513b17f 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -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;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 60d8b8be80..2b4bc89aac 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 2732bf93c1..ab65492023 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -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;
}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index d6a0c35d92..574de1675f 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -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();
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 3ed4435bb3..ed4fd44e70 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -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;
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 210be03fa8..327e623aaf 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -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)) {
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index f69f546177..97eb9be36c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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