summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp4
-rw-r--r--clang/lib/Sema/Sema.h1
-rw-r--r--clang/lib/Sema/SemaDecl.cpp24
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp6
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp32
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp14
6 files changed, 66 insertions, 15 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 638d1cfd46e..429729ea3b0 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -737,8 +737,8 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
const TemplateArgumentList *
FunctionDecl::getTemplateSpecializationArgs() const {
if (FunctionTemplateSpecializationInfo *Info
- = TemplateOrSpecialization
- .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
+ = TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArguments;
}
return 0;
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 40e7426e973..fed2fbc0816 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -551,6 +551,7 @@ public:
bool IsFunctionDefinition,
bool &Redeclaration);
void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+ bool IsExplicitSpecialization,
bool &Redeclaration,
bool &OverloadableAttrRequired);
void CheckMain(FunctionDecl *FD);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 69426ee7554..a1582a900f9 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1735,6 +1735,10 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
return DeclPtrTy();
}
+ if (!DC->isDependentContext() &&
+ RequireCompleteDeclContext(D.getCXXScopeSpec()))
+ return DeclPtrTy();
+
LookupResult Res;
LookupQualifiedName(Res, DC, Name, LookupOrdinaryName, true);
PrevDecl = Res.getAsSingleDecl(Context);
@@ -2807,11 +2811,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
CheckMemberSpecialization(NewFD, PrevDecl))
NewFD->setInvalidDecl();
-
+
// Perform semantic checking on the function declaration.
bool OverloadableAttrRequired = false; // FIXME: HACK!
- CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired);
+ CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization,
+ Redeclaration, /*FIXME:*/OverloadableAttrRequired);
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// An out-of-line member function declaration must also be a
@@ -2914,8 +2918,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// that have been instantiated via C++ template instantiation (called
/// via InstantiateDecl).
///
+/// \param IsExplicitSpecialiation whether this new function declaration is
+/// an explicit specialization of the previous declaration.
+///
/// This sets NewFD->isInvalidDecl() to true if there was an error.
void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+ bool IsExplicitSpecialization,
bool &Redeclaration,
bool &OverloadableAttrRequired) {
// If NewFD is already known erroneous, don't do any of this checking.
@@ -2990,7 +2998,7 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
if (FunctionTemplateDecl *OldTemplateDecl
= dyn_cast<FunctionTemplateDecl>(OldDecl)) {
- NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
FunctionTemplateDecl *NewTemplateDecl
= NewFD->getDescribedFunctionTemplate();
assert(NewTemplateDecl && "Template/non-template mismatch");
@@ -2999,6 +3007,14 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
Method->setAccess(OldTemplateDecl->getAccess());
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
}
+
+ // If this is an explicit specialization of a member that is a function
+ // template, mark it as a member specialization.
+ if (IsExplicitSpecialization &&
+ NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+ NewTemplateDecl->setMemberSpecialization();
+ assert(OldTemplateDecl->isMemberSpecialization());
+ }
} else {
if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
NewFD->setAccess(OldDecl->getAccess());
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 74120498573..3ee15a5b4d8 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -716,6 +716,12 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
assert(T->isDependentType() && "Class template type is not dependent?");
(void)T;
+ // If we are providing an explicit specialization of a member that is a
+ // class template, make a note of that.
+ if (PrevClassTemplate &&
+ PrevClassTemplate->getInstantiatedFromMemberTemplate())
+ PrevClassTemplate->setMemberSpecialization();
+
// Set the access specifier.
if (!Invalid && TUK != TUK_Friend)
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index ec00d9805c0..65260c8e1e6 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -46,15 +46,31 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
break;
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+
+ // If this class template specialization was instantiated from a
+ // specialized member that is a class template, we're done.
+ assert(Spec->getSpecializedTemplate() && "No class template?");
+ if (Spec->getSpecializedTemplate()->isMemberSpecialization())
+ break;
}
-
// Add template arguments from a function template specialization.
else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
- // FIXME: Check whether this is an explicit specialization.
+ if (Function->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
+ break;
+
if (const TemplateArgumentList *TemplateArgs
- = Function->getTemplateSpecializationArgs())
+ = Function->getTemplateSpecializationArgs()) {
+ // Add the template arguments for this specialization.
Result.addOuterTemplateArguments(TemplateArgs);
+ // If this function was instantiated from a specialized member that is
+ // a function template, we're done.
+ assert(Function->getPrimaryTemplate() && "No function template?");
+ if (Function->getPrimaryTemplate()->isMemberSpecialization())
+ break;
+ }
+
// If this is a friend declaration and it declares an entity at
// namespace scope, take arguments from its lexical parent
// instead of its semantic parent.
@@ -940,9 +956,15 @@ Sema::InstantiateClassTemplateSpecialization(
// -- If no matches are found, the instantiation is generated
// from the primary template.
ClassTemplateDecl *OrigTemplate = Template;
- while (OrigTemplate->getInstantiatedFromMemberTemplate())
+ while (OrigTemplate->getInstantiatedFromMemberTemplate()) {
+ // If we've found an explicit specialization of this class template,
+ // stop here and use that as the pattern.
+ if (OrigTemplate->isMemberSpecialization())
+ break;
+
OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
-
+ }
+
Pattern = OrigTemplate->getTemplatedDecl();
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b03734346c4..33fa28866e5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -581,7 +581,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
PrevDecl = 0;
}
- SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(Function, PrevDecl, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
// If the original function was part of a friend declaration,
@@ -748,7 +748,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
- SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
+ SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl) &&
@@ -1057,9 +1057,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl = 0;
if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) {
- while (Primary->getInstantiatedFromMemberTemplate())
+ while (Primary->getInstantiatedFromMemberTemplate()) {
+ // If we have hit a point where the user provided a specialization of
+ // this template, we're done looking.
+ if (Primary->isMemberSpecialization())
+ break;
+
Primary = Primary->getInstantiatedFromMemberTemplate();
-
+ }
+
PatternDecl = Primary->getTemplatedDecl();
} else
PatternDecl = Function->getInstantiatedFromMemberFunction();
OpenPOWER on IntegriCloud