// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,cxx11 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20 // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20 // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx14,since-cxx20 #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) // cxx98-error@-1 {{variadic macros are a C99 feature}} #endif namespace cwg2007 { // cwg2007: 3.4 template struct A { typename T::error e; }; template struct B { }; B > b1; B > b2 = b1; int a = b2[0]; // cxx98-error@-1 {{type 'B >' does not provide a subscript operator}} // since-cxx11-error@-2 {{type 'B>' does not provide a subscript operator}} int b = __builtin_addressof(b2)->foo; // cxx98-error@-1 {{no member named 'foo' in 'cwg2007::B >'}} // since-cxx11-error@-2 {{no member named 'foo' in 'cwg2007::B>'}} } // namespace cwg2007 // cwg2009: na // cwg2026 is in cwg2026.cpp namespace cwg2049 { // cwg2049: 18 #if __cplusplus >= 202302L template struct X {}; X<> a; X b; static_assert(__is_same(decltype(a), decltype(b))); #endif } // namespace cwg2049 namespace cwg2061 { // cwg2061: 2.7 #if __cplusplus >= 201103L namespace A { inline namespace b { namespace C { // 'f' is the example from the DR. 'S' is an example where if we didn't // properly handle the two being the same, we would get an incomplete // type error during attempted instantiation. template void f(); template struct S; } } } namespace A { namespace C { template<> void f() { } template<> struct S { }; } } void use() { A::C::f(); A::C::S s; } #endif // C++11 } // namespace cwg2061 namespace cwg2076 { // cwg2076: 13 #if __cplusplus >= 201103L namespace std_example { struct A { A(int); }; struct B { B(A); }; B b{{0}}; struct Params { int a; int b; }; struct Foo { Foo(Params); }; Foo foo{{1, 2}}; } struct string_view { string_view(int); // not an aggregate }; struct string { string(int); // not an aggregate operator string_view() const; }; void foo(const string &); // #cwg2076-foo void bar(string_view); // #cwg2076-bar void func(const string &arg) { // An argument in one set of braces is subject to user-defined conversions; // an argument in two sets of braces is not, but an identity conversion is // still OK. foo(arg); foo({arg}); foo({{arg}}); foo({{{arg}}}); // since-cxx11-error@-1 {{no matching function for call to 'foo'}} // since-cxx11-note@#cwg2076-foo {{candidate function not viable: cannot convert initializer list argument to 'const string'}} bar(arg); bar({arg}); bar({{arg}}); // since-cxx11-error@-1 {{no matching function for call to 'bar'}} // since-cxx11-note@#cwg2076-bar {{candidate function not viable: cannot convert initializer list argument to 'string_view'}} bar({{{arg}}}); // since-cxx11-error@-1 {{no matching function for call to 'bar'}} // since-cxx11-note@#cwg2076-bar {{candidate function not viable: cannot convert initializer list argument to 'string_view'}} } #endif } // namespace cwg2076 namespace cwg2082 { // cwg2082: 11 void test1(int x, int = sizeof(x)); // ok #if __cplusplus >= 201103L void test2(int x, int = decltype(x){}); // ok #endif } // namespace cwg2082 namespace cwg2083 { // cwg2083: partial #if __cplusplus >= 201103L void non_const_mem_ptr() { struct A { int x; int y; }; constexpr A a = {1, 2}; struct B { int A::*p; constexpr int g() const { // OK, not an odr-use of 'a'. return a.*p; }; }; static_assert(B{&A::x}.g() == 1, ""); static_assert(B{&A::y}.g() == 2, ""); } #endif const int a = 1; int b; // Note, references only get special odr-use / constant initializxer // treatment in C++11 onwards. We continue to apply that even after CWG2083. void ref_to_non_const() { int c; const int &ra = a; // #cwg2083-ra int &rb = b; // #cwg2083-rb int &rc = c; // #cwg2083-rc struct A { int f() { int a = ra; // cxx98-error@-1 {{reference to local variable 'ra' declared in enclosing function 'cwg2083::ref_to_non_const'}} // cxx98-note@#cwg2083-ra {{'ra' declared here}} int b = rb; // cxx98-error@-1 {{reference to local variable 'rb' declared in enclosing function 'cwg2083::ref_to_non_const'}} // cxx98-note@#cwg2083-rb {{'rb' declared here}} int c = rc; // expected-error@-1 {{reference to local variable 'rc' declared in enclosing function 'cwg2083::ref_to_non_const'}} // expected-note@#cwg2083-rc {{'rc' declared here}} return a + b + c; } }; } #if __cplusplus >= 201103L struct NoMut1 { int a, b; }; struct NoMut2 { NoMut1 m; }; struct NoMut3 : NoMut1 { constexpr NoMut3(int a, int b) : NoMut1{a, b} {} }; struct Mut1 { int a; mutable int b; }; struct Mut2 { Mut1 m; }; struct Mut3 : Mut1 { constexpr Mut3(int a, int b) : Mut1{a, b} {} }; void mutable_subobjects() { constexpr NoMut1 nm1 = {1, 2}; constexpr NoMut2 nm2 = {1, 2}; constexpr NoMut3 nm3 = {1, 2}; constexpr Mut1 m1 = {1, 2}; // #cwg2083-m1 constexpr Mut2 m2 = {1, 2}; // #cwg2083-m2 constexpr Mut3 m3 = {1, 2}; // #cwg2083-m3 struct A { void f() { static_assert(nm1.a == 1, ""); static_assert(nm2.m.a == 1, ""); static_assert(nm3.a == 1, ""); // Can't even access a non-mutable member of a variable containing mutable fields. static_assert(m1.a == 1, ""); // since-cxx11-error@-1 {{reference to local variable 'm1' declared in enclosing function 'cwg2083::mutable_subobjects'}} // since-cxx11-note@#cwg2083-m1 {{'m1' declared here}} static_assert(m2.m.a == 1, ""); // since-cxx11-error@-1 {{reference to local variable 'm2' declared in enclosing function 'cwg2083::mutable_subobjects'}} // since-cxx11-note@#cwg2083-m2 {{'m2' declared here}} static_assert(m3.a == 1, ""); // since-cxx11-error@-1 {{reference to local variable 'm3' declared in enclosing function 'cwg2083::mutable_subobjects'}} // since-cxx11-note@#cwg2083-m3 {{'m3' declared here}} } }; } #endif void ellipsis() { void ellipsis(...); struct A {}; const int n = 0; #if __cplusplus >= 201103L constexpr #endif A a = {}; // #cwg2083-a struct B { void f() { ellipsis(n); // Even though this is technically modelled as an lvalue-to-rvalue // conversion, it calls a constructor and binds 'a' to a reference, so // it results in an odr-use. ellipsis(a); // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::ellipsis'}} // expected-note@#cwg2083-a {{'a' declared here}} } }; } #if __cplusplus >= 201103L void volatile_lval() { struct A { int n; }; constexpr A a = {0}; // #cwg2083-a2 struct B { void f() { // An lvalue-to-rvalue conversion of a volatile lvalue always results // in odr-use. int A::*p = &A::n; int x = a.*p; volatile int A::*q = p; int y = a.*q; // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::volatile_lval'}} // since-cxx11-note@#cwg2083-a2 {{'a' declared here}} } }; } #endif void discarded_lval() { struct A { int x; mutable int y; volatile int z; }; A a; // #cwg2083-a-3 int &r = a.x; // #cwg2083-r struct B { void f() { // FIXME: We emit more errors than we should be. They are explicitly // marked below. (void)a.x; // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME // expected-note@#cwg2083-a-3 {{'a' declared here}} (void)(a.*&A::x); // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME // expected-note@#cwg2083-a-3 {{'a' declared here}} (void)(true ? a.x : a.y); // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME // expected-note@#cwg2083-a-3 {{'a' declared here}} // expected-error@-3 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME // expected-note@#cwg2083-a-3 {{'a' declared here}} (void)a.x; // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME // expected-note@#cwg2083-a-3 {{'a' declared here}} (void)a.x, discarded_lval(); // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME // expected-note@#cwg2083-a-3 {{'a' declared here}} // 'volatile' qualifier triggers an lvalue-to-rvalue conversion. int i = a.z; // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} // expected-note@#cwg2083-a-3 {{'a' declared here}} // References always get "loaded" to determine what they reference, // even if the result is discarded. (void)r; // expected-error@-1 {{reference to local variable 'r' declared in enclosing function 'cwg2083::discarded_lval'}} // expected-note@#cwg2083-r {{'r' declared here}} } }; } namespace dr_example_1 { extern int globx; int main() { const int &x = globx; // #cwg2083-x struct A { const int *foo() { return &x; } // cxx98-error@-1 {{reference to local variable 'x' declared in enclosing function 'cwg2083::dr_example_1::main'}} // cxx98-note@#cwg2083-x {{'x' declared here}} } a; return *a.foo(); } } #if __cplusplus >= 201103L namespace dr_example_2 { struct A { int q; constexpr A(int q) : q(q) {} constexpr A(const A &a) : q(a.q * 2) {} // (note, not called) }; int main(void) { constexpr A a(42); constexpr int aq = a.q; struct Q { int foo() { return a.q; } } q; return q.foo(); } // Checking odr-use does not invent an lvalue-to-rvalue conversion (and // hence copy construction) on the potential result variable. struct B { int b = 42; constexpr B() {} constexpr B(const B&) = delete; }; void f() { constexpr B b; struct Q { constexpr int foo() const { return b.b; } }; static_assert(Q().foo() == 42, ""); } } #endif } // namespace cwg2083 namespace cwg2084 { // cwg2084: 3.1 struct S { S(); }; union U { S s{}; // cxx98-error {{function definition does not declare parameters}} } u; } // namespace cwg2084 namespace cwg2091 { // cwg2091: 10 template struct X; template void f(X&); int n; void g(X &x) { f(x); } namespace GH42233 { enum E { I }; class AA { }; E EV[1] = {I}; template struct S { template< class E, const E* const V> friend AA& operator<<( AA& os, const S& e ); }; int f() { S< E, EV > x; AA a; a << x; return 0; } } // namespace GH42233 } // namespace cwg2091 namespace cwg2094 { // cwg2094: 5 struct A { int n; }; struct B { volatile int n; }; static_assert(__is_trivially_copyable(volatile int), ""); static_assert(__is_trivially_copyable(const volatile int), ""); static_assert(__is_trivially_copyable(const volatile int[]), ""); static_assert(__is_trivially_copyable(A), ""); static_assert(__is_trivially_copyable(volatile A), ""); static_assert(__is_trivially_copyable(const volatile A), ""); static_assert(__is_trivially_copyable(const volatile A[]), ""); static_assert(__is_trivially_copyable(B), ""); static_assert(__is_trivially_constructible(A, A const&), ""); static_assert(__is_trivially_constructible(B, B const&), ""); static_assert(__is_trivially_assignable(A, const A&), ""); static_assert(__is_trivially_assignable(B, const B&), ""); } // namespace cwg2094 // cwg2096: dup 2598