aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-20 07:12:26 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-20 07:12:26 +0000
commitc93e014cd43b08812370cfc8ef7bb7b92305f8fb (patch)
treeade50b5a591021ebf257579b3ea993351c4f6891
parentb2f245e77de13c6619923d6569a947e6dcdd0666 (diff)
Replace r155185 with a better fix, which also addresses PR12557. When looking
up an elaborated type specifier in a friend declaration, only look for type declarations, per [basic.lookup.elab]p2. If we know that the redeclaration lookup for a friend class template in a dependent context finds a non-template, don't delay the diagnostic to instantiation time. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155187 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplate.cpp6
-rw-r--r--test/SemaTemplate/class-template-decl.cpp10
-rw-r--r--test/SemaTemplate/friend-template.cpp24
3 files changed, 27 insertions, 13 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index a0b996beec..e16e7d67c6 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -867,7 +867,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Find any previous declaration with this name.
DeclContext *SemanticContext;
- LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName,
+ LookupResult Previous(*this, Name, NameLoc, LookupTagName,
ForRedeclaration);
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS, true);
@@ -938,7 +938,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
while (!OutermostContext->isFileContext())
OutermostContext = OutermostContext->getLookupParent();
- if (PrevClassTemplate &&
+ if (PrevDecl &&
(OutermostContext->Equals(PrevDecl->getDeclContext()) ||
OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
SemanticContext = PrevDecl->getDeclContext();
@@ -951,7 +951,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
}
- if (CurContext->isDependentContext()) {
+ if (CurContext->isDependentContext() && PrevClassTemplate) {
// 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
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
index 4d69ac4f71..bd2accee3c 100644
--- a/test/SemaTemplate/class-template-decl.cpp
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -94,13 +94,3 @@ namespace rdar9676205 {
};
};
}
-
-namespace Redecl {
- struct S {
- int packaged_task;
- template<typename> class future {
- template<typename> friend class packaged_task;
- };
- future<void> share;
- };
-}
diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp
index 9c95fa0151..2b05527cf1 100644
--- a/test/SemaTemplate/friend-template.cpp
+++ b/test/SemaTemplate/friend-template.cpp
@@ -243,3 +243,27 @@ namespace rdar11147355 {
A<double>::B<double> ab;
}
+
+namespace RedeclUnrelated {
+ struct S {
+ int packaged_task;
+ template<typename> class future {
+ template<typename> friend class packaged_task;
+ };
+ future<void> share;
+ };
+}
+
+namespace PR12557 {
+ template <typename>
+ struct Foo;
+
+ template <typename Foo_>
+ struct Bar {
+ typedef Foo_ Foo; // expected-note {{previous}}
+
+ template <typename> friend struct Foo; // expected-error {{redefinition of 'Foo' as different kind of symbol}}
+ };
+
+ Bar<int> b;
+}