From 309e8e9897c9565b014cf778790ee3a13a1c3b24 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 23 Aug 2014 00:49:01 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216311 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplate.cpp | 10 +++++++--- test/Modules/Inputs/cxx-templates-common.h | 2 ++ test/Modules/Inputs/cxx-templates-textual.h | 2 ++ test/Modules/cxx-templates.cpp | 16 ++++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 test/Modules/Inputs/cxx-templates-textual.h diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 63581a44db..fb05718ff1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/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/test/Modules/Inputs/cxx-templates-common.h b/test/Modules/Inputs/cxx-templates-common.h index f7c083249f..f3c9022309 100644 --- a/test/Modules/Inputs/cxx-templates-common.h +++ b/test/Modules/Inputs/cxx-templates-common.h @@ -40,3 +40,5 @@ template struct WithExplicitSpecialization; typedef WithExplicitSpecialization WithExplicitSpecializationUse; template struct WithImplicitSpecialMembers { int n; }; + +#include "cxx-templates-textual.h" diff --git a/test/Modules/Inputs/cxx-templates-textual.h b/test/Modules/Inputs/cxx-templates-textual.h new file mode 100644 index 0000000000..8bffb8eddc --- /dev/null +++ b/test/Modules/Inputs/cxx-templates-textual.h @@ -0,0 +1,2 @@ +template struct MergeClassTemplateSpecializations_basic_string {}; +typedef MergeClassTemplateSpecializations_basic_string MergeClassTemplateSpecializations_string; diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index c173d67080..fedaa03ef4 100644 --- a/test/Modules/cxx-templates.cpp +++ b/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(1.0); f(); 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(1.0); @@ -108,11 +119,15 @@ void g() { int *r = PartiallyInstantiatePartialSpec::bar(); (void)&WithImplicitSpecialMembers::n; + + MergeClassTemplateSpecializations_string s; } static_assert(Outer::Inner::f() == 1, ""); static_assert(Outer::Inner::g() == 2, ""); +#ifndef EARLY_IMPORT +// FIXME: The textual inclusion above shouldn't cause this to fail! static_assert(MergeTemplateDefinitions::f() == 1, ""); static_assert(MergeTemplateDefinitions::g() == 2, ""); @@ -126,6 +141,7 @@ MergeSpecializations::partially_specialized_in_c spec_in_c_1; MergeSpecializations::explicitly_specialized_in_a spec_in_a_2; MergeSpecializations::explicitly_specialized_in_b spec_in_b_2; MergeSpecializations::explicitly_specialized_in_c spec_in_c_2; +#endif @import cxx_templates_common; -- 2.40.0