aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-04-08 09:05:18 +0000
committerJohn McCall <rjmccall@apple.com>2010-04-08 09:05:18 +0000
commitaf2094e7cecadf36667deb61a83587ffdd979bd3 (patch)
tree5ff432cdff32239bd62431a429dd09292c69c1ec /lib/Sema/SemaDecl.cpp
parent2b60513052e81f66f852b21226ab488f9ed88f1d (diff)
Implement dependent friend function template specializations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100753 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp49
1 files changed, 32 insertions, 17 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 590a014c92..8df611fcf1 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2935,7 +2935,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
- // C++0x [temp.expl.spec]p20 forbids "template<> void foo(int);".
+ // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend && isFunctionTemplateSpecialization) {
// We want to remove the "template<>", found here.
SourceRange RemoveRange = TemplateParams->getSourceRange();
@@ -3139,23 +3139,38 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// "friend void foo<>(int);" is an implicit specialization decl.
isFunctionTemplateSpecialization = true;
}
- }
-
- if (isFunctionTemplateSpecialization) {
- if (isFriend && NewFD->getType()->isDependentType()) {
- // FIXME: When we see a friend of a function template
- // specialization with a dependent type, we can't match it now;
- // for now, we just drop it, until we have a reasonable way to
- // represent the parsed-but-not-matched friend function template
- // specialization in the AST.
- return 0;
- } else if (CheckFunctionTemplateSpecialization(NewFD,
- (HasExplicitTemplateArgs ? &TemplateArgs : 0),
- Previous))
+ } else if (isFriend && isFunctionTemplateSpecialization) {
+ // This combination is only possible in a recovery case; the user
+ // wrote something like:
+ // template <> friend void foo(int);
+ // which we're recovering from as if the user had written:
+ // friend void foo<>(int);
+ // Go ahead and fake up a template id.
+ HasExplicitTemplateArgs = true;
+ TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
+ TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
+ }
+
+ // If it's a friend (and only if it's a friend), it's possible
+ // that either the specialized function type or the specialized
+ // template is dependent, and therefore matching will fail. In
+ // this case, don't check the specialization yet.
+ if (isFunctionTemplateSpecialization && isFriend &&
+ (NewFD->getType()->isDependentType() || DC->isDependentContext())) {
+ assert(HasExplicitTemplateArgs &&
+ "friend function specialization without template args");
+ if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
+ Previous))
NewFD->setInvalidDecl();
- } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
- CheckMemberSpecialization(NewFD, Previous))
- NewFD->setInvalidDecl();
+ } else if (isFunctionTemplateSpecialization) {
+ if (CheckFunctionTemplateSpecialization(NewFD,
+ (HasExplicitTemplateArgs ? &TemplateArgs : 0),
+ Previous))
+ NewFD->setInvalidDecl();
+ } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {
+ if (CheckMemberSpecialization(NewFD, Previous))
+ NewFD->setInvalidDecl();
+ }
// Perform semantic checking on the function declaration.
bool OverloadableAttrRequired = false; // FIXME: HACK!