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 CompoundStmt;
class StringLiteral;
class NestedNameSpecifier;
class TemplateParameterList;
class TemplateArgumentList;
class MemberSpecializationInfo;
class FunctionTemplateSpecializationInfo;
@ -364,15 +366,42 @@ public:
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.
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
// A struct representing both a TInfo and a syntactic qualifier,
// to be used for the (uncommon) case of out-of-line declarations.
struct ExtInfo {
struct ExtInfo : public QualifierInfo {
TypeSourceInfo *TInfo;
NestedNameSpecifier *NNS;
SourceRange NNSRange;
};
llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;
@ -392,25 +421,37 @@ public:
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? DeclInfo.get<ExtInfo*>()->TInfo
? getExtInfo()->TInfo
: DeclInfo.get<TypeSourceInfo*>();
}
void setTypeSourceInfo(TypeSourceInfo *TI) {
if (hasExtInfo())
DeclInfo.get<ExtInfo*>()->TInfo = TI;
getExtInfo()->TInfo = TI;
else
DeclInfo = TI;
}
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0;
return hasExtInfo() ? getExtInfo()->NNS : 0;
}
SourceRange getQualifierRange() const {
return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange();
return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
}
void setQualifierInfo(NestedNameSpecifier *Qualifier,
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;
// Implement isa/cast/dyncast/etc.
@ -1715,10 +1756,7 @@ private:
// A struct representing syntactic qualifier info,
// to be used for the (uncommon) case of out-of-line declarations.
struct ExtInfo {
NestedNameSpecifier *NNS;
SourceRange NNSRange;
};
typedef QualifierInfo ExtInfo;
/// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name
/// is qualified, it points to the qualifier info (nns and range);
@ -1830,20 +1868,30 @@ public:
TypedefDecl *getTypedefForAnonDecl() const {
return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>();
}
void setTypedefForAnonDecl(TypedefDecl *TDD);
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0;
return hasExtInfo() ? getExtInfo()->NNS : 0;
}
SourceRange getQualifierRange() const {
return hasExtInfo()
? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange
: SourceRange();
return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
}
void setQualifierInfo(NestedNameSpecifier *Qualifier,
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.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
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
//===----------------------------------------------------------------------===//

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
// determine whether we have a template or a template specialization.
bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
@ -2540,6 +2541,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateParamLists.size(),
/*never a friend*/ false,
isExplicitSpecialization)) {
// 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)
@ -2568,6 +2572,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
SetNestedNameSpecifier(NewVD, D);
if (NumMatchedTemplateParamLists > 0) {
NewVD->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**)TemplateParamLists.release());
}
if (D.getDeclSpec().isThreadSpecified()) {
if (NewVD->hasLocalStorage())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@ -3088,6 +3097,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
@ -3096,6 +3106,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateParamLists.size(),
isFriend,
isExplicitSpecialization)) {
// All but one template parameter lists have been matching.
--NumMatchedTemplateParamLists;
if (TemplateParams->size() > 0) {
// This is a function template
@ -3135,11 +3148,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< FixItHint::CreateInsertion(InsertLoc, "<>");
}
}
// FIXME: Free this memory properly.
TemplateParamLists.release();
}
if (NumMatchedTemplateParamLists > 0) {
NewFD->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**)TemplateParamLists.release());
}
// C++ [dcl.fct.spec]p5:
// The virtual specifier shall only be used in declarations of
// 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.
bool isExplicitSpecialization = false;
unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
if (TUK != TUK_Reference) {
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
@ -4972,6 +4988,9 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TemplateParameterLists.size(),
TUK == TUK_Friend,
isExplicitSpecialization)) {
// 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).
@ -4989,8 +5008,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
isExplicitSpecialization = true;
}
}
TemplateParameterLists.release();
}
DeclContext *SearchDC = CurContext;
@ -5394,6 +5411,10 @@ CreateNewDecl:
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier*>(SS.getScopeRep());
New->setQualifierInfo(NNS, SS.getRange());
if (NumMatchedTemplateParamLists > 0) {
New->setTemplateParameterListsInfo(NumMatchedTemplateParamLists,
(TemplateParameterList**) TemplateParameterLists.release());
}
}
else
Invalid = true;

View File

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