// The test is check we couldn't export a redeclaration which isn't exported previously and
// check it is OK to redeclare no matter exported nor not if is the previous declaration is exported.
// RUN: %clang_cc1 -std=c++20 %s -verify
export module X;
struct S { // expected-note {{previous declaration is here}}
int n;
};
typedef S S;
export typedef S S; // OK, does not redeclare an entity
export struct S; // expected-error {{cannot export redeclaration 'S' here since the previous declaration has module linkage}}
namespace A {
struct X; // expected-note {{previous declaration is here}}
export struct Y;
} // namespace A
namespace A {
export struct X; // expected-error {{cannot export redeclaration 'X' here since the previous declaration has module linkage}}
export struct Y; // OK
struct Z; // expected-note {{previous declaration is here}}
export struct Z; // expected-error {{cannot export redeclaration 'Z' here since the previous declaration has module linkage}}
} // namespace A
namespace A {
struct B; // expected-note {{previous declaration is here}}
struct C {}; // expected-note {{previous declaration is here}}
} // namespace A
namespace A {
export struct B {}; // expected-error {{cannot export redeclaration 'B' here since the previous declaration has module linkage}}
export struct C; // expected-error {{cannot export redeclaration 'C' here since the previous declaration has module linkage}}
} // namespace A
template <typename T>
struct TemplS; // expected-note {{previous declaration is here}}
export template <typename T>
struct TemplS {}; // expected-error {{cannot export redeclaration 'TemplS' here since the previous declaration has module linkage}}
template <typename T>
struct TemplS2; // expected-note {{previous declaration is here}}
export template <typename U>
struct TemplS2 {}; // expected-error {{cannot export redeclaration 'TemplS2' here since the previous declaration has module linkage}}
void baz(); // expected-note {{previous declaration is here}}
export void baz(); // expected-error {{cannot export redeclaration 'baz' here since the previous declaration has module linkage}}
namespace A {
export void foo();
void bar(); // expected-note {{previous declaration is here}}
export void bar(); // expected-error {{cannot export redeclaration 'bar' here since the previous declaration has module linkage}}
void f1(); // expected-note {{previous declaration is here}}
} // namespace A
// OK
//
// [module.interface]/p6
// A redeclaration of an entity X is implicitly exported if X was introduced by an exported declaration
void A::foo();
// The compiler couldn't export A::f1() here since A::f1() is declared above without exported.
// See [module.interface]/p6 for details.
export void A::f1(); // expected-error {{cannot export redeclaration 'f1' here since the previous declaration has module linkage}}
template <typename T>
void TemplFunc(); // expected-note {{previous declaration is here}}
export template <typename T>
void TemplFunc() { // expected-error {{cannot export redeclaration 'TemplFunc' here since the previous declaration has module linkage}}
}
namespace A {
template <typename T>
void TemplFunc2(); // expected-note {{previous declaration is here}}
export template <typename T>
void TemplFunc2() {} // expected-error {{cannot export redeclaration 'TemplFunc2' here since the previous declaration has module linkage}}
template <typename T>
void TemplFunc3(); // expected-note {{previous declaration is here}}
} // namespace A
export template <typename T>
void A::TemplFunc3() {} // expected-error {{cannot export redeclaration 'TemplFunc3' here since the previous declaration has module linkage}}
int var; // expected-note {{previous declaration is here}}
export int var; // expected-error {{cannot export redeclaration 'var' here since the previous declaration has module linkage}}
template <typename T>
T TemplVar; // expected-note {{previous declaration is here}}
export template <typename T>
T TemplVar; // expected-error {{cannot export redeclaration 'TemplVar' here since the previous declaration has module linkage}}
// Test the compiler wouldn't complain about the redeclaration of friend in exported class.
namespace Friend {
template <typename T>
class bar;
class gua;
template <typename T>
void hello();
void hi();
export class foo;
bool operator<(const foo &a, const foo &b);
export class foo {
template <typename T>
friend class bar;
friend class gua;
template <typename T>
friend void hello();
friend void hi();
friend bool operator<(const foo &a, const foo &b);
};
} // namespace Friend