summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-08-23 00:49:01 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-08-23 00:49:01 +0000
commit234ff47366f6ae6acdd22b7b83ce91044561da60 (patch)
treef99714c5be870edc4f250c9ceec4bc54d6959bbe
parent7949a8b8ea3947043ef39929c5e080ca3d557fa3 (diff)
downloadbcm5719-llvm-234ff47366f6ae6acdd22b7b83ce91044561da60.tar.gz
bcm5719-llvm-234ff47366f6ae6acdd22b7b83ce91044561da60.zip
[modules] Put class template declarations into the scope in which they're
declared, rather than putting them into the template parameter scope. We previously had *no record* in the scope for class template declarations, once those declarations completed and their template parameter scopes were popped. This in turn caused us to be unable to merge class template declarations that were declared in the global scope (where we use scope lookup rather than DeclContext lookup for merging), when loading a module. llvm-svn: 216311
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp10
-rw-r--r--clang/test/Modules/Inputs/cxx-templates-common.h2
-rw-r--r--clang/test/Modules/Inputs/cxx-templates-textual.h2
-rw-r--r--clang/test/Modules/cxx-templates.cpp16
4 files changed, 27 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 63581a44dbe..fb05718ff1b 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1105,9 +1105,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
AddPushedVisibilityAttribute(NewClass);
- if (TUK != TUK_Friend)
- PushOnScopeChains(NewTemplate, S);
- else {
+ if (TUK != TUK_Friend) {
+ // Per C++ [basic.scope.temp]p2, skip the template parameter scopes.
+ Scope *Outer = S;
+ while ((Outer->getFlags() & Scope::TemplateParamScope) != 0)
+ Outer = Outer->getParent();
+ PushOnScopeChains(NewTemplate, Outer);
+ } else {
if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
NewTemplate->setAccess(PrevClassTemplate->getAccess());
NewClass->setAccess(PrevClassTemplate->getAccess());
diff --git a/clang/test/Modules/Inputs/cxx-templates-common.h b/clang/test/Modules/Inputs/cxx-templates-common.h
index f7c083249f8..f3c90223091 100644
--- a/clang/test/Modules/Inputs/cxx-templates-common.h
+++ b/clang/test/Modules/Inputs/cxx-templates-common.h
@@ -40,3 +40,5 @@ template<typename T> struct WithExplicitSpecialization;
typedef WithExplicitSpecialization<int> WithExplicitSpecializationUse;
template<typename T> struct WithImplicitSpecialMembers { int n; };
+
+#include "cxx-templates-textual.h"
diff --git a/clang/test/Modules/Inputs/cxx-templates-textual.h b/clang/test/Modules/Inputs/cxx-templates-textual.h
new file mode 100644
index 00000000000..8bffb8eddc2
--- /dev/null
+++ b/clang/test/Modules/Inputs/cxx-templates-textual.h
@@ -0,0 +1,2 @@
+template<typename T> struct MergeClassTemplateSpecializations_basic_string {};
+typedef MergeClassTemplateSpecializations_basic_string<char> MergeClassTemplateSpecializations_string;
diff --git a/clang/test/Modules/cxx-templates.cpp b/clang/test/Modules/cxx-templates.cpp
index c173d670802..fedaa03ef4f 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -3,6 +3,11 @@
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump-lookups -ast-dump-filter N | FileCheck %s --check-prefix=CHECK-NAMESPACE-N
// RUN: not %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -std=c++11 -ast-dump | FileCheck %s --check-prefix=CHECK-DUMP
// RUN: %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fno-modules-error-recovery -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11 -DEARLY_IMPORT
+
+#ifdef EARLY_IMPORT
+#include "cxx-templates-textual.h"
+#endif
@import cxx_templates_a;
@import cxx_templates_b;
@@ -22,8 +27,14 @@ void g() {
f<double>(1.0);
f<int>();
f(); // expected-error {{no matching function}}
+#ifdef EARLY_IMPORT
+ // FIXME: The textual inclusion above shouldn't affect this!
+ // expected-note@Inputs/cxx-templates-a.h:3 {{couldn't infer template argument}}
+ // expected-note@Inputs/cxx-templates-a.h:4 {{requires 1 argument}}
+#else
// expected-note@Inputs/cxx-templates-b.h:3 {{couldn't infer template argument}}
// expected-note@Inputs/cxx-templates-b.h:4 {{requires single argument}}
+#endif
N::f(0);
N::f<double>(1.0);
@@ -108,11 +119,15 @@ void g() {
int *r = PartiallyInstantiatePartialSpec<int*>::bar();
(void)&WithImplicitSpecialMembers<int>::n;
+
+ MergeClassTemplateSpecializations_string s;
}
static_assert(Outer<int>::Inner<int>::f() == 1, "");
static_assert(Outer<int>::Inner<int>::g() == 2, "");
+#ifndef EARLY_IMPORT
+// FIXME: The textual inclusion above shouldn't cause this to fail!
static_assert(MergeTemplateDefinitions<int>::f() == 1, "");
static_assert(MergeTemplateDefinitions<int>::g() == 2, "");
@@ -126,6 +141,7 @@ MergeSpecializations<int[]>::partially_specialized_in_c spec_in_c_1;
MergeSpecializations<char>::explicitly_specialized_in_a spec_in_a_2;
MergeSpecializations<double>::explicitly_specialized_in_b spec_in_b_2;
MergeSpecializations<bool>::explicitly_specialized_in_c spec_in_c_2;
+#endif
@import cxx_templates_common;
OpenPOWER on IntegriCloud