summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-03-26 20:28:16 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-03-26 20:28:16 +0000
commit169f2190013d4474dfa04e2fd77e85a456269d41 (patch)
tree7b6dc96cc7f19024839d6664fc0ba94f6f24d2f4 /clang/test/SemaCXX/enum-unscoped-nonexistent.cpp
parenteec0abefb65275a286db156515e9fa6ac3398957 (diff)
downloadbcm5719-llvm-169f2190013d4474dfa04e2fd77e85a456269d41.tar.gz
bcm5719-llvm-169f2190013d4474dfa04e2fd77e85a456269d41.zip
Add a special-case diagnostic for one of the more obnoxious special cases of
unscoped enumeration members: an enumerator name which is visible in the out-of-class definition of a member of a templated class might not actually exist in the instantiation of that class, if the enumeration is also lexically defined outside the class definition and is explicitly specialized. Depending on the result of a CWG discussion, we may have a different resolution for a class of problems in this area, but this fixes the immediate issue of a crash-on-invalid / accepts-invalid (depending on +Asserts). Thanks to Johannes Schaub for digging into the standard wording to find how this case is currently specified to behave. llvm-svn: 153461
Diffstat (limited to 'clang/test/SemaCXX/enum-unscoped-nonexistent.cpp')
-rw-r--r--clang/test/SemaCXX/enum-unscoped-nonexistent.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp b/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp
new file mode 100644
index 00000000000..d49800caa61
--- /dev/null
+++ b/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+struct Base {
+ static const int a = 1;
+};
+template<typename T> struct S : Base {
+ enum E : int;
+ constexpr int f();
+ constexpr int g(); // expected-note {{declared here}}
+ void h();
+};
+template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}}
+template<> enum S<short>::E : int { b = 2 };
+template<> enum S<int>::E : int { a = 4 };
+template<typename T> enum S<T>::E : int { b = 8 };
+
+// The unqualified-id here names a member of the non-dependent base class Base
+// and not the injected enumerator name 'a' from the specialization.
+template<typename T> constexpr int S<T>::f() { return a; }
+static_assert(S<char>().f() == 1, "");
+static_assert(S<int>().f() == 1, "");
+
+// The unqualified-id here names a member of the current instantiation, which
+// bizarrely might not exist in some instantiations.
+template<typename T> constexpr int S<T>::g() { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}}
+static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} expected-note {{undefined}}
+static_assert(S<short>().g() == 2, "");
+static_assert(S<long>().g() == 8, "");
+
+// 'b' is type-dependent, so these assertions should not fire before 'h' is
+// instantiated.
+template<typename T> void S<T>::h() {
+ char c[S<T>::b];
+ static_assert(b != 8, "");
+ static_assert(sizeof(c) != 8, "");
+}
+void f() {
+ S<short>().h(); // ok, b == 2
+}
OpenPOWER on IntegriCloud