diff --git a/clang/test/Modules/redefinition-merges.cppm b/clang/test/Modules/redefinition-merges.cppm new file mode 100644 index 0000000000000..9ab4006f985fa --- /dev/null +++ b/clang/test/Modules/redefinition-merges.cppm @@ -0,0 +1,117 @@ +// Tests that redefinitions in different TUs could be merged correctly and the +// redefinitions in the same TUs could be merged diagnosticed correctly. +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -I%t %t/normal.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/M1.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/M2.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/M3.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-module-interface -o %t/M.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only +// +//--- foo.h +#ifndef FOO +#define FOO +inline void func() {} +template +T templ_func(T t) { return t; } +struct S {}; +template +struct T { C c; }; +inline int v = 43; +#endif + +// If we copy foo.h directly, there are other warnings. +//--- redef.h +#ifndef REDEF +#define REDEF +inline void func() {} +template +T templ_func(T t) { return t; } +struct S {}; +template +struct T { C c; }; +inline int v = 43; +#endif + +//--- normal.cpp +#include "foo.h" +#include "redef.h" + +// expected-error@* {{redefinition of 'func'}} +// expected-error@* {{redefinition of 'templ_func'}} +// expected-error@* {{redefinition of 'S'}} +// expected-error@* {{redefinition of 'T'}} +// expected-error@* {{redefinition of 'v'}} +// expected-note@* 1+{{previous definition is here}} + +//--- M1.cppm +// These declarations are in the same TU. The compiler should complain. +module; +#include "foo.h" +#include "redef.h" +export module M1; + +// expected-error@* {{redefinition of 'func'}} +// expected-error@* {{redefinition of 'templ_func'}} +// expected-error@* {{redefinition of 'S'}} +// expected-error@* {{redefinition of 'T'}} +// expected-error@* {{redefinition of 'v'}} +// expected-note@* 1+{{previous definition is here}} + +//--- M2.cppm +// These declarations are in the same TU and the redefinitions are in the named modules. +// The compiler should complain. +module; +#include "foo.h" +export module M2; +#include "redef.h" + +// FIXME: The diagnostic message looks not so good. +// +// expected-error@* {{declaration of 'func' in module M2 follows declaration in the global module}} +// expected-error@* {{declaration of 'templ_func' in module M2 follows declaration in the global module}} +// expected-error@* {{redefinition of 'S'}} +// expected-error@* {{redefinition of 'T'}} +// expected-error@* {{declaration of 'v' in module M2 follows declaration in the global module}} +// expected-note@* 1+{{previous definition is here}} +// expected-note@* 1+{{previous declaration is here}} + +//--- M3.cppm +// These declarations are in the same TU. The compiler should complain. +export module M3; +#include "foo.h" +#include "redef.h" + +// expected-error@* {{redefinition of 'func'}} +// expected-error@* {{redefinition of 'templ_func'}} +// expected-error@* {{redefinition of 'S'}} +// expected-error@* {{redefinition of 'T'}} +// expected-error@* {{redefinition of 'v'}} +// expected-note@* 1+{{previous definition is here}} + +//--- M.cppm +module; +#include "foo.h" +export module M; +export using ::func; +export using ::templ_func; +export using ::S; +export using ::T; +export using ::v; + +//--- Use1.cpp +// These declarations are not in the same TU. The compiler shouldn't complain. +// expected-no-diagnostics +#include "foo.h" +import M; + +//--- Use2.cpp +// These declarations are not in the same TU. The compiler shouldn't complain. +// expected-no-diagnostics +import M; +#include "foo.h"