summaryrefslogtreecommitdiffstats
path: root/test/SemaCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/Inputs/array-bounds-system-header.h11
-rw-r--r--test/SemaCXX/Inputs/warn-new-overaligned-3.h19
-rw-r--r--test/SemaCXX/MicrosoftCompatibility-cxx98.cpp8
-rw-r--r--test/SemaCXX/MicrosoftCompatibility.cpp198
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp20
-rw-r--r--test/SemaCXX/PR10177.cpp40
-rw-r--r--test/SemaCXX/PR10447.cpp22
-rw-r--r--test/SemaCXX/PR11358.cpp51
-rw-r--r--test/SemaCXX/PR12481.cpp17
-rw-r--r--test/SemaCXX/PR8385.cpp7
-rw-r--r--test/SemaCXX/PR9460.cpp6
-rw-r--r--test/SemaCXX/PR9461.cpp6
-rw-r--r--test/SemaCXX/PR9572.cpp2
-rw-r--r--test/SemaCXX/__null.cpp4
-rw-r--r--test/SemaCXX/access.cpp2
-rw-r--r--test/SemaCXX/addr-of-overloaded-function.cpp76
-rw-r--r--test/SemaCXX/aggregate-initialization.cpp22
-rw-r--r--test/SemaCXX/alias-template.cpp8
-rw-r--r--test/SemaCXX/altivec.cpp10
-rw-r--r--test/SemaCXX/anonymous-struct.cpp5
-rw-r--r--test/SemaCXX/array-bounds-ptr-arith.cpp2
-rw-r--r--test/SemaCXX/array-bounds-system-header.cpp9
-rw-r--r--test/SemaCXX/array-bounds.cpp92
-rw-r--r--test/SemaCXX/atomic-type.cxx35
-rw-r--r--test/SemaCXX/attr-cxx0x.cpp11
-rw-r--r--test/SemaCXX/attr-declspec-ignored.cpp19
-rw-r--r--test/SemaCXX/attr-deprecated.cpp4
-rw-r--r--test/SemaCXX/attr-sentinel.cpp17
-rw-r--r--test/SemaCXX/auto-cxx98.cpp2
-rw-r--r--test/SemaCXX/blocks-1.cpp15
-rw-r--r--test/SemaCXX/c99-variable-length-array.cpp35
-rw-r--r--test/SemaCXX/c99.cpp4
-rw-r--r--test/SemaCXX/class-base-member-init.cpp24
-rw-r--r--test/SemaCXX/class.cpp44
-rw-r--r--test/SemaCXX/complex-overload.cpp2
-rw-r--r--test/SemaCXX/condition.cpp12
-rw-r--r--test/SemaCXX/conditional-expr.cpp4
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp1246
-rw-r--r--test/SemaCXX/constant-expression.cpp34
-rw-r--r--test/SemaCXX/constexpr-ackermann.cpp8
-rw-r--r--test/SemaCXX/constexpr-backtrace-limit.cpp34
-rw-r--r--test/SemaCXX/constexpr-depth.cpp8
-rw-r--r--test/SemaCXX/constexpr-factorial.cpp9
-rw-r--r--test/SemaCXX/constexpr-nqueens.cpp73
-rw-r--r--test/SemaCXX/constexpr-printing.cpp102
-rw-r--r--test/SemaCXX/constexpr-strlen.cpp15
-rw-r--r--test/SemaCXX/constexpr-turing.cpp55
-rw-r--r--test/SemaCXX/constexpr-value-init.cpp37
-rw-r--r--test/SemaCXX/constructor-initializer.cpp14
-rw-r--r--test/SemaCXX/conversion.cpp28
-rw-r--r--test/SemaCXX/copy-assignment.cpp9
-rw-r--r--test/SemaCXX/copy-initialization.cpp23
-rw-r--r--test/SemaCXX/cxx0x-class.cpp19
-rw-r--r--test/SemaCXX/cxx0x-compat.cpp27
-rw-r--r--test/SemaCXX/cxx0x-cursory-default-delete.cpp6
-rw-r--r--test/SemaCXX/cxx0x-defaulted-functions.cpp10
-rw-r--r--test/SemaCXX/cxx0x-deleted-default-ctor.cpp75
-rw-r--r--test/SemaCXX/cxx0x-initializer-aggregates.cpp89
-rw-r--r--test/SemaCXX/cxx0x-initializer-constructor.cpp283
-rw-r--r--test/SemaCXX/cxx0x-initializer-references.cpp87
-rw-r--r--test/SemaCXX/cxx0x-initializer-scalars.cpp84
-rw-r--r--test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp177
-rw-r--r--test/SemaCXX/cxx0x-nontrivial-union.cpp104
-rw-r--r--test/SemaCXX/cxx0x-return-init-list.cpp10
-rw-r--r--test/SemaCXX/cxx11-ast-print.cpp41
-rw-r--r--test/SemaCXX/cxx11-user-defined-literals.cpp137
-rw-r--r--test/SemaCXX/cxx98-compat-flags.cpp35
-rw-r--r--test/SemaCXX/cxx98-compat-pedantic.cpp23
-rw-r--r--test/SemaCXX/cxx98-compat.cpp273
-rw-r--r--test/SemaCXX/dcl_init_aggr.cpp2
-rw-r--r--test/SemaCXX/decl-expr-ambiguity.cpp33
-rw-r--r--test/SemaCXX/decltype-crash.cpp2
-rw-r--r--test/SemaCXX/decltype.cpp9
-rw-r--r--test/SemaCXX/default1.cpp18
-rw-r--r--test/SemaCXX/default2.cpp10
-rw-r--r--test/SemaCXX/defaulted-private-dtor.cpp56
-rw-r--r--test/SemaCXX/deleted-function.cpp24
-rw-r--r--test/SemaCXX/deleted-operator.cpp5
-rw-r--r--test/SemaCXX/dependent-auto.cpp2
-rw-r--r--test/SemaCXX/destructor.cpp2
-rw-r--r--test/SemaCXX/discrim-union.cpp118
-rw-r--r--test/SemaCXX/dr1301.cpp67
-rw-r--r--test/SemaCXX/empty-class-layout.cpp11
-rw-r--r--test/SemaCXX/enum-bitfield.cpp2
-rw-r--r--test/SemaCXX/enum-scoped.cpp107
-rw-r--r--test/SemaCXX/enum-unscoped-nonexistent.cpp39
-rw-r--r--test/SemaCXX/enum.cpp2
-rw-r--r--test/SemaCXX/exceptions.cpp28
-rw-r--r--test/SemaCXX/explicit.cpp19
-rw-r--r--test/SemaCXX/expression-traits.cpp4
-rw-r--r--test/SemaCXX/for-range-examples.cpp32
-rw-r--r--test/SemaCXX/for-range-no-std.cpp7
-rw-r--r--test/SemaCXX/format-strings-0x.cpp15
-rw-r--r--test/SemaCXX/format-strings.cpp77
-rw-r--r--test/SemaCXX/friend-out-of-line.cpp12
-rw-r--r--test/SemaCXX/friend.cpp8
-rw-r--r--test/SemaCXX/function-extern-c.cpp38
-rw-r--r--test/SemaCXX/function-redecl.cpp7
-rw-r--r--test/SemaCXX/function-type-qual.cpp14
-rw-r--r--test/SemaCXX/generalized-initializers.cpp207
-rw-r--r--test/SemaCXX/gnu-case-ranges.cpp2
-rw-r--r--test/SemaCXX/goto.cpp22
-rw-r--r--test/SemaCXX/i-c-e-cxx.cpp17
-rw-r--r--test/SemaCXX/if-empty-body.cpp35
-rw-r--r--test/SemaCXX/implicit-exception-spec.cpp7
-rw-r--r--test/SemaCXX/incomplete-call.cpp2
-rw-r--r--test/SemaCXX/indirect-goto.cpp7
-rw-r--r--test/SemaCXX/instantiate-blocks.cpp13
-rw-r--r--test/SemaCXX/invalid-member-expr.cpp4
-rw-r--r--test/SemaCXX/issue547.cpp16
-rw-r--r--test/SemaCXX/lambda-expressions.cpp150
-rw-r--r--test/SemaCXX/literal-operators.cpp8
-rw-r--r--test/SemaCXX/literal-type.cpp28
-rw-r--r--test/SemaCXX/member-class-11.cpp8
-rw-r--r--test/SemaCXX/member-expr.cpp14
-rw-r--r--test/SemaCXX/member-init.cpp3
-rw-r--r--test/SemaCXX/member-pointer.cpp2
-rw-r--r--test/SemaCXX/microsoft-cxx0x.cpp4
-rw-r--r--test/SemaCXX/missing-header.cpp4
-rw-r--r--test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp59
-rw-r--r--test/SemaCXX/namespace-alias.cpp8
-rw-r--r--test/SemaCXX/nested-name-spec.cpp7
-rw-r--r--test/SemaCXX/new-delete-0x.cpp32
-rw-r--r--test/SemaCXX/new-delete-cxx0x.cpp26
-rw-r--r--test/SemaCXX/new-delete.cpp101
-rw-r--r--test/SemaCXX/null_in_arithmetic_ops.cpp2
-rw-r--r--test/SemaCXX/nullptr.cpp48
-rw-r--r--test/SemaCXX/offsetof.cpp7
-rw-r--r--test/SemaCXX/overload-call.cpp62
-rw-r--r--test/SemaCXX/overload-member-call.cpp8
-rw-r--r--test/SemaCXX/overloaded-name.cpp5
-rw-r--r--test/SemaCXX/overloaded-operator.cpp11
-rw-r--r--test/SemaCXX/pragma-visibility.cpp23
-rw-r--r--test/SemaCXX/pseudo-destructors.cpp14
-rw-r--r--test/SemaCXX/qual-id-test.cpp4
-rw-r--r--test/SemaCXX/qualified-id-lookup.cpp5
-rw-r--r--test/SemaCXX/reinterpret-cast.cpp22
-rw-r--r--test/SemaCXX/reinterpret-fn-obj-pedantic.cpp4
-rw-r--r--test/SemaCXX/return-noreturn.cpp4
-rw-r--r--test/SemaCXX/runtimediag-ppe.cpp18
-rw-r--r--test/SemaCXX/scope-check.cpp2
-rw-r--r--test/SemaCXX/statements.cpp2
-rw-r--r--test/SemaCXX/static-assert.cpp12
-rw-r--r--test/SemaCXX/string-plus-int.cpp66
-rw-r--r--test/SemaCXX/switch.cpp23
-rw-r--r--test/SemaCXX/this.cpp4
-rw-r--r--test/SemaCXX/trailing-return-0x.cpp10
-rw-r--r--test/SemaCXX/type-traits.cpp218
-rw-r--r--test/SemaCXX/typedef-redecl.cpp39
-rw-r--r--test/SemaCXX/typeid.cpp2
-rw-r--r--test/SemaCXX/typo-correction.cpp163
-rw-r--r--test/SemaCXX/undefined-internal.cpp59
-rw-r--r--test/SemaCXX/underlying_type.cpp6
-rw-r--r--test/SemaCXX/uninit-variables.cpp2
-rw-r--r--test/SemaCXX/uninitialized.cpp52
-rw-r--r--test/SemaCXX/unknown-anytype-blocks.cpp11
-rw-r--r--test/SemaCXX/unknown-anytype.cpp4
-rw-r--r--test/SemaCXX/value-initialization.cpp7
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp7
-rw-r--r--test/SemaCXX/vector.cpp49
-rw-r--r--test/SemaCXX/vla.cpp5
-rw-r--r--test/SemaCXX/warn-bool-conversion.cpp12
-rw-r--r--test/SemaCXX/warn-empty-body.cpp271
-rw-r--r--test/SemaCXX/warn-everthing.cpp13
-rw-r--r--test/SemaCXX/warn-func-as-bool.cpp40
-rw-r--r--test/SemaCXX/warn-large-by-value-copy.cpp5
-rw-r--r--test/SemaCXX/warn-memset-bad-sizeof.cpp10
-rw-r--r--test/SemaCXX/warn-new-overaligned-2.cpp22
-rw-r--r--test/SemaCXX/warn-new-overaligned-3.cpp33
-rw-r--r--test/SemaCXX/warn-new-overaligned.cpp73
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp959
-rw-r--r--test/SemaCXX/warn-thread-safety-parsing.cpp196
-rw-r--r--test/SemaCXX/warn-unreachable.cpp31
-rw-r--r--test/SemaCXX/warn-unused-parameters.cpp10
-rw-r--r--test/SemaCXX/warn-unused-value.cpp19
-rw-r--r--test/SemaCXX/warn-unused-variables.cpp42
-rw-r--r--test/SemaCXX/warn-weak-vtables.cpp22
-rw-r--r--test/SemaCXX/zero-length-arrays.cpp26
178 files changed, 7498 insertions, 862 deletions
diff --git a/test/SemaCXX/Inputs/array-bounds-system-header.h b/test/SemaCXX/Inputs/array-bounds-system-header.h
new file mode 100644
index 0000000..07cde80
--- /dev/null
+++ b/test/SemaCXX/Inputs/array-bounds-system-header.h
@@ -0,0 +1,11 @@
+// "System header" for testing that -Warray-bounds is properly suppressed in
+// certain cases.
+
+#define BAD_MACRO_1 \
+ int i[3]; \
+ i[3] = 5
+#define BAD_MACRO_2(_b, _i) \
+ (_b)[(_i)] = 5
+#define QUESTIONABLE_MACRO(_a) \
+ sizeof(_a) > 3 ? (_a)[3] = 5 : 5
+#define NOP(x) (x)
diff --git a/test/SemaCXX/Inputs/warn-new-overaligned-3.h b/test/SemaCXX/Inputs/warn-new-overaligned-3.h
new file mode 100644
index 0000000..d2bd4d5
--- /dev/null
+++ b/test/SemaCXX/Inputs/warn-new-overaligned-3.h
@@ -0,0 +1,19 @@
+#pragma GCC system_header
+
+// This header file pretends to be <new> from the system library, for the
+// purpose of the over-aligned warnings test.
+
+void* operator new(unsigned long) {
+ return 0;
+}
+void* operator new[](unsigned long) {
+ return 0;
+}
+
+void* operator new(unsigned long, void *) {
+ return 0;
+}
+
+void* operator new[](unsigned long, void *) {
+ return 0;
+}
diff --git a/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp b/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp
new file mode 100644
index 0000000..0c7d354
--- /dev/null
+++ b/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++98 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
+
+
+//MSVC allows forward enum declaration
+enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
+ENUM *var = 0;
+ENUM var2 = (ENUM)3;
+enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}}
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp
index dfc47d6..3634fa3 100644
--- a/test/SemaCXX/MicrosoftCompatibility.cpp
+++ b/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
@@ -23,7 +23,7 @@ namespace ms_protected_scope {
int jump_over_variable_init(bool b) {
if (b)
- goto foo; // expected-warning {{illegal goto into protected scope}}
+ goto foo; // expected-warning {{goto into protected scope}}
C c; // expected-note {{jump bypasses variable initialization}}
foo:
return 1;
@@ -35,7 +35,7 @@ struct Y {
void jump_over_var_with_dtor() {
goto end; // expected-warning{{goto into protected scope}}
- Y y; // expected-note {{jump bypasses variable initialization}}
+ Y y; // expected-note {{jump bypasses variable with a non-trivial destructor}}
end:
;
}
@@ -51,7 +51,7 @@ void jump_over_var_with_dtor() {
void exception_jump() {
- goto l2; // expected-error {{illegal goto into protected scope}}
+ goto l2; // expected-error {{goto into protected scope}}
try { // expected-note {{jump bypasses initialization of try block}}
l2: ;
} catch(int) {
@@ -68,91 +68,109 @@ int jump_over_indirect_goto() {
}
+namespace PR11826 {
+ struct pair {
+ pair(int v) { }
+ void operator=(pair&& rhs) { }
+ };
+ void f() {
+ pair p0(3);
+ pair p = p0;
+ }
+}
+
+namespace PR11826_for_symmetry {
+ struct pair {
+ pair(int v) { }
+ pair(pair&& rhs) { }
+ };
+ void f() {
+ pair p0(3);
+ pair p(4);
+ p = p0;
+ }
+}
+
+namespace ms_using_declaration_bug {
+
+class A {
+public:
+ int f();
+};
+
+class B : public A {
+private:
+ using A::f;
+};
+
+class C : public B {
+private:
+ using B::f; // expected-warning {{using declaration referring to inaccessible member 'ms_using_declaration_bug::B::f' (which refers to accessible member 'ms_using_declaration_bug::A::f') is a Microsoft compatibility extension}}
+};
+
+}
+
+
+namespace MissingTypename {
+
+template<class T> class A {
+public:
+ typedef int TYPE;
+};
+
+template<class T> class B {
+public:
+ typedef int TYPE;
+};
-namespace ms_using_declaration_bug {
-
-class A {
-public:
- int f();
-};
-
-class B : public A {
-private:
- using A::f;
-};
-
-class C : public B {
-private:
- using B::f; // expected-warning {{using declaration refers to inaccessible member 'ms_using_declaration_bug::B::f', which refers to accessible member 'ms_using_declaration_bug::A::f', accepted for Microsoft compatibility}}
-};
-
-}
-
-
-namespace MissingTypename {
-
-template<class T> class A {
-public:
- typedef int TYPE;
-};
-
-template<class T> class B {
-public:
- typedef int TYPE;
-};
-
-
-template<class T, class U>
-class C : private A<T>, public B<U> {
-public:
- typedef A<T> Base1;
- typedef B<U> Base2;
- typedef A<U> Base3;
-
- A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}}
- Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}}
-
- B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}}
- Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}}
-
- A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}}
- Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}}
- };
-
-class D {
-public:
- typedef int Type;
-};
-
-template <class T>
-void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}}
-{
- const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}}
-}
-
-template void function_missing_typename<D>(const D::Type param);
-
-}
-
-
-
-namespace lookup_dependent_bases_id_expr {
-
-template<class T> class A {
-public:
- int var;
-};
-
-
-template<class T>
-class B : public A<T> {
-public:
- void f() {
- var = 3;
- }
-};
-
-template class B<int>;
-
-} \ No newline at end of file
+template<class T, class U>
+class C : private A<T>, public B<U> {
+public:
+ typedef A<T> Base1;
+ typedef B<U> Base2;
+ typedef A<U> Base3;
+
+ A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}}
+ Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}}
+
+ B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}}
+ Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}}
+
+ A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}}
+ Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}}
+ };
+
+class D {
+public:
+ typedef int Type;
+};
+
+template <class T>
+void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}}
+{
+ const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}}
+}
+
+template void function_missing_typename<D>(const D::Type param);
+
+}
+
+enum ENUM2 {
+ ENUM2_a = (enum ENUM2) 4,
+ ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
+ ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
+};
+
+
+namespace PR11791 {
+ template<class _Ty>
+ void del(_Ty *_Ptr) {
+ _Ptr->~_Ty(); // expected-warning {{pseudo-destructors on type void are a Microsoft extension}}
+ }
+
+ void f() {
+ int* a = 0;
+ del((void*)a); // expected-note {{in instantiation of function template specialization}}
+ }
+}
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index 63e058b..0b72cd3 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -92,18 +92,8 @@ void m1() {
h1(&M::subtractP);
}
-//MSVC allows forward enum declaration
-enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
-ENUM *var = 0;
-ENUM var2 = (ENUM)3;
-enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}}
-enum ENUM2 {
- ENUM2_a = (enum ENUM2) 4,
- ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
- ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
-};
void f(long long);
@@ -203,3 +193,13 @@ void f()
}
+struct PR11150 {
+ class X {
+ virtual void f() = 0;
+ };
+
+ int array[__is_abstract(X)? 1 : -1];
+};
+
+void f() { int __except = 0; }
+
diff --git a/test/SemaCXX/PR10177.cpp b/test/SemaCXX/PR10177.cpp
new file mode 100644
index 0000000..8d745de
--- /dev/null
+++ b/test/SemaCXX/PR10177.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+template<typename T, typename U, U> using alias_ref = T;
+template<typename T, typename U, U> void func_ref() {}
+template<typename T, typename U, U> struct class_ref {};
+
+template<int N>
+struct U {
+ static int a;
+};
+
+template<int N> struct S; // expected-note 2{{here}}
+
+template<int N>
+int U<N>::a = S<N>::kError; // expected-error 2{{undefined}}
+
+template<typename T>
+void f() {
+ // FIXME: The standard suggests that U<0>::a is odr-used by this expression,
+ // but it's not entirely clear that's the right behaviour.
+ (void)alias_ref<int, int&, U<0>::a>();
+ (void)func_ref<int, int&, U<1>::a>(); // expected-note {{here}}
+ (void)class_ref<int, int&, U<2>::a>(); // expected-note {{here}}
+};
+
+int main() {
+ f<int>(); // expected-note 2{{here}}
+}
+
+namespace N {
+ template<typename T> struct S { static int n; };
+ template<typename T> int S<T>::n = 5;
+ void g(int*);
+ template<typename T> int f() {
+ int k[S<T>::n];
+ g(k);
+ return k[3];
+ }
+ int j = f<int>();
+}
diff --git a/test/SemaCXX/PR10447.cpp b/test/SemaCXX/PR10447.cpp
new file mode 100644
index 0000000..08644ad
--- /dev/null
+++ b/test/SemaCXX/PR10447.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -verify %s
+
+// PR12223
+namespace test1 {
+ namespace N {
+ extern "C" void f(struct S*);
+ void g(S*);
+ }
+ namespace N {
+ void f(struct S *s) {
+ g(s);
+ }
+ }
+}
+
+// PR10447
+namespace test2 {
+ extern "C" {
+ void f(struct Bar*) { }
+ test2::Bar *ptr;
+ }
+}
diff --git a/test/SemaCXX/PR11358.cpp b/test/SemaCXX/PR11358.cpp
new file mode 100644
index 0000000..9c49227
--- /dev/null
+++ b/test/SemaCXX/PR11358.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 %s -verify
+// PR11358
+
+namespace test1 {
+ template<typename T>
+ struct container {
+ class iterator {};
+ iterator begin() { return iterator(); }
+ };
+
+ template<typename T>
+ struct Test {
+ typedef container<T> Container;
+ void test() {
+ Container::iterator i = c.begin(); // expected-error{{missing 'typename'}}
+ }
+ Container c;
+ };
+}
+
+namespace test2 {
+ template <typename Key, typename Value>
+ class hash_map {
+ class const_iterator { void operator++(); };
+ const_iterator begin() const;
+ const_iterator end() const;
+ };
+
+ template <typename KeyType, typename ValueType>
+ void MapTest(hash_map<KeyType, ValueType> map) {
+ for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); // expected-error{{missing 'typename'}}
+ it != map.end(); it++) {
+ }
+ }
+}
+
+namespace test3 {
+ template<typename T>
+ struct container {
+ class iterator {};
+ };
+
+ template<typename T>
+ struct Test {
+ typedef container<T> Container;
+ void test() {
+ Container::iterator const i; // expected-error{{missing 'typename'}}
+ }
+ Container c;
+ };
+}
diff --git a/test/SemaCXX/PR12481.cpp b/test/SemaCXX/PR12481.cpp
new file mode 100644
index 0000000..9487e4d
--- /dev/null
+++ b/test/SemaCXX/PR12481.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -x c++ -fsyntax-only %s
+
+class C1 { };
+class C2 { };
+template<class TrieData> struct BinaryTrie {
+ ~BinaryTrie() {
+ (void)(({
+ static int x = 5;
+ }
+ ));
+ }
+};
+class FooTable {
+ BinaryTrie<C1> c1_trie_;
+ BinaryTrie<C2> c2_trie_;
+};
+FooTable* foo = new FooTable;
diff --git a/test/SemaCXX/PR8385.cpp b/test/SemaCXX/PR8385.cpp
new file mode 100644
index 0000000..77a117a
--- /dev/null
+++ b/test/SemaCXX/PR8385.cpp
@@ -0,0 +1,7 @@
+// RUN: not %clang_cc1 -fsyntax-only %s
+
+// don't crash on this, but don't constrain our diagnostics here as they're
+// currently rather poor (we even accept things like "template struct {}").
+// Other, explicit tests, should verify the relevant behavior of template
+// instantiation.
+struct{template struct{
diff --git a/test/SemaCXX/PR9460.cpp b/test/SemaCXX/PR9460.cpp
index 2cc435e..0dd8446 100644
--- a/test/SemaCXX/PR9460.cpp
+++ b/test/SemaCXX/PR9460.cpp
@@ -8,11 +8,11 @@ struct basic_string{
basic_string(aT*);
};
-struct runtime_error{ // expected-note {{candidate constructor}}
- runtime_error( // expected-note {{candidate constructor}}
+struct runtime_error{
+ runtime_error(
basic_string<char> struct{ // expected-error {{cannot combine with previous 'type-name' declaration specifier}}
a(){ // expected-error {{requires a type specifier}}
- runtime_error(0); // expected-error {{no matching conversion}}
+ runtime_error(0);
}
}
);
diff --git a/test/SemaCXX/PR9461.cpp b/test/SemaCXX/PR9461.cpp
index ce17931..beed348 100644
--- a/test/SemaCXX/PR9461.cpp
+++ b/test/SemaCXX/PR9461.cpp
@@ -26,7 +26,7 @@ basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT*,const _Alloc&)
:us(_S_construct)
{string a;}
-struct runtime_error{runtime_error(string);}; // expected-note 2 {{candidate constructor}}
+struct runtime_error{runtime_error(string);};
-struct system_error:runtime_error{ // expected-note {{to match}} expected-note {{specified here}}
-system_error():time_error("" // expected-error 4 {{expected}} expected-error {{initializer}} expected-note {{to match}} expected-error {{no matching constructor}}
+struct system_error:runtime_error{ // expected-note {{to match}}
+system_error():time_error("" // expected-error 3 {{expected}} expected-note {{to match}}
diff --git a/test/SemaCXX/PR9572.cpp b/test/SemaCXX/PR9572.cpp
index b0bbfa6..b475b57 100644
--- a/test/SemaCXX/PR9572.cpp
+++ b/test/SemaCXX/PR9572.cpp
@@ -3,7 +3,7 @@ class Base {
virtual ~Base(); // expected-note {{implicitly declared private here}}
};
struct Foo : public Base { // expected-error {{base class 'Base' has private destructor}}
- const int kBlah = 3; // expected-warning {{accepted as a C++11 extension}}
+ const int kBlah = 3; // expected-warning {{is a C++11 extension}}
Foo();
};
struct Bar : public Foo {
diff --git a/test/SemaCXX/__null.cpp b/test/SemaCXX/__null.cpp
index 1989a45..56e59c0 100644
--- a/test/SemaCXX/__null.cpp
+++ b/test/SemaCXX/__null.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify
-// RUN: %clang_cc1 -triple i686-unknown-unknown %s -fsyntax-only -verify
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -Wno-null-conversion -fsyntax-only -verify
+// RUN: %clang_cc1 -triple i686-unknown-unknown %s -Wno-null-conversion -fsyntax-only -verify
void f() {
int* i = __null;
diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp
index 6115ff6..18ad301 100644
--- a/test/SemaCXX/access.cpp
+++ b/test/SemaCXX/access.cpp
@@ -28,7 +28,7 @@ namespace test1 {
private:
class X; // expected-note {{previously declared 'private' here}}
public:
- class X; // expected-error {{ 'X' redeclared with 'public' access}}
+ class X; // expected-error {{'X' redeclared with 'public' access}}
class X {};
};
}
diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp
index a36fd58..096f748 100644
--- a/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -13,9 +13,9 @@ int (*pfe)(...) = &f; // expected-error{{address of overloaded function 'f' d
int (&rfi)(int) = f; // selects f(int)
int (&rfd)(double) = f; // selects f(double)
-void g(int (*fp)(int)); // expected-note{{note: candidate function}}
+void g(int (*fp)(int)); // expected-note{{candidate function}}
void g(int (*fp)(float));
-void g(int (*fp)(double)); // expected-note{{note: candidate function}}
+void g(int (*fp)(double)); // expected-note{{candidate function}}
int g1(int);
int g1(char);
@@ -29,7 +29,7 @@ int g3(char);
void g_test() {
g(g1);
- g(g2); // expected-error{{call to 'g' is ambiguous; candidates are:}}
+ g(g2); // expected-error{{call to 'g' is ambiguous}}
g(g3);
}
@@ -57,8 +57,7 @@ struct B
struct C {
C &getC() {
- // FIXME: this error message is terrible
- return makeAC; // expected-error{{cannot bind to a value of unrelated type}}
+ return makeAC; // expected-error{{reference to non-static member function must be called}}
}
C &makeAC();
@@ -99,8 +98,10 @@ namespace PR7971 {
}
namespace PR8033 {
- template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note 2{{candidate function [with T1 = const int, T2 = int]}}
- template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note 2{{candidate function [with T1 = int, T2 = const int]}}
+ template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} \
+ // expected-note{{candidate function}}
+ template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} \
+ // expected-note{{candidate function}}
int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} \
// expected-error{{address of overloaded function 'f' is ambiguous}}
@@ -146,3 +147,64 @@ namespace PR7425 {
bar2();
}
}
+
+namespace test1 {
+ void fun(int x) {}
+
+ void parameter_number() {
+ void (*ptr1)(int, int) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(int, int)' with an rvalue of type 'void (*)(int)': different number of parameters (2 vs 1)}}
+ void (*ptr2)(int, int);
+ ptr2 = &fun; // expected-error {{assigning to 'void (*)(int, int)' from incompatible type 'void (*)(int)': different number of parameters (2 vs 1)}}
+ }
+
+ void parameter_mismatch() {
+ void (*ptr1)(double) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(double)' with an rvalue of type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}}
+ void (*ptr2)(double);
+ ptr2 = &fun; // expected-error {{assigning to 'void (*)(double)' from incompatible type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}}
+ }
+
+ void return_type_test() {
+ int (*ptr1)(int) = &fun; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an rvalue of type 'void (*)(int)': different return type ('int' vs 'void')}}
+ int (*ptr2)(int);
+ ptr2 = &fun; // expected-error {{assigning to 'int (*)(int)' from incompatible type 'void (*)(int)': different return type ('int' vs 'void')}}
+ }
+
+ int foo(double x, double y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}
+ int foo(int x, int y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}
+ int foo(double x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'double')}}
+ double foo(float x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}
+ double foo(int x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}
+ double foo(float x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'float')}}
+ double foo(int x) {return 0;} // expected-note {{candidate function has different return type ('int' expected but has 'double')}}
+
+ int (*ptr)(int) = &foo; // expected-error {{address of overloaded function 'foo' does not match required type 'int (int)'}}
+
+ struct Qualifiers {
+ void N() {};
+ void C() const {};
+ void V() volatile {};
+ void R() __restrict {};
+ void CV() const volatile {};
+ void CR() const __restrict {};
+ void VR() volatile __restrict {};
+ void CVR() const volatile __restrict {};
+ };
+
+
+ void QualifierTest() {
+ void (Qualifiers::*X)();
+ X = &Qualifiers::C; // expected-error {{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const': different qualifiers (none vs const)}}
+ X = &Qualifiers::V; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile': different qualifiers (none vs volatile)}}
+ X = &Qualifiers::R; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() restrict': different qualifiers (none vs restrict)}}
+ X = &Qualifiers::CV; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile': different qualifiers (none vs const and volatile)}}
+ X = &Qualifiers::CR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const restrict': different qualifiers (none vs const and restrict)}}
+ X = &Qualifiers::VR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile restrict': different qualifiers (none vs volatile and restrict)}}
+ X = &Qualifiers::CVR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile restrict': different qualifiers (none vs const, volatile, and restrict)}}
+ }
+
+ struct Dummy {
+ void N() {};
+ };
+
+ void (Qualifiers::*X)() = &Dummy::N; // expected-error{{cannot initialize a variable of type 'void (test1::Qualifiers::*)()' with an rvalue of type 'void (test1::Dummy::*)()': different classes ('test1::Qualifiers' vs 'test1::Dummy')}}
+}
diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp
index 3c0e448..885bf70 100644
--- a/test/SemaCXX/aggregate-initialization.cpp
+++ b/test/SemaCXX/aggregate-initialization.cpp
@@ -1,33 +1,33 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// Verify that we can't initialize non-aggregates with an initializer
-// list.
+// Verify that using an initializer list for a non-aggregate looks for
+// constructors..
// Note that due to a (likely) standard bug, this is technically an aggregate,
// but we do not treat it as one.
-struct NonAggr1 {
- NonAggr1(int) { }
+struct NonAggr1 { // expected-note 2 {{candidate constructor}}
+ NonAggr1(int, int) { } // expected-note {{candidate constructor}}
int m;
};
struct Base { };
-struct NonAggr2 : public Base {
+struct NonAggr2 : public Base { // expected-note 3 {{candidate constructor}}
int m;
};
-class NonAggr3 {
+class NonAggr3 { // expected-note 3 {{candidate constructor}}
int m;
};
-struct NonAggr4 {
+struct NonAggr4 { // expected-note 3 {{candidate constructor}}
int m;
virtual void f();
};
-NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}}
-NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}}
-NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}}
-NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}}
+NonAggr1 na1 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr1'}}
+NonAggr2 na2 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr2'}}
+NonAggr3 na3 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr3'}}
+NonAggr4 na4 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr4'}}
// PR5817
typedef int type[][2];
diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp
index 6cff420..484dd33 100644
--- a/test/SemaCXX/alias-template.cpp
+++ b/test/SemaCXX/alias-template.cpp
@@ -12,12 +12,12 @@ namespace IllegalTypeIds {
template<typename U> using C = virtual void(int n); // expected-error {{type name does not allow function specifier}}
template<typename U> using D = explicit void(int n); // expected-error {{type name does not allow function specifier}}
template<typename U> using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}}
- // FIXME: this is illegal; we incorrectly accept it for typedefs too.
- template<typename U> using F = void(*)(int n) &&; // expected-err
+ template<typename U> using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}}
template<typename U> using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
+ template<typename U> using H = constexpr int; // expected-error {{type name does not allow constexpr specifier}}
- template<typename U> using H = void(int n); // ok
- template<typename U> using I = void(int n) &&; // ok
+ template<typename U> using Y = void(int n); // ok
+ template<typename U> using Z = void(int n) &&; // ok
}
namespace IllegalSyntax {
diff --git a/test/SemaCXX/altivec.cpp b/test/SemaCXX/altivec.cpp
index 504eb1b..39421b7 100644
--- a/test/SemaCXX/altivec.cpp
+++ b/test/SemaCXX/altivec.cpp
@@ -66,3 +66,13 @@ void test2()
(++vi)[1]=1;
template_f(vi);
}
+
+namespace LValueToRValueConversions {
+ struct Struct {
+ float f();
+ int n();
+ };
+
+ vector float initFloat = (vector float)(Struct().f); // expected-error {{did you mean to call it}}
+ vector int initInt = (vector int)(Struct().n); // expected-error {{did you mean to call it}}
+}
diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp
index dfa284a..19a88d7 100644
--- a/test/SemaCXX/anonymous-struct.cpp
+++ b/test/SemaCXX/anonymous-struct.cpp
@@ -4,8 +4,13 @@ struct S {
S(); // expected-note {{because type 'S' has a user-declared constructor}}
};
+struct { // expected-error {{anonymous structs and classes must be class members}}
+};
+
struct E {
struct {
S x; // expected-error {{anonymous struct member 'x' has a non-trivial constructor}}
};
+ static struct {
+ };
};
diff --git a/test/SemaCXX/array-bounds-ptr-arith.cpp b/test/SemaCXX/array-bounds-ptr-arith.cpp
index ce1ace6..16e2567 100644
--- a/test/SemaCXX/array-bounds-ptr-arith.cpp
+++ b/test/SemaCXX/array-bounds-ptr-arith.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -Warray-bounds-pointer-arithmetic %s
+// RUN: %clang_cc1 -verify -Wno-string-plus-int -Warray-bounds-pointer-arithmetic %s
void swallow (const char *x) { (void)x; }
void test_pointer_arithmetic(int n) {
diff --git a/test/SemaCXX/array-bounds-system-header.cpp b/test/SemaCXX/array-bounds-system-header.cpp
new file mode 100644
index 0000000..34de5b5
--- /dev/null
+++ b/test/SemaCXX/array-bounds-system-header.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -isystem %S/Inputs -verify %s
+#include <array-bounds-system-header.h>
+void test_system_header_macro() {
+ BAD_MACRO_1; // no-warning
+ char a[3]; // expected-note 2 {{declared here}}
+ BAD_MACRO_2(a, 3); // expected-warning {{array index 3}}
+ QUESTIONABLE_MACRO(a);
+ NOP(a[3] = 5); // expected-warning {{array index 3}}
+}
diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp
index 555ac33..57a9e3d 100644
--- a/test/SemaCXX/array-bounds.cpp
+++ b/test/SemaCXX/array-bounds.cpp
@@ -4,16 +4,20 @@ int foo() {
int x[2]; // expected-note 4 {{array 'x' declared here}}
int y[2]; // expected-note 2 {{array 'y' declared here}}
int z[1]; // expected-note {{array 'z' declared here}}
+ int w[1][1]; // expected-note {{array 'w' declared here}}
+ int v[1][1][1]; // expected-note {{array 'v' declared here}}
int *p = &y[2]; // no-warning
(void) sizeof(x[2]); // no-warning
- y[2] = 2; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}}
- z[1] = 'x'; // expected-warning {{array index of '1' indexes past the end of an array (that contains 1 element)}}
- return x[2] + // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}}
- y[-1] + // expected-warning {{array index of '-1' indexes before the beginning of the array}}
- x[sizeof(x)] + // expected-warning {{array index of '8' indexes past the end of an array (that contains 2 elements)}}
- x[sizeof(x) / sizeof(x[0])] + // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}}
+ y[2] = 2; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
+ z[1] = 'x'; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}}
+ w[0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}}
+ v[0][0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}}
+ return x[2] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
+ y[-1] + // expected-warning {{array index -1 is before the beginning of the array}}
+ x[sizeof(x)] + // expected-warning {{array index 8 is past the end of the array (which contains 2 elements)}}
+ x[sizeof(x) / sizeof(x[0])] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
x[sizeof(x) / sizeof(x[0]) - 1] + // no-warning
- x[sizeof(x[2])]; // expected-warning {{array index of '4' indexes past the end of an array (that contains 2 elements)}}
+ x[sizeof(x[2])]; // expected-warning {{array index 4 is past the end of the array (which contains 2 elements)}}
}
// This code example tests that -Warray-bounds works with arrays that
@@ -27,7 +31,7 @@ void f1(int a[1]) {
}
void f2(const int (&a)[2]) { // expected-note {{declared here}}
- int val = a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}}
+ int val = a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
}
void test() {
@@ -40,33 +44,33 @@ void test() {
short a[2]; // expected-note 4 {{declared here}}
char c[4];
} u;
- u.a[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}}
+ u.a[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
u.c[3] = 1; // no warning
short *p = &u.a[2]; // no warning
- p = &u.a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}}
- *(&u.a[2]) = 1; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}}
- *(&u.a[3]) = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}}
+ p = &u.a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
+ *(&u.a[2]) = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
+ *(&u.a[3]) = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
*(&u.c[3]) = 1; // no warning
const int const_subscript = 3;
int array[2]; // expected-note {{declared here}}
- array[const_subscript] = 0; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}}
+ array[const_subscript] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
int *ptr;
ptr[3] = 0; // no warning for pointer references
int array2[] = { 0, 1, 2 }; // expected-note 2 {{declared here}}
- array2[3] = 0; // expected-warning {{array index of '3' indexes past the end of an array (that contains 3 elements)}}
- array2[2+2] = 0; // expected-warning {{array index of '4' indexes past the end of an array (that contains 3 elements)}}
+ array2[3] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 3 elements)}}
+ array2[2+2] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}}
const char *str1 = "foo";
char c1 = str1[5]; // no warning for pointers
const char str2[] = "foo"; // expected-note {{declared here}}
- char c2 = str2[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 4 elements)}}
+ char c2 = str2[5]; // expected-warning {{array index 5 is past the end of the array (which contains 4 elements)}}
int (*array_ptr)[2];
- (*array_ptr)[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}}
+ (*array_ptr)[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}}
}
template <int I> struct S {
@@ -74,8 +78,8 @@ template <int I> struct S {
};
template <int I> void f() {
S<3> s;
- s.arr[4] = 0; // expected-warning {{array index of '4' indexes past the end of an array (that contains 3 elements)}}
- s.arr[I] = 0; // expected-warning {{array index of '5' indexes past the end of an array (that contains 3 elements)}}
+ s.arr[4] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}}
+ s.arr[I] = 0; // expected-warning {{array index 5 is past the end of the array (which contains 3 elements)}}
}
void test_templates() {
@@ -88,13 +92,13 @@ void test_templates() {
int test_no_warn_macro_unreachable() {
int arr[SIZE]; // expected-note {{array 'arr' declared here}}
return ARR_IN_MACRO(0, arr, SIZE) + // no-warning
- ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index of '10' indexes past the end of an array (that contains 10 elements)}}
+ ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index 10 is past the end of the array (which contains 10 elements)}}
}
// This exhibited an assertion failure for a 32-bit build of Clang.
int test_pr9240() {
short array[100]; // expected-note {{array 'array' declared here}}
- return array[(unsigned long long) 100]; // expected-warning {{array index of '100' indexes past the end of an array (that contains 100 elements)}}
+ return array[(unsigned long long) 100]; // expected-warning {{array index 100 is past the end of the array (which contains 100 elements)}}
}
// PR 9284 - a template parameter can cause an array bounds access to be
@@ -112,7 +116,7 @@ void pr9284b() {
int arr[3 + (extendArray ? 1 : 0)]; // expected-note {{array 'arr' declared here}}
if (!extendArray)
- arr[3] = 42; // expected-warning{{array index of '3' indexes past the end of an array (that contains 3 elements)}}
+ arr[3] = 42; // expected-warning{{array index 3 is past the end of the array (which contains 3 elements)}}
}
void test_pr9284() {
@@ -131,7 +135,7 @@ int test_sizeof_as_condition(int flag) {
int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}}
if (flag)
return sizeof(char) != sizeof(char) ? arr[2] : arr[1];
- return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}}
+ return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
}
void test_switch() {
@@ -143,7 +147,7 @@ void test_switch() {
}
case 4: {
int arr[2]; // expected-note {{array 'arr' declared here}}
- arr[2] = 1; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}}
+ arr[2] = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
break;
}
default: {
@@ -186,10 +190,19 @@ namespace tailpad {
int x;
char c2[1];
};
-
- char bar(struct foo *F) {
- return F->c1[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}}
- return F->c2[3]; // no warning, foo could have tail padding allocated.
+
+ class baz {
+ public:
+ char c1[1]; // expected-note {{declared here}}
+ int x;
+ char c2[1];
+ };
+
+ char bar(struct foo *F, baz *B) {
+ return F->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
+ F->c2[3] + // no warning, foo could have tail padding allocated.
+ B->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
+ B->c2[3]; // no warning, baz could have tail padding allocated.
}
}
@@ -199,20 +212,20 @@ namespace metaprogramming {
template <int N> struct bar { char c[N]; }; // expected-note {{declared here}}
char test(foo *F, bar<1> *B) {
- return F->c[3] + // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}}
- B->c[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}}
+ return F->c[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
+ B->c[3]; // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}}
}
}
void bar(int x) {}
int test_more() {
int foo[5]; // expected-note 5 {{array 'foo' declared here}}
- bar(foo[5]); // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}}
- ++foo[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}}
- if (foo[6]) // expected-warning {{array index of '6' indexes past the end of an array (that contains 5 elements)}}
- return --foo[6]; // expected-warning {{array index of '6' indexes past the end of an array (that contains 5 elements)}}
+ bar(foo[5]); // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}}
+ ++foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}}
+ if (foo[6]) // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}}
+ return --foo[6]; // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}}
else
- return foo[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}}
+ return foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}}
}
void test_pr10771() {
@@ -221,7 +234,7 @@ void test_pr10771() {
((char*)foo)[sizeof(foo) - 1] = '\0'; // no-warning
*(((char*)foo) + sizeof(foo) - 1) = '\0'; // no-warning
- ((char*)foo)[sizeof(foo)] = '\0'; // expected-warning {{array index of '32768' indexes past the end of an array (that contains 32768 elements)}}
+ ((char*)foo)[sizeof(foo)] = '\0'; // expected-warning {{array index 32768 is past the end of the array (which contains 32768 elements)}}
// TODO: This should probably warn, too.
*(((char*)foo) + sizeof(foo)) = '\0'; // no-warning
@@ -232,6 +245,11 @@ int test_pr11007_aux(const char * restrict, ...);
// Test checking with varargs.
void test_pr11007() {
double a[5]; // expected-note {{array 'a' declared here}}
- test_pr11007_aux("foo", a[1000]); // expected-warning {{array index of '1000' indexes past the end of an array}}
+ test_pr11007_aux("foo", a[1000]); // expected-warning {{array index 1000 is past the end of the array}}
}
+void test_rdar10916006(void)
+{
+ int a[128]; // expected-note {{array 'a' declared here}}
+ a[(unsigned char)'\xA1'] = 1; // expected-warning {{array index 161 is past the end of the array}}
+}
diff --git a/test/SemaCXX/atomic-type.cxx b/test/SemaCXX/atomic-type.cxx
new file mode 100644
index 0000000..18707eb
--- /dev/null
+++ b/test/SemaCXX/atomic-type.cxx
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -verify %s
+
+template<typename T> struct atomic {
+ _Atomic(T) value;
+};
+
+template<typename T> struct user {
+ struct inner { char n[sizeof(T)]; };
+ atomic<inner> i;
+};
+
+user<int> u;
+
+// Test overloading behavior of atomics.
+struct A { };
+
+int &ovl1(_Atomic(int));
+long &ovl1(_Atomic(long));
+float &ovl1(_Atomic(float));
+double &ovl1(_Atomic(A const *const *));
+short &ovl1(_Atomic(A **));
+
+void test_overloading(int i, float f, _Atomic(int) ai, _Atomic(float) af,
+ long l, _Atomic(long) al, A const *const *acc,
+ A const ** ac, A **a) {
+ int& ir1 = ovl1(i);
+ int& ir2 = ovl1(ai);
+ long& lr1 = ovl1(l);
+ long& lr2 = ovl1(al);
+ float &fr1 = ovl1(f);
+ float &fr2 = ovl1(af);
+ double &dr1 = ovl1(acc);
+ double &dr2 = ovl1(ac);
+ short &sr1 = ovl1(a);
+}
diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp
index de9d7d1..4281895 100644
--- a/test/SemaCXX/attr-cxx0x.cpp
+++ b/test/SemaCXX/attr-cxx0x.cpp
@@ -9,6 +9,12 @@ struct align_member {
int member alignas(8);
};
+template <unsigned A> struct alignas(A) align_class_template {};
+
+// FIXME: these should not error
+template <typename... T> alignas(T...) struct align_class_temp_pack_type {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}}
+template <unsigned... A> alignas(A...) struct align_class_temp_pack_expr {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}}
+
typedef char align_typedef alignas(8);
template<typename T> using align_alias_template = align_typedef;
@@ -18,4 +24,9 @@ static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
static_assert(alignof(align_member) == 8, "quuux's alignment is wrong");
static_assert(sizeof(align_member) == 8, "quuux's size is wrong");
static_assert(alignof(align_typedef) == 8, "typedef's alignment is wrong");
+static_assert(alignof(align_class_template<8>) == 8, "template's alignment is wrong");
+static_assert(alignof(align_class_template<16>) == 16, "template's alignment is wrong");
+// FIXME: enable these tests
+// static_assert(alignof(align_class_temp_pack_type<short, int, long>) == alignof(long), "template's alignment is wrong");
+// static_assert(alignof(align_class_temp_pack_expr<8, 16, 32>) == 32, "template's alignment is wrong");
static_assert(alignof(align_alias_template<int>) == 8, "alias template's alignment is wrong");
diff --git a/test/SemaCXX/attr-declspec-ignored.cpp b/test/SemaCXX/attr-declspec-ignored.cpp
new file mode 100644
index 0000000..0503750
--- /dev/null
+++ b/test/SemaCXX/attr-declspec-ignored.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+namespace test1 {
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}}
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}}
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \
+ // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}}
+}
+
+namespace test2 {
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) class A {} a;
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b;
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c;
+ __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d;
+}
diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp
index 945aff3..46568aa 100644
--- a/test/SemaCXX/attr-deprecated.cpp
+++ b/test/SemaCXX/attr-deprecated.cpp
@@ -198,7 +198,7 @@ namespace test6 {
};
void testA() {
A x; // expected-warning {{'A' is deprecated}}
- x = a0; // expected-warning {{'A' is deprecated}}
+ x = a0; // expected-warning {{'a0' is deprecated}}
}
enum B {
@@ -218,7 +218,7 @@ namespace test6 {
};
void testC() {
C<int>::Enum x; // expected-warning {{'Enum' is deprecated}}
- x = C<int>::c0; // expected-warning {{'Enum' is deprecated}}
+ x = C<int>::c0; // expected-warning {{'c0' is deprecated}}
}
template <class T> struct D {
diff --git a/test/SemaCXX/attr-sentinel.cpp b/test/SemaCXX/attr-sentinel.cpp
index 56c8f88..92c6e21 100644
--- a/test/SemaCXX/attr-sentinel.cpp
+++ b/test/SemaCXX/attr-sentinel.cpp
@@ -1,6 +1,23 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+
void f(int, ...) __attribute__((sentinel));
void g() {
f(1, 2, __null);
}
+
+typedef __typeof__(sizeof(int)) size_t;
+
+struct S {
+ S(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}}
+ void a(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}}
+ void* operator new(size_t,...) __attribute__((sentinel)); // expected-note {{marked sentinel}}
+ void operator()(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}}
+};
+
+void class_test() {
+ S s(1,2,3); // expected-warning {{missing sentinel in function call}}
+ S* s2 = new (1,2,3) S(1, __null); // expected-warning {{missing sentinel in function call}}
+ s2->a(1,2,3); // expected-warning {{missing sentinel in function call}}
+ s(1,2,3); // expected-warning {{missing sentinel in function call}}
+}
diff --git a/test/SemaCXX/auto-cxx98.cpp b/test/SemaCXX/auto-cxx98.cpp
index 6c401ba..1e28d06 100644
--- a/test/SemaCXX/auto-cxx98.cpp
+++ b/test/SemaCXX/auto-cxx98.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wc++11-compat
void f() {
auto int a; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}}
int auto b; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}}
diff --git a/test/SemaCXX/blocks-1.cpp b/test/SemaCXX/blocks-1.cpp
index 29de1e6..1b15094 100644
--- a/test/SemaCXX/blocks-1.cpp
+++ b/test/SemaCXX/blocks-1.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks
+// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++11
extern "C" int exit(int);
@@ -43,3 +43,16 @@ namespace rdar8134521 {
P = (int(^)(int))((void*)1);
}
}
+
+namespace rdar11055105 {
+ struct A {
+ void foo();
+ };
+
+ template <class T> void foo(T &x) noexcept(noexcept(x.foo()));
+
+ void (^block)() = ^{
+ A a;
+ foo(a);
+ };
+}
diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp
index 3f1d6a8..7773c08 100644
--- a/test/SemaCXX/c99-variable-length-array.cpp
+++ b/test/SemaCXX/c99-variable-length-array.cpp
@@ -14,8 +14,8 @@ struct POD {
// We allow VLAs of POD types, only.
void vla(int N) {
- int array1[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
- POD array2[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ int array1[N]; // expected-warning{{variable length arrays are a C99 feature}}
+ POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}}
NonPOD array3[N]; // expected-error{{variable length array of non-POD element type 'NonPOD'}}
NonPOD2 array4[N][3]; // expected-error{{variable length array of non-POD element type 'NonPOD2'}}
}
@@ -23,7 +23,7 @@ void vla(int N) {
/// Warn about VLAs in templates.
template<typename T>
void vla_in_template(int N, T t) {
- int array1[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ int array1[N]; // expected-warning{{variable length arrays are a C99 feature}}
}
struct HasConstantValue {
@@ -36,7 +36,7 @@ struct HasNonConstantValue {
template<typename T>
void vla_in_template(T t) {
- int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature}}
}
template void vla_in_template<HasConstantValue>(HasConstantValue);
@@ -47,14 +47,14 @@ template<typename T> struct X0 { };
// Cannot use any variably-modified type with a template parameter or
// argument.
void inst_with_vla(int N) {
- int array[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ int array[N]; // expected-warning{{variable length arrays are a C99 feature}}
X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int [N]') cannot be used as a template argument}}
}
template<typename T>
struct X1 {
template<int (&Array)[T::value]> // expected-error{{non-type template parameter of variably modified type 'int (&)[HasNonConstantValue::value]'}} \
- // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ // expected-warning{{variable length arrays are a C99 feature}}
struct Inner {
};
@@ -68,16 +68,17 @@ template<typename T, unsigned N>
void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: failed template argument deduction}}
void test_accept_array(int N) {
- int array[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ int array[N]; // expected-warning{{variable length arrays are a C99 feature}}
accept_array(array); // expected-error{{no matching function for call to 'accept_array'}}
}
// Variably-modified types cannot be used in local classes.
-void local_classes(int N) {
+void local_classes(int N) { // expected-note {{declared here}}
struct X {
int size;
int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \
- // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ // expected-error{{reference to local variable 'N' declared in enclosing function 'local_classes'}} \
+ // expected-warning{{variable length arrays are a C99 feature}}
};
}
@@ -87,7 +88,7 @@ namespace PR7206 {
float left;
float right;
};
- struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature}}
}
}
@@ -95,7 +96,7 @@ namespace rdar8020206 {
template<typename T>
void f(int i) {
const unsigned value = i;
- int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature, accepted as an extension}}
+ int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature}}
}
template void f<int>(int); // expected-note{{instantiation of}}
@@ -109,7 +110,7 @@ namespace rdar8021385 {
typedef typename T::my_int my_int;
void f0() {
int M = 4;
- my_int a[M]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ my_int a[M]; // expected-warning{{variable length arrays are a C99 feature}}
}
};
B<A> a;
@@ -117,7 +118,7 @@ namespace rdar8021385 {
namespace PR8209 {
void f(int n) {
- typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
+ typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature}}
(void)new vla_type; // expected-error{{variably}}
}
}
@@ -130,3 +131,11 @@ static const int k_cVal3 = (int)(1000*0.2f);
char rgch[k_cVal3] = {0};
}
}
+
+namespace PR11744 {
+ template<typename T> int f(int n) {
+ T arr[3][n]; // expected-warning 3 {{variable length arrays are a C99 feature}}
+ return 3;
+ }
+ int test = f<int>(0); // expected-note {{instantiation of}}
+}
diff --git a/test/SemaCXX/c99.cpp b/test/SemaCXX/c99.cpp
index cda069c..13918dc 100644
--- a/test/SemaCXX/c99.cpp
+++ b/test/SemaCXX/c99.cpp
@@ -4,6 +4,6 @@ void f1(int i[static 5]) { // expected-error{{C99}}
struct Point { int x; int y; };
-Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature, accepted in C++ as an extension}}
- y: 25 }; // expected-warning{{designated initializers are a C99 feature, accepted in C++ as an extension}} \
+Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature}}
+ y: 25 }; // expected-warning{{designated initializers are a C99 feature}} \
// expected-warning{{use of GNU old-style field designator extension}}
diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp
index ca9f045..e84e57b 100644
--- a/test/SemaCXX/class-base-member-init.cpp
+++ b/test/SemaCXX/class-base-member-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
class S {
public:
@@ -69,8 +69,24 @@ namespace test4 {
};
A(char _) : a(0), b(0) {}
- A(short _) : a(0), c(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}}
- A(int _) : d(0), e(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}}
- A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}}
+ A(short _) : a(0), c(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}}
+ A(int _) : d(0), e(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}}
+ A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}}
+ };
+}
+
+namespace test5 {
+ struct Base {
+ Base(int);
+ };
+ struct A : Base {
+ A() : decltype(Base(1))(3) {
+ }
+ A(int) : Base(3), // expected-note {{previous initialization is here}}
+ decltype(Base(1))(2), // expected-error {{multiple initializations given for base 'decltype(test5::Base(1))' (aka 'test5::Base')}}
+ decltype(int())() { // expected-error {{constructor initializer 'decltype(int())' (aka 'int') does not name a class}}
+ }
+ A(float) : decltype(A())(3) {
+ }
};
}
diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp
index 160f365..4dffc8d 100644
--- a/test/SemaCXX/class.cpp
+++ b/test/SemaCXX/class.cpp
@@ -1,22 +1,24 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s
class C {
public:
- auto int errx; // expected-error {{error: storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}}
- register int erry; // expected-error {{error: storage class specified for a member declaration}}
- extern int errz; // expected-error {{error: storage class specified for a member declaration}}
+ auto int errx; // expected-error {{storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}}
+ register int erry; // expected-error {{storage class specified for a member declaration}}
+ extern int errz; // expected-error {{storage class specified for a member declaration}}
static void sm() {
sx = 0;
- this->x = 0; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}}
- x = 0; // expected-error {{error: invalid use of member 'x' in static member function}}
+ this->x = 0; // expected-error {{invalid use of 'this' outside of a non-static member function}}
+ x = 0; // expected-error {{invalid use of member 'x' in static member function}}
}
class NestedC {
public:
NestedC(int);
- void m() {
+ void f() {
sx = 0;
- x = 0; // expected-error {{invalid use of nonstatic data member 'x'}}
+ x = 0; // expected-error {{use of non-static data member 'x' of 'C' from nested type 'NestedC'}}
+ sm();
+ m(); // expected-error {{call to non-static member function 'm' of 'C' from nested type 'NestedC'}}
}
};
@@ -34,10 +36,10 @@ public:
enum E1 { en1, en2 };
- int i = 0; // expected-warning {{in-class initialization of non-static data member accepted as a C++11 extension}}
+ int i = 0; // expected-warning {{in-class initialization of non-static data member is a C++11 extension}}
static int si = 0; // expected-error {{non-const static data member must be initialized out of line}}
static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}}
- static const int nci = vs; // expected-error {{in-class initializer is not a constant expression}}
+ static const int nci = vs; // expected-error {{in-class initializer for static data member is not a constant expression}}
static const int vi = 0;
static const volatile int cvi = 0; // ok, illegal in C++11
static const E evi = 0;
@@ -46,7 +48,7 @@ public:
sx = 0;
this->x = 0;
y = 0;
- this = 0; // expected-error {{error: expression is not assignable}}
+ this = 0; // expected-error {{expression is not assignable}}
}
int f1(int p) {
@@ -57,7 +59,7 @@ public:
typedef int A;
virtual int viv; // expected-error {{'virtual' can only appear on non-static member functions}}
- virtual static int vsif(); // expected-error {{error: 'virtual' can only appear on non-static member functions}}
+ virtual static int vsif(); // expected-error {{'virtual' can only appear on non-static member functions}}
virtual int vif();
private:
@@ -65,9 +67,9 @@ private:
static int sx;
mutable int mi;
- mutable int &mir; // expected-error {{error: 'mutable' cannot be applied to references}}
- mutable void mfn(); // expected-error {{error: 'mutable' cannot be applied to functions}}
- mutable const int mci; // expected-error {{error: 'mutable' and 'const' cannot be mixed}}
+ mutable int &mir; // expected-error {{'mutable' cannot be applied to references}}
+ mutable void mfn(); // expected-error {{'mutable' cannot be applied to functions}}
+ mutable const int mci; // expected-error {{'mutable' and 'const' cannot be mixed}}
static const int number = 50;
static int arr[number];
@@ -98,11 +100,11 @@ void f()
}
// Play with mutable a bit more, to make sure it doesn't crash anything.
-mutable int gi; // expected-error {{error: 'mutable' can only be applied to member variables}}
+mutable int gi; // expected-error {{'mutable' can only be applied to member variables}}
mutable void gfn(); // expected-error {{illegal storage class on function}}
void ogfn()
{
- mutable int ml; // expected-error {{error: 'mutable' can only be applied to member variables}}
+ mutable int ml; // expected-error {{'mutable' can only be applied to member variables}}
// PR3020: This used to crash due to double ownership of C4.
struct C4;
@@ -129,10 +131,10 @@ namespace pr6629 {
bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} \
// BOGUS expected-error {{expected '{' after base class list}} \
// BOGUS expected-error {{expected ';' after struct}} \
- // BOGUS expected-error {{expected unqualified-id}} \
+ // BOGUS expected-error {{expected unqualified-id}}
{ };
- template<> struct foo<unknown,unknown> { // why isn't there an error here?
+ template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}}
template <typename U1, typename U2> struct bar {
typedef bar type;
static const int value = 0;
@@ -174,7 +176,7 @@ namespace rdar8367341 {
struct A {
static const float x = 5.0f; // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}}
- static const float y = foo(); // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} expected-error {{in-class initializer is not a constant expression}}
+ static const float y = foo(); // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} expected-error {{in-class initializer for static data member is not a constant expression}}
};
}
@@ -186,7 +188,7 @@ struct S {
};
void f() {
- S::c; // expected-error {{invalid use of nonstatic data member}}
+ S::c; // expected-error {{invalid use of non-static data member}}
}
}
diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp
index 2c057ac..719a850 100644
--- a/test/SemaCXX/complex-overload.cpp
+++ b/test/SemaCXX/complex-overload.cpp
@@ -32,7 +32,7 @@ int *promote_or_convert(long double _Complex); // expected-note{{candidate funct
void test_promote_or_convert(float f, float _Complex fc) {
char *cp = promote_or_convert(fc);
- int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}}
+ int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous}}
}
char *promote_or_convert2(float);
diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp
index 3441bae..993f8e1 100644
--- a/test/SemaCXX/condition.cpp
+++ b/test/SemaCXX/condition.cpp
@@ -7,7 +7,7 @@ void test() {
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 (int f()=0) ; // expected-error {{a function type is not allowed here}}
+ while (int f()=0) ; // expected-warning {{interpreted as a function declaration}} expected-note {{initializer}} expected-error {{a function type is not allowed here}}
struct S {} s;
if (s) ++x; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}}
@@ -20,7 +20,8 @@ void test() {
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-error {{cannot initialize}} \
- // expected-warning{{enumeration value 'E' not handled in switch}}
+ // 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}}
if (int x=0) { // expected-note 2 {{previous definition is here}}
int x; // expected-error {{redefinition of 'x'}}
@@ -49,6 +50,11 @@ void test3() {
if ("help")
(void) 0;
- if (test3)
+ if (test3) // expected-warning {{address of function 'test3' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}}
(void) 0;
}
+
+void test4(bool (&x)(void)) {
+ while (x);
+}
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index 5648d02..4aee913 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -96,8 +96,8 @@ void test()
(void)(i1 ? BadDerived() : BadBase());
// b2.1 (hierarchy stuff)
- const Base constret();
- const Derived constder();
+ extern const Base constret();
+ extern const Derived constder();
// should use const overload
A a1((i1 ? constret() : Base()).trick());
A a2((i1 ? Base() : constret()).trick());
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
new file mode 100644
index 0000000..41d214a
--- /dev/null
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -0,0 +1,1246 @@
+// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -verify -std=c++11 -pedantic %s -Wno-comment
+
+namespace StaticAssertFoldTest {
+
+int x;
+static_assert(++x, "test"); // expected-error {{not an integral constant expression}}
+static_assert(false, "test"); // expected-error {{test}}
+
+}
+
+typedef decltype(sizeof(char)) size_t;
+
+template<typename T> constexpr T id(const T &t) { return t; }
+template<typename T> constexpr T min(const T &a, const T &b) {
+ return a < b ? a : b;
+}
+template<typename T> constexpr T max(const T &a, const T &b) {
+ return a < b ? b : a;
+}
+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; }
+};
+
+namespace DerivedToVBaseCast {
+
+ struct U { int n; };
+ struct V : U { int n; };
+ struct A : virtual V { int n; };
+ struct Aa { int n; };
+ struct B : virtual A, Aa {};
+ struct C : virtual A, Aa {};
+ struct D : B, C {};
+
+ D d;
+ constexpr B *p = &d;
+ constexpr C *q = &d;
+
+ static_assert((void*)p != (void*)q, "");
+ static_assert((A*)p == (A*)q, "");
+ static_assert((Aa*)p != (Aa*)q, "");
+
+ constexpr B &pp = d;
+ constexpr C &qq = d;
+ static_assert((void*)&pp != (void*)&qq, "");
+ static_assert(&(A&)pp == &(A&)qq, "");
+ static_assert(&(Aa&)pp != &(Aa&)qq, "");
+
+ constexpr V *v = p;
+ constexpr V *w = q;
+ constexpr V *x = (A*)p;
+ static_assert(v == w, "");
+ static_assert(v == x, "");
+
+ static_assert((U*)&d == p, "");
+ static_assert((U*)&d == q, "");
+ static_assert((U*)&d == v, "");
+ static_assert((U*)&d == w, "");
+ static_assert((U*)&d == x, "");
+
+ struct X {};
+ struct Y1 : virtual X {};
+ struct Y2 : X {};
+ struct Z : Y1, Y2 {};
+ Z z;
+ static_assert((X*)(Y1*)&z != (X*)(Y2*)&z, "");
+}
+
+namespace ConstCast {
+
+constexpr int n1 = 0;
+constexpr int n2 = const_cast<int&>(n1);
+constexpr int *n3 = const_cast<int*>(&n1);
+constexpr int n4 = *const_cast<int*>(&n1);
+constexpr const int * const *n5 = const_cast<const int* const*>(&n3);
+constexpr int **n6 = const_cast<int**>(&n3);
+constexpr int n7 = **n5;
+constexpr int n8 = **n6;
+
+}
+
+namespace TemplateArgumentConversion {
+ template<int n> struct IntParam {};
+
+ using IntParam0 = IntParam<0>;
+ using IntParam0 = IntParam<id(0)>;
+ using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}}
+}
+
+namespace CaseStatements {
+ void f(int n) {
+ switch (n) {
+ case MemberZero().zero: // expected-error {{did you mean to call it with no arguments?}} expected-note {{previous}}
+ case id(0): // expected-error {{duplicate case value '0'}}
+ return;
+ }
+ }
+}
+
+extern int &Recurse1;
+int &Recurse2 = Recurse1; // expected-note {{declared here}}
+int &Recurse1 = Recurse2;
+constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'Recurse2' is not a constant expression}}
+
+extern const int RecurseA;
+const int RecurseB = RecurseA; // expected-note {{declared here}}
+const int RecurseA = 10;
+constexpr int RecurseC = RecurseB; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'RecurseB' is not a constant expression}}
+
+namespace MemberEnum {
+ struct WithMemberEnum {
+ enum E { A = 42 };
+ } wme;
+
+ static_assert(wme.A == 42, "");
+}
+
+namespace DefaultArguments {
+
+const int z = int();
+constexpr int Sum(int a = 0, const int &b = 0, const int *c = &z, char d = 0) {
+ return a + b + *c + d;
+}
+const int four = 4;
+constexpr int eight = 8;
+constexpr const int twentyseven = 27;
+static_assert(Sum() == 0, "");
+static_assert(Sum(1) == 1, "");
+static_assert(Sum(1, four) == 5, "");
+static_assert(Sum(1, eight, &twentyseven) == 36, "");
+static_assert(Sum(1, 2, &four, eight) == 15, "");
+
+}
+
+namespace Ellipsis {
+
+// Note, values passed through an ellipsis can't actually be used.
+constexpr int F(int a, ...) { return a; }
+static_assert(F(0) == 0, "");
+static_assert(F(1, 0) == 1, "");
+static_assert(F(2, "test") == 2, "");
+static_assert(F(3, &F) == 3, "");
+int k = 0; // expected-note {{here}}
+static_assert(F(4, k) == 3, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'k'}}
+
+}
+
+namespace Recursion {
+ constexpr int fib(int n) { return n > 1 ? fib(n-1) + fib(n-2) : n; }
+ static_assert(fib(11) == 89, "");
+
+ constexpr int gcd_inner(int a, int b) {
+ return b == 0 ? a : gcd_inner(b, a % b);
+ }
+ constexpr int gcd(int a, int b) {
+ return gcd_inner(max(a, b), min(a, b));
+ }
+
+ static_assert(gcd(1749237, 5628959) == 7, "");
+}
+
+namespace FunctionCast {
+ // When folding, we allow functions to be cast to different types. Such
+ // cast functions cannot be called, even if they're constexpr.
+ constexpr int f() { return 1; }
+ typedef double (*DoubleFn)();
+ typedef int (*IntFn)();
+ int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}} expected-warning{{C99 feature}}
+ int b[(int)IntFn(f)()]; // ok
+}
+
+namespace StaticMemberFunction {
+ struct S {
+ static constexpr int k = 42;
+ static constexpr int f(int n) { return n * k + 2; }
+ } s;
+
+ constexpr int n = s.f(19);
+ static_assert(S::f(19) == 800, "");
+ static_assert(s.f(19) == 800, "");
+ static_assert(n == 800, "");
+
+ constexpr int (*sf1)(int) = &S::f;
+ constexpr int (*sf2)(int) = &s.f;
+ constexpr const int *sk = &s.k;
+}
+
+namespace ParameterScopes {
+
+ const int k = 42;
+ constexpr const int &ObscureTheTruth(const int &a) { return a; }
+ constexpr const int &MaybeReturnJunk(bool b, const int a) { // expected-note 2{{declared here}}
+ return ObscureTheTruth(b ? a : k);
+ }
+ static_assert(MaybeReturnJunk(false, 0) == 42, ""); // ok
+ constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}}
+
+ constexpr const int MaybeReturnNonstaticRef(bool b, const int a) {
+ return ObscureTheTruth(b ? a : k);
+ }
+ static_assert(MaybeReturnNonstaticRef(false, 0) == 42, ""); // ok
+ constexpr int b = MaybeReturnNonstaticRef(true, 0); // ok
+
+ constexpr int InternalReturnJunk(int n) {
+ return MaybeReturnJunk(true, n); // expected-note {{read of variable whose lifetime has ended}}
+ }
+ constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'InternalReturnJunk(0)'}}
+
+ constexpr int LToR(int &n) { return n; }
+ constexpr int GrabCallersArgument(bool which, int a, int b) {
+ return LToR(which ? b : a);
+ }
+ static_assert(GrabCallersArgument(false, 1, 2) == 1, "");
+ static_assert(GrabCallersArgument(true, 4, 8) == 8, "");
+
+}
+
+namespace Pointers {
+
+ constexpr int f(int n, const int *a, const int *b, const int *c) {
+ return n == 0 ? 0 : *a + f(n-1, b, c, a);
+ }
+
+ const int x = 1, y = 10, z = 100;
+ static_assert(f(23, &x, &y, &z) == 788, "");
+
+ constexpr int g(int n, int a, int b, int c) {
+ return f(n, &a, &b, &c);
+ }
+ static_assert(g(23, x, y, z) == 788, "");
+
+}
+
+namespace FunctionPointers {
+
+ constexpr int Double(int n) { return 2 * n; }
+ constexpr int Triple(int n) { return 3 * n; }
+ constexpr int Twice(int (*F)(int), int n) { return F(F(n)); }
+ constexpr int Quadruple(int n) { return Twice(Double, n); }
+ constexpr auto Select(int n) -> int (*)(int) {
+ return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;
+ }
+ constexpr int Apply(int (*F)(int), int n) { return F(n); } // expected-note {{subexpression}}
+
+ static_assert(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, "");
+
+ constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(0, 0)'}}
+
+}
+
+namespace PointerComparison {
+
+int x, y;
+static_assert(&x == &y, "false"); // expected-error {{false}}
+static_assert(&x != &y, "");
+constexpr bool g1 = &x == &y;
+constexpr bool g2 = &x != &y;
+constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool g6 = &x > &y; // expected-error {{must be initialized by a constant expression}}
+
+struct S { int x, y; } s;
+static_assert(&s.x == &s.y, "false"); // expected-error {{false}}
+static_assert(&s.x != &s.y, "");
+static_assert(&s.x <= &s.y, "");
+static_assert(&s.x >= &s.y, "false"); // expected-error {{false}}
+static_assert(&s.x < &s.y, "");
+static_assert(&s.x > &s.y, "false"); // expected-error {{false}}
+
+static_assert(0 == &y, "false"); // expected-error {{false}}
+static_assert(0 != &y, "");
+constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}}
+
+static_assert(&x == 0, "false"); // expected-error {{false}}
+static_assert(&x != 0, "");
+constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
+
+static_assert(&x == &x, "");
+static_assert(&x != &x, "false"); // expected-error {{false}}
+static_assert(&x <= &x, "");
+static_assert(&x >= &x, "");
+static_assert(&x < &x, "false"); // expected-error {{false}}
+static_assert(&x > &x, "false"); // expected-error {{false}}
+
+constexpr S* sptr = &s;
+constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr); // expected-error {{constant expression}} expected-note {{dynamic_cast}}
+
+struct U {};
+struct Str {
+ int a : dynamic_cast<S*>(sptr) == dynamic_cast<S*>(sptr); // \
+ expected-warning {{not an integral constant expression}} \
+ expected-note {{dynamic_cast is not allowed in a constant expression}}
+ int b : reinterpret_cast<S*>(sptr) == reinterpret_cast<S*>(sptr); // \
+ expected-warning {{not an integral constant expression}} \
+ 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}}
+ 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}}
+ 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}}
+ 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}}
+ 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}}
+};
+
+extern char externalvar[];
+constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; // expected-error {{must be initialized by a constant expression}}
+constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}} expected-warning {{unspecified}}
+static_assert(0 != "foo", "");
+
+}
+
+namespace MaterializeTemporary {
+
+constexpr int f(const int &r) { return r; }
+constexpr int n = f(1);
+
+constexpr bool same(const int &a, const int &b) { return &a == &b; }
+constexpr bool sameTemporary(const int &n) { return same(n, n); }
+
+static_assert(n, "");
+static_assert(!same(4, 4), "");
+static_assert(same(n, n), "");
+static_assert(sameTemporary(9), "");
+
+}
+
+constexpr int strcmp_ce(const char *p, const char *q) {
+ return (!*p || *p != *q) ? *p - *q : strcmp_ce(p+1, q+1);
+}
+
+namespace StringLiteral {
+
+template<typename Char>
+constexpr int MangleChars(const Char *p) {
+ return *p + 3 * (*p ? MangleChars(p+1) : 0);
+}
+
+static_assert(MangleChars("constexpr!") == 1768383, "");
+static_assert(MangleChars(u8"constexpr!") == 1768383, "");
+static_assert(MangleChars(L"constexpr!") == 1768383, "");
+static_assert(MangleChars(u"constexpr!") == 1768383, "");
+static_assert(MangleChars(U"constexpr!") == 1768383, "");
+
+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 const char *p = "test" + 2;
+static_assert(*p == 's', "");
+
+constexpr const char *max_iter(const char *a, const char *b) {
+ return *a < *b ? b : a;
+}
+constexpr const char *max_element(const char *a, const char *b) {
+ return (a+1 >= b) ? a : max_iter(a, max_element(a+1, b));
+}
+
+constexpr char str[] = "the quick brown fox jumped over the lazy dog";
+constexpr const char *max = max_element(begin(str), end(str));
+static_assert(*max == 'z', "");
+static_assert(max == str + 38, "");
+
+static_assert(strcmp_ce("hello world", "hello world") == 0, "");
+static_assert(strcmp_ce("hello world", "hello clang") > 0, "");
+static_assert(strcmp_ce("constexpr", "test") < 0, "");
+static_assert(strcmp_ce("", " ") < 0, "");
+
+struct S {
+ int n : "foo"[4]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
+};
+
+struct T {
+ char c[6];
+ constexpr T() : c{"foo"} {}
+};
+constexpr T t;
+
+static_assert(t.c[0] == 'f', "");
+static_assert(t.c[1] == 'o', "");
+static_assert(t.c[2] == 'o', "");
+static_assert(t.c[3] == 0, "");
+static_assert(t.c[4] == 0, "");
+static_assert(t.c[5] == 0, "");
+static_assert(t.c[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}}
+
+struct U {
+ wchar_t chars[6];
+ int n;
+} constexpr u = { { L"test" }, 0 };
+static_assert(u.chars[2] == L's', "");
+
+struct V {
+ char c[4];
+ constexpr V() : c("hi!") {}
+};
+static_assert(V().c[1] == "i"[0], "");
+
+}
+
+namespace Array {
+
+template<typename Iter>
+constexpr auto Sum(Iter begin, Iter end) -> decltype(+*begin) {
+ return begin == end ? 0 : *begin + Sum(begin+1, end);
+}
+
+constexpr int xs[] = { 1, 2, 3, 4, 5 };
+constexpr int ys[] = { 5, 4, 3, 2, 1 };
+constexpr int sum_xs = Sum(begin(xs), end(xs));
+static_assert(sum_xs == 15, "");
+
+constexpr int ZipFoldR(int (*F)(int x, int y, int c), int n,
+ const int *xs, const int *ys, int c) {
+ return n ? F(
+ *xs, // expected-note {{read of dereferenced one-past-the-end pointer}}
+ *ys,
+ ZipFoldR(F, n-1, xs+1, ys+1, c)) // \
+ expected-note {{in call to 'ZipFoldR(&SubMul, 2, &xs[4], &ys[4], 1)'}} \
+ expected-note {{in call to 'ZipFoldR(&SubMul, 1, &xs[5], &ys[5], 1)'}}
+ : c;
+}
+constexpr int MulAdd(int x, int y, int c) { return x * y + c; }
+constexpr int InnerProduct = ZipFoldR(MulAdd, 5, xs, ys, 0);
+static_assert(InnerProduct == 35, "");
+
+constexpr int SubMul(int x, int y, int c) { return (x - y) * c; }
+constexpr int DiffProd = ZipFoldR(SubMul, 2, xs+3, ys+3, 1);
+static_assert(DiffProd == 8, "");
+static_assert(ZipFoldR(SubMul, 3, xs+3, ys+3, 1), ""); // \
+ expected-error {{constant expression}} \
+ expected-note {{in call to 'ZipFoldR(&SubMul, 3, &xs[3], &ys[3], 1)'}}
+
+constexpr const int *p = xs + 3;
+constexpr int xs4 = p[1]; // ok
+constexpr int xs5 = p[2]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
+constexpr int xs6 = p[3]; // expected-error {{constant expression}} expected-note {{cannot refer to element 6}}
+constexpr int xs0 = p[-3]; // ok
+constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}}
+
+constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+static_assert(zs[0][0][0][0] == 1, "");
+static_assert(zs[1][1][1][1] == 16, "");
+static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
+static_assert((&zs[0][0][0][2])[-1] == 2, "");
+static_assert(**(**(zs + 1) + 1) == 11, "");
+static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of array of 2 elements in a constant expression}}
+static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2) == 11, "");
+constexpr int err_zs_1_2_0_0 = zs[1][2][0][0]; // expected-error {{constant expression}} expected-note {{cannot access array element of pointer past the end}}
+
+constexpr int fail(const int &p) {
+ return (&p)[64]; // expected-note {{cannot refer to element 64 of array of 2 elements}}
+}
+static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // \
+expected-error {{static_assert expression is not an integral constant expression}} \
+expected-note {{in call to 'fail(zs[1][0][1][0])'}}
+
+constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; // expected-warning {{C99 feature}}
+constexpr int SumNonzero(const int *p) {
+ return *p + (*p ? SumNonzero(p+1) : 0);
+}
+constexpr int CountZero(const int *p, const int *q) {
+ return p == q ? 0 : (*p == 0) + CountZero(p+1, q);
+}
+static_assert(SumNonzero(arr) == 6, "");
+static_assert(CountZero(arr, arr + 40) == 36, "");
+
+struct ArrayElem {
+ constexpr ArrayElem() : n(0) {}
+ int n;
+ constexpr int f() { return n; }
+};
+struct ArrayRVal {
+ constexpr ArrayRVal() {}
+ ArrayElem elems[10];
+};
+static_assert(ArrayRVal().elems[3].f() == 0, "");
+
+}
+
+namespace DependentValues {
+
+struct I { int n; typedef I V[10]; };
+I::V x, y;
+template<bool B> struct S {
+ int k;
+ void f() {
+ I::V &cells = B ? x : y;
+ I &i = cells[k];
+ switch (i.n) {}
+ }
+};
+
+}
+
+namespace Class {
+
+struct A { constexpr A(int a, int b) : k(a + b) {} int k; };
+constexpr int fn(const A &a) { return a.k; }
+static_assert(fn(A(4,5)) == 9, "");
+
+struct B { int n; int m; } constexpr b = { 0, b.n }; // expected-warning {{uninitialized}}
+struct C {
+ constexpr C(C *this_) : m(42), n(this_->m) {} // ok
+ int m, n;
+};
+struct D {
+ C c;
+ constexpr D() : c(&c) {}
+};
+static_assert(D().c.n == 42, "");
+
+struct E {
+ constexpr E() : p(&p) {}
+ void *p;
+};
+constexpr const E &e1 = E(); // expected-error {{constant expression}} expected-note {{reference to temporary is not a constant expression}} expected-note {{temporary created here}}
+// This is a constant expression if we elide the copy constructor call, and
+// is not a constant expression if we don't! But we do, so it is.
+constexpr E e2 = E();
+static_assert(e2.p == &e2.p, "");
+constexpr E e3;
+static_assert(e3.p == &e3.p, "");
+
+extern const class F f;
+struct F {
+ constexpr F() : p(&f.p) {}
+ const void *p;
+};
+constexpr F f;
+
+struct G {
+ struct T {
+ constexpr T(T *p) : u1(), u2(p) {}
+ union U1 {
+ constexpr U1() {}
+ int a, b = 42;
+ } u1;
+ union U2 {
+ constexpr U2(T *p) : c(p->u1.b) {}
+ int c, d;
+ } u2;
+ } t;
+ constexpr G() : t(&t) {}
+} constexpr g;
+
+static_assert(g.t.u1.a == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}}
+static_assert(g.t.u1.b == 42, "");
+static_assert(g.t.u2.c == 42, "");
+static_assert(g.t.u2.d == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'd' of union with active member 'c'}}
+
+struct S {
+ int a, b;
+ const S *p;
+ double d;
+ const char *q;
+
+ constexpr S(int n, const S *p) : a(5), b(n), p(p), d(n), q("hello") {}
+};
+
+S global(43, &global);
+
+static_assert(S(15, &global).b == 15, "");
+
+constexpr bool CheckS(const S &s) {
+ return s.a == 5 && s.b == 27 && s.p == &global && s.d == 27. && s.q[3] == 'l';
+}
+static_assert(CheckS(S(27, &global)), "");
+
+struct Arr {
+ char arr[3];
+ constexpr Arr() : arr{'x', 'y', 'z'} {}
+};
+constexpr int hash(Arr &&a) {
+ return a.arr[0] + a.arr[1] * 0x100 + a.arr[2] * 0x10000;
+}
+constexpr int k = hash(Arr());
+static_assert(k == 0x007a7978, "");
+
+
+struct AggregateInit {
+ const char &c;
+ int n;
+ double d;
+ int arr[5];
+ void *p;
+};
+
+constexpr AggregateInit agg1 = { "hello"[0] };
+
+static_assert(strcmp_ce(&agg1.c, "hello") == 0, "");
+static_assert(agg1.n == 0, "");
+static_assert(agg1.d == 0.0, "");
+static_assert(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1}}
+static_assert(agg1.arr[0] == 0, "");
+static_assert(agg1.arr[4] == 0, "");
+static_assert(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end}}
+static_assert(agg1.p == nullptr, "");
+
+namespace SimpleDerivedClass {
+
+struct B {
+ constexpr B(int n) : a(n) {}
+ int a;
+};
+struct D : B {
+ constexpr D(int n) : B(n) {}
+};
+constexpr D d(3);
+static_assert(d.a == 3, "");
+
+}
+
+struct Bottom { constexpr Bottom() {} };
+struct Base : Bottom {
+ constexpr Base(int a = 42, const char *b = "test") : a(a), b(b) {}
+ int a;
+ const char *b;
+};
+struct Base2 : Bottom {
+ constexpr Base2(const int &r) : r(r) {}
+ int q = 123;
+ const int &r;
+};
+struct Derived : Base, Base2 {
+ constexpr Derived() : Base(76), Base2(a) {}
+ int c = r + b[1];
+};
+
+constexpr bool operator==(const Base &a, const Base &b) {
+ return a.a == b.a && strcmp_ce(a.b, b.b) == 0;
+}
+
+constexpr Base base;
+constexpr Base base2(76);
+constexpr Derived derived;
+static_assert(derived.a == 76, "");
+static_assert(derived.b[2] == 's', "");
+static_assert(derived.c == 76 + 'e', "");
+static_assert(derived.q == 123, "");
+static_assert(derived.r == 76, "");
+static_assert(&derived.r == &derived.a, "");
+
+static_assert(!(derived == base), "");
+static_assert(derived == base2, "");
+
+constexpr Bottom &bot1 = (Base&)derived;
+constexpr Bottom &bot2 = (Base2&)derived;
+static_assert(&bot1 != &bot2, "");
+
+constexpr Bottom *pb1 = (Base*)&derived;
+constexpr Bottom *pb2 = (Base2*)&derived;
+static_assert(&pb1 != &pb2, "");
+static_assert(pb1 == &bot1, "");
+static_assert(pb2 == &bot2, "");
+
+constexpr Base2 &fail = (Base2&)bot1; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base2'}}
+constexpr Base &fail2 = (Base&)*pb2; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base'}}
+constexpr Base2 &ok2 = (Base2&)bot2;
+static_assert(&ok2 == &derived, "");
+
+constexpr Base2 *pfail = (Base2*)pb1; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base2'}}
+constexpr Base *pfail2 = (Base*)&bot2; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base'}}
+constexpr Base2 *pok2 = (Base2*)pb2;
+static_assert(pok2 == &derived, "");
+static_assert(&ok2 == pok2, "");
+static_assert((Base2*)(Derived*)(Base*)pb1 == pok2, "");
+static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, "");
+
+constexpr Base *nullB = 42 - 6 * 7;
+static_assert((Bottom*)nullB == 0, "");
+static_assert((Derived*)nullB == 0, "");
+static_assert((void*)(Bottom*)nullB == (void*)(Derived*)nullB, "");
+
+namespace ConversionOperators {
+
+struct T {
+ constexpr T(int n) : k(5*n - 3) {}
+ constexpr operator int() { 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); }
+ int k;
+};
+
+constexpr bool check(T a, T b) { return a == b.k; }
+
+static_assert(S(5) == 11, "");
+static_assert(check(S(5), 11), "");
+
+}
+
+}
+
+namespace Temporaries {
+
+struct S {
+ constexpr S() {}
+ constexpr int f();
+};
+struct T : S {
+ constexpr T(int n) : S(), n(n) {}
+ int n;
+};
+constexpr int S::f() {
+ // 'this' must be the postfix-expression in a class member access expression,
+ // so we can't just use
+ // return static_cast<T*>(this)->n;
+ return this->*(int(S::*))&T::n;
+}
+// The T temporary is implicitly cast to an S subobject, but we can recover the
+// T full-object via a base-to-derived cast, or a derived-to-base-casted member
+// pointer.
+static_assert(T(3).f() == 3, "");
+
+constexpr int f(const S &s) {
+ return static_cast<const T&>(s).n;
+}
+constexpr int n = f(T(5));
+static_assert(f(T(5)) == 5, "");
+
+constexpr bool b(int n) { return &n; }
+static_assert(b(0), "");
+
+}
+
+namespace Union {
+
+union U {
+ int a;
+ int b;
+};
+
+constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; // expected-warning 4{{C99 feature}}
+static_assert(u[0].a == 0, "");
+static_assert(u[0].b, ""); // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}}
+static_assert(u[1].b == 1, "");
+static_assert((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
+static_assert(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element 2 of non-array object}}
+static_assert((&(u[1]) + 1 + 1)->b == 3, "");
+
+constexpr U v = {};
+static_assert(v.a == 0, "");
+
+union Empty {};
+constexpr Empty e = {};
+
+// Make sure we handle trivial copy constructors for unions.
+constexpr U x = {42};
+constexpr U y = x;
+static_assert(y.a == 42, "");
+static_assert(y.b == 42, ""); // expected-error {{constant expression}} expected-note {{'b' of union with active member 'a'}}
+
+}
+
+namespace MemberPointer {
+ struct A {
+ constexpr A(int n) : n(n) {}
+ int n;
+ constexpr int f() { return n + 3; }
+ };
+ constexpr A a(7);
+ static_assert(A(5).*&A::n == 5, "");
+ static_assert((&a)->*&A::n == 7, "");
+ static_assert((A(8).*&A::f)() == 11, "");
+ static_assert(((&a)->*&A::f)() == 10, "");
+
+ struct B : A {
+ constexpr B(int n, int m) : A(n), m(m) {}
+ int m;
+ constexpr int g() { return n + m + 1; }
+ };
+ constexpr B b(9, 13);
+ static_assert(B(4, 11).*&A::n == 4, "");
+ static_assert(B(4, 11).*&B::m == 11, "");
+ static_assert(B(4, 11).*(int(A::*))&B::m == 11, "");
+ static_assert((&b)->*&A::n == 9, "");
+ static_assert((&b)->*&B::m == 13, "");
+ static_assert((&b)->*(int(A::*))&B::m == 13, "");
+ static_assert((B(4, 11).*&A::f)() == 7, "");
+ static_assert((B(4, 11).*&B::g)() == 16, "");
+ static_assert((B(4, 11).*(int(A::*)()const)&B::g)() == 16, "");
+ static_assert(((&b)->*&A::f)() == 12, "");
+ static_assert(((&b)->*&B::g)() == 23, "");
+ static_assert(((&b)->*(int(A::*)()const)&B::g)() == 23, "");
+
+ struct S {
+ constexpr S(int m, int n, int (S::*pf)() const, int S::*pn) :
+ m(m), n(n), pf(pf), pn(pn) {}
+ constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {}
+
+ constexpr int f() { return this->*pn; }
+ virtual int g() const;
+
+ int m, n;
+ int (S::*pf)() const;
+ int S::*pn;
+ };
+
+ constexpr int S::*pm = &S::m;
+ constexpr int S::*pn = &S::n;
+ constexpr int (S::*pf)() const = &S::f;
+ constexpr int (S::*pg)() const = &S::g;
+
+ constexpr S s(2, 5, &S::f, &S::m);
+
+ static_assert((s.*&S::f)() == 2, "");
+ static_assert((s.*s.pf)() == 2, "");
+
+ static_assert(pf == &S::f, "");
+ static_assert(pf == s.*&S::pf, "");
+ static_assert(pm == &S::m, "");
+ static_assert(pm != pn, "");
+ static_assert(s.pn != pn, "");
+ static_assert(s.pn == pm, "");
+ static_assert(pg != nullptr, "");
+ static_assert(pf != nullptr, "");
+ static_assert((int S::*)nullptr == nullptr, "");
+ static_assert(pg == pg, ""); // expected-error {{constant expression}} expected-note {{comparison of pointer to virtual member function 'g' has unspecified value}}
+ static_assert(pf != pg, ""); // expected-error {{constant expression}} expected-note {{comparison of pointer to virtual member function 'g' has unspecified value}}
+
+ template<int n> struct T : T<n-1> {};
+ template<> struct T<0> { int n; };
+ template<> struct T<30> : T<29> { int m; };
+
+ T<17> t17;
+ T<30> t30;
+
+ constexpr int (T<10>::*deepn) = &T<0>::n;
+ static_assert(&(t17.*deepn) == &t17.n, "");
+ static_assert(deepn == &T<2>::n, "");
+
+ constexpr int (T<15>::*deepm) = (int(T<10>::*))&T<30>::m;
+ constexpr int *pbad = &(t17.*deepm); // expected-error {{constant expression}}
+ static_assert(&(t30.*deepm) == &t30.m, "");
+ static_assert(deepm == &T<50>::m, "");
+ static_assert(deepm != deepn, "");
+
+ constexpr T<5> *p17_5 = &t17;
+ constexpr T<13> *p17_13 = (T<13>*)p17_5;
+ constexpr T<23> *p17_23 = (T<23>*)p17_13; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'T<17>' to type 'T<23>'}}
+ static_assert(&(p17_5->*(int(T<3>::*))deepn) == &t17.n, "");
+ static_assert(&(p17_13->*deepn) == &t17.n, "");
+ constexpr int *pbad2 = &(p17_13->*(int(T<9>::*))deepm); // expected-error {{constant expression}}
+
+ constexpr T<5> *p30_5 = &t30;
+ constexpr T<23> *p30_23 = (T<23>*)p30_5;
+ constexpr T<13> *p30_13 = p30_23;
+ static_assert(&(p30_5->*(int(T<3>::*))deepn) == &t30.n, "");
+ static_assert(&(p30_13->*deepn) == &t30.n, "");
+ static_assert(&(p30_23->*deepn) == &t30.n, "");
+ static_assert(&(p30_5->*(int(T<2>::*))deepm) == &t30.m, "");
+ static_assert(&(((T<17>*)p30_13)->*deepm) == &t30.m, "");
+ static_assert(&(p30_23->*deepm) == &t30.m, "");
+
+ struct Base { int n; };
+ template<int N> struct Mid : Base {};
+ struct Derived : Mid<0>, Mid<1> {};
+ static_assert(&Mid<0>::n == &Mid<1>::n, "");
+ static_assert((int Derived::*)(int Mid<0>::*)&Mid<0>::n !=
+ (int Derived::*)(int Mid<1>::*)&Mid<1>::n, "");
+ static_assert(&Mid<0>::n == (int Mid<0>::*)&Base::n, "");
+}
+
+namespace ArrayBaseDerived {
+
+ struct Base {
+ constexpr Base() {}
+ int n = 0;
+ };
+ struct Derived : Base {
+ constexpr Derived() {}
+ constexpr const int *f() { return &n; }
+ };
+
+ constexpr Derived a[10];
+ constexpr Derived *pd3 = const_cast<Derived*>(&a[3]);
+ constexpr Base *pb3 = const_cast<Derived*>(&a[3]);
+ static_assert(pb3 == pd3, "");
+
+ // pb3 does not point to an array element.
+ constexpr Base *pb4 = pb3 + 1; // ok, one-past-the-end pointer.
+ constexpr int pb4n = pb4->n; // expected-error {{constant expression}} expected-note {{cannot access field of pointer past the end}}
+ constexpr Base *err_pb5 = pb3 + 2; // expected-error {{constant expression}} expected-note {{cannot refer to element 2}} expected-note {{here}}
+ constexpr int err_pb5n = err_pb5->n; // expected-error {{constant expression}} expected-note {{initializer of 'err_pb5' is not a constant expression}}
+ constexpr Base *err_pb2 = pb3 - 1; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} expected-note {{here}}
+ constexpr int err_pb2n = err_pb2->n; // expected-error {{constant expression}} expected-note {{initializer of 'err_pb2'}}
+ constexpr Base *pb3a = pb4 - 1;
+
+ // pb4 does not point to a Derived.
+ constexpr Derived *err_pd4 = (Derived*)pb4; // expected-error {{constant expression}} expected-note {{cannot access derived class of pointer past the end}}
+ constexpr Derived *pd3a = (Derived*)pb3a;
+ constexpr int pd3n = pd3a->n;
+
+ // pd3a still points to the Derived array.
+ constexpr Derived *pd6 = pd3a + 3;
+ static_assert(pd6 == &a[6], "");
+ constexpr Derived *pd9 = pd6 + 3;
+ constexpr Derived *pd10 = pd6 + 4;
+ constexpr int pd9n = pd9->n; // ok
+ constexpr int err_pd10n = pd10->n; // expected-error {{constant expression}} expected-note {{cannot access base class of pointer past the end}}
+ constexpr int pd0n = pd10[-10].n;
+ constexpr int err_pdminus1n = pd10[-11].n; // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of}}
+
+ constexpr Base *pb9 = pd9;
+ constexpr const int *(Base::*pfb)() const =
+ static_cast<const int *(Base::*)() const>(&Derived::f);
+ static_assert((pb9->*pfb)() == &a[9].n, "");
+}
+
+namespace Complex {
+
+class complex {
+ int re, im;
+public:
+ constexpr complex(int re = 0, int im = 0) : re(re), im(im) {}
+ constexpr complex(const complex &o) : re(o.re), im(o.im) {}
+ constexpr complex operator-() const { return complex(-re, -im); }
+ friend constexpr complex operator+(const complex &l, const complex &r) {
+ return complex(l.re + r.re, l.im + r.im);
+ }
+ friend constexpr complex operator-(const complex &l, const complex &r) {
+ return l + -r;
+ }
+ friend constexpr complex operator*(const complex &l, const complex &r) {
+ return complex(l.re * r.re - l.im * r.im, l.re * r.im + l.im * r.re);
+ }
+ friend constexpr bool operator==(const complex &l, const complex &r) {
+ return l.re == r.re && l.im == r.im;
+ }
+ constexpr bool operator!=(const complex &r) const {
+ return re != r.re || im != r.im;
+ }
+ constexpr int real() const { return re; }
+ constexpr int imag() const { return im; }
+};
+
+constexpr complex i = complex(0, 1);
+constexpr complex k = (3 + 4*i) * (6 - 4*i);
+static_assert(complex(1,0).real() == 1, "");
+static_assert(complex(1,0).imag() == 0, "");
+static_assert(((complex)1).imag() == 0, "");
+static_assert(k.real() == 34, "");
+static_assert(k.imag() == 12, "");
+static_assert(k - 34 == 12*i, "");
+static_assert((complex)1 == complex(1), "");
+static_assert((complex)1 != complex(0, 1), "");
+static_assert(complex(1) == complex(1), "");
+static_assert(complex(1) != complex(0, 1), "");
+constexpr complex makeComplex(int re, int im) { return complex(re, im); }
+static_assert(makeComplex(1,0) == complex(1), "");
+static_assert(makeComplex(1,0) != complex(0, 1), "");
+
+class complex_wrap : public complex {
+public:
+ constexpr complex_wrap(int re, int im = 0) : complex(re, im) {}
+ constexpr complex_wrap(const complex_wrap &o) : complex(o) {}
+};
+
+static_assert((complex_wrap)1 == complex(1), "");
+static_assert((complex)1 != complex_wrap(0, 1), "");
+static_assert(complex(1) == complex_wrap(1), "");
+static_assert(complex_wrap(1) != complex(0, 1), "");
+constexpr complex_wrap makeComplexWrap(int re, int im) {
+ return complex_wrap(re, im);
+}
+static_assert(makeComplexWrap(1,0) == complex(1), "");
+static_assert(makeComplexWrap(1,0) != complex(0, 1), "");
+
+}
+
+namespace PR11595 {
+ struct A { constexpr bool operator==(int x) { 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}}
+
+ constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}}
+ return B().x == k; // expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}}
+ }
+}
+
+namespace ExprWithCleanups {
+ struct A { A(); ~A(); int get(); };
+ constexpr int get(bool FromA) { return FromA ? A().get() : 1; }
+ constexpr int n = get(false);
+}
+
+namespace Volatile {
+
+volatile constexpr int n1 = 0; // expected-note {{here}}
+volatile const int n2 = 0; // expected-note {{here}}
+int n3 = 37; // expected-note {{declared here}}
+
+constexpr int m1 = n1; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}}
+constexpr int m2 = n2; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}}
+constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}}
+constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}}
+
+struct T { int n; };
+const T t = { 42 }; // expected-note {{declared here}}
+
+constexpr int f(volatile int &&r) {
+ return r; // expected-note {{read of volatile-qualified type 'volatile int'}}
+}
+constexpr int g(volatile int &&r) {
+ return const_cast<int&>(r); // expected-note {{read of volatile temporary is not allowed in a constant expression}}
+}
+struct S {
+ int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}}
+ int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}}
+ int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}}
+ int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}}
+};
+
+}
+
+namespace ExternConstexpr {
+ extern constexpr int n = 0;
+ extern constexpr int m; // expected-error {{constexpr variable declaration must be a definition}}
+ void f() {
+ extern constexpr int i; // expected-error {{constexpr variable declaration must be a definition}}
+ constexpr int j = 0;
+ constexpr int k; // expected-error {{default initialization of an object of const type}}
+ }
+}
+
+namespace ComplexConstexpr {
+ constexpr _Complex float test1 = {};
+ constexpr _Complex float test2 = {1};
+ constexpr _Complex double test3 = {1,2};
+ constexpr _Complex int test4 = {4};
+ constexpr _Complex int test5 = 4;
+ constexpr _Complex int test6 = {5,6};
+ typedef _Complex float fcomplex;
+ constexpr fcomplex test7 = fcomplex();
+
+ constexpr const double &t2r = __real test3;
+ constexpr const double &t2i = __imag test3;
+ static_assert(&t2r + 1 == &t2i, "");
+ static_assert(t2r == 1.0, "");
+ static_assert(t2i == 2.0, "");
+ constexpr const double *t2p = &t2r;
+ static_assert(t2p[-1] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element -1 of array of 2 elements}}
+ static_assert(t2p[0] == 1.0, "");
+ static_assert(t2p[1] == 2.0, "");
+ static_assert(t2p[2] == 0.0, ""); // expected-error {{constant expr}} expected-note {{one-past-the-end pointer}}
+ static_assert(t2p[3] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element 3 of array of 2 elements}}
+ constexpr _Complex float *p = 0;
+ constexpr float pr = __real *p; // expected-error {{constant expr}} expected-note {{cannot access real component of null}}
+ constexpr float pi = __imag *p; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of null}}
+ constexpr const _Complex double *q = &test3 + 1;
+ constexpr double qr = __real *q; // expected-error {{constant expr}} expected-note {{cannot access real component of pointer past the end}}
+ constexpr double qi = __imag *q; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of pointer past the end}}
+
+ static_assert(__real test6 == 5, "");
+ static_assert(__imag test6 == 6, "");
+ static_assert(&__imag test6 == &__real test6 + 1, "");
+}
+
+namespace InstantiateCaseStmt {
+ template<int x> constexpr int f() { return x; }
+ template<int x> int g(int c) { switch(c) { case f<x>(): return 1; } return 0; }
+ int gg(int c) { return g<4>(c); }
+}
+
+namespace ConvertedConstantExpr {
+ extern int &m;
+ extern int &n;
+
+ constexpr int k = 4;
+ int &m = const_cast<int&>(k);
+
+ // If we have nothing more interesting to say, ensure we don't produce a
+ // useless note and instead just point to the non-constant subexpression.
+ enum class E {
+ em = m,
+ en = n, // expected-error {{not a constant expression}}
+ eo = (m +
+ n // expected-error {{not a constant expression}}
+ ),
+ eq = reinterpret_cast<int>((int*)0) // expected-error {{not a constant expression}} expected-note {{reinterpret_cast}}
+ };
+}
+
+namespace IndirectField {
+ struct S {
+ struct { // expected-warning {{GNU extension}}
+ union {
+ struct { // expected-warning {{GNU extension}}
+ int a;
+ int b;
+ };
+ int c;
+ };
+ int d;
+ };
+ union {
+ int e;
+ int f;
+ };
+ constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {}
+ constexpr S(int c, int d, int f) : c(c), d(d), f(f) {}
+ };
+
+ constexpr S s1(1, 2, 3, 4);
+ constexpr S s2(5, 6, 7);
+
+ // FIXME: The diagnostics here do a very poor job of explaining which unnamed
+ // member is active and which is requested.
+ static_assert(s1.a == 1, "");
+ static_assert(s1.b == 2, "");
+ static_assert(s1.c == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s1.d == 3, "");
+ static_assert(s1.e == 4, "");
+ static_assert(s1.f == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+
+ static_assert(s2.a == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s2.b == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s2.c == 5, "");
+ static_assert(s2.d == 6, "");
+ static_assert(s2.e == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}}
+ static_assert(s2.f == 7, "");
+}
+
+// DR1405: don't allow reading mutable members in constant expressions.
+namespace MutableMembers {
+ struct MM {
+ mutable int n; // expected-note 3{{declared here}}
+ } constexpr mm = { 4 };
+ constexpr int mmn = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}}
+ int x = (mm.n = 1, 3);
+ constexpr int mmn2 = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}}
+
+ // Here's one reason why allowing this would be a disaster...
+ template<int n> struct Id { int k = n; };
+ int f() {
+ constexpr MM m = { 0 };
+ ++m.n;
+ return Id<m.n>().k; // expected-error {{not a constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}}
+ }
+
+ struct A { int n; };
+ struct B { mutable A a; }; // expected-note {{here}}
+ struct C { B b; };
+ constexpr C c[3] = {};
+ constexpr int k = c[1].b.a.n; // expected-error {{constant expression}} expected-note {{mutable}}
+}
+
+namespace Fold {
+
+ // This macro forces its argument to be constant-folded, even if it's not
+ // otherwise a constant expression.
+ #define fold(x) (__builtin_constant_p(x) ? (x) : (x))
+
+ constexpr int n = (int)(char*)123; // expected-error {{constant expression}} expected-note {{reinterpret_cast}}
+ constexpr int m = fold((int)(char*)123); // ok
+ static_assert(m == 123, "");
+
+ #undef fold
+
+}
+
+namespace DR1454 {
+
+constexpr const int &f(const int &n) { return n; }
+constexpr int k1 = f(0); // ok
+
+struct Wrap {
+ const int &value;
+};
+constexpr const Wrap &g(const Wrap &w) { return w; }
+constexpr int k2 = g({0}).value; // ok
+
+constexpr const int &i = 0; // expected-error {{constant expression}} expected-note {{temporary}} expected-note 2{{here}}
+constexpr const int j = i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}}
+
+}
+
+namespace RecursiveOpaqueExpr {
+ template<typename Iter>
+ constexpr auto LastNonzero(Iter p, Iter q) -> decltype(+*p) {
+ return p != q ? (LastNonzero(p+1, q) ?: *p) : 0; // expected-warning {{GNU}}
+ }
+
+ constexpr int arr1[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 0 };
+ static_assert(LastNonzero(begin(arr1), end(arr1)) == 4, "");
+
+ constexpr int arr2[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 5 };
+ static_assert(LastNonzero(begin(arr2), end(arr2)) == 5, "");
+}
+
+namespace VLASizeof {
+
+ void f(int k) {
+ int arr[k]; // expected-warning {{C99}}
+ constexpr int n = 1 +
+ sizeof(arr) // expected-error {{constant expression}}
+ * 3;
+ }
+}
+
+namespace CompoundLiteral {
+ // FIXME:
+ // We don't model the semantics of this correctly: the compound literal is
+ // represented as a prvalue in the AST, but actually behaves like an lvalue.
+ // We treat the compound literal as a temporary and refuse to produce a
+ // pointer to it. This is OK: we're not required to treat this as a constant
+ // in C++, and in C we model compound literals as lvalues.
+ constexpr int *p = (int*)(int[1]){0}; // expected-warning {{C99}} expected-error {{constant expression}} expected-note 2{{temporary}}
+}
+
+namespace Vector {
+ typedef int __attribute__((vector_size(16))) VI4;
+ constexpr VI4 f(int n) {
+ return VI4 { n * 3, n + 4, n - 5, n / 6 };
+ }
+ constexpr auto v1 = f(10);
+
+ typedef double __attribute__((vector_size(32))) VD4;
+ constexpr VD4 g(int n) {
+ return (VD4) { n / 2.0, n + 1.5, n - 5.4, n * 0.9 }; // expected-warning {{C99}}
+ }
+ constexpr auto v2 = g(4);
+}
diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp
index 1341036..23a4dda 100644
--- a/test/SemaCXX/constant-expression.cpp
+++ b/test/SemaCXX/constant-expression.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s
// C++ [expr.const]p1:
// In several places, C++ requires expressions that evaluate to an integral
// or enumeration constant: as array bounds, as case expressions, as
@@ -85,3 +85,35 @@ enum {
a = sizeof(int) == 8,
b = a? 8 : 4
};
+
+void diags(int n) {
+ switch (n) {
+ case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ ;
+ }
+}
+
+namespace IntOrEnum {
+ const int k = 0;
+ const int &p = k;
+ template<int n> struct S {};
+ S<p> s; // expected-error {{not an integral constant expression}}
+}
+
+extern const int recurse1;
+// recurse2 cannot be used in a constant expression because it is not
+// initialized by a constant expression. The same expression appearing later in
+// the TU would be a constant expression, but here it is not.
+const int recurse2 = recurse1;
+const int recurse1 = 1;
+int array1[recurse1]; // ok
+int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}}
+
+namespace FloatConvert {
+ typedef int a[(int)42.3];
+ typedef int a[(int)42.997];
+ typedef int b[(int)4e10]; // expected-warning {{variable length}} expected-error {{variable length}}
+}
diff --git a/test/SemaCXX/constexpr-ackermann.cpp b/test/SemaCXX/constexpr-ackermann.cpp
new file mode 100644
index 0000000..c4ea313
--- /dev/null
+++ b/test/SemaCXX/constexpr-ackermann.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s
+
+constexpr unsigned long long A(unsigned long long m, unsigned long long n) {
+ return m == 0 ? n + 1 : n == 0 ? A(m-1, 1) : A(m - 1, A(m, n - 1));
+}
+
+using X = int[A(3,4)];
+using X = int[125];
diff --git a/test/SemaCXX/constexpr-backtrace-limit.cpp b/test/SemaCXX/constexpr-backtrace-limit.cpp
new file mode 100644
index 0000000..9c40eed
--- /dev/null
+++ b/test/SemaCXX/constexpr-backtrace-limit.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 0 -fconstexpr-depth 4 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST1
+// TEST1: constant expression
+// TEST1-NEXT: exceeded maximum depth of 4
+// TEST1-NEXT: in call to 'recurse(2)'
+// TEST1-NEXT: in call to 'recurse(3)'
+// TEST1-NEXT: in call to 'recurse(4)'
+// TEST1-NEXT: in call to 'recurse(5)'
+
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 2 -fconstexpr-depth 4 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST2
+// TEST2: constant expression
+// TEST2-NEXT: exceeded maximum depth of 4
+// TEST2-NEXT: in call to 'recurse(2)'
+// TEST2-NEXT: skipping 2 calls
+// TEST2-NEXT: in call to 'recurse(5)'
+
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 2 -fconstexpr-depth 8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST3
+// TEST3: constant expression
+// TEST3-NEXT: reinterpret_cast
+// TEST3-NEXT: in call to 'recurse(0)'
+// TEST3-NEXT: skipping 4 calls
+// TEST3-NEXT: in call to 'recurse(5)'
+
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 8 -fconstexpr-depth 8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST4
+// TEST4: constant expression
+// TEST4-NEXT: reinterpret_cast
+// TEST4-NEXT: in call to 'recurse(0)'
+// TEST4-NEXT: in call to 'recurse(1)'
+// TEST4-NEXT: in call to 'recurse(2)'
+// TEST4-NEXT: in call to 'recurse(3)'
+// TEST4-NEXT: in call to 'recurse(4)'
+// TEST4-NEXT: in call to 'recurse(5)'
+
+constexpr int recurse(int n) { return n ? recurse(n-1) : *(int*)n; }
+static_assert(recurse(5), "");
diff --git a/test/SemaCXX/constexpr-depth.cpp b/test/SemaCXX/constexpr-depth.cpp
new file mode 100644
index 0000000..feba6fd
--- /dev/null
+++ b/test/SemaCXX/constexpr-depth.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=128 -fconstexpr-depth 128
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=2 -fconstexpr-depth 2
+// RUN: %clang -std=c++11 -fsyntax-only -Xclang -verify %s -DMAX=10 -fconstexpr-depth=10
+
+constexpr int depth(int n) { return n > 1 ? depth(n-1) : 0; } // expected-note {{exceeded maximum depth}} expected-note +{{}}
+
+constexpr int kBad = depth(MAX + 1); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'depth(}}
+constexpr int kGood = depth(MAX);
diff --git a/test/SemaCXX/constexpr-factorial.cpp b/test/SemaCXX/constexpr-factorial.cpp
new file mode 100644
index 0000000..b6cdde5
--- /dev/null
+++ b/test/SemaCXX/constexpr-factorial.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s
+
+constexpr unsigned oddfac(unsigned n) {
+ return n == 1 ? 1 : n * oddfac(n-2);
+}
+constexpr unsigned k = oddfac(123);
+
+using A = int[k % 256];
+using A = int[43];
diff --git a/test/SemaCXX/constexpr-nqueens.cpp b/test/SemaCXX/constexpr-nqueens.cpp
new file mode 100644
index 0000000..b158d6e
--- /dev/null
+++ b/test/SemaCXX/constexpr-nqueens.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s
+
+typedef unsigned long uint64_t;
+
+struct Board {
+ uint64_t State;
+ bool Failed;
+
+ constexpr Board() : State(0), Failed(false) {}
+ constexpr Board(const Board &O) : State(O.State), Failed(O.Failed) {}
+ constexpr Board(uint64_t State, bool Failed = false) :
+ State(State), Failed(Failed) {}
+ constexpr Board addQueen(int Row, int Col) {
+ return Board(State | ((uint64_t)Row << (Col * 4)));
+ }
+ constexpr int getQueenRow(int Col) {
+ return (State >> (Col * 4)) & 0xf;
+ }
+ constexpr bool ok(int Row, int Col) {
+ return okRecurse(Row, Col, 0);
+ }
+ constexpr bool okRecurse(int Row, int Col, int CheckCol) {
+ return Col == CheckCol ? true :
+ getQueenRow(CheckCol) == Row ? false :
+ getQueenRow(CheckCol) == Row + (Col - CheckCol) ? false :
+ getQueenRow(CheckCol) == Row + (CheckCol - Col) ? false :
+ okRecurse(Row, Col, CheckCol + 1);
+ }
+ constexpr bool at(int Row, int Col) {
+ return getQueenRow(Col) == Row;
+ }
+ constexpr bool check(const char *, int=0, int=0);
+};
+
+constexpr Board buildBoardRecurse(int N, int Col, const Board &B);
+constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B);
+constexpr Board tryBoard(const Board &Try,
+ int N, int Col, int Row, const Board &B) {
+ return Try.Failed ? buildBoardScan(N, Col, Row, B) : Try;
+}
+constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) {
+ return Row == N ? Board(0, true) :
+ B.ok(Row, Col) ?
+ tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)),
+ N, Col, Row+1, B) :
+ buildBoardScan(N, Col, Row + 1, B);
+}
+constexpr Board buildBoardRecurse(int N, int Col, const Board &B) {
+ return Col == N ? B : buildBoardScan(N, Col, 0, B);
+}
+constexpr Board buildBoard(int N) {
+ return buildBoardRecurse(N, 0, Board());
+}
+
+constexpr Board q8 = buildBoard(8);
+
+constexpr bool Board::check(const char *p, int Row, int Col) {
+ return
+ *p == '\n' ? check(p+1, Row+1, 0) :
+ *p == 'o' ? at(Row, Col) && check(p+1, Row, Col+1) :
+ *p == '-' ? !at(Row, Col) && check(p+1, Row, Col+1) :
+ *p == 0 ? true :
+ false;
+}
+static_assert(q8.check(
+ "o-------\n"
+ "------o-\n"
+ "----o---\n"
+ "-------o\n"
+ "-o------\n"
+ "---o----\n"
+ "-----o--\n"
+ "--o-----\n"), "");
diff --git a/test/SemaCXX/constexpr-printing.cpp b/test/SemaCXX/constexpr-printing.cpp
new file mode 100644
index 0000000..9170fa1
--- /dev/null
+++ b/test/SemaCXX/constexpr-printing.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -triple x86_64-linux-gnu
+
+struct S;
+constexpr int extract(const S &s);
+
+struct S {
+ constexpr S() : n(extract(*this)), m(0) {} // expected-note {{in call to 'extract(s1)'}}
+ constexpr S(int k) : n(k), m(extract(*this)) {}
+ 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 S s1; // ok
+void f() {
+ constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}}
+ constexpr S s2(10);
+}
+
+typedef __attribute__((vector_size(16))) int vector_int;
+
+struct T {
+ constexpr T() : arr() {}
+ int arr[4];
+};
+struct U : T {
+ constexpr U(const int *p) : T(), another(), p(p) {}
+ constexpr U(const U &u) : T(), another(), p(u.p) {}
+ T another;
+ const int *p;
+};
+constexpr U u1(&u1.arr[2]);
+
+constexpr int test_printing(int a, float b, _Complex int c, _Complex float d,
+ int *e, int &f, vector_int g, U h) {
+ return *e; // expected-note {{read of non-constexpr variable 'u2'}}
+}
+U u2(0); // expected-note {{here}}
+static_assert(test_printing(12, 39.762, 3 + 4i, 12.9 + 3.6i, &u2.arr[4], u2.another.arr[2], (vector_int){5, 1, 2, 3}, u1) == 0, ""); // \
+expected-error {{constant expression}} \
+expected-note {{in call to 'test_printing(12, 3.976200e+01, 3+4i, 1.290000e+01+3.600000e+00i, &u2.T::arr[4], u2.another.arr[2], {5, 1, 2, 3}, {{{}}, {{}}, &u1.T::arr[2]})'}}
+
+struct V {
+ // FIXME: when we can generate these as constexpr constructors, remove the
+ // explicit definitions.
+ constexpr V() : arr{[255] = 42} {}
+ constexpr V(const V &v) : arr{[255] = 42} {}
+ int arr[256];
+};
+constexpr V v;
+constexpr int get(const int *p) { return *p; } // expected-note {{read of dereferenced one-past-the-end pointer}}
+constexpr int passLargeArray(V v) { return get(v.arr+256); } // expected-note {{in call to 'get(&v.arr[256])'}}
+static_assert(passLargeArray(v) == 0, ""); // expected-error {{constant expression}} expected-note {{in call to 'passLargeArray({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...}})'}}
+
+union Union {
+ constexpr Union(int n) : b(n) {}
+ constexpr Union(const Union &u) : b(u.b) {}
+ int a, b;
+};
+constexpr Union myUnion = 76;
+
+constexpr int badness(Union u) { return u.a + u.b; } // expected-note {{read of member 'a' of union with active member 'b'}}
+static_assert(badness(myUnion), ""); // expected-error {{constant expression}} \
+ expected-note {{in call to 'badness({.b = 76})'}}
+
+struct MemPtrTest {
+ int n;
+ void f();
+};
+MemPtrTest mpt; // expected-note {{here}}
+constexpr int MemPtr(int (MemPtrTest::*a), void (MemPtrTest::*b)(), int &c) {
+ return c; // expected-note {{read of non-constexpr variable 'mpt'}}
+}
+static_assert(MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.*&MemPtrTest::n), ""); // expected-error {{constant expression}} \
+expected-note {{in call to 'MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.n)'}}
+
+template<typename CharT>
+constexpr CharT get(const CharT *p) { return p[-1]; } // expected-note 5{{}}
+
+constexpr char c = get("test\0\\\"\t\a\b\234"); // \
+ expected-error {{}} expected-note {{"test\000\\\"\t\a\b\234"}}
+constexpr char c8 = get(u8"test\0\\\"\t\a\b\234"); // \
+ expected-error {{}} expected-note {{u8"test\000\\\"\t\a\b\234"}}
+constexpr char16_t c16 = get(u"test\0\\\"\t\a\b\234\u1234"); // \
+ expected-error {{}} expected-note {{u"test\000\\\"\t\a\b\234\u1234"}}
+constexpr char32_t c32 = get(U"test\0\\\"\t\a\b\234\u1234\U0010ffff"); // \
+ expected-error {{}} expected-note {{U"test\000\\\"\t\a\b\234\u1234\U0010FFFF"}}
+constexpr wchar_t wc = get(L"test\0\\\"\t\a\b\234\u1234\xffffffff"); // \
+ expected-error {{}} expected-note {{L"test\000\\\"\t\a\b\234\x1234\xFFFFFFFF"}}
+
+constexpr char32_t c32_err = get(U"\U00110000"); // expected-error {{invalid universal character}}
+
+typedef decltype(sizeof(int)) LabelDiffTy;
+constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } // expected-note {{subexpression}}
+void LabelDiffTest() {
+ static_assert(mulBy3((LabelDiffTy)&&a-(LabelDiffTy)&&b) == 3, ""); // expected-error {{constant expression}} expected-note {{call to 'mulBy3(&&a - &&b)'}}
+ a:b:return;
+}
+
+constexpr bool test_bool_printing(bool b) { return 1 / !(2*b | !(2*b)); } // expected-note 2{{division by zero}}
+constexpr bool test_bool_0 = test_bool_printing(false); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(false)'}}
+constexpr bool test_bool_1 = test_bool_printing(true); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(true)'}}
diff --git a/test/SemaCXX/constexpr-strlen.cpp b/test/SemaCXX/constexpr-strlen.cpp
new file mode 100644
index 0000000..5e28e7f
--- /dev/null
+++ b/test/SemaCXX/constexpr-strlen.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -pedantic
+
+# 1 "/usr/include/string.h" 1 3 4
+extern "C" {
+ typedef decltype(sizeof(int)) size_t;
+ extern size_t strlen(const char *p);
+}
+
+# 10 "SemaCXX/constexpr-strlen.cpp" 2
+constexpr int n = __builtin_strlen("hello"); // ok
+constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}}
+
+// Make sure we can evaluate a call to strlen.
+int arr[3]; // expected-note {{here}}
+int k = arr[strlen("hello")]; // expected-warning {{array index 5}}
diff --git a/test/SemaCXX/constexpr-turing.cpp b/test/SemaCXX/constexpr-turing.cpp
new file mode 100644
index 0000000..c515378
--- /dev/null
+++ b/test/SemaCXX/constexpr-turing.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+// A direct proof that constexpr is Turing-complete, once DR1454 is implemented.
+
+const unsigned halt = (unsigned)-1;
+
+enum Dir { L, R };
+struct Action {
+ bool tape;
+ Dir dir;
+ unsigned next;
+};
+using State = Action[2];
+
+// An infinite tape!
+struct Tape {
+ constexpr Tape() : l(0), val(false), r(0) {}
+ constexpr Tape(const Tape &old, bool write) :
+ l(old.l), val(write), r(old.r) {}
+ constexpr Tape(const Tape &old, Dir dir) :
+ l(dir == L ? old.l ? old.l->l : 0 : &old),
+ val(dir == L ? old.l ? old.l->val : false
+ : old.r ? old.r->val : false),
+ r(dir == R ? old.r ? old.r->r : 0 : &old) {}
+ const Tape *l;
+ bool val;
+ const Tape *r;
+};
+constexpr Tape update(const Tape &old, bool write) { return Tape(old, write); }
+constexpr Tape move(const Tape &old, Dir dir) { return Tape(old, dir); }
+
+// Run turing machine 'tm' on tape 'tape' from state 'state'. Return number of
+// steps taken until halt.
+constexpr unsigned run(const State *tm, const Tape &tape, unsigned state) {
+ return state == halt ? 1 :
+ run(tm, move(update(tape, tm[state][tape.val].tape),
+ tm[state][tape.val].dir),
+ tm[state][tape.val].next) + 1;
+}
+
+// 3-state busy beaver. 14 steps.
+constexpr State bb3[] = {
+ { { true, R, 1 }, { true, L, 2 } },
+ { { true, L, 0 }, { true, R, 1 } },
+ { { true, L, 1 }, { true, R, halt } }
+};
+static_assert(run(bb3, Tape(), 0) == 14, "");
+
+// 4-state busy beaver. 108 steps.
+constexpr State bb4[] = {
+ { { true, R, 1 }, { true, L, 1 } },
+ { { true, L, 0 }, { false, L, 2 } },
+ { { true, R, halt }, { true, L, 3 } },
+ { { true, R, 3 }, { false, R, 0 } } };
+static_assert(run(bb4, Tape(), 0) == 108, "");
diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp
new file mode 100644
index 0000000..e459f09
--- /dev/null
+++ b/test/SemaCXX/constexpr-value-init.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify
+
+struct A {
+ constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{uninitialized}}
+ int a;
+ int b;
+};
+struct B {
+ A a;
+};
+
+constexpr A a; // ok, zero initialization preceeds static initialization
+void f() {
+ constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}}
+}
+
+constexpr B b1; // expected-error {{requires a user-provided default constructor}}
+constexpr B b2 = B(); // ok
+static_assert(b2.a.a == 1, "");
+static_assert(b2.a.b == 2, "");
+
+struct C {
+ int c;
+};
+struct D : C { int d; };
+constexpr C c1; // expected-error {{requires a user-provided default constructor}}
+constexpr C c2 = C(); // ok
+constexpr D d1; // expected-error {{requires a user-provided default constructor}}
+constexpr D d2 = D(); // ok with DR1452
+static_assert(D().c == 0, "");
+static_assert(D().d == 0, "");
+
+struct V : virtual C {};
+template<typename T> struct Z : T {
+ constexpr Z() : V() {}
+};
+constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{virtual base class}}
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index e439a76..e8b7f0b 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -74,7 +74,7 @@ class U {
union { int b; double d; };
U() : a(1), // expected-note {{previous initialization is here}}
- p(0), // expected-error {{initializing multiple members of anonymous union}}
+ p(0), // expected-error {{initializing multiple members of union}}
d(1.0) {}
};
@@ -268,3 +268,15 @@ struct S4 {
};
}
+
+namespace PR12049 {
+ int function();
+
+ class Class
+ {
+ public:
+ Class() : member(function() {} // expected-note {{to match this '('}}
+
+ int member; // expected-error {{expected ')'}}
+ };
+}
diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp
index b069abc..a64b187 100644
--- a/test/SemaCXX/conversion.cpp
+++ b/test/SemaCXX/conversion.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion %s 2>&1 | FileCheck %s
#include <stddef.h>
@@ -53,11 +54,30 @@ namespace test2 {
};
}
+// This file tests -Wnull-conversion, a subcategory of -Wconversion
+// which is on by default.
+
void test3() {
- int a = NULL; // expected-warning {{implicit conversion of NULL constant to integer}}
+ int a = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}}
int b;
- b = NULL; // expected-warning {{implicit conversion of NULL constant to integer}}
- int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to integer}}
+ b = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}}
+ long l = NULL; // FIXME: this should also warn, but currently does not if sizeof(NULL)==sizeof(inttype)
+ int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}}
int d;
- d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to integer}}
+ d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}}
+ bool bl = NULL; // FIXME: this should warn but we currently suppress a bunch of conversion-to-bool warnings including this one
+ char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}}
+ unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}}
+ short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}}
+
+ // Use FileCheck to ensure we don't get any unnecessary macro-expansion notes
+ // (that don't appear as 'real' notes & can't be seen/tested by -verify)
+ // CHECK-NOT: note:
+ // CHECK: note: expanded from macro 'FNULL'
+#define FNULL NULL
+ int a2 = FNULL; // expected-warning {{implicit conversion of NULL constant to 'int'}}
+ // CHECK-NOT: note:
+ // CHECK: note: expanded from macro 'FINIT'
+#define FINIT int a3 = NULL;
+ FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}}
}
diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp
index 7aca9d6..798582c 100644
--- a/test/SemaCXX/copy-assignment.cpp
+++ b/test/SemaCXX/copy-assignment.cpp
@@ -98,18 +98,13 @@ void test() {
}
// <rdar://problem/8315440>: Don't crash
-// FIXME: the recovery here is really bad.
namespace test1 {
template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}}
- A(UndeclaredType n) : X(n) {} // expected-error{{expected ')'}} expected-note{{to match this '('}} \
- // expected-error{{use of undeclared identifier 'n'}} \
- // expected-error{{expected ';' at end of declaration list}} \
- // expected-error{{field has incomplete type 'test1::A<char>'}}
+ A(UndeclaredType n) : X(n) {} // expected-error {{unknown type name 'UndeclaredType'}}
};
template<typename T> class B : public A<T> {
virtual void foo() {}
};
- extern template class A<char>; // expected-note {{in instantiation of template class 'test1::A<char>' requested here}} \
- // expected-note {{definition of 'test1::A<char>' is not complete until the closing '}'}}
+ extern template class A<char>;
extern template class B<char>;
}
diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp
index fb83dcf..ea2db0c 100644
--- a/test/SemaCXX/copy-initialization.cpp
+++ b/test/SemaCXX/copy-initialization.cpp
@@ -42,3 +42,26 @@ namespace PR6757 {
f(foo);
}
}
+
+namespace DR5 {
+ // Core issue 5: if a temporary is created in copy-initialization, it is of
+ // the cv-unqualified version of the destination type.
+ namespace Ex1 {
+ struct C { };
+ C c;
+ struct A {
+ A(const A&);
+ A(const C&);
+ };
+ const volatile A a = c; // ok
+ }
+
+ namespace Ex2 {
+ struct S {
+ S(S&&); // expected-warning {{C++11}}
+ S(int);
+ };
+ const S a(0);
+ const S b = 0;
+ }
+}
diff --git a/test/SemaCXX/cxx0x-class.cpp b/test/SemaCXX/cxx0x-class.cpp
index 3527ccb..41b0a5c 100644
--- a/test/SemaCXX/cxx0x-class.cpp
+++ b/test/SemaCXX/cxx0x-class.cpp
@@ -11,18 +11,29 @@ public:
int i = 0;
static int si = 0; // expected-error {{non-const static data member must be initialized out of line}}
static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}}
- static const int nci = vs; // expected-error {{in-class initializer is not a constant expression}}
+ static const int nci = vs; // expected-error {{in-class initializer for static data member is not a constant expression}}
static const int vi = 0;
static const volatile int cvi = 0; // expected-error {{static const volatile data member must be initialized out of line}}
};
namespace rdar8367341 {
- float foo();
+ float foo(); // expected-note {{here}}
struct A {
static const float x = 5.0f; // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}}
- static const float y = foo(); // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} expected-error {{in-class initializer is not a constant expression}}
+ static const float y = foo(); // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} expected-error {{in-class initializer for static data member is not a constant expression}}
static constexpr float x2 = 5.0f;
- static constexpr float y2 = foo(); // expected-error {{must be initialized by a constant expression}}
+ static constexpr float y2 = foo(); // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr function 'foo'}}
+ };
+}
+
+
+namespace Foo {
+ // Regression test -- forward declaration of Foo should not cause error about
+ // nonstatic data member.
+ class Foo;
+ class Foo {
+ int x;
+ int y = x;
};
}
diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp
index a01b26c..123008a 100644
--- a/test/SemaCXX/cxx0x-compat.cpp
+++ b/test/SemaCXX/cxx0x-compat.cpp
@@ -1,18 +1,23 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++0x-compat -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -verify %s
namespace N {
- template<typename T> void f(T) {} // expected-note {{here}}
+ template<typename T> void f(T) {} // expected-note 2{{here}}
namespace M {
- template void f<int>(int); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}}
+ template void ::N::f<int>(int); // expected-warning {{explicit instantiation of 'f' not in a namespace enclosing 'N'}}
}
}
+using namespace N;
+template void f<char>(char); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}}
-template<typename T> void f(T) {} // expected-note {{here}}
+template<typename T> void g(T) {} // expected-note 2{{here}}
namespace M {
- template void f<int>(int); // expected-warning {{explicit instantiation of 'f' must occur in the global namespace}}
+ template void g<int>(int); // expected-warning {{explicit instantiation of 'g' must occur at global scope}}
+ template void ::g<char>(char); // expected-warning {{explicit instantiation of 'g' must occur at global scope}}
}
-void f() {
+template inline void g<double>(double); // expected-warning {{explicit instantiation cannot be 'inline'}}
+
+void g() {
auto int n = 0; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}}
}
@@ -22,3 +27,13 @@ struct S {
}
s = { n }, // expected-warning {{non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list in C++11}} expected-note {{explicit cast}}
t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which cannot be narrowed to type 'char' in C++11}} expected-warning {{changes value}} expected-note {{explicit cast}}
+
+#define PRIuS "uS"
+int printf(const char *, ...);
+typedef __typeof(sizeof(int)) size_t;
+void h(size_t foo, size_t bar) {
+ printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a reserved user-defined literal suffix in C++11}}
+}
+
+#define _x + 1
+char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}}
diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 17933c2..3290595 100644
--- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -67,3 +67,9 @@ struct except_spec_d_mismatch : except_spec_a, except_spec_b {
struct except_spec_d_match : except_spec_a, except_spec_b {
except_spec_d_match() throw(A, B) = default;
};
+
+// gcc-compatibility: allow attributes on default definitions
+// (but not normal definitions)
+struct S { S(); };
+S::S() __attribute((pure)) = default;
+
diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp
index d01f63b..2e4107c 100644
--- a/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -28,7 +28,7 @@ bar& bar::operator = (const bar&) = default;
bar& bar::operator = (bar&) = default;
bar::~bar() = default;
-// FIXME: static_assert(__is_trivial(foo), "foo should be trivial");
+static_assert(__is_trivial(foo), "foo should be trivial");
static_assert(!__has_trivial_destructor(bar), "bar's destructor isn't trivial");
static_assert(!__has_trivial_constructor(bar),
@@ -43,3 +43,11 @@ void tester() {
b = c;
}
+template<typename T> struct S : T {
+ constexpr S() = default;
+ constexpr S(const S&) = default;
+ constexpr S(S&&) = default;
+};
+struct lit { constexpr lit() {} };
+S<lit> s_lit; // ok
+S<bar> s_bar; // ok
diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
index 16c5664..0cebc10 100644
--- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
+++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
@@ -7,27 +7,27 @@ struct non_trivial {
~non_trivial();
};
-union bad_union { // expected-note {{marked deleted here}}
- non_trivial nt;
+union bad_union {
+ non_trivial nt; // expected-note {{non-trivial default constructor}}
};
-bad_union u; // expected-error {{call to deleted constructor}}
-union bad_union2 { // expected-note {{marked deleted here}}
+bad_union u; // expected-error {{call to implicitly-deleted default constructor}}
+union bad_union2 { // expected-note {{all data members are const-qualified}}
const int i;
};
-bad_union2 u2; // expected-error {{call to deleted constructor}}
+bad_union2 u2; // expected-error {{call to implicitly-deleted default constructor}}
-struct bad_anon { // expected-note {{marked deleted here}}
+struct bad_anon {
union {
- non_trivial nt;
+ non_trivial nt; // expected-note {{non-trivial default constructor}}
};
};
-bad_anon a; // expected-error {{call to deleted constructor}}
-struct bad_anon2 { // expected-note {{marked deleted here}}
- union {
+bad_anon a; // expected-error {{call to implicitly-deleted default constructor}}
+struct bad_anon2 {
+ union { // expected-note {{all data members of an anonymous union member are const-qualified}}
const int i;
};
};
-bad_anon2 a2; // expected-error {{call to deleted constructor}}
+bad_anon2 a2; // expected-error {{call to implicitly-deleted default constructor}}
// This would be great except that we implement
union good_union {
@@ -48,10 +48,10 @@ struct good : non_trivial {
};
good g;
-struct bad_const { // expected-note {{marked deleted here}}
- const good g;
+struct bad_const {
+ const good g; // expected-note {{field 'g' of const-qualified type 'const good' would not be initialized}}
};
-bad_const bc; // expected-error {{call to deleted constructor}}
+bad_const bc; // expected-error {{call to implicitly-deleted default constructor}}
struct good_const {
const non_trivial nt;
@@ -59,44 +59,44 @@ struct good_const {
good_const gc;
struct no_default {
- no_default() = delete;
+ no_default() = delete; // expected-note 3{{deleted here}}
};
struct no_dtor {
- ~no_dtor() = delete;
+ ~no_dtor() = delete; // expected-note 2{{deleted here}}
};
-struct bad_field_default { // expected-note {{marked deleted here}}
- no_default nd;
+struct bad_field_default {
+ no_default nd; // expected-note {{field 'nd' has a deleted default constructor}}
};
-bad_field_default bfd; // expected-error {{call to deleted constructor}}
-struct bad_base_default : no_default { // expected-note {{marked deleted here}}
+bad_field_default bfd; // expected-error {{call to implicitly-deleted default constructor}}
+struct bad_base_default : no_default { // expected-note {{base class 'no_default' has a deleted default constructor}}
};
-bad_base_default bbd; // expected-error {{call to deleted constructor}}
+bad_base_default bbd; // expected-error {{call to implicitly-deleted default constructor}}
-struct bad_field_dtor { // expected-note {{marked deleted here}}
- no_dtor nd;
+struct bad_field_dtor {
+ no_dtor nd; // expected-note {{field 'nd' has a deleted destructor}}
};
-bad_field_dtor bfx; // expected-error {{call to deleted constructor}}
-struct bad_base_dtor : no_dtor { // expected-note {{marked deleted here}}
+bad_field_dtor bfx; // expected-error {{call to implicitly-deleted default constructor}}
+struct bad_base_dtor : no_dtor { // expected-note {{base class 'no_dtor' has a deleted destructor}}
};
-bad_base_dtor bbx; // expected-error {{call to deleted constructor}}
+bad_base_dtor bbx; // expected-error {{call to implicitly-deleted default constructor}}
struct ambiguous_default {
ambiguous_default();
ambiguous_default(int = 2);
};
-struct has_amb_field { // expected-note {{marked deleted here}}
- ambiguous_default ad;
+struct has_amb_field {
+ ambiguous_default ad; // expected-note {{field 'ad' has multiple default constructors}}
};
-has_amb_field haf; // expected-error {{call to deleted constructor}}
+has_amb_field haf; // expected-error {{call to implicitly-deleted default constructor}}
class inaccessible_default {
inaccessible_default();
};
-struct has_inacc_field { // expected-note {{marked deleted here}}
- inaccessible_default id;
+struct has_inacc_field {
+ inaccessible_default id; // expected-note {{field 'id' has an inaccessible default constructor}}
};
-has_inacc_field hif; // expected-error {{call to deleted constructor}}
+has_inacc_field hif; // expected-error {{call to implicitly-deleted default constructor}}
class friend_default {
friend struct has_friend;
@@ -108,10 +108,10 @@ struct has_friend {
has_friend hf;
struct defaulted_delete {
- no_default nd;
- defaulted_delete() = default; // expected-note {{marked deleted here}}
+ no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}}
+ defaulted_delete() = default; // expected-note{{implicitly deleted here}}
};
-defaulted_delete dd; // expected-error {{call to deleted constructor}}
+defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}}
struct late_delete {
no_default nd;
@@ -121,12 +121,11 @@ late_delete::late_delete() = default; // expected-error {{would delete it}}
// See also rdar://problem/8125400.
namespace empty {
- static union {}; // expected-error {{deleted constructor}} expected-note {{here}}
+ static union {};
static union { union {}; };
static union { struct {}; };
static union { union { union {}; }; };
static union { union { struct {}; }; };
- static union { struct { union {}; }; }; // expected-error {{deleted constructor}} expected-note {{here}}
+ static union { struct { union {}; }; };
static union { struct { struct {}; }; };
}
-
diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp
new file mode 100644
index 0000000..801a82f
--- /dev/null
+++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+struct one { char c[1]; };
+struct two { char c[2]; };
+
+namespace aggregate {
+ // Direct list initialization does NOT allow braces to be elided!
+ struct S {
+ int ar[2];
+ struct T {
+ int i1;
+ int i2;
+ } t;
+ struct U {
+ int i1;
+ } u[2];
+ struct V {
+ int var[2];
+ } v;
+ };
+
+ void bracing() {
+ S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error
+ S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+ S s3{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+ S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+ S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+ }
+
+ void bracing_new() {
+ new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+ new S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+ new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+ new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+ }
+
+ void bracing_construct() {
+ (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+ (void) S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+ (void) S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+ (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+ }
+
+ struct String {
+ String(const char*);
+ };
+
+ struct A {
+ int m1;
+ int m2;
+ };
+
+ void function_call() {
+ void takes_A(A);
+ takes_A({1, 2});
+ }
+
+ struct B {
+ int m1;
+ String m2;
+ };
+
+ void overloaded_call() {
+ one overloaded(A);
+ two overloaded(B);
+
+ static_assert(sizeof(overloaded({1, 2})) == sizeof(one), "bad overload");
+ static_assert(sizeof(overloaded({1, "two"})) == sizeof(two),
+ "bad overload");
+ // String is not default-constructible
+ static_assert(sizeof(overloaded({1})) == sizeof(one), "bad overload");
+ }
+
+ struct C { int a[2]; C():a({1, 2}) { } }; // expected-error {{parenthesized initialization of a member array is a GNU extension}}
+}
+
+namespace array_explicit_conversion {
+ typedef int test1[2];
+ typedef int test2[];
+ template<int x> struct A { int a[x]; }; // expected-error {{'a' declared as an array with a negative size}}
+ typedef A<1> test3[];
+ typedef A<-1> test4[];
+ void f() {
+ (void)test1{1};
+ (void)test2{1};
+ (void)test3{{{1}}};
+ (void)test4{{{1}}}; // expected-note {{in instantiation of template class 'array_explicit_conversion::A<-1>' requested here}}
+ }
+}
diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp
new file mode 100644
index 0000000..09aca24
--- /dev/null
+++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp
@@ -0,0 +1,283 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+struct one { char c[1]; };
+struct two { char c[2]; };
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
+namespace objects {
+
+ struct X1 { X1(int); };
+ struct X2 { explicit X2(int); }; // expected-note {{constructor declared here}}
+
+ template <int N>
+ struct A {
+ A() { static_assert(N == 0, ""); }
+ A(int, double) { static_assert(N == 1, ""); }
+ };
+
+ template <int N>
+ struct F {
+ F() { static_assert(N == 0, ""); }
+ F(int, double) { static_assert(N == 1, ""); }
+ F(std::initializer_list<int>) { static_assert(N == 3, ""); }
+ };
+
+ template <int N>
+ struct D {
+ D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}}
+ D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}}
+ };
+
+ template <int N>
+ struct E {
+ E(int, int) { static_assert(N == 0, ""); }
+ E(X1, int) { static_assert(N == 1, ""); }
+ };
+
+ void overload_resolution() {
+ { A<0> a{}; }
+ { A<0> a = {}; }
+ { A<1> a{1, 1.0}; }
+ { A<1> a = {1, 1.0}; }
+
+ { F<0> f{}; }
+ { F<0> f = {}; }
+ // Narrowing conversions don't affect viability. The next two choose
+ // the initializer_list constructor.
+ // FIXME: Emit narrowing conversion errors.
+ { F<3> f{1, 1.0}; } // xpected-error {{narrowing conversion}}
+ { F<3> f = {1, 1.0}; } // xpected-error {{narrowing conversion}}
+ { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; }
+ { F<3> f = {1, 2, 3, 4, 5, 6, 7, 8}; }
+ { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; }
+ { F<3> f{1, 2}; }
+
+ { D<0> d{1, 2, 3}; }
+ { D<1> d{1.0, 2.0, 3.0}; }
+ { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}}
+
+ { E<0> e{1, 2}; }
+ }
+
+ void explicit_implicit() {
+ { X1 x{0}; }
+ { X1 x = {0}; }
+ { X2 x{0}; }
+ { X2 x = {0}; } // expected-error {{constructor is explicit}}
+ }
+
+ struct C {
+ C();
+ C(int, double);
+ C(int, int);
+
+ int operator[](C);
+ };
+
+ C function_call() {
+ void takes_C(C);
+ takes_C({1, 1.0});
+
+ C c;
+ c[{1, 1.0}];
+
+ return {1, 1.0};
+ }
+
+ void inline_init() {
+ (void) C{1, 1.0};
+ (void) new C{1, 1.0};
+ (void) A<1>{1, 1.0};
+ (void) new A<1>{1, 1.0};
+ }
+
+ struct B { // expected-note 2 {{candidate constructor}}
+ B(C, int, C); // expected-note {{candidate constructor not viable: cannot convert initializer list argument to 'objects::C'}}
+ };
+
+ void nested_init() {
+ B b1{{1, 1.0}, 2, {3, 4}};
+ B b2{{1, 1.0, 4}, 2, {3, 4}}; // expected-error {{no matching constructor for initialization of 'objects::B'}}
+ }
+
+ void overloaded_call() {
+ one ov1(B); // expected-note {{not viable: cannot convert initializer list}}
+ two ov1(C); // expected-note {{not viable: cannot convert initializer list}}
+
+ static_assert(sizeof(ov1({})) == sizeof(two), "bad overload");
+ static_assert(sizeof(ov1({1, 2})) == sizeof(two), "bad overload");
+ static_assert(sizeof(ov1({{1, 1.0}, 2, {3, 4}})) == sizeof(one), "bad overload");
+
+ ov1({1}); // expected-error {{no matching function}}
+
+ one ov2(int);
+ two ov2(F<3>);
+ static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity
+ static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable
+ }
+
+ struct G { // expected-note 6 {{not viable}}
+ // This is not an initializer-list constructor.
+ template<typename ...T>
+ G(std::initializer_list<int>, T ...); // expected-note 3 {{not viable}}
+ };
+
+ struct H { // expected-note 6 {{not viable}}
+ explicit H(int, int); // expected-note 3 {{not viable}} expected-note {{declared here}}
+ H(int, void*); // expected-note 3 {{not viable}}
+ };
+
+ void edge_cases() {
+ // invalid (the first phase only considers init-list ctors)
+ // (for the second phase, no constructor is viable)
+ G g1{1, 2, 3}; // expected-error {{no matching constructor}}
+ (void) new G{1, 2, 3}; // expected-error {{no matching constructor}}
+ (void) G{1, 2, 3} // expected-error {{no matching constructor}}
+
+ // valid (T deduced to <>).
+ G g2({1, 2, 3});
+ (void) new G({1, 2, 3});
+ (void) G({1, 2, 3});
+
+ // invalid
+ H h1({1, 2}); // expected-error {{no matching constructor}}
+ (void) new H({1, 2}); // expected-error {{no matching constructor}}
+ // FIXME: Bad diagnostic, mentions void type instead of init list.
+ (void) H({1, 2}); // expected-error {{no matching conversion}}
+
+ // valid (by copy constructor).
+ H h2({1, nullptr});
+ (void) new H({1, nullptr});
+ (void) H({1, nullptr});
+
+ // valid
+ H h3{1, 2};
+ (void) new H{1, 2};
+ (void) H{1, 2};
+ }
+
+ struct memberinit {
+ H h1{1, nullptr};
+ H h2 = {1, nullptr};
+ H h3{1, 1};
+ H h4 = {1, 1}; // expected-error {{constructor is explicit}}
+ };
+}
+
+namespace PR12092 {
+
+ struct S {
+ S(const char*);
+ };
+ struct V {
+ template<typename T> V(T, T);
+ void f(std::initializer_list<S>);
+ void f(const V &);
+ };
+
+ void g() {
+ extern V s;
+ s.f({"foo", "bar"});
+ }
+
+}
+
+namespace PR12117 {
+ struct A { A(int); };
+ struct B { B(A); } b{{0}};
+ struct C { C(int); } c{0};
+}
+
+namespace PR12167 {
+ template<int N> struct string {};
+
+ struct X {
+ X(const char v);
+ template<typename T> bool operator()(T) const;
+ };
+
+ template<int N, class Comparator> bool g(const string<N>& s, Comparator cmp) {
+ return cmp(s);
+ }
+ template<int N> bool f(const string<N> &s) {
+ return g(s, X{'x'});
+ }
+
+ bool s = f(string<1>());
+}
+
+namespace PR12257_PR12241 {
+ struct command_pair
+ {
+ command_pair(int, int);
+ };
+
+ struct command_map
+ {
+ command_map(std::initializer_list<command_pair>);
+ };
+
+ struct generator_pair
+ {
+ generator_pair(const command_map);
+ };
+
+ // 5 levels: init list, gen_pair, command_map, init list, command_pair
+ const std::initializer_list<generator_pair> x = {{{{{3, 4}}}}};
+
+ // 4 levels: init list, gen_pair, command_map via init list, command_pair
+ const std::initializer_list<generator_pair> y = {{{{1, 2}}}};
+}
+
+namespace PR12120 {
+ struct A { explicit A(int); A(float); }; // expected-note {{declared here}}
+ A a = { 0 }; // expected-error {{constructor is explicit}}
+
+ struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}}
+ B b = { 0 }; // expected-error {{ambiguous}}
+}
+
+namespace PR12498 {
+ class ArrayRef; // expected-note{{forward declaration}}
+
+ struct C {
+ void foo(const ArrayRef&); // expected-note{{passing argument to parameter here}}
+ };
+
+ static void bar(C* c)
+ {
+ c->foo({ nullptr, 1 }); // expected-error{{initialization of incomplete type 'const PR12498::ArrayRef'}}
+ }
+
+}
diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp
new file mode 100644
index 0000000..d8fdd5a
--- /dev/null
+++ b/test/SemaCXX/cxx0x-initializer-references.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+struct one { char c; };
+struct two { char c[2]; };
+
+namespace reference {
+ struct A {
+ int i1, i2;
+ };
+
+ void single_init() {
+ const int &cri1a = {1};
+ const int &cri1b{1};
+
+ int i = 1;
+ int &ri1a = {i};
+ int &ri1b{i};
+
+ int &ri2 = {1}; // expected-error {{cannot bind to an initializer list temporary}}
+
+ A a{1, 2};
+ A &ra1a = {a};
+ A &ra1b{a};
+ }
+
+ void reference_to_aggregate() {
+ const A &ra1{1, 2};
+ A &ra2{1, 2}; // expected-error {{cannot bind to an initializer list temporary}}
+
+ const int (&arrayRef)[] = {1, 2, 3};
+ static_assert(sizeof(arrayRef) == 3 * sizeof(int), "bad array size");
+ }
+
+ struct B {
+ int i1;
+ };
+
+ void call() {
+ void f(const int&);
+ f({1});
+
+ void g(int&); // expected-note {{passing argument}}
+ g({1}); // expected-error {{cannot bind to an initializer list temporary}}
+ int i = 0;
+ g({i});
+
+ void h(const B&);
+ h({1});
+
+ void a(B&); // expected-note {{passing argument}}
+ a({1}); // expected-error {{cannot bind to an initializer list temporary}}
+ B b{1};
+ a({b});
+ }
+
+ void overloading() {
+ one f(const int&);
+ two f(const B&);
+
+ // First is identity conversion, second is user-defined conversion.
+ static_assert(sizeof(f({1})) == sizeof(one), "bad overload resolution");
+
+ one g(int&);
+ two g(const B&);
+
+ static_assert(sizeof(g({1})) == sizeof(two), "bad overload resolution");
+
+ one h(const int&);
+ two h(const A&);
+
+ static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution");
+ }
+
+ void edge_cases() {
+ // FIXME: very poor error message
+ int const &b({0}); // expected-error {{could not bind}}
+ }
+
+}
+
+namespace PR12182 {
+ void f(int const(&)[3]);
+
+ void g() {
+ f({1, 2});
+ }
+}
diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp
index 41fc219..627855e 100644
--- a/test/SemaCXX/cxx0x-initializer-scalars.cpp
+++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp
@@ -1,5 +1,40 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+struct one { char c[1]; };
+struct two { char c[2]; };
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
namespace integral {
void initialization() {
@@ -12,6 +47,8 @@ namespace integral {
// FIXME: Redundant warnings.
{ const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}}
{ const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}}
+ { if (const int a{1}) static_assert(a == 1, ""); }
+ { if (const int a = {1}) static_assert(a == 1, ""); }
}
int direct_usage() {
@@ -22,7 +59,7 @@ namespace integral {
}
void inline_init() {
- (void) int{1};
+ auto v = int{1};
(void) new int{1};
}
@@ -31,4 +68,49 @@ namespace integral {
A() : i{1} {}
};
+ void function_call() {
+ void takes_int(int);
+ takes_int({1});
+ }
+
+ void overloaded_call() {
+ one overloaded(int);
+ two overloaded(double);
+
+ static_assert(sizeof(overloaded({0})) == sizeof(one), "bad overload");
+ static_assert(sizeof(overloaded({0.0})) == sizeof(two), "bad overload");
+
+ void ambiguous(int, double); // expected-note {{candidate}}
+ void ambiguous(double, int); // expected-note {{candidate}}
+ ambiguous({0}, {0}); // expected-error {{ambiguous}}
+
+ void emptylist(int);
+ void emptylist(int, int, int);
+ emptylist({});
+ emptylist({}, {}, {});
+ }
+
+ void edge_cases() {
+ // FIXME: very poor error message
+ int a({0}); // expected-error {{cannot initialize}}
+ (void) int({0}); // expected-error {{functional-style cast}}
+ new int({0}); // expected-error {{cannot initialize}}
+ }
+
+ void default_argument(int i = {}) {
+ }
+ struct DefaultArgument {
+ void default_argument(int i = {}) {
+ }
+ };
+}
+
+namespace PR12118 {
+ void test() {
+ one f(std::initializer_list<int>);
+ two f(int);
+
+ // to initializer_list is preferred
+ static_assert(sizeof(f({0})) == sizeof(one), "bad overload");
+ }
}
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
new file mode 100644
index 0000000..7384309
--- /dev/null
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -0,0 +1,177 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+// This must obviously come before the definition of std::initializer_list.
+void missing_initializerlist() {
+ auto l = {1, 2, 3, 4}; // expected-error {{std::initializer_list was not found}}
+}
+
+namespace std {
+ typedef decltype(sizeof(int)) size_t;
+
+ // libc++'s implementation
+ template <class _E>
+ class initializer_list
+ {
+ const _E* __begin_;
+ size_t __size_;
+
+ initializer_list(const _E* __b, size_t __s)
+ : __begin_(__b),
+ __size_(__s)
+ {}
+
+ public:
+ typedef _E value_type;
+ typedef const _E& reference;
+ typedef const _E& const_reference;
+ typedef size_t size_type;
+
+ typedef const _E* iterator;
+ typedef const _E* const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const {return __size_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __begin_ + __size_;}
+ };
+}
+
+template <typename T, typename U>
+struct same_type { static const bool value = false; };
+template <typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+struct one { char c[1]; };
+struct two { char c[2]; };
+
+struct A {
+ int a, b;
+};
+
+struct B {
+ B();
+ B(int, int);
+};
+
+void simple_list() {
+ std::initializer_list<int> il = { 1, 2, 3 };
+ std::initializer_list<double> dl = { 1.0, 2.0, 3 };
+ std::initializer_list<A> al = { {1, 2}, {2, 3}, {3, 4} };
+ std::initializer_list<B> bl = { {1, 2}, {2, 3}, {} };
+}
+
+void function_call() {
+ void f(std::initializer_list<int>);
+ f({1, 2, 3});
+
+ void g(std::initializer_list<B>);
+ g({ {1, 2}, {2, 3}, {} });
+}
+
+struct C {
+ C(int);
+};
+
+struct D {
+ D();
+ operator int();
+ operator C();
+};
+
+void overloaded_call() {
+ one overloaded(std::initializer_list<int>);
+ two overloaded(std::initializer_list<B>);
+
+ static_assert(sizeof(overloaded({1, 2, 3})) == sizeof(one), "bad overload");
+ static_assert(sizeof(overloaded({ {1, 2}, {2, 3}, {} })) == sizeof(two), "bad overload");
+
+ void ambiguous(std::initializer_list<A>); // expected-note {{candidate}}
+ void ambiguous(std::initializer_list<B>); // expected-note {{candidate}}
+ ambiguous({ {1, 2}, {2, 3}, {3, 4} }); // expected-error {{ambiguous}}
+
+ one ov2(std::initializer_list<int>); // expected-note {{candidate}}
+ two ov2(std::initializer_list<C>); // expected-note {{candidate}}
+ // Worst sequence to int is identity, whereas to C it's user-defined.
+ static_assert(sizeof(ov2({1, 2, 3})) == sizeof(one), "bad overload");
+ // But here, user-defined is worst in both cases.
+ ov2({1, 2, D()}); // expected-error {{ambiguous}}
+}
+
+template <typename T>
+T deduce(std::initializer_list<T>); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
+template <typename T>
+T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
+
+void argument_deduction() {
+ static_assert(same_type<decltype(deduce({1, 2, 3})), int>::value, "bad deduction");
+ static_assert(same_type<decltype(deduce({1.0, 2.0, 3.0})), double>::value, "bad deduction");
+
+ deduce({1, 2.0}); // expected-error {{no matching function}}
+
+ static_assert(same_type<decltype(deduce_ref({1, 2, 3})), int>::value, "bad deduction");
+ static_assert(same_type<decltype(deduce_ref({1.0, 2.0, 3.0})), double>::value, "bad deduction");
+
+ deduce_ref({1, 2.0}); // expected-error {{no matching function}}
+}
+
+void auto_deduction() {
+ auto l = {1, 2, 3, 4};
+ static_assert(same_type<decltype(l), std::initializer_list<int>>::value, "");
+ auto bl = {1, 2.0}; // expected-error {{cannot deduce}}
+
+ for (int i : {1, 2, 3, 4}) {}
+}
+
+void dangle() {
+ new auto{1, 2, 3}; // expected-error {{cannot use list-initialization}}
+ new std::initializer_list<int>{1, 2, 3}; // expected-warning {{at the end of the full-expression}}
+}
+
+struct haslist1 {
+ std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}
+ std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}
+ haslist1();
+};
+
+haslist1::haslist1()
+: il{1, 2, 3} // expected-warning{{at the end of the constructor}}
+{}
+
+namespace PR12119 {
+ // Deduction with nested initializer lists.
+ template<typename T> void f(std::initializer_list<T>);
+ template<typename T> void g(std::initializer_list<std::initializer_list<T>>);
+
+ void foo() {
+ f({0, {1}});
+ g({{0, 1}, {2, 3}});
+ std::initializer_list<int> il = {1, 2};
+ g({il, {2, 3}});
+ }
+}
+
+namespace Decay {
+ template<typename T>
+ void f(std::initializer_list<T>) {
+ T x = 1; // expected-error{{cannot initialize a variable of type 'const char *' with an rvalue of type 'int'}}
+ }
+
+ void g() {
+ f({"A", "BB", "CCC"}); // expected-note{{in instantiation of function template specialization 'Decay::f<const char *>' requested here}}
+
+ auto x = { "A", "BB", "CCC" };
+ std::initializer_list<const char *> *il = &x;
+
+ for( auto s : {"A", "BB", "CCC", "DDD"}) { }
+ }
+}
+
+namespace PR12436 {
+ struct X {
+ template<typename T>
+ X(std::initializer_list<int>, T);
+ };
+
+ X x({}, 17);
+}
diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp
index 6275af6..0e4add8 100644
--- a/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -10,9 +10,20 @@ struct non_trivial {
union u {
non_trivial nt;
};
+union u2 {
+ non_trivial nt;
+ int k;
+ u2(int k) : k(k) {}
+ u2() : nt() {}
+};
+
+union static_data_member {
+ static int i;
+};
+int static_data_member::i;
union bad {
- static int i; // expected-error {{static data member}}
+ int &i; // expected-error {{union member 'i' has reference type 'int &'}}
};
struct s {
@@ -20,3 +31,94 @@ struct s {
non_trivial nt;
};
};
+
+// Don't crash on this.
+struct TemplateCtor { template<typename T> TemplateCtor(T); };
+union TemplateCtorMember { TemplateCtor s; };
+
+template<typename T> struct remove_ref { typedef T type; };
+template<typename T> struct remove_ref<T&> { typedef T type; };
+template<typename T> struct remove_ref<T&&> { typedef T type; };
+template<typename T> T &&forward(typename remove_ref<T>::type &&t);
+template<typename T> T &&forward(typename remove_ref<T>::type &t);
+template<typename T> typename remove_ref<T>::type &&move(T &&t);
+
+using size_t = decltype(sizeof(int));
+void *operator new(size_t, void *p) noexcept { return p; }
+
+namespace disabled_dtor {
+ template<typename T>
+ union disable_dtor {
+ T val;
+ template<typename...U>
+ disable_dtor(U &&...u) : val(forward<U>(u)...) {}
+ ~disable_dtor() {}
+ };
+
+ struct deleted_dtor {
+ deleted_dtor(int n, char c) : n(n), c(c) {}
+ int n;
+ char c;
+ ~deleted_dtor() = delete;
+ };
+
+ disable_dtor<deleted_dtor> dd(4, 'x');
+}
+
+namespace optional {
+ template<typename T> struct optional {
+ bool has;
+ union { T value; };
+
+ optional() : has(false) {}
+ template<typename...U>
+ optional(U &&...u) : has(true), value(forward<U>(u)...) {}
+
+ optional(const optional &o) : has(o.has) {
+ if (has) new (&value) T(o.value);
+ }
+ optional(optional &&o) : has(o.has) {
+ if (has) new (&value) T(move(o.value));
+ }
+
+ optional &operator=(const optional &o) {
+ if (has) {
+ if (o.has)
+ value = o.value;
+ else
+ value.~T();
+ } else if (o.has) {
+ new (&value) T(o.value);
+ }
+ has = o.has;
+ }
+ optional &operator=(optional &&o) {
+ if (has) {
+ if (o.has)
+ value = move(o.value);
+ else
+ value.~T();
+ } else if (o.has) {
+ new (&value) T(move(o.value));
+ }
+ has = o.has;
+ }
+
+ ~optional() {
+ if (has)
+ value.~T();
+ }
+
+ explicit operator bool() const { return has; }
+ T &operator*() const { return value; }
+ };
+
+ optional<non_trivial> o1;
+ optional<non_trivial> o2{non_trivial()};
+ optional<non_trivial> o3{*o2};
+ void f() {
+ if (o2)
+ o1 = o2;
+ o2 = optional<non_trivial>();
+ }
+}
diff --git a/test/SemaCXX/cxx0x-return-init-list.cpp b/test/SemaCXX/cxx0x-return-init-list.cpp
index b786922..da83271 100644
--- a/test/SemaCXX/cxx0x-return-init-list.cpp
+++ b/test/SemaCXX/cxx0x-return-init-list.cpp
@@ -1,17 +1,15 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-// This test checks for a teeny tiny subset of the functionality in
-// the C++11 generalized initializer lists feature, which happens to
-// be used in libstdc++ 4.5. We accept only this syntax so that Clang
-// can handle the libstdc++ 4.5 headers.
+// Test that a very basic variation of generalized initializer returns (that
+// required for libstdc++ 4.5) is supported in C++98.
int test0(int i) {
- return { i }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}}
+ return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}}
}
template<typename T, typename U>
T test1(U u) {
- return { u }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}}
+ return { u }; // expected-warning{{generalized initializer lists are a C++11 extension}}
}
template int test1(char);
diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp
new file mode 100644
index 0000000..afabf88
--- /dev/null
+++ b/test/SemaCXX/cxx11-ast-print.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -std=c++11 -ast-print %s | FileCheck %s
+
+// FIXME: Print the trailing-return-type properly.
+// CHECK: decltype(nullptr) operator "" _foo(const char *p, decltype(sizeof(int)));
+auto operator"" _foo(const char *p, decltype(sizeof(int))) -> decltype(nullptr);
+
+// CHECK: decltype(""_foo) operator "" _bar(unsigned long long);
+decltype(""_foo) operator"" _bar(unsigned long long);
+
+// CHECK: decltype(42_bar) operator "" _baz(long double);
+decltype(42_bar) operator"" _baz(long double);
+
+// CHECK: decltype(4.5_baz) operator "" _baz(char);
+decltype(4.5_baz) operator"" _baz(char);
+
+// CHECK: const char *operator "" _quux(const char *);
+const char *operator"" _quux(const char *);
+
+// CHECK: template <char...> const char *operator "" _fritz();
+template<char...> const char *operator"" _fritz();
+
+// CHECK: const char *p1 = "bar1"_foo;
+const char *p1 = "bar1"_foo;
+// CHECK: const char *p2 = "bar2"_foo;
+const char *p2 = R"x(bar2)x"_foo;
+// CHECK: const char *p3 = u8"bar3"_foo;
+const char *p3 = u8"bar3"_foo;
+// CHECK: const char *p4 = 297_bar;
+const char *p4 = 0x129_bar;
+// CHECK: const char *p5 = 1.0E+12_baz;
+const char *p5 = 1e12_baz;
+// CHECK: const char *p6 = 'x'_baz;
+const char *p6 = 'x'_baz;
+// CHECK: const char *p7 = 123_quux;
+const char *p7 = 123_quux;
+// CHECK: const char *p8 = 4.9_quux;
+const char *p8 = 4.9_quux;
+// CHECK: const char *p9 = 0x42e3F_fritz;
+const char *p9 = 0x42e3F_fritz;
+// CHECK: const char *p10 = 3.300e+15_fritz;
+const char *p10 = 3.300e+15_fritz;
diff --git a/test/SemaCXX/cxx11-user-defined-literals.cpp b/test/SemaCXX/cxx11-user-defined-literals.cpp
new file mode 100644
index 0000000..4bbecdb
--- /dev/null
+++ b/test/SemaCXX/cxx11-user-defined-literals.cpp
@@ -0,0 +1,137 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -fms-extensions -triple x86_64-apple-darwin9.0.0
+
+using size_t = decltype(sizeof(int));
+enum class LitKind {
+ Char, WideChar, Char16, Char32,
+ CharStr, WideStr, Char16Str, Char32Str,
+ Integer, Floating, Raw, Template
+};
+constexpr LitKind operator"" _kind(char p) { return LitKind::Char; }
+constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; }
+constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; }
+constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; }
+constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; }
+constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; }
+constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; }
+constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; }
+constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; }
+constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; }
+constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; }
+template<char ...Cs> constexpr LitKind operator"" _kind3() { return LitKind::Template; }
+
+static_assert('x'_kind == LitKind::Char, "");
+static_assert(L'x'_kind == LitKind::WideChar, "");
+static_assert(u'x'_kind == LitKind::Char16, "");
+static_assert(U'x'_kind == LitKind::Char32, "");
+static_assert("foo"_kind == LitKind::CharStr, "");
+static_assert(u8"foo"_kind == LitKind::CharStr, "");
+static_assert(L"foo"_kind == LitKind::WideStr, "");
+static_assert(u"foo"_kind == LitKind::Char16Str, "");
+static_assert(U"foo"_kind == LitKind::Char32Str, "");
+static_assert(194_kind == LitKind::Integer, "");
+static_assert(0377_kind == LitKind::Integer, "");
+static_assert(0x5ffc_kind == LitKind::Integer, "");
+static_assert(.5954_kind == LitKind::Floating, "");
+static_assert(1._kind == LitKind::Floating, "");
+static_assert(1.e-2_kind == LitKind::Floating, "");
+static_assert(4e6_kind == LitKind::Floating, "");
+static_assert(4e6_kind2 == LitKind::Raw, "");
+static_assert(4e6_kind3 == LitKind::Template, "");
+
+constexpr const char *fractional_digits_impl(const char *p) {
+ return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0;
+}
+constexpr const char *operator"" _fractional_digits(const char *p) {
+ return fractional_digits_impl(p) ?: p;
+}
+constexpr bool streq(const char *p, const char *q) {
+ return *p == *q && (!*p || streq(p+1, q+1));
+}
+
+static_assert(streq(143.97_fractional_digits, "97"), "");
+static_assert(streq(0x786_fractional_digits, "0x786"), "");
+static_assert(streq(.4_fractional_digits, "4"), "");
+static_assert(streq(4._fractional_digits, ""), "");
+static_assert(streq(1e+97_fractional_digits, "1e+97"), "");
+static_assert(streq(0377_fractional_digits, "0377"), "");
+static_assert(streq(0377.5_fractional_digits, "5"), "");
+
+int operator"" _ambiguous(char); // expected-note {{candidate}}
+namespace N {
+ void *operator"" _ambiguous(char); // expected-note {{candidate}}
+}
+using namespace N;
+int k = 'x'_ambiguous; // expected-error {{ambiguous}}
+
+int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}}
+int m = 42_deleted; // expected-error {{attempt to use a deleted}}
+
+namespace Using {
+ namespace M {
+ int operator"" _using(char);
+ }
+ int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator "" _using'}}
+
+ using M::operator "" _using;
+ int k2 = 'x'_using;
+}
+
+namespace AmbiguousRawTemplate {
+ int operator"" _ambig1(const char *); // expected-note {{candidate}}
+ template<char...> int operator"" _ambig1(); // expected-note {{candidate}}
+
+ int k1 = 123_ambig1; // expected-error {{call to 'operator "" _ambig1' is ambiguous}}
+
+ namespace Inner {
+ template<char...> int operator"" _ambig2(); // expected-note 3{{candidate}}
+ }
+ int operator"" _ambig2(const char *); // expected-note 3{{candidate}}
+ using Inner::operator"" _ambig2;
+
+ int k2 = 123_ambig2; // expected-error {{call to 'operator "" _ambig2' is ambiguous}}
+
+ namespace N {
+ using Inner::operator"" _ambig2;
+
+ int k3 = 123_ambig2; // ok
+
+ using AmbiguousRawTemplate::operator"" _ambig2;
+
+ int k4 = 123_ambig2; // expected-error {{ambiguous}}
+
+ namespace M {
+
+ template<char...> int operator"" _ambig2();
+
+ int k5 = 123_ambig2; // ok
+ }
+
+ int operator"" _ambig2(unsigned long long);
+
+ int k6 = 123_ambig2; // ok
+ int k7 = 123._ambig2; // expected-error {{ambiguous}}
+ }
+}
+
+constexpr unsigned mash(unsigned a) {
+ return 0x93ae27b5 * ((a >> 13) | a << 19);
+}
+template<typename=void> constexpr unsigned hash(unsigned a) { return a; }
+template<char C, char...Cs> constexpr unsigned hash(unsigned a) {
+ return hash<Cs...>(mash(a ^ mash(C)));
+}
+template<typename T, T v> struct constant { constexpr static T value = v; };
+template<char...Cs> constexpr unsigned operator"" _hash() {
+ return constant<unsigned, hash<Cs...>(0)>::value;
+}
+static_assert(0x1234_hash == 0x103eff5e, "");
+static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, "");
+
+// Functions and literal suffixes go in separate namespaces.
+namespace Namespace {
+ template<char...> int operator"" _x();
+ int k = _x(); // expected-error {{undeclared identifier '_x'}}
+
+ int _y(unsigned long long);
+ int k2 = 123_y; // expected-error {{no matching literal operator for call to 'operator "" _y'}}
+}
diff --git a/test/SemaCXX/cxx98-compat-flags.cpp b/test/SemaCXX/cxx98-compat-flags.cpp
new file mode 100644
index 0000000..6dc24be
--- /dev/null
+++ b/test/SemaCXX/cxx98-compat-flags.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Wno-bind-to-temporary-copy -Wno-unnamed-type-template-args -Wno-local-type-template-args -Werror %s
+
+template<typename T> int TemplateFn(T) { return 0; }
+void LocalTemplateArg() {
+ struct S {};
+ TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}}
+}
+struct {} obj_of_unnamed_type; // expected-note {{here}}
+int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}}
+
+namespace CopyCtorIssues {
+ struct Private {
+ Private();
+ private:
+ Private(const Private&); // expected-note {{declared private here}}
+ };
+ struct NoViable {
+ NoViable();
+ NoViable(NoViable&); // expected-note {{not viable}}
+ };
+ struct Ambiguous {
+ Ambiguous();
+ Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}}
+ Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}}
+ };
+ struct Deleted {
+ Private p; // expected-note {{copy constructor of 'Deleted' is implicitly deleted because field 'p' has an inaccessible copy constructor}}
+ };
+
+ const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}}
+ const NoViable &b = NoViable(); // expected-warning {{copying variable of type 'CopyCtorIssues::NoViable' when binding a reference to a temporary would find no viable constructor in C++98}}
+ const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}}
+ const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}}
+}
diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp
index 2ca0ae4..00532d5 100644
--- a/test/SemaCXX/cxx98-compat-pedantic.cpp
+++ b/test/SemaCXX/cxx98-compat-pedantic.cpp
@@ -1,4 +1,5 @@
// 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
// -Wc++98-compat-pedantic warns on C++11 features which we accept without a
@@ -9,3 +10,25 @@
#define VA_MACRO(x, ...) x // expected-warning {{variadic macros are incompatible with C++98}}
VA_MACRO(,x) // expected-warning {{empty macro argument list is incompatible with C++98}}
+
+; // expected-warning {{extra ';' outside of a function is incompatible with C++98}}
+
+enum Enum {
+ Enum_value, // expected-warning {{commas at the end of enumerator lists are incompatible with C++98}}
+};
+
+template<typename T> struct InstantiationAfterSpecialization {};
+template<> struct InstantiationAfterSpecialization<int> {}; // expected-note {{here}}
+template struct InstantiationAfterSpecialization<int>; // expected-warning {{explicit instantiation of 'InstantiationAfterSpecialization<int>' that occurs after an explicit specialization is incompatible with C++98}}
+
+void *dlsym();
+void (*FnPtr)() = (void(*)())dlsym(); // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}}
+void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}}
+
+struct ConvertToInt {
+ operator int();
+};
+int *ArraySizeConversion = new int[ConvertToInt()]; // expected-warning {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}}
+
+template<typename T> class ExternTemplate {};
+extern template class ExternTemplate<int>; // expected-warning {{extern templates are incompatible with C++98}}
diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp
index 6a3881c..4758913 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s
+
+namespace std { struct type_info; }
template<typename ...T> // expected-warning {{variadic templates are incompatible with C++98}}
class Variadic1 {};
@@ -27,4 +30,272 @@ void Literals() {
}
template<typename T> struct S {};
-S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}}
+namespace TemplateParsing {
+ S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}}
+ S< ::S<void>> t; // expected-warning {{consecutive right angle brackets are incompatible with C++98 (use '> >')}}
+}
+
+void Lambda() {
+ []{}(); // expected-warning {{lambda expressions are incompatible with C++98}}
+}
+
+int InitList(int i = {}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} \
+ // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
+ (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
+ // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
+ (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
+ // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
+ int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+ S<int> s = {}; // ok, aggregate
+ s = {}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+ return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+}
+struct DelayedDefaultArgumentParseInitList {
+ void f(int i = {1}) { // expected-warning {{generalized initializer lists are incompatible with C++98}}
+ }
+};
+
+int operator"" _hello(const char *); // expected-warning {{literal operators are incompatible with C++98}}
+
+enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}}
+};
+
+enum class EnumScoped { // expected-warning {{scoped enumerations are incompatible with C++98}}
+};
+
+void Deleted() = delete; // expected-warning {{deleted function definitions are incompatible with C++98}}
+struct Defaulted {
+ Defaulted() = default; // expected-warning {{defaulted function definitions are incompatible with C++98}}
+};
+
+int &&RvalueReference = 0; // expected-warning {{rvalue references are incompatible with C++98}}
+struct RefQualifier {
+ void f() &; // expected-warning {{reference qualifiers on functions are incompatible with C++98}}
+};
+
+auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}}
+
+void RangeFor() {
+ int xs[] = {1, 2, 3};
+ for (int &a : xs) { // expected-warning {{range-based for loop is incompatible with C++98}}
+ }
+}
+
+struct InClassInit {
+ int n = 0; // expected-warning {{in-class initialization of non-static data members is incompatible with C++98}}
+};
+
+struct OverrideControlBase {
+ virtual void f();
+ virtual void g();
+};
+struct OverrideControl final : OverrideControlBase { // expected-warning {{'final' keyword is incompatible with C++98}}
+ virtual void f() override; // expected-warning {{'override' keyword is incompatible with C++98}}
+ virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}}
+};
+
+using AliasDecl = int; // expected-warning {{alias declarations are incompatible with C++98}}
+template<typename T> using AliasTemplate = T; // expected-warning {{alias declarations are incompatible with C++98}}
+
+inline namespace InlineNS { // expected-warning {{inline namespaces are incompatible with C++98}}
+}
+
+auto auto_deduction = 0; // expected-warning {{'auto' type specifier is incompatible with C++98}}
+int *p = new auto(0); // expected-warning {{'auto' type specifier is incompatible with C++98}}
+
+const int align_of = alignof(int); // expected-warning {{alignof expressions are incompatible with C++98}}
+char16_t c16 = 0; // expected-warning {{'char16_t' type specifier is incompatible with C++98}}
+char32_t c32 = 0; // expected-warning {{'char32_t' type specifier is incompatible with C++98}}
+constexpr int const_expr = 0; // expected-warning {{'constexpr' specifier is incompatible with C++98}}
+decltype(const_expr) decl_type = 0; // expected-warning {{'decltype' type specifier is incompatible with C++98}}
+__decltype(const_expr) decl_type2 = 0; // ok
+void no_except() noexcept; // expected-warning {{noexcept specifications are incompatible with C++98}}
+bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expressions are incompatible with C++98}}
+void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}}
+static_assert(true, "!"); // expected-warning {{static_assert declarations are incompatible with C++98}}
+
+struct InhCtorBase {
+ InhCtorBase(int);
+};
+struct InhCtorDerived : InhCtorBase {
+ using InhCtorBase::InhCtorBase; // expected-warning {{inherited constructors are incompatible with C++98}}
+};
+
+struct FriendMember {
+ static void MemberFn();
+ friend void FriendMember::MemberFn(); // expected-warning {{friend declaration naming a member of the declaring class is incompatible with C++98}}
+};
+
+struct DelegCtor {
+ DelegCtor(int) : DelegCtor() {} // expected-warning {{delegating constructors are incompatible with C++98}}
+ DelegCtor();
+};
+
+template<int n = 0> void DefaultFuncTemplateArg(); // expected-warning {{default template arguments for a function template are incompatible with C++98}}
+
+template<typename T> int TemplateFn(T) { return 0; }
+void LocalTemplateArg() {
+ struct S {};
+ TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}}
+}
+struct {} obj_of_unnamed_type; // expected-note {{here}}
+int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}}
+
+namespace RedundantParensInAddressTemplateParam {
+ int n;
+ template<int*p> struct S {};
+ S<(&n)> s; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}}
+ S<(((&n)))> t; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}}
+}
+
+namespace TemplateSpecOutOfScopeNs {
+ template<typename T> struct S {}; // expected-note {{here}}
+}
+template<> struct TemplateSpecOutOfScopeNs::S<char> {}; // expected-warning {{class template specialization of 'S' outside namespace 'TemplateSpecOutOfScopeNs' is incompatible with C++98}}
+
+struct Typename {
+ template<typename T> struct Inner {};
+};
+typename ::Typename TypenameOutsideTemplate(); // expected-warning {{use of 'typename' outside of a template is incompatible with C++98}}
+Typename::template Inner<int> TemplateOutsideTemplate(); // expected-warning {{use of 'template' keyword outside of a template is incompatible with C++98}}
+
+struct TrivialButNonPOD {
+ int f(int);
+private:
+ int k;
+};
+void Ellipsis(int n, ...);
+void TrivialButNonPODThroughEllipsis() {
+ Ellipsis(1, TrivialButNonPOD()); // expected-warning {{passing object of trivial but non-POD type 'TrivialButNonPOD' through variadic function is incompatible with C++98}}
+}
+
+struct HasExplicitConversion {
+ explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}}
+};
+
+struct Struct {};
+enum Enum { enum_val = 0 };
+struct BadFriends {
+ friend enum ::Enum; // expected-warning {{befriending enumeration type 'enum ::Enum' is incompatible with C++98}}
+ friend int; // expected-warning {{non-class friend type 'int' is incompatible with C++98}}
+ friend Struct; // expected-warning {{befriending 'Struct' without 'struct' keyword is incompatible with C++98}}
+};
+
+int n = {}; // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
+
+class PrivateMember {
+ struct ImPrivate {};
+};
+template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}}
+ return typename T::ImPrivate();
+}
+int SFINAEAccessControl(...) { return 0; }
+int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember());
+
+template<typename T>
+struct FriendRedefinition {
+ friend void Friend() {} // expected-warning {{friend function 'Friend' would be implicitly redefined in C++98}} expected-note {{previous}}
+};
+FriendRedefinition<int> FriendRedef1;
+FriendRedefinition<char> FriendRedef2; // expected-note {{requested here}}
+
+namespace CopyCtorIssues {
+ struct Private {
+ Private();
+ private:
+ Private(const Private&); // expected-note {{declared private here}}
+ };
+ struct NoViable {
+ NoViable();
+ NoViable(NoViable&); // expected-note {{not viable}}
+ };
+ struct Ambiguous {
+ Ambiguous();
+ Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}}
+ Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}}
+ };
+ struct Deleted {
+ Private p; // expected-note {{implicitly deleted}}
+ };
+
+ const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}}
+ const NoViable &b = NoViable(); // expected-warning {{copying variable of type 'CopyCtorIssues::NoViable' when binding a reference to a temporary would find no viable constructor in C++98}}
+ const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}}
+ const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}}
+}
+
+namespace UnionOrAnonStructMembers {
+ struct NonTrivCtor {
+ NonTrivCtor(); // expected-note 2{{user-declared constructor}}
+ };
+ struct NonTrivCopy {
+ NonTrivCopy(const NonTrivCopy&); // expected-note 2{{user-declared copy constructor}}
+ };
+ struct NonTrivDtor {
+ ~NonTrivDtor(); // expected-note 2{{user-declared destructor}}
+ };
+ union BadUnion {
+ NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial constructor is incompatible with C++98}}
+ NonTrivCopy ntcp; // expected-warning {{union member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}}
+ NonTrivDtor ntd; // expected-warning {{union member 'ntd' with a non-trivial destructor is incompatible with C++98}}
+ };
+ struct Wrap {
+ struct {
+ NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial constructor is incompatible with C++98}}
+ NonTrivCopy ntcp; // expected-warning {{anonymous struct member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}}
+ NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}}
+ };
+ };
+ union WithStaticDataMember {
+ static constexpr double d = 0.0; // expected-warning {{static data member 'd' in union is incompatible with C++98}} expected-warning {{'constexpr' specifier is incompatible with C++98}}
+ static const int n = 0; // expected-warning {{static data member 'n' in union is incompatible with C++98}}
+ static int k; // expected-warning {{static data member 'k' in union is incompatible with C++98}}
+ };
+}
+
+int EnumNNS = Enum::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}}
+template<typename T> void EnumNNSFn() {
+ int k = T::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}}
+};
+template void EnumNNSFn<Enum>(); // expected-note {{in instantiation}}
+
+void JumpDiagnostics(int n) {
+ goto DirectJump; // expected-warning {{goto would jump into protected scope in C++98}}
+ TrivialButNonPOD tnp1; // expected-note {{jump bypasses initialization of non-POD variable}}
+
+DirectJump:
+ void *Table[] = {&&DirectJump, &&Later};
+ goto *Table[n]; // expected-warning {{indirect goto might cross protected scopes in C++98}}
+
+ TrivialButNonPOD tnp2; // expected-note {{jump bypasses initialization of non-POD variable}}
+Later: // expected-note {{possible target of indirect goto}}
+ switch (n) {
+ TrivialButNonPOD tnp3; // expected-note {{jump bypasses initialization of non-POD variable}}
+ default: // expected-warning {{switch case would be in a protected scope in C++98}}
+ return;
+ }
+}
+
+namespace UnevaluatedMemberAccess {
+ struct S {
+ int n;
+ int f() { return sizeof(S::n); } // ok
+ };
+ int k = sizeof(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}}
+ const std::type_info &ti = typeid(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}}
+}
+
+namespace LiteralUCNs {
+ char c1 = '\u001e'; // expected-warning {{universal character name referring to a control character is incompatible with C++98}}
+ wchar_t c2 = L'\u0041'; // expected-warning {{specifying character 'A' with a universal character name is incompatible with C++98}}
+ const char *s1 = "foo\u0031"; // expected-warning {{specifying character '1' with a universal character name is incompatible with C++98}}
+ const wchar_t *s2 = L"bar\u0085"; // expected-warning {{universal character name referring to a control character is incompatible with C++98}}
+}
+
+namespace NonTypeTemplateArgs {
+ template<typename T, T v> struct S {};
+ const int k = 5; // expected-note {{here}}
+ static void f() {} // expected-note {{here}}
+ S<const int&, k> s1; // expected-warning {{non-type template argument referring to object 'k' with internal linkage is incompatible with C++98}}
+ S<void(&)(), f> s2; // expected-warning {{non-type template argument referring to function 'f' with internal linkage is incompatible with C++98}}
+}
diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp
index 2dbd381..bd3de9e 100644
--- a/test/SemaCXX/dcl_init_aggr.cpp
+++ b/test/SemaCXX/dcl_init_aggr.cpp
@@ -80,7 +80,7 @@ struct HasReference {
};
int global_int;
HasReference r1 = { 1, global_int };
-HasReference r2 = { 1 } ; // expected-error{{initialization leaves reference member of type 'int &' uninitialized}}
+HasReference r2 = { 1 } ; // expected-error{{reference member of type 'int &' uninitialized}}
// C++ [dcl.init.aggr]p10
// Note: the behavior here is identical to C
diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp
index 1ddff80..6f4d08c 100644
--- a/test/SemaCXX/decl-expr-ambiguity.cpp
+++ b/test/SemaCXX/decl-expr-ambiguity.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -pedantic-errors %s
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic-errors %s
void f() {
int a;
@@ -24,14 +24,43 @@ void f() {
// Declarations.
int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}}
T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-note {{previous definition is here}}
+ typedef T(*td)(int(p));
+ extern T(*tp)(int(p));
+ T d3(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}}
+ T d3v(void);
+ typedef T d3t();
+ extern T f3();
+ __typeof(*T()) f4(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}}
+ typedef void *V;
+ __typeof(*V()) f5();
+ T multi1,
+ multi2(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}}
T(d)[5]; // expected-error {{redefinition of 'd'}}
typeof(int[])(f) = { 1, 2 }; // expected-error {{extension used}}
void(b)(int);
- int(d2) __attribute__(());
+ int(d2) __attribute__(());
if (int(a)=1) {}
int(d3(int()));
}
+struct RAII {
+ RAII();
+ ~RAII();
+};
+
+void func();
+namespace N {
+ struct S;
+
+ void emptyParens() {
+ RAII raii(); // expected-warning {{function declaration}} expected-note {{remove parentheses to declare a variable}}
+ int a, b, c, d, e, // expected-note {{change this ',' to a ';' to call 'func'}}
+ func(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}}
+
+ S s(); // expected-warning {{function declaration}}
+ }
+}
+
class C { };
void fn(int(C)) { } // void fn(int(*fp)(C c)) { } expected-note{{candidate function}}
// not: void fn(int C);
diff --git a/test/SemaCXX/decltype-crash.cpp b/test/SemaCXX/decltype-crash.cpp
index 50b3e49..002bd4c 100644
--- a/test/SemaCXX/decltype-crash.cpp
+++ b/test/SemaCXX/decltype-crash.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s
int& a();
diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp
index 78fb8ef..a1200e0 100644
--- a/test/SemaCXX/decltype.cpp
+++ b/test/SemaCXX/decltype.cpp
@@ -20,4 +20,11 @@ namespace pr10154 {
class A{
A(decltype(nullptr) param);
};
-} \ No newline at end of file
+}
+
+template<typename T> struct S {};
+template<typename T> auto f(T t) -> decltype(S<int>(t)) {
+ using U = decltype(S<int>(t));
+ using U = S<int>;
+ return S<int>(t);
+}
diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp
index e9d8a2f..ae6ef97 100644
--- a/test/SemaCXX/default1.cpp
+++ b/test/SemaCXX/default1.cpp
@@ -32,3 +32,21 @@ void k(Y y = 17); // expected-error{{no viable conversion}} \
void kk(Y = 17); // expected-error{{no viable conversion}} \
// expected-note{{passing argument to parameter here}}
+
+int l () {
+ int m(int i, int j, int k = 3);
+ if (1)
+ {
+ int m(int i, int j = 2, int k = 4);
+ m(8);
+ }
+ return 0;
+}
+
+int i () {
+ void j (int f = 4);
+ {
+ void j (int f); // expected-note{{'j' declared here}}
+ j(); // expected-error{{too few arguments to function call, expected 1, have 0}}
+ }
+}
diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
index 2076322..1626044 100644
--- a/test/SemaCXX/default2.cpp
+++ b/test/SemaCXX/default2.cpp
@@ -28,7 +28,7 @@ void g(int x, int y = x); // expected-error {{default argument references parame
void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}}
class X {
- void f(X* x = this); // expected-error{{invalid use of 'this' outside of a nonstatic member function}}
+ void f(X* x = this); // expected-error{{invalid use of 'this' outside of a non-static member function}}
void g() {
int f(X* x = this); // expected-error{{default argument references 'this'}}
@@ -55,7 +55,7 @@ void C::h() {
// C++ [dcl.fct.default]p9
struct Y {
int a;
- int mem1(int i = a); // expected-error{{invalid use of nonstatic data member 'a'}}
+ int mem1(int i = a); // expected-error{{invalid use of non-static data member 'a'}}
int mem2(int i = b); // OK; use Y::b
int mem3(int i);
int mem4(int i);
@@ -64,8 +64,8 @@ struct Y {
int mem5(int i = b, // OK; use Y::b
int j = c, // OK; use Y::Nested::c
int k = j, // expected-error{{default argument references parameter 'j'}}
- int l = a, // expected-error{{invalid use of nonstatic data member 'a'}}
- Nested* self = this, // expected-error{{invalid use of 'this' outside of a nonstatic member function}}
+ int l = a, // expected-error{{invalid use of non-static data member 'a'}}
+ Nested* self = this, // expected-error{{invalid use of 'this' outside of a non-static member function}}
int m); // expected-error{{missing default argument on parameter 'm'}}
static int c;
Nested(int i = 42);
@@ -78,7 +78,7 @@ struct Y {
int Y::mem3(int i = b) { return i; } // OK; use X::b
-int Y::mem4(int i = a) // expected-error{{invalid use of nonstatic data member 'a'}}
+int Y::mem4(int i = a) // expected-error{{invalid use of non-static data member 'a'}}
{ return i; }
diff --git a/test/SemaCXX/defaulted-private-dtor.cpp b/test/SemaCXX/defaulted-private-dtor.cpp
new file mode 100644
index 0000000..e6f9555
--- /dev/null
+++ b/test/SemaCXX/defaulted-private-dtor.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s -fcxx-exceptions
+
+class BadDtor {
+ // A private, but nonetheless trivial, destructor.
+ ~BadDtor() = default; // expected-note 9{{here}}
+ friend class K;
+};
+void f() {
+ BadDtor *p = new BadDtor[3]; // expected-error {{private destructor}}
+ delete [] p; // expected-error {{private destructor}}
+ const BadDtor &dd2 = BadDtor(); // expected-error {{private destructor}}
+ BadDtor dd; // expected-error {{private destructor}}
+ throw dd; // expected-error {{private destructor}}
+}
+struct V {
+ V();
+ BadDtor bd; // expected-note {{inaccessible destructor}}
+};
+V v; // expected-error {{deleted function}}
+struct W : BadDtor { // expected-note {{inaccessible destructor}}
+ W();
+};
+W w; // expected-error {{deleted function}}
+struct X : BadDtor { // expected-error {{private destructor}}
+ ~X() {}
+};
+struct Y {
+ BadDtor dd; // expected-error {{private destructor}}
+ ~Y() {}
+};
+struct Z : virtual BadDtor { // expected-error {{private destructor}}
+ ~Z() {}
+};
+BadDtor dd; // expected-error {{private destructor}}
+
+class K : BadDtor {
+ void f() {
+ BadDtor *p = new BadDtor[3];
+ delete [] p;
+ const BadDtor &dd2 = BadDtor();
+ BadDtor dd;
+ throw dd;
+
+ {
+ BadDtor x;
+ goto dont_call_dtor;
+ }
+dont_call_dtor:
+ ;
+ }
+ struct Z : virtual BadDtor {
+ ~Z() {}
+ };
+ BadDtor dd;
+ ~K();
+};
diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp
index 4620a19..d13fd0e 100644
--- a/test/SemaCXX/deleted-function.cpp
+++ b/test/SemaCXX/deleted-function.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s
int i = delete; // expected-error {{only functions can have deleted definitions}}
@@ -33,3 +33,25 @@ void test() {
d->fn(); // expected-error {{attempt to use a deleted function}}
int i = *d; // expected-error {{invokes a deleted function}}
}
+
+struct DelDtor {
+ ~DelDtor() = delete; // expected-note 9{{here}}
+};
+void f() {
+ DelDtor *p = new DelDtor[3]; // expected-error {{attempt to use a deleted function}}
+ delete [] p; // expected-error {{attempt to use a deleted function}}
+ const DelDtor &dd2 = DelDtor(); // expected-error {{attempt to use a deleted function}}
+ DelDtor dd; // expected-error {{attempt to use a deleted function}}
+ throw dd; // expected-error {{attempt to use a deleted function}}
+}
+struct X : DelDtor {
+ ~X() {} // expected-error {{attempt to use a deleted function}}
+};
+struct Y {
+ DelDtor dd;
+ ~Y() {} // expected-error {{attempt to use a deleted function}}
+};
+struct Z : virtual DelDtor {
+ ~Z() {} // expected-error {{attempt to use a deleted function}}
+};
+DelDtor dd; // expected-error {{attempt to use a deleted function}}
diff --git a/test/SemaCXX/deleted-operator.cpp b/test/SemaCXX/deleted-operator.cpp
index e357401..0e0282a 100644
--- a/test/SemaCXX/deleted-operator.cpp
+++ b/test/SemaCXX/deleted-operator.cpp
@@ -11,3 +11,8 @@ int PR10757f() {
if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 6 {{built-in candidate}}
if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 81 {{built-in candidate}}
}
+
+struct DelOpDel {
+ virtual ~DelOpDel() {} // expected-error {{deleted function}}
+ void operator delete(void*) = delete; // expected-note {{deleted here}}
+};
diff --git a/test/SemaCXX/dependent-auto.cpp b/test/SemaCXX/dependent-auto.cpp
index 1be1566..6d37f7a 100644
--- a/test/SemaCXX/dependent-auto.cpp
+++ b/test/SemaCXX/dependent-auto.cpp
@@ -8,7 +8,7 @@ struct only {
template<typename ...T>
void f(T ...t) {
- auto x(t...); // expected-error {{requires an initializer}} expected-error {{contains multiple expressions}}
+ auto x(t...); // expected-error {{is empty}} expected-error {{contains multiple expressions}}
only<int> check = x;
}
diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp
index 14a0cda..f3c6ab0 100644
--- a/test/SemaCXX/destructor.cpp
+++ b/test/SemaCXX/destructor.cpp
@@ -16,7 +16,7 @@ public:
struct D {
static void ~D(int, ...) const { } // \
- // expected-error{{type qualifier is not allowed on this function}} \
+ // expected-error{{static member function cannot have 'const' qualifier}} \
// expected-error{{destructor cannot be declared 'static'}} \
// expected-error{{destructor cannot have any parameters}} \
// expected-error{{destructor cannot be variadic}} \
diff --git a/test/SemaCXX/discrim-union.cpp b/test/SemaCXX/discrim-union.cpp
new file mode 100644
index 0000000..15c9a22
--- /dev/null
+++ b/test/SemaCXX/discrim-union.cpp
@@ -0,0 +1,118 @@
+// RUN: %clang_cc1 -std=c++11 %s -fsyntax-only -fcxx-exceptions
+
+template<typename T> struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+template<typename T> struct remove_reference<T&&> { typedef T type; };
+
+template<typename T> constexpr T &&forward(typename remove_reference<T>::type &t) noexcept { return static_cast<T&&>(t); }
+template<typename T> constexpr T &&forward(typename remove_reference<T>::type &&t) noexcept { return static_cast<T&&>(t); }
+template<typename T> constexpr typename remove_reference<T>::type &&move(T &&t) noexcept { return static_cast<typename remove_reference<T>::type&&>(t); }
+
+template<typename T> T declval() noexcept;
+
+namespace detail {
+ template<unsigned N> struct select {}; // : integral_constant<unsigned, N> {};
+ template<typename T> struct type {};
+
+ template<typename...T> union either_impl;
+
+ template<> union either_impl<> {
+ void get(...);
+ void destroy(...) { throw "logic_error"; }
+ };
+
+ template<typename T, typename...Ts> union either_impl<T, Ts...> {
+ private:
+ T val;
+ either_impl<Ts...> rest;
+ typedef either_impl<Ts...> rest_t;
+
+ public:
+ constexpr either_impl(select<0>, T &&t) : val(move(t)) {}
+
+ template<unsigned N, typename U>
+ constexpr either_impl(select<N>, U &&u) : rest(select<N-1>(), move(u)) {}
+
+ constexpr static unsigned index(type<T>) { return 0; }
+ template<typename U>
+ constexpr static unsigned index(type<U> t) {
+ return decltype(rest)::index(t) + 1;
+ }
+
+ void destroy(unsigned elem) {
+ if (elem)
+ rest.destroy(elem - 1);
+ else
+ val.~T();
+ }
+
+ constexpr const T &get(select<0>) { return val; }
+ template<unsigned N> constexpr const decltype(static_cast<const rest_t&>(rest).get(select<N-1>{})) get(select<N>) {
+ return rest.get(select<N-1>{});
+ }
+ };
+}
+
+template<typename T>
+struct a {
+ T value;
+ template<typename...U>
+ constexpr a(U &&...u) : value{forward<U>(u)...} {}
+};
+template<typename T> using an = a<T>;
+
+template<typename T, typename U> T throw_(const U &u) { throw u; }
+
+template<typename...T>
+class either {
+ unsigned elem;
+ detail::either_impl<T...> impl;
+ typedef decltype(impl) impl_t;
+
+public:
+ template<typename U>
+ constexpr either(a<U> &&t) :
+ elem(impl_t::index(detail::type<U>())),
+ impl(detail::select<impl_t::index(detail::type<U>())>(), move(t.value)) {}
+
+ // Destruction disabled to allow use in a constant expression.
+ // FIXME: declare a destructor iff any element has a nontrivial destructor
+ //~either() { impl.destroy(elem); }
+
+ constexpr unsigned index() noexcept { return elem; }
+
+ template<unsigned N> using const_get_result =
+ decltype(static_cast<const impl_t&>(impl).get(detail::select<N>{}));
+
+ template<unsigned N>
+ constexpr const_get_result<N> get() {
+ // Can't just use throw here, since that makes the conditional a prvalue,
+ // which means we return a reference to a temporary.
+ return (elem != N ? throw_<const_get_result<N>>("bad_either_get")
+ : impl.get(detail::select<N>{}));
+ }
+
+ template<typename U>
+ constexpr const U &get() {
+ return get<impl_t::index(detail::type<U>())>();
+ }
+};
+
+typedef either<int, char, double> icd;
+constexpr icd icd1 = an<int>(4);
+constexpr icd icd2 = a<char>('x');
+constexpr icd icd3 = a<double>(6.5);
+
+static_assert(icd1.get<int>() == 4, "");
+static_assert(icd2.get<char>() == 'x', "");
+static_assert(icd3.get<double>() == 6.5, "");
+
+struct non_triv {
+ constexpr non_triv() : n(5) {}
+ int n;
+};
+constexpr either<const icd*, non_triv> icd4 = a<const icd*>(&icd2);
+constexpr either<const icd*, non_triv> icd5 = a<non_triv>();
+
+static_assert(icd4.get<const icd*>()->get<char>() == 'x', "");
+static_assert(icd5.get<non_triv>().n == 5, "");
diff --git a/test/SemaCXX/dr1301.cpp b/test/SemaCXX/dr1301.cpp
new file mode 100644
index 0000000..ec0db74
--- /dev/null
+++ b/test/SemaCXX/dr1301.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+struct A { // expected-note 2{{candidate}}
+ A(int); // expected-note {{candidate}}
+ int n;
+};
+int a = A().n; // expected-error {{no matching constructor}}
+
+struct B {
+ B() = delete; // expected-note 3{{here}}
+ int n;
+};
+int b = B().n; // expected-error {{call to deleted}}
+
+struct C {
+ B b; // expected-note {{deleted default constructor}}
+};
+int c = C().b.n; // expected-error {{call to implicitly-deleted default}}
+
+struct D {
+ D() = default; // expected-note {{here}}
+ B b; // expected-note {{'b' has a deleted default constructor}}
+};
+int d = D().b.n; // expected-error {{call to implicitly-deleted default}}
+
+struct E {
+ E() = default;
+ int n;
+};
+int e = E().n; // ok
+
+struct F {
+ F();
+ int n;
+};
+int f = F().n; // ok
+
+union G {
+ F f; // expected-note {{non-trivial default constructor}}
+};
+int g = G().f.n; // expected-error {{call to implicitly-deleted default}}
+
+struct H {
+ int n;
+private:
+ H(); // expected-note {{here}}
+};
+int h = H().n; // expected-error {{private constructor}}
+
+struct I {
+ H h; // expected-note {{inaccessible default constructor}}
+};
+int i = I().h.n; // expected-error {{call to implicitly-deleted default}}
+
+struct J {
+ J();
+ virtual int f();
+ int n;
+};
+int j1 = J().n; // ok
+int j2 = J().f(); // ok
+
+union K {
+ J j; // expected-note 2{{non-trivial default constructor}}
+ int m;
+};
+int k1 = K().j.n; // expected-error {{call to implicitly-deleted default}}
+int k2 = K().j.f(); // expected-error {{call to implicitly-deleted default}}
diff --git a/test/SemaCXX/empty-class-layout.cpp b/test/SemaCXX/empty-class-layout.cpp
index 0b46bf0..c68f2bb 100644
--- a/test/SemaCXX/empty-class-layout.cpp
+++ b/test/SemaCXX/empty-class-layout.cpp
@@ -144,3 +144,14 @@ struct B : Empty, A { };
SA(0, sizeof(B) == 16);
}
+
+namespace Test7 {
+ // Make sure we reserve enough space for both bases; PR11745.
+ struct Empty { };
+ struct Base1 : Empty { };
+ struct Base2 : Empty { };
+ struct Test : Base1, Base2 {
+ char c;
+ };
+ SA(0, sizeof(Test) == 2);
+}
diff --git a/test/SemaCXX/enum-bitfield.cpp b/test/SemaCXX/enum-bitfield.cpp
index 1a65740..63445ca 100644
--- a/test/SemaCXX/enum-bitfield.cpp
+++ b/test/SemaCXX/enum-bitfield.cpp
@@ -14,5 +14,5 @@ struct X {
struct Y {
enum E : int(2);
- enum E : Z(); // expected-error{{not an integer constant}}
+ enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}}
};
diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp
index 35ba1b4..ebe9245 100644
--- a/test/SemaCXX/enum-scoped.cpp
+++ b/test/SemaCXX/enum-scoped.cpp
@@ -34,12 +34,12 @@ int a1[Val2];
int a2[E1::Val1]; // expected-error{{size of array has non-integer type}}
int* p1 = new int[Val2];
-int* p2 = new int[E1::Val1]; // FIXME Expected-error{{must have integral}}
+int* p2 = new int[E1::Val1]; // expected-error{{array size expression must have integral or unscoped enumeration type, not 'E1'}}
enum class E4 {
e1 = -2147483648, // ok
e2 = 2147483647, // ok
- e3 = 2147483648 // expected-error{{value is not representable}}
+ e3 = 2147483648 // expected-error{{enumerator value evaluates to 2147483648, which cannot be narrowed to type 'int'}}
};
enum class E5 {
@@ -142,3 +142,106 @@ namespace test6 {
(void) A::e; // expected-error {{incomplete type 'test6::A' named in nested name specifier}}
}
}
+
+namespace PR11484 {
+ const int val = 104;
+ enum class test1 { owner_dead = val, };
+}
+
+namespace N2764 {
+ enum class E { a, b };
+ enum E x1 = E::a; // ok
+ enum class E x2 = E::a; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}}
+
+ enum F { a, b };
+ enum F y1 = a; // ok
+ enum class F y2 = a; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}}
+
+ struct S {
+ friend enum class E; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}}
+ friend enum class F; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}}
+
+ friend enum G {}; // expected-error {{forward reference}} expected-error {{cannot define a type in a friend declaration}}
+ friend enum class H {}; // expected-error {{cannot define a type in a friend declaration}}
+
+ enum A : int;
+ A a;
+ } s;
+
+ enum S::A : int {};
+
+ enum class B;
+}
+
+enum class N2764::B {};
+
+namespace PR12106 {
+ template<typename E> struct Enum {
+ Enum() : m_e(E::Last) {}
+ E m_e;
+ };
+
+ enum eCOLORS { Last };
+ Enum<eCOLORS> e;
+}
+
+namespace test7 {
+ enum class E { e = (struct S*)0 == (struct S*)0 };
+ S *p;
+}
+
+namespace test8 {
+ template<typename T> struct S {
+ enum A : int; // expected-note {{here}}
+ enum class B; // expected-note {{here}}
+ enum class C : int; // expected-note {{here}}
+ enum class D : int; // expected-note {{here}}
+ };
+ template<typename T> enum S<T>::A { a }; // expected-error {{previously declared with fixed underlying type}}
+ template<typename T> enum class S<T>::B : char { b }; // expected-error {{redeclared with different underlying}}
+ template<typename T> enum S<T>::C : int { c }; // expected-error {{previously declared as scoped}}
+ template<typename T> enum class S<T>::D : char { d }; // expected-error {{redeclared with different underlying}}
+}
+
+namespace test9 {
+ template<typename T> struct S {
+ enum class ET : T; // expected-note 2{{here}}
+ enum class Eint : int; // expected-note 2{{here}}
+ };
+ template<> enum class S<int>::ET : int {};
+ template<> enum class S<char>::ET : short {}; // expected-error {{different underlying type}}
+ template<> enum class S<int>::Eint : short {}; // expected-error {{different underlying type}}
+ template<> enum class S<char>::Eint : int {};
+
+ template<typename T> enum class S<T>::ET : int {}; // expected-error {{different underlying type 'int' (was 'short')}}
+ template<typename T> enum class S<T>::Eint : T {}; // expected-error {{different underlying type 'short' (was 'int')}}
+
+ // The implicit instantiation of S<short> causes the implicit instantiation of
+ // all declarations of member enumerations, so is ill-formed, even though we
+ // never instantiate the definitions of S<short>::ET nor S<short>::Eint.
+ S<short> s; // expected-note {{in instantiation of}}
+}
+
+namespace test10 {
+ template<typename T> int f() {
+ enum E : int;
+ enum E : T; // expected-note {{here}}
+ E x;
+ enum E : int { e }; // expected-error {{different underlying}}
+ x = e;
+ return x;
+ }
+ int k = f<int>();
+ int l = f<short>(); // expected-note {{here}}
+
+ template<typename T> int g() {
+ enum class E : int;
+ enum class E : T; // expected-note {{here}}
+ E x;
+ enum class E : int { e }; // expected-error {{different underlying}}
+ x = E::e;
+ return (int)x;
+ }
+ int m = g<int>();
+ int n = g<short>(); // expected-note {{here}}
+}
diff --git a/test/SemaCXX/enum-unscoped-nonexistent.cpp b/test/SemaCXX/enum-unscoped-nonexistent.cpp
new file mode 100644
index 0000000..d49800c
--- /dev/null
+++ b/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
+}
diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp
index b4a050c..370e1c3 100644
--- a/test/SemaCXX/enum.cpp
+++ b/test/SemaCXX/enum.cpp
@@ -88,7 +88,7 @@ typedef enum { }; // expected-warning{{typedef requires a name}}
// PR7921
enum PR7921E {
- PR7921V = (PR7921E)(123) // expected-error {{expression is not an integer constant expression}}
+ PR7921V = (PR7921E)(123) // expected-error {{expression is not an integral constant expression}}
};
void PR8089() {
diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp
index e2bfe18..486d88e 100644
--- a/test/SemaCXX/exceptions.cpp
+++ b/test/SemaCXX/exceptions.cpp
@@ -12,8 +12,8 @@ void trys() {
} catch(float i) {
} catch(void v) { // expected-error {{cannot catch incomplete type 'void'}}
} catch(A a) { // expected-error {{cannot catch incomplete type 'A'}}
- } catch(A *a) { // expected-warning {{ISO C++ forbids catching a pointer to incomplete type 'A'}}
- } catch(A &a) { // expected-warning {{ISO C++ forbids catching a reference to incomplete type 'A'}}
+ } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'A'}}
+ } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'A'}}
} catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}}
} catch(...) {
int j = i; // expected-error {{use of undeclared identifier 'i'}}
@@ -35,37 +35,37 @@ void throws() {
void jumps() {
l1:
goto l5;
- goto l4; // expected-error {{illegal goto into protected scope}}
- goto l3; // expected-error {{illegal goto into protected scope}}
- goto l2; // expected-error {{illegal goto into protected scope}}
+ goto l4; // expected-error {{goto into protected scope}}
+ goto l3; // expected-error {{goto into protected scope}}
+ goto l2; // expected-error {{goto into protected scope}}
goto l1;
try { // expected-note 4 {{jump bypasses initialization of try block}}
l2:
goto l5;
- goto l4; // expected-error {{illegal goto into protected scope}}
- goto l3; // expected-error {{illegal goto into protected scope}}
+ goto l4; // expected-error {{goto into protected scope}}
+ goto l3; // expected-error {{goto into protected scope}}
goto l2;
goto l1;
} catch(int) { // expected-note 4 {{jump bypasses initialization of catch block}}
l3:
goto l5;
- goto l4; // expected-error {{illegal goto into protected scope}}
+ goto l4; // expected-error {{goto into protected scope}}
goto l3;
- goto l2; // expected-error {{illegal goto into protected scope}}
+ goto l2; // expected-error {{goto into protected scope}}
goto l1;
} catch(...) { // expected-note 4 {{jump bypasses initialization of catch block}}
l4:
goto l5;
goto l4;
- goto l3; // expected-error {{illegal goto into protected scope}}
- goto l2; // expected-error {{illegal goto into protected scope}}
+ goto l3; // expected-error {{goto into protected scope}}
+ goto l2; // expected-error {{goto into protected scope}}
goto l1;
}
l5:
goto l5;
- goto l4; // expected-error {{illegal goto into protected scope}}
- goto l3; // expected-error {{illegal goto into protected scope}}
- goto l2; // expected-error {{illegal goto into protected scope}}
+ goto l4; // expected-error {{goto into protected scope}}
+ goto l3; // expected-error {{goto into protected scope}}
+ goto l2; // expected-error {{goto into protected scope}}
goto l1;
}
diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp
index 11b9672..4774637 100644
--- a/test/SemaCXX/explicit.cpp
+++ b/test/SemaCXX/explicit.cpp
@@ -43,16 +43,8 @@ namespace Conversion {
class Y { }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \
expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \
expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \
- expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \
- expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \
- expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \
- expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \
- expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \
- expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \
- expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \
- expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \
- expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \
- expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
+ expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}}
+
struct Z {
explicit operator Y() const;
explicit operator int() const;
@@ -61,10 +53,9 @@ namespace Conversion {
Z z;
// 13.3.1.4p1 & 8.5p16:
Y y2 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'Conversion::Y'}}
- // FIXME: These are well-formed per C++0x 13.3.1.4p1 (see DR899).
- Y y3 = (Y)z; // expected-error {{no matching conversion for C-style cast from 'Conversion::Z' to 'Conversion::Y''}}
- Y y4 = Y(z); // expected-error {{no matching conversion for functional-style cast from 'Conversion::Z' to 'Conversion::Y'}}
- Y y5 = static_cast<Y>(z); // expected-error {{no matching conversion for static_cast from 'Conversion::Z' to 'Conversion::Y'}}
+ Y y3 = (Y)z;
+ Y y4 = Y(z);
+ Y y5 = static_cast<Y>(z);
// 13.3.1.5p1 & 8.5p16:
int i1 = (int)z;
int i2 = int(z);
diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp
index 32b3ff9..2767d4a 100644
--- a/test/SemaCXX/expression-traits.cpp
+++ b/test/SemaCXX/expression-traits.cpp
@@ -185,8 +185,8 @@ struct Class : BaseClass
template <class T>
struct NestedClassTemplate {};
- template <class T> // expected-note{{possible target for call}}
- static int& NestedFuncTemplate() { return variable; }
+ template <class T>
+ static int& NestedFuncTemplate() { return variable; } // expected-note{{possible target for call}}
template <class T>
int& NestedMemfunTemplate() { return variable; }
diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp
index b994e8c..8bda510 100644
--- a/test/SemaCXX/for-range-examples.cpp
+++ b/test/SemaCXX/for-range-examples.cpp
@@ -148,3 +148,35 @@ int main() {
}
assert(total == 500);
}
+
+// PR11793
+namespace test2 {
+ class A {
+ int xs[10]; // expected-note {{implicitly declared private here}}
+ };
+ void test(A &a) {
+ for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}}
+ }
+}
+
+namespace test3 {
+ // Make sure this doesn't crash
+ struct A {};
+ struct B { ~B(); operator bool(); };
+ struct C { B operator!=(const C&); C& operator++(); int operator*(); };
+ C begin(const A&);
+ C end(const A&);
+ template<typename T> void f() { for (auto a : A()) {} }
+ void g() { f<int>(); }
+}
+
+namespace test4 {
+ void f() {
+ int y;
+
+ // Make sure these don't crash. Better diagnostics would be nice.
+ for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}}
+ for (x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}}
+ for (y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}}
+ }
+}
diff --git a/test/SemaCXX/for-range-no-std.cpp b/test/SemaCXX/for-range-no-std.cpp
index dae41f1..fa42ca4 100644
--- a/test/SemaCXX/for-range-no-std.cpp
+++ b/test/SemaCXX/for-range-no-std.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions
struct S {
int *begin();
@@ -36,3 +36,8 @@ void f() {
for (int b : NS::ADL()) {} // ok
for (int b : NS::NoADL()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}}
}
+
+void PR11601() {
+ void (*vv[])() = {PR11601, PR11601, PR11601};
+ for (void (*i)() : vv) i();
+}
diff --git a/test/SemaCXX/format-strings-0x.cpp b/test/SemaCXX/format-strings-0x.cpp
new file mode 100644
index 0000000..e7c5904
--- /dev/null
+++ b/test/SemaCXX/format-strings-0x.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -std=c++11 %s
+
+extern "C" {
+extern int scanf(const char *restrict, ...);
+extern int printf(const char *restrict, ...);
+}
+
+void f(char **sp, float *fp) {
+ scanf("%as", sp); // expected-warning{{format specifies type 'float *' but the argument has type 'char **'}}
+
+ printf("%a", 1.0);
+ scanf("%afoobar", fp);
+ printf(nullptr);
+ printf(*sp); // expected-warning {{not a string literal}}
+}
diff --git a/test/SemaCXX/format-strings.cpp b/test/SemaCXX/format-strings.cpp
new file mode 100644
index 0000000..6b0df29
--- /dev/null
+++ b/test/SemaCXX/format-strings.cpp
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s
+
+#include <stdarg.h>
+
+extern "C" {
+extern int scanf(const char *restrict, ...);
+extern int printf(const char *restrict, ...);
+extern int vprintf(const char *restrict, va_list);
+}
+
+void f(char **sp, float *fp) {
+ scanf("%as", sp); // expected-warning{{'a' length modifier is not supported by ISO C}}
+
+ // TODO: Warn that the 'a' conversion specifier is a C++11 feature.
+ printf("%a", 1.0);
+ scanf("%afoobar", fp);
+}
+
+void g() {
+ printf("%ls", "foo"); // expected-warning{{format specifies type 'wchar_t *' but the argument has type 'const char *'}}
+}
+
+// Test that we properly handle format_idx on C++ members.
+class Foo {
+public:
+ const char *gettext(const char *fmt) __attribute__((format_arg(2)));
+
+ int scanf(const char *, ...) __attribute__((format(scanf, 2, 3)));
+ int printf(const char *, ...) __attribute__((format(printf, 2, 3)));
+ int printf2(const char *, ...);
+
+ static const char *gettext_static(const char *fmt) __attribute__((format_arg(1)));
+ static int printf_static(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+};
+
+void h(int *i) {
+ Foo foo;
+ foo.scanf("%d"); // expected-warning{{more '%' conversions than data arguments}}
+ foo.printf("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
+ Foo::printf_static("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
+
+ printf(foo.gettext("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
+ printf(Foo::gettext_static("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
+}
+
+// Test handling __null for format string literal checking.
+extern "C" {
+ int test_null_format(const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));
+}
+
+void rdar8269537(const char *f)
+{
+ test_null_format(false); // expected-warning {{null from a constant boolean}}
+ test_null_format(0); // no-warning
+ test_null_format(__null); // no-warning
+ test_null_format(f); // expected-warning {{not a string literal}}
+}
+
+int Foo::printf(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap,fmt);
+ const char * const format = fmt;
+ vprintf(format, ap); // no-warning
+
+ const char *format2 = fmt;
+ vprintf(format2, ap); // expected-warning{{format string is not a string literal}}
+
+ return 0;
+}
+
+int Foo::printf2(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap,fmt);
+ vprintf(fmt, ap); // expected-warning{{format string is not a string literal}}
+
+ return 0;
+}
diff --git a/test/SemaCXX/friend-out-of-line.cpp b/test/SemaCXX/friend-out-of-line.cpp
new file mode 100644
index 0000000..56b2daa
--- /dev/null
+++ b/test/SemaCXX/friend-out-of-line.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/10204947>
+namespace N {
+ class X;
+};
+
+class N::X {
+ template<typename T> friend const T& f(const X&);
+ friend const int& g(const X&);
+ friend class Y;
+};
diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp
index b1ef220..c5b11eb 100644
--- a/test/SemaCXX/friend.cpp
+++ b/test/SemaCXX/friend.cpp
@@ -130,3 +130,11 @@ namespace test6_3 {
v.f();
}
}
+
+namespace test7 {
+ extern "C" {
+ class X {
+ friend int f() { return 42; }
+ };
+ }
+}
diff --git a/test/SemaCXX/function-extern-c.cpp b/test/SemaCXX/function-extern-c.cpp
new file mode 100644
index 0000000..f20cd38
--- /dev/null
+++ b/test/SemaCXX/function-extern-c.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -Wreturn-type -fsyntax-only -std=c++11 -verify %s
+
+class A {
+public:
+ A(const A&);
+};
+
+struct S {
+ int i;
+ double d;
+
+ virtual void B() {}
+};
+
+union U {
+ struct {
+ int i;
+ virtual void B() {} // Can only do this in C++11
+ } t;
+};
+
+struct S2 {
+ int i;
+ double d;
+};
+
+extern "C" U f3( void ); // expected-warning {{'f3' has C-linkage specified, but returns user-defined type 'U' which is incompatible with C}}
+extern "C" S f0(void); // expected-warning {{'f0' has C-linkage specified, but returns user-defined type 'S' which is incompatible with C}}
+extern "C" A f4( void ); // expected-warning {{'f4' has C-linkage specified, but returns user-defined type 'A' which is incompatible with C}}
+
+// These should all be fine
+extern "C" S2 f5( void );
+extern "C" void f2( A x );
+extern "C" void f6( S s );
+extern "C" void f7( U u );
+extern "C" double f8(void);
+extern "C" long long f11( void );
+extern "C" A *f10( void );
diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp
index 0d9ecf3..0eb109d 100644
--- a/test/SemaCXX/function-redecl.cpp
+++ b/test/SemaCXX/function-redecl.cpp
@@ -76,9 +76,12 @@ class Crash {
void GetCart(int count) const;
};
// This out-of-line definition was fine...
-void Crash::cart(int count) const {} // expected-error {{out-of-line definition of 'cart' does not match any declaration in 'Crash'}}
+void Crash::cart(int count) const {} // expected-error {{out-of-line definition of 'cart' does not match any declaration in 'Crash'}} \
+ // expected-note {{'cart' declared here}} \
+ // expected-note {{previous definition is here}}
// ...while this one crashed clang
-void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'}}
+void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'; did you mean 'cart'?}} \
+ // expected-error {{redefinition of 'cart'}}
class TestConst {
public:
diff --git a/test/SemaCXX/function-type-qual.cpp b/test/SemaCXX/function-type-qual.cpp
index 8ebb506..73613ae 100644
--- a/test/SemaCXX/function-type-qual.cpp
+++ b/test/SemaCXX/function-type-qual.cpp
@@ -1,17 +1,17 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-void f() const; // expected-error {{type qualifier is not allowed on this function}}
-void (*pf)() const; // expected-error {{type qualifier is not allowed on this function pointer}}
-void (&rf)() const = f; // expected-error {{type qualifier is not allowed on this function reference}}
+void f() const; // expected-error {{non-member function cannot have 'const' qualifier}}
+void (*pf)() const; // expected-error {{pointer to function type cannot have 'const' qualifier}}
+extern void (&rf)() const; // expected-error {{reference to function type cannot have 'const' qualifier}}
-typedef void cfn() const;
-cfn f2; // expected-error {{a qualified function type cannot be used to declare a nonmember function}}
+typedef void cfn() const;
+cfn f2; // expected-error {{non-member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}}
class C {
void f() const;
cfn f2;
- static void f3() const; // expected-error {{type qualifier is not allowed on this function}}
- static cfn f4; // expected-error {{a qualified function type cannot be used to declare a static member function}}
+ static void f3() const; // expected-error {{static member function cannot have 'const' qualifier}}
+ static cfn f4; // expected-error {{static member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}}
void m1() {
x = 0;
diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp
deleted file mode 100644
index a1891c9..0000000
--- a/test/SemaCXX/generalized-initializers.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// XFAIL: *
-
-template <typename T, typename U>
-struct same_type { static const bool value = false; };
-template <typename T>
-struct same_type<T, T> { static const bool value = true; };
-
-namespace std {
- typedef decltype(sizeof(int)) size_t;
-
- // libc++'s implementation
- template <class _E>
- class initializer_list
- {
- const _E* __begin_;
- size_t __size_;
-
- initializer_list(const _E* __b, size_t __s)
- : __begin_(__b),
- __size_(__s)
- {}
-
- public:
- typedef _E value_type;
- typedef const _E& reference;
- typedef const _E& const_reference;
- typedef size_t size_type;
-
- typedef const _E* iterator;
- typedef const _E* const_iterator;
-
- initializer_list() : __begin_(nullptr), __size_(0) {}
-
- size_t size() const {return __size_;}
- const _E* begin() const {return __begin_;}
- const _E* end() const {return __begin_ + __size_;}
- };
-}
-
-namespace integral {
-
- int function_call() {
- void takes_int(int);
- takes_int({1});
- }
-
- void inline_init() {
- (void) int{1};
- (void) new int{1};
- }
-
- void initializer_list() {
- std::initializer_list<int> il = { 1, 2, 3 };
- std::initializer_list<double> dl = { 1.0, 2.0, 3 };
- auto l = {1, 2, 3, 4};
- static_assert(same_type<decltype(l), std::initializer_list<int>>::value, "");
- auto bl = {1, 2.0}; // expected-error {{cannot deduce}}
-
- for (int i : {1, 2, 3, 4}) {}
- }
-
-}
-
-namespace objects {
-
- struct X1 { X1(int); };
- struct X2 { explicit X2(int); };
-
- template <int N>
- struct A {
- A() { static_assert(N == 0, ""); }
- A(int, double) { static_assert(N == 1, ""); }
- A(std::initializer_list<int>) { static_assert(N == 3, ""); }
- };
-
- template <int N>
- struct D {
- D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}}
- D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}}
- };
-
- template <int N>
- struct E {
- E(int, int) { static_assert(N == 0, ""); }
- E(X1, int) { static_assert(N == 1, ""); }
- };
-
- void overload_resolution() {
- { A<0> a{}; }
- { A<0> a = {}; }
- // Narrowing conversions don't affect viability. The next two choose
- // the initializer_list constructor.
- { A<3> a{1, 1.0}; } // expected-error {{narrowing conversion}}
- { A<3> a = {1, 1.0}; } // expected-error {{narrowing conversion}}
- { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; }
- { A<3> a = {1, 2, 3, 4, 5, 6, 7, 8}; }
- { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; }
- { A<3> a{1, 2}; }
-
- { D<0> d{1, 2, 3}; }
- { D<1> d{1.0, 2.0, 3.0}; }
- { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}}
-
- { E<0> e{1, 2}; }
- }
-
- void explicit_implicit() {
- { X1 x{0}; }
- { X1 x = {0}; }
- { X2 x{0}; }
- { X2 x = {0}; } // expected-error {{explicit}}
- }
-
- struct C {
- C();
- C(int, double);
- C(int, int);
- C(std::initializer_list<int>);
-
- int operator[](C);
- };
-
- C function_call() {
- void takes_C(C);
- takes_C({1, 1.0});
-
- C c;
- c[{1, 1.0}];
-
- return {1, 1.0};
- }
-
- void inline_init() {
- (void) A<1>{1, 1.0};
- (void) new A<1>{1, 1.0};
- }
-
- struct B {
- B(C, int, C);
- };
-
- void nested_init() {
- B b{{1, 1.0}, 2, {3, 4, 5, 6, 7}};
- }
-}
-
-namespace litb {
-
- // invalid
- struct A { int a[2]; A():a({1, 2}) { } }; // expected-error {{}}
-
- // invalid
- int a({0}); // expected-error {{}}
-
- // invalid
- int const &b({0}); // expected-error {{}}
-
- struct C { explicit C(int, int); C(int, long); };
-
- // invalid
- C c({1, 2}); // expected-error {{}}
-
- // valid (by copy constructor).
- C d({1, 2L}); // expected-error {{}}
-
- // valid
- C e{1, 2};
-
- struct B {
- template<typename ...T>
- B(std::initializer_list<int>, T ...);
- };
-
- // invalid (the first phase only considers init-list ctors)
- // (for the second phase, no constructor is viable)
- B f{1, 2, 3};
-
- // valid (T deduced to <>).
- B g({1, 2, 3});
-
-}
-
-namespace aggregate {
- // Direct list initialization does NOT allow braces to be elided!
- struct S {
- int ar[2];
- struct T {
- int i1;
- int i2;
- } t;
- struct U {
- int i1;
- } u[2];
- struct V {
- int var[2];
- } v;
- };
-
- void test() {
- S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error
- S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
- S s3{ 1, 2, 3, 4, 5, 6 }; // xpected-error
- S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // xpected-error
- S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // xpected-error
- }
-}
diff --git a/test/SemaCXX/gnu-case-ranges.cpp b/test/SemaCXX/gnu-case-ranges.cpp
index c1c18a8..b082e3a 100644
--- a/test/SemaCXX/gnu-case-ranges.cpp
+++ b/test/SemaCXX/gnu-case-ranges.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify %s
+// RUN: %clang_cc1 -verify -Wno-covered-switch-default %s
enum E {
one,
diff --git a/test/SemaCXX/goto.cpp b/test/SemaCXX/goto.cpp
index d8d5ec5..24bcb7c 100644
--- a/test/SemaCXX/goto.cpp
+++ b/test/SemaCXX/goto.cpp
@@ -103,3 +103,25 @@ void f() {
exit:
return;
}
+
+namespace PR10620 {
+ struct S {
+ ~S() {}
+ };
+ void g(const S& s) {
+ goto done; // expected-error {{goto into protected scope}}
+ const S s2(s); // expected-note {{jump bypasses variable initialization}}
+ done:
+ ;
+ }
+}
+
+namespace test12 {
+ struct A { A(); A(const A&); ~A(); };
+ void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: wierd location
+ goto lbl; // expected-error {{goto into protected scope}}
+ (void) ^{ (void) a; };
+ lbl:
+ return;
+ }
+}
diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp
index 4d02ca8..5631577 100644
--- a/test/SemaCXX/i-c-e-cxx.cpp
+++ b/test/SemaCXX/i-c-e-cxx.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
// C++-specific tests for integral constant expressions.
@@ -16,9 +16,9 @@ void f() {
}
int a() {
- const int t=t;
+ const int t=t; // expected-note {{declared here}}
switch(1) { // expected-warning {{no case matching constant switch condition '1'}}
- case t:; // expected-error {{not an integer constant expression}}
+ case t:; // expected-error {{not an integral constant expression}} expected-note {{initializer of 't' is not a constant expression}}
}
}
@@ -48,7 +48,7 @@ void pr6373(const unsigned x = 0) {
namespace rdar9204520 {
struct A {
- static const int B = int(0.75 * 1000 * 1000);
+ static const int B = int(0.75 * 1000 * 1000); // expected-warning {{not a constant expression; folding it to a constant is a GNU extension}}
};
int foo() { return A::B; }
@@ -59,5 +59,10 @@ const int x = 10;
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; };
-int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))];
+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}}
+
+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}}
+const int castfloat = static_cast<int>(1.0);
+int arr2[castfloat]; // ok
diff --git a/test/SemaCXX/if-empty-body.cpp b/test/SemaCXX/if-empty-body.cpp
deleted file mode 100644
index ec7f89d..0000000
--- a/test/SemaCXX/if-empty-body.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-
-void f1(int a) {
- if (a); // expected-warning {{if statement has empty body}}
-}
-
-void f2(int a) {
- if (a) {}
-}
-
-void f3() {
- if (1)
- xx; // expected-error {{use of undeclared identifier}}
- return; // no empty body warning.
-}
-
-// Don't warn about an empty body if is expanded from a macro.
-void f4(int i) {
- #define BODY(x)
- if (i == i) // expected-warning{{self-comparison always evaluates to true}}
- BODY(0);
- #undef BODY
-}
-
-template <typename T>
-void tf() {
- #define BODY(x)
- if (0)
- BODY(0);
- #undef BODY
-}
-
-void f5() {
- tf<int>();
-}
diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp
index 559c301..786e8f4 100644
--- a/test/SemaCXX/implicit-exception-spec.cpp
+++ b/test/SemaCXX/implicit-exception-spec.cpp
@@ -54,10 +54,9 @@ namespace ExceptionSpecification {
// The same problem arises in delayed parsing of default arguments,
// which clang does not yet support.
namespace DefaultArgument {
- // FIXME: this diagnostic is completely wrong.
- struct Default { // expected-note {{explicitly marked deleted here}}
+ struct Default {
struct T {
- T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to deleted constructor}}
- } t;
+ T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to implicitly-deleted default constructor}}
+ } t; // expected-note {{has no default constructor}}
};
}
diff --git a/test/SemaCXX/incomplete-call.cpp b/test/SemaCXX/incomplete-call.cpp
index d627c33..69eb03a 100644
--- a/test/SemaCXX/incomplete-call.cpp
+++ b/test/SemaCXX/incomplete-call.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct A; // expected-note 14 {{forward declaration of 'A'}}
-A f(); // expected-note {{note: 'f' declared here}}
+A f(); // expected-note {{'f' declared here}}
struct B {
A f(); // expected-note {{'f' declared here}}
diff --git a/test/SemaCXX/indirect-goto.cpp b/test/SemaCXX/indirect-goto.cpp
new file mode 100644
index 0000000..5b3fac4
--- /dev/null
+++ b/test/SemaCXX/indirect-goto.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace test1 {
+ // Make sure this doesn't crash.
+ struct A { ~A(); };
+ void a() { goto *(A(), &&L); L: return; }
+}
diff --git a/test/SemaCXX/instantiate-blocks.cpp b/test/SemaCXX/instantiate-blocks.cpp
index a4001a7..bb0f8d8 100644
--- a/test/SemaCXX/instantiate-blocks.cpp
+++ b/test/SemaCXX/instantiate-blocks.cpp
@@ -12,8 +12,21 @@ template <typename T, typename T1> void foo(T t, T1 r)
return block_arg+arg; };
}
+// rdar://10466373
+template <typename T, typename T1> void noret(T t, T1 r)
+{
+ (void) ^{
+ if (1)
+ return t;
+ else if (2)
+ return r; // expected-error {{return type 'double' must match previous return type 'float' when block literal has unspecified explicit return type}}
+ };
+}
+
int main(void)
{
foo(100, 'a'); // expected-note {{in instantiation of function template specialization 'foo<int, char>' requested here}}
+
+ noret((float)0.0, double(0.0)); // expected-note {{in instantiation of function template specialization 'noret<float, double>' requested here}}
}
diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp
index 37025d9..287d9af 100644
--- a/test/SemaCXX/invalid-member-expr.cpp
+++ b/test/SemaCXX/invalid-member-expr.cpp
@@ -8,7 +8,7 @@ void test() {
x.int; // expected-error{{expected unqualified-id}}
x.~int(); // expected-error{{expected a class name}}
x.operator; // expected-error{{expected a type}}
- x.operator typedef; // expected-error{{expected a type}}
+ x.operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}}
}
void test2() {
@@ -17,7 +17,7 @@ void test2() {
x->int; // expected-error{{expected unqualified-id}}
x->~int(); // expected-error{{expected a class name}}
x->operator; // expected-error{{expected a type}}
- x->operator typedef; // expected-error{{expected a type}}
+ x->operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}}
}
// PR6327
diff --git a/test/SemaCXX/issue547.cpp b/test/SemaCXX/issue547.cpp
index 5b82dc6..ab03a15 100644
--- a/test/SemaCXX/issue547.cpp
+++ b/test/SemaCXX/issue547.cpp
@@ -11,17 +11,17 @@ struct classify_function<R(Args...)> {
};
template<typename R, typename ...Args>
-struct classify_function<R(Args...) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}}
+struct classify_function<R(Args...) const> {
static const unsigned value = 2;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args...) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args...) volatile> {
static const unsigned value = 3;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args...) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args...) const volatile> {
static const unsigned value = 4;
};
@@ -31,27 +31,27 @@ struct classify_function<R(Args......)> {
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) const> {
static const unsigned value = 6;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) volatile> {
static const unsigned value = 7;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) const volatile> {
static const unsigned value = 8;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) &&> { // expected-warning{{template argument of '&&' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) &&> {
static const unsigned value = 9;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const &> { // expected-warning{{template argument of 'const &' qualified function type is a GNU extension}}
+struct classify_function<R(Args......) const &> {
static const unsigned value = 10;
};
diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp
new file mode 100644
index 0000000..e91dee9
--- /dev/null
+++ b/test/SemaCXX/lambda-expressions.cpp
@@ -0,0 +1,150 @@
+// RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s
+
+namespace std { class type_info; };
+
+namespace ExplicitCapture {
+ class C {
+ int Member;
+
+ static void Overload(int);
+ void Overload();
+ virtual C& Overload(float);
+
+ void ImplicitThisCapture() {
+ [](){(void)Member;}; // expected-error {{'this' cannot be implicitly captured in this context}}
+ [&](){(void)Member;};
+
+ [this](){(void)Member;};
+ [this]{[this]{};};
+ []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}}
+ []{Overload(3);};
+ []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}}
+ []{(void)typeid(Overload());};
+ []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}}
+ }
+ };
+
+ void f() {
+ [this] () {}; // expected-error {{'this' cannot be captured in this context}}
+ }
+}
+
+namespace ReturnDeduction {
+ void test() {
+ [](){ return 1; };
+ [](){ return 1; };
+ [](){ return ({return 1; 1;}); };
+ [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} \
+ // expected-warning{{omitted result type}}
+ []()->int{ return 'c'; return 1; };
+ [](){ return 'c'; return 1; }; // expected-error {{must match previous return type}}
+ []() { return; return (void)0; };
+ [](){ return 1; return 1; }; // expected-warning{{omitted result type}}
+ }
+}
+
+namespace ImplicitCapture {
+ void test() {
+ int a = 0; // expected-note 5 {{declared}}
+ []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}}
+ [&]() { return a; };
+ [=]() { return a; };
+ [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}}
+ [=]() { return [&]() { return a; }; };
+ []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+ []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+ []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}}
+ [=]() { return [&a] { return a; }; }; //
+
+ const int b = 2;
+ []() { return b; };
+
+ union { // expected-note {{declared}}
+ int c;
+ float d;
+ };
+ d = 3;
+ [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}}
+
+ __block int e; // expected-note 3 {{declared}}
+ [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}}
+ [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}}
+
+ int f[10]; // expected-note {{declared}}
+ [&]() { return f[2]; };
+ (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \
+ // expected-note{{lambda expression begins here}}
+
+ struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}}
+ G g;
+ [=]() { const G* gg = &g; return gg->a; }; // expected-warning{{omitted result type}}
+ [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}} \
+ // expected-warning{{omitted result type}}
+ (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}} \
+ // expected-warning{{omitted result type}}
+
+ const int h = a; // expected-note {{declared}}
+ []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+
+ // The exemption for variables which can appear in constant expressions
+ // applies only to objects (and not to references).
+ // FIXME: This might be a bug in the standard.
+ static int i;
+ constexpr int &ref_i = i; // expected-note {{declared}}
+ [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+ }
+}
+
+namespace PR12031 {
+ struct X {
+ template<typename T>
+ X(const T&);
+ ~X();
+ };
+
+ void f(int i, X x);
+ void g() {
+ const int v = 10;
+ f(v, [](){});
+ }
+}
+
+namespace NullPtr {
+ int &f(int *p);
+ char &f(...);
+ void g() {
+ int n = 0;
+ [=] {
+ char &k = f(n); // not a null pointer constant
+ } ();
+
+ const int m = 0;
+ [=] {
+ int &k = f(m); // a null pointer constant
+ } ();
+
+ [=] () -> bool {
+ int &k = f(m); // a null pointer constant
+ return &m == 0;
+ } ();
+
+ [m] {
+ int &k = f(m); // a null pointer constant
+ } ();
+ }
+}
+
+void PR12248()
+{
+ unsigned int result = 0;
+ auto l = [&]() { ++result; };
+}
+
+namespace ModifyingCapture {
+ void test() {
+ int n = 0;
+ [=] {
+ n = 1; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}}
+ };
+ }
+}
diff --git a/test/SemaCXX/literal-operators.cpp b/test/SemaCXX/literal-operators.cpp
index 06ef49f..7f68cd3 100644
--- a/test/SemaCXX/literal-operators.cpp
+++ b/test/SemaCXX/literal-operators.cpp
@@ -13,7 +13,7 @@ namespace ns { void operator "" _ns_good (const char *); }
extern "C++" void operator "" _extern_good (const char *);
extern "C++" { void operator "" _extern_good (const char *); }
-void fn () { void operator "" _fn_bad (const char *); } // expected-error {{literal operator 'operator "" _fn_bad' must be in a namespace or global scope}}
+void fn () { void operator "" _fn_good (const char *); }
// One-param declarations (const char * was already checked)
void operator "" _good (char);
@@ -35,9 +35,9 @@ typedef const char c;
void operator "" _good (c*);
// Check extra cv-qualifiers
-void operator "" _cv_good (volatile const char *, const size_t);
+void operator "" _cv_good (volatile const char *, const size_t); // expected-error {{parameter declaration for literal operator 'operator "" _cv_good' is not valid}}
-// Template delcaration (not implemented yet)
-// template <char...> void operator "" good ();
+// Template declaration
+template <char...> void operator "" _good ();
// FIXME: Test some invalid decls that might crop up.
diff --git a/test/SemaCXX/literal-type.cpp b/test/SemaCXX/literal-type.cpp
index 60bfcf0..14a4094 100644
--- a/test/SemaCXX/literal-type.cpp
+++ b/test/SemaCXX/literal-type.cpp
@@ -23,6 +23,8 @@ static_assert(__is_literal(VectorExt), "fail");
// a constant expression,
// -- it is an aggregate type or has at least one constexpr constructor
// or constructor template that is not a copy or move constructor, and
+// [DR1452 adds class types with trivial default constructors to
+// this list]
// -- it has all non-static data members and base classes of literal
// types
struct Empty {};
@@ -36,25 +38,26 @@ struct LiteralType {
struct HasDtor { ~HasDtor(); };
class NonAggregate { int x; };
-struct HasNonLiteralBase : NonAggregate {};
+struct NonLiteral { NonLiteral(); };
+struct HasNonLiteralBase : NonLiteral {};
struct HasNonLiteralMember { HasDtor x; };
static_assert(__is_literal(Empty), "fail");
static_assert(__is_literal(LiteralType), "fail");
+static_assert(__is_literal(NonAggregate), "fail");
+static_assert(!__is_literal(NonLiteral), "fail");
static_assert(!__is_literal(HasDtor), "fail");
-static_assert(!__is_literal(NonAggregate), "fail");
static_assert(!__is_literal(HasNonLiteralBase), "fail");
static_assert(!__is_literal(HasNonLiteralMember), "fail");
-// FIXME: Test constexpr constructors and non-static members with initializers
-// when Clang supports them:
-#if 0
-extern int f();
+// DR1361 removes the brace-or-equal-initializer bullet so that we can allow:
+extern int f(); // expected-note {{here}}
struct HasNonConstExprMemInit {
- int x = f();
- constexpr HasNonConstExprMemInit(int y) {}
+ int x = f(); // expected-note {{non-constexpr function}}
+ constexpr HasNonConstExprMemInit() {} // expected-error {{never produces a constant expression}}
+ constexpr HasNonConstExprMemInit(int y) : x(y) {} // ok
};
-static_assert(!__is_literal(HasNonConstExprMemInit), "fail");
+static_assert(__is_literal(HasNonConstExprMemInit), "fail");
class HasConstExprCtor {
int x;
@@ -66,6 +69,9 @@ template <typename T> class HasConstExprCtorTemplate {
public:
template <typename U> constexpr HasConstExprCtorTemplate(U y) : x(y) {}
};
+template <typename T> class HasConstExprCtorT {
+ constexpr HasConstExprCtorT(T) {}
+};
static_assert(__is_literal(HasConstExprCtor), "fail");
-static_assert(__is_literal(HasConstExprCtorTemplate), "fail");
-#endif
+static_assert(__is_literal(HasConstExprCtorTemplate<int>), "fail");
+static_assert(__is_literal(HasConstExprCtorT<NonLiteral>), "fail");
diff --git a/test/SemaCXX/member-class-11.cpp b/test/SemaCXX/member-class-11.cpp
new file mode 100644
index 0000000..c230c53
--- /dev/null
+++ b/test/SemaCXX/member-class-11.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+struct rdar9677163 {
+ struct Y { ~Y(); };
+ struct Z { ~Z(); };
+ Y::~Y() { } // expected-error{{non-friend class member '~Y' cannot have a qualified name}}
+ ~Z(); // expected-error{{expected the class name after '~' to name the enclosing class}}
+};
diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp
index 2e3fd73..dbddd1c 100644
--- a/test/SemaCXX/member-expr.cpp
+++ b/test/SemaCXX/member-expr.cpp
@@ -94,11 +94,11 @@ namespace test5 {
namespace PR7508 {
struct A {
struct CleanupScope {};
- void PopCleanupBlock();
+ void PopCleanupBlock(); // expected-note{{'PopCleanupBlock' declared here}}
};
void foo(A &a) {
- a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'}}
+ a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'; did you mean 'PopCleanupBlock'?}}
}
}
@@ -147,3 +147,13 @@ namespace PR9025 {
return fun5.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}}
}
}
+
+namespace FuncInMemberExpr {
+ struct Vec { int size(); };
+ Vec fun1();
+ int test1() { return fun1.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}}
+ Vec *fun2();
+ int test2() { return fun2->size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}}
+ Vec fun3(int x = 0);
+ int test3() { return fun3.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}}
+}
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index 819c8d1..c93c85b 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -29,6 +29,9 @@ const int C = 0, D = 0;
struct S {
int as[] = { decltype(x)::B<C, D>(0) }; // expected-error {{array bound cannot be deduced from an in-class initializer}}
T<sizeof(as) / sizeof(int)> x; // expected-error {{requires a type specifier}}
+ // test that we handle invalid array bound deductions without crashing when the declarator name is itself invalid
+ operator int[](){}; // expected-error {{'operator int' cannot be the name of a variable or data member}} \
+ // expected-error {{array bound cannot be deduced from an in-class initializer}}
};
struct ThrowCtor { ThrowCtor(int) noexcept(false); };
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index cf64810..4e8b4a8 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -278,7 +278,7 @@ namespace PR9973 {
typedef R T::*F;
F f_;
template<class U> int & call(U u)
- { return u->*f_; } // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type '<bound member function type>'}}
+ { return u->*f_; } // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
template<class U> int operator()(U u)
{ call(u); } // expected-note{{in instantiation of}}
diff --git a/test/SemaCXX/microsoft-cxx0x.cpp b/test/SemaCXX/microsoft-cxx0x.cpp
index 3f78eda..3b9bbef 100644
--- a/test/SemaCXX/microsoft-cxx0x.cpp
+++ b/test/SemaCXX/microsoft-cxx0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++0x-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++11-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11
struct A {
@@ -6,5 +6,3 @@ struct A {
};
int b = 3;
A var = { b }; // expected-warning {{ cannot be narrowed }} expected-note {{override}}
-
-
diff --git a/test/SemaCXX/missing-header.cpp b/test/SemaCXX/missing-header.cpp
index f436579..5b3915b 100644
--- a/test/SemaCXX/missing-header.cpp
+++ b/test/SemaCXX/missing-header.cpp
@@ -2,8 +2,8 @@
#include "not exist" // expected-error{{'not exist' file not found}}
-class AnalysisContext {};
-static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
+class AnalysisDeclContext {};
+static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {}
bool NoReturnEdge = false;
}
diff --git a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
index 76ceea1..83f8395 100644
--- a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
+++ b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
@@ -1,15 +1,15 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
namespace fizbin { class Foobar {}; } // expected-note 2 {{'fizbin::Foobar' declared here}} \
// expected-note {{'Foobar' declared here}}
Foobar *my_bar // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}}
= new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}}
-fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{unknown type name 'FooBar'; did you mean 'Foobar'?}}
+fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{no type named 'FooBar' in namespace 'fizbin'; did you mean 'Foobar'?}}
namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}}
int Double(int x) { return x + x; }
void empty() {
- Double(toFoobar()); // expected-error{{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}
+ Double(toFoobar()); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}
}
namespace fizbin {
@@ -36,7 +36,7 @@ void Check() { // expected-note{{'Check' declared here}}
}
void Alt() {
- Cleck(); // expected-error{{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}}
+ Cleck(); // expected-error{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}}
}
namespace N {
@@ -64,13 +64,58 @@ void f() {
// Test case from http://llvm.org/bugs/show_bug.cgi?id=10318
namespace llvm {
- template <typename T> class GraphWriter {}; // expected-note {{'llvm::GraphWriter' declared here}} \
- // expected-note {{'GraphWriter' declared here}}
+ template <typename T> class GraphWriter {}; // expected-note 3{{declared here}}
}
struct S {};
void bar() {
GraphWriter<S> x; //expected-error{{no template named 'GraphWriter'; did you mean 'llvm::GraphWriter'?}}
- (void)new llvm::GraphWriter; // expected-error {{expected a type}}
+ (void)new llvm::GraphWriter; // expected-error {{use of class template llvm::GraphWriter requires template arguments}}
(void)new llvm::Graphwriter<S>; // expected-error {{no template named 'Graphwriter' in namespace 'llvm'; did you mean 'GraphWriter'?}}
}
+
+// If namespace prefixes and character edits have the same weight, correcting
+// "fimish" to "N::famish" would have the same edit distance as correcting
+// "fimish" to "Finish". The result would be no correction being suggested
+// unless one of the corrections is given precedence (e.g. by filtering out
+// suggestions with added namespace qualifiers).
+namespace N { void famish(int); }
+void Finish(int); // expected-note {{'Finish' declared here}}
+void Start() {
+ fimish(7); // expected-error {{use of undeclared identifier 'fimish'; did you mean 'Finish'?}}
+}
+
+// But just eliminating the corrections containing added namespace qualifiers
+// won't work if both of the tied corrections have namespace qualifiers added.
+namespace N {
+void someCheck(int); // expected-note {{'N::someCheck' declared here}}
+namespace O { void somechock(int); }
+}
+void confusing() {
+ somechick(7); // expected-error {{use of undeclared identifier 'somechick'; did you mean 'N::someCheck'?}}
+}
+
+
+class Message {};
+namespace extra {
+ namespace util {
+ namespace MessageUtils {
+ bool Equivalent(const Message&, const Message&); // expected-note {{'extra::util::MessageUtils::Equivalent' declared here}} \
+ // expected-note {{'::extra::util::MessageUtils::Equivalent' declared here}}
+ }
+ }
+}
+namespace util { namespace MessageUtils {} }
+bool nstest () {
+ Message a, b;
+ return util::MessageUtils::Equivalent(a, b); // expected-error {{no member named 'Equivalent' in namespace 'util::MessageUtils'; did you mean 'extra::util::MessageUtils::Equivalent'?}}
+}
+
+namespace util {
+ namespace extra {
+ bool nstest () {
+ Message a, b;
+ return MessageUtils::Equivalent(a, b); // expected-error {{no member named 'Equivalent' in namespace 'util::MessageUtils'; did you mean '::extra::util::MessageUtils::Equivalent'?}}
+ }
+ }
+}
diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp
index 52cae2e..e18b58b 100644
--- a/test/SemaCXX/namespace-alias.cpp
+++ b/test/SemaCXX/namespace-alias.cpp
@@ -11,9 +11,13 @@ namespace C { } // expected-note {{previous definition is here}}
namespace C = N; // expected-error {{redefinition of 'C'}}
int i;
-namespace D = i; // expected-error {{expected namespace name}}
+namespace D =
+i; // expected-error {{expected namespace name}}
-namespace E = N::Foo; // expected-error {{expected namespace name}}
+namespace E1 = N::
+Foo; // expected-error {{expected namespace name}}
+namespace E2 = N::
+X; // expected-error {{expected namespace name}}
namespace F {
namespace A { namespace B { } } // expected-note {{candidate found by name lookup is 'F::A::B'}}
diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp
index e13030c..b317634 100644
--- a/test/SemaCXX/nested-name-spec.cpp
+++ b/test/SemaCXX/nested-name-spec.cpp
@@ -45,7 +45,7 @@ void C2::m() {
}
namespace B {
- void ::A::Af() {} // expected-error {{definition or redeclaration of 'Af' not in a namespace enclosing 'A'}}
+ void ::A::Af() {} // expected-error {{cannot define or redeclare 'Af' here because namespace 'B' does not enclose namespace 'A'}}
}
void f1() {
@@ -160,7 +160,7 @@ namespace N {
void f();
// FIXME: if we move this to a separate definition of N, things break!
}
-void ::global_func2(int) { } // expected-error{{definition or redeclaration of 'global_func2' cannot name the global scope}}
+void ::global_func2(int) { } // expected-warning{{extra qualification on member 'global_func2'}}
void N::f() { } // okay
@@ -274,7 +274,8 @@ struct A {
protected:
struct B;
struct B::C; // expected-error {{requires a template parameter list}} \
- // expected-error {{no struct named 'C'}}
+ // expected-error {{no struct named 'C'}} \
+ // expected-error{{non-friend class member 'C' cannot have a qualified name}}
};
template<typename T>
diff --git a/test/SemaCXX/new-delete-0x.cpp b/test/SemaCXX/new-delete-0x.cpp
new file mode 100644
index 0000000..dcc2e9b
--- /dev/null
+++ b/test/SemaCXX/new-delete-0x.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu -std=c++11
+
+using size_t = decltype(sizeof(0));
+struct noreturn_t {} constexpr noreturn = {};
+
+void *operator new [[noreturn]] (size_t, noreturn_t);
+void operator delete [[noreturn]] (void*, noreturn_t);
+
+void good_news()
+{
+ auto p = new int[2][[]];
+ auto q = new int[[]][2];
+ auto r = new int*[[]][2][[]];
+ auto s = new (int(*[[]])[2][[]]);
+}
+
+void bad_news(int *ip)
+{
+ // attribute-specifiers can go almost anywhere in a new-type-id...
+ auto r = new int[[]{return 1;}()][2]; // expected-error {{expected ']'}}
+ auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected ']'}}
+ // ... but not here:
+ auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot appear here}}
+ auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} expected-error {{variably modified type}}
+}
+
+void good_deletes()
+{
+ delete [&]{ return (int*)0; }();
+ // FIXME: This appears to be legal.
+ delete []{ return (int*)0; }(); // unexpected-error {{expected expression}}
+}
diff --git a/test/SemaCXX/new-delete-cxx0x.cpp b/test/SemaCXX/new-delete-cxx0x.cpp
new file mode 100644
index 0000000..c404fab
--- /dev/null
+++ b/test/SemaCXX/new-delete-cxx0x.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=i686-pc-linux-gnu
+
+void ugly_news(int *ip) {
+ // These are ill-formed according to one reading of C++98, and at the least
+ // have undefined behavior. But they're well-formed, and defined to throw
+ // std::bad_array_new_length, in C++11.
+ (void)new int[-1]; // expected-warning {{array size is negative}}
+ (void)new int[2000000000]; // expected-warning {{array is too large}}
+}
+
+
+struct S {
+ S(int);
+ S();
+ ~S();
+};
+
+struct T { // expected-note 2 {{not viable}}
+ T(int); // expected-note {{not viable}}
+};
+
+void fn() {
+ (void) new int[2] {1, 2};
+ (void) new S[2] {1, 2};
+ (void) new T[2] {1, 2}; // expected-error {{no matching constructor}}
+}
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 748ce77..e77e3d6 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu
#include <stddef.h>
@@ -61,13 +61,13 @@ struct abstract {
void bad_news(int *ip)
{
- int i = 1;
+ int i = 1; // expected-note 2{{here}}
(void)new; // expected-error {{expected a type}}
(void)new 4; // expected-error {{expected a type}}
(void)new () int; // expected-error {{expected expression}}
- (void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}}
- (void)new int[1][i]; // expected-error {{only the first dimension}}
- (void)new (int[1][i]); // expected-error {{only the first dimension}}
+ (void)new int[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}}
+ (void)new int[1][i]; // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
+ (void)new (int[1][i]); // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
(void)new (int[i]); // expected-warning {{when type is in parentheses}}
(void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}}
(void)new int(1, 2); // expected-error {{excess elements in scalar initializer}}
@@ -77,7 +77,8 @@ void bad_news(int *ip)
(void)new float*(ip); // expected-error {{cannot initialize a new value of type 'float *' with an lvalue of type 'int *'}}
// Undefined, but clang should reject it directly.
(void)new int[-1]; // expected-error {{array size is negative}}
- (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'S'}}
+ (void)new int[2000000000]; // expected-error {{array is too large}}
+ (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumeration type, not 'S'}}
(void)::S::new int; // expected-error {{expected unqualified-id}}
(void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}}
(void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}
@@ -101,8 +102,7 @@ void good_deletes()
void bad_deletes()
{
delete 0; // expected-error {{cannot delete expression of type 'int'}}
- delete [0] (int*)0; // expected-error {{expected ']'}} \
- // expected-note {{to match this '['}}
+ delete [0] (int*)0; // expected-error {{expected expression}}
delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}}
delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
::S::delete (int*)0; // expected-error {{expected unqualified-id}}
@@ -386,7 +386,7 @@ namespace PairedDelete {
namespace PR7702 {
void test1() {
- new DoesNotExist; // expected-error {{expected a type}}
+ new DoesNotExist; // expected-error {{unknown type name 'DoesNotExist'}}
}
}
@@ -416,3 +416,86 @@ namespace PR10504 {
};
void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}}
}
+
+struct PlacementArg {};
+inline void *operator new[](size_t, const PlacementArg &) throw () {
+ return 0;
+}
+inline void operator delete[](void *, const PlacementArg &) throw () {
+}
+
+namespace r150682 {
+
+ template <typename X>
+ struct S {
+ struct Inner {};
+ S() { new Inner[1]; }
+ };
+
+ struct T {
+ };
+
+ template<typename X>
+ void tfn() {
+ new (*(PlacementArg*)0) T[1];
+ }
+
+ void fn() {
+ tfn<int>();
+ }
+
+}
+
+namespace P12023 {
+ struct CopyCounter
+ {
+ CopyCounter();
+ CopyCounter(const CopyCounter&);
+ };
+
+ int main()
+ {
+ CopyCounter* f = new CopyCounter[10](CopyCounter()); // expected-error {{cannot have initialization arguments}}
+ return 0;
+ }
+}
+
+namespace PR12061 {
+ template <class C> struct scoped_array {
+ scoped_array(C* p = __null);
+ };
+ template <class Payload> struct Foo {
+ Foo() : a_(new scoped_array<int>[5]) { }
+ scoped_array< scoped_array<int> > a_;
+ };
+ class Bar {};
+ Foo<Bar> x;
+
+ template <class C> struct scoped_array2 {
+ scoped_array2(C* p = __null, C* q = __null);
+ };
+ template <class Payload> struct Foo2 {
+ Foo2() : a_(new scoped_array2<int>[5]) { }
+ scoped_array2< scoped_array2<int> > a_;
+ };
+ class Bar2 {};
+ Foo2<Bar2> x2;
+
+ class MessageLoop {
+ public:
+ explicit MessageLoop(int type = 0);
+ };
+ template <class CookieStoreTestTraits>
+ class CookieStoreTest {
+ protected:
+ CookieStoreTest() {
+ new MessageLoop;
+ }
+ };
+ struct CookieMonsterTestTraits {
+ };
+ class DeferredCookieTaskTest : public CookieStoreTest<CookieMonsterTestTraits>
+ {
+ DeferredCookieTaskTest() {}
+ };
+}
diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp
index 24590ce..a6c0dbf 100644
--- a/test/SemaCXX/null_in_arithmetic_ops.cpp
+++ b/test/SemaCXX/null_in_arithmetic_ops.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify -Wno-string-plus-int %s
#include <stddef.h>
void f() {
diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp
index 6f66036..e313603 100644
--- a/test/SemaCXX/nullptr.cpp
+++ b/test/SemaCXX/nullptr.cpp
@@ -109,19 +109,30 @@ namespace test3 {
}
}
-int array0[__is_scalar(nullptr_t)? 1 : -1];
-int array1[__is_pod(nullptr_t)? 1 : -1];
-int array2[sizeof(nullptr_t) == sizeof(void*)? 1 : -1];
-
-// FIXME: when we implement constexpr, this will be testable.
-#if 0
-int relational0[nullptr < nullptr? -1 : 1];
-int relational1[nullptr > nullptr? -1 : 1];
-int relational2[nullptr <= nullptr? 1 : -1];
-int relational3[nullptr >= nullptr? 1 : -1];
-int equality[nullptr == nullptr? 1 : -1];
-int inequality[nullptr != nullptr? -1 : 1];
-#endif
+static_assert(__is_scalar(nullptr_t), "");
+static_assert(__is_pod(nullptr_t), "");
+static_assert(sizeof(nullptr_t) == sizeof(void*), "");
+
+static_assert(!(nullptr < nullptr), "");
+static_assert(!(nullptr > nullptr), "");
+static_assert( nullptr <= nullptr, "");
+static_assert( nullptr >= nullptr, "");
+static_assert( nullptr == nullptr, "");
+static_assert(!(nullptr != nullptr), "");
+
+static_assert(!(0 < nullptr), "");
+static_assert(!(0 > nullptr), "");
+static_assert( 0 <= nullptr, "");
+static_assert( 0 >= nullptr, "");
+static_assert( 0 == nullptr, "");
+static_assert(!(0 != nullptr), "");
+
+static_assert(!(nullptr < 0), "");
+static_assert(!(nullptr > 0), "");
+static_assert( nullptr <= 0, "");
+static_assert( nullptr >= 0, "");
+static_assert( nullptr == 0, "");
+static_assert(!(nullptr != 0), "");
namespace overloading {
int &f1(int*);
@@ -161,3 +172,14 @@ namespace templates {
X2<nullptr, nullptr, nullptr, nullptr> x2;
}
+
+namespace null_pointer_constant {
+
+// Pending implementation of core issue 903, ensure we don't allow any of the
+// C++11 constant evaluation semantics in null pointer constants.
+struct S { int n; };
+constexpr int null() { return 0; }
+void *p = S().n; // expected-error {{cannot initialize}}
+void *q = null(); // expected-error {{cannot initialize}}
+
+}
diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp
index 17cee62..a5f5d34 100644
--- a/test/SemaCXX/offsetof.cpp
+++ b/test/SemaCXX/offsetof.cpp
@@ -66,3 +66,10 @@ struct bar : public foo {
};
int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1];
+
+struct LtoRCheck {
+ int a[10];
+ int f();
+};
+int ltor = __builtin_offsetof(struct LtoRCheck, a[LtoRCheck().f]); // \
+ expected-error {{reference to non-static member function must be called}}
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 00f6a94..b5e1214 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -8,10 +8,10 @@ void test_f(int iv, float fv) {
int* ip = f(iv);
}
-int* g(int, float, int); // expected-note {{ candidate function }}
-float* g(int, int, int); // expected-note {{ candidate function }}
-double* g(int, float, float); // expected-note {{ candidate function }}
-char* g(int, float, ...); // expected-note {{ candidate function }}
+int* g(int, float, int); // expected-note {{candidate function}}
+float* g(int, int, int); // expected-note {{candidate function}}
+double* g(int, float, float); // expected-note {{candidate function}}
+char* g(int, float, ...); // expected-note {{candidate function}}
void g();
void test_g(int iv, float fv) {
@@ -21,7 +21,7 @@ void test_g(int iv, float fv) {
char* cp1 = g(0, 0);
char* cp2 = g(0, 0, 0, iv, fv);
- double* dp2 = g(0, fv, 1.5); // expected-error {{ call to 'g' is ambiguous; candidates are: }}
+ double* dp2 = g(0, fv, 1.5); // expected-error {{call to 'g' is ambiguous}}
}
double* h(double f);
@@ -126,9 +126,9 @@ void test_bitfield(Bits bits, int x) {
float* fp = bitfields(bits.uint_bitfield, 0u);
}
-int* multiparm(long, int, long); // expected-note {{ candidate function }}
-float* multiparm(int, int, int); // expected-note {{ candidate function }}
-double* multiparm(int, int, short); // expected-note {{ candidate function }}
+int* multiparm(long, int, long); // expected-note {{candidate function}}
+float* multiparm(int, int, int); // expected-note {{candidate function}}
+double* multiparm(int, int, short); // expected-note {{candidate function}}
void test_multiparm(long lv, short sv, int iv) {
int* ip1 = multiparm(lv, iv, lv);
@@ -137,7 +137,7 @@ void test_multiparm(long lv, short sv, int iv) {
float* fp2 = multiparm(sv, iv, iv);
double* dp1 = multiparm(sv, sv, sv);
double* dp2 = multiparm(iv, sv, sv);
- multiparm(sv, sv, lv); // expected-error {{ call to 'multiparm' is ambiguous; candidates are: }}
+ multiparm(sv, sv, lv); // expected-error {{call to 'multiparm' is ambiguous}}
}
// Test overloading based on qualification vs. no qualification
@@ -183,9 +183,9 @@ void test_quals_ranking(int * p, int volatile *pq, int * * pp, int * * * ppp) {
float* q6 = quals_rank2(pp);
- quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}}
+ quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous}}
- quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}}
+ quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous}}
quals_rank3(pq);
}
@@ -233,7 +233,7 @@ float* intref(const int&);
void intref_test() {
float* ir1 = intref(5);
- float* ir2 = intref(5.5);
+ float* ir2 = intref(5.5); // expected-warning{{implicit conversion turns literal floating-point number into integer}}
}
void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}}
@@ -266,8 +266,8 @@ float& cvqual_subsume2(const volatile Y&); // expected-note{{candidate function}
Z get_Z();
void cvqual_subsume_test(Z z) {
- cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous; candidates are:}}
- int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous; candidates are:}}
+ cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous}}
+ int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous}}
}
// Test overloading with cv-qualification differences in reference
@@ -534,3 +534,37 @@ namespace rdar9803316 {
int &ir = (&foo)(0);
}
}
+
+namespace IncompleteArg {
+ // Ensure that overload resolution attempts to complete argument types when
+ // performing ADL.
+ template<typename T> struct S {
+ friend int f(const S&);
+ };
+ extern S<int> s;
+ int k = f(s);
+
+ template<typename T> struct Op {
+ friend bool operator==(const Op &, const Op &);
+ };
+ extern Op<char> op;
+ bool b = op == op;
+
+ // ... and not in other cases! Nothing here requires U<int()> to be complete.
+ // (Note that instantiating U<int()> will fail.)
+ template<typename T> struct U {
+ T t;
+ };
+ struct Consumer {
+ template<typename T>
+ int operator()(const U<T> &);
+ };
+ template<typename T> U<T> &make();
+ Consumer c;
+ int n = sizeof(c(make<int()>()));
+}
+
+namespace PR12142 {
+ void fun(int (*x)[10]); // expected-note{{candidate function not viable: 1st argument ('const int (*)[10]') would lose const qualifier}}
+ void g() { fun((const int(*)[10])0); } // expected-error{{no matching function for call to 'fun'}}
+}
diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp
index 37815b9..37c9552 100644
--- a/test/SemaCXX/overload-member-call.cpp
+++ b/test/SemaCXX/overload-member-call.cpp
@@ -32,7 +32,7 @@ struct X {
static void test_member_static() {
double& d1 = g(0.0);
- g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}}
+ g(0); // expected-error{{call to 'g' is ambiguous}}
}
};
@@ -41,8 +41,8 @@ void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp)
int& i2 = xcp->f(0);
float& f1 = x.f(0);
float& f2 = xp->f(0);
- xv.f(0); // expected-error{{no matching member function for call to 'f'; candidates are:}}
- xvp->f(0); // expected-error{{no matching member function for call to 'f'; candidates are:}}
+ xv.f(0); // expected-error{{no matching member function for call to 'f'}}
+ xvp->f(0); // expected-error{{no matching member function for call to 'f'}}
int& i3 = xc.g(0);
int& i4 = xcp->g(0);
@@ -50,7 +50,7 @@ void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp)
float& f4 = xp->g(0);
double& d1 = xp->g(0.0);
double& d2 = X::g(0.0);
- X::g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}}
+ X::g(0); // expected-error{{call to 'g' is ambiguous}}
X::h(0); // expected-error{{call to non-static member function without an object argument}}
}
diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp
index a5ec51c..6da0354 100644
--- a/test/SemaCXX/overloaded-name.cpp
+++ b/test/SemaCXX/overloaded-name.cpp
@@ -21,11 +21,10 @@ namespace rdar9623945 {
public:
const char* text(void);
void g(void) {
- // FIXME: why 2x?
f(text());
- f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
+ f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
f(text());
- f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
+ f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
}
};
}
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index 1e4a3b7..8ecb54d 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -232,7 +232,7 @@ struct Arrow2 {
void test_arrow(Arrow1 a1, Arrow2 a2, const Arrow2 a3) {
int &i1 = a1->m;
int &i2 = a2->m;
- a3->m; // expected-error{{no viable overloaded 'operator->'; candidate is}}
+ a3->m; // expected-error{{no viable overloaded 'operator->'}}
}
struct CopyConBase {
@@ -392,7 +392,7 @@ namespace rdar9136502 {
};
struct Y {
- Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}}
+ Y &operator<<(int);
};
void f(X x, Y y) {
@@ -408,3 +408,10 @@ class StringRef {
};
}
+
+namespace PR11784 {
+ struct A { A& operator=(void (*x)()); };
+ void f();
+ void f(int);
+ void g() { A x; x = f; }
+}
diff --git a/test/SemaCXX/pragma-visibility.cpp b/test/SemaCXX/pragma-visibility.cpp
new file mode 100644
index 0000000..e3ef97a
--- /dev/null
+++ b/test/SemaCXX/pragma-visibility.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace test1 __attribute__((visibility("hidden"))) { // expected-note{{surrounding namespace with visibility attribute starts here}}
+#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}}
+}
+
+// GCC 4.6 accepts this, but the "hidden" leaks past the namespace end.
+namespace test2 __attribute__((visibility("hidden"))) {
+#pragma GCC visibility push(protected) // expected-error{{#pragma visibility push with no matching #pragma visibility pop}}
+} // expected-note{{surrounding namespace with visibility attribute ends here}}
+
+#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}}
+
+// <rdar://problem/10871094>
+struct A {
+ #pragma GCC visibility push(protected)
+ #pragma GCC visibility pop
+};
+
+void f() {
+ #pragma GCC visibility push(protected)
+ #pragma GCC visibility pop
+}
diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp
index d71304e..a8f6683 100644
--- a/test/SemaCXX/pseudo-destructors.cpp
+++ b/test/SemaCXX/pseudo-destructors.cpp
@@ -19,7 +19,7 @@ void cv_test(const volatile T* cvt) {
cvt->T::~T(); // no-warning
}
-void f(A* a, Foo *f, int *i, double *d) {
+void f(A* a, Foo *f, int *i, double *d, int ii) {
a->~A();
a->A::~A();
@@ -46,6 +46,9 @@ void f(A* a, Foo *f, int *i, double *d) {
i->N::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}
i->Integer::~Double(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('Double' (aka 'double')) in pseudo-destructor expression}}
+ ii->~Integer(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}}
+ ii.~Integer();
+
cv_test(a);
cv_test(f);
cv_test(i);
@@ -68,3 +71,12 @@ void test_X0(N1::X0 &x0) {
x0.~X0();
}
+namespace PR11339 {
+ template<class T>
+ void destroy(T* p) {
+ p->~T(); // ok
+ p->~oops(); // expected-error{{expected the class name after '~' to name a destructor}}
+ }
+
+ template void destroy(int*); // expected-note{{in instantiation of function template specialization}}
+}
diff --git a/test/SemaCXX/qual-id-test.cpp b/test/SemaCXX/qual-id-test.cpp
index e5c7306..9994d75 100644
--- a/test/SemaCXX/qual-id-test.cpp
+++ b/test/SemaCXX/qual-id-test.cpp
@@ -137,13 +137,13 @@ struct a {
a a;
-int a::sa = a.a; // expected-error {{invalid use of nonstatic data member 'a'}}
+int a::sa = a.a; // expected-error {{invalid use of non-static data member 'a'}}
namespace PR6645 {
typedef int foo;
namespace Inner {
typedef int PR6645::foo; // expected-error{{typedef declarator cannot be qualified}} \
- // expected-error{{definition or redeclaration of 'foo' not in a namespace enclosing 'PR6645'}}
+ // expected-error{{cannot define or redeclare 'foo' here because namespace 'Inner' does not enclose namespace 'PR6645'}}
}
}
diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp
index 3cd6e18..d65a468 100644
--- a/test/SemaCXX/qualified-id-lookup.cpp
+++ b/test/SemaCXX/qualified-id-lookup.cpp
@@ -146,3 +146,8 @@ namespace PR6830 {
Z(foo::X()).Work();
}
}
+
+namespace pr12339 {
+ extern "C" void i;
+ pr12339::FOO // expected-error{{no type named 'FOO' in namespace 'pr12339'}}
+} // expected-error{{expected unqualified-id}}
diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp
index 68005a5..7f41b93 100644
--- a/test/SemaCXX/reinterpret-cast.cpp
+++ b/test/SemaCXX/reinterpret-cast.cpp
@@ -9,13 +9,27 @@ typedef void (*fnptr)();
// Test the conversion to self.
void self_conversion()
{
- // T*->T* is allowed, T->T in general not.
+ // T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't
+ // cast away constness, and is integral, enumeration, pointer or
+ // pointer-to-member.
int i = 0;
- (void)reinterpret_cast<int>(i); // expected-error {{reinterpret_cast from 'int' to 'int' is not allowed}}
- structure s;
- (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}}
+ (void)reinterpret_cast<int>(i);
+
+ test e = testval;
+ (void)reinterpret_cast<test>(e);
+
+ // T*->T* is allowed
int *pi = 0;
(void)reinterpret_cast<int*>(pi);
+
+ const int structure::*psi = 0;
+ (void)reinterpret_cast<const int structure::*>(psi);
+
+ structure s;
+ (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}}
+
+ float f = 0.0f;
+ (void)reinterpret_cast<float>(f); // expected-error {{reinterpret_cast from 'float' to 'float' is not allowed}}
}
// Test conversion between pointer and integral types, as in /3 and /4.
diff --git a/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp
index 09d08f9..9cdf5a1 100644
--- a/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp
+++ b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp
@@ -4,6 +4,6 @@ void fnptrs()
{
typedef void (*fnptr)();
fnptr fp = 0;
- void *vp = reinterpret_cast<void*>(fp); // expected-warning {{reinterpret_cast between pointer-to-function and pointer-to-object is an extension}}
- (void)reinterpret_cast<fnptr>(vp); // expected-warning {{reinterpret_cast between pointer-to-function and pointer-to-object is an extension}}
+ void *vp = reinterpret_cast<void*>(fp); // expected-warning {{cast between pointer-to-function and pointer-to-object is an extension}}
+ (void)reinterpret_cast<fnptr>(vp); // expected-warning {{cast between pointer-to-function and pointer-to-object is an extension}}
}
diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp
index e06ba40..617de00 100644
--- a/test/SemaCXX/return-noreturn.cpp
+++ b/test/SemaCXX/return-noreturn.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code
-// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code
+// RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
+// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
// A destructor may be marked noreturn and should still influence the CFG.
void pr6884_abort() __attribute__((noreturn));
diff --git a/test/SemaCXX/runtimediag-ppe.cpp b/test/SemaCXX/runtimediag-ppe.cpp
new file mode 100644
index 0000000..0e8451b
--- /dev/null
+++ b/test/SemaCXX/runtimediag-ppe.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Make sure diagnostics that we don't print based on runtime control
+// flow are delayed correctly in cases where we can't immediately tell whether
+// the context is unevaluated.
+
+namespace std {
+ class type_info;
+}
+
+int& NP(int);
+void test1() { (void)typeid(NP(1 << 32)); }
+
+class Poly { virtual ~Poly(); };
+Poly& P(int);
+void test2() { (void)typeid(P(1 << 32)); } // expected-warning {{shift count >= width of type}}
+
+void test3() { 1 ? (void)0 : (void)typeid(P(1 << 32)); }
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index ad109f4..b659de0 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -20,7 +20,7 @@ namespace test1 {
int f(bool b) {
if (b)
- goto foo; // expected-error {{illegal goto into protected scope}}
+ goto foo; // expected-error {{goto into protected scope}}
C c; // expected-note {{jump bypasses variable initialization}}
foo:
return 1;
diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp
index 0e27f46..6d04c84 100644
--- a/test/SemaCXX/statements.cpp
+++ b/test/SemaCXX/statements.cpp
@@ -10,7 +10,7 @@ struct X {
};
void test2() {
- goto later; // expected-error {{illegal goto into protected scope}}
+ goto later; // expected-error {{goto into protected scope}}
X x; // expected-note {{jump bypasses variable initialization}}
later:
;
diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp
index 0991a5f..364e4e4 100644
--- a/test/SemaCXX/static-assert.cpp
+++ b/test/SemaCXX/static-assert.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=x86_64-linux-gnu
-int f();
+int f(); // expected-note {{declared here}}
-static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}}
+static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}}
static_assert(true, "true is not false");
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
@@ -28,3 +28,9 @@ template<typename T> struct S {
S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}}
S<int> s2;
+static_assert(false, L"\xFFFFFFFF"); // expected-error {{static_assert failed L"\xFFFFFFFF"}}
+static_assert(false, u"\U000317FF"); // expected-error {{static_assert failed u"\U000317FF"}}
+// FIXME: render this as u8"\u03A9"
+static_assert(false, u8"Ω"); // expected-error {{static_assert failed u8"\316\251"}}
+static_assert(false, L"\u1234"); // expected-error {{static_assert failed L"\x1234"}}
+static_assert(false, L"\x1ff" "0\x123" "fx\xfffff" "goop"); // expected-error {{static_assert failed L"\x1FF""0\x123""fx\xFFFFFgoop"}}
diff --git a/test/SemaCXX/string-plus-int.cpp b/test/SemaCXX/string-plus-int.cpp
new file mode 100644
index 0000000..5752f8f
--- /dev/null
+++ b/test/SemaCXX/string-plus-int.cpp
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-array-bounds %s -fpascal-strings
+// RUN: %clang_cc1 -fdiagnostics-parseable-fixits -x c++ %s 2>&1 -Wno-array-bounds -fpascal-strings | FileCheck %s
+
+void consume(const char* c) {}
+void consume(const unsigned char* c) {}
+void consume(const wchar_t* c) {}
+void consumeChar(char c) {}
+
+enum MyEnum {
+ kMySmallEnum = 1,
+ kMyEnum = 5
+};
+
+enum OperatorOverloadEnum {
+ kMyOperatorOverloadedEnum = 5
+};
+
+const char* operator+(const char* c, OperatorOverloadEnum e) {
+ return "yo";
+}
+
+const char* operator+(OperatorOverloadEnum e, const char* c) {
+ return "yo";
+}
+
+void f(int index) {
+ // Should warn.
+ // CHECK: fix-it:"{{.*}}":{31:11-31:11}:"&"
+ // CHECK: fix-it:"{{.*}}":{31:17-31:18}:"["
+ // CHECK: fix-it:"{{.*}}":{31:20-31:20}:"]"
+ consume("foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume("foo" + index); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume("foo" + kMyEnum); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ consume(5 + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume(index + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consume(kMyEnum + "foo"); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ // FIXME: suggest replacing with "foo"[5]
+ consumeChar(*("foo" + 5)); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ consumeChar(*(5 + "foo")); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ consume(L"foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ // Should not warn.
+ consume(&("foo"[3]));
+ consume(&("foo"[index]));
+ consume(&("foo"[kMyEnum]));
+ consume("foo" + kMySmallEnum);
+ consume(kMySmallEnum + "foo");
+
+ consume(L"foo" + 2);
+
+ consume("foo" + 3); // Points at the \0
+ consume("foo" + 4); // Points 1 past the \0, which is legal too.
+ consume("\pfoo" + 4); // Pascal strings don't have a trailing \0, but they
+ // have a leading length byte, so this is fine too.
+
+ consume("foo" + kMyOperatorOverloadedEnum);
+ consume(kMyOperatorOverloadedEnum + "foo");
+
+ #define A "foo"
+ #define B "bar"
+ consume(A B + sizeof(A) - 1);
+}
+
diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp
index 8a8cf33..517faa9 100644
--- a/test/SemaCXX/switch.cpp
+++ b/test/SemaCXX/switch.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-enum %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
void test() {
bool x = true;
@@ -64,3 +64,24 @@ void click_check_header_sizes() {
case 0: ;
}
}
+
+void local_class(int n) {
+ for (;;) switch (n) {
+ case 0:
+ struct S {
+ void f() {
+ case 1: // expected-error {{'case' statement not in switch statement}}
+ break; // expected-error {{'break' statement not in loop or switch statement}}
+ default: // expected-error {{'default' statement not in switch statement}}
+ continue; // expected-error {{'continue' statement not in loop statement}}
+ }
+ };
+ S().f();
+ []{
+ case 2: // expected-error {{'case' statement not in switch statement}}
+ break; // expected-error {{'break' statement not in loop or switch statement}}
+ default: // expected-error {{'default' statement not in switch statement}}
+ continue; // expected-error {{'continue' statement not in loop statement}}
+ }();
+ }
+}
diff --git a/test/SemaCXX/this.cpp b/test/SemaCXX/this.cpp
index 167755f..27ee1e8 100644
--- a/test/SemaCXX/this.cpp
+++ b/test/SemaCXX/this.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}}
+int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
void f() {
- int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}}
+ int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}}
}
diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp
index e25939f..c219b77 100644
--- a/test/SemaCXX/trailing-return-0x.cpp
+++ b/test/SemaCXX/trailing-return-0x.cpp
@@ -21,6 +21,16 @@ auto g(); // expected-error{{return without trailing return type}}
int h() -> int; // expected-error{{trailing return type must specify return type 'auto', not 'int'}}
+int i();
+auto i() -> int;
+int i() {}
+
+using T = auto (int) -> auto (*)(char) -> void; // expected-note {{previous}}
+using T = void; // expected-error {{type alias redefinition with different types ('void' vs 'auto (int) -> auto (*)(char) -> void')}}
+
+using U = auto (int) -> auto (*)(char) -> void;
+using U = void (*(int))(char); // ok
+
int x;
template <class T>
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index 0914c7c..f53939a 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -39,6 +39,18 @@ struct DerivesEmpty : Empty {};
struct HasCons { HasCons(int); };
struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); };
struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); };
+struct HasDefaultTrivialCopyAssign {
+ HasDefaultTrivialCopyAssign &operator =(const HasDefaultTrivialCopyAssign&)
+ = default;
+};
+struct TrivialMoveButNotCopy {
+ TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default;
+ TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&);
+};
+struct NonTrivialDefault {
+ NonTrivialDefault();
+};
+
struct HasDest { ~HasDest(); };
class HasPriv { int priv; };
class HasProt { protected: int prot; };
@@ -96,6 +108,10 @@ class AllPrivate {
~AllPrivate() throw();
};
+struct ThreeArgCtor {
+ ThreeArgCtor(int*, char*, int);
+};
+
void is_pod()
{
{ int arr[T(__is_pod(int))]; }
@@ -235,6 +251,37 @@ void is_enum()
{ int arr[F(__is_enum(HasAnonymousUnion))]; }
}
+struct FinalClass final {
+};
+
+template<typename T>
+struct PotentiallyFinal { };
+
+template<typename T>
+struct PotentiallyFinal<T*> final { };
+
+template<>
+struct PotentiallyFinal<int> final { };
+
+void is_final()
+{
+ { int arr[T(__is_final(FinalClass))]; }
+ { int arr[T(__is_final(PotentiallyFinal<float*>))]; }
+ { int arr[T(__is_final(PotentiallyFinal<int>))]; }
+
+ { int arr[F(__is_final(int))]; }
+ { int arr[F(__is_final(Union))]; }
+ { int arr[F(__is_final(Int))]; }
+ { int arr[F(__is_final(IntAr))]; }
+ { int arr[F(__is_final(UnionAr))]; }
+ { int arr[F(__is_final(Derives))]; }
+ { int arr[F(__is_final(ClassType))]; }
+ { int arr[F(__is_final(cvoid))]; }
+ { int arr[F(__is_final(IntArNB))]; }
+ { int arr[F(__is_final(HasAnonymousUnion))]; }
+ { int arr[F(__is_final(PotentiallyFinal<float>))]; }
+}
+
typedef HasVirt Polymorph;
struct InheritPolymorph : Polymorph {};
@@ -885,6 +932,41 @@ struct NonTCStruct {
NonTCStruct(const NonTCStruct&) {}
};
+struct AllDefaulted {
+ AllDefaulted() = default;
+ AllDefaulted(const AllDefaulted &) = default;
+ AllDefaulted(AllDefaulted &&) = default;
+ AllDefaulted &operator=(const AllDefaulted &) = default;
+ AllDefaulted &operator=(AllDefaulted &&) = default;
+ ~AllDefaulted() = default;
+};
+
+struct AllDeleted {
+ AllDeleted() = delete;
+ AllDeleted(const AllDeleted &) = delete;
+ AllDeleted(AllDeleted &&) = delete;
+ AllDeleted &operator=(const AllDeleted &) = delete;
+ AllDeleted &operator=(AllDeleted &&) = delete;
+ ~AllDeleted() = delete;
+};
+
+struct ExtDefaulted {
+ ExtDefaulted();
+ ExtDefaulted(const ExtDefaulted &);
+ ExtDefaulted(ExtDefaulted &&);
+ ExtDefaulted &operator=(const ExtDefaulted &);
+ ExtDefaulted &operator=(ExtDefaulted &&);
+ ~ExtDefaulted();
+};
+
+// Despite being defaulted, these functions are not trivial.
+ExtDefaulted::ExtDefaulted() = default;
+ExtDefaulted::ExtDefaulted(const ExtDefaulted &) = default;
+ExtDefaulted::ExtDefaulted(ExtDefaulted &&) = default;
+ExtDefaulted &ExtDefaulted::operator=(const ExtDefaulted &) = default;
+ExtDefaulted &ExtDefaulted::operator=(ExtDefaulted &&) = default;
+ExtDefaulted::~ExtDefaulted() = default;
+
void is_trivial2()
{
int t01[T(__is_trivial(char))];
@@ -909,11 +991,14 @@ void is_trivial2()
int t20[T(__is_trivial(Union))];
int t21[T(__is_trivial(UnionAr))];
int t22[T(__is_trivial(TrivialStruct))];
+ int t23[T(__is_trivial(AllDefaulted))];
+ int t24[T(__is_trivial(AllDeleted))];
int t30[F(__is_trivial(void))];
int t31[F(__is_trivial(NonTrivialStruct))];
int t32[F(__is_trivial(SuperNonTrivialStruct))];
int t33[F(__is_trivial(NonTCStruct))];
+ int t34[F(__is_trivial(ExtDefaulted))];
}
void is_trivially_copyable2()
@@ -941,10 +1026,13 @@ void is_trivially_copyable2()
int t21[T(__is_trivially_copyable(UnionAr))];
int t22[T(__is_trivially_copyable(TrivialStruct))];
int t23[T(__is_trivially_copyable(NonTrivialStruct))];
+ int t24[T(__is_trivially_copyable(AllDefaulted))];
+ int t25[T(__is_trivially_copyable(AllDeleted))];
int t30[F(__is_trivially_copyable(void))];
- int t32[F(__is_trivially_copyable(SuperNonTrivialStruct))];
- int t31[F(__is_trivially_copyable(NonTCStruct))];
+ int t31[F(__is_trivially_copyable(SuperNonTrivialStruct))];
+ int t32[F(__is_trivially_copyable(NonTCStruct))];
+ int t33[F(__is_trivially_copyable(ExtDefaulted))];
}
struct CStruct {
@@ -1100,6 +1188,8 @@ void has_trivial_default_constructor() {
{ int arr[T(__has_trivial_constructor(HasCopyAssign))]; }
{ int arr[T(__has_trivial_constructor(HasMoveAssign))]; }
{ int arr[T(__has_trivial_constructor(const Int))]; }
+ { int arr[T(__has_trivial_constructor(AllDefaulted))]; }
+ { int arr[T(__has_trivial_constructor(AllDeleted))]; }
{ int arr[F(__has_trivial_constructor(HasCons))]; }
{ int arr[F(__has_trivial_constructor(HasRef))]; }
@@ -1110,6 +1200,7 @@ void has_trivial_default_constructor() {
{ int arr[F(__has_trivial_constructor(cvoid))]; }
{ int arr[F(__has_trivial_constructor(HasTemplateCons))]; }
{ int arr[F(__has_trivial_constructor(AllPrivate))]; }
+ { int arr[F(__has_trivial_constructor(ExtDefaulted))]; }
}
void has_trivial_copy_constructor() {
@@ -1130,6 +1221,8 @@ void has_trivial_copy_constructor() {
{ int arr[T(__has_trivial_copy(HasCopyAssign))]; }
{ int arr[T(__has_trivial_copy(HasMoveAssign))]; }
{ int arr[T(__has_trivial_copy(const Int))]; }
+ { int arr[T(__has_trivial_copy(AllDefaulted))]; }
+ { int arr[T(__has_trivial_copy(AllDeleted))]; }
{ int arr[F(__has_trivial_copy(HasCopy))]; }
{ int arr[F(__has_trivial_copy(HasTemplateCons))]; }
@@ -1138,6 +1231,7 @@ void has_trivial_copy_constructor() {
{ int arr[F(__has_trivial_copy(void))]; }
{ int arr[F(__has_trivial_copy(cvoid))]; }
{ int arr[F(__has_trivial_copy(AllPrivate))]; }
+ { int arr[F(__has_trivial_copy(ExtDefaulted))]; }
}
void has_trivial_copy_assignment() {
@@ -1154,6 +1248,8 @@ void has_trivial_copy_assignment() {
{ int arr[T(__has_trivial_assign(HasCopy))]; }
{ int arr[T(__has_trivial_assign(HasMove))]; }
{ int arr[T(__has_trivial_assign(HasMoveAssign))]; }
+ { int arr[T(__has_trivial_assign(AllDefaulted))]; }
+ { int arr[T(__has_trivial_assign(AllDeleted))]; }
{ int arr[F(__has_trivial_assign(IntRef))]; }
{ int arr[F(__has_trivial_assign(HasCopyAssign))]; }
@@ -1165,6 +1261,7 @@ void has_trivial_copy_assignment() {
{ int arr[F(__has_trivial_assign(void))]; }
{ int arr[F(__has_trivial_assign(cvoid))]; }
{ int arr[F(__has_trivial_assign(AllPrivate))]; }
+ { int arr[F(__has_trivial_assign(ExtDefaulted))]; }
}
void has_trivial_destructor() {
@@ -1187,11 +1284,14 @@ void has_trivial_destructor() {
{ int arr[T(__has_trivial_destructor(const Int))]; }
{ int arr[T(__has_trivial_destructor(DerivesAr))]; }
{ int arr[T(__has_trivial_destructor(VirtAr))]; }
+ { int arr[T(__has_trivial_destructor(AllDefaulted))]; }
+ { int arr[T(__has_trivial_destructor(AllDeleted))]; }
{ int arr[F(__has_trivial_destructor(HasDest))]; }
{ int arr[F(__has_trivial_destructor(void))]; }
{ int arr[F(__has_trivial_destructor(cvoid))]; }
{ int arr[F(__has_trivial_destructor(AllPrivate))]; }
+ { int arr[F(__has_trivial_destructor(ExtDefaulted))]; }
}
struct A { ~A() {} };
@@ -1413,13 +1513,11 @@ void is_base_of() {
isBaseOfF<DerivedB<int>, BaseA<int> >();
}
-#if 0
template<class T, class U>
class TemplateClass {};
template<class T>
using TemplateAlias = TemplateClass<T, int>;
-#endif
typedef class Base BaseTypedef;
@@ -1427,9 +1525,7 @@ void is_same()
{
int t01[T(__is_same(Base, Base))];
int t02[T(__is_same(Base, BaseTypedef))];
-#if 0
int t03[T(__is_same(TemplateClass<int, int>, TemplateAlias<int>))];
-#endif
int t10[F(__is_same(Base, const Base))];
int t11[F(__is_same(Base, Base&))];
@@ -1512,6 +1608,12 @@ void is_convertible_to() {
{ int arr[T(__is_convertible_to(X0<int>, X0<float>))]; }
}
+namespace is_convertible_to_instantiate {
+ // Make sure we don't try to instantiate the constructor.
+ template<int x> class A { A(int) { int a[x]; } };
+ int x = __is_convertible_to(int, A<-1>);
+}
+
void is_trivial()
{
{ int arr[T(__is_trivial(int))]; }
@@ -1557,7 +1659,7 @@ void is_trivial()
{ int arr[F(__is_trivial(cvoid))]; }
}
-void is_trivially_copyable()
+void trivial_checks()
{
{ int arr[T(__is_trivially_copyable(int))]; }
{ int arr[T(__is_trivially_copyable(Enum))]; }
@@ -1600,6 +1702,108 @@ void is_trivially_copyable()
{ int arr[F(__is_trivially_copyable(DerivesHasVirt))]; }
{ int arr[F(__is_trivially_copyable(void))]; }
{ int arr[F(__is_trivially_copyable(cvoid))]; }
+
+ { int arr[T((__is_trivially_constructible(int)))]; }
+ { int arr[T((__is_trivially_constructible(int, int)))]; }
+ { int arr[T((__is_trivially_constructible(int, float)))]; }
+ { int arr[T((__is_trivially_constructible(int, int&)))]; }
+ { int arr[T((__is_trivially_constructible(int, const int&)))]; }
+ { int arr[T((__is_trivially_constructible(int, int)))]; }
+ { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; }
+ { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; }
+ { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; }
+ { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; }
+ { int arr[T((__is_trivially_constructible(NonTrivialDefault,
+ const NonTrivialDefault&)))]; }
+ { int arr[T((__is_trivially_constructible(NonTrivialDefault,
+ NonTrivialDefault&&)))]; }
+ { int arr[T((__is_trivially_constructible(AllDefaulted)))]; }
+ { int arr[T((__is_trivially_constructible(AllDefaulted,
+ const AllDefaulted &)))]; }
+ { int arr[T((__is_trivially_constructible(AllDefaulted,
+ AllDefaulted &&)))]; }
+
+ { int arr[F((__is_trivially_constructible(int, int*)))]; }
+ { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; }
+ { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; }
+ { int arr[F((__is_trivially_constructible(AllDeleted)))]; }
+ { int arr[F((__is_trivially_constructible(AllDeleted,
+ const AllDeleted &)))]; }
+ { int arr[F((__is_trivially_constructible(AllDeleted,
+ AllDeleted &&)))]; }
+ { int arr[F((__is_trivially_constructible(ExtDefaulted)))]; }
+ { int arr[F((__is_trivially_constructible(ExtDefaulted,
+ const ExtDefaulted &)))]; }
+ { int arr[F((__is_trivially_constructible(ExtDefaulted,
+ ExtDefaulted &&)))]; }
+
+ { int arr[T((__is_trivially_assignable(int&, int)))]; }
+ { int arr[T((__is_trivially_assignable(int&, int&)))]; }
+ { int arr[T((__is_trivially_assignable(int&, int&&)))]; }
+ { int arr[T((__is_trivially_assignable(int&, const int&)))]; }
+ { int arr[T((__is_trivially_assignable(POD&, POD)))]; }
+ { int arr[T((__is_trivially_assignable(POD&, POD&)))]; }
+ { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; }
+ { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; }
+ { int arr[T((__is_trivially_assignable(int*&, int*)))]; }
+ { int arr[T((__is_trivially_assignable(AllDefaulted,
+ const AllDefaulted &)))]; }
+ { int arr[T((__is_trivially_assignable(AllDefaulted,
+ AllDefaulted &&)))]; }
+
+ { int arr[F((__is_trivially_assignable(int*&, float*)))]; }
+ { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)))]; }
+ { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&)))]; }
+ { int arr[F((__is_trivially_assignable(HasCopyAssign&, const HasCopyAssign&)))]; }
+ { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&&)))]; }
+ { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
+ TrivialMoveButNotCopy&)))]; }
+ { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
+ const TrivialMoveButNotCopy&)))]; }
+ { int arr[F((__is_trivially_assignable(AllDeleted,
+ const AllDeleted &)))]; }
+ { int arr[F((__is_trivially_assignable(AllDeleted,
+ AllDeleted &&)))]; }
+ { int arr[F((__is_trivially_assignable(ExtDefaulted,
+ const ExtDefaulted &)))]; }
+ { int arr[F((__is_trivially_assignable(ExtDefaulted,
+ ExtDefaulted &&)))]; }
+
+ { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
+ HasDefaultTrivialCopyAssign&)))]; }
+ { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
+ const HasDefaultTrivialCopyAssign&)))]; }
+ { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
+ TrivialMoveButNotCopy)))]; }
+ { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
+ TrivialMoveButNotCopy&&)))]; }
+}
+
+// Instantiation of __is_trivially_constructible
+template<typename T, typename ...Args>
+struct is_trivially_constructible {
+ static const bool value = __is_trivially_constructible(T, Args...);
+};
+
+void is_trivially_constructible_test() {
+ { int arr[T((is_trivially_constructible<int>::value))]; }
+ { int arr[T((is_trivially_constructible<int, int>::value))]; }
+ { int arr[T((is_trivially_constructible<int, float>::value))]; }
+ { int arr[T((is_trivially_constructible<int, int&>::value))]; }
+ { int arr[T((is_trivially_constructible<int, const int&>::value))]; }
+ { int arr[T((is_trivially_constructible<int, int>::value))]; }
+ { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign>::value))]; }
+ { int arr[T((is_trivially_constructible<HasCopyAssign, const HasCopyAssign&>::value))]; }
+ { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign&&>::value))]; }
+ { int arr[T((is_trivially_constructible<HasCopyAssign>::value))]; }
+ { int arr[T((is_trivially_constructible<NonTrivialDefault,
+ const NonTrivialDefault&>::value))]; }
+ { int arr[T((is_trivially_constructible<NonTrivialDefault,
+ NonTrivialDefault&&>::value))]; }
+
+ { int arr[F((is_trivially_constructible<int, int*>::value))]; }
+ { int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; }
+ { int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, int&>::value))]; }
}
void array_rank() {
diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp
index 7db1970..b53bcd2 100644
--- a/test/SemaCXX/typedef-redecl.cpp
+++ b/test/SemaCXX/typedef-redecl.cpp
@@ -54,3 +54,42 @@ namespace PR7462 {
typedef int operator! (A); // expected-error{{typedef name must be an identifier}}
int i = !A(); // expected-error{{invalid argument type}}
}
+
+template<typename T>
+typedef T f(T t) { return t; } // expected-error {{function definition declared 'typedef'}}
+int k = f(0);
+int k2 = k;
+
+namespace PR11630 {
+ template <class T>
+ struct S
+ {
+ static const unsigned C = 1;
+ static void f()
+ {
+ typedef int q[C == 1 ? 1 : -1]; // expected-note{{previous definition is here}}
+ typedef int q[C >= 1 ? 2 : -2]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}}
+ typedef int n[C == 1 ? 1 : -1];
+ typedef int n[C >= 1 ? 1 : -1];
+ }
+ };
+
+ template <int T>
+ struct S2
+ {
+ static void f()
+ {
+ typedef int q[1]; // expected-note{{previous definition is here}}
+ typedef int q[T]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}}
+ }
+ };
+
+ void f() {
+ S<int> a;
+ a.f(); // expected-note{{in instantiation of member function 'PR11630::S<int>::f' requested here}}
+ S2<1> b;
+ b.f();
+ S2<2> b2;
+ b2.f(); // expected-note{{in instantiation of member function 'PR11630::S2<2>::f' requested here}}
+ }
+}
diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp
index 8db7db5..d3a2a28 100644
--- a/test/SemaCXX/typeid.cpp
+++ b/test/SemaCXX/typeid.cpp
@@ -2,7 +2,7 @@
void f()
{
- (void)typeid(int); // expected-error {{error: you need to include <typeinfo> before using the 'typeid' operator}}
+ (void)typeid(int); // expected-error {{you need to include <typeinfo> before using the 'typeid' operator}}
}
namespace std {
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index fa32c57..b1e8d91 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
struct errc {
int v_;
@@ -29,3 +29,164 @@ public:
inline error_condition make_error_condition(errc _e) {
return error_condition(static_cast<int>(_e));
}
+
+
+// Prior to the introduction of a callback object to further filter possible
+// typo corrections, this example would not trigger a suggestion as "base_type"
+// is a closer match to "basetype" than is "BaseType" but "base_type" does not
+// refer to a base class or non-static data member.
+struct BaseType { };
+struct Derived : public BaseType { // expected-note {{base class 'BaseType' specified here}}
+ static int base_type; // expected-note {{'base_type' declared here}}
+ Derived() : basetype() {} // expected-error{{initializer 'basetype' does not name a non-static data member or base class; did you mean the base class 'BaseType'?}}
+};
+
+// Test the improvement from passing a callback object to CorrectTypo in
+// the helper function LookupMemberExprInRecord.
+int get_type(struct Derived *st) {
+ return st->Base_Type; // expected-error{{no member named 'Base_Type' in 'Derived'; did you mean 'base_type'?}}
+}
+
+// In this example, somename should not be corrected to the cached correction
+// "some_name" since "some_name" is a class and a namespace name is needed.
+class some_name {}; // expected-note {{'some_name' declared here}}
+somename Foo; // expected-error {{unknown type name 'somename'; did you mean 'some_name'?}}
+namespace SomeName {} // expected-note {{namespace 'SomeName' defined here}}
+using namespace somename; // expected-error {{no namespace named 'somename'; did you mean 'SomeName'?}}
+
+
+// Without the callback object, CorrectTypo would choose "field1" as the
+// correction for "fielda" as it is closer than "FieldA", but that correction
+// would be later discarded by the caller and no suggestion would be given.
+struct st {
+ struct {
+ int field1;
+ };
+ double FieldA; // expected-note{{'FieldA' declared here}}
+};
+st var = { .fielda = 0.0 }; // expected-error{{field designator 'fielda' does not refer to any field in type 'st'; did you mean 'FieldA'?}}
+
+// Test the improvement from passing a callback object to CorrectTypo in
+// Sema::BuildCXXNestedNameSpecifier. And also for the improvement by doing
+// so in Sema::getTypeName.
+typedef char* another_str; // expected-note{{'another_str' declared here}}
+namespace AnotherStd { // expected-note{{'AnotherStd' declared here}}
+ class string {};
+}
+another_std::string str; // expected-error{{use of undeclared identifier 'another_std'; did you mean 'AnotherStd'?}}
+another_str *cstr = new AnotherStr; // expected-error{{unknown type name 'AnotherStr'; did you mean 'another_str'?}}
+
+// Test the improvement from passing a callback object to CorrectTypo in
+// Sema::ActOnSizeofParameterPackExpr.
+char* TireNames;
+template<typename ...TypeNames> struct count { // expected-note{{parameter pack 'TypeNames' declared here}}
+ static const unsigned value = sizeof...(TyreNames); // expected-error{{'TyreNames' does not refer to the name of a parameter pack; did you mean 'TypeNames'?}}
+};
+
+// Test the typo-correction callback in Sema::DiagnoseUnknownTypeName.
+namespace unknown_type_test {
+ class StreamOut {}; // expected-note 2 {{'StreamOut' declared here}}
+ long stream_count; // expected-note 2 {{'stream_count' declared here}}
+};
+unknown_type_test::stream_out out; // expected-error{{no type named 'stream_out' in namespace 'unknown_type_test'; did you mean 'StreamOut'?}}
+
+// Demonstrate a case where using only the cached value returns the wrong thing
+// when the cached value was the result of a previous callback object that only
+// accepts a subset of the current callback object.
+namespace {
+using namespace unknown_type_test;
+void bar(long i);
+void before_caching_classname() {
+ bar((stream_out)); // expected-error{{use of undeclared identifier 'stream_out'; did you mean 'stream_count'?}}
+}
+stream_out out; // expected-error{{unknown type name 'stream_out'; did you mean 'StreamOut'?}}
+void after_caching_classname() {
+ bar((stream_out)); // expected-error{{use of undeclared identifier 'stream_out'; did you mean 'stream_count'?}}
+}
+}
+
+// Test the typo-correction callback in Sema::DiagnoseInvalidRedeclaration.
+struct BaseDecl {
+ void add_in(int i);
+};
+struct TestRedecl : public BaseDecl {
+ void add_it(int i); // expected-note{{'add_it' declared here}}
+};
+void TestRedecl::add_in(int i) {} // expected-error{{out-of-line definition of 'add_in' does not match any declaration in 'TestRedecl'; did you mean 'add_it'?}}
+
+// Test the improved typo correction for the Parser::ParseCastExpr =>
+// Sema::ActOnIdExpression => Sema::DiagnoseEmptyLookup call path.
+class SomeNetMessage;
+class Message {};
+void foo(Message&);
+void foo(SomeNetMessage&);
+void doit(void *data) {
+ Message somenetmsg; // expected-note{{'somenetmsg' declared here}}
+ foo(somenetmessage); // expected-error{{use of undeclared identifier 'somenetmessage'; did you mean 'somenetmsg'?}}
+ foo((somenetmessage)data); // expected-error{{use of undeclared identifier 'somenetmessage'; did you mean 'SomeNetMessage'?}}
+}
+
+// Test the typo-correction callback in BuildRecoveryCallExpr.
+// Solves the main issue in PR 9320 of suggesting corrections that take the
+// wrong number of arguments.
+void revoke(const char*); // expected-note 2{{'revoke' declared here}}
+void Test() {
+ Invoke(); // expected-error{{use of undeclared identifier 'Invoke'}}
+ Invoke("foo"); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'revoke'?}}
+ Invoke("foo", "bar"); // expected-error{{use of undeclared identifier 'Invoke'}}
+}
+void Test2(void (*invoke)(const char *, int)) { // expected-note{{'invoke' declared here}}
+ Invoke(); // expected-error{{use of undeclared identifier 'Invoke'}}
+ Invoke("foo"); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'revoke'?}}
+ Invoke("foo", 7); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'invoke'?}}
+ Invoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Invoke'}}
+}
+
+void provoke(const char *x, bool y=false) {} // expected-note 2{{'provoke' declared here}}
+void Test3() {
+ Provoke(); // expected-error{{use of undeclared identifier 'Provoke'}}
+ Provoke("foo"); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}}
+ Provoke("foo", true); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}}
+ Provoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Provoke'}}
+}
+
+// PR 11737 - Don't try to typo-correct the implicit 'begin' and 'end' in a
+// C++11 for-range statement.
+struct R {};
+bool begun(R);
+void RangeTest() {
+ for (auto b : R()) {} // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type}}
+}
+
+// PR 12019 - Avoid infinite mutual recursion in DiagnoseInvalidRedeclaration
+// by not trying to typo-correct a method redeclaration to declarations not
+// in the current record.
+class Parent {
+ void set_types(int index, int value);
+ void add_types(int value);
+};
+class Child: public Parent {};
+void Child::add_types(int value) {} // expected-error{{out-of-line definition of 'add_types' does not match any declaration in 'Child'}}
+
+// Fix the callback based filtering of typo corrections within
+// Sema::ActOnIdExpression by Parser::ParseCastExpression to allow type names as
+// potential corrections for template arguments.
+namespace clash {
+class ConstructExpr {}; // expected-note{{'clash::ConstructExpr' declared here}}
+}
+class ClashTool {
+ bool HaveConstructExpr();
+ template <class T> T* getExprAs();
+
+ void test() {
+ ConstructExpr *expr = // expected-error{{unknown type name 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}}
+ getExprAs<ConstructExpr>(); // expected-error{{use of undeclared identifier 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}}
+ }
+};
+
+namespace test1 {
+ struct S {
+ struct Foobar *f; // expected-note{{'Foobar' declared here}}
+ };
+ test1::FooBar *b; // expected-error{{no type named 'FooBar' in namespace 'test1'; did you mean 'Foobar'?}}
+}
diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp
index e926f18..1541720 100644
--- a/test/SemaCXX/undefined-internal.cpp
+++ b/test/SemaCXX/undefined-internal.cpp
@@ -122,3 +122,62 @@ namespace PR9323 {
f(Uncopyable()); // expected-warning {{C++98 requires an accessible copy constructor}}
};
}
+
+
+namespace std { class type_info; };
+namespace cxx11_odr_rules {
+ // Note: the way this test is written isn't really ideal, but there really
+ // isn't any other way to check that the odr-used logic for constants
+ // is working without working implicit capture in lambda-expressions.
+ // (The more accurate used-but-not-defined warning is the only other visible
+ // effect of accurate odr-used computation.)
+ //
+ // Note that the warning in question can trigger in cases some people would
+ // consider false positives; hopefully that happens rarely in practice.
+ //
+ // FIXME: Suppressing this test while I figure out how to fix a bug in the
+ // odr-use marking code.
+
+ namespace {
+ struct A {
+ static const int unused = 10;
+ static const int used1 = 20; // xpected-warning {{internal linkage}}
+ static const int used2 = 20; // xpected-warning {{internal linkage}}
+ virtual ~A() {}
+ };
+ }
+
+ void a(int,int);
+ A& p(const int&) { static A a; return a; }
+
+ // Check handling of default arguments
+ void b(int = A::unused);
+
+ void tests() {
+ // Basic test
+ a(A::unused, A::unused);
+
+ // Check that nesting an unevaluated or constant-evaluated context does
+ // the right thing.
+ a(A::unused, sizeof(int[10]));
+
+ // Check that the checks work with unevaluated contexts
+ (void)sizeof(p(A::used1));
+ (void)typeid(p(A::used1)); // xpected-note {{used here}}
+
+ // Misc other testing
+ a(A::unused, 1 ? A::used2 : A::used2); // xpected-note {{used here}}
+ b();
+ }
+}
+
+
+namespace OverloadUse {
+ namespace {
+ void f();
+ void f(int); // expected-warning {{function 'OverloadUse::<anonymous namespace>::f' has internal linkage but is not defined}}
+ }
+ template<void x()> void t(int*) { x(); }
+ template<void x(int)> void t(long*) { x(10); } // expected-note {{used here}}
+ void g() { long a; t<f>(&a); }
+}
diff --git a/test/SemaCXX/underlying_type.cpp b/test/SemaCXX/underlying_type.cpp
index dcfaab3..7bca06b 100644
--- a/test/SemaCXX/underlying_type.cpp
+++ b/test/SemaCXX/underlying_type.cpp
@@ -35,3 +35,9 @@ static_assert(is_same_type<underlying_type<f>::type, char>::value,
"f has the wrong underlying type in the template");
underlying_type<int>::type e; // expected-note {{requested here}}
+
+using uint = unsigned;
+enum class foo : uint { bar };
+
+static_assert(is_same_type<underlying_type<foo>::type, unsigned>::value,
+ "foo has the wrong underlying type");
diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp
index 358a572..eb6428d 100644
--- a/test/SemaCXX/uninit-variables.cpp
+++ b/test/SemaCXX/uninit-variables.cpp
@@ -27,7 +27,7 @@ void unevaluated_tests() {
struct A { virtual ~A() {} };
void polymorphic_test() {
A *a; // expected-note{{initialize the variable 'a' to silence this warning}}
- (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here }}
+ (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here}}
}
// Handle cases where the CFG may constant fold some branches, thus
diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp
index c25bd20..7879e7c 100644
--- a/test/SemaCXX/uninitialized.cpp
+++ b/test/SemaCXX/uninitialized.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -std=c++11 -verify %s
int foo(int x);
int bar(int* x);
@@ -33,6 +33,7 @@ class A {
int num;
static int count;
int get() const { return num; }
+ int get2() { return num; }
void set(int x) { num = x; }
static int zero() { return 0; }
@@ -41,6 +42,7 @@ class A {
A(int x) {}
A(int *x) {}
A(A *a) {}
+ ~A();
};
A getA() { return A(); }
@@ -66,6 +68,7 @@ void setupA() {
A a14 = A(a14); // expected-warning {{variable 'a14' is uninitialized when used within its own initialization}}
A a15 = getA(a15.num); // expected-warning {{variable 'a15' is uninitialized when used within its own initialization}}
A a16(&a16.num); // expected-warning {{variable 'a16' is uninitialized when used within its own initialization}}
+ A a17(a17.get2()); // expected-warning {{variable 'a17' is uninitialized when used within its own initialization}}
}
struct B {
@@ -117,3 +120,50 @@ struct S {
};
struct C { char a[100], *e; } car = { .e = car.a };
+
+// <rdar://problem/10398199>
+namespace rdar10398199 {
+ class FooBase { protected: ~FooBase() {} };
+ class Foo : public FooBase {
+ public:
+ operator int&() const;
+ };
+ void stuff();
+ template <typename T> class FooImpl : public Foo {
+ T val;
+ public:
+ FooImpl(const T &x) : val(x) {}
+ ~FooImpl() { stuff(); }
+ };
+
+ template <typename T> FooImpl<T> makeFoo(const T& x) {
+ return FooImpl<T>(x);
+ }
+
+ void test() {
+ const Foo &x = makeFoo(42);
+ const int&y = makeFoo(42u);
+ (void)x;
+ (void)y;
+ };
+}
+
+// PR 12325 - this was a false uninitialized value warning due to
+// a broken CFG.
+int pr12325(int params) {
+ int x = ({
+ while (false)
+ ;
+ int _v = params;
+ if (false)
+ ;
+ _v; // no-warning
+ });
+ return x;
+}
+
+// Test lambda expressions with -Wuninitialized
+int test_lambda() {
+ auto f1 = [] (int x, int y) { int z; return x + y + z; }; // expected-warning {{C++11 requires lambda with omitted result type to consist of a single return statement}} expected-warning{{variable 'z' is uninitialized when used here}} expected-note {{initialize the variable 'z' to silence this warning}}
+ return f1(1, 2);
+}
diff --git a/test/SemaCXX/unknown-anytype-blocks.cpp b/test/SemaCXX/unknown-anytype-blocks.cpp
new file mode 100644
index 0000000..86ce7e1
--- /dev/null
+++ b/test/SemaCXX/unknown-anytype-blocks.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -funknown-anytype -fblocks -fsyntax-only -verify -std=c++11 %s
+
+namespace test1 {
+ __unknown_anytype (^foo)();
+ __unknown_anytype (^bar)();
+ int test() {
+ auto ret1 = (int)foo();
+ auto ret2 = bar(); // expected-error {{'bar' has unknown return type; cast the call to its declared return type}}
+ return ret1;
+ }
+}
diff --git a/test/SemaCXX/unknown-anytype.cpp b/test/SemaCXX/unknown-anytype.cpp
index ba52122..a07ec83 100644
--- a/test/SemaCXX/unknown-anytype.cpp
+++ b/test/SemaCXX/unknown-anytype.cpp
@@ -14,9 +14,9 @@ namespace test1 {
// making sure that these locations check for placeholder types
// properly.
- int x = foo; // expected-error {{cannot initialize}}
+ int x = foo; // expected-error {{'foo' has unknown type}}
int y = 0 + foo; // expected-error {{'foo' has unknown type}}
- return foo; // expected-error {{cannot initialize}}
+ return foo; // expected-error {{'foo' has unknown type}}
}
}
diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp
index 19be03a..4e3acbb 100644
--- a/test/SemaCXX/value-initialization.cpp
+++ b/test/SemaCXX/value-initialization.cpp
@@ -1,11 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
-struct A { //expected-note {{marked deleted here}} \
- // expected-warning {{does not declare any constructor to initialize}}
- const int i; // expected-note{{const member 'i' will never be initialized}}
+struct A { // expected-warning {{does not declare any constructor to initialize}}
+ const int i; // expected-note{{const member 'i' will never be initialized}} expected-note {{implicitly deleted}}
virtual void f() { }
};
int main () {
- (void)A(); // expected-error {{call to deleted constructor}}
+ (void)A(); // expected-error {{call to implicitly-deleted default constructor}}
}
diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index 42c27fb..86b560e 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/test/SemaCXX/vararg-non-pod.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wnon-pod-varargs
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
extern char version[];
@@ -118,3 +118,8 @@ void t8(int n, ...) {
(void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
__builtin_va_end(list);
}
+
+int t9(int n) {
+ // Make sure the error works in potentially-evaluated sizeof
+ return (int)sizeof(*(Helper(Foo()), (int (*)[n])0)); // expected-warning{{cannot pass object of non-POD type}}
+}
diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp
index 4d3d939..82245ac 100644
--- a/test/SemaCXX/vector.cpp
+++ b/test/SemaCXX/vector.cpp
@@ -218,3 +218,52 @@ void test(fltx2 fltx2_val, fltx4 fltx4_val, dblx2 dblx2_val, dblx4 dblx4_val) {
// Scalar-to-vector conversions.
accept_fltx2(1.0); // expected-error{{no matching function for call to 'accept_fltx2'}}
}
+
+typedef int intx4 __attribute__((__vector_size__(16)));
+typedef int inte4 __attribute__((__ext_vector_type__(4)));
+typedef int flte4 __attribute__((__ext_vector_type__(4)));
+
+void test_mixed_vector_types(fltx4 f, intx4 n, flte4 g, flte4 m) {
+ (void)(f == g);
+ (void)(g != f);
+ (void)(f <= g);
+ (void)(g >= f);
+ (void)(f < g);
+ (void)(g > f);
+
+ (void)(+g);
+ (void)(-g);
+
+ (void)(f + g);
+ (void)(f - g);
+ (void)(f * g);
+ (void)(f / g);
+ (void)(f = g);
+ (void)(f += g);
+ (void)(f -= g);
+ (void)(f *= g);
+ (void)(f /= g);
+
+
+ (void)(n == m);
+ (void)(m != n);
+ (void)(n <= m);
+ (void)(m >= n);
+ (void)(n < m);
+ (void)(m > n);
+
+ (void)(+m);
+ (void)(-m);
+ (void)(~m);
+
+ (void)(n + m);
+ (void)(n - m);
+ (void)(n * m);
+ (void)(n / m);
+ (void)(n % m);
+ (void)(n = m);
+ (void)(n += m);
+ (void)(n -= m);
+ (void)(n *= m);
+ (void)(n /= m);
+}
diff --git a/test/SemaCXX/vla.cpp b/test/SemaCXX/vla.cpp
new file mode 100644
index 0000000..d63b633
--- /dev/null
+++ b/test/SemaCXX/vla.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -verify %s
+
+// PR11925
+int n;
+int (&f())[n]; // expected-error {{function declaration cannot have variably modified type}}
diff --git a/test/SemaCXX/warn-bool-conversion.cpp b/test/SemaCXX/warn-bool-conversion.cpp
index 595c749..b3d136e 100644
--- a/test/SemaCXX/warn-bool-conversion.cpp
+++ b/test/SemaCXX/warn-bool-conversion.cpp
@@ -1,18 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-int* j = false; // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}}
+int* j = false; // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
-void foo(int* i, int *j=(false)) // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}}
+void foo(int* i, int *j=(false)) // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
{
- foo(false); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}}
+ foo(false); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
foo((int*)false); // no-warning: explicit cast
foo(0); // no-warning: not a bool, even though its convertible to bool
- foo(false == true); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}}
- foo((42 + 24) < 32); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}}
+ foo(false == true); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
+ foo((42 + 24) < 32); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
const bool kFlag = false;
- foo(kFlag); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}}
+ foo(kFlag); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
}
char f(struct Undefined*);
diff --git a/test/SemaCXX/warn-empty-body.cpp b/test/SemaCXX/warn-empty-body.cpp
new file mode 100644
index 0000000..d643ced
--- /dev/null
+++ b/test/SemaCXX/warn-empty-body.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+void a(int i);
+int b();
+int c();
+
+void test1(int x, int y) {
+ while(true) {
+ if (x); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+
+ int i;
+ // PR11329
+ for (i = 0; i < x; i++); { // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+ b();
+ }
+
+ for (i = 0; i < x; i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ {
+ a(i);
+ }
+
+ for (i = 0;
+ i < x;
+ i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ {
+ a(i);
+ }
+
+ int arr[3] = { 1, 2, 3 };
+ for (int j : arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ for (int j :
+ arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ while (b() == 0); { // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+ }
+
+ while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ {
+ a(i);
+ }
+
+ while (b() == 0 ||
+ c() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ {
+ a(i);
+ }
+
+ do; // expected-note{{to match this 'do'}}
+ b(); // expected-error{{expected 'while' in do/while loop}}
+ while (b()); // no-warning
+ c();
+
+ do; // expected-note{{to match this 'do'}}
+ b(); // expected-error{{expected 'while' in do/while loop}}
+ while (b()); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ c();
+
+ switch(x) // no-warning
+ {
+ switch(y); // expected-warning{{switch statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ {
+ case 0:
+ a(10);
+ break;
+ default:
+ a(20);
+ break;
+ }
+ }
+ }
+}
+
+/// There should be no warning when null statement is placed on its own line.
+void test2(int x, int y) {
+ if (x) // no-warning
+ ; // no-warning
+
+ int i;
+ for (i = 0; i < x; i++) // no-warning
+ ; // no-warning
+
+ for (i = 0;
+ i < x;
+ i++) // no-warning
+ ; // no-warning
+
+ int arr[3] = { 1, 2, 3 };
+ for (int j : arr) // no-warning
+ ; // no-warning
+
+ while (b() == 0) // no-warning
+ ; // no-warning
+
+ while (b() == 0 ||
+ c() == 0) // no-warning
+ ; // no-warning
+
+ switch(x)
+ {
+ switch(y) // no-warning
+ ; // no-warning
+ }
+
+ // Last `for' or `while' statement in compound statement shouldn't warn.
+ while(b() == 0); // no-warning
+}
+
+/// There should be no warning for a null statement resulting from an empty macro.
+#define EMPTY(a)
+void test3(int x, int y) {
+ if (x) EMPTY(x); // no-warning
+
+ int i;
+ for (i = 0; i < x; i++) EMPTY(i); // no-warning
+
+ for (i = 0;
+ i < x;
+ i++) EMPTY(i); // no-warning
+
+ int arr[3] = { 1, 2, 3 };
+ for (int j : arr) EMPTY(j); // no-warning
+
+ for (int j :
+ arr) EMPTY(j); // no-warning
+
+ while (b() == 0) EMPTY(i); // no-warning
+
+ while (b() == 0 ||
+ c() == 0) EMPTY(i); // no-warning
+
+ switch (x) {
+ switch (y)
+ EMPTY(i); // no-warning
+ }
+}
+
+void test4(int x)
+{
+ // Idiom used in some metaprogramming constructs.
+ switch (x) default:; // no-warning
+
+ // Frequent idiom used in macros.
+ do {} while (false); // no-warning
+}
+
+/// There should be no warning for a common for/while idiom when it is obvious
+/// from indentation that next statement wasn't meant to be a body.
+void test5(int x, int y) {
+ int i;
+ for (i = 0; i < x; i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ for (i = 0; i < x; i++); // no-warning
+ a(i);
+
+ for (i = 0;
+ i < x;
+ i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ for (i = 0;
+ i < x;
+ i++); // no-warning
+ a(i);
+
+ while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ while (b() == 0); // no-warning
+ a(i);
+
+ while (b() == 0 ||
+ c() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(i);
+
+ while (b() == 0 ||
+ c() == 0); // no-warning
+ a(i);
+}
+
+/// There should be no warning for a statement with a non-null body.
+void test6(int x, int y) {
+ if (x) {} // no-warning
+
+ if (x)
+ a(x); // no-warning
+
+ int i;
+ for (i = 0; i < x; i++) // no-warning
+ a(i); // no-warning
+
+ for (i = 0; i < x; i++) { // no-warning
+ a(i); // no-warning
+ }
+
+ for (i = 0;
+ i < x;
+ i++) // no-warning
+ a(i); // no-warning
+
+ int arr[3] = { 1, 2, 3 };
+ for (int j : arr) // no-warning
+ a(j);
+
+ for (int j : arr) {} // no-warning
+
+ while (b() == 0) // no-warning
+ a(i); // no-warning
+
+ while (b() == 0) {} // no-warning
+
+ switch(x) // no-warning
+ {
+ switch(y) // no-warning
+ {
+ case 0:
+ a(10);
+ break;
+ default:
+ a(20);
+ break;
+ }
+ }
+}
+
+void test_errors(int x) {
+ if (1)
+ aa; // expected-error{{use of undeclared identifier}}
+ // no empty body warning.
+
+ int i;
+ for (i = 0; i < x; i++)
+ bb; // expected-error{{use of undeclared identifier}}
+
+ int arr[3] = { 1, 2, 3 };
+ for (int j : arr)
+ cc; // expected-error{{use of undeclared identifier}}
+
+ while (b() == 0)
+ dd; // expected-error{{use of undeclared identifier}}
+}
+
+// Warnings for statements in templates shouldn't be duplicated for all
+// instantiations.
+template <typename T>
+void test_template(int x) {
+ if (x); // expected-warning{{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+
+ if (x)
+ EMPTY(x); // no-warning
+
+ int arr[3] = { 1, 2, 3 };
+ for (int j : arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+
+ while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+ a(x);
+}
+
+void test_template_inst(int x) {
+ test_template<int>(x);
+ test_template<double>(x);
+}
+
diff --git a/test/SemaCXX/warn-everthing.cpp b/test/SemaCXX/warn-everthing.cpp
new file mode 100644
index 0000000..144a8f9
--- /dev/null
+++ b/test/SemaCXX/warn-everthing.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang -Weverything -fsyntax-only %s -verify
+
+// This previously crashed due to a bug in the CFG. Exercising all
+// warnings helps check CFG construction.
+class PR12271 {
+public:
+ PR12271();
+ ~PR12271();
+};
+
+void testPR12271() {
+ PR12271 a[1][1];
+} \ No newline at end of file
diff --git a/test/SemaCXX/warn-func-as-bool.cpp b/test/SemaCXX/warn-func-as-bool.cpp
new file mode 100644
index 0000000..b5df744
--- /dev/null
+++ b/test/SemaCXX/warn-func-as-bool.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -x c++ -verify -fsyntax-only %s
+
+void f1();
+
+struct S {
+ static void f2();
+};
+
+extern void f3() __attribute__((weak_import));
+
+struct S2 {
+ static void f4() __attribute__((weak_import));
+};
+
+bool f5();
+bool f6(int);
+
+void bar() {
+ bool b;
+
+ b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}}
+ if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}}
+ b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}}
+ if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}}
+ b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}} \
+ expected-note {{suffix with parentheses to turn this into a function call}}
+ b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \
+ expected-note {{prefix with the address-of operator to silence this warning}}
+
+ // implicit casts of weakly imported symbols are ok:
+ b = f3;
+ if (f3) {}
+ b = S2::f4;
+ if (S2::f4) {}
+}
diff --git a/test/SemaCXX/warn-large-by-value-copy.cpp b/test/SemaCXX/warn-large-by-value-copy.cpp
index 39dbd76..3e419ec 100644
--- a/test/SemaCXX/warn-large-by-value-copy.cpp
+++ b/test/SemaCXX/warn-large-by-value-copy.cpp
@@ -40,3 +40,8 @@ void g() {
}
}
+
+template<typename T> class DependentPOD {
+ enum b { x };
+ b foo() { return x; }
+};
diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp
index a018223..e0d28da 100644
--- a/test/SemaCXX/warn-memset-bad-sizeof.cpp
+++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp
@@ -104,6 +104,14 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
// Copy to raw buffer shouldn't warn either
memcpy(&foo, &arr, sizeof(Foo));
memcpy(&arr, &foo, sizeof(Foo));
+
+ // Shouldn't warn, and shouldn't crash either.
+ memset(({
+ if (0) {}
+ while (0) {}
+ for (;;) {}
+ &s;
+ }), 0, sizeof(s));
}
namespace ns {
@@ -132,8 +140,6 @@ void strcpy_and_friends() {
strncpy(buff, BAR, sizeof(BAR)); // \
// expected-warning {{argument to 'sizeof' in 'strncpy' call is the same expression as the source}}
- strncat(buff, BAR, sizeof(BAR)); // \
- // expected-warning {{argument to 'sizeof' in 'strncat' call is the same expression as the source}}
strndup(FOO, sizeof(FOO)); // \
// expected-warning {{argument to 'sizeof' in 'strndup' call is the same expression as the source}}
}
diff --git a/test/SemaCXX/warn-new-overaligned-2.cpp b/test/SemaCXX/warn-new-overaligned-2.cpp
new file mode 100644
index 0000000..5505009
--- /dev/null
+++ b/test/SemaCXX/warn-new-overaligned-2.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned -verify %s
+
+// This test verifies that we don't warn when the global operator new is
+// overridden. That's why we can't merge this with the other test file.
+
+void* operator new(unsigned long);
+void* operator new[](unsigned long);
+
+struct Test {
+ template <typename T>
+ struct SeparateCacheLines {
+ T data;
+ } __attribute__((aligned(256)));
+
+ SeparateCacheLines<int> high_contention_data[10];
+};
+
+void helper() {
+ Test t;
+ new Test;
+ new Test[10];
+}
diff --git a/test/SemaCXX/warn-new-overaligned-3.cpp b/test/SemaCXX/warn-new-overaligned-3.cpp
new file mode 100644
index 0000000..c9a57fb
--- /dev/null
+++ b/test/SemaCXX/warn-new-overaligned-3.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned %s -isystem %S/Inputs -verify
+
+// This test ensures that we still get the warning even if we #include <new>
+// where the header here simulates <new>.
+#include <warn-new-overaligned-3.h>
+
+namespace test1 {
+struct Test {
+ template <typename T>
+ struct SeparateCacheLines {
+ T data;
+ } __attribute__((aligned(256)));
+
+ SeparateCacheLines<int> high_contention_data[10];
+};
+
+void helper() {
+ Test t;
+ new Test; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+ new Test[10]; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+}
+}
+
+namespace test2 {
+struct helper { int i __attribute__((aligned(256))); };
+
+struct Placement {
+ Placement() {
+ new (d) helper();
+ }
+ helper *d;
+};
+}
diff --git a/test/SemaCXX/warn-new-overaligned.cpp b/test/SemaCXX/warn-new-overaligned.cpp
new file mode 100644
index 0000000..42a4e35
--- /dev/null
+++ b/test/SemaCXX/warn-new-overaligned.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned -verify %s
+
+namespace test1 {
+struct Test {
+ template <typename T>
+ struct SeparateCacheLines {
+ T data;
+ } __attribute__((aligned(256)));
+
+ SeparateCacheLines<int> high_contention_data[10];
+};
+
+void helper() {
+ Test t;
+ new Test; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+ new Test[10]; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+}
+}
+
+namespace test2 {
+class Test {
+ typedef int __attribute__((aligned(256))) aligned_int;
+ aligned_int high_contention_data[10];
+};
+
+void helper() {
+ Test t;
+ new Test; // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+ new Test[10]; // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+}
+}
+
+namespace test3 {
+struct Test {
+ template <typename T>
+ struct SeparateCacheLines {
+ T data;
+ } __attribute__((aligned(256)));
+
+ void* operator new(unsigned long) {
+ return 0;
+ }
+
+ SeparateCacheLines<int> high_contention_data[10];
+};
+
+void helper() {
+ Test t;
+ new Test;
+ new Test[10]; // expected-warning {{type 'test3::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+}
+}
+
+namespace test4 {
+struct Test {
+ template <typename T>
+ struct SeparateCacheLines {
+ T data;
+ } __attribute__((aligned(256)));
+
+ void* operator new[](unsigned long) {
+ return 0;
+ }
+
+ SeparateCacheLines<int> high_contention_data[10];
+};
+
+void helper() {
+ Test t;
+ new Test; // expected-warning {{type 'test4::Test' requires 256 bytes of alignment and the default allocator only guarantees}}
+ new Test[10];
+}
+}
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 90a8933..566e5c1 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -36,6 +36,18 @@ class __attribute__((lockable)) Mutex {
void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
};
+class __attribute__((scoped_lockable)) MutexLock {
+ public:
+ MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
+ ~MutexLock() __attribute__((unlock_function));
+};
+
+class __attribute__((scoped_lockable)) ReaderMutexLock {
+ public:
+ ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
+ ~ReaderMutexLock() __attribute__((unlock_function));
+};
+
Mutex sls_mu;
@@ -160,30 +172,29 @@ void sls_fun_bad_2() {
}
void sls_fun_bad_3() {
- sls_mu.Lock(); // \
- // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_3'}}
-}
+ sls_mu.Lock(); // expected-note {{mutex acquired here}}
+} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
void sls_fun_bad_4() {
if (getBool())
sls_mu.Lock(); // \
- // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
+ expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \
+ expected-note{{mutex acquired here}}
+
else
sls_mu2.Lock(); // \
- // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}}
-}
+ expected-note{{mutex acquired here}}
+} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
void sls_fun_bad_5() {
- sls_mu.Lock(); // \
- // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
+ sls_mu.Lock(); // expected-note {{mutex acquired here}}
if (getBool())
sls_mu.Unlock();
-}
+} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
void sls_fun_bad_6() {
if (getBool()) {
- sls_mu.Lock(); // \
- // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
+ sls_mu.Lock(); // expected-note {{mutex acquired here}}
} else {
if (getBool()) {
getBool(); // EMPTY
@@ -192,29 +203,30 @@ void sls_fun_bad_6() {
}
}
sls_mu.Unlock(); // \
- // expected-warning{{unlocking 'sls_mu' that was not locked}}
+ expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
+ expected-warning{{unlocking 'sls_mu' that was not locked}}
}
void sls_fun_bad_7() {
- sls_mu.Lock(); // \
- // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+ sls_mu.Lock();
while (getBool()) {
sls_mu.Unlock();
if (getBool()) {
if (getBool()) {
- continue;
+ continue; // \
+ expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
}
}
- sls_mu.Lock(); // \
- // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
+ sls_mu.Lock(); // expected-note {{mutex acquired here}}
}
sls_mu.Unlock();
}
void sls_fun_bad_8() {
- sls_mu.Lock(); // \
- // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
- do {
+ sls_mu.Lock(); // expected-note{{mutex acquired here}}
+
+ // FIXME: TERRIBLE SOURCE LOCATION!
+ do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
sls_mu.Unlock();
} while (getBool());
}
@@ -222,29 +234,42 @@ void sls_fun_bad_8() {
void sls_fun_bad_9() {
do {
sls_mu.Lock(); // \
- // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+ // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
+ // expected-note{{mutex acquired here}}
} while (getBool());
sls_mu.Unlock();
}
void sls_fun_bad_10() {
- sls_mu.Lock(); // \
- // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_10'}} \
- // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+ sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
while(getBool()) {
- sls_mu.Unlock();
+ sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
}
-}
+} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
void sls_fun_bad_11() {
- while (getBool()) {
- sls_mu.Lock(); // \
- // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+ while (getBool()) { // \
+ expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+ sls_mu.Lock(); // expected-note {{mutex acquired here}}
}
sls_mu.Unlock(); // \
// expected-warning{{unlocking 'sls_mu' that was not locked}}
}
+void sls_fun_bad_12() {
+ sls_mu.Lock(); // expected-note {{mutex acquired here}}
+ while (getBool()) {
+ sls_mu.Unlock();
+ if (getBool()) {
+ if (getBool()) {
+ break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
+ }
+ }
+ sls_mu.Lock();
+ }
+ sls_mu.Unlock();
+}
+
//-----------------------------------------//
// Handling lock expressions in attribute args
// -------------------------------------------//
@@ -277,9 +302,8 @@ void aa_fun_bad_2() {
}
void aa_fun_bad_3() {
- glock.globalLock(); // \
- // expected-warning{{mutex 'aa_mu' is still locked at the end of function 'aa_fun_bad_3'}}
-}
+ glock.globalLock(); // expected-note{{mutex acquired here}}
+} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
//--------------------------------------------------//
// Regression tests for unusual method names
@@ -289,23 +313,20 @@ Mutex wmu;
// Test diagnostics for other method names.
class WeirdMethods {
+ // FIXME: can't currently check inside constructors and destructors.
WeirdMethods() {
- wmu.Lock(); // \
- // expected-warning {{mutex 'wmu' is still locked at the end of function 'WeirdMethods'}}
- }
+ wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
+ } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
~WeirdMethods() {
- wmu.Lock(); // \
- // expected-warning {{mutex 'wmu' is still locked at the end of function '~WeirdMethods'}}
- }
+ wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
+ } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
void operator++() {
- wmu.Lock(); // \
- // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator++'}}
- }
+ wmu.Lock(); // expected-note {{mutex acquired here}}
+ } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
operator int*() {
- wmu.Lock(); // \
- // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator int *'}}
+ wmu.Lock(); // expected-note {{mutex acquired here}}
return 0;
- }
+ } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
};
//-----------------------------------------------//
@@ -740,32 +761,12 @@ void es_bad_7() {
sls_mu.Unlock();
}
+
//-----------------------------------------------//
// Unparseable lock expressions
// ----------------------------------------------//
-Mutex UPmu;
-// FIXME: add support for lock expressions involving arrays.
-Mutex mua[5];
-
-int x __attribute__((guarded_by(UPmu = sls_mu))); // \
- // expected-warning{{cannot resolve lock expression to a specific lockable object}}
-int y __attribute__((guarded_by(mua[0]))); // \
- // expected-warning{{cannot resolve lock expression to a specific lockable object}}
-
-
-void testUnparse() {
- // no errors, since the lock expressions are not resolved
- x = 5;
- y = 5;
-}
-
-void testUnparse2() {
- mua[0].Lock(); // \
- // expected-warning{{cannot resolve lock expression to a specific lockable object}}
- (&(mua[0]) + 4)->Lock(); // \
- // expected-warning{{cannot resolve lock expression to a specific lockable object}}
-}
+// FIXME -- derive new tests for unhandled expressions
//----------------------------------------------------------------------------//
@@ -1152,7 +1153,7 @@ class Foo {
int Foo::foo()
{
int res;
- w = 5.2;
+ w = 5;
res = a_ + 5;
return res;
}
@@ -1166,7 +1167,7 @@ void Foo::bar()
mu_.Unlock();
if (x > 5) {
mu1.Lock();
- g = 2.3;
+ g = 2;
mu1.Unlock();
}
}
@@ -1184,7 +1185,7 @@ void main()
f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
f2->mu_.Unlock();
mu2.Lock();
- w = 2.5;
+ w = 2;
mu2.Unlock();
}
} // end namespace thread_annot_lock_13
@@ -1420,3 +1421,823 @@ void main()
} // end namespace thread_annot_lock_67_modified
+namespace substitution_test {
+ class MyData {
+ public:
+ Mutex mu;
+
+ void lockData() __attribute__((exclusive_lock_function(mu))) { }
+ void unlockData() __attribute__((unlock_function(mu))) { }
+
+ void doSomething() __attribute__((exclusive_locks_required(mu))) { }
+ };
+
+
+ class DataLocker {
+ public:
+ void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
+ void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
+ };
+
+
+ class Foo {
+ public:
+ void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
+
+ void bar1(MyData* d) {
+ d->lockData();
+ foo(d);
+ d->unlockData();
+ }
+
+ void bar2(MyData* d) {
+ DataLocker dlr;
+ dlr.lockData(d);
+ foo(d);
+ dlr.unlockData(d);
+ }
+
+ void bar3(MyData* d1, MyData* d2) {
+ DataLocker dlr;
+ dlr.lockData(d1); // expected-note {{mutex acquired here}}
+ dlr.unlockData(d2); // \
+ // expected-warning {{unlocking 'mu' that was not locked}}
+ } // expected-warning {{mutex 'mu' is still locked at the end of function}}
+
+ void bar4(MyData* d1, MyData* d2) {
+ DataLocker dlr;
+ dlr.lockData(d1);
+ foo(d2); // \
+ // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
+ dlr.unlockData(d1);
+ }
+ };
+} // end namespace substituation_test
+
+
+
+namespace constructor_destructor_tests {
+ Mutex fooMu;
+ int myVar GUARDED_BY(fooMu);
+
+ class Foo {
+ public:
+ Foo() __attribute__((exclusive_lock_function(fooMu))) { }
+ ~Foo() __attribute__((unlock_function(fooMu))) { }
+ };
+
+ void fooTest() {
+ Foo foo;
+ myVar = 0;
+ }
+}
+
+
+namespace invalid_lock_expression_test {
+
+class LOCKABLE MyLockable {
+public:
+ MyLockable() __attribute__((exclusive_lock_function)) { }
+ ~MyLockable() { }
+};
+
+// create an empty lock expression
+void foo() {
+ MyLockable lock; // \
+ // expected-warning {{cannot resolve lock expression}}
+}
+
+} // end namespace invalid_lock_expression_test
+
+namespace template_member_test {
+
+ struct S { int n; };
+ struct T {
+ Mutex m;
+ S *s GUARDED_BY(this->m);
+ };
+ Mutex m;
+ struct U {
+ union {
+ int n;
+ };
+ } *u GUARDED_BY(m);
+
+ template<typename U>
+ struct IndirectLock {
+ int DoNaughtyThings(T *t) {
+ u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
+ return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
+ }
+ };
+
+ template struct IndirectLock<int>; // expected-note {{here}}
+
+ struct V {
+ void f(int);
+ void f(double);
+
+ Mutex m;
+ V *p GUARDED_BY(this->m);
+ };
+ template<typename U> struct W {
+ V v;
+ void f(U u) {
+ v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
+ }
+ };
+ template struct W<int>; // expected-note {{here}}
+
+}
+
+namespace test_scoped_lockable {
+
+struct TestScopedLockable {
+ Mutex mu1;
+ Mutex mu2;
+ int a __attribute__((guarded_by(mu1)));
+ int b __attribute__((guarded_by(mu2)));
+
+ bool getBool();
+
+ void foo1() {
+ MutexLock mulock(&mu1);
+ a = 5;
+ }
+
+ void foo2() {
+ ReaderMutexLock mulock1(&mu1);
+ if (getBool()) {
+ MutexLock mulock2a(&mu2);
+ b = a + 1;
+ }
+ else {
+ MutexLock mulock2b(&mu2);
+ b = a + 2;
+ }
+ }
+
+ void foo3() {
+ MutexLock mulock_a(&mu1);
+ MutexLock mulock_b(&mu1); // \
+ // expected-warning {{locking 'mu1' that is already locked}}
+ } // expected-warning {{unlocking 'mu1' that was not locked}}
+
+ void foo4() {
+ MutexLock mulock1(&mu1), mulock2(&mu2);
+ a = b+1;
+ b = a+1;
+ }
+};
+
+} // end namespace test_scoped_lockable
+
+
+namespace FunctionAttrTest {
+
+class Foo {
+public:
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+};
+
+Foo fooObj;
+
+void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
+
+void bar() {
+ foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
+ fooObj.mu_.Lock();
+ foo();
+ fooObj.mu_.Unlock();
+}
+
+}; // end namespace FunctionAttrTest
+
+
+struct TestTryLock {
+ Mutex mu;
+ int a GUARDED_BY(mu);
+ bool cond;
+
+ void foo1() {
+ if (mu.TryLock()) {
+ a = 1;
+ mu.Unlock();
+ }
+ }
+
+ void foo2() {
+ if (!mu.TryLock()) return;
+ a = 2;
+ mu.Unlock();
+ }
+
+ void foo3() {
+ bool b = mu.TryLock();
+ if (b) {
+ a = 3;
+ mu.Unlock();
+ }
+ }
+
+ void foo4() {
+ bool b = mu.TryLock();
+ if (!b) return;
+ a = 4;
+ mu.Unlock();
+ }
+
+ void foo5() {
+ while (mu.TryLock()) {
+ a = a + 1;
+ mu.Unlock();
+ }
+ }
+
+ void foo6() {
+ bool b = mu.TryLock();
+ b = !b;
+ if (b) return;
+ a = 6;
+ mu.Unlock();
+ }
+
+ void foo7() {
+ bool b1 = mu.TryLock();
+ bool b2 = !b1;
+ bool b3 = !b2;
+ if (b3) {
+ a = 7;
+ mu.Unlock();
+ }
+ }
+
+ // Test use-def chains: join points
+ void foo8() {
+ bool b = mu.TryLock();
+ bool b2 = b;
+ if (cond)
+ b = true;
+ if (b) { // b should be unknown at this point, becuase of the join point
+ a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
+ }
+ if (b2) { // b2 should be known at this point.
+ a = 8;
+ mu.Unlock();
+ }
+ }
+
+ // Test use-def-chains: back edges
+ void foo9() {
+ bool b = mu.TryLock();
+
+ for (int i = 0; i < 10; ++i);
+
+ if (b) { // b is still known, because the loop doesn't alter it
+ a = 9;
+ mu.Unlock();
+ }
+ }
+
+ // Test use-def chains: back edges
+ void foo10() {
+ bool b = mu.TryLock();
+
+ while (cond) {
+ if (b) { // b should be uknown at this point b/c of the loop
+ a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
+ }
+ b = !b;
+ }
+ }
+}; // end TestTrylock
+
+
+namespace TestTemplateAttributeInstantiation {
+
+class Foo1 {
+public:
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+};
+
+class Foo2 {
+public:
+ int a GUARDED_BY(mu_);
+ Mutex mu_;
+};
+
+
+class Bar {
+public:
+ // Test non-dependent expressions in attributes on template functions
+ template <class T>
+ void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
+ foo->a = 0;
+ }
+
+ // Test dependent expressions in attributes on template functions
+ template <class T>
+ void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
+ fooT->a = 0;
+ }
+};
+
+
+template <class T>
+class BarT {
+public:
+ Foo1 fooBase;
+ T fooBaseT;
+
+ // Test non-dependent expression in ordinary method on template class
+ void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
+ fooBase.a = 0;
+ }
+
+ // Test dependent expressions in ordinary methods on template class
+ void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
+ fooBaseT.a = 0;
+ }
+
+ // Test dependent expressions in template method in template class
+ template <class T2>
+ void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
+ fooBaseT.a = 0;
+ fooT->a = 0;
+ }
+};
+
+template <class T>
+class Cell {
+public:
+ Mutex mu_;
+ // Test dependent guarded_by
+ T data GUARDED_BY(mu_);
+
+ void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ data = 0;
+ }
+
+ void foo() {
+ mu_.Lock();
+ data = 0;
+ mu_.Unlock();
+ }
+};
+
+void test() {
+ Bar b;
+ BarT<Foo2> bt;
+ Foo1 f1;
+ Foo2 f2;
+
+ f1.mu_.Lock();
+ f2.mu_.Lock();
+ bt.fooBase.mu_.Lock();
+ bt.fooBaseT.mu_.Lock();
+
+ b.barND(&f1, &f2);
+ b.barD(&f1, &f2);
+ bt.barND();
+ bt.barD();
+ bt.barTD(&f2);
+
+ f1.mu_.Unlock();
+ bt.barTD(&f1); // \
+ // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
+
+ bt.fooBase.mu_.Unlock();
+ bt.fooBaseT.mu_.Unlock();
+ f2.mu_.Unlock();
+
+ Cell<int> cell;
+ cell.data = 0; // \
+ // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
+ cell.foo();
+ cell.mu_.Lock();
+ cell.fooEx();
+ cell.mu_.Unlock();
+}
+
+
+template <class T>
+class CellDelayed {
+public:
+ // Test dependent guarded_by
+ T data GUARDED_BY(mu_);
+ static T static_data GUARDED_BY(static_mu_);
+
+ void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
+ this->data = other->data;
+ }
+
+ template <class T2>
+ void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
+ this->data = otherT->data;
+ }
+
+ void foo() {
+ mu_.Lock();
+ data = 0;
+ mu_.Unlock();
+ }
+
+ Mutex mu_;
+ static Mutex static_mu_;
+};
+
+void testDelayed() {
+ CellDelayed<int> celld;
+ CellDelayed<int> celld2;
+ celld.foo();
+ celld.mu_.Lock();
+ celld2.mu_.Lock();
+
+ celld.fooEx(&celld2);
+ celld.fooExT(&celld2);
+
+ celld2.mu_.Unlock();
+ celld.mu_.Unlock();
+}
+
+}; // end namespace TestTemplateAttributeInstantiation
+
+
+namespace FunctionDeclDefTest {
+
+class Foo {
+public:
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+
+ virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
+};
+
+// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
+void Foo::foo1(Foo *f_defined) {
+ f_defined->a = 0;
+};
+
+void test() {
+ Foo myfoo;
+ myfoo.foo1(&myfoo); // \
+ // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
+ myfoo.mu_.Lock();
+ myfoo.foo1(&myfoo);
+ myfoo.mu_.Unlock();
+}
+
+};
+
+namespace GoingNative {
+
+ struct __attribute__((lockable)) mutex {
+ void lock() __attribute__((exclusive_lock_function));
+ void unlock() __attribute__((unlock_function));
+ // ...
+ };
+ bool foo();
+ bool bar();
+ mutex m;
+ void test() {
+ m.lock();
+ while (foo()) {
+ m.unlock();
+ // ...
+ if (bar()) {
+ // ...
+ if (foo())
+ continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
+ //...
+ }
+ // ...
+ m.lock(); // expected-note {{mutex acquired here}}
+ }
+ m.unlock();
+ }
+
+}
+
+
+
+namespace FunctionDefinitionTest {
+
+class Foo {
+public:
+ void foo1();
+ void foo2();
+ void foo3(Foo *other);
+
+ template<class T>
+ void fooT1(const T& dummy1);
+
+ template<class T>
+ void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
+
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+};
+
+template<class T>
+class FooT {
+public:
+ void foo();
+
+ Mutex mu_;
+ T a GUARDED_BY(mu_);
+};
+
+
+void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
+ a = 1;
+}
+
+void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ a = 2;
+}
+
+void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
+ other->a = 3;
+}
+
+template<class T>
+void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ a = dummy1;
+}
+
+/* TODO -- uncomment with template instantiation of attributes.
+template<class T>
+void Foo::fooT2(const T& dummy2) {
+ a = dummy2;
+}
+*/
+
+void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
+ f->a = 1;
+}
+
+void fooF2(Foo *f);
+void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
+ f->a = 2;
+}
+
+void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
+void fooF3(Foo *f) {
+ f->a = 3;
+}
+
+template<class T>
+void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ a = 0;
+}
+
+void test() {
+ int dummy = 0;
+ Foo myFoo;
+
+ myFoo.foo2(); // \
+ // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
+ myFoo.foo3(&myFoo); // \
+ // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
+ myFoo.fooT1(dummy); // \
+ // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
+
+ // FIXME: uncomment with template instantiation of attributes patch
+ // myFoo.fooT2(dummy); // expected warning
+
+ fooF1(&myFoo); // \
+ // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
+ fooF2(&myFoo); // \
+ // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
+ fooF3(&myFoo); // \
+ // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
+
+ myFoo.mu_.Lock();
+ myFoo.foo2();
+ myFoo.foo3(&myFoo);
+ myFoo.fooT1(dummy);
+
+ // FIXME: uncomment with template instantiation of attributes patch
+ // myFoo.fooT2(dummy);
+
+ fooF1(&myFoo);
+ fooF2(&myFoo);
+ fooF3(&myFoo);
+ myFoo.mu_.Unlock();
+
+ FooT<int> myFooT;
+ myFooT.foo(); // \
+ // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
+}
+
+} // end namespace FunctionDefinitionTest
+
+
+namespace SelfLockingTest {
+
+class LOCKABLE MyLock {
+public:
+ int foo GUARDED_BY(this);
+
+ void lock() EXCLUSIVE_LOCK_FUNCTION();
+ void unlock() UNLOCK_FUNCTION();
+
+ void doSomething() {
+ this->lock(); // allow 'this' as a lock expression
+ foo = 0;
+ doSomethingElse();
+ this->unlock();
+ }
+
+ void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
+ foo = 1;
+ };
+
+ void test() {
+ foo = 2; // \
+ // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
+ }
+};
+
+
+class LOCKABLE MyLock2 {
+public:
+ Mutex mu_;
+ int foo GUARDED_BY(this);
+
+ // don't check inside lock and unlock functions
+ void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
+ void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
+
+ // don't check inside constructors and destructors
+ MyLock2() { foo = 1; }
+ ~MyLock2() { foo = 0; }
+};
+
+
+} // end namespace SelfLockingTest
+
+
+namespace InvalidNonstatic {
+
+// Forward decl here causes bogus "invalid use of non-static data member"
+// on reference to mutex_ in guarded_by attribute.
+class Foo;
+
+class Foo {
+ Mutex* mutex_;
+
+ int foo __attribute__((guarded_by(mutex_)));
+};
+
+} // end namespace InvalidNonStatic
+
+
+namespace NoReturnTest {
+
+bool condition();
+void fatal() __attribute__((noreturn));
+
+Mutex mu_;
+
+void test1() {
+ MutexLock lock(&mu_);
+ if (condition()) {
+ fatal();
+ return;
+ }
+}
+
+} // end namespace NoReturnTest
+
+
+namespace TestMultiDecl {
+
+class Foo {
+public:
+ int GUARDED_BY(mu_) a;
+ int GUARDED_BY(mu_) b, c;
+
+ void foo() {
+ a = 0; // \
+ // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ b = 0; // \
+ // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
+ c = 0; // \
+ // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
+ }
+
+private:
+ Mutex mu_;
+};
+
+} // end namespace TestMultiDecl
+
+
+namespace WarnNoDecl {
+
+class Foo {
+ void foo(int a); __attribute__(( // \
+ // expected-warning {{declaration does not declare anything}}
+ exclusive_locks_required(a))); // \
+ // expected-warning {{attribute exclusive_locks_required ignored}}
+};
+
+} // end namespace WarnNoDecl
+
+
+
+namespace MoreLockExpressions {
+
+class Foo {
+public:
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+};
+
+class Bar {
+public:
+ int b;
+ Foo* f;
+
+ Foo& getFoo() { return *f; }
+ Foo& getFoo2(int c) { return *f; }
+ Foo& getFoo3(int c, int d) { return *f; }
+
+ Foo& getFooey() { return *f; }
+};
+
+Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
+
+void test() {
+ Foo foo;
+ Foo *fooArray;
+ Bar bar;
+ int a;
+ int b;
+ int c;
+
+ bar.getFoo().mu_.Lock();
+ bar.getFoo().a = 0;
+ bar.getFoo().mu_.Unlock();
+
+ (bar.getFoo().mu_).Lock(); // test parenthesis
+ bar.getFoo().a = 0;
+ (bar.getFoo().mu_).Unlock();
+
+ bar.getFoo2(a).mu_.Lock();
+ bar.getFoo2(a).a = 0;
+ bar.getFoo2(a).mu_.Unlock();
+
+ bar.getFoo3(a, b).mu_.Lock();
+ bar.getFoo3(a, b).a = 0;
+ bar.getFoo3(a, b).mu_.Unlock();
+
+ getBarFoo(bar, a).mu_.Lock();
+ getBarFoo(bar, a).a = 0;
+ getBarFoo(bar, a).mu_.Unlock();
+
+ bar.getFoo2(10).mu_.Lock();
+ bar.getFoo2(10).a = 0;
+ bar.getFoo2(10).mu_.Unlock();
+
+ bar.getFoo2(a + 1).mu_.Lock();
+ bar.getFoo2(a + 1).a = 0;
+ bar.getFoo2(a + 1).mu_.Unlock();
+
+ (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
+ (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
+ (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
+
+ bar.getFoo().mu_.Lock();
+ bar.getFooey().a = 0; // \
+ // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ bar.getFoo().mu_.Unlock();
+
+ bar.getFoo2(a).mu_.Lock();
+ bar.getFoo2(b).a = 0; // \
+ // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ bar.getFoo2(a).mu_.Unlock();
+
+ bar.getFoo3(a, b).mu_.Lock();
+ bar.getFoo3(a, c).a = 0; // \
+ // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ bar.getFoo3(a, b).mu_.Unlock();
+
+ getBarFoo(bar, a).mu_.Lock();
+ getBarFoo(bar, b).a = 0; // \
+ // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ getBarFoo(bar, a).mu_.Unlock();
+
+ (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
+ (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
+ // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+ (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
+}
+
+
+} // end namespace
+
+
diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp
index 67882d0..587cb8a 100644
--- a/test/SemaCXX/warn-thread-safety-parsing.cpp
+++ b/test/SemaCXX/warn-thread-safety-parsing.cpp
@@ -1,9 +1,26 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
+#define LOCKABLE __attribute__ ((lockable))
+#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
+#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
+#define GUARDED_VAR __attribute__ ((guarded_var))
+#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
+#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
+#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
+#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
+#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
+#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
+#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
+#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
+#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
+#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
+#define EXCLUSIVE_LOCKS_REQUIRED(...) \
+ __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
+#define SHARED_LOCKS_REQUIRED(...) \
+ __attribute__ ((shared_locks_required(__VA_ARGS__)))
+#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
-//-----------------------------------------//
-// Helper fields
-//-----------------------------------------//
class __attribute__((lockable)) Mu {
public:
@@ -324,13 +341,13 @@ int gb_var_arg_8 __attribute__((guarded_by(muPointer)));
// illegal attribute arguments
int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \
- // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}}
int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \
- // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}}
int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \
- // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}}
int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \
- // expected-error {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}}
//3.
// Thread Safety analysis tests
@@ -395,13 +412,13 @@ int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer)));
// illegal attribute arguments
int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \
- // expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \
- // expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \
- // expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \
- // expected-error {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
//-----------------------------------------//
@@ -456,15 +473,15 @@ Mu aa_var_arg_8 __attribute__((acquired_after(muPointer)));
// illegal attribute arguments
Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \
- // expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}}
Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \
- // expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}}
Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \
- // expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}}
Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \
- // expected-error {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}}
UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \
- // expected-error {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}}
+ // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}}
//-----------------------------------------//
// Acquired Before (ab)
@@ -519,15 +536,15 @@ Mu ab_var_arg_8 __attribute__((acquired_before(muPointer)));
// illegal attribute arguments
Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \
- // expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}}
Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \
- // expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}}
Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \
- // expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}}
Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \
- // expected-error {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}}
UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \
- // expected-error {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}}
+ // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}}
//-----------------------------------------//
@@ -586,11 +603,11 @@ int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2)));
// illegal attribute arguments
int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \
- // expected-error {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \
- // expected-error {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \
- // expected-error {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \
// expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
@@ -658,11 +675,11 @@ int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2)));
// illegal attribute arguments
int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \
- // expected-error {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \
- // expected-error {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \
- // expected-error {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \
// expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
@@ -686,7 +703,7 @@ int slf_function_bad_7() __attribute__((shared_lock_function(0))); // \
// plus an optional list of locks (vars/fields)
void etf_function() __attribute__((exclusive_trylock_function)); // \
- // expected-error {{attribute takes attribute takes at least 1 argument arguments}}
+ // expected-error {{attribute takes at least 1 argument}}
void etf_function_args() __attribute__((exclusive_trylock_function(1, mu2)));
@@ -740,11 +757,11 @@ int etf_function_bad_3() __attribute__((exclusive_trylock_function(muDoublePoint
// expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \
- // expected-error {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \
- // expected-error {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \
- // expected-error {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
//-----------------------------------------//
@@ -814,11 +831,11 @@ int stf_function_bad_3() __attribute__((shared_trylock_function(muDoublePointer)
// expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \
- // expected-error {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \
- // expected-error {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \
- // expected-error {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
//-----------------------------------------//
@@ -877,11 +894,11 @@ int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2)));
// illegal attribute arguments
int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \
- // expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}}
int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \
- // expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}}
int uf_function_bad_4() __attribute__((unlock_function(umu))); // \
- // expected-error {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
int uf_function_bad_1() __attribute__((unlock_function(1))); // \
// expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
@@ -951,13 +968,13 @@ int lr_function_8() __attribute__((lock_returned(muPointer)));
// illegal attribute arguments
int lr_function_bad_1() __attribute__((lock_returned(1))); // \
- // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \
- // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \
- // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
int lr_function_bad_4() __attribute__((lock_returned(umu))); // \
- // expected-error {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}}
@@ -1018,13 +1035,13 @@ int le_function_8() __attribute__((locks_excluded(muPointer)));
// illegal attribute arguments
int le_function_bad_1() __attribute__((locks_excluded(1))); // \
- // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \
- // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \
- // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
int le_function_bad_4() __attribute__((locks_excluded(umu))); // \
- // expected-error {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}}
@@ -1085,13 +1102,13 @@ int elr_function_8() __attribute__((exclusive_locks_required(muPointer)));
// illegal attribute arguments
int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \
- // expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \
- // expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \
- // expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \
- // expected-error {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
@@ -1153,13 +1170,13 @@ int slr_function_8() __attribute__((shared_locks_required(muPointer)));
// illegal attribute arguments
int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \
- // expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \
- // expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \
- // expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
+ // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \
- // expected-error {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+ // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
//-----------------------------------------//
@@ -1253,3 +1270,76 @@ public:
Mu mu;
};
+//-------------------------
+// Empty argument lists
+//-------------------------
+
+class __attribute__((lockable)) EmptyArgListsTest {
+ void lock() __attribute__((exclusive_lock_function())) { }
+ void unlock() __attribute__((unlock_function())) { }
+};
+
+
+namespace FunctionDefinitionParseTest {
+// Test parsing of attributes on function definitions.
+
+class Foo {
+public:
+ Mu mu_;
+ void foo1();
+ void foo2(Foo *f);
+};
+
+template <class T>
+class Bar {
+public:
+ Mu mu_;
+ void bar();
+};
+
+void Foo::foo1() __attribute__((exclusive_locks_required(mu_))) { }
+void Foo::foo2(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { }
+
+template <class T>
+void Bar<T>::bar() __attribute__((exclusive_locks_required(mu_))) { }
+
+void baz(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { }
+
+} // end namespace
+
+
+namespace TestMultiDecl {
+
+class Foo {
+public:
+ int __attribute__((guarded_by(mu_))) a;
+ int __attribute__((guarded_by(mu_))) b, c;
+
+private:
+ Mu mu_;
+};
+
+
+namespace NestedClassLateDecl {
+
+class Foo {
+ class Bar {
+ int a GUARDED_BY(mu);
+ int b GUARDED_BY(fooMuStatic);
+
+ void bar() EXCLUSIVE_LOCKS_REQUIRED(mu) { a = 0; }
+ void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu) { b->a = 0; }
+ void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; }
+
+ Mu mu;
+ };
+
+ int a GUARDED_BY(fooMu);
+ Mu fooMu;
+ static Mu fooMuStatic;
+};
+
+}
+
+} // end namespace TestMultiDecl
+
diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp
index 604a3c0..f36300a 100644
--- a/test/SemaCXX/warn-unreachable.cpp
+++ b/test/SemaCXX/warn-unreachable.cpp
@@ -76,3 +76,34 @@ void test6() {
S
(halt()); // expected-warning {{will never be executed}}
}
+
+// Don't warn about unreachable code in template instantiations, as
+// they may only be unreachable in that specific instantiation.
+void isUnreachable();
+
+template <typename T> void test_unreachable_templates() {
+ T::foo();
+ isUnreachable(); // no-warning
+}
+
+struct TestUnreachableA {
+ static void foo() __attribute__((noreturn));
+};
+struct TestUnreachableB {
+ static void foo();
+};
+
+void test_unreachable_templates_harness() {
+ test_unreachable_templates<TestUnreachableA>();
+ test_unreachable_templates<TestUnreachableB>();
+}
+
+// Do warn about explict template specializations, as they represent
+// actual concrete functions that somebody wrote.
+
+template <typename T> void funcToSpecialize() {}
+template <> void funcToSpecialize<int>() {
+ halt();
+ dead(); // expected-warning {{will never be executed}}
+}
+
diff --git a/test/SemaCXX/warn-unused-parameters.cpp b/test/SemaCXX/warn-unused-parameters.cpp
index 75d8dcc..00ce1a9 100644
--- a/test/SemaCXX/warn-unused-parameters.cpp
+++ b/test/SemaCXX/warn-unused-parameters.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify -std=c++11 %s
template<typename T>
struct X {
T f0(T x);
@@ -24,3 +24,11 @@ void test_X(X<int> &x, int i) {
x.f4(i);
x.f5(i);
}
+
+// Make sure both parameters aren't considered unused.
+template <typename... T>
+static int test_pack(T... t, T... s)
+{
+ auto l = [&t...]() { return sizeof...(s); };
+ return l();
+}
diff --git a/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp
index 80298ec..1c0263c 100644
--- a/test/SemaCXX/warn-unused-value.cpp
+++ b/test/SemaCXX/warn-unused-value.cpp
@@ -30,3 +30,22 @@ void b(Foo f1, Foo f2) {
}
#undef NOP
}
+
+namespace test2 {
+ extern "C" {
+ namespace std {
+ template<typename T> struct basic_string {
+ struct X {};
+ void method() const {
+ X* x;
+ &x[0]; // expected-warning {{expression result unused}}
+ }
+ };
+ typedef basic_string<char> string;
+ void func(const std::string& str) {
+ str.method(); // expected-note {{in instantiation of member function}}
+ }
+ }
+ }
+}
+
diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp
index 5ba1f2a..5827019 100644
--- a/test/SemaCXX/warn-unused-variables.cpp
+++ b/test/SemaCXX/warn-unused-variables.cpp
@@ -80,3 +80,45 @@ namespace PR10168 {
f<char>(); // expected-note {{here}}
}
}
+
+namespace PR11550 {
+ struct S1 {
+ S1();
+ };
+ S1 makeS1();
+ void testS1(S1 a) {
+ // This constructor call can be elided.
+ S1 x = makeS1(); // expected-warning {{unused variable 'x'}}
+
+ // This one cannot, so no warning.
+ S1 y;
+
+ // This call cannot, but the constructor is trivial.
+ S1 z = a; // expected-warning {{unused variable 'z'}}
+ }
+
+ // The same is true even when we know thet constructor has side effects.
+ void foo();
+ struct S2 {
+ S2() {
+ foo();
+ }
+ };
+ S2 makeS2();
+ void testS2(S2 a) {
+ S2 x = makeS2(); // expected-warning {{unused variable 'x'}}
+ S2 y;
+ S2 z = a; // expected-warning {{unused variable 'z'}}
+ }
+
+ // Or when the constructor is not declared by the user.
+ struct S3 {
+ S1 m;
+ };
+ S3 makeS3();
+ void testS3(S3 a) {
+ S3 x = makeS3(); // expected-warning {{unused variable 'x'}}
+ S3 y;
+ S3 z = a; // expected-warning {{unused variable 'z'}}
+ }
+}
diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp
index 912622f..135e034 100644
--- a/test/SemaCXX/warn-weak-vtables.cpp
+++ b/test/SemaCXX/warn-weak-vtables.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables
+// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables -Wweak-template-vtables
struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}}
virtual void f() { }
@@ -56,3 +56,23 @@ void uses(Parent &p, Derived &d, VeryDerived &vd) {
d.getFoo();
vd.getFoo();
}
+
+template<typename T> struct TemplVirt {
+ virtual void f();
+};
+
+template class TemplVirt<float>; // expected-warning{{explicit template instantiation 'TemplVirt<float>' will emit a vtable in every translation unit}}
+
+template<> struct TemplVirt<bool> {
+ virtual void f();
+};
+
+template<> struct TemplVirt<long> { // expected-warning{{'TemplVirt<long>' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}}
+ virtual void f() {}
+};
+
+void uses(TemplVirt<float>& f, TemplVirt<bool>& b, TemplVirt<long>& l) {
+ f.f();
+ b.f();
+ l.f();
+}
diff --git a/test/SemaCXX/zero-length-arrays.cpp b/test/SemaCXX/zero-length-arrays.cpp
new file mode 100644
index 0000000..05ded4a
--- /dev/null
+++ b/test/SemaCXX/zero-length-arrays.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/10228639>
+class Foo {
+ ~Foo();
+ Foo(const Foo&);
+public:
+ Foo(int);
+};
+
+class Bar {
+ int foo_count;
+ Foo foos[0];
+ Foo foos2[0][2];
+ Foo foos3[2][0];
+
+public:
+ Bar(): foo_count(0) { }
+ ~Bar() { }
+};
+
+void testBar() {
+ Bar b;
+ Bar b2(b);
+ b = b2;
+}
OpenPOWER on IntegriCloud