forked from OSchip/llvm-project
Added template parameters info for out-of-line definitions of class template methods.
llvm-svn: 105882
This commit is contained in:
parent
7dacc95299
commit
da41d0cf5b
|
@ -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; }
|
||||||
|
|
|
@ -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
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue