]> granicus.if.org Git - clang/commitdiff
[AST] Incorrectly qualified unscoped enumeration as template actual parameter.
authorPaul Robinson <paul.robinson@sony.com>
Thu, 21 Dec 2017 21:47:22 +0000 (21:47 +0000)
committerPaul Robinson <paul.robinson@sony.com>
Thu, 21 Dec 2017 21:47:22 +0000 (21:47 +0000)
An unscoped enumeration used as template argument, should not have any
qualified information about its enclosing scope, as its visibility is
global.

In the case of scoped enumerations, they must include information
about their enclosing scope.

Patch by Carlos Alberto Enciso!

Differential Revision: https://reviews.llvm.org/D39239

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321312 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Decl.cpp
test/Modules/odr.cpp
test/SemaCXX/return-noreturn.cpp
test/SemaTemplate/temp_arg_enum_printing.cpp
test/SemaTemplate/temp_arg_enum_printing_more.cpp [new file with mode: 0644]
unittests/AST/NamedDeclPrinterTest.cpp

index 2f51ec31a7bdc203cc600b0239280878ecbb7d8a..ee15a4d2b4f8cbcb164ea94c7956a3595c994ffd 100644 (file)
@@ -1548,7 +1548,10 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
       // enumerator is declared in the scope that immediately contains
       // the enum-specifier. Each scoped enumerator is declared in the
       // scope of the enumeration.
-      if (ED->isScoped() || ED->getIdentifier())
+      // For the case of unscoped enumerator, do not include in the qualified
+      // name any information about its enum enclosing scope, as is visibility
+      // is global.
+      if (ED->isScoped())
         OS << *ED;
       else
         continue;
index 9cdbb4f0806d45ba0ed8bb13038c0cf80aa1dbd2..c4700110af442ff25e2925d1a99f32022333157c 100644 (file)
@@ -18,6 +18,6 @@ int x = f() + g();
 // expected-note@a.h:3 {{declaration of 'f' does not match}}
 // expected-note@a.h:1 {{definition has no member 'm'}}
 
-// expected-error@b.h:5 {{'E::e2' from module 'b' is not present in definition of 'E' in module 'a'}}
+// expected-error@b.h:5 {{'e2' from module 'b' is not present in definition of 'E' in module 'a'}}
 // expected-error@b.h:3 {{'Y::f' from module 'b' is not present in definition of 'Y' in module 'a'}}
 // expected-error@b.h:2 {{'Y::m' from module 'b' is not present in definition of 'Y' in module 'a'}}
index cdd96e6a9ec442cd098274725b135d930271627f..cfeddffb664e8eb8753f7350c4b25e8e136f9e67 100644 (file)
@@ -143,7 +143,7 @@ template <PR9412_MatchType type> int PR9412_t() {
 } // expected-warning {{control reaches end of non-void function}}
 
 void PR9412_f() {
-    PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_MatchType::PR9412_Exact>' requested here}}
+    PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_Exact>' requested here}}
 }
 
 struct NoReturn {
index bdf277d308c3dcf50bcd8ad09723bb5d24874a09..dbb4db81f67ad62bacbe82031e49cf5a25c49142 100644 (file)
@@ -13,9 +13,9 @@ template <NamedEnum E>
 void foo();
   
 void test() {
-  // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val0>()
+  // CHECK: template<> void foo<NamedEnumNS::Val0>()
   NamedEnumNS::foo<Val0>();
-  // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val1>()
+  // CHECK: template<> void foo<NamedEnumNS::Val1>()
   NamedEnumNS::foo<(NamedEnum)1>();
   // CHECK: template<> void foo<2>()
   NamedEnumNS::foo<(NamedEnum)2>();
diff --git a/test/SemaTemplate/temp_arg_enum_printing_more.cpp b/test/SemaTemplate/temp_arg_enum_printing_more.cpp
new file mode 100644 (file)
index 0000000..a3a7158
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -ast-print %s -std=c++11 | FileCheck %s
+
+// Make sure that for template value arguments that are unscoped enumerators,
+// no qualified enum information is included in their name, as their visibility
+// is global. In the case of scoped enumerators, they must include information
+// about their enum enclosing scope.
+
+enum E1 { e1 };
+template<E1 v> struct tmpl_1 {};
+// CHECK: template<> struct tmpl_1<e1>
+tmpl_1<E1::e1> TMPL_1;                      // Name must be 'e1'.
+
+namespace nsp_1 { enum E2 { e2 }; }
+template<nsp_1::E2 v> struct tmpl_2 {};
+// CHECK: template<> struct tmpl_2<nsp_1::e2>
+tmpl_2<nsp_1::E2::e2> TMPL_2;               // Name must be 'nsp_1::e2'.
+
+enum class E3 { e3 };
+template<E3 v> struct tmpl_3 {};
+// CHECK: template<> struct tmpl_3<E3::e3>
+tmpl_3<E3::e3> TMPL_3;                      // Name must be 'E3::e3'.
+
+namespace nsp_2 { enum class E4 { e4 }; }
+template<nsp_2::E4 v> struct tmpl_4 {};
+// CHECK: template<> struct tmpl_4<nsp_2::E4::e4>
+tmpl_4<nsp_2::E4::e4> TMPL_4;               // Name must be 'nsp_2::E4::e4'.
index 92df4577ac77942bdb4fd5abfbdc496bdd9a5f0d..002bb28f374d464ac55638130adde76926ccfba3 100644 (file)
@@ -143,7 +143,7 @@ TEST(NamedDeclPrinter, TestNamedEnum) {
   ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
     "enum X { A };",
     "A",
-    "X::A"));
+    "A"));
 }
 
 TEST(NamedDeclPrinter, TestScopedNamedEnum) {
@@ -164,7 +164,7 @@ TEST(NamedDeclPrinter, TestClassWithUnscopedNamedEnum) {
   ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
     "class X { enum Y { A }; };",
     "A",
-    "X::Y::A"));
+    "X::A"));
 }
 
 TEST(NamedDeclPrinter, TestClassWithScopedNamedEnum) {