forked from OSchip/llvm-project
Don't omit class explicit instantiation from AST.
llvm-svn: 105880
This commit is contained in:
parent
c6ac0ce89f
commit
8075c85230
|
@ -901,9 +901,22 @@ class ClassTemplateSpecializationDecl
|
|||
llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
|
||||
SpecializedTemplate;
|
||||
|
||||
/// \brief The type-as-written of an explicit template specialization.
|
||||
/// \brief Further info for explicit template specialization/instantiation.
|
||||
struct ExplicitSpecializationInfo {
|
||||
/// \brief The type-as-written.
|
||||
TypeSourceInfo *TypeAsWritten;
|
||||
/// \brief The location of the extern keyword.
|
||||
SourceLocation ExternLoc;
|
||||
/// \brief The location of the template keyword.
|
||||
SourceLocation TemplateKeywordLoc;
|
||||
|
||||
ExplicitSpecializationInfo()
|
||||
: TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
|
||||
};
|
||||
|
||||
/// \brief Further info for explicit template specialization/instantiation.
|
||||
/// Does not apply to implicit specializations.
|
||||
TypeSourceInfo *TypeAsWritten;
|
||||
ExplicitSpecializationInfo *ExplicitInfo;
|
||||
|
||||
/// \brief The template arguments used to describe this specialization.
|
||||
TemplateArgumentList TemplateArgs;
|
||||
|
@ -1018,13 +1031,33 @@ public:
|
|||
/// \brief Sets the type of this specialization as it was written by
|
||||
/// the user. This will be a class template specialization type.
|
||||
void setTypeAsWritten(TypeSourceInfo *T) {
|
||||
TypeAsWritten = T;
|
||||
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
|
||||
ExplicitInfo->TypeAsWritten = T;
|
||||
}
|
||||
|
||||
/// \brief Gets the type of this specialization as it was written by
|
||||
/// the user, if it was so written.
|
||||
TypeSourceInfo *getTypeAsWritten() const {
|
||||
return TypeAsWritten;
|
||||
return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
|
||||
}
|
||||
|
||||
/// \brief Gets the location of the extern keyword, if present.
|
||||
SourceLocation getExternLoc() const {
|
||||
return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
|
||||
}
|
||||
/// \brief Sets the location of the extern keyword.
|
||||
void setExternLoc(SourceLocation Loc) {
|
||||
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
|
||||
ExplicitInfo->ExternLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc) {
|
||||
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
|
||||
ExplicitInfo->TemplateKeywordLoc = Loc;
|
||||
}
|
||||
/// \brief Gets the location of the template keyword, if present.
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
|
|
|
@ -426,7 +426,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
|
|||
SpecializedTemplate->getIdentifier(),
|
||||
PrevDecl),
|
||||
SpecializedTemplate(SpecializedTemplate),
|
||||
TypeAsWritten(0),
|
||||
ExplicitInfo(0),
|
||||
TemplateArgs(Context, Builder, /*TakeArgs=*/true),
|
||||
SpecializationKind(TSK_Undeclared) {
|
||||
}
|
||||
|
@ -449,6 +449,8 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
|
|||
}
|
||||
|
||||
void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
|
||||
delete ExplicitInfo;
|
||||
|
||||
if (SpecializedPartialSpecialization *PartialSpec
|
||||
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
||||
C.Deallocate(PartialSpec);
|
||||
|
|
|
@ -3981,8 +3981,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
TypeSourceInfo *WrittenTy
|
||||
= Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
|
||||
TemplateArgs, CanonType);
|
||||
if (TUK != TUK_Friend)
|
||||
if (TUK != TUK_Friend) {
|
||||
Specialization->setTypeAsWritten(WrittenTy);
|
||||
Specialization->setTemplateKeywordLoc(KWLoc);
|
||||
}
|
||||
TemplateArgsIn.release();
|
||||
|
||||
// C++ [temp.expl.spec]p9:
|
||||
|
@ -4076,7 +4078,7 @@ static void StripImplicitInstantiation(NamedDecl *D) {
|
|||
/// \param PrevPointOfInstantiation if valid, indicates where the previus
|
||||
/// declaration was instantiated (either implicitly or explicitly).
|
||||
///
|
||||
/// \param SuppressNew will be set to true to indicate that the new
|
||||
/// \param HasNoEffect will be set to true to indicate that the new
|
||||
/// specialization or instantiation has no effect and should be ignored.
|
||||
///
|
||||
/// \returns true if there was an error that should prevent the introduction of
|
||||
|
@ -4087,8 +4089,8 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
NamedDecl *PrevDecl,
|
||||
TemplateSpecializationKind PrevTSK,
|
||||
SourceLocation PrevPointOfInstantiation,
|
||||
bool &SuppressNew) {
|
||||
SuppressNew = false;
|
||||
bool &HasNoEffect) {
|
||||
HasNoEffect = false;
|
||||
|
||||
switch (NewTSK) {
|
||||
case TSK_Undeclared:
|
||||
|
@ -4145,7 +4147,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
switch (PrevTSK) {
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
// This explicit instantiation declaration is redundant (that's okay).
|
||||
SuppressNew = true;
|
||||
HasNoEffect = true;
|
||||
return false;
|
||||
|
||||
case TSK_Undeclared:
|
||||
|
@ -4160,7 +4162,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
// of a template appears after a declaration of an explicit
|
||||
// specialization for that template, the explicit instantiation has no
|
||||
// effect.
|
||||
SuppressNew = true;
|
||||
HasNoEffect = true;
|
||||
return false;
|
||||
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
|
@ -4174,7 +4176,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
diag::note_explicit_instantiation_definition_here);
|
||||
assert(PrevPointOfInstantiation.isValid() &&
|
||||
"Explicit instantiation without point of instantiation?");
|
||||
SuppressNew = true;
|
||||
HasNoEffect = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -4203,7 +4205,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
Diag(PrevDecl->getLocation(),
|
||||
diag::note_previous_template_specialization);
|
||||
}
|
||||
SuppressNew = true;
|
||||
HasNoEffect = true;
|
||||
return false;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
@ -4220,7 +4222,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
<< PrevDecl;
|
||||
Diag(PrevPointOfInstantiation,
|
||||
diag::note_previous_explicit_instantiation);
|
||||
SuppressNew = true;
|
||||
HasNoEffect = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -4369,14 +4371,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
= Specialization->getTemplateSpecializationInfo();
|
||||
assert(SpecInfo && "Function template specialization info missing?");
|
||||
|
||||
bool SuppressNew = false;
|
||||
bool HasNoEffect = false;
|
||||
if (!isFriend &&
|
||||
CheckSpecializationInstantiationRedecl(FD->getLocation(),
|
||||
TSK_ExplicitSpecialization,
|
||||
Specialization,
|
||||
SpecInfo->getTemplateSpecializationKind(),
|
||||
SpecInfo->getPointOfInstantiation(),
|
||||
SuppressNew))
|
||||
HasNoEffect))
|
||||
return true;
|
||||
|
||||
// Mark the prior declaration as an explicit specialization, so that later
|
||||
|
@ -4503,13 +4505,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
|
|||
// use occurs; no diagnostic is required.
|
||||
assert(MSInfo && "Member specialization info missing?");
|
||||
|
||||
bool SuppressNew = false;
|
||||
bool HasNoEffect = false;
|
||||
if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
|
||||
TSK_ExplicitSpecialization,
|
||||
Instantiation,
|
||||
MSInfo->getTemplateSpecializationKind(),
|
||||
MSInfo->getPointOfInstantiation(),
|
||||
SuppressNew))
|
||||
HasNoEffect))
|
||||
return true;
|
||||
|
||||
// Check the scope of this explicit specialization.
|
||||
|
@ -4711,6 +4713,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
ClassTemplateSpecializationDecl *PrevDecl
|
||||
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
TemplateSpecializationKind PrevDecl_TSK
|
||||
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
|
||||
|
||||
// C++0x [temp.explicit]p2:
|
||||
// [...] An explicit instantiation shall appear in an enclosing
|
||||
// namespace of its template. [...]
|
||||
|
@ -4722,31 +4727,31 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
ClassTemplateSpecializationDecl *Specialization = 0;
|
||||
|
||||
bool ReusedDecl = false;
|
||||
bool HasNoEffect = false;
|
||||
if (PrevDecl) {
|
||||
bool SuppressNew = false;
|
||||
if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
|
||||
PrevDecl,
|
||||
PrevDecl->getSpecializationKind(),
|
||||
PrevDecl, PrevDecl_TSK,
|
||||
PrevDecl->getPointOfInstantiation(),
|
||||
SuppressNew))
|
||||
HasNoEffect))
|
||||
return DeclPtrTy::make(PrevDecl);
|
||||
|
||||
if (SuppressNew)
|
||||
return DeclPtrTy::make(PrevDecl);
|
||||
|
||||
if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation ||
|
||||
PrevDecl->getSpecializationKind() == TSK_Undeclared) {
|
||||
// Even though HasNoEffect == true means that this explicit instantiation
|
||||
// has no effect on semantics, we go on to put its syntax in the AST.
|
||||
|
||||
if (PrevDecl_TSK == TSK_ImplicitInstantiation ||
|
||||
PrevDecl_TSK == TSK_Undeclared) {
|
||||
// Since the only prior class template specialization with these
|
||||
// arguments was referenced but not declared, reuse that
|
||||
// declaration node as our own, updating its source location to
|
||||
// reflect our new declaration.
|
||||
// declaration node as our own, updating the source location
|
||||
// for the template name to reflect our new declaration.
|
||||
// (Other source locations will be updated later.)
|
||||
Specialization = PrevDecl;
|
||||
Specialization->setLocation(TemplateNameLoc);
|
||||
PrevDecl = 0;
|
||||
ReusedDecl = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!Specialization) {
|
||||
// Create a new class template specialization declaration node for
|
||||
// this explicit specialization.
|
||||
|
@ -4758,15 +4763,16 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
Converted, PrevDecl);
|
||||
SetNestedNameSpecifier(Specialization, SS);
|
||||
|
||||
if (PrevDecl) {
|
||||
// Remove the previous declaration from the folding set, since we want
|
||||
// to introduce a new declaration.
|
||||
ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
|
||||
ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
// Insert the new specialization.
|
||||
ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
|
||||
if (!HasNoEffect) {
|
||||
if (PrevDecl) {
|
||||
// Remove the previous declaration from the folding set, since we want
|
||||
// to introduce a new declaration.
|
||||
ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
|
||||
ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
// Insert the new specialization.
|
||||
ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the fully-sugared type for this explicit instantiation as
|
||||
|
@ -4783,12 +4789,21 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
Specialization->setTypeAsWritten(WrittenTy);
|
||||
TemplateArgsIn.release();
|
||||
|
||||
if (!ReusedDecl) {
|
||||
// Add the explicit instantiation into its lexical context. However,
|
||||
// since explicit instantiations are never found by name lookup, we
|
||||
// just put it into the declaration context directly.
|
||||
Specialization->setLexicalDeclContext(CurContext);
|
||||
CurContext->addDecl(Specialization);
|
||||
// Set source locations for keywords.
|
||||
Specialization->setExternLoc(ExternLoc);
|
||||
Specialization->setTemplateKeywordLoc(TemplateLoc);
|
||||
|
||||
// Add the explicit instantiation into its lexical context. However,
|
||||
// since explicit instantiations are never found by name lookup, we
|
||||
// just put it into the declaration context directly.
|
||||
Specialization->setLexicalDeclContext(CurContext);
|
||||
CurContext->addDecl(Specialization);
|
||||
|
||||
// Syntax is now OK, so return if it has no other effect on semantics.
|
||||
if (HasNoEffect) {
|
||||
// Set the template specialization kind.
|
||||
Specialization->setTemplateSpecializationKind(TSK);
|
||||
return DeclPtrTy::make(Specialization);
|
||||
}
|
||||
|
||||
// C++ [temp.explicit]p3:
|
||||
|
@ -4803,8 +4818,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
Specialization->getDefinition());
|
||||
if (!Def)
|
||||
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
|
||||
else if (TSK == TSK_ExplicitInstantiationDefinition)
|
||||
else if (TSK == TSK_ExplicitInstantiationDefinition) {
|
||||
MarkVTableUsed(TemplateNameLoc, Specialization, true);
|
||||
Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
|
||||
}
|
||||
|
||||
// Instantiate the members of this class template specialization.
|
||||
Def = cast_or_null<ClassTemplateSpecializationDecl>(
|
||||
|
@ -4821,6 +4838,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
|
||||
}
|
||||
|
||||
// Set the template specialization kind.
|
||||
Specialization->setTemplateSpecializationKind(TSK);
|
||||
return DeclPtrTy::make(Specialization);
|
||||
}
|
||||
|
||||
|
@ -4898,15 +4917,15 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
PrevDecl = Record;
|
||||
if (PrevDecl) {
|
||||
MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
|
||||
bool SuppressNew = false;
|
||||
bool HasNoEffect = false;
|
||||
assert(MSInfo && "No member specialization information?");
|
||||
if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
|
||||
PrevDecl,
|
||||
MSInfo->getTemplateSpecializationKind(),
|
||||
MSInfo->getPointOfInstantiation(),
|
||||
SuppressNew))
|
||||
HasNoEffect))
|
||||
return true;
|
||||
if (SuppressNew)
|
||||
if (HasNoEffect)
|
||||
return TagD;
|
||||
}
|
||||
|
||||
|
@ -5055,13 +5074,13 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
// Verify that it is okay to explicitly instantiate here.
|
||||
MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
|
||||
assert(MSInfo && "Missing static data member specialization info?");
|
||||
bool SuppressNew = false;
|
||||
bool HasNoEffect = false;
|
||||
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
|
||||
MSInfo->getTemplateSpecializationKind(),
|
||||
MSInfo->getPointOfInstantiation(),
|
||||
SuppressNew))
|
||||
HasNoEffect))
|
||||
return true;
|
||||
if (SuppressNew)
|
||||
if (HasNoEffect)
|
||||
return DeclPtrTy();
|
||||
|
||||
// Instantiate static data member.
|
||||
|
@ -5158,17 +5177,17 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
PrevDecl = Specialization;
|
||||
|
||||
if (PrevDecl) {
|
||||
bool SuppressNew = false;
|
||||
bool HasNoEffect = false;
|
||||
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
|
||||
PrevDecl,
|
||||
PrevDecl->getTemplateSpecializationKind(),
|
||||
PrevDecl->getPointOfInstantiation(),
|
||||
SuppressNew))
|
||||
HasNoEffect))
|
||||
return true;
|
||||
|
||||
// FIXME: We may still want to build some representation of this
|
||||
// explicit specialization.
|
||||
if (SuppressNew)
|
||||
if (HasNoEffect)
|
||||
return DeclPtrTy();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue