diff options
Diffstat (limited to 'test/CXX/basic')
-rw-r--r-- | test/CXX/basic/basic.link/p1.cpp | 57 | ||||
-rw-r--r-- | test/CXX/basic/basic.link/p2.cpp | 16 | ||||
-rw-r--r-- | test/CXX/basic/basic.link/p3.cpp | 53 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-associated-namespaces-classes.cpp | 344 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-inline-namespace.cpp | 56 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp | 16 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp | 64 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp | 93 | ||||
-rw-r--r-- | test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp | 86 |
9 files changed, 785 insertions, 0 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 |