Fixed inconsistency when adding TemplateParameterListsInfo.

llvm-svn: 127876
This commit is contained in:
Abramo Bagnara 2011-03-18 15:16:37 +00:00
parent 3fbfcc0e1e
commit 60804e1604
5 changed files with 153 additions and 111 deletions

View File

@ -507,16 +507,24 @@ public:
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
NestedNameSpecifierLoc QualifierLoc;
/// NumTemplParamLists - The number of template parameter lists
/// that were matched against the template-ids occurring into the NNS.
/// NumTemplParamLists - The number of "outer" template parameter lists.
/// The count includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
unsigned NumTemplParamLists;
/// TemplParamLists - A new-allocated array of size NumTemplParamLists,
/// containing pointers to the matched template parameter lists.
/// containing pointers to the "outer" template parameter lists.
/// It includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
TemplateParameterList** TemplParamLists;
/// Default constructor.
QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {}
/// setTemplateParameterListsInfo - Sets info about matched template
/// setTemplateParameterListsInfo - Sets info about "outer" template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
unsigned NumTPLists,
@ -603,9 +611,7 @@ public:
return getExtInfo()->TemplParamLists[index];
}
void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
TemplateParameterList **TPLists) {
getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
}
TemplateParameterList **TPLists);
SourceLocation getTypeSpecStartLoc() const;
@ -2238,9 +2244,7 @@ public:
return getExtInfo()->TemplParamLists[i];
}
void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
TemplateParameterList **TPLists) {
getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
}
TemplateParameterList **TPLists);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }

View File

@ -961,16 +961,38 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
if (hasExtInfo()) {
// Save type source info pointer.
TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
// Deallocate the extended decl info.
getASTContext().Deallocate(getExtInfo());
// Restore savedTInfo into (non-extended) decl info.
DeclInfo = savedTInfo;
if (getExtInfo()->NumTemplParamLists == 0) {
// Save type source info pointer.
TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
// Deallocate the extended decl info.
getASTContext().Deallocate(getExtInfo());
// Restore savedTInfo into (non-extended) decl info.
DeclInfo = savedTInfo;
}
else
getExtInfo()->QualifierLoc = QualifierLoc;
}
}
}
void
DeclaratorDecl::setTemplateParameterListsInfo(ASTContext &Context,
unsigned NumTPLists,
TemplateParameterList **TPLists) {
assert(NumTPLists > 0);
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
// Allocate external info struct.
DeclInfo = new (getASTContext()) ExtInfo;
// Restore savedTInfo into (extended) decl info.
getExtInfo()->TInfo = savedTInfo;
}
// Set the template parameter lists info.
getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
}
SourceLocation DeclaratorDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
@ -1030,8 +1052,6 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
TemplateParameterList **TPLists) {
assert((NumTPLists == 0 || TPLists != 0) &&
"Empty array of template parameters with positive size!");
assert((NumTPLists == 0 || QualifierLoc) &&
"Nonempty array of template parameters with no qualifier!");
// Free previous template parameters (if any).
if (NumTemplParamLists > 0) {
@ -2100,12 +2120,28 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
if (hasExtInfo()) {
getASTContext().Deallocate(getExtInfo());
TypedefDeclOrQualifier = (TypedefDecl*) 0;
if (getExtInfo()->NumTemplParamLists == 0) {
getASTContext().Deallocate(getExtInfo());
TypedefDeclOrQualifier = (TypedefDecl*) 0;
}
else
getExtInfo()->QualifierLoc = QualifierLoc;
}
}
}
void TagDecl::setTemplateParameterListsInfo(ASTContext &Context,
unsigned NumTPLists,
TemplateParameterList **TPLists) {
assert(NumTPLists > 0);
// Make sure the extended decl info is allocated.
if (!hasExtInfo())
// Allocate external info struct.
TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set the template parameter lists info.
getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
}
//===----------------------------------------------------------------------===//
// EnumDecl Implementation
//===----------------------------------------------------------------------===//

View File

@ -3094,7 +3094,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
bool Invalid = false;
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
@ -3105,9 +3104,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
/*never a friend*/ false,
isExplicitSpecialization,
Invalid)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) {
// There is no such thing as a variable template.
Diag(D.getIdentifierLoc(), diag::err_template_variable)
@ -3123,7 +3119,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
isExplicitSpecialization = true;
}
}
@ -3143,9 +3138,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
SetNestedNameSpecifier(NewVD, D);
if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) {
NewVD->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
TemplateParamLists.size(),
TemplateParamLists.release());
}
}
@ -3636,8 +3631,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
unsigned NumMatchedTemplateParamLists = 0;
if (!getLangOptions().CPlusPlus) {
// Determine whether the function was written with a
// prototype. This true when:
@ -3783,7 +3777,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
SetNestedNameSpecifier(NewFD, D);
isExplicitSpecialization = false;
isFunctionTemplateSpecialization = false;
NumMatchedTemplateParamLists = TemplateParamLists.size();
if (D.isInvalidType())
NewFD->setInvalidDecl();
@ -3804,61 +3797,71 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isFriend,
isExplicitSpecialization,
Invalid)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) {
// This is a function template
if (TemplateParams->size() > 0) {
// This is a function template
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
return 0;
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
return 0;
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
return 0;
}
FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
NewFD->getLocation(),
Name, TemplateParams,
NewFD);
FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
} else {
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend && isFunctionTemplateSpecialization) {
// We want to remove the "template<>", found here.
SourceRange RemoveRange = TemplateParams->getSourceRange();
// If we remove the template<> and the name is not a
// template-id, we're actually silently creating a problem:
// the friend declaration will refer to an untemplated decl,
// and clearly the user wants a template specialization. So
// we need to insert '<>' after the name.
SourceLocation InsertLoc;
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
InsertLoc = PP.getLocForEndOfToken(InsertLoc);
}
Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
<< Name << RemoveRange
<< FixItHint::CreateRemoval(RemoveRange)
<< FixItHint::CreateInsertion(InsertLoc, "<>");
}
}
// A destructor cannot be a template.
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
Diag(NewFD->getLocation(), diag::err_destructor_template);
return 0;
}
if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
NewFD->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
TemplateParamLists.release());
FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
NewFD->getLocation(),
Name, TemplateParams,
NewFD);
FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
NewFD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size() - 1,
TemplateParamLists.release());
}
} else {
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
// For source fidelity, store all the template param lists.
NewFD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size(),
TemplateParamLists.release());
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend) {
// We want to remove the "template<>", found here.
SourceRange RemoveRange = TemplateParams->getSourceRange();
// If we remove the template<> and the name is not a
// template-id, we're actually silently creating a problem:
// the friend declaration will refer to an untemplated decl,
// and clearly the user wants a template specialization. So
// we need to insert '<>' after the name.
SourceLocation InsertLoc;
if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
InsertLoc = D.getName().getSourceRange().getEnd();
InsertLoc = PP.getLocForEndOfToken(InsertLoc);
}
Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
<< Name << RemoveRange
<< FixItHint::CreateRemoval(RemoveRange)
<< FixItHint::CreateInsertion(InsertLoc, "<>");
}
}
}
else {
// All template param lists were matched against the scope specifier:
// this is NOT (an explicit specialization of) a template.
if (TemplateParamLists.size() > 0)
// For source fidelity, store all the template param lists.
NewFD->setTemplateParameterListsInfo(Context,
TemplateParamLists.size(),
TemplateParamLists.release());
}
if (Invalid) {
@ -4180,7 +4183,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// are situations where these conditions don't apply and we
// can actually do this check immediately.
if (isFriend &&
(NumMatchedTemplateParamLists ||
(TemplateParamLists.size() ||
D.getCXXScopeSpec().getScopeRep()->isDependent() ||
CurContext->isDependentContext())) {
// ignore these
@ -6035,27 +6038,24 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Check explicit specializations more carefully.
bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
bool Invalid = false;
// We only need to do this matching if we have template parameters
// or a scope specifier, which also conveniently avoids this work
// for non-C++ cases.
if (NumMatchedTemplateParamLists ||
if (TemplateParameterLists.size() > 0 ||
(SS.isNotEmpty() && TUK != TUK_Reference)) {
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
TemplateParameterLists.get(),
TemplateParameterLists.size(),
TemplateParameterLists.size(),
TUK == TUK_Friend,
isExplicitSpecialization,
Invalid)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).
if (Invalid)
return 0;
@ -6063,7 +6063,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
SS, Name, NameLoc, Attr,
TemplateParams, AS,
NumMatchedTemplateParamLists,
TemplateParameterLists.size() - 1,
(TemplateParameterList**) TemplateParameterLists.release());
return Result.get();
} else {
@ -6584,9 +6584,9 @@ CreateNewDecl:
if (SS.isNotEmpty()) {
if (SS.isSet()) {
New->setQualifierInfo(SS.getWithLocInContext(Context));
if (NumMatchedTemplateParamLists > 0) {
if (TemplateParameterLists.size() > 0) {
New->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
TemplateParameterLists.size(),
(TemplateParameterList**) TemplateParameterLists.release());
}
}

View File

@ -6977,7 +6977,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TempParamLists.size();
bool Invalid = false;
if (TemplateParameterList *TemplateParams
@ -6987,8 +6986,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
/*friend*/ true,
isExplicitSpecialization,
Invalid)) {
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
@ -6997,7 +6994,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
SS, Name, NameLoc, Attr,
TemplateParams, AS_public,
NumMatchedTemplateParamLists,
TempParamLists.size() - 1,
(TemplateParameterList**) TempParamLists.release()).take();
} else {
// The "template<>" header is extraneous.
@ -7012,7 +7009,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
bool isAllExplicitSpecializations = true;
for (unsigned I = 0; I != NumMatchedTemplateParamLists; ++I) {
for (unsigned I = TempParamLists.size(); I-- > 0; ) {
if (TempParamLists.get()[I]->size()) {
isAllExplicitSpecializations = false;
break;

View File

@ -1456,9 +1456,9 @@ DependsOnTemplateParameters(const TemplateSpecializationType *TemplateId,
///
/// \returns the template parameter list, if any, that corresponds to the
/// name that is preceded by the scope specifier @p SS. This template
/// parameter list may be have template parameters (if we're declaring a
/// parameter list may have template parameters (if we're declaring a
/// template) or may have no template parameters (if we're declaring a
/// template specialization), or may be NULL (if we were's declaring isn't
/// template specialization), or may be NULL (if what we're declaring isn't
/// itself a template).
TemplateParameterList *
Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
@ -4390,6 +4390,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
MultiTemplateParamsArg TemplateParameterLists) {
assert(TUK != TUK_Reference && "References are not specializations");
// NOTE: KWLoc is the location of the tag keyword. This will instead
// store the location of the outermost template keyword in the declaration.
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation();
// Find the class template we're specializing
TemplateName Name = TemplateD.getAsVal<TemplateName>();
ClassTemplateDecl *ClassTemplate
@ -4420,10 +4425,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
if (Invalid)
return true;
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
if (TemplateParams)
--NumMatchedTemplateParamLists;
if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true;
@ -4565,10 +4566,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Since the only prior class template specialization with these
// arguments was referenced but not declared, or we're only
// referencing this specialization as a friend, reuse that
// declaration node as our own, updating its source location to
// reflect our new declaration.
// declaration node as our own, updating its source location and
// the list of outer template parameters to reflect our new declaration.
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
TemplateParameterLists.size(),
(TemplateParameterList**) TemplateParameterLists.release());
}
PrevDecl = 0;
CanonType = Context.getTypeDeclType(Specialization);
} else if (isPartialSpecialization) {
@ -4594,7 +4600,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Attr,
TemplateParams,
AS_none,
NumMatchedTemplateParamLists,
TemplateParameterLists.size() - 1,
(TemplateParameterList**) TemplateParameterLists.release());
}
@ -4616,9 +4622,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial,
SequenceNumber);
SetNestedNameSpecifier(Partial, SS);
if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
TemplateParameterLists.size() - 1,
(TemplateParameterList**) TemplateParameterLists.release());
}
@ -4675,9 +4681,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted.size(),
PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
TemplateParameterLists.size(),
(TemplateParameterList**) TemplateParameterLists.release());
}
@ -4747,8 +4753,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateArgs, CanonType);
if (TUK != TUK_Friend) {
Specialization->setTypeAsWritten(WrittenTy);
if (TemplateParams)
Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc());
Specialization->setTemplateKeywordLoc(TemplateKWLoc);
}
TemplateArgsIn.release();