Added template parameters info for out-of-line definitions of class template methods.

llvm-svn: 105882
This commit is contained in:
Abramo Bagnara 2010-06-12 08:15:14 +00:00
parent 7dacc95299
commit da41d0cf5b
4 changed files with 128 additions and 23 deletions

View File

@ -28,6 +28,8 @@ class FunctionTemplateDecl;
class Stmt; class Stmt;
class CompoundStmt; class CompoundStmt;
class StringLiteral; class StringLiteral;
class NestedNameSpecifier;
class TemplateParameterList;
class TemplateArgumentList; class TemplateArgumentList;
class MemberSpecializationInfo; class MemberSpecializationInfo;
class FunctionTemplateSpecializationInfo; class FunctionTemplateSpecializationInfo;
@ -364,15 +366,42 @@ public:
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; } static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
}; };
/// QualifierInfo - A struct with extended info about a syntactic
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
/// NNS - The syntactic name qualifier.
NestedNameSpecifier *NNS;
/// NNSRange - The source range for the qualifier.
SourceRange NNSRange;
/// NumTemplParamLists - The number of template parameter lists
/// that were matched against the template-ids occurring into the NNS.
unsigned NumTemplParamLists;
/// TemplParamLists - A new-allocated array of size NumTemplParamLists,
/// containing pointers to the matched template parameter lists.
TemplateParameterList** TemplParamLists;
/// Default constructor.
QualifierInfo()
: NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {}
/// setTemplateParameterListsInfo - Sets info about matched template
/// parameter lists.
void setTemplateParameterListsInfo(unsigned NumTPLists,
TemplateParameterList **TPLists);
/// Destructor: frees the array of template parameter lists pointers.
~QualifierInfo() { delete[] TemplParamLists; }
private:
// Copy constructor and copy assignment are disabled.
QualifierInfo(const QualifierInfo&);
QualifierInfo& operator=(const QualifierInfo&);
};
/// \brief Represents a ValueDecl that came out of a declarator. /// \brief Represents a ValueDecl that came out of a declarator.
/// Contains type source information through TypeSourceInfo. /// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl { class DeclaratorDecl : public ValueDecl {
// A struct representing both a TInfo and a syntactic qualifier, // A struct representing both a TInfo and a syntactic qualifier,
// to be used for the (uncommon) case of out-of-line declarations. // to be used for the (uncommon) case of out-of-line declarations.
struct ExtInfo { struct ExtInfo : public QualifierInfo {
TypeSourceInfo *TInfo; TypeSourceInfo *TInfo;
NestedNameSpecifier *NNS;
SourceRange NNSRange;
}; };
llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;
@ -392,25 +421,37 @@ public:
TypeSourceInfo *getTypeSourceInfo() const { TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo() return hasExtInfo()
? DeclInfo.get<ExtInfo*>()->TInfo ? getExtInfo()->TInfo
: DeclInfo.get<TypeSourceInfo*>(); : DeclInfo.get<TypeSourceInfo*>();
} }
void setTypeSourceInfo(TypeSourceInfo *TI) { void setTypeSourceInfo(TypeSourceInfo *TI) {
if (hasExtInfo()) if (hasExtInfo())
DeclInfo.get<ExtInfo*>()->TInfo = TI; getExtInfo()->TInfo = TI;
else else
DeclInfo = TI; DeclInfo = TI;
} }
NestedNameSpecifier *getQualifier() const { NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0; return hasExtInfo() ? getExtInfo()->NNS : 0;
} }
SourceRange getQualifierRange() const { SourceRange getQualifierRange() const {
return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange(); return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
} }
void setQualifierInfo(NestedNameSpecifier *Qualifier, void setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange); SourceRange QualifierRange);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
TemplateParameterList *getTemplateParameterList(unsigned index) const {
assert(index < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[index];
}
void setTemplateParameterListsInfo(unsigned NumTPLists,
TemplateParameterList **TPLists) {
getExtInfo()->setTemplateParameterListsInfo(NumTPLists, TPLists);
}
SourceLocation getTypeSpecStartLoc() const; SourceLocation getTypeSpecStartLoc() const;
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
@ -1715,10 +1756,7 @@ private:
// A struct representing syntactic qualifier info, // A struct representing syntactic qualifier info,
// to be used for the (uncommon) case of out-of-line declarations. // to be used for the (uncommon) case of out-of-line declarations.
struct ExtInfo { typedef QualifierInfo ExtInfo;
NestedNameSpecifier *NNS;
SourceRange NNSRange;
};
/// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name
/// is qualified, it points to the qualifier info (nns and range); /// is qualified, it points to the qualifier info (nns and range);
@ -1830,20 +1868,30 @@ public:
TypedefDecl *getTypedefForAnonDecl() const { TypedefDecl *getTypedefForAnonDecl() const {
return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>();
} }
void setTypedefForAnonDecl(TypedefDecl *TDD); void setTypedefForAnonDecl(TypedefDecl *TDD);
NestedNameSpecifier *getQualifier() const { NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0; return hasExtInfo() ? getExtInfo()->NNS : 0;
} }
SourceRange getQualifierRange() const { SourceRange getQualifierRange() const {
return hasExtInfo() return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange
: SourceRange();
} }
void setQualifierInfo(NestedNameSpecifier *Qualifier, void setQualifierInfo(NestedNameSpecifier *Qualifier,
SourceRange QualifierRange); SourceRange QualifierRange);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
TemplateParameterList *getTemplateParameterList(unsigned i) const {
assert(i < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[i];
}
void setTemplateParameterListsInfo(unsigned NumTPLists,
TemplateParameterList **TPLists) {
getExtInfo()->setTemplateParameterListsInfo(NumTPLists, TPLists);
}
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TagDecl *D) { return true; } static bool classof(const TagDecl *D) { return true; }

