forked from OSchip/llvm-project
Make the type associated with a ClassTemplateSpecializationDecl be a
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. llvm-svn: 65577
This commit is contained in:
parent
e9817aaa05
commit
d56a91e8f6
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue