aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp17
-rw-r--r--lib/AST/DeclCXX.cpp13
-rw-r--r--lib/Sema/SemaDecl.cpp24
-rw-r--r--lib/Sema/SemaExpr.cpp38
-rw-r--r--lib/Sema/SemaTemplate.cpp72
-rw-r--r--lib/Sema/SemaType.cpp7
6 files changed, 132 insertions, 39 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 86c5719bb2..638d1cfd46 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -374,8 +374,7 @@ SourceRange VarDecl::getSourceRange() const {
}
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() {
- if (MemberSpecializationInfo *MSI
- = getASTContext().getInstantiatedFromStaticDataMember(this))
+ if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
return 0;
@@ -389,9 +388,12 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() {
return TSK_Undeclared;
}
+MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() {
+ return getASTContext().getInstantiatedFromStaticDataMember(this);
+}
+
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
- MemberSpecializationInfo *MSI
- = getASTContext().getInstantiatedFromStaticDataMember(this);
+ MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
assert(MSI && "Not an instantiated static data member?");
MSI->setTemplateSpecializationKind(TSK);
}
@@ -703,13 +705,16 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
}
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
- if (MemberSpecializationInfo *Info
- = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+ if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast<FunctionDecl>(Info->getInstantiatedFrom());
return 0;
}
+MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
+ return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
+}
+
void
FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
TemplateSpecializationKind TSK) {
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 64e800094e..b9a87aedd7 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -434,13 +434,16 @@ void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) {
}
CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
- if (MemberSpecializationInfo *MSInfo
- = TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>())
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());
return 0;
}
+MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
+ return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
+}
+
void
CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
TemplateSpecializationKind TSK) {
@@ -456,8 +459,7 @@ TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() {
= dyn_cast<ClassTemplateSpecializationDecl>(this))
return Spec->getSpecializationKind();
- if (MemberSpecializationInfo *MSInfo
- = TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>())
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
return MSInfo->getTemplateSpecializationKind();
return TSK_Undeclared;
@@ -471,8 +473,7 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
return;
}
- if (MemberSpecializationInfo *MSInfo
- = TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>()) {
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
return;
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f12f2b9985..d29b84b308 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4279,14 +4279,22 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Diagnose attempts to redefine a tag.
if (TUK == TUK_Definition) {
if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
- Diag(NameLoc, diag::err_redefinition) << Name;
- Diag(Def->getLocation(), diag::note_previous_definition);
- // If this is a redefinition, recover by making this
- // struct be anonymous, which will make any later
- // references get the previous definition.
- Name = 0;
- PrevDecl = 0;
- Invalid = true;
+ // If we're defining a specialization and the previous definition
+ // is from an implicit instantiation, don't emit an error
+ // here; we'll catch this in the general case below.
+ if (!isExplicitSpecialization ||
+ !isa<CXXRecordDecl>(Def) ||
+ cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization) {
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ // If this is a redefinition, recover by making this
+ // struct be anonymous, which will make any later
+ // references get the previous definition.
+ Name = 0;
+ PrevDecl = 0;
+ Invalid = true;
+ }
} else {
// If the type is currently being defined, complain
// about a nested redefinition.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9831fba319..3dc7d8f4ef 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -6199,10 +6199,28 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// Implicit instantiation of function templates and member functions of
// class templates.
- if (!Function->getBody() &&
- Function->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
- PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
-
+ if (!Function->getBody() &&
+ Function->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation) {
+ bool AlreadyInstantiated = false;
+ if (FunctionTemplateSpecializationInfo *SpecInfo
+ = Function->getTemplateSpecializationInfo()) {
+ if (SpecInfo->getPointOfInstantiation().isInvalid())
+ SpecInfo->setPointOfInstantiation(Loc);
+ else
+ AlreadyInstantiated = true;
+ } else if (MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid())
+ MSInfo->setPointOfInstantiation(Loc);
+ else
+ AlreadyInstantiated = true;
+ }
+
+ if (!AlreadyInstantiated)
+ PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
+ }
+
// FIXME: keep track of references to static functions
Function->setUsed(true);
return;
@@ -6211,9 +6229,15 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Implicit instantiation of static data members of class templates.
if (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember() &&
- Var->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
- PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
+ Var->getInstantiatedFromStaticDataMember()) {
+ MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
+ if (MSInfo->getPointOfInstantiation().isInvalid() &&
+ MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
+ MSInfo->setPointOfInstantiation(Loc);
+ PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
+ }
+ }
// FIXME: keep track of references to static data?
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 8a12ac1168..8ca9089c5e 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2820,7 +2820,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateNameLoc, isPartialSpecialization,
TSK_ExplicitSpecialization))
return true;
-
+
// The canonical type
QualType CanonType;
if (PrevDecl &&
@@ -2918,6 +2918,24 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
CanonType = Context.getTypeDeclType(Specialization);
}
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that specialization shall be declared
+ // before the first use of that specialization that would cause an implicit
+ // instantiation to take place, in every translation unit in which such a
+ // use occurs; no diagnostic is required.
+ if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
+ SourceRange Range(TemplateNameLoc, RAngleLoc);
+ Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
+ << Context.getTypeDeclType(Specialization) << Range;
+
+ Diag(PrevDecl->getPointOfInstantiation(),
+ diag::note_instantiation_required_here)
+ << (PrevDecl->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation);
+ return true;
+ }
+
// If this is not a friend, note that this is an explicit specialization.
if (TUK != TUK_Friend)
Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
@@ -2925,8 +2943,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Check that this isn't a redefinition of this specialization.
if (TUK == TUK_Definition) {
if (RecordDecl *Def = Specialization->getDefinition(Context)) {
- // FIXME: Should also handle explicit specialization after implicit
- // instantiation with a special diagnostic.
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_redefinition)
<< Context.getTypeDeclType(Specialization) << Range;
@@ -3106,7 +3122,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
return true;
// FIXME: Check if the prior specialization has a point of instantiation.
- // If so, we have run afoul of C++ [temp.expl.spec]p6.
+ // If so, we have run afoul of .
// Check the scope of this explicit specialization.
if (CheckTemplateSpecializationScope(*this,
@@ -3114,11 +3130,29 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
Specialization, FD->getLocation(),
false, TSK_ExplicitSpecialization))
return true;
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that spe- cialization shall be declared
+ // before the first use of that specialization that would cause an implicit
+ // instantiation to take place, in every translation unit in which such a
+ // use occurs; no diagnostic is required.
+ FunctionTemplateSpecializationInfo *SpecInfo
+ = Specialization->getTemplateSpecializationInfo();
+ assert(SpecInfo && "Function template specialization info missing?");
+ if (SpecInfo->getPointOfInstantiation().isValid()) {
+ Diag(FD->getLocation(), diag::err_specialization_after_instantiation)
+ << FD;
+ Diag(SpecInfo->getPointOfInstantiation(),
+ diag::note_instantiation_required_here)
+ << (Specialization->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation);
+ return true;
+ }
// Mark the prior declaration as an explicit specialization, so that later
// clients know that this is an explicit specialization.
- // FIXME: Check for prior explicit instantiations?
- Specialization->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+ SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
// Turn the given function declaration into a function template
// specialization, with the template arguments from the previous
@@ -3156,6 +3190,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
// Try to find the member we are instantiating.
NamedDecl *Instantiation = 0;
NamedDecl *InstantiatedFrom = 0;
+ MemberSpecializationInfo *MSInfo = 0;
+
if (!PrevDecl) {
// Nowhere to look anyway.
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
@@ -3164,6 +3200,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
if (Context.hasSameType(Function->getType(), Method->getType())) {
Instantiation = Method;
InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
+ MSInfo = Method->getMemberSpecializationInfo();
break;
}
}
@@ -3173,11 +3210,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
if (PrevVar->isStaticDataMember()) {
Instantiation = PrevDecl;
InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
+ MSInfo = PrevVar->getMemberSpecializationInfo();
}
} else if (isa<RecordDecl>(Member)) {
if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) {
Instantiation = PrevDecl;
InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
+ MSInfo = PrevRecord->getMemberSpecializationInfo();
}
}
@@ -3188,9 +3227,6 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
return false;
}
- // FIXME: Check if the prior declaration has a point of instantiation.
- // If so, we have run afoul of C++ [temp.expl.spec]p6.
-
// Make sure that this is a specialization of a member.
if (!InstantiatedFrom) {
Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
@@ -3199,6 +3235,22 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
return true;
}
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template is
+ // explicitly specialized then that spe- cialization shall be declared
+ // before the first use of that specialization that would cause an implicit
+ // instantiation to take place, in every translation unit in which such a
+ // use occurs; no diagnostic is required.
+ assert(MSInfo && "Member specialization info missing?");
+ if (MSInfo->getPointOfInstantiation().isValid()) {
+ Diag(Member->getLocation(), diag::err_specialization_after_instantiation)
+ << Member;
+ Diag(MSInfo->getPointOfInstantiation(),
+ diag::note_instantiation_required_here)
+ << (MSInfo->getTemplateSpecializationKind() != TSK_ImplicitInstantiation);
+ return true;
+ }
+
// Check the scope of this explicit specialization.
if (CheckTemplateSpecializationScope(*this,
InstantiatedFrom,
@@ -3206,8 +3258,6 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
false, TSK_ExplicitSpecialization))
return true;
- // FIXME: Check for specialization-after-instantiation errors and such.
-
// Note that this is an explicit instantiation of a member.
// the original declaration to note that it is an explicit specialization
// (if it was previously an implicit instantiation). This latter step
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index b82e5ec9b1..3cdf615423 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1677,12 +1677,17 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
+ MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
// This record was instantiated from a class within a template.
- if (Rec->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ if (MSInfo->getTemplateSpecializationKind()
+ != TSK_ExplicitSpecialization) {
+ MSInfo->setPointOfInstantiation(Loc);
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
+ }
}
}
}