View File

@ -566,6 +566,29 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
} }
} }
void
QualifierInfo::setTemplateParameterListsInfo(unsigned NumTPLists,
TemplateParameterList **TPLists) {
assert((NumTPLists == 0 || TPLists != 0) &&
"Empty array of template parameters with positive size!");
assert((NumTPLists == 0 || NNS) &&
"Nonempty array of template parameters with no qualifier!");
// Free previous template parameters (if any).
if (NumTemplParamLists > 0) {
delete[] TemplParamLists;
TemplParamLists = 0;
NumTemplParamLists = 0;
}
// Set info on matched template parameter lists (if any).
if (NumTPLists > 0) {
TemplParamLists = new TemplateParameterList*[NumTPLists];
NumTemplParamLists = NumTPLists;
for (unsigned i = NumTPLists; i-- > 0; )
TemplParamLists[i] = TPLists[i];
}
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// VarDecl Implementation // VarDecl Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -2532,6 +2532,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Match up the template parameter lists with the scope specifier, then // Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization. // determine whether we have a template or a template specialization.
bool isExplicitSpecialization = false; bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
if (TemplateParameterList *TemplateParams if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier( = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(), D.getDeclSpec().getSourceRange().getBegin(),
@ -2540,6 +2541,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateParamLists.size(), TemplateParamLists.size(),
/*never a friend*/ false, /*never a friend*/ false,
isExplicitSpecialization)) { isExplicitSpecialization)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) { if (TemplateParams->size() > 0) {
// There is no such thing as a variable template. // There is no such thing as a variable template.
Diag(D.getIdentifierLoc(), diag::err_template_variable) Diag(D.getIdentifierLoc(), diag::err_template_variable)
@ -2568,6 +2572,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
SetNestedNameSpecifier(NewVD, D); SetNestedNameSpecifier(NewVD, D);
if (NumMatchedTemplateParamLists > 0) {
NewVD->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**)TemplateParamLists.release());
}
if (D.getDeclSpec().isThreadSpecified()) { if (D.getDeclSpec().isThreadSpecified()) {
if (NewVD->hasLocalStorage()) if (NewVD->hasLocalStorage())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@ -3088,6 +3097,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
FunctionTemplateDecl *FunctionTemplate = 0; FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false; bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false; bool isFunctionTemplateSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
if (TemplateParameterList *TemplateParams if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier( = MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(), D.getDeclSpec().getSourceRange().getBegin(),
@ -3096,6 +3106,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateParamLists.size(), TemplateParamLists.size(),
isFriend, isFriend,
isExplicitSpecialization)) { isExplicitSpecialization)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) { if (TemplateParams->size() > 0) {
// This is a function template // This is a function template
@ -3135,11 +3148,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< FixItHint::CreateInsertion(InsertLoc, "<>"); << FixItHint::CreateInsertion(InsertLoc, "<>");
} }
} }
// FIXME: Free this memory properly.
TemplateParamLists.release();
} }
if (NumMatchedTemplateParamLists > 0) {
NewFD->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**)TemplateParamLists.release());
}
// C++ [dcl.fct.spec]p5: // C++ [dcl.fct.spec]p5:
// The virtual specifier shall only be used in declarations of // The virtual specifier shall only be used in declarations of
// nonstatic class member functions that appear within a // nonstatic class member functions that appear within a
@ -4965,6 +4980,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Check explicit specializations more carefully. // FIXME: Check explicit specializations more carefully.
bool isExplicitSpecialization = false; bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
if (TUK != TUK_Reference) { if (TUK != TUK_Reference) {
if (TemplateParameterList *TemplateParams if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(KWLoc, SS, = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
@ -4972,6 +4988,9 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TemplateParameterLists.size(), TemplateParameterLists.size(),
TUK == TUK_Friend, TUK == TUK_Friend,
isExplicitSpecialization)) { isExplicitSpecialization)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) { if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may // This is a declaration or definition of a class template (which may
// be a member of another template). // be a member of another template).
@ -4989,8 +5008,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
isExplicitSpecialization = true; isExplicitSpecialization = true;
} }
} }
TemplateParameterLists.release();
} }
DeclContext *SearchDC = CurContext; DeclContext *SearchDC = CurContext;
@ -5394,6 +5411,10 @@ CreateNewDecl:
NestedNameSpecifier *NNS NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier*>(SS.getScopeRep()); = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
New->setQualifierInfo(NNS, SS.getRange()); New->setQualifierInfo(NNS, SS.getRange());
if (NumMatchedTemplateParamLists > 0) {
New->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**) TemplateParameterLists.release());
}
} }
else else
Invalid = true; Invalid = true;

View File

@ -3666,6 +3666,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateParameterLists.size(), TemplateParameterLists.size(),
TUK == TUK_Friend, TUK == TUK_Friend,
isExplicitSpecialization); isExplicitSpecialization);
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
if (TemplateParams)
--NumMatchedTemplateParamLists;
if (TemplateParams && TemplateParams->size() > 0) { if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true; isPartialSpecialization = true;
@ -3857,6 +3861,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial, PrevPartial,
SequenceNumber); SequenceNumber);
SetNestedNameSpecifier(Partial, SS); SetNestedNameSpecifier(Partial, SS);
if (NumMatchedTemplateParamLists > 0) {
Partial->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**) TemplateParameterLists.release());
}
if (PrevPartial) { if (PrevPartial) {
ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial); ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial);
@ -3914,6 +3922,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted, Converted,
PrevDecl); PrevDecl);
SetNestedNameSpecifier(Specialization, SS); SetNestedNameSpecifier(Specialization, SS);
if (NumMatchedTemplateParamLists > 0) {
Specialization->setTemplateParameterListsInfo(
NumMatchedTemplateParamLists,
(TemplateParameterList**) TemplateParameterLists.release());
}
if (PrevDecl) { if (PrevDecl) {
ClassTemplate->getSpecializations().RemoveNode(PrevDecl); ClassTemplate->getSpecializations().RemoveNode(PrevDecl);