aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-18 16:23:48 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-18 16:23:48 +0000
commit06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 (patch)
tree3eb853da77d46cc77c4b017525a422f9ddb1385b /test/SemaCXX
parent30d791273d07fac9c0c1641a0731191bca6e8606 (diff)
downloadsrc-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.tar.gz
src-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.zip
Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1):vendor/clang/clang-release_360-r226102
Notes
Notes: svn path=/vendor/clang/dist/; revision=277325 svn path=/vendor/clang/clang-release_360-r226102/; revision=277326; tag=vendor/clang/clang-release_360-r226102
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/Inputs/header-with-pragma-optimize-off.h5
-rw-r--r--test/SemaCXX/Inputs/override-system-header.h6
-rw-r--r--test/SemaCXX/MicrosoftCompatibility.cpp10
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp8
-rw-r--r--test/SemaCXX/MicrosoftSuper.cpp149
-rw-r--r--test/SemaCXX/PR10177.cpp31
-rw-r--r--test/SemaCXX/PR20705.cpp21
-rw-r--r--test/SemaCXX/align_value.cpp26
-rw-r--r--test/SemaCXX/anonymous-union.cpp6
-rw-r--r--test/SemaCXX/arrow-operator.cpp5
-rw-r--r--test/SemaCXX/ast-print.cpp5
-rw-r--r--test/SemaCXX/atomic-type.cpp4
-rw-r--r--test/SemaCXX/attr-cxx0x-fixit.cpp5
-rw-r--r--test/SemaCXX/attr-flag-enum-reject.cpp4
-rw-r--r--test/SemaCXX/attr-gnu.cpp29
-rw-r--r--test/SemaCXX/attr-nodebug.cpp4
-rw-r--r--test/SemaCXX/attr-nonnull.cpp4
-rw-r--r--test/SemaCXX/attr-optnone.cpp38
-rw-r--r--test/SemaCXX/attr-print.cpp9
-rw-r--r--test/SemaCXX/attributed-auto-deduction.cpp20
-rw-r--r--test/SemaCXX/bitfield.cpp32
-rw-r--r--test/SemaCXX/blocks.cpp45
-rw-r--r--test/SemaCXX/builtin-assume-aligned-tmpl.cpp87
-rw-r--r--test/SemaCXX/builtin-assume-aligned.cpp49
-rw-r--r--test/SemaCXX/call-with-static-chain.cpp15
-rw-r--r--test/SemaCXX/complex-folding.cpp90
-rw-r--r--test/SemaCXX/const-cast.cpp3
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp126
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp31
-rw-r--r--test/SemaCXX/constexpr-value-init.cpp6
-rw-r--r--test/SemaCXX/conversion-function.cpp12
-rw-r--r--test/SemaCXX/conversion.cpp20
-rw-r--r--test/SemaCXX/crashes.cpp6
-rw-r--r--test/SemaCXX/cxx-deprecated.cpp26
-rw-r--r--test/SemaCXX/cxx0x-compat.cpp8
-rw-r--r--test/SemaCXX/cxx0x-cursory-default-delete.cpp2
-rw-r--r--test/SemaCXX/cxx0x-initializer-references.cpp6
-rw-r--r--test/SemaCXX/cxx11-ast-print.cpp2
-rw-r--r--test/SemaCXX/cxx11-thread-unsupported.cpp5
-rw-r--r--test/SemaCXX/cxx1y-constexpr-not-const.cpp2
-rw-r--r--test/SemaCXX/cxx1y-deduced-return-type.cpp13
-rw-r--r--test/SemaCXX/cxx1y-generic-lambdas.cpp32
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_in_class.cpp10
-rw-r--r--test/SemaCXX/cxx98-compat-flags.cpp4
-rw-r--r--test/SemaCXX/cxx98-compat-pedantic.cpp31
-rw-r--r--test/SemaCXX/cxx98-compat.cpp65
-rw-r--r--test/SemaCXX/decl-init-ref.cpp2
-rw-r--r--test/SemaCXX/decl-microsoft-call-conv.cpp13
-rw-r--r--test/SemaCXX/default1.cpp6
-rw-r--r--test/SemaCXX/default2.cpp6
-rw-r--r--test/SemaCXX/dependent-noexcept-unevaluated.cpp3
-rw-r--r--test/SemaCXX/deprecated.cpp8
-rw-r--r--test/SemaCXX/devirtualize-vtable-marking.cpp47
-rw-r--r--test/SemaCXX/dllexport.cpp58
-rw-r--r--test/SemaCXX/dllimport.cpp344
-rw-r--r--test/SemaCXX/enable_if.cpp41
-rw-r--r--test/SemaCXX/enum-scoped.cpp8
-rw-r--r--test/SemaCXX/exceptions.cpp24
-rw-r--r--test/SemaCXX/explicit.cpp2
-rw-r--r--test/SemaCXX/flexible-array-test.cpp6
-rw-r--r--test/SemaCXX/for-range-examples.cpp20
-rw-r--r--test/SemaCXX/friend.cpp55
-rw-r--r--test/SemaCXX/goto.cpp4
-rw-r--r--test/SemaCXX/implicit-exception-spec.cpp35
-rw-r--r--test/SemaCXX/issue547.cpp12
-rw-r--r--test/SemaCXX/lambda-expressions.cpp80
-rw-r--r--test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp (renamed from test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp)0
-rw-r--r--test/SemaCXX/libstdcxx_is_pod_hack.cpp15
-rw-r--r--test/SemaCXX/libstdcxx_pair_swap_hack.cpp74
-rw-r--r--test/SemaCXX/member-init.cpp84
-rw-r--r--test/SemaCXX/member-pointer-ms.cpp19
-rw-r--r--test/SemaCXX/namespace-alias.cpp6
-rw-r--r--test/SemaCXX/nonnull.cpp5
-rw-r--r--test/SemaCXX/nullptr.cpp2
-rw-r--r--test/SemaCXX/overloaded-operator.cpp12
-rw-r--r--test/SemaCXX/override-in-system-header.cpp19
-rw-r--r--test/SemaCXX/pragma-optimize.cpp53
-rw-r--r--test/SemaCXX/predefined-expr.cpp16
-rw-r--r--test/SemaCXX/return-noreturn.cpp100
-rw-r--r--test/SemaCXX/return.cpp8
-rw-r--r--test/SemaCXX/runtimediag-ppe.cpp2
-rw-r--r--test/SemaCXX/scope-check.cpp38
-rw-r--r--test/SemaCXX/statements.cpp19
-rw-r--r--test/SemaCXX/string-plus-int.cpp5
-rw-r--r--test/SemaCXX/struct-class-redecl.cpp6
-rw-r--r--test/SemaCXX/trailing-return-0x.cpp10
-rw-r--r--test/SemaCXX/type-traits.cpp8
-rw-r--r--test/SemaCXX/typeid.cpp6
-rw-r--r--test/SemaCXX/typo-correction-delayed.cpp159
-rw-r--r--test/SemaCXX/typo-correction-pt2.cpp302
-rw-r--r--test/SemaCXX/typo-correction.cpp385
-rw-r--r--test/SemaCXX/undefined-internal.cpp4
-rw-r--r--test/SemaCXX/uninitialized.cpp713
-rw-r--r--test/SemaCXX/unknown-type-name.cpp6
-rw-r--r--test/SemaCXX/using-decl-1.cpp8
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp5
-rw-r--r--test/SemaCXX/vtable-instantiation.cpp (renamed from test/SemaCXX/vtable-instantiation.cc)4
-rw-r--r--test/SemaCXX/warn-bool-conversion.cpp27
-rw-r--r--test/SemaCXX/warn-consumed-parsing.cpp1
-rw-r--r--test/SemaCXX/warn-global-constructors.cpp6
-rw-r--r--test/SemaCXX/warn-overloaded-virtual.cpp22
-rw-r--r--test/SemaCXX/warn-self-move.cpp55
-rw-r--r--test/SemaCXX/warn-tautological-compare.cpp40
-rw-r--r--test/SemaCXX/warn-tautological-undefined-compare.cpp28
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp484
-rw-r--r--test/SemaCXX/warn-thread-safety-negative.cpp104
-rw-r--r--test/SemaCXX/warn-thread-safety-verbose.cpp86
-rw-r--r--test/SemaCXX/warn-undefined-bool-conversion.cpp24
-rw-r--r--test/SemaCXX/warn-unused-comparison.cpp2
-rw-r--r--test/SemaCXX/warn-unused-filescoped.cpp4
-rw-r--r--test/SemaCXX/warn-unused-local-typedef-serialize.cpp11
-rw-r--r--test/SemaCXX/warn-unused-local-typedef-x86asm.cpp16
-rw-r--r--test/SemaCXX/warn-unused-local-typedef.cpp242
-rw-r--r--test/SemaCXX/warn-unused-private-field-delayed-template.cpp11
-rw-r--r--test/SemaCXX/warn-unused-result.cpp47
-rw-r--r--test/SemaCXX/warn-unused-value-cxx11.cpp44
-rw-r--r--test/SemaCXX/warn-unused-value.cpp34
117 files changed, 4622 insertions, 650 deletions
diff --git a/test/SemaCXX/Inputs/header-with-pragma-optimize-off.h b/test/SemaCXX/Inputs/header-with-pragma-optimize-off.h
new file mode 100644
index 000000000000..ac5020697eba
--- /dev/null
+++ b/test/SemaCXX/Inputs/header-with-pragma-optimize-off.h
@@ -0,0 +1,5 @@
+
+// Open an "off" region in this header.
+#pragma clang optimize off
+
+// Let the "off" region fall through to anything including this header.
diff --git a/test/SemaCXX/Inputs/override-system-header.h b/test/SemaCXX/Inputs/override-system-header.h
new file mode 100644
index 000000000000..9831ab7952b1
--- /dev/null
+++ b/test/SemaCXX/Inputs/override-system-header.h
@@ -0,0 +1,6 @@
+// override-system-header.h to test out 'override' warning.
+// rdar://18295240
+#define END_COM_MAP virtual unsigned AddRef(void) = 0;
+
+#define STDMETHOD(method) virtual void method
+#define IFACEMETHOD(method) STDMETHOD(method)
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp
index fb7d9751d1a5..56486b8f049a 100644
--- a/test/SemaCXX/MicrosoftCompatibility.cpp
+++ b/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -34,7 +34,7 @@ namespace ms_protected_scope {
int jump_over_variable_init(bool b) {
if (b)
- goto foo; // expected-warning {{goto into protected scope}}
+ goto foo; // expected-warning {{jump from this goto statement to its label is a Microsoft extension}}
C c; // expected-note {{jump bypasses variable initialization}}
foo:
return 1;
@@ -45,7 +45,7 @@ struct Y {
};
void jump_over_var_with_dtor() {
- goto end; // expected-warning{{goto into protected scope}}
+ goto end; // expected-warning{{jump from this goto statement to its label is a Microsoft extension}}
Y y; // expected-note {{jump bypasses variable with a non-trivial destructor}}
end:
;
@@ -55,14 +55,14 @@ void jump_over_var_with_dtor() {
switch (c) {
case 0:
int x = 56; // expected-note {{jump bypasses variable initialization}}
- case 1: // expected-error {{switch case is in protected scope}}
+ case 1: // expected-error {{cannot jump}}
x = 10;
}
}
void exception_jump() {
- goto l2; // expected-error {{goto into protected scope}}
+ goto l2; // expected-error {{cannot jump}}
try { // expected-note {{jump bypasses initialization of try block}}
l2: ;
} catch(int) {
@@ -71,7 +71,7 @@ void exception_jump() {
int jump_over_indirect_goto() {
static void *ps[] = { &&a0 };
- goto *&&a0; // expected-warning {{goto into protected scope}}
+ goto *&&a0; // expected-warning {{jump from this goto statement to its label is a Microsoft extension}}
int a = 3; // expected-note {{jump bypasses variable initialization}}
a0:
return 0;
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index 6d221a409e7b..57d6f0d6bef2 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -79,6 +79,7 @@ struct M {
// __unaligned handling
typedef char __unaligned *aligned_type;
+typedef struct UnalignedTag { int f; } __unaligned *aligned_type2;
template<typename T> void h1(T (__stdcall M::* const )()) { }
@@ -372,14 +373,15 @@ struct SomeBase {
// expected-note@+2 {{overridden virtual function is here}}
// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}
- virtual void SealedFunction() sealed;
+ virtual void SealedFunction() sealed; // expected-note {{overridden virtual function is here}}
};
// expected-note@+2 {{'SealedType' declared here}}
// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}}
struct SealedType sealed : SomeBase {
- // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
- virtual void SealedFunction();
+ // expected-error@+2 {{declaration of 'SealedFunction' overrides a 'sealed' function}}
+ // FIXME. warning can be suppressed if we're also issuing error for overriding a 'final' function.
+ virtual void SealedFunction(); // expected-warning {{'SealedFunction' overrides a member function but is not marked 'override'}}
// expected-warning@+1 {{'override' keyword is a C++11 extension}}
virtual void OverrideMe() override;
diff --git a/test/SemaCXX/MicrosoftSuper.cpp b/test/SemaCXX/MicrosoftSuper.cpp
new file mode 100644
index 000000000000..cb21656ab762
--- /dev/null
+++ b/test/SemaCXX/MicrosoftSuper.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 %s -fsyntax-only -fms-extensions -std=c++11 -verify
+
+struct Errors {
+ using __super::foo; // expected-error {{'__super' cannot be used with a using declaration}}
+ __super::XXX x; // expected-error {{invalid use of '__super', Errors has no base classes}} expected-error {{expected}}
+
+ void foo() {
+ // expected-note@+4 {{replace parentheses with an initializer to declare a variable}}
+ // expected-warning@+3 {{empty parentheses interpreted as a function declaration}}
+ // expected-error@+2 {{C++ requires a type specifier for all declarations}}
+ // expected-error@+1 {{use of '__super' inside a lambda is unsupported}}
+ auto lambda = []{ __super::foo(); };
+ }
+};
+
+struct Base1 {
+ void foo(int) {}
+
+ static void static_foo() {}
+
+ typedef int XXX;
+};
+
+struct Derived : Base1 {
+ __super::XXX x;
+ typedef __super::XXX Type;
+
+ enum E {
+ X = sizeof(__super::XXX)
+ };
+
+ void foo() {
+ __super::foo(1);
+
+ if (true) {
+ __super::foo(1);
+ }
+
+ return __super::foo(1);
+ }
+
+ static void bar() {
+ __super::static_foo();
+ }
+};
+
+struct Outer {
+ struct Inner : Base1 {
+ static const int x = sizeof(__super::XXX);
+ };
+};
+
+struct Base2 {
+ void foo(char) {}
+};
+
+struct MemberFunctionInMultipleBases : Base1, Base2 {
+ void foo() {
+ __super::foo('x');
+ }
+};
+
+struct Base3 {
+ void foo(int) {}
+ void foo(char) {}
+};
+
+struct OverloadedMemberFunction : Base3 {
+ void foo() {
+ __super::foo('x');
+ }
+};
+
+struct PointerToMember : Base1 {
+ template <void (Base1::*MP)(int)>
+ struct Wrapper {
+ static void bar() {}
+ };
+
+ void baz();
+};
+
+void PointerToMember::baz() {
+ Wrapper<&__super::foo>::bar();
+}
+
+template <typename T>
+struct BaseTemplate {
+ typedef int XXX;
+
+ int foo() { return 0; }
+};
+
+struct DerivedFromKnownSpecialization : BaseTemplate<int> {
+ __super::XXX a;
+ typedef __super::XXX b;
+
+ void foo() {
+ __super::XXX c;
+ typedef __super::XXX d;
+
+ __super::foo();
+ }
+};
+
+template <typename T>
+struct DerivedFromDependentBase : BaseTemplate<T> {
+ typename __super::XXX a;
+ typedef typename __super::XXX b;
+
+ __super::XXX c; // expected-error {{missing 'typename'}}
+ typedef __super::XXX d; // expected-error {{missing 'typename'}}
+
+ void foo() {
+ typename __super::XXX e;
+ typedef typename __super::XXX f;
+
+ __super::XXX g; // expected-error {{missing 'typename'}}
+ typedef __super::XXX h; // expected-error {{missing 'typename'}}
+
+ int x = __super::foo();
+ }
+};
+
+template <typename T>
+struct DerivedFromTemplateParameter : T {
+ typename __super::XXX a;
+ typedef typename __super::XXX b;
+
+ __super::XXX c; // expected-error {{missing 'typename'}}
+ typedef __super::XXX d; // expected-error {{missing 'typename'}}
+
+ void foo() {
+ typename __super::XXX e;
+ typedef typename __super::XXX f;
+
+ __super::XXX g; // expected-error {{missing 'typename'}}
+ typedef __super::XXX h; // expected-error {{missing 'typename'}}
+
+ __super::foo(1);
+ }
+};
+
+void instantiate() {
+ DerivedFromDependentBase<int> d;
+ d.foo();
+ DerivedFromTemplateParameter<Base1> t;
+ t.foo();
+}
diff --git a/test/SemaCXX/PR10177.cpp b/test/SemaCXX/PR10177.cpp
index 8d745de0a6a1..e361ff37bc03 100644
--- a/test/SemaCXX/PR10177.cpp
+++ b/test/SemaCXX/PR10177.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y -verify %s -DCXX1Y
+
+#ifndef CXX1Y
template<typename T, typename U, U> using alias_ref = T;
template<typename T, typename U, U> void func_ref() {}
@@ -9,22 +12,29 @@ struct U {
static int a;
};
-template<int N> struct S; // expected-note 2{{here}}
+template<int N> struct S; // expected-note 6{{here}}
template<int N>
-int U<N>::a = S<N>::kError; // expected-error 2{{undefined}}
+int U<N>::a = S<N>::kError; // expected-error 6{{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)alias_ref<int, int&, U<0>::a>(); // expected-note {{here}}
(void)func_ref<int, int&, U<1>::a>(); // expected-note {{here}}
(void)class_ref<int, int&, U<2>::a>(); // expected-note {{here}}
};
+
+template<int N>
+void fi() {
+ (void)alias_ref<int, int&, U<N>::a>(); // expected-note {{here}}
+ (void)func_ref<int, int&, U<N+1>::a>(); // expected-note {{here}}
+ (void)class_ref<int, int&, U<N+2>::a>(); // expected-note {{here}}
+};
+
int main() {
- f<int>(); // expected-note 2{{here}}
+ f<int>(); // NOTE: Non-dependent name uses are type-checked at template definition time.
+ fi<10>(); // expected-note 3{{here}}
}
namespace N {
@@ -38,3 +48,12 @@ namespace N {
}
int j = f<int>();
}
+
+#else
+// expected-no-diagnostics
+
+namespace { template<typename> extern int n; }
+template<typename T> int g() { return n<int>; }
+
+#endif
+
diff --git a/test/SemaCXX/PR20705.cpp b/test/SemaCXX/PR20705.cpp
new file mode 100644
index 000000000000..be2676e56356
--- /dev/null
+++ b/test/SemaCXX/PR20705.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+template <typename T>
+struct X {};
+auto b = []() {
+ struct S {
+ static typename X<decltype(int)>::type Run(){};
+ // expected-error@-1 4{{}}
+ };
+ return 5;
+}();
+
+template <typename T1, typename T2>
+class PC {
+};
+
+template <typename T>
+class P {
+ static typename PC<T, Invalid>::Type Foo();
+ // expected-error@-1 4{{}}
+};
diff --git a/test/SemaCXX/align_value.cpp b/test/SemaCXX/align_value.cpp
new file mode 100644
index 000000000000..519868201f99
--- /dev/null
+++ b/test/SemaCXX/align_value.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef double * __attribute__((align_value(64))) aligned_double;
+
+void foo(aligned_double x, double * y __attribute__((align_value(32))),
+ double & z __attribute__((align_value(128)))) { };
+
+template <typename T, int Q>
+struct x {
+ typedef T* aligned_int __attribute__((align_value(32+8*Q)));
+ aligned_int V;
+
+ void foo(aligned_int a, T &b __attribute__((align_value(sizeof(T)*4))));
+};
+
+x<float, 4> y;
+
+template <typename T, int Q>
+struct nope {
+ // expected-error@+1 {{requested alignment is not a power of 2}}
+ void foo(T &b __attribute__((align_value(sizeof(T)+1))));
+};
+
+// expected-note@+1 {{in instantiation of template class 'nope<long double, 4>' requested here}}
+nope<long double, 4> y2;
+
diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp
index fde27b049d88..46d426cf0c0f 100644
--- a/test/SemaCXX/anonymous-union.cpp
+++ b/test/SemaCXX/anonymous-union.cpp
@@ -80,10 +80,14 @@ union { // expected-error{{anonymous unions at namespace or global scope must be
};
static union {
- int int_val2;
+ int int_val2; // expected-note{{previous definition is here}}
float float_val2;
};
+void PR21858() {
+ void int_val2(); // expected-error{{redefinition of 'int_val2' as different kind of symbol}}
+}
+
void f() {
int_val2 = 0;
float_val2 = 0.0;
diff --git a/test/SemaCXX/arrow-operator.cpp b/test/SemaCXX/arrow-operator.cpp
index 173ff729fc1b..3e32a6ba33eb 100644
--- a/test/SemaCXX/arrow-operator.cpp
+++ b/test/SemaCXX/arrow-operator.cpp
@@ -52,14 +52,15 @@ class wrapped_ptr {
class Worker {
public:
- void DoSomething();
+ void DoSomething(); // expected-note {{'DoSomething' declared here}}
void Chuck();
};
void test() {
wrapped_ptr<Worker> worker(new Worker);
worker.DoSomething(); // expected-error {{no member named 'DoSomething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}}
- worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'}}
+ worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}} \
+ // expected-error {{no member named 'DoSamething' in 'arrow_suggest::Worker'; did you mean 'DoSomething'?}}
worker.Chuck(); // expected-error {{no member named 'Chuck' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean 'Check'?}}
}
diff --git a/test/SemaCXX/ast-print.cpp b/test/SemaCXX/ast-print.cpp
index 4851571283f4..baece3c2b320 100644
--- a/test/SemaCXX/ast-print.cpp
+++ b/test/SemaCXX/ast-print.cpp
@@ -208,3 +208,8 @@ void test(int i) {
}
}
}
+
+namespace {
+// CHECK: struct {{\[\[gnu::visibility\(\"hidden\"\)\]\]}} S;
+struct [[gnu::visibility("hidden")]] S;
+}
diff --git a/test/SemaCXX/atomic-type.cpp b/test/SemaCXX/atomic-type.cpp
index ae18eab5b4a9..779b0671cad6 100644
--- a/test/SemaCXX/atomic-type.cpp
+++ b/test/SemaCXX/atomic-type.cpp
@@ -83,3 +83,7 @@ namespace copy_init {
// allows extraneous braces around initializers.
Y y3 = { { X(0) }, { 4 } }; // expected-error 2{{illegal initializer type}}
}
+
+bool PR21836(_Atomic(int) *x) {
+ return *x;
+}
diff --git a/test/SemaCXX/attr-cxx0x-fixit.cpp b/test/SemaCXX/attr-cxx0x-fixit.cpp
new file mode 100644
index 000000000000..69eb22399607
--- /dev/null
+++ b/test/SemaCXX/attr-cxx0x-fixit.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -std=c++11 %s 2>&1 | FileCheck %s
+
+[[noreturn()]] void f(); // expected-error {{attribute 'noreturn' cannot have an argument list}} \
+// CHECK: fix-it:"{{.*}}":{4:11-4:13}:""
diff --git a/test/SemaCXX/attr-flag-enum-reject.cpp b/test/SemaCXX/attr-flag-enum-reject.cpp
new file mode 100644
index 000000000000..f28d60c0c295
--- /dev/null
+++ b/test/SemaCXX/attr-flag-enum-reject.cpp
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -x c++ -Wassign-enum %s
+
+enum __attribute__((flag_enum)) flag { // expected-warning {{ignored}}
+};
diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp
new file mode 100644
index 000000000000..b4e9f4609f67
--- /dev/null
+++ b/test/SemaCXX/attr-gnu.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -fms-compatibility -verify %s
+
+void f() {
+ // GNU-style attributes are prohibited in this position.
+ auto P = new int * __attribute__((vector_size(8))); // expected-error {{an attribute list cannot appear here}} \
+ // expected-error {{invalid vector element type 'int *'}}
+
+ // Ensure that MS type attribute keywords are still supported in this
+ // position.
+ auto P2 = new int * __sptr; // Ok
+}
+
+void g(int a[static [[]] 5]); // expected-error {{static array size is a C99 feature, not permitted in C++}}
+
+namespace {
+class B {
+public:
+ virtual void test() {}
+ virtual void test2() {}
+ virtual void test3() {}
+};
+
+class D : public B {
+public:
+ void test() __attribute__((deprecated)) final {} // expected-warning {{GCC does not allow an attribute in this position on a function declaration}}
+ void test2() [[]] override {} // Ok
+ void test3() __attribute__((cf_unknown_transfer)) override {} // Ok, not known to GCC.
+};
+}
diff --git a/test/SemaCXX/attr-nodebug.cpp b/test/SemaCXX/attr-nodebug.cpp
index b441da21f8e7..fd35722f62b1 100644
--- a/test/SemaCXX/attr-nodebug.cpp
+++ b/test/SemaCXX/attr-nodebug.cpp
@@ -1,7 +1,9 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 %s -std=c++11 -verify -fsyntax-only
// Note: most of the 'nodebug' tests are in attr-nodebug.c.
// expected-no-diagnostics
class c {
void t3() __attribute__((nodebug));
};
+
+[[gnu::nodebug]] void f() {}
diff --git a/test/SemaCXX/attr-nonnull.cpp b/test/SemaCXX/attr-nonnull.cpp
index 8af49d9d29e6..8fce99759b6a 100644
--- a/test/SemaCXX/attr-nonnull.cpp
+++ b/test/SemaCXX/attr-nonnull.cpp
@@ -27,8 +27,8 @@ namespace rdar8769025 {
__attribute__((nonnull(2))) void f2(int i, int * const &p);
void test_f1() {
- f1(0); // expected-warning{{null passed to a callee which requires a non-null argument}}
- f2(0, 0); // expected-warning{{null passed to a callee which requires a non-null argument}}
+ f1(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
+ f2(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}}
}
}
diff --git a/test/SemaCXX/attr-optnone.cpp b/test/SemaCXX/attr-optnone.cpp
index eaa50004047c..58776caf7ae6 100644
--- a/test/SemaCXX/attr-optnone.cpp
+++ b/test/SemaCXX/attr-optnone.cpp
@@ -3,11 +3,37 @@
int foo() __attribute__((optnone));
int bar() __attribute__((optnone)) __attribute__((noinline));
-int baz() __attribute__((always_inline)) __attribute__((optnone)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}}
-int quz() __attribute__((optnone)) __attribute__((always_inline)); // expected-error{{'optnone' and 'always_inline' attributes are not compatible}}
+int baz() __attribute__((always_inline)) __attribute__((optnone)); // expected-warning{{'always_inline' attribute ignored}} expected-note{{conflicting attribute is here}}
+int quz() __attribute__((optnone)) __attribute__((always_inline)); // expected-warning{{'always_inline' attribute ignored}} expected-note{{conflicting attribute is here}}
-__forceinline __attribute__((optnone)) int bax(); // expected-error{{'__forceinline' and 'optnone' attributes are not compatible}}
-__attribute__((optnone)) __forceinline int qux(); // expected-error{{'optnone' and '__forceinline' attributes are not compatible}}
+__attribute__((always_inline)) int baz1(); // expected-warning{{'always_inline' attribute ignored}}
+__attribute__((optnone)) int baz1() { return 1; } // expected-note{{conflicting attribute is here}}
+
+__attribute__((optnone)) int quz1(); // expected-note{{conflicting attribute is here}}
+__attribute__((always_inline)) int quz1() { return 1; } // expected-warning{{'always_inline' attribute ignored}}
+
+int bay() __attribute__((minsize)) __attribute__((optnone)); // expected-warning{{'minsize' attribute ignored}} expected-note{{conflicting}}
+int quy() __attribute__((optnone)) __attribute__((minsize)); // expected-warning{{'minsize' attribute ignored}} expected-note{{conflicting}}
+
+__attribute__((minsize)) int bay1(); // expected-warning{{'minsize' attribute ignored}}
+__attribute__((optnone)) int bay1() { return 1; } // expected-note{{conflicting attribute is here}}
+
+__attribute__((optnone)) int quy1(); // expected-note{{conflicting attribute is here}}
+__attribute__((minsize)) int quy1() { return 1; } // expected-warning{{'minsize' attribute ignored}}
+
+__attribute__((always_inline)) // expected-warning{{'always_inline' attribute ignored}}
+ __attribute__((minsize)) // expected-warning{{'minsize' attribute ignored}}
+void bay2();
+__attribute__((optnone)) // expected-note 2 {{conflicting}}
+void bay2() {}
+
+__forceinline __attribute__((optnone)) int bax(); // expected-warning{{'__forceinline' attribute ignored}} expected-note{{conflicting}}
+__attribute__((optnone)) __forceinline int qux(); // expected-warning{{'__forceinline' attribute ignored}} expected-note{{conflicting}}
+
+__forceinline int bax2(); // expected-warning{{'__forceinline' attribute ignored}}
+__attribute__((optnone)) int bax2() { return 1; } // expected-note{{conflicting}}
+__attribute__((optnone)) int qux2(); // expected-note{{conflicting}}
+__forceinline int qux2() { return 1; } // expected-warning{{'__forceinline' attribute ignored}}
int globalVar __attribute__((optnone)); // expected-warning{{'optnone' attribute only applies to functions}}
@@ -29,8 +55,8 @@ int foo2();
[[clang::optnone]]
int bar2() __attribute__((noinline));
-[[clang::optnone]]
-int baz2() __attribute__((always_inline)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}}
+[[clang::optnone]] // expected-note {{conflicting}}
+int baz2() __attribute__((always_inline)); // expected-warning{{'always_inline' attribute ignored}}
[[clang::optnone]] int globalVar2; //expected-warning{{'optnone' attribute only applies to functions}}
diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp
index a07eeff5646e..337a6fb69ba3 100644
--- a/test/SemaCXX/attr-print.cpp
+++ b/test/SemaCXX/attr-print.cpp
@@ -22,3 +22,12 @@ typedef int Small1 __attribute__((mode(byte)));
// CHECK: int small __attribute__((mode(byte)));
int small __attribute__((mode(byte)));
+
+// CHECK: int v __attribute__((visibility("hidden")));
+int v __attribute__((visibility("hidden")));
+
+// CHECK: class __attribute__((consumable("unknown"))) AttrTester1
+class __attribute__((consumable(unknown))) AttrTester1 {
+ // CHECK: void callableWhen() __attribute__((callable_when("unconsumed", "consumed")));
+ void callableWhen() __attribute__((callable_when("unconsumed", "consumed")));
+};
diff --git a/test/SemaCXX/attributed-auto-deduction.cpp b/test/SemaCXX/attributed-auto-deduction.cpp
new file mode 100644
index 000000000000..b0cae187e8e3
--- /dev/null
+++ b/test/SemaCXX/attributed-auto-deduction.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple armv7 -std=c++14 -x c++ %s -fsyntax-only
+// expected-no-diagnostics
+
+void deduce() {
+ auto single_int = [](int i) __attribute__ (( pcs("aapcs") )) {
+ return i;
+ };
+ auto multiple_int = [](int i) __attribute__ (( pcs("aapcs") ))
+ __attribute__ (( pcs("aapcs") )) {
+ return i;
+ };
+
+ auto single_void = []() __attribute__ (( pcs("aapcs") )) { };
+ auto multiple_void = []() __attribute__ (( pcs("aapcs") ))
+ __attribute__ (( pcs("aapcs") )) { };
+}
+
+auto ( __attribute__ (( pcs("aapcs") )) single_attribute() ) { }
+auto ( ( __attribute__ (( pcs("aapcs") )) ( ( __attribute__ (( pcs("aapcs") )) multiple_attributes() ) ) ) ) { }
+
diff --git a/test/SemaCXX/bitfield.cpp b/test/SemaCXX/bitfield.cpp
new file mode 100644
index 000000000000..083c28ffbb3d
--- /dev/null
+++ b/test/SemaCXX/bitfield.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 %s -verify
+
+// expected-no-diagnostics
+
+namespace PromotionVersusMutation {
+ typedef unsigned Unsigned;
+ typedef signed Signed;
+
+ struct T { unsigned n : 2; } t;
+
+ typedef __typeof__(t.n) Unsigned; // Bitfield is unsigned
+ typedef __typeof__(+t.n) Signed; // ... but promotes to signed.
+
+ typedef __typeof__(t.n + 0) Signed; // Arithmetic promotes.
+
+ typedef __typeof__(t.n = 0) Unsigned; // Assignment produces an lvalue...
+ typedef __typeof__(t.n += 0) Unsigned;
+ typedef __typeof__(t.n *= 0) Unsigned;
+ typedef __typeof__(+(t.n = 0)) Signed; // ... which is a bit-field.
+ typedef __typeof__(+(t.n += 0)) Signed;
+ typedef __typeof__(+(t.n *= 0)) Signed;
+
+ typedef __typeof__(++t.n) Unsigned; // Increment is equivalent to compound-assignment.
+ typedef __typeof__(--t.n) Unsigned;
+ typedef __typeof__(+(++t.n)) Signed;
+ typedef __typeof__(+(--t.n)) Signed;
+
+ typedef __typeof__(t.n++) Unsigned; // Post-increment's result has the type
+ typedef __typeof__(t.n--) Unsigned; // of the operand...
+ typedef __typeof__(+(t.n++)) Unsigned; // ... and is not a bit-field (because
+ typedef __typeof__(+(t.n--)) Unsigned; // it's not a glvalue).
+}
diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp
index a2672d13b72d..0521802172f9 100644
--- a/test/SemaCXX/blocks.cpp
+++ b/test/SemaCXX/blocks.cpp
@@ -100,3 +100,48 @@ namespace test5 {
});
}
}
+
+
+// rdar://16356628
+//
+// Ensure that we can end function bodies while parsing an
+// expression that requires an explicitly-tracked cleanup object
+// (i.e. a block literal).
+
+// The nested function body in this test case is a template
+// instantiation. The template function has to be constexpr because
+// we'll otherwise delay its instantiation to the end of the
+// translation unit.
+namespace test6a {
+ template <class T> constexpr int func() { return 0; }
+ void run(void (^)(), int);
+
+ void test() {
+ int aCapturedVar = 0;
+ run(^{ (void) aCapturedVar; }, func<int>());
+ }
+}
+
+// The nested function body in this test case is a method of a local
+// class.
+namespace test6b {
+ void run(void (^)(), void (^)());
+ void test() {
+ int aCapturedVar = 0;
+ run(^{ (void) aCapturedVar; },
+ ^{ struct A { static void foo() {} };
+ A::foo(); });
+ }
+}
+
+// The nested function body in this test case is a lambda invocation
+// function.
+namespace test6c {
+ void run(void (^)(), void (^)());
+ void test() {
+ int aCapturedVar = 0;
+ run(^{ (void) aCapturedVar; },
+ ^{ struct A { static void foo() {} };
+ A::foo(); });
+ }
+}
diff --git a/test/SemaCXX/builtin-assume-aligned-tmpl.cpp b/test/SemaCXX/builtin-assume-aligned-tmpl.cpp
new file mode 100644
index 000000000000..0909070c5e11
--- /dev/null
+++ b/test/SemaCXX/builtin-assume-aligned-tmpl.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<int z>
+int test9(int *a) {
+ a = (int *) __builtin_assume_aligned(a, z + 1); // expected-error {{requested alignment is not a power of 2}}
+ return a[0];
+}
+
+void test9i(int *a) {
+ test9<42>(a); // expected-note {{in instantiation of function template specialization 'test9<42>' requested here}}
+}
+
+template<typename T>
+int test10(int *a, T z) {
+ a = (int *) __builtin_assume_aligned(a, z + 1); // expected-error {{must be a constant integer}}
+ return a[0];
+}
+
+int test10i(int *a) {
+ return test10(a, 42); // expected-note {{in instantiation of function template specialization 'test10<int>' requested here}}
+}
+
+template <int q>
+void *atest() __attribute__((assume_aligned(q))); // expected-error {{requested alignment is not a power of 2}}
+
+template <int q, int o>
+void *atest2() __attribute__((assume_aligned(q, o))); // expected-error {{requested alignment is not a power of 2}}
+
+void test20() {
+ atest<31>(); // expected-note {{in instantiation of function template specialization 'atest<31>' requested here}}
+ atest<32>();
+
+ atest2<31, 5>(); // expected-note {{in instantiation of function template specialization 'atest2<31, 5>' requested here}}
+ atest2<32, 4>();
+}
+
+// expected-error@+1 {{invalid application of 'sizeof' to a function type}}
+template<typename T> __attribute__((assume_aligned(sizeof(int(T()))))) T *f();
+void test21() {
+ void *p = f<void>(); // expected-note {{in instantiation of function template specialization 'f<void>' requested here}}
+}
+
+// expected-error@+1 {{functional-style cast from 'void' to 'int' is not allowed}}
+template<typename T> __attribute__((assume_aligned(sizeof((int(T())))))) T *g();
+void test23() {
+ void *p = g<void>(); // expected-note {{in instantiation of function template specialization 'g<void>' requested here}}
+}
+
+template <typename T, int o>
+T *atest3() __attribute__((assume_aligned(31, o))); // expected-error {{requested alignment is not a power of 2}}
+
+template <typename T, int o>
+T *atest4() __attribute__((assume_aligned(32, o)));
+
+void test22() {
+ atest3<int, 5>();
+ atest4<int, 5>();
+}
+
+// expected-warning@+1 {{'assume_aligned' attribute only applies to functions and methods}}
+class __attribute__((assume_aligned(32))) x {
+ int y;
+};
+
+// expected-warning@+1 {{'assume_aligned' attribute only applies to return values that are pointers or references}}
+x foo() __attribute__((assume_aligned(32)));
+
+struct s1 {
+ static const int x = 32;
+};
+
+struct s2 {
+ static const int x = 64;
+};
+
+struct s3 {
+ static const int x = 63;
+};
+
+template <typename X>
+void *atest5() __attribute__((assume_aligned(X::x))); // expected-error {{requested alignment is not a power of 2}}
+void test24() {
+ atest5<s1>();
+ atest5<s2>();
+ atest5<s3>(); // expected-note {{in instantiation of function template specialization 'atest5<s3>' requested here}}
+}
+
diff --git a/test/SemaCXX/builtin-assume-aligned.cpp b/test/SemaCXX/builtin-assume-aligned.cpp
new file mode 100644
index 000000000000..48bd8414fc50
--- /dev/null
+++ b/test/SemaCXX/builtin-assume-aligned.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s
+
+int n;
+constexpr int *p = 0;
+// expected-error@+1 {{must be initialized by a constant expression}}
+constexpr int *k = (int *) __builtin_assume_aligned(p, 16, n = 5);
+
+constexpr void *l = __builtin_assume_aligned(p, 16);
+
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{cast from 'void *' is not allowed in a constant expression}}
+constexpr int *c = (int *) __builtin_assume_aligned(p, 16);
+
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{alignment of the base pointee object (4 bytes) is less than the asserted 16 bytes}}
+constexpr void *m = __builtin_assume_aligned(&n, 16);
+
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{offset of the aligned pointer from the base pointee object (-2 bytes) is not a multiple of the asserted 4 bytes}}
+constexpr void *q1 = __builtin_assume_aligned(&n, 4, 2);
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{offset of the aligned pointer from the base pointee object (2 bytes) is not a multiple of the asserted 4 bytes}}
+constexpr void *q2 = __builtin_assume_aligned(&n, 4, -2);
+constexpr void *q3 = __builtin_assume_aligned(&n, 4, 4);
+constexpr void *q4 = __builtin_assume_aligned(&n, 4, -4);
+
+static char ar1[6];
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{alignment of the base pointee object (1 byte) is less than the asserted 16 bytes}}
+constexpr void *r1 = __builtin_assume_aligned(&ar1[2], 16);
+
+static char ar2[6] __attribute__((aligned(32)));
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{offset of the aligned pointer from the base pointee object (2 bytes) is not a multiple of the asserted 16 bytes}}
+constexpr void *r2 = __builtin_assume_aligned(&ar2[2], 16);
+constexpr void *r3 = __builtin_assume_aligned(&ar2[2], 16, 2);
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{offset of the aligned pointer from the base pointee object (1 byte) is not a multiple of the asserted 16 bytes}}
+constexpr void *r4 = __builtin_assume_aligned(&ar2[2], 16, 1);
+
+constexpr int* x = __builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF;
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{value of the aligned pointer (255) is not a multiple of the asserted 32 bytes}}
+constexpr void *s1 = __builtin_assume_aligned(x, 32);
+// expected-error@+2 {{must be initialized by a constant expression}}
+// expected-note@+1 {{value of the aligned pointer (250) is not a multiple of the asserted 32 bytes}}
+constexpr void *s2 = __builtin_assume_aligned(x, 32, 5);
+constexpr void *s3 = __builtin_assume_aligned(x, 32, -1);
+
diff --git a/test/SemaCXX/call-with-static-chain.cpp b/test/SemaCXX/call-with-static-chain.cpp
new file mode 100644
index 000000000000..45fe2ac29472
--- /dev/null
+++ b/test/SemaCXX/call-with-static-chain.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int &f();
+
+struct A {
+ void f();
+};
+
+typedef int I;
+
+void g() {
+ __builtin_call_with_static_chain(f(), f) = 42;
+ __builtin_call_with_static_chain(A().f(), f); // expected-error {{first argument to __builtin_call_with_static_chain must be a non-member call expression}}
+ __builtin_call_with_static_chain((42).~I(), f); // expected-error {{first argument to __builtin_call_with_static_chain must not be a pseudo-destructor call}}
+}
diff --git a/test/SemaCXX/complex-folding.cpp b/test/SemaCXX/complex-folding.cpp
new file mode 100644
index 000000000000..1c2f9c73eb31
--- /dev/null
+++ b/test/SemaCXX/complex-folding.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify
+//
+// Test the constant folding of builtin complex numbers.
+
+static_assert((0.0 + 0.0j) == (0.0 + 0.0j));
+static_assert((0.0 + 0.0j) != (0.0 + 0.0j)); // expected-error {{static_assert}}
+
+static_assert((0.0 + 0.0j) == 0.0);
+static_assert(0.0 == (0.0 + 0.0j));
+static_assert(0.0 == 0.0j);
+static_assert((0.0 + 1.0j) != 0.0);
+static_assert(1.0 != (0.0 + 0.0j));
+static_assert(0.0 != 1.0j);
+
+// Walk around the complex plane stepping between angular differences and
+// equality.
+static_assert((1.0 + 0.0j) == (0.0 + 0.0j)); // expected-error {{static_assert}}
+static_assert((1.0 + 0.0j) == (1.0 + 0.0j));
+static_assert((1.0 + 1.0j) == (1.0 + 0.0j)); // expected-error {{static_assert}}
+static_assert((1.0 + 1.0j) == (1.0 + 1.0j));
+static_assert((0.0 + 1.0j) == (1.0 + 1.0j)); // expected-error {{static_assert}}
+static_assert((0.0 + 1.0j) == (0.0 + 1.0j));
+static_assert((-1.0 + 1.0j) == (0.0 + 1.0j)); // expected-error {{static_assert}}
+static_assert((-1.0 + 1.0j) == (-1.0 + 1.0j));
+static_assert((-1.0 + 0.0j) == (-1.0 + 1.0j)); // expected-error {{static_assert}}
+static_assert((-1.0 + 0.0j) == (-1.0 + 0.0j));
+static_assert((-1.0 - 1.0j) == (-1.0 + 0.0j)); // expected-error {{static_assert}}
+static_assert((-1.0 - 1.0j) == (-1.0 - 1.0j));
+static_assert((0.0 - 1.0j) == (-1.0 - 1.0j)); // expected-error {{static_assert}}
+static_assert((0.0 - 1.0j) == (0.0 - 1.0j));
+static_assert((1.0 - 1.0j) == (0.0 - 1.0j)); // expected-error {{static_assert}}
+static_assert((1.0 - 1.0j) == (1.0 - 1.0j));
+
+// Test basic mathematical folding of both complex and real operands.
+static_assert(((1.0 + 0.5j) + (0.25 - 0.75j)) == (1.25 - 0.25j));
+static_assert(((1.0 + 0.5j) + 0.25) == (1.25 + 0.5j));
+static_assert((1.0 + (0.25 - 0.75j)) == (1.25 - 0.75j));
+
+static_assert(((1.0 + 0.5j) - (0.25 - 0.75j)) == (0.75 + 1.25j));
+static_assert(((1.0 + 0.5j) - 0.25) == (0.75 + 0.5j));
+static_assert((1.0 - (0.25 - 0.75j)) == (0.75 + 0.75j));
+
+static_assert(((1.25 + 0.5j) * (0.25 - 0.75j)) == (0.6875 - 0.8125j));
+static_assert(((1.25 + 0.5j) * 0.25) == (0.3125 + 0.125j));
+static_assert((1.25 * (0.25 - 0.75j)) == (0.3125 - 0.9375j));
+
+static_assert(((1.25 + 0.5j) / (0.25 - 0.75j)) == (-0.1 + 1.7j));
+static_assert(((1.25 + 0.5j) / 0.25) == (5.0 + 2.0j));
+static_assert((1.25 / (0.25 - 0.75j)) == (0.5 + 1.5j));
+
+// Test that infinities are preserved, don't turn into NaNs, and do form zeros
+// when the divisor.
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * 1.0)) == 1);
+static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * 1.0)) == 1);
+static_assert(__builtin_isinf_sign(__real__(1.0 * (__builtin_inf() + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__imag__(1.0 * (1.0 + __builtin_inf() * 1.0j))) == 1);
+
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * (1.0 + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (__builtin_inf() + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * (__builtin_inf() + 1.0j))) == 1);
+
+static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == -1);
+static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1);
+static_assert(__builtin_isinf_sign(__imag__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == 1);
+
+static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1);
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + __builtin_inf() * 1.0j) * (__builtin_inf() + __builtin_inf() * 1.0j))) == -1);
+
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (1.0 + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1);
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 1.0)) == 1);
+static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / 1.0)) == 1);
+static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 1.0)) == 1);
+
+static_assert(((1.0 + 1.0j) / (__builtin_inf() + 1.0j)) == (0.0 + 0.0j));
+static_assert(((1.0 + 1.0j) / (1.0 + __builtin_inf() * 1.0j)) == (0.0 + 0.0j));
+static_assert(((1.0 + 1.0j) / (__builtin_inf() + __builtin_inf() * 1.0j)) == (0.0 + 0.0j));
+static_assert(((1.0 + 1.0j) / __builtin_inf()) == (0.0 + 0.0j));
+
+static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / (0.0 + 0.0j))) == 1);
+static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1);
+
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (0.0 + 0.0j))) == 1);
+static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1);
+static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1);
+static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 0.0)) == 1);
+static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / 0.0)) == 1);
+static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 0.0)) == 1);
diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp
index cb9937c50d50..330e18661b19 100644
--- a/test/SemaCXX/const-cast.cpp
+++ b/test/SemaCXX/const-cast.cpp
@@ -64,3 +64,6 @@ short *bad_const_cast_test(char const *volatile *const volatile *var)
(void)const_cast<int&&>(0); // expected-error {{const_cast from rvalue to reference type 'int &&'}} expected-warning {{C++11}}
return **var3;
}
+
+template <typename T>
+char *PR21845() { return const_cast<char *>((void)T::x); } // expected-error {{const_cast from 'void' to 'char *' is not allowed}}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 09d93fa73af1..14c0ae320d77 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -95,11 +95,13 @@ namespace TemplateArgumentConversion {
}
namespace CaseStatements {
+ int x;
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;
+ case __builtin_constant_p(true) ? (__SIZE_TYPE__)&x : 0:; // expected-error {{constant}}
}
}
}
@@ -602,7 +604,7 @@ 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 B { int n; int m; } constexpr b = { 0, b.n };
struct C {
constexpr C(C *this_) : m(42), n(this_->m) {} // ok
int m, n;
@@ -1177,7 +1179,7 @@ namespace ExternConstexpr {
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}}
+ constexpr int k; // expected-error {{default initialization of an object of const type}} expected-note{{add an explicit initializer to initialize 'k'}}
}
}
@@ -1326,6 +1328,49 @@ namespace MutableMembers {
struct C { B b; };
constexpr C c[3] = {};
constexpr int k = c[1].b.a.n; // expected-error {{constant expression}} expected-note {{mutable}}
+
+ struct D { int x; mutable int y; }; // expected-note {{here}}
+ constexpr D d1 = { 1, 2 };
+ int l = ++d1.y;
+ constexpr D d2 = d1; // expected-error {{constant}} expected-note {{mutable}} expected-note {{in call}}
+
+ struct E {
+ union {
+ int a;
+ mutable int b; // expected-note {{here}}
+ };
+ };
+ constexpr E e1 = {{1}};
+ constexpr E e2 = e1; // expected-error {{constant}} expected-note {{mutable}} expected-note {{in call}}
+
+ struct F {
+ union U { };
+ mutable U u;
+ struct X { };
+ mutable X x;
+ struct Y : X { X x; U u; };
+ mutable Y y;
+ int n;
+ };
+ // This is OK; we don't actually read any mutable state here.
+ constexpr F f1 = {};
+ constexpr F f2 = f1;
+
+ struct G {
+ struct X {};
+ union U { X a; };
+ mutable U u; // expected-note {{here}}
+ };
+ constexpr G g1 = {};
+ constexpr G g2 = g1; // expected-error {{constant}} expected-note {{mutable}} expected-note {{in call}}
+ constexpr G::U gu1 = {};
+ constexpr G::U gu2 = gu1;
+
+ union H {
+ mutable G::X gx; // expected-note {{here}}
+ };
+ constexpr H h1 = {};
+ constexpr H h2 = h1; // expected-error {{constant}} expected-note {{mutable}} expected-note {{in call}}
}
namespace Fold {
@@ -1443,7 +1488,7 @@ namespace InvalidClasses {
namespace NamespaceAlias {
constexpr int f() {
- namespace NS = NamespaceAlias; // expected-warning {{use of this statement in a constexpr function is a C++1y extension}}
+ namespace NS = NamespaceAlias; // expected-warning {{use of this statement in a constexpr function is a C++14 extension}}
return &NS::f != nullptr;
}
}
@@ -1568,7 +1613,8 @@ namespace TypeId {
A &g();
constexpr auto &x = typeid(f());
constexpr auto &y = typeid(g()); // expected-error{{constant expression}} \
- // expected-note{{typeid applied to expression of polymorphic type 'TypeId::A' is not allowed in a constant expression}}
+ // expected-note{{typeid applied to expression of polymorphic type 'TypeId::A' is not allowed in a constant expression}} \
+ // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
}
namespace PR14203 {
@@ -1667,6 +1713,9 @@ namespace InitializerList {
return sum(ints.begin(), ints.end());
}
static_assert(sum({1, 2, 3, 4, 5}) == 15, "");
+
+ static_assert(*std::initializer_list<int>{1, 2, 3}.begin() == 1, "");
+ static_assert(std::initializer_list<int>{1, 2, 3}.begin()[2] == 3, "");
}
namespace StmtExpr {
@@ -1700,7 +1749,7 @@ namespace VirtualFromBase {
template <typename T> struct X : T {
constexpr X() {}
double d = 0.0;
- constexpr int f() { return sizeof(T); } // expected-warning {{will not be implicitly 'const' in C++1y}}
+ constexpr int f() { return sizeof(T); } // expected-warning {{will not be implicitly 'const' in C++14}}
};
// Virtual f(), not OK.
@@ -1715,17 +1764,17 @@ namespace VirtualFromBase {
}
namespace ConstexprConstructorRecovery {
- class X {
- public:
- enum E : short {
- headers = 0x1,
- middlefile = 0x2,
- choices = 0x4
- };
- constexpr X() noexcept {};
- protected:
+ class X {
+ public:
+ enum E : short {
+ headers = 0x1,
+ middlefile = 0x2,
+ choices = 0x4
+ };
+ constexpr X() noexcept {};
+ protected:
E val{0}; // expected-error {{cannot initialize a member subobject of type 'ConstexprConstructorRecovery::X::E' with an rvalue of type 'int'}}
- };
+ };
constexpr X x{};
}
@@ -1799,8 +1848,9 @@ namespace ZeroSizeTypes {
namespace BadDefaultInit {
template<int N> struct X { static const int n = N; };
- struct A { // expected-note {{subexpression}}
- int k = X<A().k>::n; // expected-error {{defaulted default constructor of 'A' cannot be used}} expected-error {{not a constant expression}} expected-note {{in call to 'A()'}}
+ struct A {
+ int k = // expected-error {{cannot use defaulted default constructor of 'A' within the class outside of member functions because 'k' has an initializer}}
+ X<A().k>::n; // expected-error {{not a constant expression}} expected-note {{implicit default constructor for 'BadDefaultInit::A' first required here}}
};
// FIXME: The "constexpr constructor must initialize all members" diagnostic
@@ -1892,3 +1942,45 @@ namespace PR19010 {
};
void test() { constexpr Test t; }
}
+
+void PR21327(int a, int b) {
+ static_assert(&a + 1 != &b, ""); // expected-error {{constant expression}}
+}
+
+namespace EmptyClass {
+ struct E1 {} e1;
+ union E2 {} e2; // expected-note {{here}}
+ struct E3 : E1 {} e3;
+
+ // The defaulted copy constructor for an empty class does not read any
+ // members. The defaulted copy constructor for an empty union reads the
+ // object representation.
+ constexpr E1 e1b(e1);
+ constexpr E2 e2b(e2); // expected-error {{constant expression}} expected-note{{read of non-const}} expected-note {{in call}}
+ constexpr E3 e3b(e3);
+}
+
+namespace PR21786 {
+ extern void (*start[])();
+ extern void (*end[])();
+ static_assert(&start != &end, ""); // expected-error {{constant expression}}
+ static_assert(&start != nullptr, "");
+
+ struct Foo;
+ struct Bar {
+ static const Foo x;
+ static const Foo y;
+ };
+ static_assert(&Bar::x != nullptr, "");
+ static_assert(&Bar::x != &Bar::y, "");
+}
+
+namespace PR21859 {
+ constexpr int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}}
+ constexpr int Var = Fun(); // expected-error {{constexpr variable 'Var' must be initialized by a constant expression}}
+}
+
+struct InvalidRedef {
+ int f; // expected-note{{previous definition is here}}
+ constexpr int f(void); // expected-error{{redefinition of 'f'}} expected-warning{{will not be implicitly 'const'}}
+};
diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp
index 521526ddba44..e8925f3f84aa 100644
--- a/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -719,8 +719,7 @@ namespace deduced_return_type {
namespace modify_temporary_during_construction {
struct A { int &&temporary; int x; int y; };
constexpr int f(int &r) { r *= 9; return r - 12; }
- // FIXME: The 'uninitialized' warning here is bogus.
- constexpr A a = { 6, f(a.temporary), a.temporary }; // expected-warning {{uninitialized}} expected-note {{temporary created here}}
+ constexpr A a = { 6, f(a.temporary), a.temporary }; // expected-note {{temporary created here}}
static_assert(a.x == 42, "");
static_assert(a.y == 54, "");
constexpr int k = a.temporary++; // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}}
@@ -911,3 +910,31 @@ namespace PR17331 {
constexpr int ARR[] = { 1, 2, 3, 4, 5 };
static_assert(sum(ARR) == 15, "");
}
+
+namespace EmptyClass {
+ struct E1 {} e1;
+ union E2 {} e2; // expected-note 4{{here}}
+ struct E3 : E1 {} e3;
+
+ template<typename E>
+ constexpr int f(E &a, int kind) {
+ switch (kind) {
+ case 0: { E e(a); return 0; } // expected-note {{read}} expected-note {{in call}}
+ case 1: { E e(static_cast<E&&>(a)); return 0; } // expected-note {{read}} expected-note {{in call}}
+ case 2: { E e; e = a; return 0; } // expected-note {{read}} expected-note {{in call}}
+ case 3: { E e; e = static_cast<E&&>(a); return 0; } // expected-note {{read}} expected-note {{in call}}
+ }
+ }
+ constexpr int test1 = f(e1, 0);
+ constexpr int test2 = f(e2, 0); // expected-error {{constant expression}} expected-note {{in call}}
+ constexpr int test3 = f(e3, 0);
+ constexpr int test4 = f(e1, 1);
+ constexpr int test5 = f(e2, 1); // expected-error {{constant expression}} expected-note {{in call}}
+ constexpr int test6 = f(e3, 1);
+ constexpr int test7 = f(e1, 2);
+ constexpr int test8 = f(e2, 2); // expected-error {{constant expression}} expected-note {{in call}}
+ constexpr int test9 = f(e3, 2);
+ constexpr int testa = f(e1, 3);
+ constexpr int testb = f(e2, 3); // expected-error {{constant expression}} expected-note {{in call}}
+ constexpr int testc = f(e3, 3);
+}
diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp
index 9ad11290190f..3657c18ddbac 100644
--- a/test/SemaCXX/constexpr-value-init.cpp
+++ b/test/SemaCXX/constexpr-value-init.cpp
@@ -14,7 +14,7 @@ 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 b1; // expected-error {{without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'b1'}}
constexpr B b2 = B(); // ok
static_assert(b2.a.a == 1, "");
static_assert(b2.a.b == 2, "");
@@ -23,9 +23,9 @@ struct C {
int c;
};
struct D : C { int d; };
-constexpr C c1; // expected-error {{requires a user-provided default constructor}}
+constexpr C c1; // expected-error {{without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 'c1'}}
constexpr C c2 = C(); // ok
-constexpr D d1; // expected-error {{requires a user-provided default constructor}}
+constexpr D d1; // expected-error {{without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 'd1'}}
constexpr D d2 = D(); // ok with DR1452
static_assert(D().c == 0, "");
static_assert(D().d == 0, "");
diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp
index 40ac33b8eb0d..077e4d9f3cce 100644
--- a/test/SemaCXX/conversion-function.cpp
+++ b/test/SemaCXX/conversion-function.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wbind-to-temporary-copy -verify %s
class X {
public:
operator bool();
@@ -172,12 +172,10 @@ namespace source_locations {
namespace crazy_declarators {
struct A {
- (&operator bool())(); // expected-error {{must use a typedef to declare a conversion to 'bool (&)()'}}
-
- // FIXME: This diagnostic is misleading (the correct spelling
- // would be 'operator int*'), but it's a corner case of a
- // rarely-used syntax extension.
- *operator int(); // expected-error {{must use a typedef to declare a conversion to 'int *'}}
+ (&operator bool())(); // expected-error {{use a typedef to declare a conversion to 'bool (&)()'}}
+ *operator int(); // expected-error {{put the complete type after 'operator'}}
+ // No suggestion of using a typedef here; that's not possible.
+ template<typename T> (&operator T())(); // expected-error-re {{cannot specify any part of a return type in the declaration of a conversion function{{$}}}}
};
}
diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp
index 852bbba7efa1..b8f0e076a2bc 100644
--- a/test/SemaCXX/conversion.cpp
+++ b/test/SemaCXX/conversion.cpp
@@ -90,6 +90,18 @@ void test3() {
;
do ;
while(NULL_COND(true));
+
+#define NULL_WRAPPER NULL_COND(false)
+ if (NULL_WRAPPER)
+ ;
+ while (NULL_WRAPPER)
+ ;
+ for (; NULL_WRAPPER;)
+ ;
+ do
+ ;
+ while (NULL_WRAPPER);
+
int *ip = NULL;
int (*fp)() = NULL;
struct foo {
@@ -137,3 +149,11 @@ namespace test6 {
return NULL;
}
}
+
+namespace test7 {
+ bool fun() {
+ bool x = nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
+ if (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
+ return nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
+ }
+}
diff --git a/test/SemaCXX/crashes.cpp b/test/SemaCXX/crashes.cpp
index 1570d12eeb2f..6ae476f7080c 100644
--- a/test/SemaCXX/crashes.cpp
+++ b/test/SemaCXX/crashes.cpp
@@ -231,3 +231,9 @@ namespace pr16989 {
};
void C2::f() {}
}
+
+namespace pr20660 {
+ appendList(int[]...); // expected-error {{C++ requires a type specifier for all declarations}}
+ appendList(int[]...) { } // expected-error {{C++ requires a type specifier for all declarations}}
+}
+
diff --git a/test/SemaCXX/cxx-deprecated.cpp b/test/SemaCXX/cxx-deprecated.cpp
new file mode 100644
index 000000000000..47accd4ae1d5
--- /dev/null
+++ b/test/SemaCXX/cxx-deprecated.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
+
+namespace [[deprecated]] {} // expected-warning {{'deprecated' attribute on anonymous namespace ignored}}
+
+namespace [[deprecated]] N { // expected-note 4{{'N' has been explicitly marked deprecated here}}
+ int X;
+ int Y = X; // Ok
+ int f();
+}
+
+int N::f() { // Ok
+ return Y; // Ok
+}
+
+void f() {
+ int Y = N::f(); // expected-warning {{'N' is deprecated}}
+ using N::X; // expected-warning {{'N' is deprecated}}
+ int Z = X; //Ok
+}
+
+void g() {
+ using namespace N; // expected-warning {{'N' is deprecated}}
+ int Z = Y; // Ok
+}
+
+namespace M = N; // expected-warning {{'N' is deprecated}}
diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp
index a58a7f875cdb..bcf0cf11dc18 100644
--- a/test/SemaCXX/cxx0x-compat.cpp
+++ b/test/SemaCXX/cxx0x-compat.cpp
@@ -41,9 +41,15 @@ void h(size_t foo, size_t bar) {
#define _x + 1
char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}}
+template<int ...N> int f() { // expected-warning {{C++11 extension}}
+ return (N + ...); // expected-warning {{C++1z extension}}
+}
+
#else
-auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++1y}}
+auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++14}}
static_assert(true); // expected-warning {{incompatible with C++ standards before C++1z}}
+template<int ...N> int f() { return (N + ...); } // expected-warning {{incompatible with C++ standards before C++1z}}
+
#endif
diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 07a784226640..375cf4a1ac5c 100644
--- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -25,7 +25,7 @@ void fn1 () {
non_const_copy ncc2 = ncc;
ncc = ncc2;
const non_const_copy cncc{};
- const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' requires a user-provided default constructor}}
+ const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'cncc1'}}
non_const_copy ncc3 = cncc; // expected-error {{no matching}}
ncc = cncc; // expected-error {{no viable overloaded}}
};
diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp
index 9096c8a1c2d5..d1a9ed30076f 100644
--- a/test/SemaCXX/cxx0x-initializer-references.cpp
+++ b/test/SemaCXX/cxx0x-initializer-references.cpp
@@ -118,3 +118,9 @@ namespace inner_init {
F f2 { { 0 } }; // expected-error {{chosen constructor is explicit}}
F f3 { { { 0 } } }; // expected-error {{chosen constructor is explicit}}
}
+
+namespace PR20844 {
+ struct A {};
+ struct B { operator A&(); } b;
+ A &a{b}; // expected-error {{excess elements}} expected-note {{in initialization of temporary of type 'PR20844::A'}}
+}
diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp
index f7bfc1123a7f..5604374c5610 100644
--- a/test/SemaCXX/cxx11-ast-print.cpp
+++ b/test/SemaCXX/cxx11-ast-print.cpp
@@ -15,7 +15,7 @@ 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();
+// CHECK: template <char ...> const char *operator "" _fritz();
template<char...> const char *operator"" _fritz();
// CHECK: const char *p1 = "bar1"_foo;
diff --git a/test/SemaCXX/cxx11-thread-unsupported.cpp b/test/SemaCXX/cxx11-thread-unsupported.cpp
new file mode 100644
index 000000000000..d3fcf82ef415
--- /dev/null
+++ b/test/SemaCXX/cxx11-thread-unsupported.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-apple-macosx10.6 -verify %s
+
+void f() {
+ thread_local int x; // expected-error {{thread-local storage is not supported for the current target}}
+}
diff --git a/test/SemaCXX/cxx1y-constexpr-not-const.cpp b/test/SemaCXX/cxx1y-constexpr-not-const.cpp
index 3f100b8b691e..071b39c7fb39 100644
--- a/test/SemaCXX/cxx1y-constexpr-not-const.cpp
+++ b/test/SemaCXX/cxx1y-constexpr-not-const.cpp
@@ -14,5 +14,5 @@ struct X {
// expected-error@6 {{non-constexpr declaration of 'f' follows constexpr declaration}}
// expected-note@5 {{previous}}
#else
-// expected-warning@5 {{'constexpr' non-static member function will not be implicitly 'const' in C++1y; add 'const' to avoid a change in behavior}}
+// expected-warning@5 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}}
#endif
diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp
index 60864165954a..50e0cf79c57b 100644
--- a/test/SemaCXX/cxx1y-deduced-return-type.cpp
+++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp
@@ -483,3 +483,16 @@ namespace OverloadedOperators {
int g = a - a;
}
}
+
+namespace TrailingReturnTypeForConversionOperator {
+ struct X {
+ operator auto() -> int { return 0; } // expected-error {{cannot specify any part of a return type in the declaration of a conversion function; put the complete type after 'operator'}}
+ } x;
+ int k = x.operator auto();
+
+ struct Y {
+ operator auto() -> int & { // expected-error {{cannot specify}}
+ return 0; // expected-error {{cannot bind to}}
+ }
+ };
+};
diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp
index dc8574825dd9..90ecf6904e54 100644
--- a/test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp
@@ -859,11 +859,13 @@ namespace ns1 {
struct X1 {
struct X2 {
enum { E = [](auto i) { return i; }(3) }; //expected-error{{inside of a constant expression}}\
- //expected-error{{not an integral constant}}
+ //expected-error{{not an integral constant}}\
+ //expected-note{{non-literal type}}
int L = ([] (int i) { return i; })(2);
void foo(int i = ([] (int i) { return i; })(2)) { }
int B : ([](int i) { return i; })(3); //expected-error{{inside of a constant expression}}\
- //expected-error{{not an integral constant}}
+ //expected-error{{not an integral constant}}\
+ //expected-note{{non-literal type}}
int arr[([](int i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
//expected-error{{must have a constant size}}
int (*fp)(int) = [](int i) { return i; };
@@ -871,9 +873,10 @@ struct X1 {
int L2 = ([](auto i) { return i; })(2);
void fooG(int i = ([] (auto i) { return i; })(2)) { }
int BG : ([](auto i) { return i; })(3); //expected-error{{inside of a constant expression}} \
- //expected-error{{not an integral constant}}
+ //expected-error{{not an integral constant}}\
+ //expected-note{{non-literal type}}
int arrG[([](auto i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
- //expected-error{{must have a constant size}}
+ //expected-error{{must have a constant size}}
int (*fpG)(int) = [](auto i) { return i; };
void fooptrG(int (*fp)(char) = [](auto c) { return 0; }) { }
};
@@ -887,14 +890,16 @@ struct X1 {
int L = ([] (T i) { return i; })(2);
void foo(int i = ([] (int i) { return i; })(2)) { }
int B : ([](T i) { return i; })(3); //expected-error{{inside of a constant expression}}\
- //expected-error{{not an integral constant}}
+ //expected-error{{not an integral constant}}\
+ //expected-note{{non-literal type}}
int arr[([](T i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\
- //expected-error{{must have a constant size}}
+ //expected-error{{must have a constant size}}
int (*fp)(T) = [](T i) { return i; };
void fooptr(T (*fp)(char) = [](char c) { return 0; }) { }
int L2 = ([](auto i) { return i; })(2);
void fooG(T i = ([] (auto i) { return i; })(2)) { }
- int BG : ([](auto i) { return i; })(3); //expected-error{{not an integral constant}}
+ int BG : ([](auto i) { return i; })(3); //expected-error{{not an integral constant}}\
+ //expected-note{{non-literal type}}
int arrG[([](auto i) { return i; })(3)]; //expected-error{{must have a constant size}}
int (*fpG)(T) = [](auto i) { return i; };
void fooptrG(T (*fp)(char) = [](auto c) { return 0; }) { }
@@ -913,3 +918,16 @@ int run2 = x2.fooG3();
} //end ns inclass_lambdas_within_nested_classes
+
+namespace pr21684_disambiguate_auto_followed_by_ellipsis_no_id {
+int a = [](auto ...) { return 0; }();
+}
+
+namespace PR22117 {
+ int x = [](auto) {
+ return [](auto... run_args) {
+ using T = int(decltype(run_args)...);
+ return 0;
+ };
+ }(0)(0);
+}
diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 1e5e834b6d2a..93a2095c9b8c 100644
--- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -58,13 +58,13 @@ namespace out_of_line {
template<typename T, typename T0> static CONST T b = T(100);
template<typename T> static CONST T b<T,int>;
};
- template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}}
+ template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'a<int, char>'}}
template<typename T> CONST T B4::a<T,int>;
template CONST int B4::a<int,char>; // expected-note {{in instantiation of}}
template CONST int B4::a<int,int>;
template<typename T, typename T0> CONST T B4::b;
- template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}}
+ template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'b<int, int>'}}
template CONST int B4::b<int,char>;
template CONST int B4::b<int,int>; // expected-note {{in instantiation of}}
}
@@ -321,3 +321,9 @@ namespace in_nested_classes {
// TODO:
}
+namespace bitfield {
+struct S {
+ template <int I>
+ static int f : I; // expected-error {{static member 'f' cannot be a bit-field}}
+};
+}
diff --git a/test/SemaCXX/cxx98-compat-flags.cpp b/test/SemaCXX/cxx98-compat-flags.cpp
index 6dc24be6bbfa..f90ad345e975 100644
--- a/test/SemaCXX/cxx98-compat-flags.cpp
+++ b/test/SemaCXX/cxx98-compat-flags.cpp
@@ -1,5 +1,5 @@
-// 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
+// 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-pedantic -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() {
diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp
index b74dcb4238ae..38bc341e83ce 100644
--- a/test/SemaCXX/cxx98-compat-pedantic.cpp
+++ b/test/SemaCXX/cxx98-compat-pedantic.cpp
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s -DCXX1Y2
// 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
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Werror %s -DCXX98
// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-compat-pedantic -verify %s -Wno-c++98-c++11-compat-pedantic -DCXX1Y2
@@ -49,5 +49,32 @@ unsigned long long ull1 = // expected-warning {{'long long' is incompatible with
int k = 0b1001;
#ifdef CXX1Y
-// expected-warning@-2 {{binary integer literals are incompatible with C++ standards before C++1y}}
+// expected-warning@-2 {{binary integer literals are incompatible with C++ standards before C++14}}
#endif
+
+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}}
+#if !CXX98
+ 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}}
+#endif
+ 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.cpp b/test/SemaCXX/cxx98-compat.cpp
index 96af95425aec..029e90989628 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-compat -verify %s -DCXX1YCOMPAT
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -Wc++98-compat -verify %s -DCXX14COMPAT
namespace std {
struct type_info;
@@ -225,31 +225,6 @@ template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expecte
int SFINAEAccessControl(...) { return 0; }
int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember()); // expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}}
-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-provided default constructor}}
@@ -286,18 +261,18 @@ template<typename T> void EnumNNSFn() {
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}}
+ goto DirectJump; // expected-warning {{jump from this goto statement to its label is incompatible with 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}}
+ goto *Table[n]; // expected-warning {{jump from this indirect goto statement to one of its possible targets is incompatible with C++98}}
TrivialButNonPOD tnp2; // expected-note {{jump bypasses initialization of non-POD variable}}
-Later: // expected-note {{possible target of indirect goto}}
+Later: // expected-note {{possible target of indirect goto statement}}
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}}
+ default: // expected-warning {{jump from switch statement to this case label is incompatible with C++98}}
return;
}
}
@@ -373,10 +348,10 @@ namespace rdar11736429 {
}
template<typename T> T var = T(10);
-#ifdef CXX1YCOMPAT
-// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}}
+#ifdef CXX14COMPAT
+// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}}
#else
-// expected-warning@-4 {{variable templates are a C++1y extension}}
+// expected-warning@-4 {{variable templates are a C++14 extension}}
#endif
// No diagnostic for specializations of variable templates; we will have
@@ -388,27 +363,27 @@ float fvar = var<float>;
class A {
template<typename T> static T var = T(10);
-#ifdef CXX1YCOMPAT
-// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}}
+#ifdef CXX14COMPAT
+// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}}
#else
-// expected-warning@-4 {{variable templates are a C++1y extension}}
+// expected-warning@-4 {{variable templates are a C++14 extension}}
#endif
- template<typename T> static T* var<T*> = new T();
+ template<typename T> static T* var<T*> = new T();
};
struct B { template<typename T> static T v; };
-#ifdef CXX1YCOMPAT
-// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}}
+#ifdef CXX14COMPAT
+// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}}
#else
-// expected-warning@-4 {{variable templates are a C++1y extension}}
+// expected-warning@-4 {{variable templates are a C++14 extension}}
#endif
template<typename T> T B::v = T();
-#ifdef CXX1YCOMPAT
-// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}}
+#ifdef CXX14COMPAT
+// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}}
#else
-// expected-warning@-4 {{variable templates are a C++1y extension}}
+// expected-warning@-4 {{variable templates are a C++14 extension}}
#endif
template<typename T> T* B::v<T*> = new T();
@@ -416,6 +391,6 @@ template<> int B::v<int> = 10;
template int B::v<int>;
float fsvar = B::v<float>;
-#ifdef CXX1YCOMPAT
-int digit_seps = 123'456; // expected-warning {{digit separators are incompatible with C++ standards before C++1y}}
+#ifdef CXX14COMPAT
+int digit_seps = 123'456; // expected-warning {{digit separators are incompatible with C++ standards before C++14}}
#endif
diff --git a/test/SemaCXX/decl-init-ref.cpp b/test/SemaCXX/decl-init-ref.cpp
index 2d0c9cb4ffbe..42b9286852c7 100644
--- a/test/SemaCXX/decl-init-ref.cpp
+++ b/test/SemaCXX/decl-init-ref.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-uninitialized
struct A {};
diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp
index eb6c8507eddc..a4b68cdbc7d4 100644
--- a/test/SemaCXX/decl-microsoft-call-conv.cpp
+++ b/test/SemaCXX/decl-microsoft-call-conv.cpp
@@ -10,6 +10,7 @@ void free_func_default(); // expected-note 2 {{previous declaration i
void __cdecl free_func_cdecl(); // expected-note 2 {{previous declaration is here}}
void __stdcall free_func_stdcall(); // expected-note 2 {{previous declaration is here}}
void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}}
+void __vectorcall free_func_vectorcall(); // expected-note 2 {{previous declaration is here}}
void __cdecl free_func_default();
void __stdcall free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
@@ -27,6 +28,10 @@ void __cdecl free_func_fastcall(); // expected-error {{function declared 'cde
void __stdcall free_func_fastcall(); // expected-error {{function declared 'stdcall' here was previously declared 'fastcall'}}
void free_func_fastcall();
+void __cdecl free_func_vectorcall(); // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}
+void __stdcall free_func_vectorcall(); // expected-error {{function declared 'stdcall' here was previously declared 'vectorcall'}}
+void free_func_vectorcall();
+
// Overloaded functions may have different calling conventions
void __fastcall free_func_default(int);
void __cdecl free_func_default(int *);
@@ -45,6 +50,8 @@ struct S {
void __cdecl member_cdecl2(); // expected-note {{previous declaration is here}}
void __thiscall member_thiscall1();
void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}}
+ void __vectorcall member_vectorcall1();
+ void __vectorcall member_vectorcall2(); // expected-note {{previous declaration is here}}
// Typedefs carrying the __cdecl convention are adjusted to __thiscall.
void_fun_t member_typedef_default; // expected-note {{previous declaration is here}}
@@ -83,6 +90,9 @@ void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thi
void S::member_thiscall1() {}
void __cdecl S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}}
+void S::member_vectorcall1() {}
+void __cdecl S::member_vectorcall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}
+
void S::static_member_default1() {}
void __cdecl S::static_member_default2() {}
void __stdcall S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
@@ -143,9 +153,10 @@ void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attri
void multi_attribute(int x) { __builtin_unreachable(); }
+// expected-error@+3 {{vectorcall and cdecl attributes are not compatible}}
// expected-error@+2 {{stdcall and cdecl attributes are not compatible}}
// expected-error@+1 {{fastcall and cdecl attributes are not compatible}}
-void __cdecl __cdecl __stdcall __cdecl __fastcall multi_cc(int x);
+void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x);
template <typename T> void __stdcall StdcallTemplate(T) {}
template <> void StdcallTemplate<int>(int) {}
diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp
index 23466fac62aa..6001001b11eb 100644
--- a/test/SemaCXX/default1.cpp
+++ b/test/SemaCXX/default1.cpp
@@ -65,3 +65,9 @@ int i2() {
int pr20055_f(int x = 0, int y = UNDEFINED); // expected-error{{use of undeclared identifier}}
int pr20055_v = pr20055_f(0);
+
+void PR20769() { void PR20769(int = 1); }
+void PR20769(int = 2);
+
+void PR20769_b(int = 1);
+void PR20769_b() { void PR20769_b(int = 2); }
diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
index 16260449d4be..c4d40b4280e9 100644
--- a/test/SemaCXX/default2.cpp
+++ b/test/SemaCXX/default2.cpp
@@ -122,3 +122,9 @@ class XX {
void A(int length = -1 ) { }
void B() { A(); }
};
+
+template <int I = (1 * I)> struct S {}; // expected-error-re {{use of undeclared identifier 'I'{{$}}}}
+S<1> s;
+
+template <int I1 = I2, int I2 = 1> struct T {}; // expected-error-re {{use of undeclared identifier 'I2'{{$}}}}
+T<0, 1> t;
diff --git a/test/SemaCXX/dependent-noexcept-unevaluated.cpp b/test/SemaCXX/dependent-noexcept-unevaluated.cpp
index 0a3a8bb250bc..fad8d0918d53 100644
--- a/test/SemaCXX/dependent-noexcept-unevaluated.cpp
+++ b/test/SemaCXX/dependent-noexcept-unevaluated.cpp
@@ -23,7 +23,7 @@ struct array
{
T data[N];
- void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>())));
+ void swap(array& a) noexcept(noexcept(::swap(declval<T&>(), declval<T&>())));
};
struct DefaultOnly
@@ -38,3 +38,4 @@ int main()
{
array<DefaultOnly, 1> a, b;
}
+
diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp
index 2fe6d59861ac..5fcf2130d36f 100644
--- a/test/SemaCXX/deprecated.cpp
+++ b/test/SemaCXX/deprecated.cpp
@@ -35,7 +35,7 @@ void stuff() {
#endif
}
-struct S { int n; };
+struct S { int n; void operator+(int); };
struct T : private S {
S::n;
#if __cplusplus < 201103L
@@ -43,6 +43,12 @@ struct T : private S {
#else
// expected-error@-4 {{ISO C++11 does not allow access declarations; use using declarations instead}}
#endif
+ S::operator+;
+#if __cplusplus < 201103L
+ // expected-warning@-2 {{access declarations are deprecated; use using declarations instead}}
+#else
+ // expected-error@-4 {{ISO C++11 does not allow access declarations; use using declarations instead}}
+#endif
};
#if __cplusplus >= 201103L
diff --git a/test/SemaCXX/devirtualize-vtable-marking.cpp b/test/SemaCXX/devirtualize-vtable-marking.cpp
new file mode 100644
index 000000000000..fc3e8ce7704c
--- /dev/null
+++ b/test/SemaCXX/devirtualize-vtable-marking.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+template <typename T> struct OwnPtr {
+ T *p;
+ ~OwnPtr() {
+ // expected-error@+1 {{invalid application of 'sizeof'}}
+ static_assert(sizeof(T) > 0, "incomplete T");
+ delete p;
+ }
+};
+
+namespace use_vtable_for_vcall {
+struct Incomplete; // expected-note {{forward declaration}}
+struct A {
+ virtual ~A() {}
+ virtual void m() {}
+};
+struct B : A { // expected-note {{in instantiation}}
+ B();
+ virtual void m() { }
+ virtual void m2() { static_cast<A *>(this)->m(); }
+ OwnPtr<Incomplete> m_sqlError;
+};
+
+B *f() {
+ return new B();
+}
+}
+
+namespace dont_mark_qualified_vcall {
+struct Incomplete;
+struct A {
+ virtual ~A() {}
+ virtual void m() {}
+};
+struct B : A {
+ B();
+ // Previously we would mark B's vtable referenced to devirtualize this call to
+ // A::m, even though it's not a virtual call.
+ virtual void m() { A::m(); }
+ OwnPtr<Incomplete> m_sqlError;
+};
+
+B *f() {
+ return new B();
+}
+}
diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp
index 668553b5c500..5d002ac81e5c 100644
--- a/test/SemaCXX/dllexport.cpp
+++ b/test/SemaCXX/dllexport.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 -DMS %s
-// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y -DMS %s
-// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y %s
-// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 -Wunsupported-dll-base-class-template -DMS %s
+// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y -Wunsupported-dll-base-class-template -DMS %s
+// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y -Wunsupported-dll-base-class-template %s
+// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 -Wunsupported-dll-base-class-template %s
// Helper structs to make templates more expressive.
struct ImplicitInst_Exported {};
@@ -69,6 +69,9 @@ namespace ns { __declspec(dllexport) int ExternalGlobal; }
__declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}}
__declspec(dllexport) auto ExternalAutoTypeGlobal = External();
+// Thread local variables are invalid.
+__declspec(dllexport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllexport'}}
+
// Export in local scope.
void functionScope() {
__declspec(dllexport) int LocalVarDecl; // expected-error{{'LocalVarDecl' must have external linkage when declared 'dllexport'}}
@@ -324,6 +327,10 @@ template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exp
// Classes
//===----------------------------------------------------------------------===//
+namespace {
+ struct __declspec(dllexport) AnonymousClass {}; // expected-error{{(anonymous namespace)::AnonymousClass' must have external linkage when declared 'dllexport'}}
+}
+
class __declspec(dllexport) ClassDecl;
class __declspec(dllexport) ClassDef {};
@@ -337,6 +344,49 @@ template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemp
template <typename T> struct ExpliciallySpecializedClassTemplate {};
template <> struct __declspec(dllexport) ExpliciallySpecializedClassTemplate<int> { void f() {} };
+// Don't instantiate class members of implicitly instantiated templates, even if they are exported.
+struct IncompleteType;
+template <typename T> struct __declspec(dllexport) ImplicitlyInstantiatedExportedTemplate {
+ int f() { return sizeof(T); } // no-error
+};
+ImplicitlyInstantiatedExportedTemplate<IncompleteType> implicitlyInstantiatedExportedTemplate;
+
+// Don't instantiate class members of templates with explicit instantiation declarations, even if they are exported.
+struct IncompleteType2;
+template <typename T> struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl {
+ int f() { return sizeof(T); } // no-error
+};
+extern template struct ExportedTemplateWithExplicitInstantiationDecl<IncompleteType2>;
+
+// Instantiate class members for explicitly instantiated exported templates.
+struct IncompleteType3; // expected-note{{forward declaration of 'IncompleteType3'}}
+template <typename T> struct __declspec(dllexport) ExplicitlyInstantiatedExportedTemplate {
+ int f() { return sizeof(T); } // expected-error{{invalid application of 'sizeof' to an incomplete type 'IncompleteType3'}}
+};
+template struct ExplicitlyInstantiatedExportedTemplate<IncompleteType3>; // expected-note{{in instantiation of member function 'ExplicitlyInstantiatedExportedTemplate<IncompleteType3>::f' requested here}}
+
+// In MS mode, instantiate members of class templates that are base classes of exported classes.
+#ifdef MS
+ // expected-note@+3{{forward declaration of 'IncompleteType4'}}
+ // expected-note@+3{{in instantiation of member function 'BaseClassTemplateOfExportedClass<IncompleteType4>::f' requested here}}
+#endif
+struct IncompleteType4;
+template <typename T> struct BaseClassTemplateOfExportedClass {
+#ifdef MS
+ // expected-error@+2{{invalid application of 'sizeof' to an incomplete type 'IncompleteType4'}}
+#endif
+ int f() { return sizeof(T); };
+};
+struct __declspec(dllexport) ExportedBaseClass : public BaseClassTemplateOfExportedClass<IncompleteType4> {};
+
+// Don't instantiate members of explicitly exported class templates that are base classes of exported classes.
+struct IncompleteType5;
+template <typename T> struct __declspec(dllexport) ExportedBaseClassTemplateOfExportedClass {
+ int f() { return sizeof(T); }; // no-error
+};
+struct __declspec(dllexport) ExportedBaseClass2 : public ExportedBaseClassTemplateOfExportedClass<IncompleteType5> {};
+
+
//===----------------------------------------------------------------------===//
// Classes with template base classes
diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp
index 889b7b9a8068..eb6a554522ba 100644
--- a/test/SemaCXX/dllimport.cpp
+++ b/test/SemaCXX/dllimport.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 -DMS %s
-// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y -DMS %s
-// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y %s
-// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 -Wunsupported-dll-base-class-template -DMS %s
+// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y -Wunsupported-dll-base-class-template -DMS %s
+// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y -Wunsupported-dll-base-class-template -DGNU %s
+// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 -Wunsupported-dll-base-class-template -DGNU %s
// Helper structs to make templates more expressive.
struct ImplicitInst_Imported {};
@@ -91,6 +91,9 @@ namespace ns { __declspec(dllimport) int ExternalGlobal; }
__declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllimport'}}
// expected-error@-1{{definition of dllimport data}}
+// Thread local variables are invalid.
+__declspec(dllimport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllimport'}}
+
// Import in local scope.
__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
@@ -188,7 +191,6 @@ template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Def_Imported> = 1; //
#endif // __has_feature(cxx_variable_templates)
-
//===----------------------------------------------------------------------===//
// Functions
//===----------------------------------------------------------------------===//
@@ -207,13 +209,23 @@ __declspec(dllimport) void def() {} // expected-error{{dllimport cannot be appli
extern "C" __declspec(dllimport) void externC();
// Import inline function.
+#ifdef GNU
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+#endif
__declspec(dllimport) inline void inlineFunc1() {}
inline void __attribute__((dllimport)) inlineFunc2() {}
+#ifdef GNU
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
__declspec(dllimport) inline void inlineDecl();
void inlineDecl() {}
__declspec(dllimport) void inlineDef();
+#ifdef GNU
+// expected-warning@+2{{'inlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
inline void inlineDef() {}
// Redeclarations
@@ -236,8 +248,13 @@ extern "C" {
__declspec(dllimport) void redecl5(); // expected-warning{{redeclaration of 'redecl5' should not add 'dllimport' attribute}}
}
+#ifdef MS
void redecl6(); // expected-note{{previous declaration is here}}
__declspec(dllimport) inline void redecl6() {} // expected-warning{{redeclaration of 'redecl6' should not add 'dllimport' attribute}}
+#else
+ void redecl6();
+__declspec(dllimport) inline void redecl6() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
// Friend functions
struct FuncFriend {
@@ -245,13 +262,28 @@ struct FuncFriend {
friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
friend void friend4(); // expected-note{{previous declaration is here}}
- friend void friend5(); // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-note@+2{{previous declaration is here}}
+#endif
+ friend void friend5();
};
__declspec(dllimport) void friend1();
void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
__declspec(dllimport) void friend4(); // expected-warning{{redeclaration of 'friend4' should not add 'dllimport' attribute}}
+#ifdef MS
__declspec(dllimport) inline void friend5() {} // expected-warning{{redeclaration of 'friend5' should not add 'dllimport' attribute}}
+#else
+__declspec(dllimport) inline void friend5() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
+
+
+void __declspec(dllimport) friend6(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+void __declspec(dllimport) friend7();
+struct FuncFriend2 {
+ friend void friend6(); // expected-warning{{'friend6' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+ friend void ::friend7();
+};
// Implicit declarations can be redeclared with dllimport.
__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
@@ -267,7 +299,11 @@ namespace ns { __declspec(dllimport) void externalFunc(); }
// here which is irrelevant. But because the delete keyword is parsed later
// there is currently no straight-forward way to avoid this diagnostic.
__declspec(dllimport) void deletedFunc() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} expected-error{{dllimport cannot be applied to non-inline function definition}}
+#ifdef MS
__declspec(dllimport) inline void deletedInlineFunc() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
+#else
+__declspec(dllimport) inline void deletedInlineFunc() = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
@@ -283,6 +319,12 @@ template<typename T> void __declspec(dllimport) funcTmplDecl2();
template<typename T> __declspec(dllimport) void funcTmplDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
// Import inline function template.
+#ifdef GNU
+// expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+6{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+9{{'inlineFuncTmplDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {}
template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {}
@@ -305,8 +347,10 @@ template<typename T> void funcTmplRedecl3() {} // expected
template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}}
template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}}
+#ifdef MS
template<typename T> void funcTmplRedecl5(); // expected-note{{previous declaration is here}}
template<typename T> __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5' cannot add 'dllimport' attribute}}
+#endif
// Function template friends
struct FuncTmplFriend {
@@ -314,6 +358,9 @@ struct FuncTmplFriend {
template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
template<typename T> friend __declspec(dllimport) void funcTmplFriend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}}
+#ifdef GNU
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<typename T> friend __declspec(dllimport) inline void funcTmplFriend5();
};
template<typename T> __declspec(dllimport) void funcTmplFriend1();
@@ -332,6 +379,9 @@ namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(
template<typename T> void funcTmpl() {}
template<typename T> inline void inlineFuncTmpl() {}
template<typename T> __declspec(dllimport) void importedFuncTmplDecl();
+#ifdef GNU
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {}
// Import implicit instantiation of an imported function template.
@@ -350,7 +400,9 @@ template void importedFuncTmpl<ExplicitInst_Imported>();
// declared inline.
template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>();
template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+#ifdef MS
template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {}
+#endif
// Not importing specialization of an imported function template without
// explicit dllimport.
@@ -359,16 +411,25 @@ template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {}
// Import explicit instantiation declaration of a non-imported function template.
extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>();
+#ifdef GNU
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>();
// Import explicit instantiation definition of a non-imported function template.
template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>();
+#ifdef GNU
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>();
// Import specialization of a non-imported function template. A definition must
// be declared inline.
template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>();
template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+#ifdef GNU
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}
@@ -383,16 +444,28 @@ struct ImportMembers {
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
};
+#ifdef GNU
+// expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+6{{'dllimport' attribute ignored on inline function}}
+#endif
__declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
__declspec(dllimport) void normalInclass() {}
__declspec(dllimport) void normalInlineDef();
__declspec(dllimport) inline void normalInlineDecl();
+#ifdef GNU
+// expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+6{{'dllimport' attribute ignored on inline function}}
+#endif
__declspec(dllimport) virtual void virtualDecl();
__declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
__declspec(dllimport) virtual void virtualInclass() {}
__declspec(dllimport) virtual void virtualInlineDef();
__declspec(dllimport) virtual inline void virtualInlineDecl();
+#ifdef GNU
+// expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+6{{'dllimport' attribute ignored on inline function}}
+#endif
__declspec(dllimport) static void staticDecl();
__declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
__declspec(dllimport) static void staticInclass() {}
@@ -418,12 +491,21 @@ public:
void ImportMembers::Nested::normalDef() {} // expected-warning{{'ImportMembers::Nested::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
void ImportMembers::normalDef() {} // expected-warning{{'ImportMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-warning@+2{{'ImportMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
inline void ImportMembers::normalInlineDef() {}
void ImportMembers::normalInlineDecl() {}
void ImportMembers::virtualDef() {} // expected-warning{{'ImportMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-warning@+2{{'ImportMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
inline void ImportMembers::virtualInlineDef() {}
void ImportMembers::virtualInlineDecl() {}
void ImportMembers::staticDef() {} // expected-warning{{'ImportMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-warning@+2{{'ImportMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
inline void ImportMembers::staticInlineDef() {}
void ImportMembers::staticInlineDecl() {}
@@ -436,13 +518,15 @@ constexpr int ImportMembers::ConstexprFieldDef; // expected-error{{definition of
struct ImportMemberDefs {
__declspec(dllimport) void normalDef();
__declspec(dllimport) void normalInlineDef();
- __declspec(dllimport) inline void normalInlineDecl();
__declspec(dllimport) virtual void virtualDef();
__declspec(dllimport) virtual void virtualInlineDef();
- __declspec(dllimport) virtual inline void virtualInlineDecl();
__declspec(dllimport) static void staticDef();
__declspec(dllimport) static void staticInlineDef();
+#ifdef MS
+ __declspec(dllimport) inline void normalInlineDecl();
+ __declspec(dllimport) virtual inline void virtualInlineDecl();
__declspec(dllimport) static inline void staticInlineDecl();
+#endif
__declspec(dllimport) static int StaticField;
__declspec(dllimport) static const int StaticConstField;
@@ -450,14 +534,16 @@ struct ImportMemberDefs {
};
__declspec(dllimport) void ImportMemberDefs::normalDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+__declspec(dllimport) void ImportMemberDefs::virtualDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+__declspec(dllimport) void ImportMemberDefs::staticDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+#ifdef MS
__declspec(dllimport) inline void ImportMemberDefs::normalInlineDef() {}
__declspec(dllimport) void ImportMemberDefs::normalInlineDecl() {}
-__declspec(dllimport) void ImportMemberDefs::virtualDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
__declspec(dllimport) inline void ImportMemberDefs::virtualInlineDef() {}
__declspec(dllimport) void ImportMemberDefs::virtualInlineDecl() {}
-__declspec(dllimport) void ImportMemberDefs::staticDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
__declspec(dllimport) inline void ImportMemberDefs::staticInlineDef() {}
__declspec(dllimport) void ImportMemberDefs::staticInlineDecl() {}
+#endif
__declspec(dllimport) int ImportMemberDefs::StaticField; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}}
__declspec(dllimport) const int ImportMemberDefs::StaticConstField = 1; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}}
@@ -477,6 +563,7 @@ struct ImportSpecials {
// Import deleted member functions.
struct ImportDeleted {
+#ifdef MS
__declspec(dllimport) ImportDeleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
__declspec(dllimport) ~ImportDeleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
__declspec(dllimport) ImportDeleted(const ImportDeleted&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
@@ -484,6 +571,15 @@ struct ImportDeleted {
__declspec(dllimport) ImportDeleted(ImportDeleted&&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
__declspec(dllimport) ImportDeleted& operator=(ImportDeleted&&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
__declspec(dllimport) void deleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}}
+#else
+ __declspec(dllimport) ImportDeleted() = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+ __declspec(dllimport) ~ImportDeleted() = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+ __declspec(dllimport) ImportDeleted(const ImportDeleted&) = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+ __declspec(dllimport) ImportDeleted& operator=(const ImportDeleted&) = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+ __declspec(dllimport) ImportDeleted(ImportDeleted&&) = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+ __declspec(dllimport) ImportDeleted& operator=(ImportDeleted&&) = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+ __declspec(dllimport) void deleted() = delete; // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
};
@@ -498,6 +594,14 @@ struct ImportAlloc {
// Import defaulted member functions.
struct ImportDefaulted {
+#ifdef GNU
+ // expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+#endif
__declspec(dllimport) ImportDefaulted() = default;
__declspec(dllimport) ~ImportDefaulted() = default;
__declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default;
@@ -512,6 +616,10 @@ struct ImportDefaultedDefs {
__declspec(dllimport) ImportDefaultedDefs();
__declspec(dllimport) ~ImportDefaultedDefs(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+#ifdef GNU
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+// expected-note@+2{{previous declaration is here}}
+#endif
__declspec(dllimport) inline ImportDefaultedDefs(const ImportDefaultedDefs&);
__declspec(dllimport) ImportDefaultedDefs& operator=(const ImportDefaultedDefs&);
@@ -526,6 +634,10 @@ __declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default; // e
ImportDefaultedDefs::~ImportDefaultedDefs() = default; // expected-warning{{'ImportDefaultedDefs::~ImportDefaultedDefs' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
// Import inline declaration and definition.
+#ifdef GNU
+// expected-error@+3{{redeclaration of 'ImportDefaultedDefs::ImportDefaultedDefs' cannot add 'dllimport' attribute}}
+// expected-warning@+3{{'ImportDefaultedDefs::operator=' redeclared inline; 'dllimport' attribute ignored}}
+#endif
__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default;
inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default;
@@ -536,15 +648,21 @@ ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = def
// Redeclarations cannot add dllimport.
struct MemberRedecl {
void normalDef(); // expected-note{{previous declaration is here}}
- void normalInlineDef(); // expected-note{{previous declaration is here}}
inline void normalInlineDecl(); // expected-note{{previous declaration is here}}
virtual void virtualDef(); // expected-note{{previous declaration is here}}
- virtual void virtualInlineDef(); // expected-note{{previous declaration is here}}
virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}}
static void staticDef(); // expected-note{{previous declaration is here}}
- static void staticInlineDef(); // expected-note{{previous declaration is here}}
static inline void staticInlineDecl(); // expected-note{{previous declaration is here}}
+#ifdef MS
+ // expected-note@+4{{previous declaration is here}}
+ // expected-note@+4{{previous declaration is here}}
+ // expected-note@+4{{previous declaration is here}}
+#endif
+ void normalInlineDef();
+ virtual void virtualInlineDef();
+ static void staticInlineDef();
+
static int StaticField; // expected-note{{previous declaration is here}}
static const int StaticConstField; // expected-note{{previous declaration is here}}
constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
@@ -552,17 +670,26 @@ struct MemberRedecl {
__declspec(dllimport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-__declspec(dllimport) inline void MemberRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDef' cannot add 'dllimport' attribute}}
__declspec(dllimport) void MemberRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDecl' cannot add 'dllimport' attribute}}
__declspec(dllimport) void MemberRedecl::virtualDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-__declspec(dllimport) inline void MemberRedecl::virtualInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDef' cannot add 'dllimport' attribute}}
__declspec(dllimport) void MemberRedecl::virtualInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDecl' cannot add 'dllimport' attribute}}
__declspec(dllimport) void MemberRedecl::staticDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-__declspec(dllimport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllimport' attribute}}
__declspec(dllimport) void MemberRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDecl' cannot add 'dllimport' attribute}}
+#ifdef MS
+__declspec(dllimport) inline void MemberRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDef' cannot add 'dllimport' attribute}}
+__declspec(dllimport) inline void MemberRedecl::virtualInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDef' cannot add 'dllimport' attribute}}
+__declspec(dllimport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllimport' attribute}}
+#else
+__declspec(dllimport) inline void MemberRedecl::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+__declspec(dllimport) inline void MemberRedecl::virtualInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+__declspec(dllimport) inline void MemberRedecl::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
+
+
+
__declspec(dllimport) int MemberRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticField' cannot add 'dllimport' attribute}}
// expected-error@-1{{definition of dllimport static field not allowed}}
// expected-note@-2{{attribute is here}}
@@ -582,13 +709,20 @@ __declspec(dllimport) constexpr int MemberRedecl::ConstexprField; // expect
struct ImportMemberTmpl {
template<typename T> __declspec(dllimport) void normalDecl();
template<typename T> __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- template<typename T> __declspec(dllimport) void normalInclass() {}
template<typename T> __declspec(dllimport) void normalInlineDef();
- template<typename T> __declspec(dllimport) inline void normalInlineDecl();
template<typename T> __declspec(dllimport) static void staticDecl();
template<typename T> __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- template<typename T> __declspec(dllimport) static void staticInclass() {}
template<typename T> __declspec(dllimport) static void staticInlineDef();
+
+#ifdef GNU
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+#endif
+ template<typename T> __declspec(dllimport) void normalInclass() {}
+ template<typename T> __declspec(dllimport) inline void normalInlineDecl();
+ template<typename T> __declspec(dllimport) static void staticInclass() {}
template<typename T> __declspec(dllimport) static inline void staticInlineDecl();
#if __has_feature(cxx_variable_templates)
@@ -604,12 +738,17 @@ struct ImportMemberTmpl {
};
template<typename T> void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> inline void ImportMemberTmpl::normalInlineDef() {}
template<typename T> void ImportMemberTmpl::normalInlineDecl() {}
template<typename T> void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> inline void ImportMemberTmpl::staticInlineDef() {}
template<typename T> void ImportMemberTmpl::staticInlineDecl() {}
+#ifdef GNU
+// expected-warning@+3{{ImportMemberTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+3{{ImportMemberTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
+template<typename T> inline void ImportMemberTmpl::normalInlineDef() {}
+template<typename T> inline void ImportMemberTmpl::staticInlineDef() {}
+
#if __has_feature(cxx_variable_templates)
template<typename T> int ImportMemberTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}}
template<typename T> const int ImportMemberTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}}
@@ -620,12 +759,17 @@ template<typename T> constexpr int ImportMemberTmpl::ConstexprFieldDef; // expec
// Redeclarations cannot add dllimport.
struct MemTmplRedecl {
template<typename T> void normalDef(); // expected-note{{previous declaration is here}}
- template<typename T> void normalInlineDef(); // expected-note{{previous declaration is here}}
template<typename T> inline void normalInlineDecl(); // expected-note{{previous declaration is here}}
template<typename T> static void staticDef(); // expected-note{{previous declaration is here}}
- template<typename T> static void staticInlineDef(); // expected-note{{previous declaration is here}}
template<typename T> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-note@+3{{previous declaration is here}}
+// expected-note@+3{{previous declaration is here}}
+#endif
+ template<typename T> void normalInlineDef();
+ template<typename T> static void staticInlineDef();
+
#if __has_feature(cxx_variable_templates)
template<typename T> static int StaticField; // expected-note{{previous declaration is here}}
template<typename T> static const int StaticConstField; // expected-note{{previous declaration is here}}
@@ -635,11 +779,19 @@ struct MemTmplRedecl {
template<typename T> __declspec(dllimport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
+#ifdef MS
template<typename T> __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllimport' attribute}}
+#else
+template<typename T> __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
template<typename T> __declspec(dllimport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllimport' attribute}}
template<typename T> __declspec(dllimport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
+#ifdef MS
template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}}
+#else
+template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
template<typename T> __declspec(dllimport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}}
#if __has_feature(cxx_variable_templates)
@@ -658,8 +810,14 @@ template<typename T> __declspec(dllimport) constexpr int MemTmplRedecl::Constexp
struct MemFunTmpl {
template<typename T> void normalDef() {}
+#ifdef GNU
+ // expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<typename T> __declspec(dllimport) void importedNormal() {}
template<typename T> static void staticDef() {}
+#ifdef GNU
+ // expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<typename T> __declspec(dllimport) static void importedStatic() {}
};
@@ -683,16 +841,24 @@ template void MemFunTmpl::importedStatic<ExplicitInst_Imported>();
// Import specialization of an imported member function template.
template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Imported>();
template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Def_Imported>() {} // error on mingw
+#ifdef GNU
+ // expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {}
-#ifndef MSABI
-// expected-error@-3{{dllimport cannot be applied to non-inline function definition}}
+#if 1
+// FIXME: This should not be an error when targeting MSVC. (PR21406)
+// expected-error@-7{{dllimport cannot be applied to non-inline function definition}}
#endif
template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Imported>();
template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>() {} // error on mingw
+#ifdef GNU
+ // expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {}
-#ifndef MSABI
-// expected-error@-3{{dllimport cannot be applied to non-inline function definition}}
+#if 1
+// FIXME: This should not be an error when targeting MSVC. (PR21406)
+// expected-error@-7{{dllimport cannot be applied to non-inline function definition}}
#endif
// Not importing specialization of an imported member function template without
@@ -703,27 +869,43 @@ template<> void MemFunTmpl::importedStatic<ExplicitSpec_NotImported>() {}
// Import explicit instantiation declaration of a non-imported member function
// template.
+#ifdef GNU
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+#endif
extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>();
extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>();
// Import explicit instantiation definition of a non-imported member function
// template.
+#ifdef GNU
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
+#endif
template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>();
template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>();
// Import specialization of a non-imported member function template.
template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Imported>();
template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Imported>() {} // error on mingw
+#ifdef GNU
+ // expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {}
-#ifndef MSABI
-// expected-error@-3{{dllimport cannot be applied to non-inline function definition}}
+#if 1
+// FIXME: This should not be an error when targeting MSVC. (PR21406)
+// expected-error@-7{{dllimport cannot be applied to non-inline function definition}}
#endif
template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Imported>();
template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>() {} // error on mingw
+#ifdef GNU
+ // expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {}
-#ifndef MSABI
-// expected-error@-3{{dllimport cannot be applied to non-inline function definition}}
+#if 1
+// FIXME: This should not be an error when targeting MSVC. (PR21406)
+// expected-error@-7{{dllimport cannot be applied to non-inline function definition}}
#endif
@@ -783,18 +965,27 @@ template<typename T>
struct ImportClassTmplMembers {
__declspec(dllimport) void normalDecl();
__declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- __declspec(dllimport) void normalInclass() {}
__declspec(dllimport) void normalInlineDef();
- __declspec(dllimport) inline void normalInlineDecl();
__declspec(dllimport) virtual void virtualDecl();
__declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- __declspec(dllimport) virtual void virtualInclass() {}
__declspec(dllimport) virtual void virtualInlineDef();
- __declspec(dllimport) virtual inline void virtualInlineDecl();
__declspec(dllimport) static void staticDecl();
__declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- __declspec(dllimport) static void staticInclass() {}
__declspec(dllimport) static void staticInlineDef();
+
+#ifdef GNU
+// expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+// expected-warning@+7{{'dllimport' attribute ignored on inline function}}
+#endif
+ __declspec(dllimport) void normalInclass() {}
+ __declspec(dllimport) inline void normalInlineDecl();
+ __declspec(dllimport) virtual void virtualInclass() {}
+ __declspec(dllimport) virtual inline void virtualInlineDecl();
+ __declspec(dllimport) static void staticInclass() {}
__declspec(dllimport) static inline void staticInlineDecl();
protected:
@@ -817,12 +1008,21 @@ public:
// NB: MSVC is inconsistent here and disallows *InlineDef on class templates,
// but allows it on classes. We allow both.
template<typename T> void ImportClassTmplMembers<T>::normalDef() {} // expected-warning{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
template<typename T> inline void ImportClassTmplMembers<T>::normalInlineDef() {}
template<typename T> void ImportClassTmplMembers<T>::normalInlineDecl() {}
template<typename T> void ImportClassTmplMembers<T>::virtualDef() {} // expected-warning{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
template<typename T> inline void ImportClassTmplMembers<T>::virtualInlineDef() {}
template<typename T> void ImportClassTmplMembers<T>::virtualInlineDecl() {}
template<typename T> void ImportClassTmplMembers<T>::staticDef() {} // expected-warning{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+#ifdef GNU
+// expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
template<typename T> inline void ImportClassTmplMembers<T>::staticInlineDef() {}
template<typename T> void ImportClassTmplMembers<T>::staticInlineDecl() {}
@@ -835,15 +1035,21 @@ template<typename T> constexpr int ImportClassTmplMembers<T>::ConstexprFieldDef;
template<typename T>
struct CTMR /*ClassTmplMemberRedecl*/ {
void normalDef(); // expected-note{{previous declaration is here}}
- void normalInlineDef(); // expected-note{{previous declaration is here}}
inline void normalInlineDecl(); // expected-note{{previous declaration is here}}
virtual void virtualDef(); // expected-note{{previous declaration is here}}
- virtual void virtualInlineDef(); // expected-note{{previous declaration is here}}
virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}}
static void staticDef(); // expected-note{{previous declaration is here}}
- static void staticInlineDef(); // expected-note{{previous declaration is here}}
static inline void staticInlineDecl(); // expected-note{{previous declaration is here}}
+#ifdef MS
+// expected-note@+4{{previous declaration is here}}
+// expected-note@+4{{previous declaration is here}}
+// expected-note@+4{{previous declaration is here}}
+#endif
+ void normalInlineDef();
+ virtual void virtualInlineDef();
+ static void staticInlineDef();
+
static int StaticField; // expected-note{{previous declaration is here}}
static const int StaticConstField; // expected-note{{previous declaration is here}}
constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
@@ -851,17 +1057,24 @@ struct CTMR /*ClassTmplMemberRedecl*/ {
template<typename T> __declspec(dllimport) void CTMR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}}
template<typename T> __declspec(dllimport) void CTMR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllimport' attribute}}
template<typename T> __declspec(dllimport) void CTMR<T>::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}}
template<typename T> __declspec(dllimport) void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllimport' attribute}}
template<typename T> __declspec(dllimport) void CTMR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}}
template<typename T> __declspec(dllimport) void CTMR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}}
+#ifdef MS
+template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}}
+#else
+template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
+
template<typename T> __declspec(dllimport) int CTMR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllimport' attribute}}
// expected-warning@-1{{definition of dllimport static field}}
// expected-note@-2{{attribute is here}}
@@ -882,13 +1095,20 @@ template<typename T>
struct ImportClsTmplMemTmpl {
template<typename U> __declspec(dllimport) void normalDecl();
template<typename U> __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- template<typename U> __declspec(dllimport) void normalInclass() {}
template<typename U> __declspec(dllimport) void normalInlineDef();
- template<typename U> __declspec(dllimport) inline void normalInlineDecl();
template<typename U> __declspec(dllimport) static void staticDecl();
template<typename U> __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
- template<typename U> __declspec(dllimport) static void staticInclass() {}
template<typename U> __declspec(dllimport) static void staticInlineDef();
+
+#ifdef GNU
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+ // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
+#endif
+ template<typename U> __declspec(dllimport) void normalInclass() {}
+ template<typename U> __declspec(dllimport) inline void normalInlineDecl();
+ template<typename U> __declspec(dllimport) static void staticInclass() {}
template<typename U> __declspec(dllimport) static inline void staticInlineDecl();
#if __has_feature(cxx_variable_templates)
@@ -904,12 +1124,17 @@ struct ImportClsTmplMemTmpl {
};
template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::normalInlineDef() {}
template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::normalInlineDecl() {}
template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::staticInlineDef() {}
template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::staticInlineDecl() {}
+#ifdef GNU
+// expected-warning@+3{{'ImportClsTmplMemTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+3{{'ImportClsTmplMemTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+#endif
+template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::normalInlineDef() {}
+template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::staticInlineDef() {}
+
#if __has_feature(cxx_variable_templates)
template<typename T> template<typename U> int ImportClsTmplMemTmpl<T>::StaticFieldDef; // expected-warning{{definition of dllimport static field}}
template<typename T> template<typename U> const int ImportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}}
@@ -921,12 +1146,17 @@ template<typename T> template<typename U> constexpr int ImportClsTmplMemTmpl<T>:
template<typename T>
struct CTMTR /*ClassTmplMemberTmplRedecl*/ {
template<typename U> void normalDef(); // expected-note{{previous declaration is here}}
- template<typename U> void normalInlineDef(); // expected-note{{previous declaration is here}}
template<typename U> inline void normalInlineDecl(); // expected-note{{previous declaration is here}}
template<typename U> static void staticDef(); // expected-note{{previous declaration is here}}
- template<typename U> static void staticInlineDef(); // expected-note{{previous declaration is here}}
template<typename U> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}}
+#ifdef MS
+ // expected-note@+3{{previous declaration is here}}
+ // expected-note@+3{{previous declaration is here}}
+#endif
+ template<typename U> void normalInlineDef();
+ template<typename U> static void staticInlineDef();
+
#if __has_feature(cxx_variable_templates)
template<typename U> static int StaticField; // expected-note{{previous declaration is here}}
template<typename U> static const int StaticConstField; // expected-note{{previous declaration is here}}
@@ -936,13 +1166,19 @@ struct CTMTR /*ClassTmplMemberTmplRedecl*/ {
template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}}
template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllimport' attribute}}
template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllimport' attribute}}
// expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}}
template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}}
+#ifdef MS
+template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}}
+#else
+template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}}
+#endif
+
#if __has_feature(cxx_variable_templates)
template<typename T> template<typename U> __declspec(dllimport) int CTMTR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllimport' attribute}}
// expected-warning@-1{{definition of dllimport static field}}
@@ -961,6 +1197,10 @@ template<typename T> template<typename U> __declspec(dllimport) constexpr int CT
// Classes
//===----------------------------------------------------------------------===//
+namespace {
+ struct __declspec(dllimport) AnonymousClass {}; // expected-error{{(anonymous namespace)::AnonymousClass' must have external linkage when declared 'dllimport'}}
+}
+
class __declspec(dllimport) ClassDecl;
class __declspec(dllimport) ClassDef { };
@@ -984,7 +1224,7 @@ class __declspec(dllimport) ImportClassWithDllMember {
// expected-error@+4{{attribute 'dllimport' cannot be applied to member of 'dllexport' class}}
// expected-error@+4{{attribute 'dllexport' cannot be applied to member of 'dllexport' class}}
#endif
-class __declspec(dllexport) ExportClassWithDllMember {
+template <typename T> class __declspec(dllexport) ExportClassWithDllMember {
void __declspec(dllimport) foo();
void __declspec(dllexport) bar();
};
diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp
index e9dc24254f20..99545e09820e 100644
--- a/test/SemaCXX/enable_if.cpp
+++ b/test/SemaCXX/enable_if.cpp
@@ -77,3 +77,44 @@ void test() {
typedep(1);
typedep(n); // expected-note{{in instantiation of function template specialization 'typedep<Nothing>' requested here}}
}
+
+template <typename T> class C {
+ void f() __attribute__((enable_if(T::expr == 0, ""))) {}
+ void g() { f(); }
+};
+
+int fn3(bool b) __attribute__((enable_if(b, "")));
+template <class T> void test3() {
+ fn3(sizeof(T) == 1);
+}
+
+// FIXME: issue an error (without instantiation) because ::h(T()) is not
+// convertible to bool, because return types aren't overloadable.
+void h(int);
+template <typename T> void outer() {
+ void local_function() __attribute__((enable_if(::h(T()), "")));
+ local_function();
+};
+
+namespace PR20988 {
+ struct Integer {
+ Integer(int);
+ };
+
+ int fn1(const Integer &) __attribute__((enable_if(true, "")));
+ template <class T> void test1() {
+ int &expr = T::expr();
+ fn1(expr);
+ }
+
+ int fn2(const Integer &) __attribute__((enable_if(false, ""))); // expected-note{{candidate disabled}}
+ template <class T> void test2() {
+ int &expr = T::expr();
+ fn2(expr); // expected-error{{no matching function for call to 'fn2'}}
+ }
+
+ int fn3(bool b) __attribute__((enable_if(b, "")));
+ template <class T> void test3() {
+ fn3(sizeof(T) == 1);
+ }
+}
diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp
index 1eed2281e935..909802335e46 100644
--- a/test/SemaCXX/enum-scoped.cpp
+++ b/test/SemaCXX/enum-scoped.cpp
@@ -301,3 +301,11 @@ namespace PR18044 {
using E::a; // ok!
E b = a;
}
+
+namespace test11 {
+ enum class E { a };
+ typedef E E2;
+ E2 f1() { return E::a; }
+
+ bool f() { return !f1(); } // expected-error {{invalid argument type 'E2' (aka 'test11::E') to unary expression}}
+}
diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp
index c2ca9f952b22..9646a9c3b31a 100644
--- a/test/SemaCXX/exceptions.cpp
+++ b/test/SemaCXX/exceptions.cpp
@@ -35,37 +35,37 @@ void throws() {
void jumps() {
l1:
goto l5;
- 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 l4; // expected-error {{cannot jump}}
+ goto l3; // expected-error {{cannot jump}}
+ goto l2; // expected-error {{cannot jump}}
goto l1;
try { // expected-note 4 {{jump bypasses initialization of try block}}
l2:
goto l5;
- goto l4; // expected-error {{goto into protected scope}}
- goto l3; // expected-error {{goto into protected scope}}
+ goto l4; // expected-error {{cannot jump}}
+ goto l3; // expected-error {{cannot jump}}
goto l2;
goto l1;
} catch(int) { // expected-note 4 {{jump bypasses initialization of catch block}}
l3:
goto l5;
- goto l4; // expected-error {{goto into protected scope}}
+ goto l4; // expected-error {{cannot jump}}
goto l3;
- goto l2; // expected-error {{goto into protected scope}}
+ goto l2; // expected-error {{cannot jump}}
goto l1;
} catch(...) { // expected-note 4 {{jump bypasses initialization of catch block}}
l4:
goto l5;
goto l4;
- goto l3; // expected-error {{goto into protected scope}}
- goto l2; // expected-error {{goto into protected scope}}
+ goto l3; // expected-error {{cannot jump}}
+ goto l2; // expected-error {{cannot jump}}
goto l1;
}
l5:
goto l5;
- 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 l4; // expected-error {{cannot jump}}
+ goto l3; // expected-error {{cannot jump}}
+ goto l2; // expected-error {{cannot jump}}
goto l1;
}
diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp
index aa28bd85af46..155141c058c4 100644
--- a/test/SemaCXX/explicit.cpp
+++ b/test/SemaCXX/explicit.cpp
@@ -86,7 +86,7 @@ namespace Conversion {
// Y is an aggregate, so aggregate-initialization is performed and the
// conversion function is not considered.
const Y y10{z}; // expected-error {{excess elements}}
- const Y& y11{z}; // expected-error {{no viable conversion from 'Z' to 'const Y'}}
+ const Y& y11{z}; // expected-error {{excess elements}} expected-note {{in initialization of temporary of type 'const Y'}}
const int& y12{z};
// X is not an aggregate, so constructors are considered.
diff --git a/test/SemaCXX/flexible-array-test.cpp b/test/SemaCXX/flexible-array-test.cpp
index e58f19a62eca..2d74fa52452e 100644
--- a/test/SemaCXX/flexible-array-test.cpp
+++ b/test/SemaCXX/flexible-array-test.cpp
@@ -14,6 +14,12 @@ void QMap<Key, T>::insert(const Key &, const T &avalue)
v = avalue;
}
+struct Rec {
+ union { // expected-warning-re {{variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}}
+ int u0[];
+ };
+ int x;
+} rec;
struct inotify_event
{
diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp
index 2f777fb46df0..d07331c51e29 100644
--- a/test/SemaCXX/for-range-examples.cpp
+++ b/test/SemaCXX/for-range-examples.cpp
@@ -214,17 +214,19 @@ namespace test6 {
namespace test7 {
void f() {
int arr[5], b;
- for (a : arr) {} // expected-warning {{extension}}
- // FIXME: Give a -Wshadow for this by default?
- for (b : arr) {} // expected-warning {{extension}}
- for (arr : arr) {} // expected-warning {{extension}}
- for (c alignas(8) : arr) { // expected-warning {{extension}}
+ for (a : arr) {} // expected-error {{requires type for loop variable}}
+ // FIXME: Give a different error in this case?
+ for (b : arr) {} // expected-error {{requires type for loop variable}}
+ for (arr : arr) {} // expected-error {{requires type for loop variable}}
+ for (c alignas(8) : arr) { // expected-error {{requires type for loop variable}}
static_assert(alignof(c) == 8, ""); // expected-warning {{extension}}
}
- // FIXME: We should reject this, but don't, because we only check the
- // attribute before we deduce the 'auto' type.
- for (d alignas(1) : arr) {} // expected-warning {{extension}}
- for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-warning {{extension}}
+ // FIXME: The fix-it hint here is not sufficient to fix the error.
+ // We fail to diagnose that d is underaligned for its type, because
+ // we check the alignment attribute before we perform the auto
+ // deduction.
+ for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}}
+ for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}}
}
}
diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp
index 03589101e1b8..55aa069803bf 100644
--- a/test/SemaCXX/friend.cpp
+++ b/test/SemaCXX/friend.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
friend class A; // expected-error {{'friend' used outside of class}}
void f() { friend class A; } // expected-error {{'friend' used outside of class}}
@@ -296,3 +296,56 @@ namespace test11 {
friend class __attribute__((visibility("hidden"), noreturn)) B; // expected-warning {{'noreturn' attribute only applies to functions and methods}}
};
}
+
+namespace pr21851 {
+// PR21851 was a problem where we assumed that when the friend function redecl
+// lookup found a C++ method, it would necessarily have a qualifier. Below we
+// have some test cases where unqualified lookup finds C++ methods without using
+// qualifiers. Unfortunately, we can't exercise the case of an access check
+// failure because nested classes always have access to the members of outer
+// classes.
+
+void friend_own_method() {
+ class A {
+ void m() {}
+ friend void m();
+ };
+}
+
+void friend_enclosing_method() {
+ class A;
+ class C {
+ int p;
+ friend class A;
+ };
+ class A {
+ void enclosing_friend() {
+ (void)b->p;
+ (void)c->p;
+ }
+ class B {
+ void b(A *a) {
+ (void)a->c->p;
+ }
+ int p;
+ friend void enclosing_friend();
+ };
+ B *b;
+ C *c;
+ };
+}
+
+static auto friend_file_func() {
+ extern void file_scope_friend();
+ class A {
+ int p;
+ friend void file_scope_friend();
+ };
+ return A();
+}
+
+void file_scope_friend() {
+ auto a = friend_file_func();
+ (void)a.p;
+}
+}
diff --git a/test/SemaCXX/goto.cpp b/test/SemaCXX/goto.cpp
index 042ec3cd8035..2d37ea9099a2 100644
--- a/test/SemaCXX/goto.cpp
+++ b/test/SemaCXX/goto.cpp
@@ -109,7 +109,7 @@ namespace PR10620 {
~S() {}
};
void g(const S& s) {
- goto done; // expected-error {{goto into protected scope}}
+ goto done; // expected-error {{cannot jump}}
const S s2(s); // expected-note {{jump bypasses variable initialization}}
done:
;
@@ -119,7 +119,7 @@ namespace PR10620 {
namespace test12 {
struct A { A(); A(const A&); ~A(); };
void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: weird location
- goto lbl; // expected-error {{goto into protected scope}}
+ goto lbl; // expected-error {{cannot jump}}
(void) ^{ (void) a; };
lbl:
return;
diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp
index e26f985f0d0a..ff3d685d912e 100644
--- a/test/SemaCXX/implicit-exception-spec.cpp
+++ b/test/SemaCXX/implicit-exception-spec.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall -Wno-unused-local-typedefs %s
template<bool b> struct ExceptionIf { static int f(); };
template<> struct ExceptionIf<false> { typedef int f; };
@@ -17,42 +17,43 @@ namespace InClassInitializers {
// is false.
bool ThrowSomething() noexcept(false);
struct ConstExpr {
- bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{cannot be used by non-static data member initializer}}
+ bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{cannot use defaulted default constructor of 'ConstExpr' within the class outside of member functions}}
+ // expected-note@-1 {{implicit default constructor for 'InClassInitializers::ConstExpr' first required here}}
};
- // We can use it now.
- bool w = noexcept(ConstExpr());
// Much more obviously broken: we can't parse the initializer without already
// knowing whether it produces a noexcept expression.
struct TemplateArg {
- int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{cannot be used by non-static data member initializer}}
+ int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{cannot use defaulted default constructor of 'TemplateArg' within the class outside of member functions}}
+ // expected-note@-1 {{implicit default constructor for 'InClassInitializers::TemplateArg' first required here}}
};
- bool x = noexcept(TemplateArg());
// And within a nested class.
- struct Nested { // expected-error {{cannot be used by non-static data member initializer}}
+ struct Nested { // expected-note {{implicit default constructor for 'InClassInitializers::Nested::Inner' first required here}}
struct Inner {
+ // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested' outside of member functions}}
int n = ExceptionIf<noexcept(Nested())>::f(); // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}}
} inner;
};
- struct Nested2 {
+ struct Nested2 { // expected-error {{implicit default constructor for 'InClassInitializers::Nested2' must explicitly initialize the member 'inner' which does not have a default constructor}}
struct Inner;
- int n = Inner().n; // expected-error {{cannot be used by non-static data member initializer}}
- struct Inner {
+ int n = Inner().n; // expected-note {{implicit default constructor for 'InClassInitializers::Nested2::Inner' first required here}}
+ struct Inner { // expected-note {{declared here}}
+ // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested2' outside of member functions}}
int n = ExceptionIf<noexcept(Nested2())>::f();
- } inner;
+ // expected-note@-1 {{implicit default constructor for 'InClassInitializers::Nested2' first required here}}
+ } inner; // expected-note {{member is declared here}}
};
}
namespace ExceptionSpecification {
- // A type is permitted to be used in a dynamic exception specification when it
- // is still being defined, but isn't complete within such an exception
- // specification.
- struct Nested { // expected-note {{not complete}}
+ // FIXME: This diagnostic is quite useless; we should indicate whose
+ // exception specification we were looking for and why.
+ struct Nested {
struct T {
- T() noexcept(!noexcept(Nested())); // expected-error{{incomplete type}}
- } t;
+ T() noexcept(!noexcept(Nested()));
+ } t; // expected-error{{exception specification is not available until end of class definition}}
};
}
diff --git a/test/SemaCXX/issue547.cpp b/test/SemaCXX/issue547.cpp
index bfec6e080ba5..2a9dd13adf4e 100644
--- a/test/SemaCXX/issue547.cpp
+++ b/test/SemaCXX/issue547.cpp
@@ -27,32 +27,32 @@ struct classify_function<R(Args...) const volatile> {
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......)> {
+struct classify_function<R(Args..., ...)> {
static const unsigned value = 5;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const> {
+struct classify_function<R(Args..., ...) const> {
static const unsigned value = 6;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) volatile> {
+struct classify_function<R(Args..., ...) volatile> {
static const unsigned value = 7;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const volatile> {
+struct classify_function<R(Args..., ...) const volatile> {
static const unsigned value = 8;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) &&> {
+struct classify_function<R(Args..., ...) &&> {
static const unsigned value = 9;
};
template<typename R, typename ...Args>
-struct classify_function<R(Args......) const &> {
+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
index 9a53e4604f76..cad322ab52fe 100644
--- a/test/SemaCXX/lambda-expressions.cpp
+++ b/test/SemaCXX/lambda-expressions.cpp
@@ -258,9 +258,7 @@ namespace TypeDeduction {
void f() {
const S s {};
S &&t = [&] { return s; } ();
-#if __cplusplus <= 201103L
- // expected-error@-2 {{drops qualifiers}}
-#else
+#if __cplusplus > 201103L
S &&u = [&] () -> auto { return s; } ();
#endif
}
@@ -363,3 +361,79 @@ namespace PR18473 {
void PR19249() {
auto x = [&x]{}; // expected-error {{cannot appear in its own init}}
}
+
+namespace PR20731 {
+template <class L, int X = sizeof(L)>
+void Job(L l);
+
+template <typename... Args>
+void Logger(Args &&... args) {
+ auto len = Invalid_Function((args)...);
+ // expected-error@-1 {{use of undeclared identifier 'Invalid_Function'}}
+ Job([len]() {});
+}
+
+void GetMethod() {
+ Logger();
+ // expected-note@-1 {{in instantiation of function template specialization 'PR20731::Logger<>' requested here}}
+}
+
+template <typename T>
+struct A {
+ T t;
+ // expected-error@-1 {{field has incomplete type 'void'}}
+};
+
+template <typename F>
+void g(F f) {
+ auto a = A<decltype(f())>{};
+ // expected-note@-1 {{in instantiation of template class 'PR20731::A<void>' requested here}}
+ auto xf = [a, f]() {};
+ int x = sizeof(xf);
+};
+void f() {
+ g([] {});
+ // expected-note-re@-1 {{in instantiation of function template specialization 'PR20731::g<(lambda at {{.*}}>' requested here}}
+}
+
+template <class _Rp> struct function {
+ template <class _Fp>
+ function(_Fp) {
+ static_assert(sizeof(_Fp) > 0, "Type must be complete.");
+ }
+};
+
+template <typename T> void p(T t) {
+ auto l = some_undefined_function(t);
+ // expected-error@-1 {{use of undeclared identifier 'some_undefined_function'}}
+ function<void()>(([l]() {}));
+}
+void q() { p(0); }
+// expected-note@-1 {{in instantiation of function template specialization 'PR20731::p<int>' requested here}}
+}
+
+namespace lambda_in_default_mem_init {
+ template<typename T> void f() {
+ struct S { int n = []{ return 0; }(); };
+ }
+ template void f<int>();
+
+ template<typename T> void g() {
+ struct S { int n = [](int n){ return n; }(0); };
+ }
+ template void g<int>();
+}
+
+namespace error_in_transform_prototype {
+ template<class T>
+ void f(T t) {
+ // expected-error@+2 {{type 'int' cannot be used prior to '::' because it has no members}}
+ // expected-error@+1 {{no member named 'ns' in 'error_in_transform_prototype::S'}}
+ auto x = [](typename T::ns::type &k) {};
+ }
+ class S {};
+ void foo() {
+ f(5); // expected-note {{requested here}}
+ f(S()); // expected-note {{requested here}}
+ }
+}
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp b/test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp
index 774745777c17..774745777c17 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp
+++ b/test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp
diff --git a/test/SemaCXX/libstdcxx_is_pod_hack.cpp b/test/SemaCXX/libstdcxx_is_pod_hack.cpp
index 1ba3721c8c2e..8d187124f013 100644
--- a/test/SemaCXX/libstdcxx_is_pod_hack.cpp
+++ b/test/SemaCXX/libstdcxx_is_pod_hack.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
// This is a test for an egregious hack in Clang that works around
// issues with GCC's evolution. libstdc++ 4.2.x uses __is_pod as an
@@ -7,7 +7,7 @@
// a keyword *unless* it is introduced following the struct keyword.
template<typename T>
-struct __is_pod {
+struct __is_pod { // expected-warning {{keyword '__is_pod' will be made available as an identifier}}
__is_pod() {}
};
@@ -15,7 +15,7 @@ __is_pod<int> ipi;
// Ditto for __is_same.
template<typename T>
-struct __is_same {
+struct __is_same { // expected-warning {{keyword '__is_same' will be made available as an identifier}}
};
__is_same<int> isi;
@@ -24,7 +24,7 @@ __is_same<int> isi;
// trait in Embarcadero's compiler but is used as an identifier in
// libstdc++.
struct test_is_signed {
- static const bool __is_signed = true;
+ static const bool __is_signed = true; // expected-warning {{keyword '__is_signed' will be made available as an identifier}}
};
bool check_signed = test_is_signed::__is_signed;
@@ -36,6 +36,13 @@ void foo() {
bool b = __is_pod(int);
must_be_true<__is_pod(int)> mbt;
}
+
+// expected-warning@+1 {{declaration does not declare anything}}
+struct // expected-error {{declaration of anonymous struct must be a definition}}
+#pragma pack(pop)
+ S {
+};
+
#if !__has_feature(is_pod)
# error __is_pod should still be available.
#endif
diff --git a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
new file mode 100644
index 000000000000..02431e02e48d
--- /dev/null
+++ b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
@@ -0,0 +1,74 @@
+// This is a test for an egregious hack in Clang that works around
+// an issue with GCC's <utility> implementation. std::pair::swap
+// has an exception specification that makes an unqualified call to
+// swap. This is invalid, because it ends up calling itself with
+// the wrong number of arguments.
+//
+// The same problem afflicts a bunch of other class templates. Those
+// affected are array, pair, priority_queue, stack, and queue.
+
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=pair
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue
+
+// MSVC's standard library uses a very similar pattern that relies on delayed
+// parsing of exception specifications.
+//
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DMSVC
+
+#ifdef BE_THE_HEADER
+
+#pragma GCC system_header
+namespace std {
+ template<typename T> void swap(T &, T &);
+ template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) {
+ swap(a, b);
+ }
+
+ template<typename A, typename B> struct CLASS {
+#ifdef MSVC
+ void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member)));
+#endif
+ A member;
+#ifndef MSVC
+ void swap(CLASS &other) noexcept(noexcept(swap(member, other.member)));
+#endif
+ };
+
+// template<typename T> void do_swap(T &, T &);
+// template<typename A> struct vector {
+// void swap(vector &other) noexcept(noexcept(do_swap(member, other.member)));
+// A member;
+// };
+}
+
+#else
+
+#define BE_THE_HEADER
+#include __FILE__
+
+struct X {};
+using PX = std::CLASS<X, X>;
+using PI = std::CLASS<int, int>;
+void swap(X &, X &) noexcept;
+PX px;
+PI pi;
+
+static_assert(noexcept(px.swap(px)), "");
+static_assert(!noexcept(pi.swap(pi)), "");
+
+namespace sad {
+ template<typename T> void swap(T &, T &);
+
+ template<typename A, typename B> struct CLASS {
+ void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}}
+ };
+
+ CLASS<int, int> pi;
+
+ static_assert(!noexcept(pi.swap(pi)), ""); // expected-note {{in instantiation of}}
+}
+
+#endif
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index d8a00b3b1e24..b3ee30b456ec 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -14,7 +14,10 @@ public:
bool b();
int k;
struct Recurse {
- int &n = b() ? Recurse().n : k; // expected-error {{defaulted default constructor of 'Recurse' cannot be used by non-static data member initializer which appears before end of class definition}}
+ int &n = // expected-error {{cannot use defaulted default constructor of 'Recurse' within the class outside of member functions because 'n' has an initializer}}
+ b() ?
+ Recurse().n : // expected-note {{implicit default constructor for 'Recurse' first required here}}
+ k;
};
struct UnknownBound {
@@ -110,3 +113,82 @@ namespace PR18560 {
struct Y { int b = f(); };
}
+
+namespace template_valid {
+// Valid, we shouldn't build a CXXDefaultInitExpr until A's ctor definition.
+struct A {
+ A();
+ template <typename T>
+ struct B { int m1 = sizeof(A) + sizeof(T); };
+ B<int> m2;
+};
+A::A() {}
+}
+
+namespace template_default_ctor {
+struct A {
+ template <typename T>
+ struct B {
+ int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'B' within 'A' outside of member functions because 'm1' has an initializer}}
+ };
+ // expected-note@+1 {{implicit default constructor for 'template_default_ctor::A::B<int>' first required here}}
+ enum { NOE = noexcept(B<int>()) };
+};
+}
+
+namespace default_ctor {
+struct A {
+ struct B {
+ int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'B' within 'A' outside of member functions because 'm1' has an initializer}}
+ };
+ // expected-note@+1 {{implicit default constructor for 'default_ctor::A::B' first required here}}
+ enum { NOE = noexcept(B()) };
+};
+}
+
+namespace member_template {
+struct A {
+ template <typename T>
+ struct B {
+ struct C {
+ int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'C' within 'A' outside of member functions because 'm1' has an initializer}}
+ };
+ template <typename U>
+ struct D {
+ int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'D' within 'A' outside of member functions because 'm1' has an initializer}}
+ };
+ };
+ enum {
+ // expected-note@+1 {{implicit default constructor for 'member_template::A::B<int>::C' first required here}}
+ NOE1 = noexcept(B<int>::C()),
+ // expected-note@+1 {{implicit default constructor for 'member_template::A::B<int>::D<int>' first required here}}
+ NOE2 = noexcept(B<int>::D<int>())
+ };
+};
+}
+
+namespace explicit_instantiation {
+template<typename T> struct X {
+ X(); // expected-note {{in instantiation of default member initializer 'explicit_instantiation::X<float>::n' requested here}}
+ int n = T::error; // expected-error {{type 'float' cannot be used prior to '::' because it has no members}}
+};
+template struct X<int>; // ok
+template<typename T> X<T>::X() {}
+template struct X<float>; // expected-note {{in instantiation of member function 'explicit_instantiation::X<float>::X' requested here}}
+}
+
+namespace local_class {
+template<typename T> void f() {
+ struct X { // expected-note {{in instantiation of default member initializer 'local_class::f()::X::n' requested here}}
+ int n = T::error; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+ };
+}
+void g() { f<int>(); } // expected-note {{in instantiation of function template specialization 'local_class::f<int>' requested here}}
+}
+
+namespace PR22056 {
+template <int N>
+struct S {
+ int x[3] = {[N] = 3};
+};
+}
diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp
index e7c4ae9409e0..39cf601dc956 100644
--- a/test/SemaCXX/member-pointer-ms.cpp
+++ b/test/SemaCXX/member-pointer-ms.cpp
@@ -249,6 +249,25 @@ struct __virtual_inheritance D;
struct D : virtual B {};
}
#ifdef VMB
+
+namespace PR20017 {
+template <typename T>
+struct A {
+ int T::*f();
+};
+
+struct B;
+
+auto a = &A<B>::f;
+
+struct B {};
+
+void q() {
+ A<B> b;
+ (b.*a)();
+}
+}
+
#pragma pointers_to_members(full_generality, multiple_inheritance)
struct TrulySingleInheritance;
static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, "");
diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp
index e18b58b4d441..63615ecbd352 100644
--- a/test/SemaCXX/namespace-alias.cpp
+++ b/test/SemaCXX/namespace-alias.cpp
@@ -35,12 +35,12 @@ namespace H {
namespace A2 { }
// These all point to A1.
- namespace B = A1; // expected-note {{previous definition is here}}
+ namespace B = A1;
namespace B = A1;
namespace C = B;
- namespace B = C;
+ namespace B = C; // expected-note {{previously defined as an alias for 'A1'}}
- namespace B = A2; // expected-error {{redefinition of 'B' as different kind of symbol}}
+ namespace B = A2; // expected-error {{redefinition of 'B' as an alias for a different namespace}}
}
namespace I {
diff --git a/test/SemaCXX/nonnull.cpp b/test/SemaCXX/nonnull.cpp
index 9ff6d115bd16..97b54553427d 100644
--- a/test/SemaCXX/nonnull.cpp
+++ b/test/SemaCXX/nonnull.cpp
@@ -13,3 +13,8 @@ struct TS {
}
};
+namespace Template {
+ template<typename T> __attribute__((nonnull)) void f(T t);
+ void g() { f((void*)0); } // expected-warning {{null passed to a callee that requires a non-null argument}}
+ void h() { f(0); }
+}
diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp
index 28798a4f8ce8..7d765b482c73 100644
--- a/test/SemaCXX/nullptr.cpp
+++ b/test/SemaCXX/nullptr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion %s
#include <stdint.h>
typedef decltype(nullptr) nullptr_t;
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index feb7c716ff00..369e9eb802a5 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -519,3 +519,15 @@ namespace ConversionVersusTemplateOrdering {
int x = a;
int y = b;
}
+
+namespace NoADLForMemberOnlyOperators {
+ template<typename T> struct A { typename T::error e; }; // expected-error {{type 'char' cannot be used prior to '::'}}
+ template<typename T> struct B { int n; };
+
+ void f(B<A<void> > b1, B<A<int> > b2, B<A<char> > b3) {
+ b1 = b1; // ok, does not instantiate A<void>.
+ (void)b1->n; // expected-error {{is not a pointer}}
+ b2[3]; // expected-error {{does not provide a subscript}}
+ b3 / 0; // expected-note {{in instantiation of}} expected-error {{invalid operands to}}
+ }
+}
diff --git a/test/SemaCXX/override-in-system-header.cpp b/test/SemaCXX/override-in-system-header.cpp
new file mode 100644
index 000000000000..689585e0cf12
--- /dev/null
+++ b/test/SemaCXX/override-in-system-header.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs %s -verify
+// expected-no-diagnostics
+// rdar://18295240
+
+#include <override-system-header.h>
+
+struct A
+{
+ virtual void x();
+ END_COM_MAP;
+ IFACEMETHOD(Initialize)();
+};
+
+struct B : A
+{
+ virtual void x() override;
+ END_COM_MAP;
+ IFACEMETHOD(Initialize)();
+};
diff --git a/test/SemaCXX/pragma-optimize.cpp b/test/SemaCXX/pragma-optimize.cpp
index 0f03b81f5fff..48a15460fc96 100644
--- a/test/SemaCXX/pragma-optimize.cpp
+++ b/test/SemaCXX/pragma-optimize.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Os < %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -Oz < %s | FileCheck %s
#pragma clang optimize off
@@ -55,6 +57,13 @@ int __attribute__((always_inline)) baz(int z) {
}
// CHECK-DAG: @_Z3bazi{{.*}} [[ATTRBAZ:#[0-9]+]]
+// This function definition will not be decorated with `optnone` because the
+// attribute would conflict with `minsize`.
+int __attribute__((minsize)) bax(int z) {
+ return foo(z, 2);
+}
+// CHECK-DAG: @_Z3baxi{{.*}} [[ATTRBAX:#[0-9]+]]
+
#pragma clang optimize on
// The function "int wombat(int param)" created by the macro is not
@@ -96,18 +105,60 @@ int container3 (int par) {
// CHECK-DAG: @_Z6thriceIiET_S0_{{.*}} [[ATTRTHRICEINT:#[0-9]+]]
+// Test that we can re-open and re-close an "off" region after the first one,
+// and that this works as expected.
+
+#pragma clang optimize off
+
+int another_optnone(int x) {
+ return x << 1;
+}
+// CHECK-DAG: @_Z15another_optnonei{{.*}} [[ATTRANOTHEROPTNONE:#[0-9]+]]
+
+#pragma clang optimize on
+
+int another_normal(int x) {
+ return x << 2;
+}
+// CHECK-DAG: @_Z14another_normali{{.*}} [[ATTRANOTHERNORMAL:#[0-9]+]]
+
+
+// Test that we can re-open an "off" region by including a header with the
+// pragma and that this works as expected (i.e. the off region "falls through"
+// the end of the header into this file).
+
+#include <header-with-pragma-optimize-off.h>
+
+int yet_another_optnone(int x) {
+ return x << 3;
+}
+// CHECK-DAG: @_Z19yet_another_optnonei{{.*}} [[ATTRYETANOTHEROPTNONE:#[0-9]+]]
+
+#pragma clang optimize on
+
+int yet_another_normal(int x) {
+ return x << 4;
+}
+// CHECK-DAG: @_Z18yet_another_normali{{.*}} [[ATTRYETANOTHERNORMAL:#[0-9]+]]
+
+
// Check for both noinline and optnone on each function that should have them.
// CHECK-DAG: attributes [[ATTRBAR]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// CHECK-DAG: attributes [[ATTRCREATED]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// CHECK-DAG: attributes [[ATTRMETHOD]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// CHECK-DAG: attributes [[ATTRTHRICEFLOAT]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
+// CHECK-DAG: attributes [[ATTRANOTHEROPTNONE]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
+// CHECK-DAG: attributes [[ATTRYETANOTHEROPTNONE]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// Check that the other functions do NOT have optnone.
// CHECK-DAG-NOT: attributes [[ATTRFOO]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRBAZ]] = { {{.*}}optnone{{.*}} }
+// CHECK-DAG-NOT: attributes [[ATTRBAX]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRWOMBAT]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRTWICE]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER2]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER3]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRTHRICEINT]] = { {{.*}}optnone{{.*}} }
+// CHECK-DAG-NOT: attributes [[ATTRANOTHERNORMAL]] = { {{.*}}optnone{{.*}} }
+// CHECK-DAG-NOT: attributes [[ATTRYETANOTHERNORMAL]] = { {{.*}}optnone{{.*}} }
diff --git a/test/SemaCXX/predefined-expr.cpp b/test/SemaCXX/predefined-expr.cpp
index 257d44c60069..f4a155da6678 100644
--- a/test/SemaCXX/predefined-expr.cpp
+++ b/test/SemaCXX/predefined-expr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++1y -fblocks -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -std=c++1y -fblocks -fsyntax-only -triple %itanium_abi_triple -verify %s
// PR16946
// expected-no-diagnostics
@@ -33,10 +33,9 @@ int baz() {
();
^{
- // FIXME: This is obviously wrong.
- static_assert(sizeof(__func__) == 1, "__baz_block_invoke");
- static_assert(sizeof(__FUNCTION__) == 1, "__baz_block_invoke");
- static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__baz_block_invoke");
+ static_assert(sizeof(__func__) == 27, "___Z3bazIiEiv_block_invoke");
+ static_assert(sizeof(__FUNCTION__) == 27, "___Z3bazIiEiv_block_invoke");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 27, "___Z3bazIiEiv_block_invoke");
}
();
@@ -65,10 +64,9 @@ int main() {
();
^{
- // FIXME: This is obviously wrong.
- static_assert(sizeof(__func__) == 1, "__main_block_invoke");
- static_assert(sizeof(__FUNCTION__) == 1, "__main_block_invoke");
- static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__main_block_invoke");
+ static_assert(sizeof(__func__) == 20, "__main_block_invoke");
+ static_assert(sizeof(__FUNCTION__) == 20, "__main_block_invoke");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "__main_block_invoke");
}
();
diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp
index 531dc23995d2..cdd96e6a9ec4 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 -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
+// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
+// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -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));
@@ -143,7 +143,84 @@ template <PR9412_MatchType type> int PR9412_t() {
} // expected-warning {{control reaches end of non-void function}}
void PR9412_f() {
- PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<0>' requested here}}
+ PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_MatchType::PR9412_Exact>' requested here}}
+}
+
+struct NoReturn {
+ ~NoReturn() __attribute__((noreturn));
+ operator bool() const;
+};
+struct Return {
+ ~Return();
+ operator bool() const;
+};
+
+int testTernaryUnconditionalNoreturn() {
+ true ? NoReturn() : NoReturn();
+}
+
+int testTernaryStaticallyConditionalNoretrunOnTrue() {
+ true ? NoReturn() : Return();
+}
+
+int testTernaryStaticallyConditionalRetrunOnTrue() {
+ true ? Return() : NoReturn();
+} // expected-warning {{control reaches end of non-void function}}
+
+int testTernaryStaticallyConditionalNoretrunOnFalse() {
+ false ? Return() : NoReturn();
+}
+
+int testTernaryStaticallyConditionalRetrunOnFalse() {
+ false ? NoReturn() : Return();
+} // expected-warning {{control reaches end of non-void function}}
+
+int testTernaryConditionalNoreturnTrueBranch(bool value) {
+ value ? (NoReturn() || NoReturn()) : Return();
+} // expected-warning {{control may reach end of non-void function}}
+
+int testTernaryConditionalNoreturnFalseBranch(bool value) {
+ value ? Return() : (NoReturn() || NoReturn());
+} // expected-warning {{control may reach end of non-void function}}
+
+int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
+ value || (true ? NoReturn() : true);
+} // expected-warning {{control may reach end of non-void function}}
+
+int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
+ value || (false ? true : NoReturn());
+} // expected-warning {{control may reach end of non-void function}}
+
+int testStaticallyExecutedLogicalOrBranch() {
+ false || NoReturn();
+}
+
+int testStaticallyExecutedLogicalAndBranch() {
+ true && NoReturn();
+}
+
+int testStaticallySkippedLogicalOrBranch() {
+ true || NoReturn();
+} // expected-warning {{control reaches end of non-void function}}
+
+int testStaticallySkppedLogicalAndBranch() {
+ false && NoReturn();
+} // expected-warning {{control reaches end of non-void function}}
+
+int testConditionallyExecutedComplexLogicalBranch(bool value) {
+ value || (true && NoReturn());
+} // expected-warning {{control may reach end of non-void function}}
+
+int testConditionallyExecutedComplexLogicalBranch2(bool value) {
+ (true && value) || (true && NoReturn());
+} // expected-warning {{control may reach end of non-void function}}
+
+int testConditionallyExecutedComplexLogicalBranch3(bool value) {
+ (false && (Return() || true)) || (true && NoReturn());
+}
+
+int testConditionallyExecutedComplexLogicalBranch4(bool value) {
+ false || ((Return() || true) && (true && NoReturn()));
}
#if __cplusplus >= 201103L
@@ -168,3 +245,20 @@ namespace LambdaVsTemporaryDtor {
} // ok, initialization of lambda does not return
}
#endif
+
+// Ensure that function-try-blocks also check for return values properly.
+int functionTryBlock1(int s) try {
+ return 0;
+} catch (...) {
+} // expected-warning {{control may reach end of non-void function}}
+
+int functionTryBlock2(int s) try {
+} catch (...) {
+ return 0;
+} // expected-warning {{control may reach end of non-void function}}
+
+int functionTryBlock3(int s) try {
+ return 0;
+} catch (...) {
+ return 0;
+} // ok, both paths return.
diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp
index 98dbd51f5806..8c1664516a71 100644
--- a/test/SemaCXX/return.cpp
+++ b/test/SemaCXX/return.cpp
@@ -112,3 +112,11 @@ namespace ctor_returns_void {
~S() { return f(); } // expected-error {{destructor '~S' must not return void expression}}
};
}
+
+void cxx_unresolved_expr() {
+ // The use of an undeclared variable tricks clang into building a
+ // CXXUnresolvedConstructExpr, and the missing ')' gives it an invalid source
+ // location for its rparen. Check that emitting a diag on the range of the
+ // expr doesn't assert.
+ return int(undeclared, 4; // expected-error {{expected ')'}} expected-note{{to match this '('}} expected-error {{void function 'cxx_unresolved_expr' should not return a value}} expected-error {{use of undeclared identifier 'undeclared'}}
+}
diff --git a/test/SemaCXX/runtimediag-ppe.cpp b/test/SemaCXX/runtimediag-ppe.cpp
index 0e8451b472e7..2788963b6c1b 100644
--- a/test/SemaCXX/runtimediag-ppe.cpp
+++ b/test/SemaCXX/runtimediag-ppe.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value %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
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index dc15dc8b3e60..ac700999c284 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -32,7 +32,7 @@ namespace test1 {
int f(bool b) {
if (b)
- goto foo; // expected-error {{goto into protected scope}}
+ goto foo; // expected-error {{cannot jump}}
C c; // expected-note {{jump bypasses variable initialization}}
foo:
return 1;
@@ -79,7 +79,7 @@ namespace test4 {
C c0;
- goto *ip; // expected-error {{indirect goto might cross protected scopes}}
+ goto *ip; // expected-error {{cannot jump}}
C c1; // expected-note {{jump bypasses variable initialization}}
lbl1: // expected-note {{possible target of indirect goto}}
return 0;
@@ -103,7 +103,7 @@ namespace test5 {
if (ip[1]) {
D d; // expected-note {{jump exits scope of variable with non-trivial destructor}}
ip += 2;
- goto *ip; // expected-error {{indirect goto might cross protected scopes}}
+ goto *ip; // expected-error {{cannot jump}}
}
return 1;
}
@@ -153,13 +153,13 @@ namespace test8 {
switch (c) {
case 0:
int x = 56; // expected-note {{jump bypasses variable initialization}}
- case 1: // expected-error {{switch case is in protected scope}}
+ case 1: // expected-error {{cannot jump}}
x = 10;
}
}
void test2() {
- goto l2; // expected-error {{goto into protected scope}}
+ goto l2; // expected-error {{cannot jump}}
l1: int x = 5; // expected-note {{jump bypasses variable initialization}}
l2: x++;
}
@@ -208,7 +208,7 @@ namespace PR10462 {
namespace test10 {
int test() {
static void *ps[] = { &&a0 };
- goto *&&a0; // expected-error {{goto into protected scope}}
+ goto *&&a0; // expected-error {{cannot jump}}
int a = 3; // expected-note {{jump bypasses variable initialization}}
a0:
return 0;
@@ -225,7 +225,7 @@ namespace test11 {
static void *ips[] = { &&l0 };
l0: // expected-note {{possible target of indirect goto}}
C c0 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}}
- goto *ip; // expected-error {{indirect goto might cross protected scopes}}
+ goto *ip; // expected-error {{cannot jump}}
}
}
@@ -240,7 +240,7 @@ namespace test12 {
l0: // expected-note {{possible target of indirect goto}}
const C &c1 = 42; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
const C &c2 = c0;
- goto *ip; // expected-error {{indirect goto might cross protected scopes}}
+ goto *ip; // expected-error {{cannot jump}}
}
}
@@ -254,7 +254,7 @@ namespace test13 {
static void *ips[] = { &&l0 };
l0: // expected-note {{possible target of indirect goto}}
const int &c1 = C(1).i; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
- goto *ip; // expected-error {{indirect goto might cross protected scopes}}
+ goto *ip; // expected-error {{cannot jump}}
}
}
@@ -276,21 +276,21 @@ namespace test14 {
// PR14225
namespace test15 {
void f1() try {
- goto x; // expected-error {{goto into protected scope}}
+ goto x; // expected-error {{cannot jump}}
} catch(...) { // expected-note {{jump bypasses initialization of catch block}}
x: ;
}
void f2() try { // expected-note {{jump bypasses initialization of try block}}
x: ;
} catch(...) {
- goto x; // expected-error {{goto into protected scope}}
+ goto x; // expected-error {{cannot jump}}
}
}
namespace test16 {
struct S { int n; };
int f() {
- goto x; // expected-error {{goto into protected scope}}
+ goto x; // expected-error {{cannot jump}}
const S &s = S(); // expected-note {{jump bypasses variable initialization}}
x: return s.n;
}
@@ -300,7 +300,7 @@ x: return s.n;
namespace test17 {
struct S { int get(); private: int n; };
int f() {
- goto x; // expected-error {{goto into protected scope}}
+ goto x; // expected-error {{cannot jump}}
S s = {}; // expected-note {{jump bypasses variable initialization}}
x: return s.get();
}
@@ -321,7 +321,7 @@ namespace test18 {
void *p = &&x;
x: // expected-note {{possible target of indirect goto}}
B b = { 0, A() }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
- goto *p; // expected-error {{indirect goto might cross protected scopes}}
+ goto *p; // expected-error {{cannot jump}}
}
}
@@ -342,7 +342,7 @@ namespace test19 {
A a;
x: // expected-note {{possible target of indirect goto}}
std::initializer_list<A> il = { a }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
- goto *p; // expected-error {{indirect goto might cross protected scopes}}
+ goto *p; // expected-error {{cannot jump}}
}
}
@@ -370,14 +370,14 @@ namespace test20 {
a,
{ A() } // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
};
- goto *p; // expected-error {{indirect goto might cross protected scopes}}
+ goto *p; // expected-error {{cannot jump}}
}
}
#endif
namespace test21 {
template<typename T> void f() {
- goto x; // expected-error {{protected scope}}
+ goto x; // expected-error {{cannot jump}}
T t; // expected-note {{bypasses}}
x: return;
}
@@ -428,7 +428,7 @@ namespace test_recovery {
void test(nexist, int c) { // expected-error {{}}
nexist_fn(); // expected-error {{}}
goto nexist_label; // expected-error {{use of undeclared label}}
- goto a0; // expected-error {{goto into protected scope}}
+ goto a0; // expected-error {{cannot jump}}
int a = 0; // expected-note {{jump bypasses variable initialization}}
a0:;
@@ -436,7 +436,7 @@ namespace test_recovery {
case $: // expected-error {{}}
case 0:
int x = 56; // expected-note {{jump bypasses variable initialization}}
- case 1: // expected-error {{switch case is in protected scope}}
+ case 1: // expected-error {{cannot jump}}
x = 10;
}
}
diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp
index 6d04c84a6752..15b0b50ddc75 100644
--- a/test/SemaCXX/statements.cpp
+++ b/test/SemaCXX/statements.cpp
@@ -10,7 +10,7 @@ struct X {
};
void test2() {
- goto later; // expected-error {{goto into protected scope}}
+ goto later; // expected-error {{cannot jump}}
X x; // expected-note {{jump bypasses variable initialization}}
later:
;
@@ -20,3 +20,20 @@ namespace PR6536 {
struct A {};
void a() { goto out; A x; out: return; }
}
+
+void test3() {
+ __asm__ ("":"+r" (test3)); // expected-error{{invalid lvalue in asm output}}
+}
+
+void test4(); // expected-note{{possible target for call}}
+void test4(int) { // expected-note{{possible target for call}}
+ // expected-error@+1{{overloaded function could not be resolved}}
+ __asm__ ("":"+r" (test4)); // expected-error{{invalid lvalue in asm output}}
+}
+void test5() {
+ char buf[1];
+ __asm__ ("":"+r" (buf));
+}
+
+struct MMX_t {};
+void test6() { __asm__("" : "=m"(*(MMX_t *)0)); }
diff --git a/test/SemaCXX/string-plus-int.cpp b/test/SemaCXX/string-plus-int.cpp
index 5752f8f96631..fe9c71949698 100644
--- a/test/SemaCXX/string-plus-int.cpp
+++ b/test/SemaCXX/string-plus-int.cpp
@@ -64,3 +64,8 @@ void f(int index) {
consume(A B + sizeof(A) - 1);
}
+template <typename T>
+void PR21848() {
+ (void)(sizeof(T) + ""); // expected-warning {{to a string does not append to the string}} expected-note {{use array indexing to silence this warning}}
+}
+template void PR21848<int>(); // expected-note {{in instantiation of function template specialization 'PR21848<int>' requested here}}
diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp
index e1b95ba8d63c..706ec5688ba5 100644
--- a/test/SemaCXX/struct-class-redecl.cpp
+++ b/test/SemaCXX/struct-class-redecl.cpp
@@ -7,6 +7,12 @@ union X { int x; float y; }; // expected-error{{use of 'X' with tag type that do
template<typename T> struct Y; // expected-note{{did you mean class here?}}
template<class U> class Y { }; // expected-warning{{previously declared}}
+template <typename>
+struct Z { // expected-note{{previous definition is here}}
+ struct Z { // expected-error{{nested redefinition of 'Z'}}
+ };
+};
+
class A;
class A; // expected-note{{previous use is here}}
struct A; // expected-warning{{struct 'A' was previously declared as a class}}
diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp
index cf5e659660eb..c6b22c54be0c 100644
--- a/test/SemaCXX/trailing-return-0x.cpp
+++ b/test/SemaCXX/trailing-return-0x.cpp
@@ -17,8 +17,8 @@ auto f() -> int
return 0;
}
-auto g(); // expected-error{{return without trailing return type; deduced return types are a C++1y extension}}
-decltype(auto) g2(); // expected-warning{{extension}} expected-error-re{{{{^}}deduced return types are a C++1y extension}}
+auto g(); // expected-error{{return without trailing return type; deduced return types are a C++14 extension}}
+decltype(auto) g2(); // expected-warning{{extension}} expected-error-re{{{{^}}deduced return types are a C++14 extension}}
auto badness = g2();
int h() -> int; // expected-error{{trailing return type must specify return type 'auto', not 'int'}}
@@ -75,14 +75,14 @@ only<double> p4 = xx.get_nested<double>().h(0L, 1.0, 3.14f);
namespace PR12053 {
template <typename T>
auto f1(T t) -> decltype(f1(t)) {} // expected-note{{candidate template ignored}}
-
+
void test_f1() {
f1(0); // expected-error{{no matching function for call to 'f1'}}
}
-
+
template <typename T>
auto f2(T t) -> decltype(f2(&t)) {} // expected-note{{candidate template ignored}}
-
+
void test_f2() {
f2(0); // expected-error{{no matching function for call to 'f2'}}
}
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index 3b94ef0951eb..4833c14b30be 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -146,6 +146,10 @@ struct ThreeArgCtor {
ThreeArgCtor(int*, char*, int);
};
+struct VariadicCtor {
+ template<typename...T> VariadicCtor(T...);
+};
+
void is_pod()
{
{ int arr[T(__is_pod(int))]; }
@@ -1968,6 +1972,10 @@ void constructible_checks() {
// PR19178
{ int arr[F(__is_constructible(Abstract))]; }
{ int arr[F(__is_nothrow_constructible(Abstract))]; }
+
+ // PR20228
+ { int arr[T(__is_constructible(VariadicCtor,
+ int, int, int, int, int, int, int, int, int))]; }
}
// Instantiation of __is_trivially_constructible
diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp
index d3a2a28deb8b..48fcce0b4924 100644
--- a/test/SemaCXX/typeid.cpp
+++ b/test/SemaCXX/typeid.cpp
@@ -21,3 +21,9 @@ void g1(X &x) {
(void)typeid(X&); // expected-error{{'typeid' of incomplete type 'X'}}
(void)typeid(x); // expected-error{{'typeid' of incomplete type 'X'}}
}
+
+void h(int i) {
+ char V[i];
+ typeid(V); // expected-error{{'typeid' of variably modified type 'char [i]'}}
+ typeid(char [i]); // expected-error{{'typeid' of variably modified type 'char [i]'}}
+}
diff --git a/test/SemaCXX/typo-correction-delayed.cpp b/test/SemaCXX/typo-correction-delayed.cpp
new file mode 100644
index 000000000000..e028faad2510
--- /dev/null
+++ b/test/SemaCXX/typo-correction-delayed.cpp
@@ -0,0 +1,159 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
+
+struct A {};
+struct B {};
+struct D {
+ A fizbin; // expected-note 2 {{declared here}}
+ A foobar; // expected-note 2 {{declared here}}
+ B roxbin; // expected-note 2 {{declared here}}
+ B toobad; // expected-note 2 {{declared here}}
+ void BooHoo();
+ void FoxBox();
+};
+
+void something(A, B);
+void test() {
+ D obj;
+ something(obj.fixbin, // expected-error {{did you mean 'fizbin'?}}
+ obj.toobat); // expected-error {{did you mean 'toobad'?}}
+ something(obj.toobat, // expected-error {{did you mean 'foobar'?}}
+ obj.fixbin); // expected-error {{did you mean 'roxbin'?}}
+ something(obj.fixbin, // expected-error {{did you mean 'fizbin'?}}
+ obj.fixbin); // expected-error {{did you mean 'roxbin'?}}
+ something(obj.toobat, // expected-error {{did you mean 'foobar'?}}
+ obj.toobat); // expected-error {{did you mean 'toobad'?}}
+ // Both members could be corrected to methods, but that isn't valid.
+ something(obj.boohoo, // expected-error-re {{no member named 'boohoo' in 'D'{{$}}}}
+ obj.foxbox); // expected-error-re {{no member named 'foxbox' in 'D'{{$}}}}
+ // The first argument has a usable correction but the second doesn't.
+ something(obj.boobar, // expected-error-re {{no member named 'boobar' in 'D'{{$}}}}
+ obj.foxbox); // expected-error-re {{no member named 'foxbox' in 'D'{{$}}}}
+}
+
+// Ensure the delayed typo correction does the right thing when trying to
+// recover using a seemingly-valid correction for which a valid expression to
+// replace the TypoExpr cannot be created (but which does have a second
+// correction candidate that would be a valid and usable correction).
+class Foo {
+public:
+ template <> void testIt(); // expected-error {{no function template matches}}
+ void textIt(); // expected-note {{'textIt' declared here}}
+};
+void testMemberExpr(Foo *f) {
+ f->TestIt(); // expected-error {{no member named 'TestIt' in 'Foo'; did you mean 'textIt'?}}
+}
+
+void callee(double, double);
+void testNoCandidates() {
+ callee(xxxxxx, // expected-error-re {{use of undeclared identifier 'xxxxxx'{{$}}}}
+ zzzzzz); // expected-error-re {{use of undeclared identifier 'zzzzzz'{{$}}}}
+}
+
+class string {};
+struct Item {
+ void Nest();
+ string text();
+ Item* next(); // expected-note {{'next' declared here}}
+};
+void testExprFilter(Item *i) {
+ Item *j;
+ j = i->Next(); // expected-error {{no member named 'Next' in 'Item'; did you mean 'next'?}}
+}
+
+// Test that initializer expressions are handled correctly and that the type
+// being initialized is taken into account when choosing a correction.
+namespace initializerCorrections {
+struct Node {
+ string text() const;
+ // Node* Next() is not implemented yet
+};
+void f(Node *node) {
+ // text is only an edit distance of 1 from Next, but would trigger type
+ // conversion errors if used in this initialization expression.
+ Node *next = node->Next(); // expected-error-re {{no member named 'Next' in 'initializerCorrections::Node'{{$}}}}
+}
+
+struct LinkedNode {
+ LinkedNode* next(); // expected-note {{'next' declared here}}
+ string text() const;
+};
+void f(LinkedNode *node) {
+ // text and next are equidistant from Next, but only one results in a valid
+ // initialization expression.
+ LinkedNode *next = node->Next(); // expected-error {{no member named 'Next' in 'initializerCorrections::LinkedNode'; did you mean 'next'?}}
+}
+
+struct NestedNode {
+ NestedNode* Nest();
+ NestedNode* next();
+ string text() const;
+};
+void f(NestedNode *node) {
+ // There are two equidistant, usable corrections for Next: next and Nest
+ NestedNode *next = node->Next(); // expected-error-re {{no member named 'Next' in 'initializerCorrections::NestedNode'{{$}}}}
+}
+}
+
+namespace PR21669 {
+void f(int *i) {
+ // Check that arguments to a builtin with custom type checking are corrected
+ // properly, since calls to such builtins bypass much of the normal code path
+ // for building and checking the call.
+ __atomic_load(i, i, something_something); // expected-error-re {{use of undeclared identifier 'something_something'{{$}}}}
+}
+}
+
+const int DefaultArg = 9; // expected-note {{'DefaultArg' declared here}}
+template <int I = defaultArg> struct S {}; // expected-error {{use of undeclared identifier 'defaultArg'; did you mean 'DefaultArg'?}}
+S<1> s;
+
+namespace foo {}
+void test_paren_suffix() {
+ foo::bar({5, 6}); // expected-error-re {{no member named 'bar' in namespace 'foo'{{$}}}} \
+ // expected-error {{expected expression}}
+}
+
+const int kNum = 10; // expected-note {{'kNum' declared here}}
+class SomeClass {
+ int Kind;
+public:
+ explicit SomeClass() : Kind(kSum) {} // expected-error {{use of undeclared identifier 'kSum'; did you mean 'kNum'?}}
+};
+
+// There used to be an issue with typo resolution inside overloads.
+struct AssertionResult { ~AssertionResult(); };
+AssertionResult Overload(const char *a);
+AssertionResult Overload(int a);
+void UseOverload() {
+ // expected-note@+1 {{'result' declared here}}
+ const char *result;
+ // expected-error@+1 {{use of undeclared identifier 'resulta'; did you mean 'result'?}}
+ Overload(resulta);
+}
+
+namespace PR21925 {
+struct X {
+ int get() { return 7; } // expected-note {{'get' declared here}}
+};
+void test() {
+ X variable; // expected-note {{'variable' declared here}}
+
+ // expected-error@+2 {{use of undeclared identifier 'variableX'; did you mean 'variable'?}}
+ // expected-error@+1 {{no member named 'getX' in 'PR21925::X'; did you mean 'get'?}}
+ int x = variableX.getX();
+}
+}
+
+namespace PR21905 {
+int (*a) () = (void)Z; // expected-error-re {{use of undeclared identifier 'Z'{{$}}}}
+}
+
+namespace PR21947 {
+int blue; // expected-note {{'blue' declared here}}
+__typeof blur y; // expected-error {{use of undeclared identifier 'blur'; did you mean 'blue'?}}
+}
+
+namespace PR22092 {
+a = b ? : 0; // expected-error {{C++ requires a type specifier for all declarations}} \
+ // expected-error-re {{use of undeclared identifier 'b'{{$}}}}
+}
diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp
deleted file mode 100644
index 88a7073f9946..000000000000
--- a/test/SemaCXX/typo-correction-pt2.cpp
+++ /dev/null
@@ -1,302 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
-//
-// FIXME: This file is overflow from test/SemaCXX/typo-correction.cpp due to a
-// hard-coded limit of 20 different typo corrections Sema::CorrectTypo will
-// attempt within a single file (which is to avoid having very broken files take
-// minutes to finally be rejected by the parser).
-
-namespace PR12951 {
-// If there are two corrections that have the same identifier and edit distance
-// and only differ by their namespaces, don't suggest either as a correction
-// since both are equally likely corrections.
-namespace foobar { struct Thing {}; }
-namespace bazquux { struct Thing {}; }
-void f() { Thing t; } // expected-error{{unknown type name 'Thing'}}
-}
-
-namespace bogus_keyword_suggestion {
-void test() {
- status = "OK"; // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
- return status; // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
- }
-}
-
-namespace PR13387 {
-struct A {
- void CreateFoo(float, float);
- void CreateBar(float, float);
-};
-struct B : A {
- using A::CreateFoo;
- void CreateFoo(int, int);
-};
-void f(B &x) {
- x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}}
-}
-}
-
-struct DataStruct {void foo();};
-struct T {
- DataStruct data_struct;
- void f();
-};
-// should be void T::f();
-void f() {
- data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'{{$}}}}
-}
-
-namespace PR12287 {
-class zif {
- void nab(int);
-};
-void nab(); // expected-note{{'::PR12287::nab' declared here}}
-void zif::nab(int) {
- nab(); // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::PR12287::nab'?}}
-}
-}
-
-namespace TemplateFunction {
-template <class T>
-void A(T) { } // expected-note {{'::TemplateFunction::A' declared here}}
-
-template <class T>
-void B(T) { } // expected-note {{'::TemplateFunction::B' declared here}}
-
-class Foo {
- public:
- void A(int, int) {}
- void B() {}
-};
-
-void test(Foo F, int num) {
- F.A(num); // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}}
- F.B(num); // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}}
-}
-}
-namespace using_suggestion_val_dropped_specifier {
-void FFF() {} // expected-note {{'::using_suggestion_val_dropped_specifier::FFF' declared here}}
-namespace N { }
-using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean '::using_suggestion_val_dropped_specifier::FFF'?}}
-}
-
-namespace class_member_typo_corrections {
-class Outer {
-public:
- class Inner {}; // expected-note {{'Outer::Inner' declared here}}
- Inner MyMethod(Inner arg);
-};
-
-Inner Outer::MyMethod(Inner arg) { // expected-error {{unknown type name 'Inner'; did you mean 'Outer::Inner'?}}
- return Inner();
-}
-
-class Result {
-public:
- enum ResultType {
- ENTITY, // expected-note {{'Result::ENTITY' declared here}}
- PREDICATE, // expected-note {{'Result::PREDICATE' declared here}}
- LITERAL // expected-note {{'Result::LITERAL' declared here}}
- };
-
- ResultType type();
-};
-
-void test() {
- Result result_cell;
- switch (result_cell.type()) {
- case ENTITY: // expected-error {{use of undeclared identifier 'ENTITY'; did you mean 'Result::ENTITY'?}}
- case LITERAL: // expected-error {{use of undeclared identifier 'LITERAL'; did you mean 'Result::LITERAL'?}}
- case PREDICAT: // expected-error {{use of undeclared identifier 'PREDICAT'; did you mean 'Result::PREDICATE'?}}
- break;
- }
-}
-
-class Figure {
- enum ResultType {
- SQUARE,
- TRIANGLE,
- CIRCLE
- };
-
-public:
- ResultType type();
-};
-
-void testAccess() {
- Figure obj;
- switch (obj.type()) { // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
- case SQUARE: // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
- case TRIANGLE: // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
- case CIRCE: // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
- break;
- }
-}
-}
-
-long readline(const char *, char *, unsigned long);
-void assign_to_unknown_var() {
- deadline_ = 1; // expected-error-re {{use of undeclared identifier 'deadline_'{{$}}}}
-}
-
-namespace no_ns_before_dot {
-namespace re2 {}
-void test() {
- req.set_check(false); // expected-error-re {{use of undeclared identifier 'req'{{$}}}}
-}
-}
-
-namespace PR17394 {
- class A {
- protected:
- long zzzzzzzzzz;
- };
- class B : private A {};
- B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{}
-}
-
-namespace correct_fields_in_member_funcs {
-struct S {
- int my_member; // expected-note {{'my_member' declared here}}
- void f() { my_menber = 1; } // expected-error {{use of undeclared identifier 'my_menber'; did you mean 'my_member'?}}
-};
-}
-
-namespace PR17019 {
- template<class F>
- struct evil {
- evil(F de) { // expected-note {{'de' declared here}}
- de_; // expected-error {{use of undeclared identifier 'de_'; did you mean 'de'?}} \
- // expected-warning {{expression result unused}}
- }
- ~evil() {
- de_->bar() // expected-error {{use of undeclared identifier 'de_'}}
- }
- };
-
- void meow() {
- evil<int> Q(0); // expected-note {{in instantiation of member function}}
- }
-}
-
-namespace fix_class_name_qualifier {
-class MessageHeaders {};
-class MessageUtils {
- public:
- static void ParseMessageHeaders(int, int); // expected-note {{'MessageUtils::ParseMessageHeaders' declared here}}
-};
-
-void test() {
- // No, we didn't mean to call MessageHeaders::MessageHeaders.
- MessageHeaders::ParseMessageHeaders(5, 4); // expected-error {{no member named 'ParseMessageHeaders' in 'fix_class_name_qualifier::MessageHeaders'; did you mean 'MessageUtils::ParseMessageHeaders'?}}
-}
-}
-
-namespace PR18213 { // expected-note {{'PR18213' declared here}}
-struct WrapperInfo {
- int i;
-};
-
-template <typename T> struct Wrappable {
- static WrapperInfo kWrapperInfo;
-};
-
-// Note the space before "::PR18213" is intended and needed, as it highlights
-// the actual typo, which is the leading "::".
-// TODO: Suggest removing the "::" from "::PR18213" (the right correction)
-// instead of incorrectly suggesting dropping "PR18213::WrapperInfo::".
-template <>
-PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 }; // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \
- // expected-error {{C++ requires a type specifier for all declarations}}
-}
-
-namespace PR18651 {
-struct {
- int x;
-} a, b;
-
-int y = x; // expected-error-re {{use of undeclared identifier 'x'{{$}}}}
-}
-
-namespace PR18685 {
-template <class C, int I, int J>
-class SetVector {
- public:
- SetVector() {}
-};
-
-template <class C, int I>
-class SmallSetVector : public SetVector<C, I, 8> {};
-
-class foo {};
-SmallSetVector<foo*, 2> fooSet;
-}
-
-PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}}
-
-namespace shadowed_template {
-template <typename T> class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}}
-class Baz {
- int Fizbin();
- // TODO: Teach the parser to recover from the typo correction instead of
- // continuing to treat the template name as an implicit-int declaration.
- Fizbin<int> qux; // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \
- // expected-error {{expected member name or ';' after declaration specifiers}}
-};
-}
-
-namespace PR18852 {
-void func() {
- struct foo {
- void bar() {}
- };
- bar(); // expected-error-re {{use of undeclared identifier 'bar'{{$}}}}
-}
-
-class Thread {
- public:
- void Start();
- static void Stop(); // expected-note {{'Thread::Stop' declared here}}
-};
-
-class Manager {
- public:
- void Start(int); // expected-note {{'Start' declared here}}
- void Stop(int); // expected-note {{'Stop' declared here}}
-};
-
-void test(Manager *m) {
- // Don't suggest Thread::Start as a correction just because it has the same
- // (unqualified) name and accepts the right number of args; this is a method
- // call on an object in an unrelated class.
- m->Start(); // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
- m->Stop(); // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
- Stop(); // expected-error {{use of undeclared identifier 'Stop'; did you mean 'Thread::Stop'?}}
-}
-
-}
-
-namespace std {
-class bernoulli_distribution {
- public:
- double p() const;
-};
-}
-void test() {
- // Make sure that typo correction doesn't suggest changing 'p' to
- // 'std::bernoulli_distribution::p' as that is most likely wrong.
- if (p) // expected-error-re {{use of undeclared identifier 'p'{{$}}}}
- return;
-}
-
-namespace PR19681 {
- struct TypoA {};
- struct TypoB {
- void test();
- private:
- template<typename T> void private_memfn(T); // expected-note{{declared here}}
- };
- void TypoB::test() {
- // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn'
- (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn); // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}}
- }
-}
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index e8160b066de4..324900150c7f 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -1,8 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
-//
-// WARNING: Do not add more typo correction test cases to this file lest you run
-// afoul the hard-coded limit (escape hatch) of 20 different typos whose
-// correction was attempted by Sema::CorrectTypo
+// RUN: %clang_cc1 -fspell-checking-limit 0 -verify -Wno-c++11-extensions %s
+
+namespace PR21817{
+int a(-rsing[2]); // expected-error {{undeclared identifier 'rsing'; did you mean 'using'?}}
+ // expected-error@-1 {{expected expression}}
+}
struct errc {
int v_;
@@ -97,7 +98,7 @@ unknown_type_test::stream_out out; // expected-error{{no type named 'stream_out'
// 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 {
+namespace cache_invalidation_test {
using namespace unknown_type_test;
void bar(long i);
void before_caching_classname() {
@@ -209,11 +210,12 @@ namespace PR13051 {
};
void foo(); // expected-note{{'foo' declared here}}
- void g(void(*)());
- void g(bool(S<int>::*)() const);
+ void g(void(*)()); // expected-note{{candidate function not viable}}
+ void g(bool(S<int>::*)() const); // expected-note{{candidate function not viable}}
void test() {
- g(&S<int>::tempalte f<int>); // expected-error{{did you mean 'template'?}}
+ g(&S<int>::tempalte f<int>); // expected-error{{did you mean 'template'?}} \
+ // expected-error{{no matching function for call to 'g'}}
g(&S<int>::opeartor bool); // expected-error{{did you mean 'operator'?}}
g(&S<int>::foo); // expected-error{{no member named 'foo' in 'PR13051::S<int>'; did you mean simply 'foo'?}}
}
@@ -247,7 +249,7 @@ namespace b6956809_test1 {
struct S1 {
void method(A*); // no note here
- void method(B*);
+ void method(B*); // expected-note{{'method' declared here}}
};
void test1() {
@@ -258,15 +260,15 @@ namespace b6956809_test1 {
struct S2 {
S2();
- void method(A*) const; // expected-note{{candidate function not viable}}
+ void method(A*) const;
private:
- void method(B*); // expected-note{{candidate function not viable}}
+ void method(B*);
};
void test2() {
B b;
const S2 s;
- s.methodd(&b); // expected-error{{no member named 'methodd' in 'b6956809_test1::S2'; did you mean 'method'}} expected-error{{no matching member function for call to 'method'}}
+ s.methodd(&b); // expected-error-re{{no member named 'methodd' in 'b6956809_test1::S2'{{$}}}}
}
}
@@ -274,7 +276,7 @@ namespace b6956809_test2 {
template<typename T> struct Err { typename T::error n; }; // expected-error{{type 'void *' cannot be used prior to '::' because it has no members}}
struct S {
template<typename T> typename Err<T>::type method(T); // expected-note{{in instantiation of template class 'b6956809_test2::Err<void *>' requested here}}
- template<typename T> int method(T *);
+ template<typename T> int method(T *); // expected-note{{'method' declared here}}
};
void test() {
@@ -283,13 +285,352 @@ namespace b6956809_test2 {
}
}
-// This test should have one correction, followed by an error without a
-// suggestion due to exceeding the maximum number of typos for which correction
-// is attempted.
-namespace CorrectTypo_has_reached_its_limit {
-int flibberdy(); // expected-note{{'flibberdy' declared here}}
-int no_correction() {
- return hibberdy() + // expected-error{{use of undeclared identifier 'hibberdy'; did you mean 'flibberdy'?}}
- gibberdy(); // expected-error-re{{use of undeclared identifier 'gibberdy'{{$}}}}
+namespace PR12951 {
+// If there are two corrections that have the same identifier and edit distance
+// and only differ by their namespaces, don't suggest either as a correction
+// since both are equally likely corrections.
+namespace foobar { struct Thing {}; }
+namespace bazquux { struct Thing {}; }
+void f() { Thing t; } // expected-error{{unknown type name 'Thing'}}
+}
+
+namespace bogus_keyword_suggestion {
+void test() {
+ status = "OK"; // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
+ return status; // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
+ }
+}
+
+namespace PR13387 {
+struct A {
+ void CreateFoo(float, float);
+ void CreateBar(float, float);
+};
+struct B : A {
+ using A::CreateFoo;
+ void CreateFoo(int, int); // expected-note {{'CreateFoo' declared here}}
+};
+void f(B &x) {
+ x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}}
+}
+}
+
+struct DataStruct {void foo();};
+struct T {
+ DataStruct data_struct;
+ void f();
+};
+// should be void T::f();
+void f() {
+ data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'{{$}}}}
+}
+
+namespace PR12287 {
+class zif {
+ void nab(int);
+};
+void nab(); // expected-note{{'::PR12287::nab' declared here}}
+void zif::nab(int) {
+ nab(); // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::PR12287::nab'?}}
+}
+}
+
+namespace TemplateFunction {
+template <class T>
+void A(T) { } // expected-note {{'::TemplateFunction::A' declared here}}
+
+template <class T>
+void B(T) { } // expected-note {{'::TemplateFunction::B' declared here}}
+
+class Foo {
+ public:
+ void A(int, int) {}
+ void B() {}
+};
+
+void test(Foo F, int num) {
+ F.A(num); // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}}
+ F.B(num); // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}}
+}
+}
+namespace using_suggestion_val_dropped_specifier {
+void FFF() {} // expected-note {{'::using_suggestion_val_dropped_specifier::FFF' declared here}}
+namespace N { }
+using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean '::using_suggestion_val_dropped_specifier::FFF'?}}
+}
+
+namespace class_member_typo_corrections {
+class Outer {
+public:
+ class Inner {}; // expected-note {{'Outer::Inner' declared here}}
+ Inner MyMethod(Inner arg);
+};
+
+Inner Outer::MyMethod(Inner arg) { // expected-error {{unknown type name 'Inner'; did you mean 'Outer::Inner'?}}
+ return Inner();
+}
+
+class Result {
+public:
+ enum ResultType {
+ ENTITY, // expected-note {{'Result::ENTITY' declared here}}
+ PREDICATE, // expected-note {{'Result::PREDICATE' declared here}}
+ LITERAL // expected-note {{'Result::LITERAL' declared here}}
+ };
+
+ ResultType type();
+};
+
+void test() {
+ Result result_cell;
+ switch (result_cell.type()) {
+ case ENTITY: // expected-error {{use of undeclared identifier 'ENTITY'; did you mean 'Result::ENTITY'?}}
+ case LITERAL: // expected-error {{use of undeclared identifier 'LITERAL'; did you mean 'Result::LITERAL'?}}
+ case PREDICAT: // expected-error {{use of undeclared identifier 'PREDICAT'; did you mean 'Result::PREDICATE'?}}
+ break;
+ }
+}
+
+class Figure {
+ enum ResultType {
+ SQUARE,
+ TRIANGLE,
+ CIRCLE
+ };
+
+public:
+ ResultType type();
+};
+
+void testAccess() {
+ Figure obj;
+ switch (obj.type()) { // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
+ case SQUARE: // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
+ case TRIANGLE: // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
+ case CIRCE: // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
+ break;
+ }
+}
+}
+
+long readline(const char *, char *, unsigned long);
+void assign_to_unknown_var() {
+ deadline_ = 1; // expected-error-re {{use of undeclared identifier 'deadline_'{{$}}}}
+}
+
+namespace no_ns_before_dot {
+namespace re2 {}
+void test() {
+ req.set_check(false); // expected-error-re {{use of undeclared identifier 'req'{{$}}}}
+}
+}
+
+namespace PR17394 {
+ class A {
+ protected:
+ long zzzzzzzzzz;
+ };
+ class B : private A {};
+ B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{}
+}
+
+namespace correct_fields_in_member_funcs {
+struct S {
+ int my_member; // expected-note {{'my_member' declared here}}
+ void f() { my_menber = 1; } // expected-error {{use of undeclared identifier 'my_menber'; did you mean 'my_member'?}}
+};
+}
+
+namespace PR17019 {
+ template<class F>
+ struct evil {
+ evil(F de) { // expected-note {{'de' declared here}}
+ de_; // expected-error {{use of undeclared identifier 'de_'; did you mean 'de'?}} \
+ // expected-warning {{expression result unused}}
+ }
+ ~evil() {
+ de_->bar() // expected-error {{use of undeclared identifier 'de_'}}
+ }
+ };
+
+ void meow() {
+ evil<int> Q(0); // expected-note {{in instantiation of member function}}
+ }
+}
+
+namespace fix_class_name_qualifier {
+class MessageHeaders {};
+class MessageUtils {
+ public:
+ static void ParseMessageHeaders(int, int); // expected-note {{'MessageUtils::ParseMessageHeaders' declared here}}
+};
+
+void test() {
+ // No, we didn't mean to call MessageHeaders::MessageHeaders.
+ MessageHeaders::ParseMessageHeaders(5, 4); // expected-error {{no member named 'ParseMessageHeaders' in 'fix_class_name_qualifier::MessageHeaders'; did you mean 'MessageUtils::ParseMessageHeaders'?}}
+}
+}
+
+namespace PR18213 { // expected-note {{'PR18213' declared here}}
+struct WrapperInfo {
+ int i;
+};
+
+template <typename T> struct Wrappable {
+ static WrapperInfo kWrapperInfo;
+};
+
+// Note the space before "::PR18213" is intended and needed, as it highlights
+// the actual typo, which is the leading "::".
+// TODO: Suggest removing the "::" from "::PR18213" (the right correction)
+// instead of incorrectly suggesting dropping "PR18213::WrapperInfo::".
+template <>
+PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 }; // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \
+ // expected-error {{C++ requires a type specifier for all declarations}}
+}
+
+namespace PR18651 {
+struct {
+ int x;
+} a, b;
+
+int y = x; // expected-error-re {{use of undeclared identifier 'x'{{$}}}}
+}
+
+namespace PR18685 {
+template <class C, int I, int J>
+class SetVector {
+ public:
+ SetVector() {}
+};
+
+template <class C, int I>
+class SmallSetVector : public SetVector<C, I, 8> {};
+
+class foo {};
+SmallSetVector<foo*, 2> fooSet;
+}
+
+PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}}
+
+namespace shadowed_template {
+template <typename T> class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}}
+class Baz {
+ int Fizbin();
+ // TODO: Teach the parser to recover from the typo correction instead of
+ // continuing to treat the template name as an implicit-int declaration.
+ Fizbin<int> qux; // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \
+ // expected-error {{expected member name or ';' after declaration specifiers}}
+};
+}
+
+namespace PR18852 {
+void func() {
+ struct foo {
+ void bar() {}
+ };
+ bar(); // expected-error-re {{use of undeclared identifier 'bar'{{$}}}}
+}
+
+class Thread {
+ public:
+ void Start();
+ static void Stop(); // expected-note {{'Thread::Stop' declared here}}
+};
+
+class Manager {
+ public:
+ void Start(int); // expected-note {{'Start' declared here}}
+ void Stop(int); // expected-note {{'Stop' declared here}}
+};
+
+void test(Manager *m) {
+ // Don't suggest Thread::Start as a correction just because it has the same
+ // (unqualified) name and accepts the right number of args; this is a method
+ // call on an object in an unrelated class.
+ m->Start(); // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
+ m->Stop(); // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
+ Stop(); // expected-error {{use of undeclared identifier 'Stop'; did you mean 'Thread::Stop'?}}
+}
+
+}
+
+namespace std {
+class bernoulli_distribution {
+ public:
+ double p() const;
+};
+}
+void test() {
+ // Make sure that typo correction doesn't suggest changing 'p' to
+ // 'std::bernoulli_distribution::p' as that is most likely wrong.
+ if (p) // expected-error-re {{use of undeclared identifier 'p'{{$}}}}
+ return;
+}
+
+namespace PR19681 {
+ struct TypoA {};
+ struct TypoB {
+ void test();
+ private:
+ template<typename T> void private_memfn(T); // expected-note{{declared here}}
+ };
+ void TypoB::test() {
+ // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn'
+ (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn); // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}}
+ }
+}
+
+namespace testWantFunctionLikeCasts {
+ long test(bool a) {
+ if (a)
+ return struc(5.7); // expected-error-re {{use of undeclared identifier 'struc'{{$}}}}
+ else
+ return lon(8.0); // expected-error {{use of undeclared identifier 'lon'; did you mean 'long'?}}
+ }
+}
+
+namespace testCXXDeclarationSpecifierParsing {
+namespace test {
+ struct SomeSettings {}; // expected-note {{'test::SomeSettings' declared here}}
+}
+class Test {};
+int bar() {
+ Test::SomeSettings some_settings; // expected-error {{no type named 'SomeSettings' in 'testCXXDeclarationSpecifierParsing::Test'; did you mean 'test::SomeSettings'?}}
+}
+}
+
+namespace testNonStaticMemberHandling {
+struct Foo {
+ bool usesMetadata; // expected-note {{'usesMetadata' declared here}}
+};
+int test(Foo f) {
+ if (UsesMetadata) // expected-error-re {{use of undeclared identifier 'UsesMetadata'{{$}}}}
+ return 5;
+ if (f.UsesMetadata) // expected-error {{no member named 'UsesMetadata' in 'testNonStaticMemberHandling::Foo'; did you mean 'usesMetadata'?}}
+ return 11;
+ return 0;
+}
};
+
+namespace testMemberExprDeclarationNameInfo {
+ // The AST should only have the corrected name with no mention of 'data_'.
+ void f(int);
+ struct S {
+ int data; // expected-note 2{{'data' declared here}}
+ void m_fn1() {
+ data_ // expected-error {{use of undeclared identifier 'data_'}}
+ [] = // expected-error {{expected expression}}
+ f(data_); // expected-error {{use of undeclared identifier 'data_'}}
+ }
+ };
+}
+
+namespace testArraySubscriptIndex {
+ struct S {
+ int data; // expected-note {{'data' declared here}}
+ void m_fn1() {
+ (+)[data_]; // expected-error{{expected expression}} expected-error {{use of undeclared identifier 'data_'; did you mean 'data'}}
+ }
+ };
}
diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp
index f32036a025f4..0138967ef80c 100644
--- a/test/SemaCXX/undefined-internal.cpp
+++ b/test/SemaCXX/undefined-internal.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wbind-to-temporary-copy %s
// Make sure we don't produce invalid IR.
// RUN: %clang_cc1 -emit-llvm-only %s
@@ -163,7 +163,7 @@ namespace cxx11_odr_rules {
// Check that the checks work with unevaluated contexts
(void)sizeof(p(A::used1));
- (void)typeid(p(A::used1)); // xpected-note {{used here}}
+ (void)typeid(p(A::used1)); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}} xpected-note {{used here}}
// Misc other testing
a(A::unused, 1 ? A::used2 : A::used2); // xpected-note {{used here}}
diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp
index 677a141f3ec3..018b1feba96b 100644
--- a/test/SemaCXX/uninitialized.cpp
+++ b/test/SemaCXX/uninitialized.cpp
@@ -1,9 +1,22 @@
// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -std=c++11 -verify %s
+// definitions for std::move
+namespace std {
+inline namespace foo {
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> typename remove_reference<T>::type&& move(T&& t);
+}
+}
+
int foo(int x);
int bar(int* x);
int boo(int& x);
int far(const int& x);
+int moved(int&& x);
+int &ref(int x);
// Test self-references within initializers which are guaranteed to be
// uninitialized.
@@ -24,6 +37,20 @@ int k = __alignof__(k);
int l = k ? l : l; // expected-warning 2{{variable 'l' is uninitialized when used within its own initialization}}
int m = 1 + (k ? m : m); // expected-warning 2{{variable 'm' is uninitialized when used within its own initialization}}
int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+int o = std::move(o); // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+const int p = std::move(p); // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+int q = moved(std::move(q)); // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
+int r = std::move((p ? q : (18, r))); // expected-warning {{variable 'r' is uninitialized when used within its own initialization}}
+int s = r ?: s; // expected-warning {{variable 's' is uninitialized when used within its own initialization}}
+int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
+int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
+int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+int z = ++ref(z); // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
+int bb = bb ? x : y; // expected-warning {{variable 'bb' is uninitialized when used within its own initialization}}
void test_stuff () {
int a = a; // no-warning: used to signal intended lack of initialization.
@@ -44,6 +71,21 @@ void test_stuff () {
int l = k ? l : l; // expected-warning {{variable 'l' is uninitialized when used within its own initialization}}
int m = 1 + (k ? m : m); // expected-warning {{'m' is uninitialized when used within its own initialization}}
int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+ int o = std::move(o); // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+ const int p = std::move(p); // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+ int q = moved(std::move(q)); // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
+ int r = std::move((p ? q : (18, r))); // expected-warning {{variable 'r' is uninitialized when used within its own initialization}}
+ int s = r ?: s; // expected-warning {{variable 's' is uninitialized when used within its own initialization}}
+ int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
+ int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
+ int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+ int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+ int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+ int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+ int z = ++ref(z); // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+ int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
+ int bb = bb ? x : y; // expected-warning {{variable 'bb' is uninitialized when used within its own initialization}}
+
for (;;) {
int a = a; // no-warning: used to signal intended lack of initialization.
@@ -64,9 +106,64 @@ void test_stuff () {
int l = k ? l : l; // expected-warning {{variable 'l' is uninitialized when used within its own initialization}}
int m = 1 + (k ? m : m); // expected-warning {{'m' is uninitialized when used within its own initialization}}
int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+ int o = std::move(o); // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+ const int p = std::move(p); // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+ int q = moved(std::move(q)); // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
+ int r = std::move((p ? q : (18, r))); // expected-warning {{variable 'r' is uninitialized when used within its own initialization}}
+ int s = r ?: s; // expected-warning {{variable 's' is uninitialized when used within its own initialization}}
+ int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
+ int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
+ int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+ int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+ int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+ int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+ int z = ++ref(z); // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+ int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
+ int bb = bb ? x : y; // expected-warning {{variable 'bb' is uninitialized when used within its own initialization}}
+
}
}
+// Also test similar constructs in a field's initializer.
+struct S {
+ int x;
+ int y;
+ const int z = 5;
+ void *ptr;
+
+ S(bool (*)[1]) : x(x) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(bool (*)[2]) : x(x + 1) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(bool (*)[3]) : x(x + x) {} // expected-warning 2{{field 'x' is uninitialized when used here}}
+ S(bool (*)[4]) : x(static_cast<long>(x) + 1) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(bool (*)[5]) : x(foo(x)) {} // expected-warning {{field 'x' is uninitialized when used here}}
+
+ // These don't actually require the value of x and so shouldn't warn.
+ S(char (*)[1]) : x(sizeof(x)) {} // rdar://8610363
+ S(char (*)[2]) : ptr(&ptr) {}
+ S(char (*)[3]) : x(bar(&x)) {}
+ S(char (*)[4]) : x(boo(x)) {}
+ S(char (*)[5]) : x(far(x)) {}
+ S(char (*)[6]) : x(__alignof__(x)) {}
+
+ S(int (*)[1]) : x(0), y(x ? y : y) {} // expected-warning 2{{field 'y' is uninitialized when used here}}
+ S(int (*)[2]) : x(0), y(1 + (x ? y : y)) {} // expected-warning 2{{field 'y' is uninitialized when used here}}
+ S(int (*)[3]) : x(-x) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[4]) : x(std::move(x)) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[5]) : z(std::move(z)) {} // expected-warning {{field 'z' is uninitialized when used here}}
+ S(int (*)[6]) : x(moved(std::move(x))) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[7]) : x(0), y(std::move((x ? x : (18, y)))) {} // expected-warning {{field 'y' is uninitialized when used here}}
+ S(int (*)[8]) : x(0), y(x ?: y) {} // expected-warning {{field 'y' is uninitialized when used here}}
+ S(int (*)[9]) : x(0), y(y ?: x) {} // expected-warning {{field 'y' is uninitialized when used here}}
+ S(int (*)[10]) : x(0), y((foo(y), x)) {} // expected-warning {{field 'y' is uninitialized when used here}}
+ S(int (*)[11]) : x(0), y(x += y) {} // expected-warning {{field 'y' is uninitialized when used here}}
+ S(int (*)[12]) : x(x += 10) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[13]) : x(x++) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[14]) : x(0), y(((x ? (y, x) : (77, y))++, sizeof(y))) {} // expected-warning {{field 'y' is uninitialized when used here}}
+ S(int (*)[15]) : x(++ref(x)) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[16]) : x((ref(x) += 10)) {} // expected-warning {{field 'x' is uninitialized when used here}}
+ S(int (*)[17]) : x(0), y(y ? x : x) {} // expected-warning {{field 'y' is uninitialized when used here}}
+};
+
// Test self-references with record types.
class A {
// Non-POD class.
@@ -76,7 +173,7 @@ class A {
static int count;
int get() const { return num; }
int get2() { return num; }
- void set(int x) { num = x; }
+ int set(int x) { num = x; return num; }
static int zero() { return 0; }
A() {}
@@ -84,13 +181,20 @@ class A {
A(int x) {}
A(int *x) {}
A(A *a) {}
+ A(A &&a) {}
~A();
+ bool operator!();
+ bool operator!=(const A&);
};
+bool operator!=(int, const A&);
+
A getA() { return A(); }
A getA(int x) { return A(); }
A getA(A* a) { return A(); }
A getA(A a) { return A(); }
+A moveA(A&& a) { return A(); }
+A const_refA(const A& a) { return A(); }
void setupA(bool x) {
A a1;
@@ -127,9 +231,36 @@ void setupA(bool x) {
A *a26 = new A(a26->get()); // expected-warning {{variable 'a26' is uninitialized when used within its own initialization}}
A *a27 = new A(a27->get2()); // expected-warning {{variable 'a27' is uninitialized when used within its own initialization}}
A *a28 = new A(a28->num); // expected-warning {{variable 'a28' is uninitialized when used within its own initialization}}
+
+ const A a29(a29); // expected-warning {{variable 'a29' is uninitialized when used within its own initialization}}
+ const A a30 = a30; // expected-warning {{variable 'a30' is uninitialized when used within its own initialization}}
+
+ A a31 = std::move(a31); // expected-warning {{variable 'a31' is uninitialized when used within its own initialization}}
+ A a32 = moveA(std::move(a32)); // expected-warning {{variable 'a32' is uninitialized when used within its own initialization}}
+ A a33 = A(std::move(a33)); // expected-warning {{variable 'a33' is uninitialized when used within its own initialization}}
+ A a34(std::move(a34)); // expected-warning {{variable 'a34' is uninitialized when used within its own initialization}}
+ A a35 = std::move(x ? a34 : (37, a35)); // expected-warning {{variable 'a35' is uninitialized when used within its own initialization}}
+
+ A a36 = const_refA(a36);
+ A a37(const_refA(a37));
+
+ A a38({a38}); // expected-warning {{variable 'a38' is uninitialized when used within its own initialization}}
+ A a39 = {a39}; // expected-warning {{variable 'a39' is uninitialized when used within its own initialization}}
+ A a40 = A({a40}); // expected-warning {{variable 'a40' is uninitialized when used within its own initialization}}
+
+ A a41 = !a41; // expected-warning {{variable 'a41' is uninitialized when used within its own initialization}}
+ A a42 = !(a42); // expected-warning {{variable 'a42' is uninitialized when used within its own initialization}}
+ A a43 = a43 != a42; // expected-warning {{variable 'a43' is uninitialized when used within its own initialization}}
+ A a44 = a43 != a44; // expected-warning {{variable 'a44' is uninitialized when used within its own initialization}}
+ A a45 = a45 != a45; // expected-warning 2{{variable 'a45' is uninitialized when used within its own initialization}}
+ A a46 = 0 != a46; // expected-warning {{variable 'a46' is uninitialized when used within its own initialization}}
+
+ A a47(a47.set(a47.num)); // expected-warning 2{{variable 'a47' is uninitialized when used within its own initialization}}
+ A a48(a47.set(a48.num)); // expected-warning {{variable 'a48' is uninitialized when used within its own initialization}}
+ A a49(a47.set(a48.num));
}
-bool x;
+bool cond;
A a1;
A a2(a1.get());
@@ -149,8 +280,8 @@ A a14 = A(a14); // expected-warning {{variable 'a14' is uninitialized when used
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}}
-A a18 = x ? a18 : a17; // expected-warning {{variable 'a18' is uninitialized when used within its own initialization}}
-A a19 = getA(x ? a19 : a17); // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}}
+A a18 = cond ? a18 : a17; // expected-warning {{variable 'a18' is uninitialized when used within its own initialization}}
+A a19 = getA(cond ? a19 : a17); // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}}
A a20{a20}; // expected-warning {{variable 'a20' is uninitialized when used within its own initialization}}
A a21 = {a21}; // expected-warning {{variable 'a21' is uninitialized when used within its own initialization}}
@@ -163,6 +294,101 @@ A *a26 = new A(a26->get()); // expected-warning {{variable 'a26' is uninitial
A *a27 = new A(a27->get2()); // expected-warning {{variable 'a27' is uninitialized when used within its own initialization}}
A *a28 = new A(a28->num); // expected-warning {{variable 'a28' is uninitialized when used within its own initialization}}
+const A a29(a29); // expected-warning {{variable 'a29' is uninitialized when used within its own initialization}}
+const A a30 = a30; // expected-warning {{variable 'a30' is uninitialized when used within its own initialization}}
+
+A a31 = std::move(a31); // expected-warning {{variable 'a31' is uninitialized when used within its own initialization}}
+A a32 = moveA(std::move(a32)); // expected-warning {{variable 'a32' is uninitialized when used within its own initialization}}
+A a33 = A(std::move(a33)); // expected-warning {{variable 'a33' is uninitialized when used within its own initialization}}
+A a34(std::move(a34)); // expected-warning {{variable 'a34' is uninitialized when used within its own initialization}}
+A a35 = std::move(x ? a34 : (37, a35)); // expected-warning {{variable 'a35' is uninitialized when used within its own initialization}}
+
+A a36 = const_refA(a36);
+A a37(const_refA(a37));
+
+A a38({a38}); // expected-warning {{variable 'a38' is uninitialized when used within its own initialization}}
+A a39 = {a39}; // expected-warning {{variable 'a39' is uninitialized when used within its own initialization}}
+A a40 = A({a40}); // expected-warning {{variable 'a40' is uninitialized when used within its own initialization}}
+
+A a41 = !a41; // expected-warning {{variable 'a41' is uninitialized when used within its own initialization}}
+A a42 = !(a42); // expected-warning {{variable 'a42' is uninitialized when used within its own initialization}}
+A a43 = a43 != a42; // expected-warning {{variable 'a43' is uninitialized when used within its own initialization}}
+A a44 = a43 != a44; // expected-warning {{variable 'a44' is uninitialized when used within its own initialization}}
+A a45 = a45 != a45; // expected-warning 2{{variable 'a45' is uninitialized when used within its own initialization}}
+
+A a46 = 0 != a46; // expected-warning {{variable 'a46' is uninitialized when used within its own initialization}}
+
+A a47(a47.set(a47.num)); // expected-warning 2{{variable 'a47' is uninitialized when used within its own initialization}}
+A a48(a47.set(a48.num)); // expected-warning {{variable 'a48' is uninitialized when used within its own initialization}}
+A a49(a47.set(a48.num));
+
+class T {
+ A a, a2;
+ const A c_a;
+ A* ptr_a;
+
+ T() {}
+ T(bool (*)[1]) : a() {}
+ T(bool (*)[2]) : a2(a.get()) {}
+ T(bool (*)[3]) : a2(a) {}
+ T(bool (*)[4]) : a(&a) {}
+ T(bool (*)[5]) : a(a.zero()) {}
+ T(bool (*)[6]) : a(a.ONE) {}
+ T(bool (*)[7]) : a(getA()) {}
+ T(bool (*)[8]) : a2(getA(a.TWO)) {}
+ T(bool (*)[9]) : a(getA(&a)) {}
+ T(bool (*)[10]) : a(a.count) {}
+
+ T(bool (*)[11]) : a(a) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[12]) : a(a.get()) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[13]) : a(a.num) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[14]) : a(A(a)) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[15]) : a(getA(a.num)) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[16]) : a(&a.num) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[17]) : a(a.get2()) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[18]) : a2(cond ? a2 : a) {} // expected-warning {{field 'a2' is uninitialized when used here}}
+ T(bool (*)[19]) : a2(cond ? a2 : a) {} // expected-warning {{field 'a2' is uninitialized when used here}}
+ T(bool (*)[20]) : a{a} {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[21]) : a({a}) {} // expected-warning {{field 'a' is uninitialized when used here}}
+
+ T(bool (*)[22]) : ptr_a(new A(ptr_a->count)) {}
+ T(bool (*)[23]) : ptr_a(new A(ptr_a->ONE)) {}
+ T(bool (*)[24]) : ptr_a(new A(ptr_a->TWO)) {}
+ T(bool (*)[25]) : ptr_a(new A(ptr_a->zero())) {}
+
+ T(bool (*)[26]) : ptr_a(new A(ptr_a->get())) {} // expected-warning {{field 'ptr_a' is uninitialized when used here}}
+ T(bool (*)[27]) : ptr_a(new A(ptr_a->get2())) {} // expected-warning {{field 'ptr_a' is uninitialized when used here}}
+ T(bool (*)[28]) : ptr_a(new A(ptr_a->num)) {} // expected-warning {{field 'ptr_a' is uninitialized when used here}}
+
+ T(bool (*)[29]) : c_a(c_a) {} // expected-warning {{field 'c_a' is uninitialized when used here}}
+ T(bool (*)[30]) : c_a(A(c_a)) {} // expected-warning {{field 'c_a' is uninitialized when used here}}
+
+ T(bool (*)[31]) : a(std::move(a)) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[32]) : a(moveA(std::move(a))) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[33]) : a(A(std::move(a))) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[34]) : a(A(std::move(a))) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[35]) : a2(std::move(x ? a : (37, a2))) {} // expected-warning {{field 'a2' is uninitialized when used here}}
+
+ T(bool (*)[36]) : a(const_refA(a)) {}
+ T(bool (*)[37]) : a(A(const_refA(a))) {}
+
+ T(bool (*)[38]) : a({a}) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[39]) : a{a} {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[40]) : a({a}) {} // expected-warning {{field 'a' is uninitialized when used here}}
+
+ T(bool (*)[41]) : a(!a) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[42]) : a(!(a)) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ T(bool (*)[43]) : a(), a2(a2 != a) {} // expected-warning {{field 'a2' is uninitialized when used here}}
+ T(bool (*)[44]) : a(), a2(a != a2) {} // expected-warning {{field 'a2' is uninitialized when used here}}
+ T(bool (*)[45]) : a(a != a) {} // expected-warning 2{{field 'a' is uninitialized when used here}}
+ T(bool (*)[46]) : a(0 != a) {} // expected-warning {{field 'a' is uninitialized when used here}}
+
+ T(bool (*)[47]) : a2(a2.set(a2.num)) {} // expected-warning 2{{field 'a2' is uninitialized when used here}}
+ T(bool (*)[48]) : a2(a.set(a2.num)) {} // expected-warning {{field 'a2' is uninitialized when used here}}
+ T(bool (*)[49]) : a2(a.set(a.num)) {}
+
+};
+
struct B {
// POD struct.
int x;
@@ -173,13 +399,14 @@ B getB() { return B(); };
B getB(int x) { return B(); };
B getB(int *x) { return B(); };
B getB(B *b) { return B(); };
+B moveB(B &&b) { return B(); };
B* getPtrB() { return 0; };
B* getPtrB(int x) { return 0; };
B* getPtrB(int *x) { return 0; };
B* getPtrB(B **b) { return 0; };
-void setupB() {
+void setupB(bool x) {
B b1;
B b2(b1);
B b3 = { 5, &b3.x };
@@ -209,6 +436,14 @@ void setupB() {
B b17 = { b17.x = 5, b17.y = 0 };
B b18 = { b18.x + 1, b18.y }; // expected-warning 2{{variable 'b18' is uninitialized when used within its own initialization}}
+
+ const B b19 = b19; // expected-warning {{variable 'b19' is uninitialized when used within its own initialization}}
+ const B b20(b20); // expected-warning {{variable 'b20' is uninitialized when used within its own initialization}}
+
+ B b21 = std::move(b21); // expected-warning {{variable 'b21' is uninitialized when used within its own initialization}}
+ B b22 = moveB(std::move(b22)); // expected-warning {{variable 'b22' is uninitialized when used within its own initialization}}
+ B b23 = B(std::move(b23)); // expected-warning {{variable 'b23' is uninitialized when used within its own initialization}}
+ B b24 = std::move(x ? b23 : (18, b24)); // expected-warning {{variable 'b24' is uninitialized when used within its own initialization}}
}
B b1;
@@ -234,25 +469,50 @@ B* b16 = getPtrB(b16->y); // expected-warning {{variable 'b16' is uninitialized
B b17 = { b17.x = 5, b17.y = 0 };
B b18 = { b18.x + 1, b18.y }; // expected-warning 2{{variable 'b18' is uninitialized when used within its own initialization}}
-
-// Also test similar constructs in a field's initializer.
-struct S {
- int x;
- void *ptr;
-
- S(bool (*)[1]) : x(x) {} // expected-warning {{field 'x' is uninitialized when used here}}
- S(bool (*)[2]) : x(x + 1) {} // expected-warning {{field 'x' is uninitialized when used here}}
- S(bool (*)[3]) : x(x + x) {} // expected-warning 2{{field 'x' is uninitialized when used here}}
- S(bool (*)[4]) : x(static_cast<long>(x) + 1) {} // expected-warning {{field 'x' is uninitialized when used here}}
- S(bool (*)[5]) : x(foo(x)) {} // expected-warning {{field 'x' is uninitialized when used here}}
-
- // These don't actually require the value of x and so shouldn't warn.
- S(char (*)[1]) : x(sizeof(x)) {} // rdar://8610363
- S(char (*)[2]) : ptr(&ptr) {}
- S(char (*)[3]) : x(__alignof__(x)) {}
- S(char (*)[4]) : x(bar(&x)) {}
- S(char (*)[5]) : x(boo(x)) {}
- S(char (*)[6]) : x(far(x)) {}
+const B b19 = b19; // expected-warning {{variable 'b19' is uninitialized when used within its own initialization}}
+const B b20(b20); // expected-warning {{variable 'b20' is uninitialized when used within its own initialization}}
+
+B b21 = std::move(b21); // expected-warning {{variable 'b21' is uninitialized when used within its own initialization}}
+B b22 = moveB(std::move(b22)); // expected-warning {{variable 'b22' is uninitialized when used within its own initialization}}
+B b23 = B(std::move(b23)); // expected-warning {{variable 'b23' is uninitialized when used within its own initialization}}
+B b24 = std::move(x ? b23 : (18, b24)); // expected-warning {{variable 'b24' is uninitialized when used within its own initialization}}
+
+class U {
+ B b1, b2;
+ B *ptr1, *ptr2;
+ const B constb = {};
+
+ U() {}
+ U(bool (*)[1]) : b1() {}
+ U(bool (*)[2]) : b2(b1) {}
+ U(bool (*)[3]) : b1{ 5, &b1.x } {}
+ U(bool (*)[4]) : b1(getB()) {}
+ U(bool (*)[5]) : b1(getB(&b1)) {}
+ U(bool (*)[6]) : b1(getB(&b1.x)) {}
+
+ U(bool (*)[7]) : b1(b1) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+ U(bool (*)[8]) : b1(getB(b1.x)) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+ U(bool (*)[9]) : b1(getB(b1.y)) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+ U(bool (*)[10]) : b1(getB(-b1.x)) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+
+ U(bool (*)[11]) : ptr1(0) {}
+ U(bool (*)[12]) : ptr1(0), ptr2(ptr1) {}
+ U(bool (*)[13]) : ptr1(getPtrB()) {}
+ U(bool (*)[14]) : ptr1(getPtrB(&ptr1)) {}
+
+ U(bool (*)[15]) : ptr1(getPtrB(ptr1->x)) {} // expected-warning {{field 'ptr1' is uninitialized when used here}}
+ U(bool (*)[16]) : ptr2(getPtrB(ptr2->y)) {} // expected-warning {{field 'ptr2' is uninitialized when used here}}
+
+ U(bool (*)[17]) : b1 { b1.x = 5, b1.y = 0 } {}
+ U(bool (*)[18]) : b1 { b1.x + 1, b1.y } {} // expected-warning 2{{field 'b1' is uninitialized when used here}}
+
+ U(bool (*)[19]) : constb(constb) {} // expected-warning {{field 'constb' is uninitialized when used here}}
+ U(bool (*)[20]) : constb(B(constb)) {} // expected-warning {{field 'constb' is uninitialized when used here}}
+
+ U(bool (*)[21]) : b1(std::move(b1)) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+ U(bool (*)[22]) : b1(moveB(std::move(b1))) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+ U(bool (*)[23]) : b1(B(std::move(b1))) {} // expected-warning {{field 'b1' is uninitialized when used here}}
+ U(bool (*)[24]) : b2(std::move(x ? b1 : (18, b2))) {} // expected-warning {{field 'b2' is uninitialized when used here}}
};
struct C { char a[100], *e; } car = { .e = car.a };
@@ -360,6 +620,8 @@ namespace {
E(char (*)[12]) : a((b + c, c, a)) {} // expected-warning {{field 'a' is uninitialized when used here}}
E(char (*)[13]) : a((a, a, a, a)) {} // expected-warning {{field 'a' is uninitialized when used here}}
E(char (*)[14]) : a((b, c, c)) {}
+ E(char (*)[15]) : a(b ?: a) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ E(char (*)[16]) : a(a ?: b) {} // expected-warning {{field 'a' is uninitialized when used here}}
};
struct F {
@@ -385,6 +647,11 @@ namespace {
G(char (*)[7]) : f3(f3->*f_ptr) {} // expected-warning {{field 'f3' is uninitialized when used here}}
G(char (*)[8]) : f3(new F(f3->*ptr)) {} // expected-warning {{field 'f3' is uninitialized when used here}}
};
+
+ struct H {
+ H() : a(a) {} // expected-warning {{field 'a' is uninitialized when used here}}
+ const A a;
+ };
}
namespace statics {
@@ -406,6 +673,21 @@ namespace statics {
static int l = k ? l : l; // expected-warning 2{{variable 'l' is uninitialized when used within its own initialization}}
static int m = 1 + (k ? m : m); // expected-warning 2{{variable 'm' is uninitialized when used within its own initialization}}
static int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+ static int o = std::move(o); // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+ static const int p = std::move(p); // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+ static int q = moved(std::move(q)); // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
+ static int r = std::move((p ? q : (18, r))); // expected-warning {{variable 'r' is uninitialized when used within its own initialization}}
+ static int s = r ?: s; // expected-warning {{variable 's' is uninitialized when used within its own initialization}}
+ static int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
+ static int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
+ static int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+ static int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+ static int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+ static int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+ static int z = ++ref(z); // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+ static int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
+ static int bb = bb ? x : y; // expected-warning {{variable 'bb' is uninitialized when used within its own initialization}}
+
void test() {
static int a = a; // no-warning: used to signal intended lack of initialization.
@@ -426,7 +708,22 @@ namespace statics {
static int l = k ? l : l; // expected-warning 2{{static variable 'l' is suspiciously used within its own initialization}}
static int m = 1 + (k ? m : m); // expected-warning 2{{static variable 'm' is suspiciously used within its own initialization}}
static int n = -n; // expected-warning {{static variable 'n' is suspiciously used within its own initialization}}
- for (;;) {
+ static int o = std::move(o); // expected-warning {{static variable 'o' is suspiciously used within its own initialization}}
+ static const int p = std::move(p); // expected-warning {{static variable 'p' is suspiciously used within its own initialization}}
+ static int q = moved(std::move(q)); // expected-warning {{static variable 'q' is suspiciously used within its own initialization}}
+ static int r = std::move((p ? q : (18, r))); // expected-warning {{static variable 'r' is suspiciously used within its own initialization}}
+ static int s = r ?: s; // expected-warning {{static variable 's' is suspiciously used within its own initialization}}
+ static int t = t ?: s; // expected-warning {{static variable 't' is suspiciously used within its own initialization}}
+ static int u = (foo(u), s); // expected-warning {{static variable 'u' is suspiciously used within its own initialization}}
+ static int v = (u += v); // expected-warning {{static variable 'v' is suspiciously used within its own initialization}}
+ static int w = (w += 10); // expected-warning {{static variable 'w' is suspiciously used within its own initialization}}
+ static int x = x++; // expected-warning {{static variable 'x' is suspiciously used within its own initialization}}
+ static int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{static variable 'y' is suspiciously used within its own initialization}}
+ static int z = ++ref(z); // expected-warning {{static variable 'z' is suspiciously used within its own initialization}}
+ static int aa = (ref(aa) += 10); // expected-warning {{static variable 'aa' is suspiciously used within its own initialization}}
+ static int bb = bb ? x : y; // expected-warning {{static variable 'bb' is suspiciously used within its own initialization}}
+
+ for (;;) {
static int a = a; // no-warning: used to signal intended lack of initialization.
static int b = b + 1; // expected-warning {{static variable 'b' is suspiciously used within its own initialization}}
static int c = (c + c); // expected-warning 2{{static variable 'c' is suspiciously used within its own initialization}}
@@ -445,6 +742,20 @@ namespace statics {
static int l = k ? l : l; // expected-warning 2{{static variable 'l' is suspiciously used within its own initialization}}
static int m = 1 + (k ? m : m); // expected-warning 2{{static variable 'm' is suspiciously used within its own initialization}}
static int n = -n; // expected-warning {{static variable 'n' is suspiciously used within its own initialization}}
+ static int o = std::move(o); // expected-warning {{static variable 'o' is suspiciously used within its own initialization}}
+ static const int p = std::move(p); // expected-warning {{static variable 'p' is suspiciously used within its own initialization}}
+ static int q = moved(std::move(q)); // expected-warning {{static variable 'q' is suspiciously used within its own initialization}}
+ static int r = std::move((p ? q : (18, r))); // expected-warning {{static variable 'r' is suspiciously used within its own initialization}}
+ static int s = r ?: s; // expected-warning {{static variable 's' is suspiciously used within its own initialization}}
+ static int t = t ?: s; // expected-warning {{static variable 't' is suspiciously used within its own initialization}}
+ static int u = (foo(u), s); // expected-warning {{static variable 'u' is suspiciously used within its own initialization}}
+ static int v = (u += v); // expected-warning {{static variable 'v' is suspiciously used within its own initialization}}
+ static int w = (w += 10); // expected-warning {{static variable 'w' is suspiciously used within its own initialization}}
+ static int x = x++; // expected-warning {{static variable 'x' is suspiciously used within its own initialization}}
+ static int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{static variable 'y' is suspiciously used within its own initialization}}
+ static int z = ++ref(z); // expected-warning {{static variable 'z' is suspiciously used within its own initialization}}
+ static int aa = (ref(aa) += 10); // expected-warning {{static variable 'aa' is suspiciously used within its own initialization}}
+ static int bb = bb ? x : y; // expected-warning {{static variable 'bb' is suspiciously used within its own initialization}}
}
}
}
@@ -473,13 +784,21 @@ namespace references {
int &b(b); // expected-warning{{reference 'b' is not yet bound to a value when used within its own initialization}}
int &c = a ? b : c; // expected-warning{{reference 'c' is not yet bound to a value when used within its own initialization}}
int &d{d}; // expected-warning{{reference 'd' is not yet bound to a value when used within its own initialization}}
+ int &e = d ?: e; // expected-warning{{reference 'e' is not yet bound to a value when used within its own initialization}}
+ int &f = f ?: d; // expected-warning{{reference 'f' is not yet bound to a value when used within its own initialization}}
+
+ int &return_ref1(int);
+ int &return_ref2(int&);
+
+ int &g = return_ref1(g); // expected-warning{{reference 'g' is not yet bound to a value when used within its own initialization}}
+ int &h = return_ref2(h); // expected-warning{{reference 'h' is not yet bound to a value when used within its own initialization}}
struct S {
S() : a(a) {} // expected-warning{{reference 'a' is not yet bound to a value when used here}}
int &a;
};
- void f() {
+ void test() {
int &a = a; // expected-warning{{reference 'a' is not yet bound to a value when used within its own initialization}}
int &b(b); // expected-warning{{reference 'b' is not yet bound to a value when used within its own initialization}}
int &c = a ? b : c; // expected-warning{{reference 'c' is not yet bound to a value when used within its own initialization}}
@@ -529,6 +848,7 @@ namespace lambdas {
}
namespace record_fields {
+ bool x;
struct A {
A() {}
A get();
@@ -541,6 +861,7 @@ namespace record_fields {
A const_ref(const A&);
A pointer(A*);
A normal(A);
+ A rref(A&&);
struct B {
A a;
@@ -553,9 +874,13 @@ namespace record_fields {
B(char (*)[7]) : a(const_ref(a)) {}
B(char (*)[8]) : a(pointer(&a)) {}
B(char (*)[9]) : a(normal(a)) {} // expected-warning {{uninitialized}}
+ B(char (*)[10]) : a(std::move(a)) {} // expected-warning {{uninitialized}}
+ B(char (*)[11]) : a(A(std::move(a))) {} // expected-warning {{uninitialized}}
+ B(char (*)[12]) : a(rref(std::move(a))) {} // expected-warning {{uninitialized}}
+ B(char (*)[13]) : a(std::move(x ? a : (25, a))) {} // expected-warning 2{{uninitialized}}
};
struct C {
- C() {} // expected-note4{{in this constructor}}
+ C() {} // expected-note9{{in this constructor}}
A a1 = a1; // expected-warning {{uninitialized}}
A a2 = a2.get(); // expected-warning {{uninitialized}}
A a3 = a3.num();
@@ -565,8 +890,13 @@ namespace record_fields {
A a7 = const_ref(a7);
A a8 = pointer(&a8);
A a9 = normal(a9); // expected-warning {{uninitialized}}
+ const A a10 = a10; // expected-warning {{uninitialized}}
+ A a11 = std::move(a11); // expected-warning {{uninitialized}}
+ A a12 = A(std::move(a12)); // expected-warning {{uninitialized}}
+ A a13 = rref(std::move(a13)); // expected-warning {{uninitialized}}
+ A a14 = std::move(x ? a13 : (22, a14)); // expected-warning {{uninitialized}}
};
- struct D { // expected-note4{{in the implicit default constructor}}
+ struct D { // expected-note9{{in the implicit default constructor}}
A a1 = a1; // expected-warning {{uninitialized}}
A a2 = a2.get(); // expected-warning {{uninitialized}}
A a3 = a3.num();
@@ -576,6 +906,11 @@ namespace record_fields {
A a7 = const_ref(a7);
A a8 = pointer(&a8);
A a9 = normal(a9); // expected-warning {{uninitialized}}
+ const A a10 = a10; // expected-warning {{uninitialized}}
+ A a11 = std::move(a11); // expected-warning {{uninitialized}}
+ A a12 = A(std::move(a12)); // expected-warning {{uninitialized}}
+ A a13 = rref(std::move(a13)); // expected-warning {{uninitialized}}
+ A a14 = std::move(x ? a13 : (22, a14)); // expected-warning {{uninitialized}}
};
D d;
struct E {
@@ -588,6 +923,11 @@ namespace record_fields {
A a7 = const_ref(a7);
A a8 = pointer(&a8);
A a9 = normal(a9);
+ const A a10 = a10;
+ A a11 = std::move(a11);
+ A a12 = A(std::move(a12));
+ A a13 = rref(std::move(a13));
+ A a14 = std::move(x ? a13 : (22, a14));
};
}
@@ -710,6 +1050,20 @@ namespace cross_field_warnings {
int d = a + b + c;
R() : a(c = 5), b(c), c(a) {}
};
+
+ // FIXME: Use the CFG-based analysis to give a sometimes uninitialized
+ // warning on y.
+ struct T {
+ int x;
+ int y;
+ T(bool b)
+ : x(b ? (y = 5) : (1 + y)), // expected-warning{{field 'y' is uninitialized when used here}}
+ y(y + 1) {}
+ T(int b)
+ : x(!b ? (1 + y) : (y = 5)), // expected-warning{{field 'y' is uninitialized when used here}}
+ y(y + 1) {}
+ };
+
}
namespace base_class {
@@ -728,3 +1082,306 @@ namespace base_class {
C() : A(y = 4), x(y) {}
};
}
+
+namespace delegating_constructor {
+ struct A {
+ A(int);
+ A(int&, int);
+
+ A(char (*)[1]) : A(x) {}
+ // expected-warning@-1 {{field 'x' is uninitialized when used here}}
+ A(char (*)[2]) : A(x, x) {}
+ // expected-warning@-1 {{field 'x' is uninitialized when used here}}
+
+ A(char (*)[3]) : A(x, 0) {}
+
+ int x;
+ };
+}
+
+namespace init_list {
+ int num = 5;
+ struct A { int i1, i2; };
+ struct B { A a1, a2; };
+
+ A a1{1,2};
+ A a2{a2.i1 + 2}; // expected-warning{{uninitialized}}
+ A a3 = {a3.i1 + 2}; // expected-warning{{uninitialized}}
+ A a4 = A{a4.i2 + 2}; // expected-warning{{uninitialized}}
+
+ B b1 = { {}, {} };
+ B b2 = { {}, b2.a1 };
+ B b3 = { b3.a1 }; // expected-warning{{uninitialized}}
+ B b4 = { {}, b4.a2} ; // expected-warning{{uninitialized}}
+ B b5 = { b5.a2 }; // expected-warning{{uninitialized}}
+
+ B b6 = { {b6.a1.i1} }; // expected-warning{{uninitialized}}
+ B b7 = { {0, b7.a1.i1} };
+ B b8 = { {}, {b8.a1.i1} };
+ B b9 = { {}, {0, b9.a1.i1} };
+
+ B b10 = { {b10.a1.i2} }; // expected-warning{{uninitialized}}
+ B b11 = { {0, b11.a1.i2} }; // expected-warning{{uninitialized}}
+ B b12 = { {}, {b12.a1.i2} };
+ B b13 = { {}, {0, b13.a1.i2} };
+
+ B b14 = { {b14.a2.i1} }; // expected-warning{{uninitialized}}
+ B b15 = { {0, b15.a2.i1} }; // expected-warning{{uninitialized}}
+ B b16 = { {}, {b16.a2.i1} }; // expected-warning{{uninitialized}}
+ B b17 = { {}, {0, b17.a2.i1} };
+
+ B b18 = { {b18.a2.i2} }; // expected-warning{{uninitialized}}
+ B b19 = { {0, b19.a2.i2} }; // expected-warning{{uninitialized}}
+ B b20 = { {}, {b20.a2.i2} }; // expected-warning{{uninitialized}}
+ B b21 = { {}, {0, b21.a2.i2} }; // expected-warning{{uninitialized}}
+
+ B b22 = { {b18.a2.i2 + 5} };
+
+ struct C {int a; int& b; int c; };
+ C c1 = { 0, num, 0 };
+ C c2 = { 1, num, c2.b };
+ C c3 = { c3.b, num }; // expected-warning{{uninitialized}}
+ C c4 = { 0, c4.b, 0 }; // expected-warning{{uninitialized}}
+ C c5 = { 0, c5.c, 0 };
+ C c6 = { c6.b, num, 0 }; // expected-warning{{uninitialized}}
+ C c7 = { 0, c7.a, 0 };
+
+ struct D {int &a; int &b; };
+ D d1 = { num, num };
+ D d2 = { num, d2.a };
+ D d3 = { d3.b, num }; // expected-warning{{uninitialized}}
+
+ // Same as above in member initializer form.
+ struct Awrapper {
+ A a1{1,2};
+ A a2{a2.i1 + 2}; // expected-warning{{uninitialized}}
+ A a3 = {a3.i1 + 2}; // expected-warning{{uninitialized}}
+ A a4 = A{a4.i2 + 2}; // expected-warning{{uninitialized}}
+ Awrapper() {} // expected-note 3{{in this constructor}}
+ Awrapper(int) :
+ a1{1,2},
+ a2{a2.i1 + 2}, // expected-warning{{uninitialized}}
+ a3{a3.i1 + 2}, // expected-warning{{uninitialized}}
+ a4{a4.i2 + 2} // expected-warning{{uninitialized}}
+ {}
+ };
+
+ struct Bwrapper {
+ B b1 = { {}, {} };
+ B b2 = { {}, b2.a1 };
+ B b3 = { b3.a1 }; // expected-warning{{uninitialized}}
+ B b4 = { {}, b4.a2} ; // expected-warning{{uninitialized}}
+ B b5 = { b5.a2 }; // expected-warning{{uninitialized}}
+
+ B b6 = { {b6.a1.i1} }; // expected-warning{{uninitialized}}
+ B b7 = { {0, b7.a1.i1} };
+ B b8 = { {}, {b8.a1.i1} };
+ B b9 = { {}, {0, b9.a1.i1} };
+
+ B b10 = { {b10.a1.i2} }; // expected-warning{{uninitialized}}
+ B b11 = { {0, b11.a1.i2} }; // expected-warning{{uninitialized}}
+ B b12 = { {}, {b12.a1.i2} };
+ B b13 = { {}, {0, b13.a1.i2} };
+
+ B b14 = { {b14.a2.i1} }; // expected-warning{{uninitialized}}
+ B b15 = { {0, b15.a2.i1} }; // expected-warning{{uninitialized}}
+ B b16 = { {}, {b16.a2.i1} }; // expected-warning{{uninitialized}}
+ B b17 = { {}, {0, b17.a2.i1} };
+
+ B b18 = { {b18.a2.i2} }; // expected-warning{{uninitialized}}
+ B b19 = { {0, b19.a2.i2} }; // expected-warning{{uninitialized}}
+ B b20 = { {}, {b20.a2.i2} }; // expected-warning{{uninitialized}}
+ B b21 = { {}, {0, b21.a2.i2} }; // expected-warning{{uninitialized}}
+
+ B b22 = { {b18.a2.i2 + 5} };
+ Bwrapper() {} // expected-note 13{{in this constructor}}
+ Bwrapper(int) :
+ b1{ {}, {} },
+ b2{ {}, b2.a1 },
+ b3{ b3.a1 }, // expected-warning{{uninitialized}}
+ b4{ {}, b4.a2}, // expected-warning{{uninitialized}}
+ b5{ b5.a2 }, // expected-warning{{uninitialized}}
+
+ b6{ {b6.a1.i1} }, // expected-warning{{uninitialized}}
+ b7{ {0, b7.a1.i1} },
+ b8{ {}, {b8.a1.i1} },
+ b9{ {}, {0, b9.a1.i1} },
+
+ b10{ {b10.a1.i2} }, // expected-warning{{uninitialized}}
+ b11{ {0, b11.a1.i2} }, // expected-warning{{uninitialized}}
+ b12{ {}, {b12.a1.i2} },
+ b13{ {}, {0, b13.a1.i2} },
+
+ b14{ {b14.a2.i1} }, // expected-warning{{uninitialized}}
+ b15{ {0, b15.a2.i1} }, // expected-warning{{uninitialized}}
+ b16{ {}, {b16.a2.i1} }, // expected-warning{{uninitialized}}
+ b17{ {}, {0, b17.a2.i1} },
+
+ b18{ {b18.a2.i2} }, // expected-warning{{uninitialized}}
+ b19{ {0, b19.a2.i2} }, // expected-warning{{uninitialized}}
+ b20{ {}, {b20.a2.i2} }, // expected-warning{{uninitialized}}
+ b21{ {}, {0, b21.a2.i2} }, // expected-warning{{uninitialized}}
+
+ b22{ {b18.a2.i2 + 5} }
+ {}
+ };
+
+ struct Cwrapper {
+ C c1 = { 0, num, 0 };
+ C c2 = { 1, num, c2.b };
+ C c3 = { c3.b, num }; // expected-warning{{uninitialized}}
+ C c4 = { 0, c4.b, 0 }; // expected-warning{{uninitialized}}
+ C c5 = { 0, c5.c, 0 };
+ C c6 = { c6.b, num, 0 }; // expected-warning{{uninitialized}}
+ C c7 = { 0, c7.a, 0 };
+
+ Cwrapper() {} // expected-note 3{{in this constructor}}
+ Cwrapper(int) :
+ c1{ 0, num, 0 },
+ c2{ 1, num, c2.b },
+ c3{ c3.b, num }, // expected-warning{{uninitialized}}
+ c4{ 0, c4.b, 0 }, // expected-warning{{uninitialized}}
+ c5{ 0, c5.c, 0 },
+ c6{ c6.b, num, 0 }, // expected-warning{{uninitialized}}
+ c7{ 0, c7.a, 0 }
+ {}
+ };
+
+ struct Dwrapper {
+ D d1 = { num, num };
+ D d2 = { num, d2.a };
+ D d3 = { d3.b, num }; // expected-warning{{uninitialized}}
+ Dwrapper() {} // expected-note{{in this constructor}}
+ Dwrapper(int) :
+ d1{ num, num },
+ d2{ num, d2.a },
+ d3{ d3.b, num } // expected-warning{{uninitialized}}
+ {}
+ };
+}
+
+namespace template_class {
+class Foo {
+ public:
+ int *Create() { return nullptr; }
+};
+
+template <typename T>
+class A {
+public:
+ // Don't warn on foo here.
+ A() : ptr(foo->Create()) {}
+
+private:
+ Foo *foo = new Foo;
+ int *ptr;
+};
+
+template <typename T>
+class B {
+public:
+ // foo is uninitialized here, but class B is never instantiated.
+ B() : ptr(foo->Create()) {}
+
+private:
+ Foo *foo;
+ int *ptr;
+};
+
+template <typename T>
+class C {
+public:
+ C() : ptr(foo->Create()) {}
+ // expected-warning@-1 {{field 'foo' is uninitialized when used here}}
+private:
+ Foo *foo;
+ int *ptr;
+};
+
+C<int> c;
+// expected-note@-1 {{in instantiation of member function 'template_class::C<int>::C' requested here}}
+
+}
+
+namespace base_class_access {
+struct A {
+ A();
+ A(int);
+
+ int i;
+ int foo();
+
+ static int bar();
+};
+
+struct B : public A {
+ B(int (*)[1]) : A() {}
+ B(int (*)[2]) : A(bar()) {}
+
+ B(int (*)[3]) : A(i) {}
+ // expected-warning@-1 {{base class 'base_class_access::A' is uninitialized when used here to access 'base_class_access::A::i'}}
+
+ B(int (*)[4]) : A(foo()) {}
+ // expected-warning@-1 {{base_class_access::A' is uninitialized when used here to access 'base_class_access::A::foo'}}
+};
+
+struct C {
+ C(int) {}
+};
+
+struct D : public C, public A {
+ D(int (*)[1]) : C(0) {}
+ D(int (*)[2]) : C(bar()) {}
+
+ D(int (*)[3]) : C(i) {}
+ // expected-warning@-1 {{base class 'base_class_access::A' is uninitialized when used here to access 'base_class_access::A::i'}}
+
+ D(int (*)[4]) : C(foo()) {}
+ // expected-warning@-1 {{base_class_access::A' is uninitialized when used here to access 'base_class_access::A::foo'}}
+};
+
+}
+
+namespace value {
+template <class T> T move(T t);
+template <class T> T notmove(T t);
+}
+namespace lvalueref {
+template <class T> T move(T& t);
+template <class T> T notmove(T& t);
+}
+namespace rvalueref {
+template <class T> T move(T&& t);
+template <class T> T notmove(T&& t);
+}
+
+namespace move_test {
+int a1 = std::move(a1); // expected-warning {{uninitialized}}
+int a2 = value::move(a2); // expected-warning {{uninitialized}}
+int a3 = value::notmove(a3); // expected-warning {{uninitialized}}
+int a4 = lvalueref::move(a4);
+int a5 = lvalueref::notmove(a5);
+int a6 = rvalueref::move(a6);
+int a7 = rvalueref::notmove(a7);
+
+void test() {
+ int a1 = std::move(a1); // expected-warning {{uninitialized}}
+ int a2 = value::move(a2); // expected-warning {{uninitialized}}
+ int a3 = value::notmove(a3); // expected-warning {{uninitialized}}
+ int a4 = lvalueref::move(a4);
+ int a5 = lvalueref::notmove(a5);
+ int a6 = rvalueref::move(a6);
+ int a7 = rvalueref::notmove(a7);
+}
+
+class A {
+ int a;
+ A(int (*) [1]) : a(std::move(a)) {} // expected-warning {{uninitialized}}
+ A(int (*) [2]) : a(value::move(a)) {} // expected-warning {{uninitialized}}
+ A(int (*) [3]) : a(value::notmove(a)) {} // expected-warning {{uninitialized}}
+ A(int (*) [4]) : a(lvalueref::move(a)) {}
+ A(int (*) [5]) : a(lvalueref::notmove(a)) {}
+ A(int (*) [6]) : a(rvalueref::move(a)) {}
+ A(int (*) [7]) : a(rvalueref::notmove(a)) {}
+};
+}
diff --git a/test/SemaCXX/unknown-type-name.cpp b/test/SemaCXX/unknown-type-name.cpp
index f2c84df242ff..9d28c310ed97 100644
--- a/test/SemaCXX/unknown-type-name.cpp
+++ b/test/SemaCXX/unknown-type-name.cpp
@@ -27,7 +27,7 @@ int var(zepelin); // expected-error{{did you mean 'zeppelin'?}}
template<typename T>
struct A {
typedef T type;
-
+
type f();
type g();
@@ -93,14 +93,14 @@ template<typename T> int A<T>::h(T::type x, char) {} // expected-error{{missing
template<typename T> int h(T::type, int); // expected-error{{missing 'typename'}}
template<typename T> int h(T::type x, char); // expected-error{{missing 'typename'}}
-template<typename T> int junk1(T::junk); // expected-warning{{variable templates are a C++1y extension}}
+template<typename T> int junk1(T::junk); // expected-warning{{variable templates are a C++14 extension}}
template<typename T> int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
template<typename T> int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} expected-warning{{C++11}}
template<typename T> int junk4(T::junk j); // expected-error{{missing 'typename'}}
// FIXME: We can tell this was intended to be a function because it does not
// have a dependent nested name specifier.
-template<typename T> int i(T::type, int()); // expected-warning{{variable templates are a C++1y extension}}
+template<typename T> int i(T::type, int()); // expected-warning{{variable templates are a C++14 extension}}
// FIXME: We know which type specifier should have been specified here. Provide
// a fix-it to add 'typename A<T>::type'
diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp
index 40f80a70ef37..e730c9d63a20 100644
--- a/test/SemaCXX/using-decl-1.cpp
+++ b/test/SemaCXX/using-decl-1.cpp
@@ -255,3 +255,11 @@ namespace TypoCorrectTemplateMember {
using A::goobar; // expected-error {{no member named 'goobar' in 'TypoCorrectTemplateMember::A'; did you mean 'foobar'?}}
};
}
+
+namespace use_instance_in_static {
+struct A { int n; };
+struct B : A {
+ using A::n;
+ static int f() { return n; } // expected-error {{invalid use of member 'n' in static member function}}
+};
+}
diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index 56dafc41f132..39d4cccacd35 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/test/SemaCXX/vararg-non-pod.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
+// Check that the warning is still there under -fms-compatibility.
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs -fms-compatibility
+
extern char version[];
class C {
@@ -100,7 +103,7 @@ Base &get_base(...);
int eat_base(...);
void test_typeid(Base &base) {
- (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}}
+ (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}} expected-warning{{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
(void)typeid(eat_base(base)); // okay
}
diff --git a/test/SemaCXX/vtable-instantiation.cc b/test/SemaCXX/vtable-instantiation.cpp
index 2a1b98900647..78f2b3ed1a2a 100644
--- a/test/SemaCXX/vtable-instantiation.cc
+++ b/test/SemaCXX/vtable-instantiation.cpp
@@ -41,7 +41,7 @@ namespace PR9325 {
void f()
{
- Target<int*>* traits = &Provider<int*>::Instance;
+ Target<int*>* traits = &Provider<int*>::Instance; // expected-note{{requested here}}
}
}
@@ -60,7 +60,7 @@ namespace PR10020 {
};
template <typename Type>
- GMG<Type> GMG<Type>::singleton;
+ GMG<Type> GMG<Type>::singleton; // expected-note{{requested here}}
void test(void) {
GMG<int>::Method(); // expected-note{{in instantiation of}}
diff --git a/test/SemaCXX/warn-bool-conversion.cpp b/test/SemaCXX/warn-bool-conversion.cpp
index b4628947f06e..b0c8d0d19d14 100644
--- a/test/SemaCXX/warn-bool-conversion.cpp
+++ b/test/SemaCXX/warn-bool-conversion.cpp
@@ -118,3 +118,30 @@ namespace Pointer {
// expected-warning@-1{{address of 'S::a' will always evaluate to 'true'}}
}
}
+
+namespace macros {
+ #define assert(x) if (x) {}
+ #define zero_on_null(x) ((x) ? *(x) : 0)
+
+ int array[5];
+ void fun();
+ int x;
+
+ void test() {
+ assert(array);
+ assert(array && "expecting null pointer");
+ // expected-warning@-1{{address of array 'array' will always evaluate to 'true'}}
+
+ assert(fun);
+ assert(fun && "expecting null pointer");
+ // expected-warning@-1{{address of function 'fun' will always evaluate to 'true'}}
+ // expected-note@-2 {{prefix with the address-of operator to silence this warning}}
+
+ // TODO: warn on assert(&x) while not warning on zero_on_null(&x)
+ zero_on_null(&x);
+ assert(zero_on_null(&x));
+ assert(&x);
+ assert(&x && "expecting null pointer");
+ // expected-warning@-1{{address of 'x' will always evaluate to 'true'}}
+ }
+}
diff --git a/test/SemaCXX/warn-consumed-parsing.cpp b/test/SemaCXX/warn-consumed-parsing.cpp
index 5c0a04fffe36..179604141b7b 100644
--- a/test/SemaCXX/warn-consumed-parsing.cpp
+++ b/test/SemaCXX/warn-consumed-parsing.cpp
@@ -37,6 +37,7 @@ class CONSUMABLE(unknown) AttrTester1 {
void callableWhen0() CALLABLE_WHEN("unconsumed");
void callableWhen1() CALLABLE_WHEN(42); // expected-error {{'callable_when' attribute requires a string}}
void callableWhen2() CALLABLE_WHEN("foo"); // expected-warning {{'callable_when' attribute argument not supported: foo}}
+ void callableWhen3() CALLABLE_WHEN(unconsumed);
void consumes() SET_TYPESTATE(consumed);
bool testUnconsumed() TEST_TYPESTATE(consumed);
};
diff --git a/test/SemaCXX/warn-global-constructors.cpp b/test/SemaCXX/warn-global-constructors.cpp
index 90d8558666c3..856826414a8b 100644
--- a/test/SemaCXX/warn-global-constructors.cpp
+++ b/test/SemaCXX/warn-global-constructors.cpp
@@ -120,3 +120,9 @@ namespace pr19253 {
};
E e;
}
+
+namespace pr20420 {
+// No warning is expected. This used to crash.
+void *array_storage[1];
+const int &global_reference = *(int *)array_storage;
+}
diff --git a/test/SemaCXX/warn-overloaded-virtual.cpp b/test/SemaCXX/warn-overloaded-virtual.cpp
index 629d59dee537..6204826192d7 100644
--- a/test/SemaCXX/warn-overloaded-virtual.cpp
+++ b/test/SemaCXX/warn-overloaded-virtual.cpp
@@ -48,8 +48,8 @@ struct Base {
void Base::foo(int) { }
struct Derived : public Base {
- virtual void foo(int);
- void foo(int, int);
+ virtual void foo(int);
+ void foo(int, int);
};
}
@@ -138,3 +138,21 @@ namespace {
// expected-warning@-1{{hides overloaded virtual functions}}
};
}
+
+namespace {
+struct base {
+ void f(char) {}
+};
+
+struct derived : base {
+ void f(int) {}
+};
+
+void foo(derived &d) {
+ d.f('1'); // FIXME: this should warn about calling (anonymous namespace)::derived::f(int)
+ // instead of (anonymous namespace)::base::f(char).
+ // Note: this should be under a new diagnostic flag and eventually moved to a
+ // new test case since it's not strictly related to virtual functions.
+ d.f(12); // This should not warn.
+}
+}
diff --git a/test/SemaCXX/warn-self-move.cpp b/test/SemaCXX/warn-self-move.cpp
new file mode 100644
index 000000000000..23778c187113
--- /dev/null
+++ b/test/SemaCXX/warn-self-move.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -fsyntax-only -Wself-move -std=c++11 -verify %s
+
+// definitions for std::move
+namespace std {
+inline namespace foo {
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> typename remove_reference<T>::type &&move(T &&t);
+}
+}
+
+void int_test() {
+ int x = 5;
+ x = std::move(x); // expected-warning{{explicitly moving}}
+ (x) = std::move(x); // expected-warning{{explicitly moving}}
+
+ using std::move;
+ x = move(x); // expected-warning{{explicitly moving}}
+}
+
+int global;
+void global_int_test() {
+ global = std::move(global); // expected-warning{{explicitly moving}}
+ (global) = std::move(global); // expected-warning{{explicitly moving}}
+
+ using std::move;
+ global = move(global); // expected-warning{{explicitly moving}}
+}
+
+class field_test {
+ int x;
+ field_test(field_test&& other) {
+ x = std::move(x); // expected-warning{{explicitly moving}}
+ x = std::move(other.x);
+ other.x = std::move(x);
+ other.x = std::move(other.x); // expected-warning{{explicitly moving}}
+ }
+};
+
+struct A {};
+struct B { A a; };
+struct C { C() {}; ~C() {} };
+void struct_test() {
+ A a;
+ a = std::move(a); // expected-warning{{explicitly moving}}
+
+ B b;
+ b = std::move(b); // expected-warning{{explicitly moving}}
+ b.a = std::move(b.a); // expected-warning{{explicitly moving}}
+
+ C c;
+ c = std::move(c); // expected-warning{{explicitly moving}}
+}
diff --git a/test/SemaCXX/warn-tautological-compare.cpp b/test/SemaCXX/warn-tautological-compare.cpp
index b44f3f9d8fa3..7d5b4b14e998 100644
--- a/test/SemaCXX/warn-tautological-compare.cpp
+++ b/test/SemaCXX/warn-tautological-compare.cpp
@@ -136,3 +136,43 @@ namespace PointerCompare {
// expected-warning@-1{{comparison of address of 'S::a' equal to a null pointer is always false}}
}
}
+
+namespace macros {
+ #define assert(x) if (x) {}
+ int array[5];
+ void fun();
+ int x;
+
+ void test() {
+ assert(array == 0);
+ // expected-warning@-1{{comparison of array 'array' equal to a null pointer is always false}}
+ assert(array != 0);
+ // expected-warning@-1{{comparison of array 'array' not equal to a null pointer is always true}}
+ assert(array == 0 && "expecting null pointer");
+ // expected-warning@-1{{comparison of array 'array' equal to a null pointer is always false}}
+ assert(array != 0 && "expecting non-null pointer");
+ // expected-warning@-1{{comparison of array 'array' not equal to a null pointer is always true}}
+
+ assert(fun == 0);
+ // expected-warning@-1{{comparison of function 'fun' equal to a null pointer is always false}}
+ // expected-note@-2{{prefix with the address-of operator to silence this warning}}
+ assert(fun != 0);
+ // expected-warning@-1{{comparison of function 'fun' not equal to a null pointer is always true}}
+ // expected-note@-2{{prefix with the address-of operator to silence this warning}}
+ assert(fun == 0 && "expecting null pointer");
+ // expected-warning@-1{{comparison of function 'fun' equal to a null pointer is always false}}
+ // expected-note@-2{{prefix with the address-of operator to silence this warning}}
+ assert(fun != 0 && "expecting non-null pointer");
+ // expected-warning@-1{{comparison of function 'fun' not equal to a null pointer is always true}}
+ // expected-note@-2{{prefix with the address-of operator to silence this warning}}
+
+ assert(&x == 0);
+ // expected-warning@-1{{comparison of address of 'x' equal to a null pointer is always false}}
+ assert(&x != 0);
+ // expected-warning@-1{{comparison of address of 'x' not equal to a null pointer is always true}}
+ assert(&x == 0 && "expecting null pointer");
+ // expected-warning@-1{{comparison of address of 'x' equal to a null pointer is always false}}
+ assert(&x != 0 && "expecting non-null pointer");
+ // expected-warning@-1{{comparison of address of 'x' not equal to a null pointer is always true}}
+ }
+}
diff --git a/test/SemaCXX/warn-tautological-undefined-compare.cpp b/test/SemaCXX/warn-tautological-undefined-compare.cpp
index ce05bfc14d17..9321c0edbd3a 100644
--- a/test/SemaCXX/warn-tautological-undefined-compare.cpp
+++ b/test/SemaCXX/warn-tautological-undefined-compare.cpp
@@ -110,3 +110,31 @@ namespace function_return_reference {
// expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
}
}
+
+namespace macros {
+ #define assert(x) if (x) {}
+
+ void test(int &x) {
+ assert(&x != 0);
+ // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+ assert(&x == 0);
+ // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+ assert(&x != 0 && "Expecting valid reference");
+ // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+ assert(&x == 0 && "Expecting invalid reference");
+ // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+ }
+
+ class S {
+ void test() {
+ assert(this != 0);
+ // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+ assert(this == 0);
+ // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+ assert(this != 0 && "Expecting valid reference");
+ // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+ assert(this == 0 && "Expecting invalid reference");
+ // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+ }
+ };
+}
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 34a33aab42d2..091e47335b57 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -fcxx-exceptions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
@@ -36,6 +36,9 @@ class __attribute__((lockable)) Mutex {
bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+ // for negative capabilities
+ const Mutex& operator!() const { return *this; }
+
void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
void AssertReaderHeld() ASSERT_SHARED_LOCK();
};
@@ -60,6 +63,12 @@ class SCOPED_LOCKABLE ReleasableMutexLock {
void Release() UNLOCK_FUNCTION();
};
+class __attribute__((scoped_lockable)) DoubleMutexLock {
+public:
+ DoubleMutexLock(Mutex *mu1, Mutex *mu2)
+ __attribute__((exclusive_lock_function(mu1, mu2)));
+ ~DoubleMutexLock() __attribute__((unlock_function));
+};
// The universal lock, written "*", allows checking to be selectively turned
// off for a particular piece of code.
@@ -95,6 +104,37 @@ public:
};
+// For testing operator overloading
+template <class K, class T>
+class MyMap {
+public:
+ T& operator[](const K& k);
+};
+
+
+// For testing handling of containers.
+template <class T>
+class MyContainer {
+public:
+ MyContainer();
+
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ T* begin();
+ T* end();
+
+ const T* cbegin();
+ const T* cend();
+
+ T& operator[](int i);
+ const T& operator[](int i) const;
+
+private:
+ T* ptr_;
+};
+
+
Mutex sls_mu;
@@ -1628,6 +1668,12 @@ struct TestScopedLockable {
a = b+1;
b = a+1;
}
+
+ void foo5() {
+ DoubleMutexLock mulock(&mu1, &mu2);
+ a = b + 1;
+ b = a + 1;
+ }
};
} // end namespace test_scoped_lockable
@@ -2280,6 +2326,15 @@ void test() {
(a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
(a > 0 ? fooArray[1] : fooArray[b]).a = 0;
(a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
+}
+
+
+void test2() {
+ Foo *fooArray;
+ Bar bar;
+ int a;
+ int b;
+ int c;
bar.getFoo().mu_.Lock();
bar.getFooey().a = 0; // \
@@ -2295,20 +2350,20 @@ void test() {
bar.getFoo3(a, b).mu_.Lock();
bar.getFoo3(a, c).a = 0; // \
- // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a,c).mu_' exclusively}} \
- // expected-note {{'bar.getFoo3(a,b).mu_'}}
+ // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \
+ // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}
bar.getFoo3(a, b).mu_.Unlock();
getBarFoo(bar, a).mu_.Lock();
getBarFoo(bar, b).a = 0; // \
- // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar,b).mu_' exclusively}} \
- // expected-note {{'getBarFoo(bar,a).mu_'}}
+ // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \
+ // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}
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 holding mutex '((a#_)#_#fooArray[b]).mu_' exclusively}} \
- // expected-note {{'((a#_)#_#fooArray[_]).mu_'}}
+ // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \
+ // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}
(a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
}
@@ -4378,3 +4433,418 @@ class Foo {
};
} // end namespace ThreadAttributesOnLambdas
+
+
+
+namespace AttributeExpressionCornerCases {
+
+class Foo {
+ int a GUARDED_BY(getMu());
+
+ Mutex* getMu() LOCK_RETURNED("");
+ Mutex* getUniv() LOCK_RETURNED("*");
+
+ void test1() {
+ a = 0;
+ }
+
+ void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {
+ a = 0;
+ }
+
+ void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);
+
+ void test3() {
+ foo(nullptr);
+ }
+};
+
+
+class MapTest {
+ struct MuCell { Mutex* mu; };
+
+ MyMap<MyString, Mutex*> map;
+ MyMap<MyString, MuCell> mapCell;
+
+ int a GUARDED_BY(map["foo"]);
+ int b GUARDED_BY(mapCell["foo"].mu);
+
+ void test() {
+ map["foo"]->Lock();
+ a = 0;
+ map["foo"]->Unlock();
+ }
+
+ void test2() {
+ mapCell["foo"].mu->Lock();
+ b = 0;
+ mapCell["foo"].mu->Unlock();
+ }
+};
+
+
+class PreciseSmartPtr {
+ SmartPtr<Mutex> mu;
+ int val GUARDED_BY(mu);
+
+ static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {
+ a.mu->Lock();
+ bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \
+ // expected-note {{found near match 'a.mu'}}
+ a.mu->Unlock();
+ return result;
+ }
+};
+
+
+class SmartRedeclare {
+ SmartPtr<Mutex> mu;
+ int val GUARDED_BY(mu);
+
+ void test() EXCLUSIVE_LOCKS_REQUIRED(mu);
+ void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
+ void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
+};
+
+
+void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {
+ val = 0;
+}
+
+void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {
+ val = 0;
+}
+
+void SmartRedeclare::test3() {
+ val = 0;
+}
+
+
+namespace CustomMutex {
+
+
+class LOCKABLE BaseMutex { };
+class DerivedMutex : public BaseMutex { };
+
+void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);
+void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);
+
+static struct DerivedMutex custMu;
+
+static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }
+
+void customTest() {
+ customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts
+ doSomethingRequiringLock();
+ customUnlock(reinterpret_cast<BaseMutex*>(&custMu));
+}
+
+} // end namespace CustomMutex
+
+} // end AttributeExpressionCornerCases
+
+
+namespace ScopedLockReturnedInvalid {
+
+class Opaque;
+
+Mutex* getMutex(Opaque* o) LOCK_RETURNED("");
+
+void test(Opaque* o) {
+ MutexLock lock(getMutex(o));
+}
+
+} // end namespace ScopedLockReturnedInvalid
+
+
+namespace NegativeRequirements {
+
+class Bar {
+ Mutex mu;
+ int a GUARDED_BY(mu);
+
+public:
+ void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ mu.Lock();
+ a = 0;
+ mu.Unlock();
+ }
+};
+
+
+class Foo {
+ Mutex mu;
+ int a GUARDED_BY(mu);
+
+public:
+ void foo() {
+ mu.Lock(); // warning? needs !mu?
+ baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
+ bar();
+ mu.Unlock();
+ }
+
+ void bar() {
+ bar2(); // expected-warning {{calling function 'bar2' requires holding '!mu'}}
+ }
+
+ void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ baz();
+ }
+
+ void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ mu.Lock();
+ a = 0;
+ mu.Unlock();
+ }
+
+ void test() {
+ Bar b;
+ b.baz(); // no warning -- in different class.
+ }
+};
+
+} // end namespace NegativeRequirements
+
+
+namespace NegativeThreadRoles {
+
+typedef int __attribute__((capability("role"))) ThreadRole;
+
+void acquire(ThreadRole R) __attribute__((exclusive_lock_function(R))) __attribute__((no_thread_safety_analysis)) {}
+void release(ThreadRole R) __attribute__((unlock_function(R))) __attribute__((no_thread_safety_analysis)) {}
+
+ThreadRole FlightControl, Logger;
+
+extern void enque_log_msg(const char *msg);
+void log_msg(const char *msg) {
+ enque_log_msg(msg);
+}
+
+void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}
+void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}
+
+void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {
+ dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while mutex 'FlightControl' is held}} */
+ dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */
+}
+
+void spawn_fake_flight_control_thread(void) {
+ acquire(FlightControl);
+ flight_control_entry();
+ release(FlightControl);
+}
+
+extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
+void logger_entry(void) __attribute__((requires_capability(Logger))) {
+ const char *msg;
+
+ while ((msg = deque_log_msg())) {
+ dispatch_log(msg);
+ }
+}
+
+void spawn_fake_logger_thread(void) {
+ acquire(Logger);
+ logger_entry();
+ release(Logger);
+}
+
+int main(void) {
+ spawn_fake_flight_control_thread();
+ spawn_fake_logger_thread();
+
+ for (;;)
+ ; /* Pretend to dispatch things. */
+
+ return 0;
+}
+
+} // end namespace NegativeThreadRoles
+
+
+namespace AssertSharedExclusive {
+
+void doSomething();
+
+class Foo {
+ Mutex mu;
+ int a GUARDED_BY(mu);
+
+ void test() SHARED_LOCKS_REQUIRED(mu) {
+ mu.AssertHeld();
+ if (a > 0)
+ doSomething();
+ }
+};
+
+} // end namespace AssertSharedExclusive
+
+
+namespace RangeBasedForAndReferences {
+
+class Foo {
+ struct MyStruct {
+ int a;
+ };
+
+ Mutex mu;
+ int a GUARDED_BY(mu);
+ MyContainer<int> cntr GUARDED_BY(mu);
+ MyStruct s GUARDED_BY(mu);
+ int arr[10] GUARDED_BY(mu);
+
+ void nonref_test() {
+ int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
+ b = 0; // no warning
+ }
+
+ void auto_test() {
+ auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
+ b = 0; // no warning
+ auto &c = a; // no warning
+ c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
+ }
+
+ void ref_test() {
+ int &b = a;
+ int &c = b;
+ int &d = c;
+ b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
+ c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
+ d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
+
+ MyStruct &rs = s;
+ rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}
+
+ int (&rarr)[10] = arr;
+ rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}
+ }
+
+ void ptr_test() {
+ int *b = &a;
+ *b = 0; // no expected warning yet
+ }
+
+ void for_test() {
+ int total = 0;
+ for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}
+ total += i;
+ }
+ }
+};
+
+
+} // end namespace RangeBasedForAndReferences
+
+
+
+namespace PassByRefTest {
+
+class Foo {
+public:
+ Foo() : a(0), b(0) { }
+
+ int a;
+ int b;
+
+ void operator+(const Foo& f);
+
+ void operator[](const Foo& g);
+};
+
+template<class T>
+T&& mymove(T& f);
+
+
+// test top-level functions
+void copy(Foo f);
+void write1(Foo& f);
+void write2(int a, Foo& f);
+void read1(const Foo& f);
+void read2(int a, const Foo& f);
+void destroy(Foo&& f);
+
+void operator/(const Foo& f, const Foo& g);
+void operator*(const Foo& f, const Foo& g);
+
+
+
+
+class Bar {
+public:
+ Mutex mu;
+ Foo foo GUARDED_BY(mu);
+ Foo foo2 GUARDED_BY(mu);
+ Foo* foop PT_GUARDED_BY(mu);
+ SmartPtr<Foo> foosp PT_GUARDED_BY(mu);
+
+ // test methods.
+ void mwrite1(Foo& f);
+ void mwrite2(int a, Foo& f);
+ void mread1(const Foo& f);
+ void mread2(int a, const Foo& f);
+
+ // static methods
+ static void smwrite1(Foo& f);
+ static void smwrite2(int a, Foo& f);
+ static void smread1(const Foo& f);
+ static void smread2(int a, const Foo& f);
+
+ void operator<<(const Foo& f);
+
+ void test1() {
+ copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
+ write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+
+ mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+
+ smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+ smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+
+ foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
+ // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
+ foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
+ // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
+ foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
+ // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
+ foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
+ // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
+ (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
+
+ copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
+ write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
+ write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
+ read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
+ read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
+ destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
+
+ copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
+ write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
+ write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
+ read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
+ read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
+ destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
+
+ // TODO -- these requires better smart pointer handling.
+ copy(*foosp.get());
+ write1(*foosp.get());
+ write2(10, *foosp.get());
+ read1(*foosp.get());
+ read2(10, *foosp.get());
+ destroy(mymove(*foosp.get()));
+ }
+};
+
+
+} // end namespace PassByRefTest
+
diff --git a/test/SemaCXX/warn-thread-safety-negative.cpp b/test/SemaCXX/warn-thread-safety-negative.cpp
new file mode 100644
index 000000000000..f88233a60b27
--- /dev/null
+++ b/test/SemaCXX/warn-thread-safety-negative.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions %s
+
+// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
+// FIXME: should also 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 ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))
+#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__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))
+
+
+class __attribute__((lockable)) Mutex {
+ public:
+ void Lock() __attribute__((exclusive_lock_function));
+ void ReaderLock() __attribute__((shared_lock_function));
+ void Unlock() __attribute__((unlock_function));
+ bool TryLock() __attribute__((exclusive_trylock_function(true)));
+ bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
+ void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+
+ // for negative capabilities
+ const Mutex& operator!() const { return *this; }
+
+ void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
+ void AssertReaderHeld() ASSERT_SHARED_LOCK();
+};
+
+
+namespace SimpleTest {
+
+class Bar {
+ Mutex mu;
+ int a GUARDED_BY(mu);
+
+public:
+ void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ mu.Lock();
+ a = 0;
+ mu.Unlock();
+ }
+};
+
+
+class Foo {
+ Mutex mu;
+ int a GUARDED_BY(mu);
+
+public:
+ void foo() {
+ mu.Lock(); // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
+ baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
+ bar();
+ mu.Unlock();
+ }
+
+ void bar() {
+ baz(); // expected-warning {{calling function 'baz' requires holding '!mu'}}
+ }
+
+ void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ mu.Lock();
+ a = 0;
+ mu.Unlock();
+ }
+
+ void test() {
+ Bar b;
+ b.baz(); // no warning -- in different class.
+ }
+
+ void test2() {
+ mu.Lock(); // expected-warning {{acquiring mutex 'mu' requires negative capability '!mu'}}
+ a = 0;
+ mu.Unlock();
+ baz(); // no warning -- !mu in set.
+ }
+
+ void test3() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
+ mu.Lock();
+ a = 0;
+ mu.Unlock();
+ baz(); // no warning -- !mu in set.
+ }
+};
+
+} // end namespace SimpleTest
diff --git a/test/SemaCXX/warn-thread-safety-verbose.cpp b/test/SemaCXX/warn-thread-safety-verbose.cpp
new file mode 100644
index 000000000000..4e19f30bf2c3
--- /dev/null
+++ b/test/SemaCXX/warn-thread-safety-verbose.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions %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 ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))
+#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__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))
+
+
+class __attribute__((lockable)) Mutex {
+ public:
+ void Lock() __attribute__((exclusive_lock_function));
+ void ReaderLock() __attribute__((shared_lock_function));
+ void Unlock() __attribute__((unlock_function));
+ bool TryLock() __attribute__((exclusive_trylock_function(true)));
+ bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
+ void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+
+ // for negative capabilities
+ const Mutex& operator!() const { return *this; }
+
+ void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
+ void AssertReaderHeld() ASSERT_SHARED_LOCK();
+};
+
+
+class Test {
+ Mutex mu;
+ int a GUARDED_BY(mu); // expected-note3 {{Guarded_by declared here.}}
+
+ void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu);
+ void foo2() SHARED_LOCKS_REQUIRED(mu);
+ void foo3() LOCKS_EXCLUDED(mu);
+
+ void test1() { // expected-note {{Thread warning in function 'test1'}}
+ a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
+ }
+
+ void test2() { // expected-note {{Thread warning in function 'test2'}}
+ int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
+ }
+
+ void test3() { // expected-note {{Thread warning in function 'test3'}}
+ foo1(); // expected-warning {{calling function 'foo1' requires holding mutex 'mu' exclusively}}
+ }
+
+ void test4() { // expected-note {{Thread warning in function 'test4'}}
+ foo2(); // expected-warning {{calling function 'foo2' requires holding mutex 'mu'}}
+ }
+
+ void test5() { // expected-note {{Thread warning in function 'test5'}}
+ mu.ReaderLock();
+ foo1(); // expected-warning {{calling function 'foo1' requires holding mutex 'mu' exclusively}}
+ mu.Unlock();
+ }
+
+ void test6() { // expected-note {{Thread warning in function 'test6'}}
+ mu.ReaderLock();
+ a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
+ mu.Unlock();
+ }
+
+ void test7() { // expected-note {{Thread warning in function 'test7'}}
+ mu.Lock();
+ foo3(); // expected-warning {{cannot call function 'foo3' while mutex 'mu' is held}}
+ mu.Unlock();
+ }
+};
+
diff --git a/test/SemaCXX/warn-undefined-bool-conversion.cpp b/test/SemaCXX/warn-undefined-bool-conversion.cpp
index 1f8baa0e8d8a..24099f79adc5 100644
--- a/test/SemaCXX/warn-undefined-bool-conversion.cpp
+++ b/test/SemaCXX/warn-undefined-bool-conversion.cpp
@@ -95,3 +95,27 @@ namespace function_return_reference {
// expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
}
}
+
+namespace macros {
+ #define assert(x) if (x) {}
+ #define zero_on_null(x) ((x) ? *(x) : 0)
+
+ void test(int &x) {
+ // TODO: warn on assert(&x) but not on zero_on_null(&x)
+ zero_on_null(&x);
+ assert(zero_on_null(&x));
+ assert(&x);
+
+ assert(&x && "Expecting valid reference");
+ // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+ }
+
+ class S {
+ void test() {
+ assert(this);
+
+ assert(this && "Expecting invalid reference");
+ // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true}}
+ }
+ };
+}
diff --git a/test/SemaCXX/warn-unused-comparison.cpp b/test/SemaCXX/warn-unused-comparison.cpp
index 3afad585b668..a24b5a29a3df 100644
--- a/test/SemaCXX/warn-unused-comparison.cpp
+++ b/test/SemaCXX/warn-unused-comparison.cpp
@@ -83,6 +83,8 @@ void test() {
#define EQ(x,y) (x) == (y)
EQ(x, 5);
#undef EQ
+
+ (void)sizeof(1 < 2, true); // No warning; unevaluated context.
}
namespace PR10291 {
diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp
index df4c47e71787..18defee7d04a 100644
--- a/test/SemaCXX/warn-unused-filescoped.cpp
+++ b/test/SemaCXX/warn-unused-filescoped.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-c++11-extensions -std=c++98 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -Wno-c++11-extensions -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-unused-local-typedefs -std=c++11 %s
#ifdef HEADER
diff --git a/test/SemaCXX/warn-unused-local-typedef-serialize.cpp b/test/SemaCXX/warn-unused-local-typedef-serialize.cpp
new file mode 100644
index 000000000000..aa2c48bb5719
--- /dev/null
+++ b/test/SemaCXX/warn-unused-local-typedef-serialize.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang -x c++-header -c -Wunused-local-typedef %s -o %t.gch -Werror
+// RUN: %clang -DBE_THE_SOURCE -c -Wunused-local-typedef -include %t %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -DBE_THE_SOURCE -c -Wunused-local-typedef -include %t %s -o /dev/null 2>&1 | FileCheck %s
+
+#ifndef BE_THE_SOURCE
+inline void myfun() {
+// The warning should fire every time the pch file is used, not when it's built.
+// CHECK: warning: unused typedef
+ typedef int a;
+}
+#endif
diff --git a/test/SemaCXX/warn-unused-local-typedef-x86asm.cpp b/test/SemaCXX/warn-unused-local-typedef-x86asm.cpp
new file mode 100644
index 000000000000..d7792c0e11eb
--- /dev/null
+++ b/test/SemaCXX/warn-unused-local-typedef-x86asm.cpp
@@ -0,0 +1,16 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -std=c++11 -Wunused-local-typedef -verify -fasm-blocks %s
+// expected-no-diagnostics
+void use_in_asm() {
+ typedef struct {
+ int a;
+ int b;
+ } A;
+ __asm mov eax, [eax].A.b
+
+ using Alias = struct {
+ int a;
+ int b;
+ };
+ __asm mov eax, [eax].Alias.b
+}
diff --git a/test/SemaCXX/warn-unused-local-typedef.cpp b/test/SemaCXX/warn-unused-local-typedef.cpp
new file mode 100644
index 000000000000..a9406531d2d7
--- /dev/null
+++ b/test/SemaCXX/warn-unused-local-typedef.cpp
@@ -0,0 +1,242 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-local-typedef -verify -std=c++1y %s
+
+struct S {
+ typedef int Foo; // no diag
+};
+
+namespace N {
+ typedef int Foo; // no diag
+ typedef int Foo2; // no diag
+}
+
+template <class T> class Vec {};
+
+typedef int global_foo; // no diag
+
+void f() {
+ typedef int foo0; // expected-warning {{unused typedef 'foo0'}}
+ using foo0alias = int ; // expected-warning {{unused type alias 'foo0alias'}}
+
+ typedef int foo1 __attribute__((unused)); // no diag
+
+ typedef int foo2;
+ {
+ typedef int foo2; // expected-warning {{unused typedef 'foo2'}}
+ }
+ typedef foo2 foo3; // expected-warning {{unused typedef 'foo3'}}
+
+ typedef int foo2_2; // expected-warning {{unused typedef 'foo2_2'}}
+ {
+ typedef int foo2_2;
+ typedef foo2_2 foo3_2; // expected-warning {{unused typedef 'foo3_2'}}
+ }
+
+ typedef int foo4;
+ foo4 the_thing;
+
+ typedef int* foo5;
+ typedef foo5* foo6; // no diag
+ foo6 *myptr;
+
+ struct S2 {
+ typedef int Foo; // no diag
+ typedef int Foo2; // expected-warning {{unused typedef 'Foo2'}}
+
+ struct Deeper {
+ typedef int DeepFoo; // expected-warning {{unused typedef 'DeepFoo'}}
+ };
+ };
+
+ S2::Foo s2foo;
+
+ typedef struct {} foostruct; // expected-warning {{unused typedef 'foostruct'}}
+
+ typedef struct {} foostruct2; // no diag
+ foostruct2 fs2;
+
+ typedef int vecint; // no diag
+ Vec<vecint> v;
+
+ N::Foo nfoo;
+
+ typedef int ConstExprInt;
+ static constexpr int a = (ConstExprInt)4;
+}
+
+int printf(char const *, ...);
+
+void test() {
+ typedef signed long int superint; // no diag
+ printf("%f", (superint) 42);
+
+ typedef signed long int superint2; // no diag
+ printf("%f", static_cast<superint2>(42));
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
+ typedef int trungl_bot_was_here; // no diag
+#pragma clang diagnostic pop
+
+ typedef int foo; // expected-warning {{unused typedef 'foo'}}
+}
+
+template <class T>
+void template_fun(T t) {
+ typedef int foo; // expected-warning {{unused typedef 'foo'}}
+ typedef int bar; // no-diag
+ bar asdf;
+
+ struct S2 {
+ typedef int Foo; // no diag
+
+ typedef int Foo2; // expected-warning {{unused typedef 'Foo2'}}
+
+ typedef int Foo3; // no diag
+ };
+
+ typename S2::Foo s2foo;
+ typename T::Foo s3foo;
+
+ typedef typename S2::Foo3 TTSF; // expected-warning {{unused typedef 'TTSF'}}
+}
+void template_fun_user() {
+ struct Local {
+ typedef int Foo; // no-diag
+ typedef int Bar; // expected-warning {{unused typedef 'Bar'}}
+ } p;
+ template_fun(p);
+}
+
+void typedef_in_nested_name() {
+ typedef struct {
+ typedef int Foo;
+ } A;
+ A::Foo adsf;
+
+ using A2 = struct {
+ typedef int Foo;
+ };
+ A2::Foo adsf2;
+}
+
+auto sneaky() {
+ struct S {
+ // Local typedefs can be used after the scope they were in has closed:
+ typedef int t;
+
+ // Even if they aren't, this could be an inline function that could be used
+ // in another TU, so this shouldn't warn either:
+ typedef int s;
+
+ private:
+ typedef int p; // expected-warning{{unused typedef 'p'}}
+ };
+ return S();
+}
+auto x = sneaky();
+decltype(x)::t y;
+
+static auto static_sneaky() {
+ struct S {
+ typedef int t;
+ // This function has internal linkage, so we can warn:
+ typedef int s; // expected-warning {{unused typedef 's'}}
+ };
+ return S();
+}
+auto sx = static_sneaky();
+decltype(sx)::t sy;
+
+auto sneaky_with_friends() {
+ struct S {
+ private:
+ friend class G;
+ // Can't warn if we have friends:
+ typedef int p;
+ };
+ return S();
+}
+
+namespace {
+auto nstatic_sneaky() {
+ struct S {
+ typedef int t;
+ // This function has internal linkage, so we can warn:
+ typedef int s; // expected-warning {{unused typedef 's'}}
+ };
+ return S();
+}
+auto nsx = nstatic_sneaky();
+decltype(nsx)::t nsy;
+}
+
+// Like sneaky(), but returning pointer to local type
+template<typename T>
+struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+auto pointer_sneaky() {
+ struct S {
+ typedef int t;
+ typedef int s;
+ };
+ return (S*)nullptr;
+}
+remove_reference<decltype(*pointer_sneaky())>::type::t py;
+
+// Like sneaky(), but returning templated struct referencing local type.
+template <class T> struct container { int a; T t; };
+auto template_sneaky() {
+ struct S {
+ typedef int t;
+ typedef int s;
+ };
+ return container<S>();
+}
+auto tx = template_sneaky();
+decltype(tx.t)::t ty;
+
+// Like sneaky(), but doing its sneakiness by returning a member function
+// pointer.
+auto sneaky_memfun() {
+ struct S {
+ typedef int type;
+ int n;
+ };
+ return &S::n;
+}
+
+template <class T> void sneaky_memfun_g(int T::*p) {
+ typename T::type X;
+}
+
+void sneaky_memfun_h() {
+ sneaky_memfun_g(sneaky_memfun());
+}
+
+void typedefs_in_constructors() {
+ struct A {};
+ struct B : public A {
+ // Neither of these two should warn:
+ typedef A INHERITED;
+ B() : INHERITED() {}
+
+ typedef B SELF;
+ B(int) : SELF() {}
+ };
+}
+
+void *operator new(__SIZE_TYPE__, void *p) throw() { return p; }
+void placement_new_and_delete() {
+ struct MyStruct { };
+ char memory[sizeof(MyStruct)];
+ void *p = memory;
+
+ typedef MyStruct A_t1;
+ MyStruct *a = new (p) A_t1();
+
+ typedef MyStruct A_t2;
+ a->~A_t2();
+}
+
+// This should not disable any warnings:
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
diff --git a/test/SemaCXX/warn-unused-private-field-delayed-template.cpp b/test/SemaCXX/warn-unused-private-field-delayed-template.cpp
new file mode 100644
index 000000000000..7cafcca643f5
--- /dev/null
+++ b/test/SemaCXX/warn-unused-private-field-delayed-template.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -fdelayed-template-parsing -Wunused-private-field -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++11 %s
+// expected-no-diagnostics
+
+class EverythingMayBeUsed {
+ int x;
+public:
+ template <class T>
+ void f() {
+ x = 0;
+ }
+};
diff --git a/test/SemaCXX/warn-unused-result.cpp b/test/SemaCXX/warn-unused-result.cpp
index 581af09080db..7bdb4245a95a 100644
--- a/test/SemaCXX/warn-unused-result.cpp
+++ b/test/SemaCXX/warn-unused-result.cpp
@@ -94,3 +94,50 @@ void Bar() {
};
}
+
+namespace PR18571 {
+// Unevaluated contexts should not trigger unused result warnings.
+template <typename T>
+auto foo(T) -> decltype(f(), bool()) { // Should not warn.
+ return true;
+}
+
+void g() {
+ foo(1);
+}
+}
+
+namespace std {
+class type_info { };
+}
+
+namespace {
+// The typeid expression operand is evaluated only when the expression type is
+// a glvalue of polymorphic class type.
+
+struct B {
+ virtual void f() {}
+};
+
+struct D : B {
+ void f() override {}
+};
+
+struct C {};
+
+void g() {
+ // The typeid expression operand is evaluated only when the expression type is
+ // a glvalue of polymorphic class type; otherwise the expression operand is not
+ // evaluated and should not trigger a diagnostic.
+ D d;
+ C c;
+ (void)typeid(f(), c); // Should not warn.
+ (void)typeid(f(), d); // expected-warning {{ignoring return value}} expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
+
+ // The sizeof expression operand is never evaluated.
+ (void)sizeof(f(), c); // Should not warn.
+
+ // The noexcept expression operand is never evaluated.
+ (void)noexcept(f(), false); // Should not warn.
+}
+}
diff --git a/test/SemaCXX/warn-unused-value-cxx11.cpp b/test/SemaCXX/warn-unused-value-cxx11.cpp
new file mode 100644
index 000000000000..d929b4fd12fb
--- /dev/null
+++ b/test/SemaCXX/warn-unused-value-cxx11.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wunused-value %s
+
+void f() __attribute__((const));
+
+namespace PR18571 {
+// Unevaluated contexts should not trigger unused result warnings.
+template <typename T>
+auto foo(T) -> decltype(f(), bool()) { // Should not warn.
+ return true;
+}
+
+void g() {
+ foo(1);
+}
+
+void h() {
+ int i = 0;
+ (void)noexcept(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ decltype(i++) j = 0; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+}
+
+struct S {
+ S operator++(int);
+ S(int i);
+ S();
+
+ int& f();
+ S g();
+};
+
+void j() {
+ S s;
+ int i = 0;
+ (void)noexcept(s++); // Ok
+ (void)noexcept(i++); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ (void)noexcept(i = 5); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ (void)noexcept(s = 5); // Ok
+
+ (void)sizeof(s.f()); // Ok
+ (void)sizeof(s.f() = 5); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+ (void)noexcept(s.g() = 5); // Ok
+}
+
+} \ No newline at end of file
diff --git a/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp
index 4e1347cc307a..efabd5063068 100644
--- a/test/SemaCXX/warn-unused-value.cpp
+++ b/test/SemaCXX/warn-unused-value.cpp
@@ -39,13 +39,13 @@ namespace test2 {
void method() const {
X* x;
&x[0]; // expected-warning {{expression result unused}}
- }
+ }
};
typedef basic_string<char> string;
- void func(const std::string& str) {
+ void func(const std::string& str) {
str.method(); // expected-note {{in instantiation of member function}}
}
- }
+ }
}
}
@@ -69,3 +69,31 @@ void f() {
Unused(1, 1); // expected-warning {{expression result unused}}
}
}
+
+namespace std {
+ struct type_info {};
+}
+
+namespace test4 {
+struct Good { Good &f(); };
+struct Bad { virtual Bad& f(); };
+
+void f() {
+ int i = 0;
+ (void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+
+ Good g;
+ (void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.
+
+ // This is a polymorphic use of a glvalue, which results in the typeid being
+ // evaluated instead of unevaluated.
+ Bad b;
+ (void)typeid(b.f()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
+
+ // A dereference of a volatile pointer is a side effecting operation, however
+ // since it is idiomatic code, and the alternatives induce higher maintenance
+ // costs, it is allowed.
+ int * volatile x;
+ (void)sizeof(*x); // Ok
+}
+}