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 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; }
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue