def err_export_non_namespace_scope_name : Error<
"cannot export %0 as it is not at namespace scope">;
def err_redeclaration_non_exported : Error <
- "cannot export redeclaration %0 here since the previous declaration is not "
- "exported">;
+ "cannot export redeclaration %0 here since the previous declaration "
+ "%select{is not exported|has internal linkage|has module linkage}1">;
def err_invalid_declarator_global_scope : Error<
"definition or redeclaration of %0 cannot name the global scope">;
def err_invalid_declarator_in_function : Error<
def ext_export_no_names : ExtWarn<
"ISO C++20 does not permit a declaration that does not introduce any names "
"to be exported">, InGroup<ExportUnnamed>;
+def introduces_no_names : Error<
+ "declaration does not introduce any names to be exported">;
def note_export : Note<"export block begins here">;
def err_export_no_name : Error<
"%select{empty|static_assert|asm}0 declaration cannot be exported">;
def err_export_internal : Error<
"declaration of %0 with internal linkage cannot be exported">;
def err_export_using_internal : Error<
- "using declaration referring to %0 with internal linkage cannot be exported">;
+ "using declaration referring to %1 with %select{internal|module|unknown}0 "
+ "linkage cannot be exported">;
def err_export_not_in_module_interface : Error<
"export declaration can only be used within a module interface unit"
"%select{ after the module declaration|}0">;
assert(IsNewExported);
- Diag(New->getLocation(), diag::err_redeclaration_non_exported) << New;
+ auto Lk = Old->getFormalLinkage();
+ int S = 0;
+ if (Lk == Linkage::InternalLinkage)
+ S = 1;
+ else if (Lk == Linkage::ModuleLinkage)
+ S = 2;
+ Diag(New->getLocation(), diag::err_redeclaration_non_exported) << New << S;
Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
StaticAssert,
Asm,
UsingDirective,
+ Namespace,
Context
};
}
// Allow exporting using-directives as an extension.
return diag::ext_export_using_directive;
+ case UnnamedDeclKind::Namespace:
+ // Anonymous namespace with no content.
+ return diag::introduces_no_names;
+
case UnnamedDeclKind::Context:
// Allow exporting DeclContexts that transitively contain no declarations
// as an extension.
diagExportedUnnamedDecl(S, *UDK, D, BlockStart);
// [...] shall not declare a name with internal linkage.
+ bool HasName = false;
if (auto *ND = dyn_cast<NamedDecl>(D)) {
// Don't diagnose anonymous union objects; we'll diagnose their members
// instead.
- if (ND->getDeclName() && ND->getFormalLinkage() == InternalLinkage) {
+ HasName = (bool)ND->getDeclName();
+ if (HasName && ND->getFormalLinkage() == InternalLinkage) {
S.Diag(ND->getLocation(), diag::err_export_internal) << ND;
if (BlockStart.isValid())
S.Diag(BlockStart, diag::note_export);
// shall have been introduced with a name having external linkage
if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
NamedDecl *Target = USD->getUnderlyingDecl();
- if (Target->getFormalLinkage() == InternalLinkage) {
- S.Diag(USD->getLocation(), diag::err_export_using_internal) << Target;
+ Linkage Lk = Target->getFormalLinkage();
+ if (Lk == InternalLinkage || Lk == ModuleLinkage) {
+ S.Diag(USD->getLocation(), diag::err_export_using_internal)
+ << (Lk == InternalLinkage ? 0 : 1) << Target;
S.Diag(Target->getLocation(), diag::note_using_decl_target);
if (BlockStart.isValid())
S.Diag(BlockStart, diag::note_export);
}
// Recurse into namespace-scope DeclContexts. (Only namespace-scope
- // declarations are exported.)
- if (auto *DC = dyn_cast<DeclContext>(D))
- if (DC->getRedeclContext()->isFileContext() && !isa<EnumDecl>(D))
+ // declarations are exported.).
+ if (auto *DC = dyn_cast<DeclContext>(D)) {
+ if (isa<NamespaceDecl>(D) && DC->decls().empty()) {
+ if (!HasName)
+ // We don't allow an empty anonymous namespace (we don't allow decls
+ // in them either, but that's handled in the recursion).
+ diagExportedUnnamedDecl(S, UnnamedDeclKind::Namespace, D, BlockStart);
+ else
+ ; // We allow an empty named namespace decl.
+ } else if (DC->getRedeclContext()->isFileContext() && !isa<EnumDecl>(D))
return checkExportedDeclContext(S, DC, BlockStart);
+ }
return false;
}
export module p3;
-namespace A { int ns_mem; }
+namespace A { int ns_mem; } // expected-note 2{{target}}
// 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 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}}
+ 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 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;
+export using A::ns_mem; // expected-error {{using declaration referring to 'ns_mem' with module linkage cannot be exported}}
namespace A {
- export using A::ns_mem;
+ export using A::ns_mem; // expected-error {{using declaration referring to 'ns_mem' with module linkage cannot be exported}}
}
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 module p5;
-int a;
+int a; // expected-note {{target}}
static int sa; // expected-note {{target}}
-void b();
+void b(); // expected-note {{target}}
static void sb(); // expected-note {{target}}
-struct c {};
-enum d {};
+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;
+template<typename> int ta; // expected-note {{target}}
template<typename> static int sta; // expected-note {{target}}
-template<typename> void tb();
+template<typename> void tb(); // expected-note {{target}}
template<typename> static void stb(); // expected-note {{target}}
-template<typename> struct tc {};
-template<typename> using te = int;
-template<typename> using tf = c;
+template<typename> struct tc {}; // expected-note {{target}}
+template<typename> using te = int; // expected-note {{target}}
+template<typename> using tf = c; // expected-note {{target}}
namespace UnnamedNS {
namespace {
}
}
-export { // expected-note 19{{here}}
- using ::a;
+export { // expected-note 28{{here}}
+ using ::a; // expected-error {{using declaration referring to 'a' with module linkage cannot be exported}}
using ::sa; // expected-error {{using declaration referring to 'sa' with internal linkage}}
- using ::b;
+ using ::b; // expected-error {{using declaration referring to 'b' with module linkage cannot be exported}}
using ::sb; // expected-error {{using declaration referring to 'sb' with internal linkage}}
- using ::c;
- using ::d;
+ using ::c; // expected-error {{using declaration referring to 'c' with module linkage cannot be exported}}
+ using ::d; // expected-error {{using declaration referring to 'd' with module linkage cannot be exported}}
using ::e;
using ::f;
using ::sg1; // expected-error {{using declaration referring to 'sg1' with internal linkage}}
- using ::ta;
+ using ::ta; // expected-error {{using declaration referring to 'ta' with module linkage cannot be exported}}
using ::sta; // expected-error {{using declaration referring to 'sta' with internal linkage}}
- using ::tb;
+ using ::tb; // expected-error {{using declaration referring to 'tb' with module linkage cannot be exported}}
using ::stb; // expected-error {{using declaration referring to 'stb' with internal linkage}}
- using ::tc;
- using ::te;
- using ::tf;
+ using ::tc; // expected-error {{using declaration referring to 'tc' with module linkage cannot be exported}}
+ using ::te; // expected-error {{using declaration referring to 'te' with module linkage cannot be exported}}
+ using ::tf; // expected-error {{using declaration referring to 'tf' with module linkage cannot be exported}}
namespace NS2 = ::NS;
namespace UnnamedNS {
};
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 is not exported}}
+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}}
} // namespace A
namespace A {
-export struct X; // expected-error {{cannot export redeclaration 'X' here since the previous declaration is not exported}}
+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 is not exported}}
+export struct Z; // expected-error {{cannot export redeclaration 'Z' here since the previous declaration has module linkage}}
} // namespace A
namespace A {
} // namespace A
namespace A {
-export struct B {}; // expected-error {{cannot export redeclaration 'B' here since the previous declaration is not exported}}
-export struct C; // expected-error {{cannot export redeclaration 'C' here since the previous declaration is not exported}}
+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 is not exported}}
+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 is not exported}}
+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 is not exported}}
+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 is not exported}}
+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
// 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 is not exported}}
+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 is not exported}}
+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 is not exported}}
+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 is not exported}}
+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 is not exported}}
+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 is not exported}}
+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 {
--- /dev/null
+// Based on C++20 10.2 example 1.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std-10-2-ex1-tu1.cpp \
+// RUN: -pedantic-errors -verify -o %t/m1.pcm
+
+//--- std-10-2-ex1.h
+export int x;
+
+//--- std-10-2-ex1-tu1.cpp
+module;
+
+#include "std-10-2-ex1.h"
+// expected-error@std-10-2-ex1.h:* {{export declaration can only be used within a module interface unit after the module declaration}}
+
+export module M1;
+export namespace {} // expected-error {{declaration does not introduce any names to be exported}}
+export namespace {
+int a1; // expected-error {{declaration of 'a1' with internal linkage cannot be exported}}
+}
+namespace { // expected-note {{anonymous namespace begins here}}
+export int a2; // expected-error {{export declaration appears within anonymous namespace}}
+}
+export static int b; // expected-error {{declaration of 'b' with internal linkage cannot be exported}}
+export int f(); // OK
+
+export namespace N {} // namespace N
+export using namespace N; // expected-error {{ISO C++20 does not permit using directive to be exported}}
--- /dev/null
+// Based on C++20 10.2 example 3.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -o M.pcm
+
+export module M;
+struct S;
+export using T = S; // OK, exports name T denoting type S
+
+// expected-no-diagnostics
--- /dev/null
+// Based on C++20 10.2 example 4.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o M.pcm
+
+export module M;
+
+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}}
--- /dev/null
+// Based on C++20 10.2 example 5.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std-10-2-ex5-tu1.cpp \
+// RUN: -o %t/M.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu2.cpp \
+// RUN: -fmodule-file=%t/M.pcm -o %t/tu-2.o
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \
+// RUN: -fmodule-file=%t/M.pcm -verify -o %t/main.o
+
+//--- std-10-2-ex5-tu1.cpp
+export module M;
+export struct X {
+ static void f();
+ struct Y {};
+};
+namespace {
+struct S {};
+} // namespace
+export void f(S); // OK
+struct T {};
+export T id(T); // OK
+export struct A; // A exported as incomplete
+
+export auto rootFinder(double a) {
+ return [=](double x) { return (x + a / x) / 2; };
+}
+export const int n = 5; // OK, n has external linkage
+
+//--- std-10-2-ex5-tu2.cpp
+
+module M;
+struct A {
+ int value;
+};
+
+//--- std-10-2-ex5-tu3.cpp
+
+import M;
+
+int main() {
+ X::f(); // OK, X is exported and definition of X is reachable
+ X::Y y; // OK, X::Y is exported as a complete type
+ auto f = rootFinder(2); // OK
+ // error: A is incomplete
+ return A{45}.value; // expected-error {{invalid use of incomplete type 'A'}}
+ // expected-error@-1 {{member access into incomplete type 'A'}}
+ // expected-note@std-10-2-ex5-tu1.cpp:12 2{{forward declaration of 'A'}}
+}
--- /dev/null
+// Based on C++20 10.2 example 6.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o M.pcm
+
+export module M;
+
+static int f(); // expected-note {{previous declaration is here}} #1
+ // error: #1 gives internal linkage
+export int f(); // expected-error {{cannot export redeclaration 'f' here since the previous declaration has internal linkage}}
+struct S; // expected-note {{previous declaration is here}} #2
+ // error: #2 gives module linkage
+export struct S; // expected-error {{cannot export redeclaration 'S' here since the previous declaration has module linkage}}
+
+namespace {
+namespace N {
+extern int x; // expected-note {{previous declaration is here}} #3
+}
+} // namespace
+ // error: #3 gives internal linkage
+export int N::x; // expected-error {{cannot export redeclaration 'x' here since the previous declaration has internal linkage}}
+ // expected-error@-1 {{declaration of 'x' with internal linkage cannot be exported}}
--- /dev/null
+// Based on C++20 10.2 example 6.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o M.pcm
+
+export module M;
+export namespace N {
+int x; // OK
+static_assert(1 == 1); // expected-error {{static_assert declaration cannot be exported}}
+} // namespace N