diff options
author | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2024-06-24 18:59:08 +0800 |
---|---|---|
committer | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2024-06-24 19:03:31 +0800 |
commit | cc4ec6daf0d4f43110e8220d542c1155b8c1ef51 (patch) | |
tree | e1ee5b1414fb590740a0dc4245b208dadf38dca4 /clang | |
parent | 6b41de3605658069eb69b8684c2760e54bd1bea3 (diff) | |
download | llvm-cc4ec6daf0d4f43110e8220d542c1155b8c1ef51.zip llvm-cc4ec6daf0d4f43110e8220d542c1155b8c1ef51.tar.gz llvm-cc4ec6daf0d4f43110e8220d542c1155b8c1ef51.tar.bz2 |
[C++20] [Modules] Diagnose redeclarations from different modules
[basic.link]/p10:
> If two declarations of an entity are attached to different modules,
> the program is ill-formed
But we only implemented the check for ODR. In this patch, we tried to
diagnose the redeclarations from different modules.
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 17 | ||||
-rw-r--r-- | clang/test/Modules/no-eager-load.cppm | 6 | ||||
-rw-r--r-- | clang/test/Modules/same-decl-in-different-modules.cppm | 42 |
4 files changed, 68 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f323d1c..134a4e4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6075,6 +6075,9 @@ def err_thread_thread_different_kind : Error< def err_mismatched_owning_module : Error< "declaration of %0 in %select{the global module|module %2}1 follows " "declaration in %select{the global module|module %4}3">; +def err_multiple_decl_in_different_modules : Error< + "declaration %0 attached to named module '%1' can't be attached to " + "other modules">; def err_redefinition_different_type : Error< "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; def err_redefinition_different_kind : Error< diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 4b8b515..6afb18f 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3723,6 +3723,23 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, #include "clang/AST/DeclNodes.inc" } + // [basic.link]/p10: + // If two declarations of an entity are attached to different modules, + // the program is ill-formed; + // + // FIXME: Get rid of the enumeration of decl types once we have an appropriate + // abstract for decls of an entity. e.g., the namespace decl and using decl + // doesn't introduce an entity. + if (Module *M = Previous->getOwningModule(); + M && M->isNamedModule() && + isa<VarDecl, FunctionDecl, TagDecl, RedeclarableTemplateDecl>(Previous) && + !Reader.getContext().isInSameModule(M, D->getOwningModule())) { + Reader.Diag(Previous->getLocation(), + diag::err_multiple_decl_in_different_modules) + << cast<NamedDecl>(Previous) << M->Name; + Reader.Diag(D->getLocation(), diag::note_also_found); + } + // If the declaration was visible in one module, a redeclaration of it in // another module remains visible even if it wouldn't be visible by itself. // diff --git a/clang/test/Modules/no-eager-load.cppm b/clang/test/Modules/no-eager-load.cppm index 8a2c7656..c9eddaa 100644 --- a/clang/test/Modules/no-eager-load.cppm +++ b/clang/test/Modules/no-eager-load.cppm @@ -44,6 +44,9 @@ void use() { // expected-note@* {{but in 'a' found a different body}} } +// expected-error@a.cppm:* {{declaration 'foo' attached to named module 'a' can't be attached to other modules}} +// expected-note@b.cppm:* {{}} + //--- h.cppm export module h; export import a; @@ -55,3 +58,6 @@ void use() { foo(); // expected-error@* {{'foo' has different definitions in different modules;}} // expected-note@* {{but in 'a' found a different body}} } + +// expected-error@a.cppm:* {{declaration 'foo' attached to named module 'a' can't be attached to other modules}} +// expected-note@b.cppm:* {{}} diff --git a/clang/test/Modules/same-decl-in-different-modules.cppm b/clang/test/Modules/same-decl-in-different-modules.cppm new file mode 100644 index 0000000..2e8e90f --- /dev/null +++ b/clang/test/Modules/same-decl-in-different-modules.cppm @@ -0,0 +1,42 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/mod1.cppm -emit-module-interface -o %t/mod1.pcm +// RUN: %clang_cc1 -std=c++20 %t/mod2.cppm -emit-module-interface -o %t/mod2.pcm +// RUN: %clang_cc1 -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -verify + +//--- mod1.cppm +export module mod1; +export int v; +export void func(); +export class A {}; +export template <class C> +struct S {}; + +//--- mod2.cppm +export module mod2; +export int v; +export void func(); +export class A; +export template <class C> +struct S {}; + +//--- test.cc +import mod1; +import mod2; +void test() { + int value = v; + func(); + A a; + S<int> s; +} + +// expected-error@mod1.cppm:* {{declaration 'v' attached to named module 'mod1' can't be attached to other modules}} +// expected-note@mod2.cppm:* {{}} +// expected-error@mod1.cppm:* {{declaration 'func' attached to named module 'mod1' can't be attached to other modules}} +// expected-note@mod2.cppm:* {{}} +// expected-error@mod1.cppm:* {{declaration 'A' attached to named module 'mod1' can't be attached to other modules}} +// expected-note@mod2.cppm:* {{}} +// expected-error@mod1.cppm:* 1+{{declaration 'S' attached to named module 'mod1' can't be attached to other modules}} +// expected-note@mod2.cppm:* 1+{{}} |