diff options
Diffstat (limited to 'test/CXX')
47 files changed, 1597 insertions, 97 deletions
diff --git a/test/CXX/basic/basic.link/p1.cpp b/test/CXX/basic/basic.link/p1.cpp new file mode 100644 index 0000000000..c6a119aa7f --- /dev/null +++ b/test/CXX/basic/basic.link/p1.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_MODULE_DECL %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_PRIVATE_FRAG %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_MODULE_DECL -DNO_PRIVATE_FRAG %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG -DNO_PRIVATE_FRAG %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG -DNO_MODULE_DECL %s +// RUN: %clang_cc1 -std=c++2a -verify -DNO_GLOBAL_FRAG -DNO_MODULE_DECL -DNO_PRIVATE_FRAG %s +// RUN: %clang_cc1 -std=c++2a -verify -DEXPORT_FRAGS %s + +#ifndef NO_GLOBAL_FRAG +#ifdef EXPORT_FRAGS +export // expected-error {{global module fragment cannot be exported}} +#endif +module; +#ifdef NO_MODULE_DECL +// expected-error@-2 {{missing 'module' declaration at end of global module fragment introduced here}} +#endif +#endif + +extern int a; // #a1 + +#ifndef NO_MODULE_DECL +export module Foo; +#ifdef NO_GLOBAL_FRAG +// expected-error@-2 {{module declaration must occur at the start of the translation unit}} +// expected-note@1 {{add 'module;' to the start of the file to introduce a global module fragment}} +#endif + +// expected-error@#a2 {{declaration of 'a' in module Foo follows declaration in the global module}} +// expected-note@#a1 {{previous decl}} +#endif + +int a; // #a2 +extern int b; + +module; // expected-error {{'module;' introducing a global module fragment can appear only at the start of the translation unit}} + +#ifndef NO_PRIVATE_FRAG +#ifdef EXPORT_FRAGS +export // expected-error {{private module fragment cannot be exported}} +#endif +module :private; // #priv-frag +#ifdef NO_MODULE_DECL +// expected-error@-2 {{private module fragment declaration with no preceding module declaration}} +#endif +#endif + +int b; // ok + + +#ifndef NO_PRIVATE_FRAG +#ifndef NO_MODULE_DECL +module :private; // expected-error {{private module fragment redefined}} +// expected-note@#priv-frag {{previous definition is here}} +#endif +#endif diff --git a/test/CXX/basic/basic.link/p2.cpp b/test/CXX/basic/basic.link/p2.cpp new file mode 100644 index 0000000000..54e347c91e --- /dev/null +++ b/test/CXX/basic/basic.link/p2.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++2a -DEXPORT %s -verify +// RUN: %clang_cc1 -std=c++2a -DEXPORT %s -emit-module-interface -o %t.pcm +// RUN: %clang_cc1 -std=c++2a -UEXPORT %s -verify -fmodule-file=%t.pcm + +#ifdef EXPORT +// expected-no-diagnostics +export +#else +// expected-note@+2 {{add 'export' here}} +#endif +module M; + +#ifndef EXPORT +// expected-error@+2 {{private module fragment in module implementation unit}} +#endif +module :private; diff --git a/test/CXX/basic/basic.link/p3.cpp b/test/CXX/basic/basic.link/p3.cpp new file mode 100644 index 0000000000..23f39d11b6 --- /dev/null +++ b/test/CXX/basic/basic.link/p3.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -verify %s -DIMPORT_ERROR=1 +// RUN: %clang_cc1 -std=c++2a -verify %s -DIMPORT_ERROR=2 + +module; + +#if IMPORT_ERROR != 2 +struct import { struct inner {}; }; +#endif +struct module { struct inner {}; }; + +constexpr int n = 123; + +export module m; // #1 + +// Import errors are fatal, so we test them in isolation. +#if IMPORT_ERROR == 1 +import x = {}; // expected-error {{module 'x' not found}} + +#elif IMPORT_ERROR == 2 +struct X; +template<int> struct import; +template<> struct import<n> { + static X y; +}; + +// This is not valid because the 'import <n>' is a pp-import, even though it +// grammatically can't possibly be an import declaration. +struct X {} import<n>::y; // expected-error {{'n' file not found}} + +#else +module y = {}; // expected-error {{multiple module declarations}} expected-error 2{{}} +// expected-note@#1 {{previous module declaration}} + +::import x = {}; +::module y = {}; + +import::inner xi = {}; +module::inner yi = {}; + +namespace N { + module a; + import b; +} + +extern "C++" module cxxm; +extern "C++" import cxxi; + +template<typename T> module module_var_template; + +// This is a variable named 'import' that shadows the type 'import' above. +struct X {} import; +#endif diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp new file mode 100644 index 0000000000..7562e64b17 --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp @@ -0,0 +1,344 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +// Attempt to test each rule for forming associated namespaces +// and classes as described in [basic.lookup.argdep]p2. + +// fundamental type: no associated namespace and no associated class +namespace adl_fundamental_type { + constexpr int g(char) { return 1; } // #1 + template <typename T> constexpr int foo(T t) { return g(t); } + constexpr int g(int) { return 2; } // #2 not found + void test() { + static_assert(foo(0) == 1); // ok, #1 + } +} + +// class type: +// associated classes: itself, the class of which it is a member (if any), +// direct and indirect base classes +// associated namespaces: innermost enclosing namespaces of associated classes +namespace adl_class_type { + // associated class: itself, simple case + namespace X1 { + namespace N { + struct S {}; + void f(S); // found + } + void g(N::S); // not found + }; + void test1() { + f(X1::N::S{}); // ok + g(X1::N::S{}); // expected-error {{use of undeclared identifier}} + } + + // associated class: itself, local type + namespace X2 { + auto foo() { + struct S {} s; + return s; + } + using S = decltype(foo()); + void f(S); // #1 + } + void test2() { + f(X2::S{}); // This is well-formed; X2 is the innermost enclosing namespace + // of the local struct S. Calls #1. + } + + // associated class: the parent class + namespace X3 { + struct S { + struct T {}; + friend void f(T); + }; + } + void test3() { + f(X3::S::T{}); // ok + } + + // associated class: direct and indirect base classes + namespace X4 { + namespace IndirectBaseNamespace { + struct IndirectBase {}; + void f(IndirectBase); // #1 + } + namespace DirectBaseNamespace { + struct DirectBase : IndirectBaseNamespace::IndirectBase {}; + void g(DirectBase); // #2 + } + struct S : DirectBaseNamespace::DirectBase {}; + } + void test4() { + f(X4::S{}); // ok, #1 + g(X4::S{}); // ok, #2 + } + + // associated class: itself, lambda + namespace X5 { + namespace N { + auto get_lambda() { return [](){}; } + void f(decltype(get_lambda())); + } + + void test5() { + auto lambda = N::get_lambda(); + f(lambda); // ok + } + } + + // The parameter types and return type of a lambda's operator() do not + // contribute to the associated namespaces and classes of the lambda itself. + namespace X6 { + namespace N { + struct A {}; + template<class T> constexpr int f(T) { return 1; } + } + + constexpr int f(N::A (*)()) { return 2; } + constexpr int f(void (*)(N::A)) { return 3; } + + void test() { + constexpr auto lambda = []() -> N::A { return {}; }; + static_assert(f(lambda) == 2); + + constexpr auto lambda2 = [](N::A) {}; + static_assert(f(lambda2) == 3); + } + } +} // namespace adl_class_type + +// class template specialization: as for class type plus +// for non-type template arguments: +// - nothing +// for type template arguments: +// - associated namespaces and classes of the type template arguments +// for template template arguments: +// - namespaces of which template template arguments are member of +// - classes of which member template used as template template arguments +// are member of +namespace adl_class_template_specialization_type { + // non-type template argument + namespace X1 { + namespace BaseNamespace { struct Base {}; } + namespace N { struct S : BaseNamespace::Base {}; } + template <N::S *> struct C {}; + namespace N { + template <S *p> void X1_f(C<p>); // #1 + } + namespace BaseNamespace { + template <N::S *p> void X1_g(C<p>); // #2 + } + template <N::S *p> void X1_h(C<p>); // #3 + } + void test1() { + constexpr X1::N::S *p = nullptr; + X1::C<p> c; + X1_f(c); // N is not added to the set of associated namespaces + // and #1 is not found... + // expected-error@-2 {{use of undeclared identifier}} + X1_g(c); // ... nor is #2 ... + // expected-error@-1 {{use of undeclared identifier}} + X1_h(c); // ... but the namespace X1 is added and #3 is found. + } + + // type template argument + namespace X2 { + template <typename T> struct C {}; + namespace BaseNamespace { struct Base {}; } + namespace N { struct S : BaseNamespace::Base {}; } + namespace N { + template <typename T> void X2_f(C<T>); // #1 + } + namespace BaseNamespace { + template <typename T> void X2_g(C<T>); // #2 + } + template <typename T> void X2_h(C<T>); // #2 + } + void test2() { + X2::C<X2::N::S> c; + X2_f(c); // N is added to the set of associated namespaces and #1 is found. + X2_g(c); // Similarly BaseNamespace is added and #2 is found. + X2_h(c); // As before, X2 is also added and #3 is found. + } + + // template template argument + namespace X3 { + template <template <typename> class TT> struct C {}; + namespace N { + template <typename T> struct Z {}; + void X3_f(C<Z>); // #1 + } + struct M { + template <typename T> struct Z {}; + friend void X3_g(C<Z>); // #2 + }; + } + void test3() { + X3::C<X3::N::Z> c1; + X3::C<X3::M::Z> c2; + X3_f(c1); // ok, namespace N is added, #1 + X3_g(c2); // ok, struct M is added, #2 + } +} + +// enumeration type: +// associated namespace: innermost enclosing namespace of its declaration. +// associated class: if the enumeration is a class member, the member's class. +namespace adl_enumeration_type { + namespace N { + enum E : int; + void f(E); + struct S { + enum F : int; + friend void g(F); + }; + auto foo() { + enum G {} g; + return g; + } + using G = decltype(foo()); + void h(G); + } + + void test() { + N::E e; + f(e); // ok + N::S::F f; + g(f); // ok + N::G g; + h(g); // ok + + } +} + +// pointer and reference type: +// associated namespaces and classes of the pointee type +// array type: +// associated namespaces and classes of the base type +namespace adl_point_array_reference_type { + namespace N { + struct S {}; + void f(S *); + void f(S &); + } + + void test() { + N::S *p; + f(p); // ok + extern N::S &r; + f(r); // ok + N::S a[2]; + f(a); // ok + } +} + +// function type: +// associated namespaces and classes of the function parameter types +// and the return type. +namespace adl_function_type { + namespace M { struct T; } + namespace N { + struct S {}; + void f(S (*)(M::T)); + }; + namespace M { + struct T {}; + void g(N::S (*)(T)); + } + + void test() { + extern N::S x(M::T); + f(x); // ok + g(x); // ok + } +} + +// pointer to member function: +// associated namespaces and classes of the class, parameter types +// and return type. +namespace adl_pointer_to_member_function { + namespace M { struct C; } + namespace L { struct T; } + namespace N { + struct S {}; + void f(N::S (M::C::*)(L::T)); + } + namespace L { + struct T {}; + void g(N::S (M::C::*)(L::T)); + } + namespace M { + struct C {}; + void h(N::S (M::C::*)(L::T)); + } + + void test() { + N::S (M::C::*p)(L::T); + f(p); // ok + g(p); // ok + h(p); // ok + } +} + +// pointer to member: +// associated namespaces and classes of the class and of the member type. +namespace adl_pointer_to_member { + namespace M { struct C; } + namespace N { + struct S {}; + void f(N::S (M::C::*)); + } + namespace M { + struct C {}; + void g(N::S (M::C::*)); + } + + void test() { + N::S (M::C::*p); + f(p); // ok + g(p); // ok + } +} + +// [...] if the argument is the name or address of a set of overloaded +// functions and/or function templates, its associated classes and namespaces +// are the union of those associated with each of the members of the set, +// i.e., the classes and namespaces associated with its parameter types and +// return type. +// +// Additionally, if the aforementioned set of overloaded functions is named +// with a template-id, its associated classes and namespaces also include +// those of its type template-arguments and its template template-arguments. +// +// CWG 33 for the union rule. CWG 997 for the template-id rule. +namespace adl_overload_set { + namespace N { + struct S {}; + constexpr int f(int (*g)()) { return g(); } + // expected-note@-1 2{{'N::f' declared here}} + template <typename T> struct Q; + } + + constexpr int g1() { return 1; } + constexpr int g1(N::S) { return 2; } + + template <typename T> constexpr int g2() { return 3; } + + // Inspired from CWG 997. + constexpr int g3() { return 4; } + template <typename T> constexpr int g3(T, N::Q<T>) { return 5; } + + void test() { + static_assert(f(g1) == 1, ""); // Well-formed from the union rule above + static_assert(f(g2<N::S>) == 3, ""); // FIXME: Well-formed from the template-id rule above. + // expected-error@-1 {{use of undeclared}} + + // A objection was raised during review against implementing the + // template-id rule. Currently only GCC implements it. Implementing + // it would weaken the argument to remove it in the future since + // actual real code might start to depend on it. + + static_assert(f(g3) == 4, ""); // FIXME: Also well-formed from the union rule. + // expected-error@-1 {{use of undeclared}} + } +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-inline-namespace.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-inline-namespace.cpp new file mode 100644 index 0000000000..19054f6415 --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-inline-namespace.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// C++11 [basic.lookup.argdep]p2 +// +// [...] If an associated namespace is an inline namespace (10.3.1), its +// enclosing namespace is also included in the set. If an associated +// namespace directly contains inline namespaces, those inline namespaces +// are also included in the set. + +namespace test1 { + namespace L { + namespace M { + inline namespace N { + inline namespace O { + struct S {}; + void f1(S); + } + void f2(S); + } + void f3(S); + } + void f4(M::S); // expected-note {{declared here}} + } + + void test() { + L::M::S s; + f1(s); // ok + f2(s); // ok + f3(s); // ok + f4(s); // expected-error {{use of undeclared}} + } +} + +namespace test2 { + namespace L { + struct S {}; + inline namespace M { + inline namespace N { + inline namespace O { + void f1(S); + } + void f2(S); + } + void f3(S); + } + void f4(S); + } + + void test() { + L::S s; + f1(s); // ok + f2(s); // ok + f3(s); // ok + f4(s); // ok + } +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp index e352bbe83c..b19c81f2f3 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp @@ -132,3 +132,19 @@ namespace test8 { test8_function(ref); } } + + + +// [...] Typedef names and using-declarations used to specify the types +// do not contribute to this set. +namespace typedef_names_and_using_declarations { + namespace N { struct S {}; void f(S); } + namespace M { typedef N::S S; void g1(S); } // expected-note {{declared here}} + namespace L { using N::S; void g2(S); } // expected-note {{declared here}} + void test() { + M::S s; + f(s); // ok + g1(s); // expected-error {{use of undeclared}} + g2(s); // expected-error {{use of undeclared}} + } +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp index c4c2c8d605..88e06fc9ae 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp @@ -18,3 +18,67 @@ namespace test0 { } }; } + +// If X contains [...] then Y is empty. +// - a declaration of a class member +namespace test_adl_suppression_by_class_member { + namespace N { + struct T {}; + void f(T); // expected-note {{declared here}} + } + struct S { + void f(); + void test() { + N::T t; + f(t); // expected-error {{too many arguments}} + } + }; +} + +// - a block-scope function declaration that is not a using-declaration +namespace test_adl_suppression_by_block_scope { + namespace N { + struct S {}; + void f(S); + } + namespace M { void f(int); } // expected-note 2{{candidate}} + void test1() { + N::S s; + using M::f; + f(s); // ok + } + + void test2() { + N::S s; + extern void f(char); // expected-note {{passing argument to parameter here}} + f(s); // expected-error {{no viable conversion from 'N::S' to 'char'}} + } + + void test3() { + N::S s; + extern void f(char); // expected-note {{candidate}} + using M::f; + f(s); // expected-error {{no matching function}} + } + + void test4() { + N::S s; + using M::f; + extern void f(char); // expected-note {{candidate}} + f(s); // expected-error {{no matching function}} + } + +} + +// - a declaration that is neither a function nor a function template +namespace test_adl_suppression_by_non_function { + namespace N { + struct S {}; + void f(S); + } + void test() { + extern void (*f)(); + N::S s; + f(s); // expected-error {{too many arguments}} + } +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp index 2292fc540c..910eb0c1a8 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp @@ -67,3 +67,96 @@ namespace test1 { foo(a, 10); // expected-error {{no matching function for call to 'foo'}} } } + + +// Check the rules described in p4: +// When considering an associated namespace, the lookup is the same as the lookup +// performed when the associated namespace is used as a qualifier (6.4.3.2) except that: + +// - Any using-directives in the associated namespace are ignored. +namespace test_using_directives { + namespace M { struct S; } + namespace N { + void f(M::S); // expected-note {{declared here}} + } + namespace M { + using namespace N; + struct S {}; + } + void test() { + M::S s; + f(s); // expected-error {{use of undeclared}} + M::f(s); // ok + } +} + +// - Any namespace-scope friend functions or friend function templates declared in +// associated classes are visible within their respective namespaces even if +// they are not visible during an ordinary lookup +// (Note: For the friend declaration to be visible, the corresponding class must be +// included in the set of associated classes. Merely including the namespace in +// the set of associated namespaces is not enough.) +namespace test_friend1 { + namespace N { + struct S; + struct T { + friend void f(S); // #1 + }; + struct S { S(); S(T); }; + } + + void test() { + N::S s; + N::T t; + f(s); // expected-error {{use of undeclared}} + f(t); // ok, #1 + } +} + +// credit: Arthur O’Dwyer +namespace test_friend2 { + struct A { + struct B { + struct C {}; + }; + friend void foo(...); // #1 + }; + + struct D { + friend void foo(...); // #2 + }; + template<class> struct E { + struct F {}; + }; + + template<class> struct G {}; + template<class> struct H {}; + template<class> struct I {}; + struct J { friend void foo(...) {} }; // #3 + + void test() { + A::B::C c; + foo(c); // #1 is not visible since A is not an associated class + // expected-error@-1 {{use of undeclared}} + E<D>::F f; + foo(f); // #2 is not visible since D is not an associated class + // expected-error@-1 {{use of undeclared}} + G<H<I<J> > > j; + foo(j); // ok, #3. + } +} + +// - All names except those of (possibly overloaded) functions and +// function templates are ignored. +namespace test_other_names { + namespace N { + struct S {}; + struct Callable { void operator()(S); }; + static struct Callable Callable; + } + + void test() { + N::S s; + Callable(s); // expected-error {{use of undeclared}} + } +} diff --git a/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp b/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp new file mode 100644 index 0000000000..55c5ce6c4c --- /dev/null +++ b/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp @@ -0,0 +1,86 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: echo '#ifndef FOO_H' > %t/foo.h +// RUN: echo '#define FOO_H' >> %t/foo.h +// RUN: echo 'extern int in_header;' >> %t/foo.h +// RUN: echo '#endif' >> %t/foo.h +// RUN: %clang_cc1 -std=c++2a -I%t -emit-module-interface -DINTERFACE %s -o %t.pcm +// RUN: %clang_cc1 -std=c++2a -I%t -fmodule-file=%t.pcm -DIMPLEMENTATION %s -verify -fno-modules-error-recovery +// RUN: %clang_cc1 -std=c++2a -I%t -fmodule-file=%t.pcm %s -verify -fno-modules-error-recovery + +#ifdef INTERFACE +module; +#include "foo.h" +int global_module_fragment; +export module A; +export int exported; +int not_exported; +static int internal; + +module :private; +int not_exported_private; +static int internal_private; +#else + +#ifdef IMPLEMENTATION +module; +#endif + +void test_early() { + in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}} + // expected-note@*{{previous}} + + global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}} + + exported = 1; // expected-error {{must be imported from module 'A'}} + // expected-note@p2.cpp:16 {{previous}} + + not_exported = 1; // expected-error {{undeclared identifier}} + + internal = 1; // expected-error {{undeclared identifier}} + + not_exported_private = 1; // expected-error {{undeclared identifier}} + + internal_private = 1; // expected-error {{undeclared identifier}} +} + +#ifdef IMPLEMENTATION +module A; +#else +import A; +#endif + +void test_late() { + in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}} + // expected-note@*{{previous}} + + global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}} + + exported = 1; + + not_exported = 1; +#ifndef IMPLEMENTATION + // expected-error@-2 {{undeclared identifier 'not_exported'; did you mean 'exported'}} + // expected-note@p2.cpp:16 {{declared here}} +#endif + + internal = 1; +#ifndef IMPLEMENTATION + // FIXME: should not be visible here + // expected-error@-3 {{undeclared identifier}} +#endif + + not_exported_private = 1; +#ifndef IMPLEMENTATION + // FIXME: should not be visible here + // expected-error@-3 {{undeclared identifier}} +#endif + + internal_private = 1; +#ifndef IMPLEMENTATION + // FIXME: should not be visible here + // expected-error@-3 {{undeclared identifier}} +#endif +} + +#endif diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index 6d452d8199..a2d0da1a83 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -514,16 +514,12 @@ namespace test17 { } namespace test18 { - template <class T> class A {}; - class B : A<int> { + template <class T> class A {}; // expected-note {{member is declared here}} + class B : A<int> { // expected-note {{constrained by implicitly private inheritance here}} A<int> member; }; - - // FIXME: this access to A should be forbidden (because C++ is dumb), - // but LookupResult can't express the necessary information to do - // the check, so we aggressively suppress access control. class C : B { - A<int> member; + A<int> member; // expected-error {{'A' is a private member of 'test18::A<int>'}} }; } diff --git a/test/CXX/class/class.union/class.union.anon/p4.cpp b/test/CXX/class/class.union/class.union.anon/p4.cpp index cc54ba4066..a12ec38503 100644 --- a/test/CXX/class/class.union/class.union.anon/p4.cpp +++ b/test/CXX/class/class.union/class.union.anon/p4.cpp @@ -2,7 +2,7 @@ union U { int x = 0; // expected-note {{previous initialization is here}} - union {}; + union {}; // expected-warning {{does not declare anything}} union { int z; int y = 1; // expected-error {{initializing multiple members of union}} diff --git a/test/CXX/cpp/cpp.module/Inputs/attrs.h b/test/CXX/cpp/cpp.module/Inputs/attrs.h new file mode 100644 index 0000000000..bc6b78b056 --- /dev/null +++ b/test/CXX/cpp/cpp.module/Inputs/attrs.h @@ -0,0 +1 @@ +#define ATTRS [[ ]] diff --git a/test/CXX/cpp/cpp.module/Inputs/empty.h b/test/CXX/cpp/cpp.module/Inputs/empty.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/CXX/cpp/cpp.module/Inputs/empty.h diff --git a/test/CXX/cpp/cpp.module/p1.cpp b/test/CXX/cpp/cpp.module/p1.cpp new file mode 100644 index 0000000000..d56375e1fc --- /dev/null +++ b/test/CXX/cpp/cpp.module/p1.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++2a -emit-header-module -fmodule-name=attrs -x c++-header %S/Inputs/empty.h %S/Inputs/attrs.h -o %t.pcm +// RUN: %clang_cc1 -std=c++2a %s -fmodule-file=%t.pcm -E -verify -I%S/Inputs | FileCheck %s + +#define SEMI ; +// expected-error@+1 {{semicolon terminating header import declaration cannot be produced by a macro}} +import "empty.h" SEMI // CHECK: import attrs.{{.*}}; + +#define IMPORT import "empty.h" +IMPORT; // CHECK: import attrs.{{.*}}; + +#define IMPORT_ANGLED import <empty.h> +IMPORT_ANGLED; // CHECK: import attrs.{{.*}}; + +// Ensure that macros only become visible at the semicolon. +// CHECK: import attrs.{{.*}} ATTRS ; +import "attrs.h" ATTRS ; +// CHECK: {{\[\[}} ]] int n; +ATTRS int n; diff --git a/test/CXX/cpp/cpp.module/p2.cpp b/test/CXX/cpp/cpp.module/p2.cpp new file mode 100644 index 0000000000..d5bf4fa1a6 --- /dev/null +++ b/test/CXX/cpp/cpp.module/p2.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++2a -emit-header-module -fmodule-name=attrs -x c++-header %S/Inputs/empty.h %S/Inputs/attrs.h -o %t.pcm +// RUN: %clang_cc1 -std=c++2a %s -fmodule-file=%t.pcm -fsyntax-only -verify -I%S/Inputs + +template<int> struct import; // expected-note 2{{previous}} +constexpr struct { int h; } empty = {0}; +struct A; +struct B; +struct C; +template<> struct import<0> { + static A a; + static B b; + static C c; +}; + +// OK, not an import-declaration. +struct A {} +::import +<empty.h>::a; + +// This is invalid: the tokens after 'import' are a header-name, so cannot be +// parsed as a template-argument-list. +struct B {} +import // expected-error {{redefinition of 'import'}} expected-error {{expected ';'}} +<empty.h>::b; // (error recovery skips these tokens) + +// Likewise, this is ill-formed after the tokens are reconstituted into a +// header-name token. +struct C {} +import // expected-error {{redefinition of 'import'}} expected-error {{expected ';'}} +< +empty.h // (error recovery skips these tokens) +>::c; diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp index 686aac2802..e435bee2c8 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -verify %s +// RUN: %clang_cc1 -std=c++11 -verify %s -triple x86_64-linux-gnu alignas(double) void f(); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} alignas(double) unsigned char c[sizeof(double)]; // expected-note {{previous}} diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p3.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p3.cpp index 551df38a81..5f715a1ec2 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.unused/p3.cpp @@ -5,9 +5,17 @@ static_assert(__has_cpp_attribute(maybe_unused) == 201603, ""); struct [[maybe_unused]] S {}; +enum E1 { + EnumVal [[maybe_unused]], + UsedEnumVal, +}; + void f() { int x; // expected-warning {{unused variable}} typedef int I; // expected-warning {{unused typedef 'I'}} + E1 e; + switch (e) { // expected-warning {{enumeration value 'UsedEnumVal' not handled in switch}} + } // Should not warn about these due to not being used. [[maybe_unused]] int y; @@ -17,10 +25,16 @@ void f() { S s; maybe_unused_int test; y = 12; + switch (e) { + case UsedEnumVal: + break; + } } #ifdef EXT // expected-warning@6 {{use of the 'maybe_unused' attribute is a C++17 extension}} -// expected-warning@13 {{use of the 'maybe_unused' attribute is a C++17 extension}} -// expected-warning@14 {{use of the 'maybe_unused' attribute is a C++17 extension}} +// expected-warning@9 {{use of the 'maybe_unused' attribute is a C++17 extension}} +// expected-warning@9 {{attributes on an enumerator declaration are a C++17 extension}} +// expected-warning@21 {{use of the 'maybe_unused' attribute is a C++17 extension}} +// expected-warning@22 {{use of the 'maybe_unused' attribute is a C++17 extension}} #endif diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index 54aabe6ef3..e24e63178e 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -181,8 +181,8 @@ union Empty { } constexpr empty1; struct EmptyVariant { - union {}; - struct {}; + union {}; // expected-warning {{does not declare anything}} + struct {}; // expected-warning {{does not declare anything}} constexpr EmptyVariant() {} // ok } constexpr empty2; diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp index c2f3b5a045..2b7886d383 100644 --- a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp +++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -56,8 +56,8 @@ constexpr S5::S5() = default; static_assert(S5().m == 4, ""); -// An explicitly-defaulted function may have an exception specification only if -// it is compatible with the exception specification on an implicit declaration. +// An explicitly-defaulted function may have a different exception specification +// from the exception specification on an implicit declaration. struct E1 { E1() noexcept = default; E1(const E1&) noexcept = default; @@ -67,13 +67,24 @@ struct E1 { ~E1() noexcept = default; }; struct E2 { - E2() noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} - E2(const E2&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted copy constructor does not match the calculated one}} - E2(E2&&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted move constructor does not match the calculated one}} - E2 &operator=(const E2&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted copy assignment operator does not match the calculated one}} - E2 &operator=(E2&&) noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted move assignment operator does not match the calculated one}} - ~E2() noexcept(false) = default; // expected-error {{exception specification of explicitly defaulted destructor does not match the calculated one}} + E2() noexcept(false) = default; + E2(const E2&) noexcept(false) = default; + E2(E2&&) noexcept(false) = default; + E2 &operator=(const E2&) noexcept(false) = default; + E2 &operator=(E2&&) noexcept(false) = default; + ~E2() noexcept(false) = default; }; +E2 e2; +E2 make_e2() noexcept; +void take_e2(E2&&) noexcept; +static_assert(!noexcept(E2()), ""); +static_assert(!noexcept(E2(e2)), ""); +static_assert(!noexcept(E2(static_cast<E2&&>(e2))), ""); +static_assert(!noexcept(e2 = e2), ""); +static_assert(!noexcept(e2 = static_cast<E2&&>(e2)), ""); +// FIXME: This expression results in destruction of an E2 temporary; the +// noexcept expression should evaluate to false. +static_assert(noexcept(take_e2(make_e2())), ""); // If a function is explicitly defaulted on its first declaration // -- it is implicitly considered to have the same exception-specification as diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index 048187814d..53bd6f3f05 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -413,6 +413,36 @@ namespace dr33 { // dr33: yes void g(X::S); template<typename Z> Z g(Y::T); void h() { f(&g); } // expected-error {{ambiguous}} + + template<typename T> void t(X::S); + template<typename T, typename U = void> void u(X::S); // expected-error 0-1{{default template argument}} + void templ() { f(t<int>); f(u<int>); } + + // Even though v<int> cannot select the first overload, ADL considers it + // and adds namespace Z to the set of associated namespaces, and then picks + // Z::f even though that function has nothing to do with any associated type. + namespace Z { struct Q; void f(void(*)()); } + template<int> Z::Q v(); + template<typename> void v(); + void unrelated_templ() { f(v<int>); } + + namespace dependent { + struct X {}; + template<class T> struct Y { + friend int operator+(X, void(*)(Y)) {} + }; + + template<typename T> void f(Y<T>); + int use = X() + f<int>; // expected-error {{invalid operands}} + } + + namespace member { + struct Q {}; + struct Y { friend int operator+(Q, Y (*)()); }; + struct X { template<typename> static Y f(); }; + int m = Q() + X().f<int>; // ok + int n = Q() + (&(X().f<int>)); // ok + } } // dr34: na @@ -839,18 +869,17 @@ namespace dr68 { // dr68: yes } namespace dr69 { // dr69: yes - template<typename T> static void f() {} + template<typename T> static void f() {} // #dr69-f // FIXME: Should we warn here? inline void g() { f<int>(); } - // FIXME: This should be rejected, per [temp.explicit]p11. - extern template void f<char>(); + extern template void f<char>(); // expected-error {{explicit instantiation declaration of 'f' with internal linkage}} #if __cplusplus < 201103L // expected-error@-2 {{C++11 extension}} #endif template<void(*)()> struct Q {}; Q<&f<int> > q; #if __cplusplus < 201103L - // expected-error@-2 {{internal linkage}} expected-note@-11 {{here}} + // expected-error@-2 {{internal linkage}} expected-note@#dr69-f {{here}} #endif } diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp index 208ab8a03b..1d61e8687e 100644 --- a/test/CXX/drs/dr13xx.cpp +++ b/test/CXX/drs/dr13xx.cpp @@ -272,7 +272,7 @@ namespace dr1359 { // dr1359: 3.5 union A { constexpr A() = default; }; union B { constexpr B() = default; int a; }; // expected-error {{not constexpr}} expected-note 2{{candidate}} union C { constexpr C() = default; int a, b; }; // expected-error {{not constexpr}} expected-note 2{{candidate}} - struct X { constexpr X() = default; union {}; }; + struct X { constexpr X() = default; union {}; }; // expected-error {{does not declare anything}} struct Y { constexpr Y() = default; union { int a; }; }; // expected-error {{not constexpr}} expected-note 2{{candidate}} constexpr A a = A(); diff --git a/test/CXX/drs/dr14xx.cpp b/test/CXX/drs/dr14xx.cpp index eb5ba3db44..eb086178fc 100644 --- a/test/CXX/drs/dr14xx.cpp +++ b/test/CXX/drs/dr14xx.cpp @@ -13,22 +13,22 @@ namespace dr1460 { // dr1460: 3.5 #if __cplusplus >= 201103L namespace DRExample { union A { - union {}; - union {}; + union {}; // expected-error {{does not declare anything}} + union {}; // expected-error {{does not declare anything}} constexpr A() {} }; constexpr A a = A(); union B { - union {}; - union {}; + union {}; // expected-error {{does not declare anything}} + union {}; // expected-error {{does not declare anything}} constexpr B() = default; }; constexpr B b = B(); union C { - union {}; - union {}; + union {}; // expected-error {{does not declare anything}} + union {}; // expected-error {{does not declare anything}} }; constexpr C c = C(); #if __cplusplus > 201103L @@ -40,7 +40,7 @@ namespace dr1460 { // dr1460: 3.5 union A {}; union B { int n; }; // expected-note +{{here}} union C { int n = 0; }; - struct D { union {}; }; + struct D { union {}; }; // expected-error {{does not declare anything}} struct E { union { int n; }; }; // expected-note +{{here}} struct F { union { int n = 0; }; }; @@ -66,7 +66,7 @@ namespace dr1460 { // dr1460: 3.5 union A { constexpr A() = default; }; union B { int n; constexpr B() = default; }; // expected-error {{not constexpr}} union C { int n = 0; constexpr C() = default; }; - struct D { union {}; constexpr D() = default; }; + struct D { union {}; constexpr D() = default; }; // expected-error {{does not declare anything}} struct E { union { int n; }; constexpr E() = default; }; // expected-error {{not constexpr}} struct F { union { int n = 0; }; constexpr F() = default; }; diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp index cca4509fa0..bd714865ee 100644 --- a/test/CXX/drs/dr15xx.cpp +++ b/test/CXX/drs/dr15xx.cpp @@ -236,6 +236,16 @@ namespace dr1560 { // dr1560: 3.5 const X &x = true ? get() : throw 0; } +namespace dr1563 { // dr1563: yes +#if __cplusplus >= 201103L + double bar(double) { return 0.0; } + float bar(float) { return 0.0f; } + + using fun = double(double); + fun &foo{bar}; // ok +#endif +} + namespace dr1573 { // dr1573: 3.9 #if __cplusplus >= 201103L // ellipsis is inherited (p0136r1 supersedes this part). diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index 4f2f06e0d0..b5047e8fe2 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -284,6 +284,54 @@ namespace dr1687 { // dr1687: 7 #endif } +namespace dr1690 { // dr1690: 9 + // See also the various tests in "CXX/basic/basic.lookup/basic.lookup.argdep". +#if __cplusplus >= 201103L + namespace N { + static auto lambda = []() { struct S {} s; return s; }; + void f(decltype(lambda())); + } + + void test() { + auto s = N::lambda(); + f(s); // ok + } +#endif +} + +namespace dr1691 { // dr1691: 9 +#if __cplusplus >= 201103L + namespace N { + namespace M { + enum E : int; + void f(E); + } + enum M::E : int {}; + void g(M::E); // expected-note {{declared here}} + } + void test() { + N::M::E e; + f(e); // ok + g(e); // expected-error {{use of undeclared}} + } +#endif +} + +namespace dr1692 { // dr1692: 9 + namespace N { + struct A { + struct B { + struct C {}; + }; + }; + void f(A::B::C); + } + void test() { + N::A::B::C c; + f(c); // ok + } +} + namespace dr1696 { // dr1696: 7 namespace std_examples { #if __cplusplus >= 201402L diff --git a/test/CXX/drs/dr17xx.cpp b/test/CXX/drs/dr17xx.cpp index a917412adc..ca55c42977 100644 --- a/test/CXX/drs/dr17xx.cpp +++ b/test/CXX/drs/dr17xx.cpp @@ -76,3 +76,30 @@ namespace dr1758 { // dr1758: 3.7 A a{b}; #endif } + +namespace dr1722 { // dr1722: 9 +#if __cplusplus >= 201103L +void f() { + const auto lambda = [](int x) { return x + 1; }; + // Without the DR applied, this static_assert would fail. + static_assert( + noexcept((int (*)(int))(lambda)), + "Lambda-to-function-pointer conversion is expected to be noexcept"); +} +#endif +} // namespace dr1722 + +namespace dr1778 { // dr1778: 9 + // Superseded by P1286R2. +#if __cplusplus >= 201103L + struct A { A() noexcept(true) = default; }; + struct B { B() noexcept(false) = default; }; + static_assert(noexcept(A()), ""); + static_assert(!noexcept(B()), ""); + + struct C { A a; C() noexcept(false) = default; }; + struct D { B b; D() noexcept(true) = default; }; + static_assert(!noexcept(C()), ""); + static_assert(noexcept(D()), ""); +#endif +} diff --git a/test/CXX/drs/dr19xx.cpp b/test/CXX/drs/dr19xx.cpp index e6cf337da0..a1e8c76435 100644 --- a/test/CXX/drs/dr19xx.cpp +++ b/test/CXX/drs/dr19xx.cpp @@ -84,6 +84,7 @@ namespace dr1940 { // dr1940: yes static union { static_assert(true, ""); // ok static_assert(false, ""); // expected-error {{static_assert failed}} + int not_empty; }; #endif } diff --git a/test/CXX/drs/dr23xx.cpp b/test/CXX/drs/dr23xx.cpp new file mode 100644 index 0000000000..87db0d4c9b --- /dev/null +++ b/test/CXX/drs/dr23xx.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors + +#if __cplusplus <= 201103L +// expected-no-diagnostics +#endif + +namespace dr2387 { // dr2387: 9 +#if __cplusplus >= 201402L + template<int> int a = 0; + extern template int a<0>; // ok + + template<int> static int b = 0; + extern template int b<0>; // expected-error {{internal linkage}} + + template<int> const int c = 0; + extern template const int c<0>; // ok, has external linkage despite 'const' + + template<typename T> T d = 0; + extern template int d<int>; + extern template const int d<const int>; +#endif +} diff --git a/test/CXX/drs/dr7xx.cpp b/test/CXX/drs/dr7xx.cpp index d02582b5b4..2d9d396018 100644 --- a/test/CXX/drs/dr7xx.cpp +++ b/test/CXX/drs/dr7xx.cpp @@ -1,7 +1,21 @@ // RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors + +namespace dr705 { // dr705: yes + namespace N { + struct S {}; + void f(S); // expected-note {{declared here}} + } + + void g() { + N::S s; + f(s); // ok + (f)(s); // expected-error {{use of undeclared}} + } +} namespace dr727 { // dr727: partial struct A { @@ -53,7 +67,7 @@ namespace dr727 { // dr727: partial struct D { template<typename T> struct C { typename T::error e; }; // expected-error {{no members}} template<typename T> void f() { T::error; } // expected-error {{no members}} - template<typename T> static const int N = T::error; // expected-error 2{{no members}} expected-error 0-1{{C++14}} + template<typename T> static const int N = T::error; // expected-error {{no members}} expected-error 0-1{{C++14}} template<> struct C<int> {}; template<> void f<int>() {} @@ -66,7 +80,7 @@ namespace dr727 { // dr727: partial void d(D<int> di) { D<int>::C<int>(); di.f<int>(); - int a = D<int>::N<int>; // FIXME: expected-note {{instantiation of}} + int a = D<int>::N<int>; D<int>::C<int*>(); int b = D<int>::N<int*>; @@ -75,6 +89,98 @@ namespace dr727 { // dr727: partial di.f<float>(); // expected-note {{instantiation of}} int c = D<int>::N<float>; // expected-note {{instantiation of}} } + + namespace mixed_inner_outer_specialization { +#if __cplusplus >= 201103L + template<int> struct A { + template<int> constexpr int f() const { return 1; } + template<> constexpr int f<0>() const { return 2; } + }; + template<> template<int> constexpr int A<0>::f() const { return 3; } + template<> template<> constexpr int A<0>::f<0>() const { return 4; } + static_assert(A<1>().f<1>() == 1, ""); + static_assert(A<1>().f<0>() == 2, ""); + static_assert(A<0>().f<1>() == 3, ""); + static_assert(A<0>().f<0>() == 4, ""); +#endif + +#if __cplusplus >= 201402L + template<int> struct B { + template<int> static const int u = 1; + template<> static const int u<0> = 2; // expected-note {{here}} + + // Note that in C++17 onwards, these are implicitly inline, and so the + // initializer of v<0> is not instantiated with the declaration. In + // C++14, v<0> is a non-defining declaration and its initializer is + // instantiated with the class. + template<int> static constexpr int v = 1; + template<> static constexpr int v<0> = 2; // #v0 + + template<int> static const inline int w = 1; // expected-error 0-1{{C++17 extension}} + template<> static const inline int w<0> = 2; // expected-error 0-1{{C++17 extension}} + }; + + template<> template<int> constexpr int B<0>::u = 3; + template<> template<> constexpr int B<0>::u<0> = 4; // expected-error {{already has an initializer}} + + template<> template<int> constexpr int B<0>::v = 3; + template<> template<> constexpr int B<0>::v<0> = 4; +#if __cplusplus < 201702L + // expected-error@-2 {{already has an initializer}} + // expected-note@#v0 {{here}} +#endif + + template<> template<int> constexpr int B<0>::w = 3; + template<> template<> constexpr int B<0>::w<0> = 4; + + static_assert(B<1>().u<1> == 1, ""); + static_assert(B<1>().u<0> == 2, ""); + static_assert(B<0>().u<1> == 3, ""); + + static_assert(B<1>().v<1> == 1, ""); + static_assert(B<1>().v<0> == 2, ""); + static_assert(B<0>().v<1> == 3, ""); + static_assert(B<0>().v<0> == 4, ""); +#if __cplusplus < 201702L + // expected-error@-2 {{failed}} +#endif + + static_assert(B<1>().w<1> == 1, ""); + static_assert(B<1>().w<0> == 2, ""); + static_assert(B<0>().w<1> == 3, ""); + static_assert(B<0>().w<0> == 4, ""); +#endif + } + + template<typename T, typename U> struct Collision { + // FIXME: Missing diagnostic for duplicate function explicit specialization declaration. + template<typename> int f1(); + template<> int f1<T>(); + template<> int f1<U>(); + + // FIXME: Missing diagnostic for fucntion redefinition! + template<typename> int f2(); + template<> int f2<T>() {} + template<> int f2<U>() {} + + template<typename> static int v1; // expected-error 0-1{{C++14 extension}} + template<> static int v1<T>; // expected-note {{previous}} + template<> static int v1<U>; // expected-error {{duplicate member}} + + template<typename> static inline int v2; // expected-error 0-1{{C++17 extension}} expected-error 0-1{{C++14 extension}} + template<> static inline int v2<T>; // expected-error 0-1{{C++17 extension}} expected-note {{previous}} + template<> static inline int v2<U>; // expected-error 0-1{{C++17 extension}} expected-error {{duplicate member}} + + // FIXME: Missing diagnostic for duplicate class explicit specialization. + template<typename> struct S1; + template<> struct S1<T>; + template<> struct S1<U>; + + template<typename> struct S2; + template<> struct S2<T> {}; // expected-note {{previous}} + template<> struct S2<U> {}; // expected-error {{redefinition}} + }; + Collision<int, int> c; // expected-note {{in instantiation of}} } namespace dr777 { // dr777: 3.7 diff --git a/test/CXX/except/except.spec/p14.cpp b/test/CXX/except/except.spec/p14.cpp index c717d97797..b1c8b207b4 100644 --- a/test/CXX/except/except.spec/p14.cpp +++ b/test/CXX/except/except.spec/p14.cpp @@ -83,7 +83,12 @@ namespace PR14141 { Derived &operator=(const Derived&) noexcept(false) = default; Derived &operator=(Derived&&) noexcept(false) = default; ~Derived() noexcept(false) = default; - }; + } d1; + static_assert(!noexcept(Derived()), ""); + static_assert(!noexcept(Derived(static_cast<Derived&&>(d1))), ""); + static_assert(!noexcept(Derived(d1)), ""); + static_assert(!noexcept(d1 = static_cast<Derived&&>(d1)), ""); + static_assert(!noexcept(d1 = d1), ""); struct Derived2 : ThrowingBase { Derived2() = default; Derived2(const Derived2&) = default; @@ -91,15 +96,21 @@ namespace PR14141 { Derived2 &operator=(const Derived2&) = default; Derived2 &operator=(Derived2&&) = default; ~Derived2() = default; - }; + } d2; + static_assert(!noexcept(Derived2()), ""); + static_assert(!noexcept(Derived2(static_cast<Derived2&&>(d2))), ""); + static_assert(!noexcept(Derived2(d2)), ""); + static_assert(!noexcept(d2 = static_cast<Derived2&&>(d2)), ""); + static_assert(!noexcept(d2 = d2), ""); struct Derived3 : ThrowingBase { - Derived3() noexcept(true) = default; // expected-error {{does not match the calculated}} - Derived3(const Derived3&) noexcept(true) = default; // expected-error {{does not match the calculated}} - Derived3(Derived3&&) noexcept(true) = default; // expected-error {{does not match the calculated}} - Derived3 &operator=(const Derived3&) noexcept(true) = default; // expected-error {{does not match the calculated}} - Derived3 &operator=(Derived3&&) noexcept(true) = default; // expected-error {{does not match the calculated}} - ~Derived3() noexcept(true) = default; // expected-error {{does not match the calculated}} - }; + Derived3() noexcept(true) = default; + Derived3(const Derived3&) noexcept(true) = default; + Derived3(Derived3&&) noexcept(true) = default; + Derived3 &operator=(const Derived3&) noexcept(true) = default; + Derived3 &operator=(Derived3&&) noexcept(true) = default; + ~Derived3() noexcept(true) = default; + } d3; + static_assert(noexcept(Derived3(), Derived3(Derived3()), Derived3(d3), d3 = Derived3(), d3 = d3), ""); } namespace rdar13017229 { diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p9.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p9.cpp new file mode 100644 index 0000000000..2d3c69fc38 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p9.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++17 %s -verify +// expected-no-diagnostics + +void test_noexcept() { + const auto lambda = [](int x) { return x + 1; }; + static_assert(noexcept((int (*)(int))(lambda)), + "Lambda-to-function-pointer conversion is expected to be noexcept"); +} diff --git a/test/CXX/lex/lex.pptoken/Inputs/foo bar b/test/CXX/lex/lex.pptoken/Inputs/foo bar new file mode 100644 index 0000000000..9fb8e2fb61 --- /dev/null +++ b/test/CXX/lex/lex.pptoken/Inputs/foo bar @@ -0,0 +1 @@ +#error ERROR: This file should never actually be included diff --git a/test/CXX/lex/lex.pptoken/Inputs/foo bar b/test/CXX/lex/lex.pptoken/Inputs/foo bar new file mode 100644 index 0000000000..9fb8e2fb61 --- /dev/null +++ b/test/CXX/lex/lex.pptoken/Inputs/foo bar @@ -0,0 +1 @@ +#error ERROR: This file should never actually be included diff --git a/test/CXX/lex/lex.pptoken/p3-2a.cpp b/test/CXX/lex/lex.pptoken/p3-2a.cpp new file mode 100644 index 0000000000..0e0e5fec6e --- /dev/null +++ b/test/CXX/lex/lex.pptoken/p3-2a.cpp @@ -0,0 +1,81 @@ +// RUN: not %clang_cc1 -std=c++2a -E -I%S/Inputs %s -o - | FileCheck %s --strict-whitespace --implicit-check-not=ERROR + +// Check for context-sensitive header-name token formation. +// CHECK: import <foo bar>; +import <foo bar>; + +// Not at the top level: these are each 8 tokens rather than 5. +// CHECK: { import <foo bar>; } +{ import <foo bar>; } +// CHECK: ( import <foo bar>; :> +( import <foo bar>; :> +// CHECK: [ import <foo bar>; %> +[ import <foo bar>; %> + +// CHECK: import <foo bar>; +import <foo bar>; + +// CHECK: foo; import <foo bar>; +foo; import <foo bar>; + +// CHECK: foo import <foo bar>; +foo import <foo bar>; + +// CHECK: import <foo bar> {{\[\[ ]]}}; +import <foo bar> [[ ]]; + +// CHECK: import <foo bar> import <foo bar>; +import <foo bar> import <foo bar>; + +// FIXME: We do not form header-name tokens in the pp-import-suffix of a +// pp-import. Conforming programs can't tell the difference. +// CHECK: import <foo bar> {} import <foo bar>; +// FIXME: import <foo bar> {} import <foo bar>; +import <foo bar> {} import <foo bar>; + + +// CHECK: export import <foo bar>; +export import <foo bar>; + +// CHECK: export export import <foo bar>; +export export import <foo bar>; + +#define UNBALANCED_PAREN ( +// CHECK: import <foo bar>; +import <foo bar>; + +UNBALANCED_PAREN +// CHECK: import <foo bar>; +import <foo bar>; +) + +_Pragma("clang no_such_pragma ("); +// CHECK: import <foo bar>; +import <foo bar>; + +#define HEADER <foo bar> +// CHECK: import <foo bar>; +import HEADER; + +// CHECK: import <foo bar>; +import < +foo + bar +>; + +// CHECK: import{{$}} +// CHECK: {{^}}<foo bar>; +import +< +foo + bar +>; + +// CHECK: import{{$}} +// CHECK: {{^}}<foo bar>; +import +<foo bar>; + +#define IMPORT import <foo bar> +// CHECK: import <foo bar>; +IMPORT; diff --git a/test/CXX/module/module.interface/Inputs/header.h b/test/CXX/module/module.interface/Inputs/header.h new file mode 100644 index 0000000000..f2e2cbb53c --- /dev/null +++ b/test/CXX/module/module.interface/Inputs/header.h @@ -0,0 +1,3 @@ +extern int foo; +namespace bar { extern int baz(); } +static int baz; diff --git a/test/CXX/module/module.interface/p1.cpp b/test/CXX/module/module.interface/p1.cpp new file mode 100644 index 0000000000..0947b81915 --- /dev/null +++ b/test/CXX/module/module.interface/p1.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++2a %s -DERRORS -verify +// RUN: %clang_cc1 -std=c++2a %s -emit-module-interface -o %t.pcm +// RUN: %clang_cc1 -std=c++2a %s -fmodule-file=%t.pcm -DIMPLEMENTATION -verify -Db=b2 -Dc=c2 + +module; + +#ifdef ERRORS +export int a; // expected-error {{after the module declaration}} +#endif + +#ifndef IMPLEMENTATION +export +#else +// expected-error@#1 {{can only be used within a module interface unit}} +// expected-error@#2 {{can only be used within a module interface unit}} +// expected-note@+2 1+{{add 'export'}} +#endif +module M; + +export int b; // #1 +namespace N { + export int c; // #2 +} + +#ifdef ERRORS +namespace { // expected-note 2{{anonymous namespace begins here}} + export int d1; // expected-error {{export declaration appears within anonymous namespace}} + namespace X { + export int d2; // expected-error {{export declaration appears within anonymous namespace}} + } +} + +export export int e; // expected-error {{within another export declaration}} +export { export int f; } // expected-error {{within another export declaration}} expected-note {{export block begins here}} + +module :private; // expected-note {{private module fragment begins here}} +export int priv; // expected-error {{export declaration cannot be used in a private module fragment}} +#endif diff --git a/test/CXX/module/module.interface/p2.cpp b/test/CXX/module/module.interface/p2.cpp new file mode 100644 index 0000000000..0a6f8c2aad --- /dev/null +++ b/test/CXX/module/module.interface/p2.cpp @@ -0,0 +1,94 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: %clang_cc1 -std=c++2a -x c++-header %S/Inputs/header.h -emit-header-module -fmodule-name=FIXME -o %t/h.pcm +// RUN: %clang_cc1 -std=c++2a %s -DX_INTERFACE -emit-module-interface -o %t/x.pcm +// RUN: %clang_cc1 -std=c++2a %s -DY_INTERFACE -emit-module-interface -o %t/y.pcm +// RUN: %clang_cc1 -std=c++2a %s -DINTERFACE -fmodule-file=%t/x.pcm -fmodule-file=%t/y.pcm -emit-module-interface -o %t/m.pcm +// RUN: %clang_cc1 -std=c++2a %s -DIMPLEMENTATION -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify +// RUN: %clang_cc1 -std=c++2a %s -DUSER -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify + +#if defined(X_INTERFACE) +export module X; +export int x; + +#elif defined(Y_INTERFACE) +export module Y; +export int y; + +#elif defined(INTERFACE) +export module p2; +export import X; +import Y; // not exported + +namespace A { + int f(); + export int g(); + int h(); + namespace inner {} +} +export namespace B { + namespace inner {} +} +namespace B { + int f(); +} +namespace C {} +namespace D { int f(); } +export namespace D {} + +#elif defined(IMPLEMENTATION) +module p2; +import "header.h"; + +// Per [basic.scope.namespace]/2.3, exportedness has no impact on visibility +// within the same module. +// +// expected-no-diagnostics + +void use() { + A::f(); + A::g(); + A::h(); + using namespace A::inner; + + using namespace B; + using namespace B::inner; + B::f(); + f(); + + using namespace C; + + D::f(); +} + +int use_header() { return foo + bar::baz(); } + +#elif defined(USER) +import p2; +import "header.h"; + +void use() { + // namespace A is implicitly exported by the export of A::g. + A::f(); // expected-error {{no member named 'f' in namespace 'A'}} + A::g(); + A::h(); // expected-error {{no member named 'h' in namespace 'A'}} + using namespace A::inner; // expected-error {{expected namespace name}} + + // namespace B and B::inner are explicitly exported + using namespace B; + using namespace B::inner; + B::f(); // expected-error {{no member named 'f' in namespace 'B'}} + f(); // expected-error {{undeclared identifier 'f'}} + + // namespace C is not exported + using namespace C; // expected-error {{expected namespace name}} + + // namespace D is exported, but D::f is not + D::f(); // expected-error {{no member named 'f' in namespace 'D'}} +} + +int use_header() { return foo + bar::baz(); } + +#else +#error unknown mode +#endif diff --git a/test/CXX/module/module.interface/p3.cpp b/test/CXX/module/module.interface/p3.cpp new file mode 100644 index 0000000000..29d2cb43b4 --- /dev/null +++ b/test/CXX/module/module.interface/p3.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -std=c++2a %s -verify -pedantic-errors + +export module p3; + +namespace A { int ns_mem; } + +// An exported declaration shall declare at least one name. +export; // expected-error {{empty declaration cannot be exported}} +export static_assert(true); // expected-error {{static_assert declaration cannot be exported}} +export using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}} + +export { // expected-note 3{{export block begins here}} + ; // expected-error {{ISO C++20 does not permit an empty declaration to appear in an export block}} + static_assert(true); // expected-error {{ISO C++20 does not permit a static_assert declaration to appear in an export block}} + using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}} +} + +export struct {}; // expected-error {{must be class member}} expected-error {{GNU extension}} expected-error {{does not declare anything}} +export struct {} struct_; +export union {}; // expected-error {{must be declared 'static'}} expected-error {{does not declare anything}} +export union {} union_; +export enum {}; // expected-error {{does not declare anything}} +export enum {} enum_; +export enum E : int; +export typedef int; // expected-error {{typedef requires a name}} +export static union {}; // expected-error {{does not declare anything}} +export asm(""); // expected-error {{asm declaration cannot be exported}} +export namespace B = A; +export using A::ns_mem; +namespace A { + export using A::ns_mem; +} +export using Int = int; +export extern "C++" {} // expected-error {{ISO C++20 does not permit a declaration that does not introduce any names to be exported}} +export extern "C++" { extern "C" {} } // expected-error {{ISO C++20 does not permit a declaration that does not introduce any names to be exported}} +export extern "C++" { extern "C" int extern_c; } +export { // expected-note {{export block}} + extern "C++" int extern_cxx; + extern "C++" {} // expected-error {{ISO C++20 does not permit a declaration that does not introduce any names to be exported}} +} +export [[]]; // FIXME (bad diagnostic text): expected-error {{empty declaration cannot be exported}} +export [[example::attr]]; // FIXME: expected-error {{empty declaration cannot be exported}} expected-warning {{unknown attribute 'attr'}} + +// [...] shall not declare a name with internal linkage +export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}} +export static int b(); // expected-error {{declaration of 'b' with internal linkage cannot be exported}} +export namespace { int c; } // expected-error {{declaration of 'c' with internal linkage cannot be exported}} +namespace { // expected-note {{here}} + export int d; // expected-error {{export declaration appears within anonymous namespace}} +} +export template<typename> static int e; // expected-error {{declaration of 'e' with internal linkage cannot be exported}} +export template<typename> static int f(); // expected-error {{declaration of 'f' with internal linkage cannot be exported}} +export const int k = 5; +export static union { int n; }; // expected-error {{declaration of 'n' with internal linkage cannot be exported}} diff --git a/test/CXX/module/module.interface/p5.cpp b/test/CXX/module/module.interface/p5.cpp new file mode 100644 index 0000000000..17c4105baa --- /dev/null +++ b/test/CXX/module/module.interface/p5.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++2a %s -verify -pedantic-errors + +export module p5; + +int a; +static int sa; // expected-note {{target}} +void b(); +static void sb(); // expected-note {{target}} +struct c {}; +enum d {}; +using e = int; +using f = c; +static union { int sg1, sg2; }; // expected-note {{target}} +namespace NS {} + +template<typename> int ta; +template<typename> static int sta; // expected-note {{target}} +template<typename> void tb(); +template<typename> static void stb(); // expected-note {{target}} +template<typename> struct tc {}; +template<typename> using te = int; +template<typename> using tf = c; + +namespace UnnamedNS { + namespace { + int a; // expected-note {{target}} + static int sa; // expected-note {{target}} + void b(); // expected-note {{target}} + static void sb(); // expected-note {{target}} + struct c {}; // expected-note {{target}} + enum d {}; // expected-note {{target}} + using e = int; + using f = c; + static union { int sg1, sg2; }; // expected-note {{target}} + namespace NS {} + + template<typename> int ta; // expected-note {{target}} + template<typename> static int sta; // expected-note {{target}} + template<typename> void tb(); // expected-note {{target}} + template<typename> static void stb(); // expected-note {{target}} + template<typename> struct tc {}; // expected-note {{target}} + template<typename> using te = int; // expected-note {{target}} + template<typename> using tf = c; // expected-note {{target}} + } +} + +export { // expected-note 19{{here}} + using ::a; + using ::sa; // expected-error {{using declaration referring to 'sa' with internal linkage}} + using ::b; + using ::sb; // expected-error {{using declaration referring to 'sb' with internal linkage}} + using ::c; + using ::d; + using ::e; + using ::f; + using ::sg1; // expected-error {{using declaration referring to 'sg1' with internal linkage}} + + using ::ta; + using ::sta; // expected-error {{using declaration referring to 'sta' with internal linkage}} + using ::tb; + using ::stb; // expected-error {{using declaration referring to 'stb' with internal linkage}} + using ::tc; + using ::te; + using ::tf; + namespace NS2 = ::NS; + + namespace UnnamedNS { + using UnnamedNS::a; // expected-error {{internal linkage}} + using UnnamedNS::sa; // expected-error {{internal linkage}} + using UnnamedNS::b; // expected-error {{internal linkage}} + using UnnamedNS::sb; // expected-error {{internal linkage}} + using UnnamedNS::c; // expected-error {{internal linkage}} + using UnnamedNS::d; // expected-error {{internal linkage}} + using UnnamedNS::e; // ok + using UnnamedNS::f; // ok? using-declaration refers to alias-declaration, + // which does not have linkage (even though that then + // refers to a type that has internal linkage) + using UnnamedNS::sg1; // expected-error {{internal linkage}} + + using UnnamedNS::ta; // expected-error {{internal linkage}} + using UnnamedNS::sta; // expected-error {{internal linkage}} + using UnnamedNS::tb; // expected-error {{internal linkage}} + using UnnamedNS::stb; // expected-error {{internal linkage}} + using UnnamedNS::tc; // expected-error {{internal linkage}} + using UnnamedNS::te; // expected-error {{internal linkage}} + using UnnamedNS::tf; // expected-error {{internal linkage}} + namespace NS2 = UnnamedNS::NS; // ok (wording bug?) + } +} diff --git a/test/CXX/module/module.unit/p3.cpp b/test/CXX/module/module.unit/p3.cpp new file mode 100644 index 0000000000..2e08f4a9a8 --- /dev/null +++ b/test/CXX/module/module.unit/p3.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +export module foo:bar; // expected-error {{sorry, module partitions are not yet supported}} +import :baz; // expected-error {{sorry, module partitions are not yet supported}} diff --git a/test/CXX/module/module.unit/p8.cpp b/test/CXX/module/module.unit/p8.cpp new file mode 100644 index 0000000000..aad65272f0 --- /dev/null +++ b/test/CXX/module/module.unit/p8.cpp @@ -0,0 +1,40 @@ +// RUN: echo 'export module foo; export int n;' > %t.cppm +// RUN: %clang_cc1 -std=c++2a %t.cppm -emit-module-interface -o %t.pcm +// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=0 %s +// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=1 %s +// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=2 %s +// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=3 %s +// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=4 %s +// RUN: %clang_cc1 -std=c++2a -fmodule-file=%t.pcm -verify -DMODE=5 %s + +#if MODE == 0 +// no module declaration + +#elif MODE == 1 +// expected-no-diagnostics +module foo; +#define IMPORTED + +#elif MODE == 2 +export module foo; // expected-error {{redefinition of module 'foo'}} +// expected-note-re@* {{module loaded from '{{.*}}.pcm'}} +#define IMPORTED + +#elif MODE == 3 +export module bar; + +#elif MODE == 4 +module foo:bar; // expected-error {{not yet supported}} +#define IMPORTED // FIXME + +#elif MODE == 5 +export module foo:bar; // expected-error {{not yet supported}} expected-error {{redefinition}} expected-note@* {{loaded from}} +#define IMPORTED // FIXME + +#endif + +int k = n; +#ifndef IMPORTED +// expected-error@-2 {{declaration of 'n' must be imported from module 'foo' before it is required}} +// expected-note@* {{previous}} +#endif diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp index ad03191363..6eb5639d30 100644 --- a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp +++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp @@ -3,7 +3,6 @@ // CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global // CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally {{(dso_local )?}}global i32 0, // CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3, // // CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global @@ -21,7 +20,6 @@ void use() { (void)&extern_var_exported; (void)&inline_var_exported; - (void)&static_var_exported; // FIXME: Should not be exported. (void)&const_var_exported; // FIXME: This symbol should not be visible here. diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm index 0f2c0db66e..65861f84ba 100644 --- a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm +++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm @@ -11,7 +11,6 @@ // can discard this global and its initializer (if any), and other TUs are not // permitted to run the initializer for this variable. // CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE19static_var_exported = {{(dso_local )?}}global // CHECK-DAG: @const_var_exported = {{(dso_local )?}}constant // // CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global @@ -58,32 +57,17 @@ void noninline_global_module() { export module Module; export { - // FIXME: These should be ill-formed: you can't export an internal linkage - // symbol, per [dcl.module.interface]p2. - // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE22unused_static_exportedv - static void unused_static_exported() {} - // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE20used_static_exportedv - static void used_static_exported() {} - inline void unused_inline_exported() {} inline void used_inline_exported() {} extern int extern_var_exported; inline int inline_var_exported; - // FIXME: This should be ill-formed: you can't export an internal linkage - // symbol. - static int static_var_exported; const int const_var_exported = 3; // CHECK: define {{(dso_local )?}}void {{.*}}@_Z18noninline_exportedv void noninline_exported() { - used_static_exported(); - // CHECK: define linkonce_odr {{.*}}@_Z20used_inline_exportedv - used_inline_exported(); - (void)&extern_var_exported; (void)&inline_var_exported; - (void)&static_var_exported; (void)&const_var_exported; } } diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp b/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp index 97c69fa0bb..d55e063797 100644 --- a/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp +++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp @@ -3,7 +3,6 @@ // CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global // CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE19static_var_exported = available_externally {{(dso_local )?}}global i32 0 // CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3 import Module; @@ -16,7 +15,6 @@ void use() { (void)&extern_var_exported; (void)&inline_var_exported; - (void)&static_var_exported; (void)&const_var_exported; // Module-linkage declarations are not visible here. diff --git a/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp b/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp index feb0afdda0..7615536b81 100644 --- a/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp +++ b/test/CXX/modules-ts/basic/basic.link/module-declaration.cpp @@ -10,47 +10,39 @@ // // Module implementation for unknown and known module. (The former is ill-formed.) // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=1 -DEXPORT= -DPARTITION= -DMODULE_NAME=z +// RUN: -DTEST=1 -DEXPORT= -DMODULE_NAME=z // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=2 -DEXPORT= -DPARTITION= -DMODULE_NAME=x +// RUN: -DTEST=2 -DEXPORT= -DMODULE_NAME=x // // Module interface for unknown and known module. (The latter is ill-formed due to // redefinition.) // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=3 -DEXPORT=export -DPARTITION= -DMODULE_NAME=z +// RUN: -DTEST=3 -DEXPORT=export -DMODULE_NAME=z // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=4 -DEXPORT=export -DPARTITION= -DMODULE_NAME=x -// -// Defining a module partition. -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=5 -DEXPORT=export -DPARTITION=partition -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=6 -DEXPORT= -DPARTITION=partition -DMODULE_NAME=z +// RUN: -DTEST=4 -DEXPORT=export -DMODULE_NAME=x // // Miscellaneous syntax. // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=7 -DEXPORT= -DPARTITION=elderberry -DMODULE_NAME=z +// RUN: -DTEST=7 -DEXPORT=export -DMODULE_NAME='z elderberry' // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=8 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[]]' +// RUN: -DTEST=8 -DEXPORT=export -DMODULE_NAME='z [[]]' // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=9 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[fancy]]' +// RUN: -DTEST=9 -DEXPORT=export -DMODULE_NAME='z [[fancy]]' // RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \ -// RUN: -DTEST=10 -DEXPORT=export -DPARTITION= -DMODULE_NAME='z [[maybe_unused]]' +// RUN: -DTEST=10 -DEXPORT=export -DMODULE_NAME='z [[maybe_unused]]' -EXPORT module PARTITION MODULE_NAME; +EXPORT module MODULE_NAME; #if TEST == 4 // expected-error@-2 {{redefinition of module 'x'}} // expected-note-re@module-declaration.cpp:* {{loaded from '{{.*[/\\]}}x.pcm'}} -#elif TEST == 6 -// expected-error@-5 {{module partition must be declared 'export'}} #elif TEST == 7 -// expected-error@-7 {{expected ';'}} expected-error@-7 {{requires a type specifier}} expected-error@-7 {{definition of module 'elderberry' is not available}} +// expected-error@-5 {{expected ';'}} expected-error@-5 {{requires a type specifier}} #elif TEST == 9 -// expected-warning@-9 {{unknown attribute 'fancy' ignored}} +// expected-warning@-7 {{unknown attribute 'fancy' ignored}} #elif TEST == 10 -// expected-error-re@-11 {{'maybe_unused' attribute cannot be applied to a module{{$}}}} +// expected-error-re@-9 {{'maybe_unused' attribute cannot be applied to a module{{$}}}} #elif TEST == 1 -// expected-error@-13 {{definition of module 'z' is not available}} +// expected-error@-11 {{definition of module 'z' is not available}} #else // expected-no-diagnostics #endif diff --git a/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp b/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp index 68f2570dd3..52f45f578d 100644 --- a/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp +++ b/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.interface/p1.cpp @@ -10,7 +10,7 @@ // expected-no-diagnostics export module A; #elif IMPLEMENTATION -module A; +module A; // #module-decl #ifdef BUILT_AS_INTERFACE // expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}} #define INTERFACE @@ -23,6 +23,9 @@ module A; #ifndef INTERFACE export int b; // expected-error {{export declaration can only be used within a module interface unit}} +#ifdef IMPLEMENTATION +// expected-note@#module-decl {{add 'export' here}} +#endif #else export int a; #endif diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp index 849728a448..ab1b9f7a73 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -380,10 +380,10 @@ template <class T> struct A { namespace test18 { namespace ns1 { template <class T> struct foo {}; } // expected-note{{candidate ignored: not a function template}} namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}} -using ns1::foo; -using ns2::foo; +using ns1::foo; // expected-note {{found by name lookup}} +using ns2::foo; // expected-note {{found by name lookup}} template <class T> class A { - friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} + friend void foo<T>() {} // expected-error {{ambiguous}} expected-error{{no candidate function template was found for dependent friend function template specialization}} }; } diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 1681325f2e..da9895ca6d 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -213,8 +213,10 @@ namespace PackExpansionWithinLambda { }; #endif +#if __cplusplus > 201703L // - in a template parameter pack that is a pack expansion - // FIXME: We do not support any way to reach this case yet. + swallow([]<T *...v, template<T *> typename ...W>(W<v> ...wv) { }); +#endif // - in an initializer-list int arr[] = {T().x...}; @@ -279,11 +281,6 @@ namespace PackExpansionWithinLambda { struct T { int x; using U = int; }; void g() { f<T>(1, 2, 3); } - template<typename ...T, typename ...U> void pack_in_lambda(U ...u) { // expected-note {{here}} - // FIXME: Move this test into 'f' above once we support this syntax. - []<T *...v, template<T *> typename ...U>(U<v> ...uv) {}; // expected-error {{expected body of lambda}} expected-error {{does not refer to a value}} - } - template<typename ...T> void pack_expand_attr() { // FIXME: Move this test into 'f' above once we support this. [[gnu::aligned(alignof(T))...]] int x; // expected-error {{cannot be used as an attribute pack}} expected-error {{unexpanded}} |