aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-30 22:42:42 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-30 22:42:42 +0000
commit259571e27e513cfaf691cc7447e09b31a47d5438 (patch)
tree05709f41ebcbf2eb326c037eed9ffbf0305e9b6f
parentc78c06d81f9838aea4198e4965cc1b26bb0bf838 (diff)
When a friend is declared in a dependent context, don't even try to
match it up with a declaration in the outer scope. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85628 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplate.cpp10
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp5
-rw-r--r--test/SemaTemplate/friend-template.cpp19
3 files changed, 31 insertions, 3 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index fb5eef2760..f7a22d2eb0 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -613,11 +613,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
SemanticContext = PrevDecl->getDeclContext();
} else {
// Declarations in outer scopes don't matter. However, the outermost
- // context we computed is the semntic context for our new
+ // context we computed is the semantic context for our new
// declaration.
PrevDecl = 0;
SemanticContext = OutermostContext;
}
+
+ if (CurContext->isDependentContext()) {
+ // If this is a dependent context, we don't want to link the friend
+ // class template to the template in scope, because that would perform
+ // checking of the template parameter lists that can't be performed
+ // until the outer context is instantiated.
+ PrevDecl = 0;
+ }
} else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
PrevDecl = 0;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f511eb15d2..f8f2217464 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -434,9 +434,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Trigger creation of the type for the instantiation.
SemaRef.Context.getTypeDeclType(RecordInst);
- // We're done with friends now.
- if (Inst->getFriendObjectKind())
+ // Finish handling of friends.
+ if (Inst->getFriendObjectKind()) {
return Inst;
+ }
Owner->addDecl(Inst);
diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp
index dc277f4657..84a8e899db 100644
--- a/test/SemaTemplate/friend-template.cpp
+++ b/test/SemaTemplate/friend-template.cpp
@@ -72,3 +72,22 @@ class Foo {
};
Foo<int> foo;
+
+template<typename T, T Value>
+struct X2a;
+
+template<typename T, int Size>
+struct X2b;
+
+template<typename T>
+class X3 {
+ template<typename U, U Value>
+ friend struct X2a;
+
+ template<typename U, T Value>
+ friend struct X2b;
+};
+
+X3<int> x3i; // okay
+
+X3<long> x3l; // FIXME: should cause an instantiation-time failure