From 06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 18 Jan 2015 16:23:48 +0000 Subject: Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1): https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_360/rc1@226102 --- .../Inputs/header-with-pragma-optimize-off.h | 5 + test/SemaCXX/Inputs/override-system-header.h | 6 + test/SemaCXX/MicrosoftCompatibility.cpp | 10 +- test/SemaCXX/MicrosoftExtensions.cpp | 8 +- test/SemaCXX/MicrosoftSuper.cpp | 149 +++++ test/SemaCXX/PR10177.cpp | 31 +- test/SemaCXX/PR20705.cpp | 21 + test/SemaCXX/align_value.cpp | 26 + test/SemaCXX/anonymous-union.cpp | 6 +- test/SemaCXX/arrow-operator.cpp | 5 +- test/SemaCXX/ast-print.cpp | 5 + test/SemaCXX/atomic-type.cpp | 4 + test/SemaCXX/attr-cxx0x-fixit.cpp | 5 + test/SemaCXX/attr-flag-enum-reject.cpp | 4 + test/SemaCXX/attr-gnu.cpp | 29 + test/SemaCXX/attr-nodebug.cpp | 4 +- test/SemaCXX/attr-nonnull.cpp | 4 +- test/SemaCXX/attr-optnone.cpp | 38 +- test/SemaCXX/attr-print.cpp | 9 + test/SemaCXX/attributed-auto-deduction.cpp | 20 + test/SemaCXX/bitfield.cpp | 32 + test/SemaCXX/blocks.cpp | 45 ++ test/SemaCXX/builtin-assume-aligned-tmpl.cpp | 87 +++ test/SemaCXX/builtin-assume-aligned.cpp | 49 ++ test/SemaCXX/call-with-static-chain.cpp | 15 + test/SemaCXX/complex-folding.cpp | 90 +++ test/SemaCXX/const-cast.cpp | 3 + test/SemaCXX/constant-expression-cxx11.cpp | 126 +++- test/SemaCXX/constant-expression-cxx1y.cpp | 31 +- test/SemaCXX/constexpr-value-init.cpp | 6 +- test/SemaCXX/conversion-function.cpp | 12 +- test/SemaCXX/conversion.cpp | 20 + test/SemaCXX/crashes.cpp | 6 + test/SemaCXX/cxx-deprecated.cpp | 26 + test/SemaCXX/cxx0x-compat.cpp | 8 +- test/SemaCXX/cxx0x-cursory-default-delete.cpp | 2 +- test/SemaCXX/cxx0x-initializer-references.cpp | 6 + ...nitializer-stdinitializerlist-system-header.cpp | 23 - test/SemaCXX/cxx11-ast-print.cpp | 2 +- test/SemaCXX/cxx11-thread-unsupported.cpp | 5 + test/SemaCXX/cxx1y-constexpr-not-const.cpp | 2 +- test/SemaCXX/cxx1y-deduced-return-type.cpp | 13 + test/SemaCXX/cxx1y-generic-lambdas.cpp | 32 +- test/SemaCXX/cxx1y-variable-templates_in_class.cpp | 10 +- test/SemaCXX/cxx98-compat-flags.cpp | 4 +- test/SemaCXX/cxx98-compat-pedantic.cpp | 31 +- test/SemaCXX/cxx98-compat.cpp | 65 +- test/SemaCXX/decl-init-ref.cpp | 2 +- test/SemaCXX/decl-microsoft-call-conv.cpp | 13 +- test/SemaCXX/default1.cpp | 6 + test/SemaCXX/default2.cpp | 6 + test/SemaCXX/dependent-noexcept-unevaluated.cpp | 3 +- test/SemaCXX/deprecated.cpp | 8 +- test/SemaCXX/devirtualize-vtable-marking.cpp | 47 ++ test/SemaCXX/dllexport.cpp | 58 +- test/SemaCXX/dllimport.cpp | 344 ++++++++-- test/SemaCXX/enable_if.cpp | 41 ++ test/SemaCXX/enum-scoped.cpp | 8 + test/SemaCXX/exceptions.cpp | 24 +- test/SemaCXX/explicit.cpp | 2 +- test/SemaCXX/flexible-array-test.cpp | 6 + test/SemaCXX/for-range-examples.cpp | 20 +- test/SemaCXX/friend.cpp | 55 +- test/SemaCXX/goto.cpp | 4 +- test/SemaCXX/implicit-exception-spec.cpp | 35 +- test/SemaCXX/issue547.cpp | 12 +- test/SemaCXX/lambda-expressions.cpp | 80 ++- test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp | 23 + test/SemaCXX/libstdcxx_is_pod_hack.cpp | 15 +- test/SemaCXX/libstdcxx_pair_swap_hack.cpp | 74 +++ test/SemaCXX/member-init.cpp | 84 ++- test/SemaCXX/member-pointer-ms.cpp | 19 + test/SemaCXX/namespace-alias.cpp | 6 +- test/SemaCXX/nonnull.cpp | 5 + test/SemaCXX/nullptr.cpp | 2 +- test/SemaCXX/overloaded-operator.cpp | 12 + test/SemaCXX/override-in-system-header.cpp | 19 + test/SemaCXX/pragma-optimize.cpp | 53 +- test/SemaCXX/predefined-expr.cpp | 16 +- test/SemaCXX/return-noreturn.cpp | 100 ++- test/SemaCXX/return.cpp | 8 + test/SemaCXX/runtimediag-ppe.cpp | 2 +- test/SemaCXX/scope-check.cpp | 38 +- test/SemaCXX/statements.cpp | 19 +- test/SemaCXX/string-plus-int.cpp | 5 + test/SemaCXX/struct-class-redecl.cpp | 6 + test/SemaCXX/trailing-return-0x.cpp | 10 +- test/SemaCXX/type-traits.cpp | 8 + test/SemaCXX/typeid.cpp | 6 + test/SemaCXX/typo-correction-delayed.cpp | 159 +++++ test/SemaCXX/typo-correction-pt2.cpp | 302 --------- test/SemaCXX/typo-correction.cpp | 385 ++++++++++- test/SemaCXX/undefined-internal.cpp | 4 +- test/SemaCXX/uninitialized.cpp | 713 ++++++++++++++++++++- test/SemaCXX/unknown-type-name.cpp | 6 +- test/SemaCXX/using-decl-1.cpp | 8 + test/SemaCXX/vararg-non-pod.cpp | 5 +- test/SemaCXX/vtable-instantiation.cc | 68 -- test/SemaCXX/vtable-instantiation.cpp | 68 ++ test/SemaCXX/warn-bool-conversion.cpp | 27 + test/SemaCXX/warn-consumed-parsing.cpp | 1 + test/SemaCXX/warn-global-constructors.cpp | 6 + test/SemaCXX/warn-overloaded-virtual.cpp | 22 +- test/SemaCXX/warn-self-move.cpp | 55 ++ test/SemaCXX/warn-tautological-compare.cpp | 40 ++ .../warn-tautological-undefined-compare.cpp | 28 + test/SemaCXX/warn-thread-safety-analysis.cpp | 484 +++++++++++++- test/SemaCXX/warn-thread-safety-negative.cpp | 104 +++ test/SemaCXX/warn-thread-safety-verbose.cpp | 86 +++ test/SemaCXX/warn-undefined-bool-conversion.cpp | 24 + test/SemaCXX/warn-unused-comparison.cpp | 2 + test/SemaCXX/warn-unused-filescoped.cpp | 4 +- .../warn-unused-local-typedef-serialize.cpp | 11 + test/SemaCXX/warn-unused-local-typedef-x86asm.cpp | 16 + test/SemaCXX/warn-unused-local-typedef.cpp | 242 +++++++ .../warn-unused-private-field-delayed-template.cpp | 11 + test/SemaCXX/warn-unused-result.cpp | 47 ++ test/SemaCXX/warn-unused-value-cxx11.cpp | 44 ++ test/SemaCXX/warn-unused-value.cpp | 34 +- 119 files changed, 4711 insertions(+), 739 deletions(-) create mode 100644 test/SemaCXX/Inputs/header-with-pragma-optimize-off.h create mode 100644 test/SemaCXX/Inputs/override-system-header.h create mode 100644 test/SemaCXX/MicrosoftSuper.cpp create mode 100644 test/SemaCXX/PR20705.cpp create mode 100644 test/SemaCXX/align_value.cpp create mode 100644 test/SemaCXX/attr-cxx0x-fixit.cpp create mode 100644 test/SemaCXX/attr-flag-enum-reject.cpp create mode 100644 test/SemaCXX/attr-gnu.cpp create mode 100644 test/SemaCXX/attributed-auto-deduction.cpp create mode 100644 test/SemaCXX/bitfield.cpp create mode 100644 test/SemaCXX/builtin-assume-aligned-tmpl.cpp create mode 100644 test/SemaCXX/builtin-assume-aligned.cpp create mode 100644 test/SemaCXX/call-with-static-chain.cpp create mode 100644 test/SemaCXX/complex-folding.cpp create mode 100644 test/SemaCXX/cxx-deprecated.cpp delete mode 100644 test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp create mode 100644 test/SemaCXX/cxx11-thread-unsupported.cpp create mode 100644 test/SemaCXX/devirtualize-vtable-marking.cpp create mode 100644 test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp create mode 100644 test/SemaCXX/libstdcxx_pair_swap_hack.cpp create mode 100644 test/SemaCXX/override-in-system-header.cpp create mode 100644 test/SemaCXX/typo-correction-delayed.cpp delete mode 100644 test/SemaCXX/typo-correction-pt2.cpp delete mode 100644 test/SemaCXX/vtable-instantiation.cc create mode 100644 test/SemaCXX/vtable-instantiation.cpp create mode 100644 test/SemaCXX/warn-self-move.cpp create mode 100644 test/SemaCXX/warn-thread-safety-negative.cpp create mode 100644 test/SemaCXX/warn-thread-safety-verbose.cpp create mode 100644 test/SemaCXX/warn-unused-local-typedef-serialize.cpp create mode 100644 test/SemaCXX/warn-unused-local-typedef-x86asm.cpp create mode 100644 test/SemaCXX/warn-unused-local-typedef.cpp create mode 100644 test/SemaCXX/warn-unused-private-field-delayed-template.cpp create mode 100644 test/SemaCXX/warn-unused-value-cxx11.cpp (limited to 'test/SemaCXX') 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 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 + struct Wrapper { + static void bar() {} + }; + + void baz(); +}; + +void PointerToMember::baz() { + Wrapper<&__super::foo>::bar(); +} + +template +struct BaseTemplate { + typedef int XXX; + + int foo() { return 0; } +}; + +struct DerivedFromKnownSpecialization : BaseTemplate { + __super::XXX a; + typedef __super::XXX b; + + void foo() { + __super::XXX c; + typedef __super::XXX d; + + __super::foo(); + } +}; + +template +struct DerivedFromDependentBase : BaseTemplate { + 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 +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 d; + d.foo(); + DerivedFromTemplateParameter 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 using alias_ref = T; template void func_ref() {} @@ -9,22 +12,29 @@ struct U { static int a; }; -template struct S; // expected-note 2{{here}} +template struct S; // expected-note 6{{here}} template -int U::a = S::kError; // expected-error 2{{undefined}} +int U::a = S::kError; // expected-error 6{{undefined}} template 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::a>(); + (void)alias_ref::a>(); // expected-note {{here}} (void)func_ref::a>(); // expected-note {{here}} (void)class_ref::a>(); // expected-note {{here}} }; + +template +void fi() { + (void)alias_ref::a>(); // expected-note {{here}} + (void)func_ref::a>(); // expected-note {{here}} + (void)class_ref::a>(); // expected-note {{here}} +}; + int main() { - f(); // expected-note 2{{here}} + f(); // 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(); } + +#else +// expected-no-diagnostics + +namespace { template extern int n; } +template int g() { return n; } + +#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 +struct X {}; +auto b = []() { + struct S { + static typename X::type Run(){}; + // expected-error@-1 4{{}} + }; + return 5; +}(); + +template +class PC { +}; + +template +class P { + static typename PC::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 +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 y; + +template +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' requested here}} +nope 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(new Worker); worker.DoSomething(); // expected-error {{no member named 'DoSomething' in 'arrow_suggest::wrapped_ptr'; did you mean to use '->' instead of '.'?}} - worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr'}} + worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr'; 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'; 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 constexpr int func() { return 0; } + void run(void (^)(), int); + + void test() { + int aCapturedVar = 0; + run(^{ (void) aCapturedVar; }, func()); + } +} + +// 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 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 +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' requested here}} +} + +template +void *atest() __attribute__((assume_aligned(q))); // expected-error {{requested alignment is not a power of 2}} + +template +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 __attribute__((assume_aligned(sizeof(int(T()))))) T *f(); +void test21() { + void *p = f(); // expected-note {{in instantiation of function template specialization 'f' requested here}} +} + +// expected-error@+1 {{functional-style cast from 'void' to 'int' is not allowed}} +template __attribute__((assume_aligned(sizeof((int(T())))))) T *g(); +void test23() { + void *p = g(); // expected-note {{in instantiation of function template specialization 'g' requested here}} +} + +template +T *atest3() __attribute__((assume_aligned(31, o))); // expected-error {{requested alignment is not a power of 2}} + +template +T *atest4() __attribute__((assume_aligned(32, o))); + +void test22() { + atest3(); + atest4(); +} + +// 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 +void *atest5() __attribute__((assume_aligned(X::x))); // expected-error {{requested alignment is not a power of 2}} +void test24() { + atest5(); + atest5(); + atest5(); // expected-note {{in instantiation of function template specialization 'atest5' 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(0); // expected-error {{const_cast from rvalue to reference type 'int &&'}} expected-warning {{C++11}} return **var3; } + +template +char *PR21845() { return const_cast((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{1, 2, 3}.begin() == 1, ""); + static_assert(std::initializer_list{1, 2, 3}.begin()[2] == 3, ""); } namespace StmtExpr { @@ -1700,7 +1749,7 @@ namespace VirtualFromBase { template 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 struct X { static const int n = N; }; - struct A { // expected-note {{subexpression}} - int k = X::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::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 + 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(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(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 (&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 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 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/cxx0x-initializer-stdinitializerlist-system-header.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp deleted file mode 100644 index 774745777c17..000000000000 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers %s - -// libstdc++4.6 in debug mode has explicit default constructors. -// stlport has this for all containers. -#ifdef BE_THE_HEADER -#pragma clang system_header -namespace std { -namespace __debug { -template -class vector { -public: - explicit vector() {} // expected-warning{{should not be explicit}} -}; -} -} -#else - -#define BE_THE_HEADER -#include __FILE__ - -struct { int a, b; std::__debug::vector c; } e[] = { {1, 1} }; // expected-note{{used in initialization here}} - -#endif 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 const char *operator "" _fritz(); +// CHECK: template const char *operator "" _fritz(); template 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 static CONST T b = T(100); template static CONST T b; }; - template CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}} + template 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'}} template CONST T B4::a; template CONST int B4::a; // expected-note {{in instantiation of}} template CONST int B4::a; template CONST T B4::b; - template CONST T B4::b; // expected-error {{default initialization of an object of const type 'const int'}} + template CONST T B4::b; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'b'}} template CONST int B4::b; template CONST int B4::b; // expected-note {{in instantiation of}} } @@ -321,3 +321,9 @@ namespace in_nested_classes { // TODO: } +namespace bitfield { +struct S { + template + 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 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::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 void EnumNNSFn() { template void EnumNNSFn(); // 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 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; class A { template 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 static T* var = new T(); + template static T* var = new T(); }; struct B { template 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 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 T* B::v = new T(); @@ -416,6 +391,6 @@ template<> int B::v = 10; template int B::v; float fsvar = B::v; -#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 void __stdcall StdcallTemplate(T) {} template <> void StdcallTemplate(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 struct S {}; // expected-error-re {{use of undeclared identifier 'I'{{$}}}} +S<1> s; + +template 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(), declval()))); + void swap(array& a) noexcept(noexcept(::swap(declval(), declval()))); }; struct DefaultOnly @@ -38,3 +38,4 @@ int main() { array 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,13 +35,19 @@ void stuff() { #endif } -struct S { int n; }; +struct S { int n; void operator+(int); }; struct T : private S { S::n; #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 + 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 }; 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 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(this)->m(); } + OwnPtr 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 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 struct __declspec(dllexport) PartiallySpecializedClassTemp template struct ExpliciallySpecializedClassTemplate {}; template <> struct __declspec(dllexport) ExpliciallySpecializedClassTemplate { void f() {} }; +// Don't instantiate class members of implicitly instantiated templates, even if they are exported. +struct IncompleteType; +template struct __declspec(dllexport) ImplicitlyInstantiatedExportedTemplate { + int f() { return sizeof(T); } // no-error +}; +ImplicitlyInstantiatedExportedTemplate implicitlyInstantiatedExportedTemplate; + +// Don't instantiate class members of templates with explicit instantiation declarations, even if they are exported. +struct IncompleteType2; +template struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl { + int f() { return sizeof(T); } // no-error +}; +extern template struct ExportedTemplateWithExplicitInstantiationDecl; + +// Instantiate class members for explicitly instantiated exported templates. +struct IncompleteType3; // expected-note{{forward declaration of 'IncompleteType3'}} +template struct __declspec(dllexport) ExplicitlyInstantiatedExportedTemplate { + int f() { return sizeof(T); } // expected-error{{invalid application of 'sizeof' to an incomplete type 'IncompleteType3'}} +}; +template struct ExplicitlyInstantiatedExportedTemplate; // expected-note{{in instantiation of member function 'ExplicitlyInstantiatedExportedTemplate::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::f' requested here}} +#endif +struct IncompleteType4; +template 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 {}; + +// Don't instantiate members of explicitly exported class templates that are base classes of exported classes. +struct IncompleteType5; +template struct __declspec(dllexport) ExportedBaseClassTemplateOfExportedClass { + int f() { return sizeof(T); }; // no-error +}; +struct __declspec(dllexport) ExportedBaseClass2 : public ExportedBaseClassTemplateOfExportedClass {}; + + //===----------------------------------------------------------------------===// // 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 = 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 void __declspec(dllimport) funcTmplDecl2(); template __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 __declspec(dllimport) inline void inlineFuncTmpl1() {} template inline void __attribute__((dllimport)) inlineFuncTmpl2() {} @@ -305,8 +347,10 @@ template void funcTmplRedecl3() {} // expected template void funcTmplRedecl4(); // expected-note{{previous declaration is here}} template __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}} +#ifdef MS template void funcTmplRedecl5(); // expected-note{{previous declaration is here}} template __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 friend __declspec(dllimport) void funcTmplFriend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} template friend __declspec(dllimport) void funcTmplFriend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} template friend void funcTmplFriend4(); // expected-note{{previous declaration is here}} +#ifdef GNU +// expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template friend __declspec(dllimport) inline void funcTmplFriend5(); }; template __declspec(dllimport) void funcTmplFriend1(); @@ -332,6 +379,9 @@ namespace ns { template __declspec(dllimport) void externalFuncTmpl( template void funcTmpl() {} template inline void inlineFuncTmpl() {} template __declspec(dllimport) void importedFuncTmplDecl(); +#ifdef GNU +// expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template __declspec(dllimport) inline void importedFuncTmpl() {} // Import implicit instantiation of an imported function template. @@ -350,7 +400,9 @@ template void importedFuncTmpl(); // declared inline. template<> __declspec(dllimport) void importedFuncTmpl(); template<> __declspec(dllimport) void importedFuncTmpl() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} +#ifdef MS template<> __declspec(dllimport) inline void importedFuncTmpl() {} +#endif // Not importing specialization of an imported function template without // explicit dllimport. @@ -359,16 +411,25 @@ template<> void importedFuncTmpl() {} // Import explicit instantiation declaration of a non-imported function template. extern template __declspec(dllimport) void funcTmpl(); +#ifdef GNU +// expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif extern template __declspec(dllimport) void inlineFuncTmpl(); // Import explicit instantiation definition of a non-imported function template. template __declspec(dllimport) void funcTmpl(); +#ifdef GNU +// expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template __declspec(dllimport) void inlineFuncTmpl(); // Import specialization of a non-imported function template. A definition must // be declared inline. template<> __declspec(dllimport) void funcTmpl(); template<> __declspec(dllimport) void funcTmpl() {} // 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() {} @@ -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 __declspec(dllimport) void normalDecl(); template __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} - template __declspec(dllimport) void normalInclass() {} template __declspec(dllimport) void normalInlineDef(); - template __declspec(dllimport) inline void normalInlineDecl(); template __declspec(dllimport) static void staticDecl(); template __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} - template __declspec(dllimport) static void staticInclass() {} template __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 __declspec(dllimport) void normalInclass() {} + template __declspec(dllimport) inline void normalInlineDecl(); + template __declspec(dllimport) static void staticInclass() {} template __declspec(dllimport) static inline void staticInlineDecl(); #if __has_feature(cxx_variable_templates) @@ -604,12 +738,17 @@ struct ImportMemberTmpl { }; template void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -template inline void ImportMemberTmpl::normalInlineDef() {} template void ImportMemberTmpl::normalInlineDecl() {} template void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -template inline void ImportMemberTmpl::staticInlineDef() {} template 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 inline void ImportMemberTmpl::normalInlineDef() {} +template inline void ImportMemberTmpl::staticInlineDef() {} + #if __has_feature(cxx_variable_templates) template int ImportMemberTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} template const int ImportMemberTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} @@ -620,12 +759,17 @@ template constexpr int ImportMemberTmpl::ConstexprFieldDef; // expec // Redeclarations cannot add dllimport. struct MemTmplRedecl { template void normalDef(); // expected-note{{previous declaration is here}} - template void normalInlineDef(); // expected-note{{previous declaration is here}} template inline void normalInlineDecl(); // expected-note{{previous declaration is here}} template static void staticDef(); // expected-note{{previous declaration is here}} - template static void staticInlineDef(); // expected-note{{previous declaration is here}} template 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 void normalInlineDef(); + template static void staticInlineDef(); + #if __has_feature(cxx_variable_templates) template static int StaticField; // expected-note{{previous declaration is here}} template static const int StaticConstField; // expected-note{{previous declaration is here}} @@ -635,11 +779,19 @@ struct MemTmplRedecl { template __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 __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllimport' attribute}} +#else +template __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +#endif template __declspec(dllimport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllimport' attribute}} template __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 __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}} +#else +template __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +#endif template __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 __declspec(dllimport) constexpr int MemTmplRedecl::Constexp struct MemFunTmpl { template void normalDef() {} +#ifdef GNU + // expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template __declspec(dllimport) void importedNormal() {} template static void staticDef() {} +#ifdef GNU + // expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template __declspec(dllimport) static void importedStatic() {} }; @@ -683,16 +841,24 @@ template void MemFunTmpl::importedStatic(); // Import specialization of an imported member function template. template<> __declspec(dllimport) void MemFunTmpl::importedNormal(); template<> __declspec(dllimport) void MemFunTmpl::importedNormal() {} // error on mingw +#ifdef GNU + // expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal() {} -#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(); template<> __declspec(dllimport) void MemFunTmpl::importedStatic() {} // error on mingw +#ifdef GNU + // expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic() {} -#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() {} // 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(); extern template __declspec(dllimport) void MemFunTmpl::staticDef(); // 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(); template __declspec(dllimport) void MemFunTmpl::staticDef(); // Import specialization of a non-imported member function template. template<> __declspec(dllimport) void MemFunTmpl::normalDef(); template<> __declspec(dllimport) void MemFunTmpl::normalDef() {} // error on mingw +#ifdef GNU + // expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template<> __declspec(dllimport) inline void MemFunTmpl::normalDef() {} -#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(); template<> __declspec(dllimport) void MemFunTmpl::staticDef() {} // error on mingw +#ifdef GNU + // expected-warning@+2{{'dllimport' attribute ignored on inline function}} +#endif template<> __declspec(dllimport) inline void MemFunTmpl::staticDef() {} -#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 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 void ImportClassTmplMembers::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 inline void ImportClassTmplMembers::normalInlineDef() {} template void ImportClassTmplMembers::normalInlineDecl() {} template void ImportClassTmplMembers::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 inline void ImportClassTmplMembers::virtualInlineDef() {} template void ImportClassTmplMembers::virtualInlineDecl() {} template void ImportClassTmplMembers::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 inline void ImportClassTmplMembers::staticInlineDef() {} template void ImportClassTmplMembers::staticInlineDecl() {} @@ -835,15 +1035,21 @@ template constexpr int ImportClassTmplMembers::ConstexprFieldDef; template 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 __declspec(dllimport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template __declspec(dllimport) inline void CTMR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}} template __declspec(dllimport) void CTMR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllimport' attribute}} template __declspec(dllimport) void CTMR::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template __declspec(dllimport) inline void CTMR::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}} template __declspec(dllimport) void CTMR::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllimport' attribute}} template __declspec(dllimport) void CTMR::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}} template __declspec(dllimport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}} +#ifdef MS +template __declspec(dllimport) inline void CTMR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void CTMR::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}} +#else +template __declspec(dllimport) inline void CTMR::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +template __declspec(dllimport) inline void CTMR::virtualInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +#endif + template __declspec(dllimport) int CTMR::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 struct ImportClsTmplMemTmpl { template __declspec(dllimport) void normalDecl(); template __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} - template __declspec(dllimport) void normalInclass() {} template __declspec(dllimport) void normalInlineDef(); - template __declspec(dllimport) inline void normalInlineDecl(); template __declspec(dllimport) static void staticDecl(); template __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} - template __declspec(dllimport) static void staticInclass() {} template __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 __declspec(dllimport) void normalInclass() {} + template __declspec(dllimport) inline void normalInlineDecl(); + template __declspec(dllimport) static void staticInclass() {} template __declspec(dllimport) static inline void staticInlineDecl(); #if __has_feature(cxx_variable_templates) @@ -904,12 +1124,17 @@ struct ImportClsTmplMemTmpl { }; template template void ImportClsTmplMemTmpl::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -template template inline void ImportClsTmplMemTmpl::normalInlineDef() {} template template void ImportClsTmplMemTmpl::normalInlineDecl() {} template template void ImportClsTmplMemTmpl::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -template template inline void ImportClsTmplMemTmpl::staticInlineDef() {} template template void ImportClsTmplMemTmpl::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 template inline void ImportClsTmplMemTmpl::normalInlineDef() {} +template template inline void ImportClsTmplMemTmpl::staticInlineDef() {} + #if __has_feature(cxx_variable_templates) template template int ImportClsTmplMemTmpl::StaticFieldDef; // expected-warning{{definition of dllimport static field}} template template const int ImportClsTmplMemTmpl::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} @@ -921,12 +1146,17 @@ template template constexpr int ImportClsTmplMemTmpl: template struct CTMTR /*ClassTmplMemberTmplRedecl*/ { template void normalDef(); // expected-note{{previous declaration is here}} - template void normalInlineDef(); // expected-note{{previous declaration is here}} template inline void normalInlineDecl(); // expected-note{{previous declaration is here}} template static void staticDef(); // expected-note{{previous declaration is here}} - template static void staticInlineDef(); // expected-note{{previous declaration is here}} template 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 void normalInlineDef(); + template static void staticInlineDef(); + #if __has_feature(cxx_variable_templates) template static int StaticField; // expected-note{{previous declaration is here}} template static const int StaticConstField; // expected-note{{previous declaration is here}} @@ -936,13 +1166,19 @@ struct CTMTR /*ClassTmplMemberTmplRedecl*/ { template template __declspec(dllimport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template template __declspec(dllimport) inline void CTMTR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}} template template __declspec(dllimport) void CTMTR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllimport' attribute}} template template __declspec(dllimport) void CTMTR::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}} template template __declspec(dllimport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}} +#ifdef MS +template template __declspec(dllimport) inline void CTMTR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}} +#else +template template __declspec(dllimport) inline void CTMTR::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} +#endif + #if __has_feature(cxx_variable_templates) template template __declspec(dllimport) int CTMTR::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 template __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 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' requested here}} } + +template class C { + void f() __attribute__((enable_if(T::expr == 0, ""))) {} + void g() { f(); } +}; + +int fn3(bool b) __attribute__((enable_if(b, ""))); +template 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 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 void test1() { + int &expr = T::expr(); + fn1(expr); + } + + int fn2(const Integer &) __attribute__((enable_if(false, ""))); // expected-note{{candidate disabled}} + template 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 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::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 struct ExceptionIf { static int f(); }; template<> struct ExceptionIf { 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::f(); // expected-error {{cannot be used by non-static data member initializer}} + int n = ExceptionIf::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::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::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 { }; template -struct classify_function { +struct classify_function { static const unsigned value = 5; }; template -struct classify_function { +struct classify_function { static const unsigned value = 6; }; template -struct classify_function { +struct classify_function { static const unsigned value = 7; }; template -struct classify_function { +struct classify_function { static const unsigned value = 8; }; template -struct classify_function { +struct classify_function { static const unsigned value = 9; }; template -struct classify_function { +struct classify_function { 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 +void Job(L l); + +template +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 +struct A { + T t; + // expected-error@-1 {{field has incomplete type 'void'}} +}; + +template +void g(F f) { + auto a = A{}; + // expected-note@-1 {{in instantiation of template class 'PR20731::A' 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 struct function { + template + function(_Fp) { + static_assert(sizeof(_Fp) > 0, "Type must be complete."); + } +}; + +template void p(T t) { + auto l = some_undefined_function(t); + // expected-error@-1 {{use of undeclared identifier 'some_undefined_function'}} + function(([l]() {})); +} +void q() { p(0); } +// expected-note@-1 {{in instantiation of function template specialization 'PR20731::p' requested here}} +} + +namespace lambda_in_default_mem_init { + template void f() { + struct S { int n = []{ return 0; }(); }; + } + template void f(); + + template void g() { + struct S { int n = [](int n){ return n; }(0); }; + } + template void g(); +} + +namespace error_in_transform_prototype { + template + 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/libstdcxx_explicit_init_list_hack.cpp b/test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp new file mode 100644 index 000000000000..774745777c17 --- /dev/null +++ b/test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers %s + +// libstdc++4.6 in debug mode has explicit default constructors. +// stlport has this for all containers. +#ifdef BE_THE_HEADER +#pragma clang system_header +namespace std { +namespace __debug { +template +class vector { +public: + explicit vector() {} // expected-warning{{should not be explicit}} +}; +} +} +#else + +#define BE_THE_HEADER +#include __FILE__ + +struct { int a, b; std::__debug::vector c; } e[] = { {1, 1} }; // expected-note{{used in initialization here}} + +#endif 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 -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 ipi; // Ditto for __is_same. template -struct __is_same { +struct __is_same { // expected-warning {{keyword '__is_same' will be made available as an identifier}} }; __is_same isi; @@ -24,7 +24,7 @@ __is_same 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 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 void swap(T &, T &); + template void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) { + swap(a, b); + } + + template 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 void do_swap(T &, T &); +// template 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; +using PI = std::CLASS; +void swap(X &, X &) noexcept; +PX px; +PI pi; + +static_assert(noexcept(px.swap(px)), ""); +static_assert(!noexcept(pi.swap(pi)), ""); + +namespace sad { + template void swap(T &, T &); + + template struct CLASS { + void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}} + }; + + CLASS 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 + struct B { int m1 = sizeof(A) + sizeof(T); }; + B m2; +}; +A::A() {} +} + +namespace template_default_ctor { +struct A { + template + 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' first required here}} + enum { NOE = noexcept(B()) }; +}; +} + +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 + 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 + 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::C' first required here}} + NOE1 = noexcept(B::C()), + // expected-note@+1 {{implicit default constructor for 'member_template::A::B::D' first required here}} + NOE2 = noexcept(B::D()) + }; +}; +} + +namespace explicit_instantiation { +template struct X { + X(); // expected-note {{in instantiation of default member initializer 'explicit_instantiation::X::n' requested here}} + int n = T::error; // expected-error {{type 'float' cannot be used prior to '::' because it has no members}} +}; +template struct X; // ok +template X::X() {} +template struct X; // expected-note {{in instantiation of member function 'explicit_instantiation::X::X' requested here}} +} + +namespace local_class { +template 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(); } // expected-note {{in instantiation of function template specialization 'local_class::f' requested here}} +} + +namespace PR22056 { +template +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 +struct A { + int T::*f(); +}; + +struct B; + +auto a = &A::f; + +struct B {}; + +void q() { + A 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 __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 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 struct A { typename T::error e; }; // expected-error {{type 'char' cannot be used prior to '::'}} + template struct B { int n; }; + + void f(B > b1, B > b2, B > b3) { + b1 = b1; // ok, does not instantiate A. + (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 + +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 + +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 int PR9412_t() { } // expected-warning {{control reaches end of non-void function}} void PR9412_f() { - PR9412_t(); // expected-note {{in instantiation of function template specialization 'PR9412_t<0>' requested here}} + PR9412_t(); // expected-note {{in instantiation of function template specialization 'PR9412_t' 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 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 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 +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(); // expected-note {{in instantiation of function template specialization 'PR21848' 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 struct Y; // expected-note{{did you mean class here?}} template class Y { }; // expected-warning{{previously declared}} +template +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 p4 = xx.get_nested().h(0L, 1.0, 3.14f); namespace PR12053 { template 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 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 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 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 -void A(T) { } // expected-note {{'::TemplateFunction::A' declared here}} - -template -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 - 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 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 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::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 SetVector { - public: - SetVector() {} -}; - -template -class SmallSetVector : public SetVector {}; - -class foo {}; -SmallSetVector fooSet; -} - -PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}} - -namespace shadowed_template { -template 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 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 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(&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::*)() const); + void g(void(*)()); // expected-note{{candidate function not viable}} + void g(bool(S::*)() const); // expected-note{{candidate function not viable}} void test() { - g(&S::tempalte f); // expected-error{{did you mean 'template'?}} + g(&S::tempalte f); // expected-error{{did you mean 'template'?}} \ + // expected-error{{no matching function for call to 'g'}} g(&S::opeartor bool); // expected-error{{did you mean 'operator'?}} g(&S::foo); // expected-error{{no member named 'foo' in 'PR13051::S'; 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 struct Err { typename T::error n; }; // expected-error{{type 'void *' cannot be used prior to '::' because it has no members}} struct S { template typename Err::type method(T); // expected-note{{in instantiation of template class 'b6956809_test2::Err' requested here}} - template int method(T *); + template 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 +void A(T) { } // expected-note {{'::TemplateFunction::A' declared here}} + +template +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 + 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 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 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::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 SetVector { + public: + SetVector() {} +}; + +template +class SmallSetVector : public SetVector {}; + +class foo {}; +SmallSetVector fooSet; +} + +PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}} + +namespace shadowed_template { +template 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 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 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(&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 struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template typename remove_reference::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(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(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 +class A { +public: + // Don't warn on foo here. + A() : ptr(foo->Create()) {} + +private: + Foo *foo = new Foo; + int *ptr; +}; + +template +class B { +public: + // foo is uninitialized here, but class B is never instantiated. + B() : ptr(foo->Create()) {} + +private: + Foo *foo; + int *ptr; +}; + +template +class C { +public: + C() : ptr(foo->Create()) {} + // expected-warning@-1 {{field 'foo' is uninitialized when used here}} +private: + Foo *foo; + int *ptr; +}; + +C c; +// expected-note@-1 {{in instantiation of member function 'template_class::C::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 T move(T t); +template T notmove(T t); +} +namespace lvalueref { +template T move(T& t); +template T notmove(T& t); +} +namespace rvalueref { +template T move(T&& t); +template 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 struct A { typedef T type; - + type f(); type g(); @@ -93,14 +93,14 @@ template int A::h(T::type x, char) {} // expected-error{{missing template int h(T::type, int); // expected-error{{missing 'typename'}} template int h(T::type x, char); // expected-error{{missing 'typename'}} -template int junk1(T::junk); // expected-warning{{variable templates are a C++1y extension}} +template int junk1(T::junk); // expected-warning{{variable templates are a C++14 extension}} template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}} template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} expected-warning{{C++11}} template 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 int i(T::type, int()); // expected-warning{{variable templates are a C++1y extension}} +template 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::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.cc deleted file mode 100644 index 2a1b98900647..000000000000 --- a/test/SemaCXX/vtable-instantiation.cc +++ /dev/null @@ -1,68 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -namespace PR8640 { - template struct C1 { - virtual void c1() { - T1 t1 = 3; // expected-error {{cannot initialize a variable}} - } - }; - - template struct C2 { - void c2() { - new C1(); // expected-note {{in instantiation of member function}} - } - }; - - void f() { - C2 c2; - c2.c2(); // expected-note {{in instantiation of member function}} - } -} - -namespace PR9325 { - template - class Target - { - public: - virtual T Value() const - { - return 1; // expected-error{{cannot initialize return object of type 'int *' with an rvalue of type 'int'}} - } - }; - - template - struct Provider - { - static Target Instance; - }; - - template - Target Provider::Instance; // expected-note{{in instantiation of}} - - void f() - { - Target* traits = &Provider::Instance; - } -} - -namespace PR10020 { - struct MG { - virtual void Accept(int) = 0; - }; - - template - struct GMG : MG { - void Accept(int i) { - static_cast(0)->Accept(i); // expected-error{{member reference base}} - } - static GMG* Method() { return &singleton; } // expected-note{{in instantiation of}} - static GMG singleton; - }; - - template - GMG GMG::singleton; - - void test(void) { - GMG::Method(); // expected-note{{in instantiation of}} - } -} diff --git a/test/SemaCXX/vtable-instantiation.cpp b/test/SemaCXX/vtable-instantiation.cpp new file mode 100644 index 000000000000..78f2b3ed1a2a --- /dev/null +++ b/test/SemaCXX/vtable-instantiation.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8640 { + template struct C1 { + virtual void c1() { + T1 t1 = 3; // expected-error {{cannot initialize a variable}} + } + }; + + template struct C2 { + void c2() { + new C1(); // expected-note {{in instantiation of member function}} + } + }; + + void f() { + C2 c2; + c2.c2(); // expected-note {{in instantiation of member function}} + } +} + +namespace PR9325 { + template + class Target + { + public: + virtual T Value() const + { + return 1; // expected-error{{cannot initialize return object of type 'int *' with an rvalue of type 'int'}} + } + }; + + template + struct Provider + { + static Target Instance; + }; + + template + Target Provider::Instance; // expected-note{{in instantiation of}} + + void f() + { + Target* traits = &Provider::Instance; // expected-note{{requested here}} + } +} + +namespace PR10020 { + struct MG { + virtual void Accept(int) = 0; + }; + + template + struct GMG : MG { + void Accept(int i) { + static_cast(0)->Accept(i); // expected-error{{member reference base}} + } + static GMG* Method() { return &singleton; } // expected-note{{in instantiation of}} + static GMG singleton; + }; + + template + GMG GMG::singleton; // expected-note{{requested here}} + + void test(void) { + GMG::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 struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template typename remove_reference::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 MyMap { +public: + T& operator[](const K& k); +}; + + +// For testing handling of containers. +template +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 map; + MyMap 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 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 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(&custMu)); // ignore casts + doSomethingRequiringLock(); + customUnlock(reinterpret_cast(&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 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 +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 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 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 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(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 +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 +struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +auto pointer_sneaky() { + struct S { + typedef int t; + typedef int s; + }; + return (S*)nullptr; +} +remove_reference::type::t py; + +// Like sneaky(), but returning templated struct referencing local type. +template struct container { int a; T t; }; +auto template_sneaky() { + struct S { + typedef int t; + typedef int s; + }; + return container(); +} +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 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 + 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 +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 +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 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 +} +} -- cgit v1.2.3