summaryrefslogtreecommitdiffstats
path: root/test/SemaCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/Inputs/warn-unused-variables.h11
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp125
-rw-r--r--test/SemaCXX/access.cpp76
-rw-r--r--test/SemaCXX/alignof.cpp52
-rw-r--r--test/SemaCXX/ast-print.cpp11
-rw-r--r--test/SemaCXX/attr-noreturn.cpp83
-rw-r--r--test/SemaCXX/captured-statements.cpp166
-rw-r--r--test/SemaCXX/compound-literal.cpp66
-rw-r--r--test/SemaCXX/condition.cpp8
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp84
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp459
-rw-r--r--test/SemaCXX/constexpr-printing.cpp2
-rw-r--r--test/SemaCXX/constexpr-value-init.cpp2
-rw-r--r--test/SemaCXX/cxx11-ast-print.cpp2
-rw-r--r--test/SemaCXX/cxx11-crashes.cpp4
-rw-r--r--test/SemaCXX/cxx11-inheriting-ctors.cpp28
-rw-r--r--test/SemaCXX/cxx11-thread-local-print.cpp9
-rw-r--r--test/SemaCXX/cxx11-thread-local.cpp23
-rw-r--r--test/SemaCXX/cxx11-user-defined-literals-unused.cpp13
-rw-r--r--test/SemaCXX/cxx1y-array-runtime-bound.cpp68
-rw-r--r--test/SemaCXX/cxx1y-constexpr-not-const.cpp18
-rw-r--r--test/SemaCXX/cxx1y-deduced-return-type.cpp338
-rw-r--r--test/SemaCXX/cxx1y-initializer-aggregates.cpp63
-rw-r--r--test/SemaCXX/cxx98-compat-pedantic.cpp11
-rw-r--r--test/SemaCXX/enum-unscoped-nonexistent.cpp8
-rw-r--r--test/SemaCXX/for-range-unused.cpp4
-rw-r--r--test/SemaCXX/i-c-e-cxx.cpp2
-rw-r--r--test/SemaCXX/linkage-spec.cpp8
-rw-r--r--test/SemaCXX/linkage.cpp9
-rw-r--r--test/SemaCXX/linkage2.cpp12
-rw-r--r--test/SemaCXX/pascal-strings.cpp2
-rw-r--r--test/SemaCXX/trailing-return-0x.cpp9
-rw-r--r--test/SemaCXX/undefined-internal.cpp7
-rw-r--r--test/SemaCXX/uninitialized.cpp12
-rw-r--r--test/SemaCXX/warn-c++11-extensions.cpp2
-rw-r--r--test/SemaCXX/warn-overloaded-virtual.cpp18
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp90
-rw-r--r--test/SemaCXX/warn-unused-filescoped.cpp21
-rw-r--r--test/SemaCXX/warn-unused-variables-error.cpp10
-rw-r--r--test/SemaCXX/warn-unused-variables.cpp11
40 files changed, 1893 insertions, 54 deletions
diff --git a/test/SemaCXX/Inputs/warn-unused-variables.h b/test/SemaCXX/Inputs/warn-unused-variables.h
new file mode 100644
index 0000000..5fac459
--- /dev/null
+++ b/test/SemaCXX/Inputs/warn-unused-variables.h
@@ -0,0 +1,11 @@
+// Verify that we don't warn about variables of internal-linkage type in
+// headers, as the use may be in another TU.
+namespace PR15558 {
+namespace {
+class A {};
+}
+
+class B {
+ static A a;
+};
+}
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index 449e24b..ab3ff69 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -208,3 +208,128 @@ void ::f(); // expected-warning{{extra qualification on member 'f'}}
class C {
C::C(); // expected-warning{{extra qualification on member 'C'}}
};
+
+struct StructWithProperty {
+ __declspec(property(get=GetV)) int V1;
+ __declspec(property(put=SetV)) int V2;
+ __declspec(property(get=GetV, put=SetV_NotExist)) int V3;
+ __declspec(property(get=GetV_NotExist, put=SetV)) int V4;
+ __declspec(property(get=GetV, put=SetV)) int V5;
+
+ int GetV() { return 123; }
+ void SetV(int i) {}
+};
+void TestProperty() {
+ StructWithProperty sp;
+ int i = sp.V2; // expected-error{{no getter defined for property 'V2'}}
+ sp.V1 = 12; // expected-error{{no setter defined for property 'V1'}}
+ int j = sp.V4; // expected-error{{no member named 'GetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable getter for property 'V4'}}
+ sp.V3 = 14; // expected-error{{no member named 'SetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable setter for property 'V3'}}
+ int k = sp.V5;
+ sp.V5 = k++;
+}
+
+/* 4 tests for PseudoObject, begin */
+struct SP1
+{
+ bool operator()() { return true; }
+};
+struct SP2
+{
+ __declspec(property(get=GetV)) SP1 V;
+ SP1 GetV() { return SP1(); }
+};
+void TestSP2() {
+ SP2 sp2;
+ bool b = sp2.V();
+}
+
+struct SP3 {
+ template <class T>
+ void f(T t) {}
+};
+template <class T>
+struct SP4
+{
+ __declspec(property(get=GetV)) int V;
+ int GetV() { return 123; }
+ void f() { SP3 s2; s2.f(V); }
+};
+void TestSP4() {
+ SP4<int> s;
+ s.f();
+}
+
+template <class T>
+struct SP5
+{
+ __declspec(property(get=GetV)) T V;
+ int GetV() { return 123; }
+ void f() { int *p = new int[V]; }
+};
+
+template <class T>
+struct SP6
+{
+public:
+ __declspec(property(get=GetV)) T V;
+ T GetV() { return 123; }
+ void f() { int t = V; }
+};
+void TestSP6() {
+ SP6<int> c;
+ c.f();
+}
+/* 4 tests for PseudoObject, end */
+
+// Property access: explicit, implicit, with Qualifier
+struct SP7 {
+ __declspec(property(get=GetV, put=SetV)) int V;
+ int GetV() { return 123; }
+ void SetV(int v) {}
+
+ void ImplicitAccess() { int i = V; V = i; }
+ void ExplicitAccess() { int i = this->V; this->V = i; }
+};
+struct SP8: public SP7 {
+ void AccessWithQualifier() { int i = SP7::V; SP7::V = i; }
+};
+
+// Property usage
+template <class T>
+struct SP9 {
+ __declspec(property(get=GetV, put=SetV)) T V;
+ T GetV() { return 0; }
+ void SetV(T v) {}
+ void f() { V = this->V; V < this->V; }
+ void g() { V++; }
+ void h() { V*=2; }
+};
+struct SP10 {
+ SP10(int v) {}
+ bool operator<(const SP10& v) { return true; }
+ SP10 operator*(int v) { return *this; }
+ SP10 operator+(int v) { return *this; }
+ SP10& operator=(const SP10& v) { return *this; }
+};
+void TestSP9() {
+ SP9<int> c;
+ int i = c.V; // Decl initializer
+ i = c.V; // Binary op operand
+ c.SetV(c.V); // CallExpr arg
+ int *p = new int[c.V + 1]; // Array size
+ p[c.V] = 1; // Array index
+
+ c.V = 123; // Setter
+
+ c.V++; // Unary op operand
+ c.V *= 2; // Unary op operand
+
+ SP9<int*> c2;
+ c2.V[0] = 123; // Array
+
+ SP9<SP10> c3;
+ c3.f(); // Overloaded binary op operand
+ c3.g(); // Overloaded incdec op operand
+ c3.h(); // Overloaded unary op operand
+}
diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp
index 18ad301..50f2eff 100644
--- a/test/SemaCXX/access.cpp
+++ b/test/SemaCXX/access.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
class C {
struct S; // expected-note {{previously declared 'private' here}}
@@ -32,3 +32,77 @@ namespace test1 {
class X {};
};
}
+
+// PR15209
+namespace PR15209 {
+ namespace alias_templates {
+ template<typename T1, typename T2> struct U { };
+ template<typename T1> using W = U<T1, float>;
+
+ class A {
+ typedef int I;
+ static constexpr I x = 0; // expected-note {{implicitly declared private here}}
+ static constexpr I y = 42; // expected-note {{implicitly declared private here}}
+ friend W<int>;
+ };
+
+ template<typename T1>
+ struct U<T1, float> {
+ int v_;
+ // the following will trigger for U<float, float> instantiation, via W<float>
+ U() : v_(A::x) { } // expected-error {{'x' is a private member of 'PR15209::alias_templates::A'}}
+ };
+
+ template<typename T1>
+ struct U<T1, int> {
+ int v_;
+ U() : v_(A::y) { } // expected-error {{'y' is a private member of 'PR15209::alias_templates::A'}}
+ };
+
+ template struct U<int, int>; // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<int, int>::U' requested here}}
+
+ void f()
+ {
+ W<int>();
+ // we should issue diagnostics for the following
+ W<float>(); // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<float, float>::U' requested here}}
+ }
+ }
+
+ namespace templates {
+ class A {
+ typedef int I; // expected-note {{implicitly declared private here}}
+ static constexpr I x = 0; // expected-note {{implicitly declared private here}}
+
+ template<int> friend struct B;
+ template<int> struct C;
+ template<template<int> class T> friend struct TT;
+ template<typename T> friend void funct(T);
+ };
+ template<A::I> struct B { };
+
+ template<A::I> struct A::C { };
+
+ template<template<A::I> class T> struct TT {
+ T<A::x> t;
+ };
+
+ template struct TT<B>;
+ template<A::I> struct D { }; // expected-error {{'I' is a private member of 'PR15209::templates::A'}}
+ template struct TT<D>;
+
+ // function template case
+ template<typename T>
+ void funct(T)
+ {
+ (void)A::x;
+ }
+
+ template void funct<int>(int);
+
+ void f()
+ {
+ (void)A::x; // expected-error {{'x' is a private member of 'PR15209::templates::A'}}
+ }
+ }
+}
diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp
new file mode 100644
index 0000000..a9de1ad
--- /dev/null
+++ b/test/SemaCXX/alignof.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+// rdar://13784901
+
+struct S0 {
+ int x;
+ static const int test0 = __alignof__(x); // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
+ static const int test1 = __alignof__(S0::x); // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
+ auto test2() -> char(&)[__alignof__(x)]; // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
+};
+
+struct S1; // expected-note 5 {{forward declaration}}
+extern S1 s1;
+const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+
+struct S2 {
+ S2();
+ S1 &s;
+ int x;
+
+ int test4 = __alignof__(x); // ok
+ int test5 = __alignof__(s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+};
+
+const int test6 = __alignof__(S2::x);
+const int test7 = __alignof__(S2::s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+
+// Arguably, these should fail like the S1 cases do: the alignment of
+// 's2.x' should depend on the alignment of both x-within-S2 and
+// s2-within-S3 and thus require 'S3' to be complete. If we start
+// doing the appropriate recursive walk to do that, we should make
+// sure that these cases don't explode.
+struct S3 {
+ S2 s2;
+
+ static const int test8 = __alignof__(s2.x);
+ static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+ auto test10() -> char(&)[__alignof__(s2.x)];
+ static const int test11 = __alignof__(S3::s2.x);
+ static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
+ auto test13() -> char(&)[__alignof__(s2.x)];
+};
+
+// Same reasoning as S3.
+struct S4 {
+ union {
+ int x;
+ };
+ static const int test0 = __alignof__(x);
+ static const int test1 = __alignof__(S0::x);
+ auto test2() -> char(&)[__alignof__(x)];
+};
diff --git a/test/SemaCXX/ast-print.cpp b/test/SemaCXX/ast-print.cpp
index 5de8c4b..921f7d8 100644
--- a/test/SemaCXX/ast-print.cpp
+++ b/test/SemaCXX/ast-print.cpp
@@ -137,3 +137,14 @@ void test12() {
ConstrWithCleanupsClass cwcExplicitArg(VirualDestrClass(56));
}
+// CHECK: void test13() {
+// CHECK: _Atomic(int) i;
+// CHECK: __c11_atomic_init(&i, 0);
+// CHECK: __c11_atomic_load(&i, 0);
+// CHECK: }
+void test13() {
+ _Atomic(int) i;
+ __c11_atomic_init(&i, 0);
+ __c11_atomic_load(&i, 0);
+}
+
diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp
index f3d548b..41214c4 100644
--- a/test/SemaCXX/attr-noreturn.cpp
+++ b/test/SemaCXX/attr-noreturn.cpp
@@ -80,3 +80,86 @@ namespace PR12948 {
template<typename> void wibble() __attribute__((__noreturn__));
template<typename> voidfn wibble;
}
+
+// PR15291
+// Overload resolution per over.over should allow implicit noreturn adjustment.
+namespace PR15291 {
+ __attribute__((noreturn)) void foo(int) {}
+ __attribute__((noreturn)) void foo(double) {}
+
+ template <typename T>
+ __attribute__((noreturn)) void bar(T) {}
+
+ void baz(int) {}
+ void baz(double) {}
+
+ template <typename T>
+ void qux(T) {}
+
+ // expected-note@+5 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+4 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+3 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+2 {{candidate function [with T = void (*)(int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ // expected-note@+1 {{candidate function [with T = void (int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ template <typename T> void accept_T(T) {}
+
+ // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}}
+ void accept_fptr(void (*f)(int)) {
+ f(42);
+ }
+
+ // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}}
+ void accept_noreturn_fptr(void __attribute__((noreturn)) (*f)(int)) {
+ f(42);
+ }
+
+ typedef void (*fptr_t)(int);
+ typedef void __attribute__((noreturn)) (*fptr_noreturn_t)(int);
+
+ // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'fptr_t' (aka 'void (*)(int)') for 1st argument}}
+ void accept_fptr_t(fptr_t f) {
+ f(42);
+ }
+
+ // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}}
+ // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}}
+ void accept_fptr_noreturn_t(fptr_noreturn_t f) {
+ f(42);
+ }
+
+ // Stripping noreturn should work if everything else is correct.
+ void strip_noreturn() {
+ accept_fptr(foo);
+ accept_fptr(bar<int>);
+ accept_fptr(bar<double>); // expected-error {{no matching function for call to 'accept_fptr'}}
+
+ accept_fptr_t(foo);
+ accept_fptr_t(bar<int>);
+ accept_fptr_t(bar<double>); // expected-error {{no matching function for call to 'accept_fptr_t'}}
+
+ accept_T<void __attribute__((noreturn)) (*)(int)>(foo);
+ accept_T<void __attribute__((noreturn)) (*)(int)>(bar<int>);
+ accept_T<void __attribute__((noreturn)) (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}}
+
+ accept_T<void (*)(int)>(foo);
+ accept_T<void (*)(int)>(bar<int>);
+ accept_T<void (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}}
+
+ accept_T<void (int)>(foo);
+ accept_T<void (int)>(bar<int>);
+ accept_T<void (int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}}
+ }
+
+ // Introducing noreturn should not work.
+ void introduce_noreturn() {
+ accept_noreturn_fptr(baz); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}}
+ accept_noreturn_fptr(qux<int>); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}}
+
+ accept_fptr_noreturn_t(baz); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}}
+ accept_fptr_noreturn_t(qux<int>); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}}
+
+ accept_T<void __attribute__((noreturn)) (*)(int)>(baz); // expected-error {{no matching function for call to 'accept_T'}}
+ accept_T<void __attribute__((noreturn)) (*)(int)>(qux<int>); // expected-error {{no matching function for call to 'accept_T'}}
+ }
+}
diff --git a/test/SemaCXX/captured-statements.cpp b/test/SemaCXX/captured-statements.cpp
new file mode 100644
index 0000000..dbb18a7
--- /dev/null
+++ b/test/SemaCXX/captured-statements.cpp
@@ -0,0 +1,166 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -fblocks
+
+void test_nest_lambda() {
+ int x;
+ int y;
+ [&,y]() {
+ int z;
+ #pragma clang __debug captured
+ {
+ x = y; // OK
+ y = z; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}}
+ z = y; // OK
+ }
+ }();
+
+ int a;
+ #pragma clang __debug captured
+ {
+ int b;
+ int c;
+ [&,c]() {
+ a = b; // OK
+ b = c; // OK
+ c = a; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}}
+ }();
+ }
+}
+
+class test_obj_capture {
+ int a;
+ void b();
+ static void test() {
+ test_obj_capture c;
+ #pragma clang __debug captured
+ { (void)c.a; } // OK
+ #pragma clang __debug captured
+ { c.b(); } // OK
+ }
+};
+
+class test_this_capture {
+ int a;
+ void b();
+ void test() {
+ #pragma clang __debug captured
+ { (void)this; } // OK
+ #pragma clang __debug captured
+ { (void)a; } // OK
+ #pragma clang __debug captured
+ { b(); } // OK
+ }
+};
+
+template <typename T>
+void template_capture_var() {
+ T x; // expected-error{{declaration of reference variable 'x' requires an initializer}}
+ #pragma clang _debug captured
+ {
+ (void)x;
+ }
+}
+
+template <typename T>
+class Val {
+ T v;
+public:
+ void set(const T &v0) {
+ #pragma clang __debug captured
+ {
+ v = v0;
+ }
+ }
+};
+
+void test_capture_var() {
+ template_capture_var<int>(); // OK
+ template_capture_var<int&>(); // expected-note{{in instantiation of function template specialization 'template_capture_var<int &>' requested here}}
+
+ Val<float> Obj;
+ Obj.set(0.0f); // OK
+}
+
+template <typename S, typename T>
+S template_capture_var(S x, T y) {
+ #pragma clang _debug captured
+ {
+ x++;
+ y++; // expected-error{{read-only variable is not assignable}}
+ }
+
+ return x;
+}
+
+// Check if can recover from a template error.
+void test_capture_var_error() {
+ template_capture_var<int, int>(0, 1); // OK
+ template_capture_var<int, const int>(0, 1); // expected-note{{in instantiation of function template specialization 'template_capture_var<int, const int>' requested here}}
+ template_capture_var<int, int>(0, 1); // OK
+}
+
+template <typename T>
+void template_capture_in_lambda() {
+ T x, y;
+ [=, &y]() {
+ #pragma clang __debug captured
+ {
+ y += x;
+ }
+ }();
+}
+
+void test_lambda() {
+ template_capture_in_lambda<int>(); // OK
+}
+
+struct Foo {
+ void foo() { }
+ static void bar() { }
+};
+
+template <typename T>
+void template_capture_func(T &t) {
+ #pragma clang __debug captured
+ {
+ t.foo();
+ }
+
+ #pragma clang __debug captured
+ {
+ T::bar();
+ }
+}
+
+void test_template_capture_func() {
+ Foo Obj;
+ template_capture_func(Obj);
+}
+
+template <typename T>
+T captured_sum(const T &a, const T &b) {
+ T result;
+
+ #pragma clang __debug captured
+ {
+ result = a + b;
+ }
+
+ return result;
+}
+
+template <typename T, typename... Args>
+T captured_sum(const T &a, const Args&... args) {
+ T result;
+
+ #pragma clang __debug captured
+ {
+ result = a + captured_sum(args...);
+ }
+
+ return result;
+}
+
+void test_capture_variadic() {
+ (void)captured_sum(1, 2, 3); // OK
+ (void)captured_sum(1, 2, 3, 4, 5); // OK
+}
diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp
index fe0e45d..595747e 100644
--- a/test/SemaCXX/compound-literal.cpp
+++ b/test/SemaCXX/compound-literal.cpp
@@ -1,4 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03
+// RUN: FileCheck --input-file=%t-03 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11
+// RUN: FileCheck --input-file=%t-11 %s
+// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11
// http://llvm.org/PR7905
namespace PR7905 {
@@ -12,3 +16,63 @@ void foo2() {
(void)(M<short> []) {{3}};
}
}
+
+// Check compound literals mixed with C++11 list-initialization.
+namespace brace_initializers {
+ struct POD {
+ int x, y;
+ };
+ struct HasCtor {
+ HasCtor(int x, int y);
+ };
+ struct HasDtor {
+ int x, y;
+ ~HasDtor();
+ };
+ struct HasCtorDtor {
+ HasCtorDtor(int x, int y);
+ ~HasCtorDtor();
+ };
+
+ void test() {
+ (void)(POD){1, 2};
+ // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::POD'
+ // CHECK: CompoundLiteralExpr {{.*}} 'struct brace_initializers::POD'
+ // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::POD'
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+ (void)(HasDtor){1, 2};
+ // CHECK: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasDtor'
+ // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasDtor'
+ // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::HasDtor'
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+#if __cplusplus >= 201103L
+ (void)(HasCtor){1, 2};
+ // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtor'
+ // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtor'
+ // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtor'
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+ (void)(HasCtorDtor){1, 2};
+ // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
+#endif
+ }
+
+ struct PrivateDtor {
+ int x, y;
+ private:
+ ~PrivateDtor(); // expected-note {{declared private here}}
+ };
+
+ void testPrivateDtor() {
+ (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}}
+ }
+}
diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp
index d805881..73f3dce 100644
--- a/test/SemaCXX/condition.cpp
+++ b/test/SemaCXX/condition.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
void test() {
int x;
@@ -6,7 +6,7 @@ void test() {
if (int x=0) ++x;
typedef int arr[10];
- while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}}
+ while (arr x={0}) ; // expected-error {{an array type is not allowed here}}
while (int f()=0) ; // expected-error {{a function type is not allowed here}}
struct S {} s;
@@ -19,9 +19,7 @@ void test() {
while (struct NewS *x=0) ;
while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}}
while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}}
- switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} \
- // expected-warning{{enumeration value 'E' not handled in switch}} expected-warning {{switch statement has empty body}} \
- // expected-note{{put the semicolon on a separate line}}
+ switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}}
if (int x=0) { // expected-note 2 {{previous definition is here}}
int x; // expected-error {{redefinition of 'x'}}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 30aa7d7..09a9cb5 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -21,7 +21,7 @@ template<typename T, size_t N> constexpr T *begin(T (&xs)[N]) { return xs; }
template<typename T, size_t N> constexpr T *end(T (&xs)[N]) { return xs + N; }
struct MemberZero {
- constexpr int zero() { return 0; }
+ constexpr int zero() const { return 0; }
};
namespace DerivedToVBaseCast {
@@ -304,16 +304,16 @@ struct Str {
expected-note {{reinterpret_cast is not allowed in a constant expression}}
int c : (S*)(long)(sptr) == (S*)(long)(sptr); // \
expected-warning {{not an integral constant expression}} \
- expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
+ expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
int d : (S*)(42) == (S*)(42); // \
expected-warning {{not an integral constant expression}} \
- expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
+ expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
int e : (Str*)(sptr) == (Str*)(sptr); // \
expected-warning {{not an integral constant expression}} \
- expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
+ expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
int f : &(U&)(*sptr) == &(U&)(*sptr); // \
expected-warning {{not an integral constant expression}} \
- expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
+ expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
int g : (S*)(void*)(sptr) == sptr; // \
expected-warning {{not an integral constant expression}} \
expected-note {{cast from 'void *' is not allowed in a constant expression}}
@@ -362,7 +362,7 @@ constexpr char c0 = "nought index"[0];
constexpr char c1 = "nice index"[10];
constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}} expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}} expected-note {{cannot refer to element -1 of array of 15 elements}}
-constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast which performs the conversions of a reinterpret_cast}}
+constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast that performs the conversions of a reinterpret_cast}}
constexpr const char *p = "test" + 2;
static_assert(*p == 's', "");
@@ -414,6 +414,19 @@ struct V {
};
static_assert(V().c[1] == "i"[0], "");
+namespace Parens {
+ constexpr unsigned char a[] = ("foo"), b[] = {"foo"}, c[] = {("foo")},
+ d[4] = ("foo"), e[5] = {"foo"}, f[6] = {("foo")};
+ static_assert(a[0] == 'f', "");
+ static_assert(b[1] == 'o', "");
+ static_assert(c[2] == 'o', "");
+ static_assert(d[0] == 'f', "");
+ static_assert(e[1] == 'o', "");
+ static_assert(f[2] == 'o', "");
+ static_assert(f[5] == 0, "");
+ static_assert(f[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}}
+}
+
}
namespace Array {
@@ -486,7 +499,7 @@ static_assert(CountZero(arr, arr + 40) == 36, "");
struct ArrayElem {
constexpr ArrayElem() : n(0) {}
int n;
- constexpr int f() { return n; }
+ constexpr int f() const { return n; }
};
struct ArrayRVal {
constexpr ArrayRVal() {}
@@ -731,14 +744,14 @@ namespace ConversionOperators {
struct T {
constexpr T(int n) : k(5*n - 3) {}
- constexpr operator int() { return k; }
+ constexpr operator int() const { return k; }
int k;
};
struct S {
constexpr S(int n) : k(2*n + 1) {}
- constexpr operator int() { return k; }
- constexpr operator T() { return T(k); }
+ constexpr operator int() const { return k; }
+ constexpr operator T() const { return T(k); }
int k;
};
@@ -750,7 +763,7 @@ static_assert(check(S(5), 11), "");
namespace PR14171 {
struct X {
- constexpr (operator int)() { return 0; }
+ constexpr (operator int)() const { return 0; }
};
static_assert(X() == 0, "");
@@ -764,13 +777,13 @@ namespace Temporaries {
struct S {
constexpr S() {}
- constexpr int f();
+ constexpr int f() const;
};
struct T : S {
constexpr T(int n) : S(), n(n) {}
int n;
};
-constexpr int S::f() {
+constexpr int S::f() const {
// 'this' must be the postfix-expression in a class member access expression,
// so we can't just use
// return static_cast<T*>(this)->n;
@@ -825,7 +838,7 @@ namespace MemberPointer {
struct A {
constexpr A(int n) : n(n) {}
int n;
- constexpr int f() { return n + 3; }
+ constexpr int f() const { return n + 3; }
};
constexpr A a(7);
static_assert(A(5).*&A::n == 5, "");
@@ -836,7 +849,7 @@ namespace MemberPointer {
struct B : A {
constexpr B(int n, int m) : A(n), m(m) {}
int m;
- constexpr int g() { return n + m + 1; }
+ constexpr int g() const { return n + m + 1; }
};
constexpr B b(9, 13);
static_assert(B(4, 11).*&A::n == 4, "");
@@ -857,7 +870,7 @@ namespace MemberPointer {
m(m), n(n), pf(pf), pn(pn) {}
constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {}
- constexpr int f() { return this->*pn; }
+ constexpr int f() const { return this->*pn; }
virtual int g() const;
int m, n;
@@ -938,7 +951,7 @@ namespace ArrayBaseDerived {
};
struct Derived : Base {
constexpr Derived() {}
- constexpr const int *f() { return &n; }
+ constexpr const int *f() const { return &n; }
};
constexpr Derived a[10];
@@ -1038,7 +1051,7 @@ static_assert(makeComplexWrap(1,0) != complex(0, 1), "");
}
namespace PR11595 {
- struct A { constexpr bool operator==(int x) { return true; } };
+ struct A { constexpr bool operator==(int x) const { return true; } };
struct B { B(); A& x; };
static_assert(B().x == 3, ""); // expected-error {{constant expression}} expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}}
@@ -1312,6 +1325,13 @@ namespace InvalidClasses {
}
}
+namespace NamespaceAlias {
+ constexpr int f() {
+ namespace NS = NamespaceAlias; // expected-warning {{use of this statement in a constexpr function is a C++1y extension}}
+ return &NS::f != nullptr;
+ }
+}
+
// Constructors can be implicitly constexpr, even for a non-literal type.
namespace ImplicitConstexpr {
struct Q { Q() = default; Q(const Q&) = default; Q(Q&&) = default; ~Q(); }; // expected-note 3{{here}}
@@ -1455,3 +1475,31 @@ namespace PR14203 {
// constructor here.
int n = sizeof(short{duration(duration())});
}
+
+namespace ArrayEltInit {
+ struct A {
+ constexpr A() : p(&p) {}
+ void *p;
+ };
+ constexpr A a[10];
+ static_assert(a[0].p == &a[0].p, "");
+ static_assert(a[9].p == &a[9].p, "");
+ static_assert(a[0].p != &a[9].p, "");
+ static_assert(a[9].p != &a[0].p, "");
+
+ constexpr A b[10] = {};
+ static_assert(b[0].p == &b[0].p, "");
+ static_assert(b[9].p == &b[9].p, "");
+ static_assert(b[0].p != &b[9].p, "");
+ static_assert(b[9].p != &b[0].p, "");
+}
+
+namespace PR15884 {
+ struct S {};
+ constexpr S f() { return {}; }
+ constexpr S *p = &f();
+ // expected-error@-1 {{taking the address of a temporary}}
+ // expected-error@-2 {{constexpr variable 'p' must be initialized by a constant expression}}
+ // expected-note@-3 {{pointer to temporary is not a constant expression}}
+ // expected-note@-4 {{temporary created here}}
+}
diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp
new file mode 100644
index 0000000..60ec820
--- /dev/null
+++ b/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -0,0 +1,459 @@
+// RUN: %clang_cc1 -std=c++1y -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu
+
+struct S {
+ // dummy ctor to make this a literal type
+ constexpr S(int);
+
+ S();
+
+ int arr[10];
+
+ constexpr int &get(int n) { return arr[n]; }
+ constexpr const int &get(int n) const { return arr[n]; }
+};
+
+S s = S();
+const S &sr = s;
+static_assert(&s.get(4) - &sr.get(2) == 2, "");
+
+// Compound-statements can be used in constexpr functions.
+constexpr int e() {{{{}} return 5; }}
+static_assert(e() == 5, "");
+
+// Types can be defined in constexpr functions.
+constexpr int f() {
+ enum E { e1, e2, e3 };
+
+ struct S {
+ constexpr S(E e) : e(e) {}
+ constexpr int get() { return e; }
+ E e;
+ };
+
+ return S(e2).get();
+}
+static_assert(f() == 1, "");
+
+// Variables can be declared in constexpr functions.
+constexpr int g(int k) {
+ const int n = 9;
+ int k2 = k * k;
+ int k3 = k2 * k;
+ return 3 * k3 + 5 * k2 + n * k - 20;
+}
+static_assert(g(2) == 42, "");
+constexpr int h(int n) {
+ static const int m = n; // expected-error {{static variable not permitted in a constexpr function}}
+ return m;
+}
+constexpr int i(int n) {
+ thread_local const int m = n; // expected-error {{thread_local variable not permitted in a constexpr function}}
+ return m;
+}
+
+// if-statements can be used in constexpr functions.
+constexpr int j(int k) {
+ if (k == 5)
+ return 1;
+ if (k == 1)
+ return 5;
+ else {
+ if (int n = 2 * k - 4) {
+ return n + 1;
+ return 2;
+ }
+ }
+} // expected-note 2{{control reached end of constexpr function}}
+static_assert(j(0) == -3, "");
+static_assert(j(1) == 5, "");
+static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}}
+static_assert(j(3) == 3, "");
+static_assert(j(4) == 5, "");
+static_assert(j(5) == 1, "");
+
+// There can be 0 return-statements.
+constexpr void k() {
+}
+
+// If the return type is not 'void', no return statements => never a constant
+// expression, so still diagnose that case.
+[[noreturn]] constexpr int fn() { // expected-error {{no return statement in constexpr function}}
+ fn();
+}
+
+// We evaluate the body of a constexpr constructor, to check for side-effects.
+struct U {
+ constexpr U(int n) {
+ if (j(n)) {} // expected-note {{in call to 'j(2)'}}
+ }
+};
+constexpr U u1{1};
+constexpr U u2{2}; // expected-error {{constant expression}} expected-note {{in call to 'U(2)'}}
+
+// We allow expression-statements.
+constexpr int l(bool b) {
+ if (b)
+ throw "invalid value for b!"; // expected-note {{subexpression not valid}}
+ return 5;
+}
+static_assert(l(false) == 5, "");
+static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}}
+
+// Potential constant expression checking is still applied where possible.
+constexpr int htonl(int x) { // expected-error {{never produces a constant expression}}
+ typedef unsigned char uchar;
+ uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
+ return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
+}
+
+constexpr int maybe_htonl(bool isBigEndian, int x) {
+ if (isBigEndian)
+ return x;
+
+ typedef unsigned char uchar;
+ uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
+ return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
+}
+
+constexpr int swapped = maybe_htonl(false, 123); // expected-error {{constant expression}} expected-note {{in call}}
+
+namespace NS {
+ constexpr int n = 0;
+}
+constexpr int namespace_alias() {
+ namespace N = NS;
+ return N::n;
+}
+
+namespace assign {
+ constexpr int a = 0;
+ const int b = 0;
+ int c = 0; // expected-note 2{{here}}
+
+ constexpr void set(const int &a, int b) {
+ const_cast<int&>(a) = b; // expected-note 2{{constant expression cannot modify an object that is visible outside that expression}}
+ }
+ constexpr int wrap(int a, int b) {
+ set(a, b);
+ return a;
+ }
+
+ static_assert((set(a, 1), a) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(a, 1)'}}
+ static_assert((set(b, 1), b) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(b, 1)'}}
+ static_assert((set(c, 1), c) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}}
+
+ static_assert(wrap(a, 1) == 1, "");
+ static_assert(wrap(b, 1) == 1, "");
+ static_assert(wrap(c, 1) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}}
+}
+
+namespace string_assign {
+ template<typename T>
+ constexpr void swap(T &a, T &b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+ template<typename Iterator>
+ constexpr void reverse(Iterator begin, Iterator end) {
+ while (begin != end && begin != --end)
+ swap(*begin++, *end);
+ }
+ template<typename Iterator1, typename Iterator2>
+ constexpr bool equal(Iterator1 a, Iterator1 ae, Iterator2 b, Iterator2 be) {
+ while (a != ae && b != be)
+ if (*a++ != *b++)
+ return false;
+ return a == ae && b == be;
+ }
+ constexpr bool test1(int n) {
+ char stuff[100] = "foobarfoo";
+ const char stuff2[100] = "oofraboof";
+ reverse(stuff, stuff + n); // expected-note {{cannot refer to element 101 of array of 100 elements}}
+ return equal(stuff, stuff + n, stuff2, stuff2 + n);
+ }
+ static_assert(!test1(1), "");
+ static_assert(test1(3), "");
+ static_assert(!test1(6), "");
+ static_assert(test1(9), "");
+ static_assert(!test1(100), "");
+ static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}}
+
+ // FIXME: We should be able to reject this before it's called
+ constexpr void f() {
+ char foo[10] = { "z" }; // expected-note {{here}}
+ foo[10] = 'x'; // expected-warning {{past the end}} expected-note {{assignment to dereferenced one-past-the-end pointer}}
+ }
+ constexpr int k = (f(), 0); // expected-error {{constant expression}} expected-note {{in call}}
+}
+
+namespace array_resize {
+ constexpr int do_stuff(int k1, int k2) {
+ int arr[1234] = { 1, 2, 3, 4 };
+ arr[k1] = 5; // expected-note {{past-the-end}} expected-note {{cannot refer to element 1235}} expected-note {{cannot refer to element -1}}
+ return arr[k2];
+ }
+ static_assert(do_stuff(1, 2) == 3, "");
+ static_assert(do_stuff(0, 0) == 5, "");
+ static_assert(do_stuff(1233, 1233) == 5, "");
+ static_assert(do_stuff(1233, 0) == 1, "");
+ static_assert(do_stuff(1234, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
+ static_assert(do_stuff(1235, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
+ static_assert(do_stuff(-1, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
+}
+
+namespace potential_const_expr {
+ constexpr void set(int &n) { n = 1; }
+ constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error
+ constexpr int div_zero_2() { // expected-error {{never produces a constant expression}}
+ int z = 0;
+ return 100 / (set(z), 0); // expected-note {{division by zero}}
+ }
+ int n; // expected-note {{declared here}}
+ constexpr int ref() { // expected-error {{never produces a constant expression}}
+ int &r = n;
+ return r; // expected-note {{read of non-const variable 'n'}}
+ }
+}
+
+namespace subobject {
+ union A { constexpr A() : y(5) {} int x, y; };
+ struct B { A a; };
+ struct C : B {};
+ union D { constexpr D() : c() {} constexpr D(int n) : n(n) {} C c; int n; };
+ constexpr void f(D &d) {
+ d.c.a.y = 3;
+ // expected-note@-1 {{cannot modify an object that is visible outside}}
+ // expected-note@-2 {{assignment to member 'c' of union with active member 'n'}}
+ }
+ constexpr bool check(D &d) { return d.c.a.y == 3; }
+
+ constexpr bool g() { D d; f(d); return d.c.a.y == 3; }
+ static_assert(g(), "");
+
+ D d;
+ constexpr bool h() { f(d); return check(d); } // expected-note {{in call}}
+ static_assert(h(), ""); // expected-error {{constant expression}} expected-note {{in call}}
+
+ constexpr bool i() { D d(0); f(d); return check(d); } // expected-note {{in call}}
+ static_assert(i(), ""); // expected-error {{constant expression}} expected-note {{in call}}
+
+ constexpr bool j() { D d; d.c.a.x = 3; return check(d); } // expected-note {{assignment to member 'x' of union with active member 'y'}}
+ static_assert(j(), ""); // expected-error {{constant expression}} expected-note {{in call}}
+}
+
+namespace lifetime {
+ constexpr int &&id(int &&n) { return static_cast<int&&>(n); }
+ constexpr int &&dead() { return id(0); } // expected-note {{temporary created here}}
+ constexpr int bad() { int &&n = dead(); n = 1; return n; } // expected-note {{assignment to temporary whose lifetime has ended}}
+ static_assert(bad(), ""); // expected-error {{constant expression}} expected-note {{in call}}
+}
+
+namespace const_modify {
+ constexpr int modify(int &n) { return n = 1; } // expected-note {{modification of object of const-qualified type 'const int'}}
+ constexpr int test1() { int k = 0; return modify(k); }
+ constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note {{in call}}
+ static_assert(test1() == 1, "");
+ static_assert(test2() == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
+}
+
+namespace null {
+ constexpr int test(int *p) {
+ return *p = 123; // expected-note {{assignment to dereferenced null pointer}}
+ }
+ static_assert(test(0), ""); // expected-error {{constant expression}} expected-note {{in call}}
+}
+
+namespace incdec {
+ template<typename T> constexpr T &ref(T &&r) { return r; }
+ template<typename T> constexpr T postinc(T &&r) { return (r++, r); }
+ template<typename T> constexpr T postdec(T &&r) { return (r--, r); }
+
+ static_assert(++ref(0) == 1, "");
+ static_assert(ref(0)++ == 0, "");
+ static_assert(postinc(0) == 1, "");
+ static_assert(--ref(0) == -1, "");
+ static_assert(ref(0)-- == 0, "");
+ static_assert(postdec(0) == -1, "");
+
+ constexpr int overflow_int_inc_1 = ref(0x7fffffff)++; // expected-error {{constant}} expected-note {{2147483648}}
+ constexpr int overflow_int_inc_1_ok = ref(0x7ffffffe)++;
+ constexpr int overflow_int_inc_2 = ++ref(0x7fffffff); // expected-error {{constant}} expected-note {{2147483648}}
+ constexpr int overflow_int_inc_2_ok = ++ref(0x7ffffffe);
+
+ // inc/dec on short can't overflow because we promote to int first
+ static_assert(++ref<short>(0x7fff) == (int)0xffff8000u, "");
+ static_assert(--ref<short>(0x8000) == 0x7fff, "");
+
+ // inc on bool sets to true
+ static_assert(++ref(false), ""); // expected-warning {{deprecated}}
+ static_assert(++ref(true), ""); // expected-warning {{deprecated}}
+
+ int arr[10];
+ static_assert(++ref(&arr[0]) == &arr[1], "");
+ static_assert(++ref(&arr[9]) == &arr[10], "");
+ static_assert(++ref(&arr[10]) == &arr[11], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}}
+ static_assert(ref(&arr[0])++ == &arr[0], "");
+ static_assert(ref(&arr[10])++ == &arr[10], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}}
+ static_assert(postinc(&arr[0]) == &arr[1], "");
+ static_assert(--ref(&arr[10]) == &arr[9], "");
+ static_assert(--ref(&arr[1]) == &arr[0], "");
+ static_assert(--ref(&arr[0]) != &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}}
+ static_assert(ref(&arr[1])-- == &arr[1], "");
+ static_assert(ref(&arr[0])-- == &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}}
+ static_assert(postdec(&arr[1]) == &arr[0], "");
+
+ int x;
+ static_assert(++ref(&x) == &x + 1, "");
+
+ static_assert(++ref(0.0) == 1.0, "");
+ static_assert(ref(0.0)++ == 0.0, "");
+ static_assert(postinc(0.0) == 1.0, "");
+ static_assert(--ref(0.0) == -1.0, "");
+ static_assert(ref(0.0)-- == 0.0, "");
+ static_assert(postdec(0.0) == -1.0, "");
+
+ static_assert(++ref(1e100) == 1e100, "");
+ static_assert(--ref(1e100) == 1e100, "");
+
+ union U {
+ int a, b;
+ };
+ constexpr int f(U u) {
+ return ++u.b; // expected-note {{increment of member 'b' of union with active member 'a'}}
+ }
+ constexpr int wrong_member = f({0}); // expected-error {{constant}} expected-note {{in call to 'f({.a = 0})'}}
+ constexpr int vol = --ref<volatile int>(0); // expected-error {{constant}} expected-note {{decrement of volatile-qualified}}
+
+ constexpr int incr(int k) {
+ int x = k;
+ if (x++ == 100)
+ return x;
+ return incr(x);
+ }
+ static_assert(incr(0) == 101, "");
+}
+
+namespace loops {
+ constexpr int fib_loop(int a) {
+ int f_k = 0, f_k_plus_one = 1;
+ for (int k = 1; k != a; ++k) {
+ int f_k_plus_two = f_k + f_k_plus_one;
+ f_k = f_k_plus_one;
+ f_k_plus_one = f_k_plus_two;
+ }
+ return f_k_plus_one;
+ }
+ static_assert(fib_loop(46) == 1836311903, "");
+
+ constexpr bool breaks_work() {
+ int a = 0;
+ for (int n = 0; n != 100; ++n) {
+ ++a;
+ if (a == 5) continue;
+ if ((a % 5) == 0) break;
+ }
+
+ int b = 0;
+ while (b != 17) {
+ ++b;
+ if (b == 6) continue;
+ if ((b % 6) == 0) break;
+ }
+
+ int c = 0;
+ do {
+ ++c;
+ if (c == 7) continue;
+ if ((c % 7) == 0) break;
+ } while (c != 21);
+
+ return a == 10 && b == 12 & c == 14;
+ }
+ static_assert(breaks_work(), "");
+
+ void not_constexpr();
+ constexpr bool no_cont_after_break() {
+ for (;;) {
+ break;
+ not_constexpr();
+ }
+ while (true) {
+ break;
+ not_constexpr();
+ }
+ do {
+ break;
+ not_constexpr();
+ } while (true);
+ return true;
+ }
+ static_assert(no_cont_after_break(), "");
+
+ constexpr bool cond() {
+ for (int a = 1; bool b = a != 3; ++a) {
+ if (!b)
+ return false;
+ }
+ while (bool b = true) {
+ b = false;
+ break;
+ }
+ return true;
+ }
+ static_assert(cond(), "");
+
+ constexpr int range_for() {
+ int arr[] = { 1, 2, 3, 4, 5 };
+ int sum = 0;
+ for (int x : arr)
+ sum = sum + x;
+ return sum;
+ }
+ static_assert(range_for() == 15, "");
+
+ template<int...N> struct ints {};
+ template<typename A, typename B> struct join_ints;
+ template<int...As, int...Bs> struct join_ints<ints<As...>, ints<Bs...>> {
+ using type = ints<As..., sizeof...(As) + Bs...>;
+ };
+ template<unsigned N> struct make_ints {
+ using type = typename join_ints<typename make_ints<N/2>::type, typename make_ints<(N+1)/2>::type>::type;
+ };
+ template<> struct make_ints<0> { using type = ints<>; };
+ template<> struct make_ints<1> { using type = ints<0>; };
+
+ struct ignore { template<typename ...Ts> constexpr ignore(Ts &&...) {} };
+
+ template<typename T, unsigned N> struct array {
+ constexpr array() : arr{} {}
+ template<typename ...X>
+ constexpr array(X ...x) : arr{} {
+ init(typename make_ints<sizeof...(X)>::type{}, x...);
+ }
+ template<int ...I, typename ...X> constexpr void init(ints<I...>, X ...x) {
+ ignore{arr[I] = x ...};
+ }
+ T arr[N];
+ struct iterator {
+ T *p;
+ constexpr explicit iterator(T *p) : p(p) {}
+ constexpr bool operator!=(iterator o) { return p != o.p; }
+ constexpr iterator &operator++() { ++p; return *this; }
+ constexpr T &operator*() { return *p; }
+ };
+ constexpr iterator begin() { return iterator(arr); }
+ constexpr iterator end() { return iterator(arr + N); }
+ };
+
+ constexpr int range_for_2() {
+ array<int, 5> arr { 1, 2, 3, 4, 5 };
+ int sum = 0;
+ for (int k : arr) {
+ sum = sum + k;
+ if (sum > 8) break;
+ }
+ return sum;
+ }
+ static_assert(range_for_2() == 10, "");
+}
diff --git a/test/SemaCXX/constexpr-printing.cpp b/test/SemaCXX/constexpr-printing.cpp
index 9170fa1..e545f45 100644
--- a/test/SemaCXX/constexpr-printing.cpp
+++ b/test/SemaCXX/constexpr-printing.cpp
@@ -9,7 +9,7 @@ struct S {
int n, m;
};
-constexpr int extract(const S &s) { return s.n; } // expected-note {{read of uninitialized object is not allowed in a constant expression}}
+constexpr int extract(const S &s) { return s.n; } // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
constexpr S s1; // ok
void f() {
diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp
index e459f09..d137bd8 100644
--- a/test/SemaCXX/constexpr-value-init.cpp
+++ b/test/SemaCXX/constexpr-value-init.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify
struct A {
- constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{uninitialized}}
+ constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{outside its lifetime}}
int a;
int b;
};
diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp
index f95eeb5..f7bfc11 100644
--- a/test/SemaCXX/cxx11-ast-print.cpp
+++ b/test/SemaCXX/cxx11-ast-print.cpp
@@ -41,3 +41,5 @@ const char *p10 = 3.300e+15_fritz;
// CHECK: ;
;
// CHECK-NOT: ;
+
+
diff --git a/test/SemaCXX/cxx11-crashes.cpp b/test/SemaCXX/cxx11-crashes.cpp
index bd51af1..a4d4829 100644
--- a/test/SemaCXX/cxx11-crashes.cpp
+++ b/test/SemaCXX/cxx11-crashes.cpp
@@ -70,7 +70,9 @@ namespace b6981007 {
for (auto x : s) {
// We used to attempt to evaluate the initializer of this variable,
// and crash because it has an undeduced type.
- const int &n(x);
+ // FIXME: We should set the loop variable to be invalid if we can't build
+ // the loop, to suppress this follow-on error.
+ const int &n(x); // expected-error {{could not bind to an lvalue of type 'auto'}}
}
}
}
diff --git a/test/SemaCXX/cxx11-inheriting-ctors.cpp b/test/SemaCXX/cxx11-inheriting-ctors.cpp
new file mode 100644
index 0000000..67d5521
--- /dev/null
+++ b/test/SemaCXX/cxx11-inheriting-ctors.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+// expected-no-diagnostics
+
+namespace PR15757 {
+ struct S {
+ };
+
+ template<typename X, typename Y> struct T {
+ template<typename A> T(X x, A &&a) {}
+
+ template<typename A> explicit T(A &&a)
+ noexcept(noexcept(T(X(), static_cast<A &&>(a))))
+ : T(X(), static_cast<A &&>(a)) {}
+ };
+
+ template<typename X, typename Y> struct U : T<X, Y> {
+ using T<X, Y>::T;
+ };
+
+ U<S, char> foo(char ch) { return U<S, char>(ch); }
+
+ int main() {
+ U<S, int> a(42);
+ U<S, char> b('4');
+ return 0;
+ }
+}
diff --git a/test/SemaCXX/cxx11-thread-local-print.cpp b/test/SemaCXX/cxx11-thread-local-print.cpp
new file mode 100644
index 0000000..9d9a82b
--- /dev/null
+++ b/test/SemaCXX/cxx11-thread-local-print.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-linux-gnu -ast-print %s | FileCheck %s
+
+// CHECK: __thread int gnu_tl;
+// CHECK: _Thread_local int c11_tl;
+// CHECK: thread_local int cxx11_tl;
+__thread int gnu_tl;
+_Thread_local int c11_tl;
+thread_local int cxx11_tl;
+
diff --git a/test/SemaCXX/cxx11-thread-local.cpp b/test/SemaCXX/cxx11-thread-local.cpp
new file mode 100644
index 0000000..f1dddc1
--- /dev/null
+++ b/test/SemaCXX/cxx11-thread-local.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-linux-gnu -verify %s
+
+struct S {
+ static thread_local int a;
+ static int b; // expected-note {{here}}
+ thread_local int c; // expected-error {{'thread_local' is only allowed on variable declarations}}
+ static thread_local int d; // expected-note {{here}}
+};
+
+thread_local int S::a;
+thread_local int S::b; // expected-error {{thread-local declaration of 'b' follows non-thread-local declaration}}
+thread_local int S::c; // expected-error {{non-static data member defined out-of-line}}
+int S::d; // expected-error {{non-thread-local declaration of 'd' follows thread-local declaration}}
+
+thread_local int x[3];
+thread_local int y[3];
+thread_local int z[3]; // expected-note {{previous}}
+
+void f() {
+ thread_local int x;
+ static thread_local int y;
+ extern thread_local int z; // expected-error {{redefinition of 'z' with a different type}}
+}
diff --git a/test/SemaCXX/cxx11-user-defined-literals-unused.cpp b/test/SemaCXX/cxx11-user-defined-literals-unused.cpp
new file mode 100644
index 0000000..cd93ffb
--- /dev/null
+++ b/test/SemaCXX/cxx11-user-defined-literals-unused.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -Wunused
+
+namespace {
+double operator"" _x(long double value) { return double(value); }
+int operator"" _ii(long double value) { return int(value); } // expected-warning {{not needed and will not be emitted}}
+}
+
+namespace rdar13589856 {
+ template<class T> double value() { return 3.2_x; }
+ template<class T> int valuei() { return 3.2_ii; }
+
+ double get_value() { return value<double>(); }
+}
diff --git a/test/SemaCXX/cxx1y-array-runtime-bound.cpp b/test/SemaCXX/cxx1y-array-runtime-bound.cpp
new file mode 100644
index 0000000..1643adb
--- /dev/null
+++ b/test/SemaCXX/cxx1y-array-runtime-bound.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -std=c++1y %s -verify -triple=x86_64-linux-gnu -pedantic-errors
+
+// FIXME: many diagnostics here say 'variably modified type'.
+// catch this case and say 'array of runtime bound' instead.
+
+namespace std { struct type_info; }
+
+struct S {
+ int arr[__SIZE_MAX__ / 32];
+};
+S s[32]; // expected-error {{array is too large}}
+
+int n;
+int a[n]; // expected-error {{not allowed at file scope}}
+
+struct T {
+ int a[n]; // expected-error {{fields must have a constant size}}
+ static int b[n]; // expected-error {{not allowed at file scope}}
+};
+
+int g(int n, int a[n]);
+
+template<typename T> struct X {};
+template<int N, int[N]> struct Y {};
+template<int[n]> struct Z {}; // expected-error {{of variably modified type}}
+
+int f(int n) {
+ int arb[n]; // expected-note 3{{here}}
+ [arb] {} (); // expected-error {{cannot be captured}}
+
+ // FIXME: an array of runtime bound can be captured by reference.
+ [&arb] { // expected-error {{cannot be captured}}
+ // Capturing the array implicitly captures the bound, if we need it
+ // in a range-based for loop.
+ for (auto &n : arb) { } // expected-error {{cannot be captured}}
+ } ();
+
+ X<int[n]> x; // expected-error {{variably modified type}}
+
+ int arb_neg[-1]; // expected-error {{negative size}}
+ int arb_of_array[n][2];
+ int arr[3] = { 1, 2, 3, 4 }; // expected-error {{excess elements}}
+ char foo[4] = "fool"; // expected-error {{initializer-string for char array is too long}}
+
+ static int not_auto1[n]; // expected-error {{can not have 'static'}}
+ extern int not_auto2[n]; // expected-error {{can not have 'extern'}}
+ // FIXME: say 'thread_local' not 'static'.
+ thread_local int not_auto1[n]; // expected-error {{can not have 'static'}}
+
+ // FIXME: these should all be invalid.
+ auto &&ti1 = typeid(arb);
+ auto &&ti2 = typeid(int[n]);
+ auto &&so1 = sizeof(arb);
+ auto &&so2 = sizeof(int[n]);
+ auto *p = &arb;
+ decltype(arb) arb2;
+ int (*arbp)[n] = 0;
+ const int (&arbr)[n] = arbr; // expected-warning {{not yet bound}}
+ typedef int arbty[n];
+ int array_of_arb[2][n];
+
+ struct Dyn { Dyn() {} Dyn(int) {} ~Dyn() {} };
+
+ // FIXME: these should be valid.
+ int arb_dynamic[n] = { 1, 2, 3, 4 }; // expected-error {{may not be initialized}}
+ Dyn dyn[n]; // expected-error {{non-POD}}
+ Dyn dyn_init[n] = { 1, 2, 3, 4 }; // expected-error {{non-POD}}
+}
diff --git a/test/SemaCXX/cxx1y-constexpr-not-const.cpp b/test/SemaCXX/cxx1y-constexpr-not-const.cpp
new file mode 100644
index 0000000..3f100b8
--- /dev/null
+++ b/test/SemaCXX/cxx1y-constexpr-not-const.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+// RUN: %clang_cc1 -std=c++1y %s -verify -DCXX1Y
+
+struct X {
+ constexpr int f(); // @5
+ int f(); // @6
+};
+
+#ifdef CXX1Y
+// FIXME: Detect this situation and provide a better recovery.
+
+// expected-error@6 {{class member cannot be redeclared}}
+// expected-note@5 {{previous}}
+// expected-error@6 {{non-constexpr declaration of 'f' follows constexpr declaration}}
+// expected-note@5 {{previous}}
+#else
+// expected-warning@5 {{'constexpr' non-static member function will not be implicitly 'const' in C++1y; add 'const' to avoid a change in behavior}}
+#endif
diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp
new file mode 100644
index 0000000..f0146f8
--- /dev/null
+++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp
@@ -0,0 +1,338 @@
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s
+
+auto f(); // expected-note {{previous}}
+int f(); // expected-error {{differ only in their return type}}
+
+auto &g();
+auto g() -> auto &;
+
+auto h() -> auto *;
+auto *h();
+
+struct Conv1 {
+ operator auto(); // expected-note {{declared here}}
+} conv1;
+int conv1a = conv1; // expected-error {{function 'operator auto' with deduced return type cannot be used before it is defined}}
+// expected-error@-1 {{no viable conversion}}
+Conv1::operator auto() { return 123; }
+int conv1b = conv1;
+int conv1c = conv1.operator auto();
+int conv1d = conv1.operator int(); // expected-error {{no member named 'operator int'}}
+
+struct Conv2 {
+ operator auto() { return 0; } // expected-note 2{{previous}}
+ operator auto() { return 0.; } // expected-error {{cannot be redeclared}} expected-error {{redefinition of 'operator auto'}}
+};
+
+struct Conv3 {
+ operator auto() { int *p = nullptr; return p; } // expected-note {{candidate}}
+ operator auto*() { int *p = nullptr; return p; } // expected-note {{candidate}}
+} conv3;
+int *conv3a = conv3; // expected-error {{ambiguous}}
+int *conv3b = conv3.operator auto();
+int *conv3c = conv3.operator auto*();
+
+template<typename T>
+struct Conv4 {
+ operator auto() { return T(); }
+};
+Conv4<int> conv4int;
+int conv4a = conv4int;
+int conv4b = conv4int.operator auto();
+
+auto a();
+auto a() { return 0; }
+using T = decltype(a());
+using T = int;
+auto a(); // expected-note {{previous}}
+using T = decltype(a());
+auto *a(); // expected-error {{differ only in their return type}}
+
+auto b(bool k) {
+ if (k)
+ return "hello";
+ return "goodbye";
+}
+
+auto *ptr_1() {
+ return 100; // expected-error {{cannot deduce return type 'auto *' from returned value of type 'int'}}
+}
+
+const auto &ref_1() {
+ return 0; // expected-warning {{returning reference to local temporary}}
+}
+
+auto init_list() {
+ return { 1, 2, 3 }; // expected-error {{cannot deduce return type from initializer list}}
+}
+
+auto fwd_decl(); // expected-note 2{{here}}
+
+int n = fwd_decl(); // expected-error {{function 'fwd_decl' with deduced return type cannot be used before it is defined}}
+int k = sizeof(fwd_decl()); // expected-error {{used before it is defined}}
+
+auto fac(int n) {
+ if (n <= 2)
+ return n;
+ return n * fac(n-1); // ok
+}
+
+auto fac_2(int n) { // expected-note {{declared here}}
+ if (n > 2)
+ return n * fac_2(n-1); // expected-error {{cannot be used before it is defined}}
+ return n;
+}
+
+auto void_ret() {}
+using Void = void;
+using Void = decltype(void_ret());
+
+auto &void_ret_2() {} // expected-error {{cannot deduce return type 'auto &' for function with no return statements}}
+const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 'void'
+
+const auto void_ret_4() {
+ if (false)
+ return void();
+ if (false)
+ return;
+ return 0; // expected-error {{'auto' in return type deduced as 'int' here but deduced as 'void' in earlier return statement}}
+}
+
+namespace Templates {
+ template<typename T> auto f1() {
+ return T() + 1;
+ }
+ template<typename T> auto &f2(T &&v) { return v; }
+ int a = f1<int>();
+ const int &b = f2(0);
+ double d;
+ float &c = f2(0.0); // expected-error {{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'double'}}
+
+ template<typename T> auto fwd_decl(); // expected-note {{declared here}}
+ int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}}
+ template<typename T> auto fwd_decl() { return 0; }
+ int f = fwd_decl<int>();
+ template<typename T> auto fwd_decl();
+ int g = fwd_decl<char>();
+
+ auto (*p)() = f1; // expected-error {{incompatible initializer}}
+ auto (*q)() = f1<int>; // ok
+
+ typedef decltype(f2(1.2)) dbl; // expected-note {{previous}}
+ typedef float dbl; // expected-error {{typedef redefinition with different types ('float' vs 'decltype(f2(1.2))' (aka 'double &'))}}
+
+ extern template auto fwd_decl<double>();
+ int k1 = fwd_decl<double>();
+ extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}}
+ int k2 = fwd_decl<char>();
+
+ template<typename T> auto instantiate() { T::error; } // expected-error {{has no members}}
+ extern template auto instantiate<int>(); // ok
+ int k = instantiate<int>(); // expected-note {{in instantiation of}}
+ template<> auto instantiate<char>() {} // ok
+ template<> void instantiate<double>() {} // expected-error {{no function template matches}}
+
+ template<typename T> auto arg_single() { return 0; }
+ template<typename T> auto arg_multi() { return 0l; }
+ template<typename T> auto arg_multi(int) { return "bad"; }
+ template<typename T> struct Outer {
+ static auto arg_single() { return 0.f; }
+ static auto arg_multi() { return 0.; }
+ static auto arg_multi(int) { return "bad"; }
+ };
+ template<typename T> T &take_fn(T (*p)());
+
+ int &check1 = take_fn(arg_single); // expected-error {{no matching}} expected-note@-2 {{couldn't infer}}
+ int &check2 = take_fn(arg_single<int>);
+ int &check3 = take_fn<int>(arg_single); // expected-error {{no matching}} expected-note@-4{{no overload of 'arg_single'}}
+ int &check4 = take_fn<int>(arg_single<int>);
+ long &check5 = take_fn(arg_multi); // expected-error {{no matching}} expected-note@-6 {{couldn't infer}}
+ long &check6 = take_fn(arg_multi<int>);
+ long &check7 = take_fn<long>(arg_multi); // expected-error {{no matching}} expected-note@-8{{no overload of 'arg_multi'}}
+ long &check8 = take_fn<long>(arg_multi<int>);
+
+ float &mem_check1 = take_fn(Outer<int>::arg_single);
+ float &mem_check2 = take_fn<float>(Outer<char>::arg_single);
+ double &mem_check3 = take_fn(Outer<long>::arg_multi);
+ double &mem_check4 = take_fn<double>(Outer<double>::arg_multi);
+
+ namespace Deduce1 {
+ template<typename T> auto f() { return 0; } // expected-note {{candidate}}
+ template<typename T> void g(T(*)()); // expected-note 2{{candidate}}
+ void h() {
+ auto p = f<int>;
+ auto (*q)() = f<int>;
+ int (*r)() = f; // expected-error {{does not match}}
+ g(f<int>);
+ g<int>(f); // expected-error {{no matching function}}
+ g(f); // expected-error {{no matching function}}
+ }
+ }
+
+ namespace Deduce2 {
+ template<typename T> auto f(int) { return 0; } // expected-note {{candidate}}
+ template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}}
+ void h() {
+ auto p = f<int>;
+ auto (*q)(int) = f<int>;
+ int (*r)(int) = f; // expected-error {{does not match}}
+ g(f<int>);
+ g<int>(f); // expected-error {{no matching function}}
+ g(f); // expected-error {{no matching function}}
+ }
+ }
+
+ namespace Deduce3 {
+ template<typename T> auto f(T) { return 0; }
+ template<typename T> void g(T(*)(int)); // expected-note {{couldn't infer}}
+ void h() {
+ auto p = f<int>;
+ auto (*q)(int) = f<int>;
+ int (*r)(int) = f; // ok
+ g(f<int>);
+ g<int>(f); // ok
+ g(f); // expected-error {{no matching function}}
+ }
+ }
+
+ namespace DeduceInDeducedReturnType {
+ template<typename T, typename U> auto f() -> auto (T::*)(U) {
+ int (T::*result)(U) = nullptr;
+ return result;
+ }
+ struct S {};
+ int (S::*(*p)())(double) = f;
+ int (S::*(*q)())(double) = f<S, double>;
+ }
+}
+
+auto fwd_decl_using();
+namespace N { using ::fwd_decl_using; }
+auto fwd_decl_using() { return 0; }
+namespace N { int k = N::fwd_decl_using(); }
+
+namespace OverloadResolutionNonTemplate {
+ auto f();
+ auto f(int); // expected-note {{here}}
+
+ int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}}
+ char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}}
+
+ int a = g(f); // expected-error {{no matching function}}
+
+ auto f() { return 0; }
+
+ // FIXME: It's not completely clear whether this should be ill-formed.
+ int &b = g(f); // expected-error {{used before it is defined}}
+
+ auto f(int) { return 0.0; }
+
+ int &c = g(f); // ok
+}
+
+namespace OverloadResolutionTemplate {
+ auto f();
+ template<typename T> auto f(T);
+
+ int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}} expected-note {{candidate}}
+ char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}} expected-note {{candidate}}
+
+ int a = g(f); // expected-error {{no matching function}}
+
+ auto f() { return 0; }
+
+ int &b = g(f); // ok (presumably), due to deduction failure forming type of 'f<int>'
+
+ template<typename T> auto f(T) { return 0; }
+
+ int &c = g(f); // expected-error {{ambiguous}}
+}
+
+namespace DefaultedMethods {
+ struct A {
+ auto operator=(const A&) = default; // expected-error {{must return 'DefaultedMethods::A &'}}
+ A &operator=(A&&); // expected-note {{previous}}
+ };
+ auto A::operator=(A&&) = default; // expected-error {{differs from the declaration in the return type}}
+}
+
+namespace Constexpr {
+ constexpr auto f1(int n) { return n; }
+ struct NonLiteral { ~NonLiteral(); } nl; // expected-note {{user-provided destructor}}
+ constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}}
+}
+
+// It's not really clear whether these are valid, but this matches g++.
+using size_t = decltype(sizeof(0));
+auto operator new(size_t n, const char*); // expected-error {{must return type 'void *'}}
+auto operator delete(void *, const char*); // expected-error {{must return type 'void'}}
+
+namespace Virtual {
+ struct S {
+ virtual auto f() { return 0; } // expected-error {{function with deduced return type cannot be virtual}} expected-note {{here}}
+ };
+ // Allow 'auto' anyway for error recovery.
+ struct T : S {
+ int f();
+ };
+ struct U : S {
+ auto f(); // expected-error {{different return}}
+ };
+
+ // And here's why...
+ struct V { virtual auto f(); }; // expected-error {{cannot be virtual}}
+ struct W : V { virtual auto f(); }; // expected-error {{cannot be virtual}}
+ auto V::f() { return 0; } // in tu1.cpp
+ auto W::f() { return 0.0; } // in tu2.cpp
+ W w;
+ int k1 = w.f();
+ int k2 = ((V&)w).f();
+}
+
+namespace std_examples {
+
+namespace NoReturn {
+ auto f() {}
+ void (*p)() = &f;
+
+ auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}}
+}
+
+namespace UseBeforeComplete {
+ auto n = n; // expected-error {{variable 'n' declared with 'auto' type cannot appear in its own initializer}}
+ auto f(); // expected-note {{declared here}}
+ void g() { &f; } // expected-error {{function 'f' with deduced return type cannot be used before it is defined}}
+ auto sum(int i) {
+ if (i == 1)
+ return i;
+ else
+ return sum(i - 1) + i;
+ }
+}
+
+namespace Redecl {
+ auto f();
+ auto f() { return 42; }
+ auto f(); // expected-note 2{{previous}}
+ int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+ decltype(auto) f(); // expected-error {{cannot be overloaded}}
+
+ template<typename T> auto g(T t) { return t; } // expected-note {{candidate}}
+ template auto g(int);
+ template char g(char); // expected-error {{does not refer to a function}}
+ template<> auto g(double);
+
+ template<typename T> T g(T t) { return t; } // expected-note {{candidate}}
+ template char g(char);
+ template auto g(float);
+
+ void h() { return g(42); } // expected-error {{ambiguous}}
+}
+
+namespace ExplicitInstantiationDecl {
+ template<typename T> auto f(T t) { return t; }
+ extern template auto f(int);
+ int (*p)(int) = f;
+}
+
+}
diff --git a/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/test/SemaCXX/cxx1y-initializer-aggregates.cpp
new file mode 100644
index 0000000..9b54240
--- /dev/null
+++ b/test/SemaCXX/cxx1y-initializer-aggregates.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -std=c++1y %s -verify
+
+namespace in_class_init {
+ union U { char c; double d = 4.0; };
+ constexpr U u1 = U();
+ constexpr U u2 {};
+ constexpr U u3 { 'x' };
+ static_assert(u1.d == 4.0, "");
+ static_assert(u2.d == 4.0, "");
+ static_assert(u3.c == 'x', "");
+
+ struct A {
+ int n = 5;
+ int m = n * 3;
+ union {
+ char c;
+ double d = 4.0;
+ };
+ };
+ constexpr A a1 {};
+ constexpr A a2 { 8 };
+ constexpr A a3 { 1, 2, { 3 } };
+ constexpr A a4 { 1, 2, { .d = 3.0 } };
+ static_assert(a1.d == 4.0, "");
+ static_assert(a2.m == 24, "");
+ static_assert(a2.d == 4.0, "");
+ static_assert(a3.c == 3, "");
+ static_assert(a3.d == 4.0, ""); // expected-error {{constant expression}} expected-note {{active member 'c'}}
+ static_assert(a4.d == 3.0, "");
+
+ struct B {
+ int n;
+ constexpr int f() { return n * 5; }
+ int m = f();
+ };
+ B b1 {};
+ constexpr B b2 { 2 };
+ B b3 { 1, 2 };
+ static_assert(b2.m == 10, "");
+
+ struct C {
+ int k;
+ union {
+ int l = k; // expected-error {{invalid use of non-static}}
+ };
+ };
+}
+
+namespace nested_aggregate_init {
+ struct A {
+ int n = 5;
+ int b = n * 3;
+ };
+ struct B {
+ constexpr B(int k) : d(1.23), k(k) {}
+ // Within this aggregate, both this object's 'this' and the temporary's
+ // 'this' are used.
+ constexpr int f() const { return A{k}.b; }
+ double d;
+ int k;
+ };
+ static_assert(B(6).f() == 18, "");
+}
diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp
index 18fd152..208ea4c 100644
--- a/test/SemaCXX/cxx98-compat-pedantic.cpp
+++ b/test/SemaCXX/cxx98-compat-pedantic.cpp
@@ -1,3 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat-pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat-pedantic -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Werror %s
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Werror %s
@@ -38,3 +40,12 @@ long long ll1 = // expected-warning {{'long long' is incompatible with C++98}}
unsigned long long ull1 = // expected-warning {{'long long' is incompatible with C++98}}
42ULL; // expected-warning {{'long long' is incompatible with C++98}}
+int k = 0b1001;
+#ifdef CXX1Y
+// expected-warning@-2 {{binary integer literals are incompatible with C++ standards before C++1y}}
+#endif
+
+void f(int n) { int a[n]; }
+#ifdef CXX1Y
+// expected-warning@-2 {{arrays of runtime bound are incompatible with C++ standards before C++1y}}
+#endif
diff --git a/test/SemaCXX/enum-unscoped-nonexistent.cpp b/test/SemaCXX/enum-unscoped-nonexistent.cpp
index d49800c..e9da38f 100644
--- a/test/SemaCXX/enum-unscoped-nonexistent.cpp
+++ b/test/SemaCXX/enum-unscoped-nonexistent.cpp
@@ -5,8 +5,8 @@ struct Base {
};
template<typename T> struct S : Base {
enum E : int;
- constexpr int f();
- constexpr int g(); // expected-note {{declared here}}
+ constexpr int f() const;
+ constexpr int g() const; // expected-note {{declared here}}
void h();
};
template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}}
@@ -16,13 +16,13 @@ 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; }
+template<typename T> constexpr int S<T>::f() const { 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>'}}
+template<typename T> constexpr int S<T>::g() const { 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, "");
diff --git a/test/SemaCXX/for-range-unused.cpp b/test/SemaCXX/for-range-unused.cpp
index ce6b379..ec11015 100644
--- a/test/SemaCXX/for-range-unused.cpp
+++ b/test/SemaCXX/for-range-unused.cpp
@@ -7,7 +7,7 @@ template <typename T>
void doIt() {
int a; // expected-warning {{unused variable 'a'}}
- for (auto& e : elements)
+ for (auto& e : elements) // expected-warning {{unused variable 'e'}}
;
}
@@ -17,5 +17,5 @@ template <typename T>
int main(int, char**) {
Vector<int> vector;
- vector.doIt();
+ vector.doIt(); // expected-note {{here}}
}
diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp
index 5631577..c80323c 100644
--- a/test/SemaCXX/i-c-e-cxx.cpp
+++ b/test/SemaCXX/i-c-e-cxx.cpp
@@ -60,7 +60,7 @@ int* y = reinterpret_cast<const char&>(x); // expected-error {{cannot initialize
// This isn't an integral constant expression, but make sure it folds anyway.
struct PR8836 { char _; long long a; }; // expected-warning {{long long}}
-int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
+int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
const int nonconst = 1.0; // expected-note {{declared here}}
int arr[nonconst]; // expected-warning {{folded to constant array as an extension}} expected-note {{initializer of 'nonconst' is not a constant expression}}
diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp
index 0ba9508..504df0d 100644
--- a/test/SemaCXX/linkage-spec.cpp
+++ b/test/SemaCXX/linkage-spec.cpp
@@ -106,3 +106,11 @@ namespace PR9162 {
return sizeof(ArtsSink);
}
}
+
+namespace pr14958 {
+ namespace js { extern int ObjectClass; }
+ extern "C" {
+ namespace js {}
+ }
+ int js::ObjectClass;
+}
diff --git a/test/SemaCXX/linkage.cpp b/test/SemaCXX/linkage.cpp
index 6b73d59..13d295a 100644
--- a/test/SemaCXX/linkage.cpp
+++ b/test/SemaCXX/linkage.cpp
@@ -94,3 +94,12 @@ extern "C" {
// CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv(
// CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv(
+
+namespace test5 {
+ struct foo {
+ };
+ extern "C" {
+ const foo bar[] = {
+ };
+ }
+}
diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp
index ddf4064..3cfa981 100644
--- a/test/SemaCXX/linkage2.cpp
+++ b/test/SemaCXX/linkage2.cpp
@@ -152,3 +152,15 @@ namespace test15 {
const int a = 5; // expected-note {{previous definition is here}}
static const int a; // expected-error {{redefinition of 'a'}}
}
+
+namespace test16 {
+ extern "C" {
+ class Foo {
+ int x;
+ friend int bar(Foo *y);
+ };
+ int bar(Foo *y) {
+ return y->x;
+ }
+ }
+}
diff --git a/test/SemaCXX/pascal-strings.cpp b/test/SemaCXX/pascal-strings.cpp
index 89194b5..f4c692d 100644
--- a/test/SemaCXX/pascal-strings.cpp
+++ b/test/SemaCXX/pascal-strings.cpp
@@ -4,3 +4,5 @@ const wchar_t *pascalString = L"\pThis is a Pascal string";
unsigned char a[3] = "\pa";
unsigned char b[3] = "\pab";
unsigned char c[3] = "\pabc"; // expected-error {{initializer-string for char array is too long}}
+unsigned char d[3] = ("\pab");
+unsigned char e[3] = ("\pabc"); // expected-error {{initializer-string for char array is too long}}
diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp
index 462b4fa..bd601db 100644
--- a/test/SemaCXX/trailing-return-0x.cpp
+++ b/test/SemaCXX/trailing-return-0x.cpp
@@ -85,3 +85,12 @@ namespace PR12053 {
f2(0); // expected-error{{no matching function for call to 'f2'}}
}
}
+
+namespace DR1608 {
+ struct S {
+ void operator+();
+ int operator[](int);
+ auto f() -> decltype(+*this); // expected-note {{here}}
+ auto f() -> decltype((*this)[0]); // expected-error {{cannot be overloaded}}
+ };
+}
diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp
index 839fdaf..1b76a86 100644
--- a/test/SemaCXX/undefined-internal.cpp
+++ b/test/SemaCXX/undefined-internal.cpp
@@ -323,3 +323,10 @@ namespace test13 {
}
}
+namespace test14 {
+ extern "C" const int foo;
+
+ int f() {
+ return foo;
+ }
+}
diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp
index 2aa5662..665cfe7 100644
--- a/test/SemaCXX/uninitialized.cpp
+++ b/test/SemaCXX/uninitialized.cpp
@@ -511,3 +511,15 @@ namespace operators {
int x = x = 5;
}
+
+namespace lambdas {
+ struct A {
+ template<typename T> A(T) {}
+ int x;
+ };
+ A a0([] { return a0.x; }); // ok
+ void f() {
+ A a1([=] { return a1.x; }); // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}}
+ A a2([&] { return a2.x; }); // ok
+ }
+}
diff --git a/test/SemaCXX/warn-c++11-extensions.cpp b/test/SemaCXX/warn-c++11-extensions.cpp
index 8f35171..bf8612a 100644
--- a/test/SemaCXX/warn-c++11-extensions.cpp
+++ b/test/SemaCXX/warn-c++11-extensions.cpp
@@ -5,3 +5,5 @@ long long ll1 = // expected-warning {{'long long' is a C++11 extension}}
unsigned long long ull1 = // expected-warning {{'long long' is a C++11 extension}}
42ULL; // expected-warning {{'long long' is a C++11 extension}}
+enum struct E1 { A, B }; // expected-warning {{scoped enumerations are a C++11 extension}}
+enum class E2 { C, D }; // expected-warning {{scoped enumerations are a C++11 extension}}
diff --git a/test/SemaCXX/warn-overloaded-virtual.cpp b/test/SemaCXX/warn-overloaded-virtual.cpp
index 9b0f5aa..629d59d 100644
--- a/test/SemaCXX/warn-overloaded-virtual.cpp
+++ b/test/SemaCXX/warn-overloaded-virtual.cpp
@@ -120,3 +120,21 @@ struct MostDerived: Derived3, Derived2 {
void func();
};
}
+
+namespace {
+ class A {
+ virtual int foo(bool) const;
+ // expected-note@-1{{type mismatch at 1st parameter ('bool' vs 'int')}}
+ virtual int foo(int, int) const;
+ // expected-note@-1{{different number of parameters (2 vs 1)}}
+ virtual int foo(int*) const;
+ // expected-note@-1{{type mismatch at 1st parameter ('int *' vs 'int')}}
+ virtual int foo(int) volatile;
+ // expected-note@-1{{different qualifiers (volatile vs const)}}
+ };
+
+ class B : public A {
+ virtual int foo(int) const;
+ // expected-warning@-1{{hides overloaded virtual functions}}
+ };
+}
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 3f41124..bc4b40e 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -1475,8 +1475,8 @@ namespace substitution_test {
public:
Mutex mu;
- void lockData() __attribute__((exclusive_lock_function(mu))) { }
- void unlockData() __attribute__((unlock_function(mu))) { }
+ void lockData() __attribute__((exclusive_lock_function(mu)));
+ void unlockData() __attribute__((unlock_function(mu)));
void doSomething() __attribute__((exclusive_locks_required(mu))) { }
};
@@ -1484,8 +1484,8 @@ namespace substitution_test {
class DataLocker {
public:
- void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
- void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
+ void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu)));
+ void unlockData(MyData *d) __attribute__((unlock_function(d->mu)));
};
@@ -2858,7 +2858,7 @@ void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
}
void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
- mu1_.Lock();
+ mu1_.ReaderLock();
}
void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
@@ -3640,8 +3640,8 @@ class Foo {
LOCKS_EXCLUDED(mu2_);
void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
EXCLUSIVE_LOCK_FUNCTION(mu2_);
- void readerlock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
- EXCLUSIVE_LOCK_FUNCTION(mu2_);
+ void readerlock() SHARED_LOCK_FUNCTION(mu1_)
+ SHARED_LOCK_FUNCTION(mu2_);
void unlock() UNLOCK_FUNCTION(mu1_)
UNLOCK_FUNCTION(mu2_);
bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
@@ -3663,9 +3663,9 @@ void Foo::foo2() {
}
void Foo::foo3() { }
-void Foo::lock() { }
-void Foo::readerlock() { }
-void Foo::unlock() { }
+void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }
+void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }
+void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }
bool Foo::trylock() { return true; }
bool Foo::readertrylock() { return true; }
@@ -3915,3 +3915,73 @@ void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());
} // end namespace UnevaluatedContextTest
+
+namespace LockUnlockFunctionTest {
+
+// Check built-in lock functions
+class LOCKABLE MyLockable {
+public:
+ void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
+ void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }
+ void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
+
+private:
+ Mutex mu_;
+};
+
+
+class Foo {
+public:
+ // Correct lock/unlock functions
+ void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {
+ mu_.Lock();
+ }
+
+ void readerLock() SHARED_LOCK_FUNCTION(mu_) {
+ mu_.ReaderLock();
+ }
+
+ void unlock() UNLOCK_FUNCTION(mu_) {
+ mu_.Unlock();
+ }
+
+ // Check failure to lock.
+ void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
+ mu2_.Lock();
+ mu2_.Unlock();
+ } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}}
+
+ void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
+ mu2_.Lock();
+ mu2_.Unlock();
+ } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}}
+
+ void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
+ mu2_.Lock();
+ mu2_.Unlock();
+ } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
+
+ // Check locking the wrong thing.
+ void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
+ mu2_.Lock(); // expected-note {{mutex acquired here}}
+ } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} \
+ // expected-warning {{mutex 'mu2_' is still locked at the end of function}}
+
+
+ void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
+ mu2_.ReaderLock(); // expected-note {{mutex acquired here}}
+ } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} \
+ // expected-warning {{mutex 'mu2_' is still locked at the end of function}}
+
+
+ void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
+ mu2_.Unlock(); // expected-warning {{unlocking 'mu2_' that was not locked}}
+ } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
+
+private:
+ Mutex mu_;
+ Mutex mu2_;
+};
+
+} // end namespace LockUnlockFunctionTest
+
diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp
index e12668b..9fb6011 100644
--- a/test/SemaCXX/warn-unused-filescoped.cpp
+++ b/test/SemaCXX/warn-unused-filescoped.cpp
@@ -133,6 +133,27 @@ namespace test6 {
};
}
+namespace test7
+{
+ template<typename T>
+ static inline void foo(T) { }
+
+ // This should not emit an unused-function warning since it inherits
+ // the static storage type from the base template.
+ template<>
+ inline void foo(int) { }
+
+ // Partial specialization
+ template<typename T, typename U>
+ static inline void bar(T, U) { }
+
+ template<typename U>
+ inline void bar(int, U) { }
+
+ template<>
+ inline void bar(int, int) { }
+};
+
namespace pr14776 {
namespace {
struct X {};
diff --git a/test/SemaCXX/warn-unused-variables-error.cpp b/test/SemaCXX/warn-unused-variables-error.cpp
new file mode 100644
index 0000000..6386c4b
--- /dev/null
+++ b/test/SemaCXX/warn-unused-variables-error.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s
+
+namespace PR6948 {
+ template<typename T> class X; // expected-note{{template is declared here}}
+
+ void f() {
+ X<char> str (read_from_file()); // expected-error{{use of undeclared identifier 'read_from_file'}} \
+ expected-error{{implicit instantiation of undefined template 'PR6948::X<char>'}}
+ }
+}
diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp
index 4e8d51d..00597f9 100644
--- a/test/SemaCXX/warn-unused-variables.cpp
+++ b/test/SemaCXX/warn-unused-variables.cpp
@@ -41,15 +41,6 @@ void test_dependent_init(T *p) {
(void)i;
}
-namespace PR6948 {
- template<typename T> class X; // expected-note{{template is declared here}}
-
- void f() {
- X<char> str (read_from_file()); // expected-error{{use of undeclared identifier 'read_from_file'}} \
- expected-error{{implicit instantiation of undefined template 'PR6948::X<char>'}}
- }
-}
-
void unused_local_static() {
static int x = 0;
static int y = 0; // expected-warning{{unused variable 'y'}}
@@ -135,3 +126,5 @@ namespace ctor_with_cleanups {
S2 s((S1()));
}
}
+
+#include "Inputs/warn-unused-variables.h"
OpenPOWER on IntegriCloud