r216311 - [modules] Put class template declarations into the scope in which they're

Richard Smith richard-llvm at metafoo.co.uk
Fri Aug 22 17:49:01 PDT 2014


Author: rsmith
Date: Fri Aug 22 19:49:01 2014
New Revision: 216311

URL: http://llvm.org/viewvc/llvm-project?rev=216311&view=rev
Log:
[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.

Added:
    cfe/trunk/test/Modules/Inputs/cxx-templates-textual.h
Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/Modules/Inputs/cxx-templates-common.h
    cfe/trunk/test/Modules/cxx-templates.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=216311&r1=216310&r2=216311&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Aug 22 19:49:01 2014
@@ -1105,9 +1105,13 @@ Sema::CheckClassTemplate(Scope *S, unsig
 
   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());

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-common.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-common.h?rev=216311&r1=216310&r2=216311&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-common.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-common.h Fri Aug 22 19:49:01 2014
@@ -40,3 +40,5 @@ template<typename T> struct WithExplicit
 typedef WithExplicitSpecialization<int> WithExplicitSpecializationUse;
 
 template<typename T> struct WithImplicitSpecialMembers { int n; };
+
+#include "cxx-templates-textual.h"

Added: cfe/trunk/test/Modules/Inputs/cxx-templates-textual.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-textual.h?rev=216311&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-textual.h (added)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-textual.h Fri Aug 22 19:49:01 2014
@@ -0,0 +1,2 @@
+template<typename T> struct MergeClassTemplateSpecializations_basic_string {};
+typedef MergeClassTemplateSpecializations_basic_string<char> MergeClassTemplateSpecializations_string;

Modified: cfe/trunk/test/Modules/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=216311&r1=216310&r2=216311&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)
+++ cfe/trunk/test/Modules/cxx-templates.cpp Fri Aug 22 19:49:01 2014
@@ -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 at Inputs/cxx-templates-a.h:3 {{couldn't infer template argument}}
+  // expected-note at Inputs/cxx-templates-a.h:4 {{requires 1 argument}}
+#else
   // expected-note at Inputs/cxx-templates-b.h:3 {{couldn't infer template argument}}
   // expected-note at 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_s
 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;
 





More information about the cfe-commits mailing list