Author: Vlad Serebrennikov Date: 2024-10-28T18:48:23+04:00 New Revision: d83485a080341688cbb9d5c07a3839bd97f9001e
URL: https://github.com/llvm/llvm-project/commit/d83485a080341688cbb9d5c07a3839bd97f9001e DIFF: https://github.com/llvm/llvm-project/commit/d83485a080341688cbb9d5c07a3839bd97f9001e.diff LOG: [clang][NFC] Add test for CWG issues about linkage in cross-TU context (#113736) [CWG279](https://cplusplus.github.io/CWG/issues/279.html) Correspondence of "names for linkage purposes" ==================== [P1787R6](https://wg21.link/p1787r6): > CWG1884, CWG279, and CWG338 are resolved by defining entity identity explicitly. In both cases discussed in the issue, declaration matching succeeds per [[basic.link]/8](https://eel.is/c++draft/basic.link#8), thanks to the > considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]) and > they both declare names with external linkage parts. Which means that both pairs of declarations of `S` and `S2` declare the same entity. [[basic.link]/11](https://eel.is/c++draft/basic.link#11) is also satisfied, because in all cases type is declared. Then cases diverge. `S` is a pair of a forward declaration and a definition, which means it's not a subject to [[basic.def.odr]/15](https://eel.is/c++draft/basic.def.odr#15), hence it's well-formed. Whereas `S2` is a pair of two definitions, so they are subjects to [[basic.def.odr]/15](https://eel.is/c++draft/basic.def.odr#15), which they do not satisfy due to the violation of the following requirement: > — Each such definition shall consist of the same sequence of tokens, <...> Because per [[class.pre/2]](https://eel.is/c++draft/class#pre-2), class definition is class-specifier, which includes class-head, but class-head is different between definitions. [CWG338](https://cplusplus.github.io/CWG/issues/338.html) Enumerator name with linkage used as class name in other translation unit ==================== [P1787R6](https://wg21.link/p1787r6): > CWG1884, CWG279, and CWG338 are resolved by defining entity identity explicitly. I believe this CWG issue points to the same underlying issue with old [basic.link]/9 as CWG1884 (see below), so I'm calling it a duplicate of CWG1884. Cases described there are a part of an extensive CWG1884 test. Also worth noting that enumerators don't have linkage these days. [CWG1884](https://cplusplus.github.io/CWG/issues/1898.html) Unclear requirements for same-named external-linkage entities ==================== [P1787R6](https://wg21.link/p1787r6): > CWG1884, CWG279, and CWG338 are resolved by defining entity identity explicitly. [basic.link]/9 quoted in the issue is now split into several pieces. > Two names that are the same (6.1 [basic.pre]) I believe this is corresponding declarations now, defined in [[basic.scope.scope]/4](https://eel.is/c++draft/basic.scope#scope-4). > and that are declared in different scopes shall denote the same variable, function, type, enumerator, template or namespace if This is covered by [[basic.link]/11](https://eel.is/c++draft/basic.link#11) after it's determined by [[basic.link]/8](https://eel.is/c++draft/basic.link#8) that two declarations declare the same entity. > — both names have external linkage or else both names have internal linkage and are declared in the same translation unit; and > — both names refer to members of the same namespace or to members, not by inheritance, of the same class; and Most of this is covered by [[basic.link]/8](https://eel.is/c++draft/basic.link#8). > — when both names denote functions, the parameter-type-lists of the functions (9.3.4.6 [dcl.fct]) are identical; and > — when both names denote function templates, the signatures (13.7.7.2 [temp.over.link]) are the same. This is corresponding overloads now, defined in [[basic.scope.scope]/4](https://eel.is/c++draft/basic.scope#scope-4). > Among other things, it should be clarified that "declared in" refers to the namespace of which the name is a member, not the lexical scope in which the declaration appears (which affects friend declarations, block-scope extern declarations, and elaborated-type-specifiers). This is addressed by "have the same target scope" part of [[basic.link]/8](https://eel.is/c++draft/basic.link#8). The tests basically test [[basic.link]/11](https://eel.is/c++draft/basic.link#11) from the following standpoint: > The intent is that this rule prevents declaring a name with extenal linkage to be, for instance, a type in one translation unit and a namespace in a different translation unit. See the comment in the beginning of the test for details on testing approach. Reviewers are advised to check compiler output for any surprises, but if they are in a hurry, they can search for `FIXME`, `OK`, and `#cwg1884` to see the most of irregularities in Clang behavior across the test (not all of them are incorrect behavior, though). Added: clang/test/CXX/drs/cwg1884.cpp clang/test/CXX/drs/cwg279.cpp Modified: clang/test/CXX/drs/cwg18xx.cpp clang/test/CXX/drs/cwg2xx.cpp clang/test/CXX/drs/cwg3xx.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/test/CXX/drs/cwg1884.cpp b/clang/test/CXX/drs/cwg1884.cpp new file mode 100644 index 00000000000000..c4f76baa3933fb --- /dev/null +++ b/clang/test/CXX/drs/cwg1884.cpp @@ -0,0 +1,643 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file --leading-lines %s %t +// RUN: %clang_cc1 -std=c++20 -pedantic-errors -fexceptions -fcxx-exceptions %t/cwg1884_A.cppm -triple x86_64-unknown-unknown -emit-module-interface -o %t/cwg1884_A.pcm +// RUN: %clang_cc1 -std=c++20 -verify=since-cxx20 -pedantic-errors -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown %t/cwg1884.cpp -fmodule-file=cwg1884_A=%t/cwg1884_A.pcm +// RUN: %clang_cc1 -std=c++23 -pedantic-errors -fexceptions -fcxx-exceptions %t/cwg1884_A.cppm -triple x86_64-unknown-unknown -emit-module-interface -o %t/cwg1884_A.pcm +// RUN: %clang_cc1 -std=c++23 -verify=since-cxx20 -pedantic-errors -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown %t/cwg1884.cpp -fmodule-file=cwg1884_A=%t/cwg1884_A.pcm +// RUN: %clang_cc1 -std=c++2c -pedantic-errors -fexceptions -fcxx-exceptions %t/cwg1884_A.cppm -triple x86_64-unknown-unknown -emit-module-interface -o %t/cwg1884_A.pcm +// RUN: %clang_cc1 -std=c++2c -verify=since-cxx20 -pedantic-errors -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown %t/cwg1884.cpp -fmodule-file=cwg1884_A=%t/cwg1884_A.pcm + +// cwg1884: partial +// Cases b11, e11, g3, g4 are problematic, but we handle the other 101 cases fine. + +// _N4993_.[basic.link]/11: +// For any two declarations of an entity E: +// — If one declares E to be a variable or function, +// the other shall declare E as one of the same type. +// — If one declares E to be an enumerator, the other shall do so. +// — If one declares E to be a namespace, the other shall do so. +// — If one declares E to be a type, +// the other shall declare E to be a type of the same kind (9.2.9.5). +// — If one declares E to be a class template, +// the other shall do so with the same kind and an equivalent template-head (13.7.7.2). +// [Note 5 : The declarations can supply diff erent default template arguments. — end note] +// — If one declares E to be a function template or a (partial specialization of a) variable template, +// the other shall declare E to be one with an equivalent template-head and type. +// — If one declares E to be an alias template, +// the other shall declare E to be one with an equivalent template-head and defining-type-id. +// — If one declares E to be a concept, the other shall do so. +// Types are compared after all adjustments of types (during which typedefs (9.2.4) are replaced by their definitions); +// declarations for an array object can specify array types that diff er by the presence or absence of a major array bound (9.3.4.5). +// No diagnostic is required if neither declaration is reachable from the other. + +// The structure of the test is the following. First, module cwg1884_A +// provides all (significant) kinds of entities, each named 'a' through 'h', and copies of them. +// Then the .cpp file does MxN kind of testing, where it tests one kind of entity against every other kind. + +//--- cwg1884_A.cppm +export module cwg1884_A; + +export { +int a1; +int a2; +int a3; +int a4; +int a5; +int a6; +int a7; +int a8; +int a9; +int a10; +int a11; +void b1(); +void b2(); +void b3(); +void b4(); +void b5(); +void b6(); +void b7(); +void b8(); +void b9(); +void b10(); +void b11(); +enum E { + c1, + c2, + c3, + c4, + c5, + c6, + c7, + c8, + c9, + c10 +}; +namespace d1 {} +namespace d2 {} +namespace d3 {} +namespace d4 {} +namespace d5 {} +namespace d6 {} +namespace d7 {} +namespace d8 {} +namespace d9 {} +namespace d10 {} +struct e1; +struct e2; +struct e3; +struct e4; +struct e5; +struct e6; +struct e7; +struct e8; +struct e9; +struct e10; +struct e11; +struct e12; +struct e13; +template <typename> +class f1; +template <typename> +class f2; +template <typename> +class f3; +template <typename> +class f4; +template <typename> +class f5; +template <typename> +class f6; +template <typename> +class f7; +template <typename> +class f8; +template <typename> +class f9; +template <typename> +class f10; +template <typename> +class f11; +template <typename> +void g1(int); +template <typename> +void g2(int); +template <typename> +void g3(int); +template <typename> +void g4(int); +template <typename> +void g5(int); +template <typename> +void g6(int); +template <typename> +void g7(int); +template <typename> +void g8(int); +template <typename> +void g9(int); +template <typename> +void g10(int); +template <typename, typename> +int h1; +template <typename, typename> +int h2; +template <typename, typename> +int h3; +template <typename, typename> +int h4; +template <typename, typename> +int h5; +template <typename, typename> +int h6; +template <typename, typename> +int h7; +template <typename, typename> +int h8; +template <typename, typename> +int h9; +template <typename, typename> +int h10; +template <typename> +using i1 = int; +template <typename> +using i2 = int; +template <typename> +using i3 = int; +template <typename> +using i4 = int; +template <typename> +using i5 = int; +template <typename> +using i6 = int; +template <typename> +using i7 = int; +template <typename> +using i8 = int; +template <typename> +using i9 = int; +template <typename> +using i10 = int; +template <typename> +using i11 = int; +template <typename> +concept j1 = true; +template <typename> +concept j2 = true; +template <typename> +concept j3 = true; +template <typename> +concept j4 = true; +template <typename> +concept j5 = true; +template <typename> +concept j6 = true; +template <typename> +concept j7 = true; +template <typename> +concept j8 = true; +template <typename> +concept j9 = true; +template <typename> +concept j10 = true; +template <typename> +concept j11 = true; +} // export + + +//--- cwg1884.cpp +import cwg1884_A; + +// FIXME: we don't diagnose several cases we should be. They are marked with MISSING prefix. + +// Part A: matching against `int a;` +// --------------------------------- + +void a1(); +// since-cxx20-error@-1 {{redefinition of 'a1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}} +enum Ea { + a2 + // since-cxx20-error@-1 {{redefinition of 'a2'}} + // since-cxx20-note@cwg1884_A.cppm:43 {{previous definition is here}} +}; +namespace a3 {} +// since-cxx20-error@-1 {{redefinition of 'a3' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}} +struct a4; +// @-1 OK, types and variables do not correspond +template <typename> +class a5; +// since-cxx20-error@-1 {{redefinition of 'a5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:46 {{previous definition is here}} +template <typename> +void a6(int); +// since-cxx20-error@-1 {{redefinition of 'a6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:47 {{previous definition is here}} +template <typename, typename> +int a7; +// since-cxx20-error@-1 {{redefinition of 'a7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:48 {{previous definition is here}} +template <typename T> +int a8<T, int>; +// since-cxx20-error@-1 {{redefinition of 'a8' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}} +// since-cxx20-error@-3 {{expected ';' after top level declarator}} +template <typename> +using a9 = int; +// since-cxx20-error@-1 {{redefinition of 'a9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:50 {{previous definition is here}} +template <typename> +concept a10 = true; +// since-cxx20-error@-1 {{redefinition of 'a10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:51 {{previous definition is here}} +// For variables, type has to match as well. +long a11; +// since-cxx20-error@-1 {{redefinition of 'a11' with a diff erent type: 'long' vs 'int'}} +// since-cxx20-note@cwg1884_A.cppm:52 {{previous definition is here}} + + +// Part B: matching against `void b();` +// ------------------------------------ + +int b1; +// since-cxx20-error@-1 {{redefinition of 'b1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}} +enum Eb { + b2 + // since-cxx20-error@-1 {{redefinition of 'b2'}} + // since-cxx20-note@cwg1884_A.cppm:54 {{previous definition is here}} +}; +namespace b3 {} // #cwg1884-namespace-b +// since-cxx20-error@-1 {{redefinition of 'b3' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:55 {{previous definition is here}} +struct b4; +// @-1 OK, types and functions do not correspond +template <typename> +class b5; +// since-cxx20-error@-1 {{redefinition of 'b5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:57 {{previous definition is here}} +template <typename> +void b6(int); +// @-1 OK, a non-corresponding overload +template <typename, typename> +int b7; +// since-cxx20-error@-1 {{redefinition of 'b7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:59 {{previous definition is here}} +template <typename T> +int b8<T, int>; +// since-cxx20-error@-1 {{no variable template matches partial specialization}} +template <typename> +using b9 = int; +// since-cxx20-error@-1 {{redefinition of 'b9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:61 {{previous definition is here}} +template <typename> +concept b10 = true; +// since-cxx20-error@-1 {{redefinition of 'b10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:62 {{previous definition is here}} +// For functions, type has to match as well. +// FIXME: we should be loud and clear here about type mismatch, like we do in `a11` case. +int b11(); +// since-cxx20-error@-1 {{declaration of 'b11' in the global module follows declaration in module cwg1884_A}} +// since-cxx20-note@cwg1884_A.cppm:63 {{previous declaration is here}} + + +// Part C: matching against `enum E { c };` +// ---------------------------------------- + +int c1; +// since-cxx20-error@-1 {{redefinition of 'c1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:65 {{previous definition is here}} +void c2(); +// since-cxx20-error@-1 {{redefinition of 'c2' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:66 {{previous definition is here}} +namespace c3 {} +// since-cxx20-error@-1 {{redefinition of 'c3' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:67 {{previous definition is here}} +struct c4; +// @-1 OK, types and enumerators do not correspond +template <typename> +class c5; +// since-cxx20-error@-1 {{redefinition of 'c5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:69 {{previous definition is here}} +template <typename> +void c6(int); +// since-cxx20-error@-1 {{redefinition of 'c6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:70 {{previous definition is here}} +template <typename, typename> +int c7; +// since-cxx20-error@-1 {{redefinition of 'c7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:71 {{previous definition is here}} +template <typename T> +int c8<T, int>; +// since-cxx20-error@-1 {{redefinition of 'c8' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:72 {{previous definition is here}} +// since-cxx20-error@-3 {{expected ';' after top level declarator}} +template <typename> +using c9 = int; +// since-cxx20-error@-1 {{redefinition of 'c9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:73 {{previous definition is here}} +template <typename> +concept c10 = true; +// since-cxx20-error@-1 {{redefinition of 'c10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:74 {{previous definition is here}} + + +// Part D: matching against `namespace d {};` +// ------------------------------------------ + +int d1; +// since-cxx20-error@-1 {{redefinition of 'd1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:76 {{previous definition is here}} +void d2(); +// since-cxx20-error@-1 {{redefinition of 'd2' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:77 {{previous definition is here}} +enum Ed { + d3 + // since-cxx20-error@-1 {{redefinition of 'd3'}} + // since-cxx20-note@cwg1884_A.cppm:78 {{previous definition is here}} +}; +struct d4; +// since-cxx20-error@-1 {{redefinition of 'd4' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:79 {{previous definition is here}} +template <typename> +class d5; +// since-cxx20-error@-1 {{redefinition of 'd5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:80 {{previous definition is here}} +template <typename> +void d6(int); +// since-cxx20-error@-1 {{redefinition of 'd6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:81 {{previous definition is here}} +template <typename, typename> +int d7; +// since-cxx20-error@-1 {{redefinition of 'd7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:82 {{previous definition is here}} +template <typename T> +int d8<T, int>; +// since-cxx20-error@-1 {{redefinition of 'd8' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:83 {{previous definition is here}} +// since-cxx20-error@-3 {{expected ';' after top level declarator}} +template <typename> +using d9 = int; +// since-cxx20-error@-1 {{redefinition of 'd9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:84 {{previous definition is here}} +template <typename> +concept d10 = true; +// since-cxx20-error@-1 {{redefinition of 'd10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:85 {{previous definition is here}} + + +// Part E: matching against `struct e;` +// ------------------------------------ + +int e1; +// @-1 OK, types and variables do not correspond +void e2(); +// @-1 OK, types and functions do not correspond +enum Ee { + e3 + // @-1 OK, types and enumerators do not correspond +}; +namespace e4 {} +// since-cxx20-error@-1 {{redefinition of 'e4' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:89 {{previous definition is here}} +template <typename> +class e5; +// since-cxx20-error@-1 {{redefinition of 'e5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:90 {{previous definition is here}} +template <typename> +void e6(int); +// @-1 OK, types and function templates do not correspond +template <typename, typename> +int e7; +// since-cxx20-error@-1 {{redefinition of 'e7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:92 {{previous definition is here}} +template <typename T> +int e8<T, int>; +// since-cxx20-error@-1 {{redefinition of 'e8' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:93 {{previous definition is here}} +// since-cxx20-error@-3 {{expected ';' after top level declarator}} +template <typename> +using e9 = int; +// since-cxx20-error@-1 {{redefinition of 'e9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:94 {{previous definition is here}} +template <typename> +concept e10 = true; +// since-cxx20-error@-1 {{redefinition of 'e10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:95 {{previous definition is here}} +// FIXME: the following forward declaration is well-formed. +// Agreement on 'struct' vs 'class' is not required per [dcl.type.elab]/7. +class e11; +// since-cxx20-error@-1 {{declaration of 'e11' in the global module follows declaration in module cwg1884_A}} +// since-cxx20-note@cwg1884_A.cppm:96 {{previous declaration is here}} +union e12; +// since-cxx20-error@-1 {{use of 'e12' with tag type that does not match previous declaration}} +// since-cxx20-note@cwg1884_A.cppm:97 {{previous use is here}} +// since-cxx20-error@-3 {{declaration of 'e12' in the global module follows declaration in module cwg1884_A}} +// since-cxx20-note@cwg1884_A.cppm:97 {{previous declaration is here}} +enum e13 {}; +// since-cxx20-error@-1 {{use of 'e13' with tag type that does not match previous declaration}} +// since-cxx20-note@cwg1884_A.cppm:98 {{previous use is here}} + + +// Part F: matching against `template <typename> class f;` +// ------------------------------------------------------- + +int f1; +// since-cxx20-error@-1 {{redefinition of 'f1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:100 {{previous definition is here}} +void f2(); +// since-cxx20-error@-1 {{redefinition of 'f2' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:102 {{previous definition is here}} +enum Ef { + f3 + // since-cxx20-error@-1 {{redefinition of 'f3'}} + // since-cxx20-note@cwg1884_A.cppm:104 {{previous definition is here}} +}; +namespace f4 {} +// since-cxx20-error@-1 {{redefinition of 'f4' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:106 {{previous definition is here}} +struct f5; +// since-cxx20-error@-1 {{redefinition of 'f5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:108 {{previous definition is here}} +template <typename> +void f6(int); +// since-cxx20-error@-1 {{redefinition of 'f6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:110 {{previous definition is here}} +template <typename, typename> +int f7; +// since-cxx20-error@-1 {{redefinition of 'f7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:112 {{previous definition is here}} +template <typename T> +int f8<T, int>; +// since-cxx20-error@-1 {{no variable template matches partial specialization}} +template <typename> +using f9 = int; +// since-cxx20-error@-1 {{redefinition of 'f9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:116 {{previous definition is here}} +template <typename> +concept f10 = true; +// since-cxx20-error@-1 {{redefinition of 'f10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:118 {{previous definition is here}} + + +// Part G: matching against `template <typename> void g(int);` +// ----------------------------------------------------------- + +int g1; +// since-cxx20-error@-1 {{redefinition of 'g1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:122 {{previous definition is here}} +void g2(); +// @-1 OK, a non-corresponding overload +enum Eg { + g3 + // MISSING-since-cxx20-error@-1 {{redefinition of 'g3'}} + // MISSING-since-cxx20-note@cwg1884_A.cppm:126 {{previous definition is here}} +}; +namespace g4 {} +// MISSING-since-cxx20-error@-1 {{redefinition of 'g4' as diff erent kind of symbol}} +// MISSING-since-cxx20-note@cwg1884_A.cppm:128 {{previous definition is here}} +struct g5; +// @-1 OK, types and function templates do not correspond +template <typename> +class g6; +// since-cxx20-error@-1 {{redefinition of 'g6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:132 {{previous definition is here}} +template <typename, typename> +int g7; +// since-cxx20-error@-1 {{redefinition of 'g7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:134 {{previous definition is here}} +template <typename T> +int g8<T, int>; +// since-cxx20-error@-1 {{no variable template matches specialization; did you mean to use 'g8' as function template instead?}} +template <typename> +using g9 = int; +// since-cxx20-error@-1 {{redefinition of 'g9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:138 {{previous definition is here}} +template <typename> +concept g10 = true; +// since-cxx20-error@-1 {{redefinition of 'g10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:140 {{previous definition is here}} + + +// Part H: matching against `template <typename, typename> int h;` +// --------------------------------------------------------------- + +int h1; +// since-cxx20-error@-1 {{redefinition of 'h1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:142 {{previous definition is here}} +void h2(); +// since-cxx20-error@-1 {{redefinition of 'h2' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:144 {{previous definition is here}} +enum Eh { + h3 + // since-cxx20-error@-1 {{redefinition of 'h3'}} + // since-cxx20-note@cwg1884_A.cppm:146 {{previous definition is here}} +}; +namespace h4 {} +// since-cxx20-error@-1 {{redefinition of 'h4' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:148 {{previous definition is here}} +struct h5; +// since-cxx20-error@-1 {{redefinition of 'h5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:150 {{previous definition is here}} +template <typename> +class h6; +// since-cxx20-error@-1 {{redefinition of 'h6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:152 {{previous definition is here}} +template <typename> +void h7(int); +// since-cxx20-error@-1 {{redefinition of 'h7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:154 {{previous definition is here}} +template <typename T> +int h8<T, int>; +// @-1 OK, partial specialization +template <typename> +using h9 = int; +// since-cxx20-error@-1 {{redefinition of 'h9' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:158 {{previous definition is here}} +template <typename> +concept h10 = true; +// since-cxx20-error@-1 {{redefinition of 'h10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:160 {{previous definition is here}} + + +// Part I: matching against `template <typename> using i = int;` +// ------------------------------------------------------------- + +int i1; +// since-cxx20-error@-1 {{redefinition of 'i1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:162 {{previous definition is here}} +void i2(); +// since-cxx20-error@-1 {{redefinition of 'i2' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:164 {{previous definition is here}} +enum Ei { + i3 + // since-cxx20-error@-1 {{redefinition of 'i3'}} + // since-cxx20-note@cwg1884_A.cppm:166 {{previous definition is here}} +}; +namespace i4 {} +// since-cxx20-error@-1 {{redefinition of 'i4' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:168 {{previous definition is here}} +struct i5; +// since-cxx20-error@-1 {{redefinition of 'i5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:170 {{previous definition is here}} +template <typename> +class i6; +// since-cxx20-error@-1 {{redefinition of 'i6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:172 {{previous definition is here}} +template <typename> +void i7(int); +// since-cxx20-error@-1 {{redefinition of 'i7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:174 {{previous definition is here}} +template <typename, typename> +int i8; +// since-cxx20-error@-1 {{redefinition of 'i8' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:176 {{previous definition is here}} +template <typename T> +int i9<T, int>; +// since-cxx20-error@-1 {{no variable template matches partial specialization}} +template <typename> +concept i10 = true; +// since-cxx20-error@-1 {{redefinition of 'i10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:180 {{previous definition is here}} + + +// Part J: matching against `template <typename> concept j = true;` +// ---------------------------------------------------------------- + +int j1; +// since-cxx20-error@-1 {{redefinition of 'j1' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:184 {{previous definition is here}} +void j2(); +// since-cxx20-error@-1 {{redefinition of 'j2' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:186 {{previous definition is here}} +enum Ej { + j3 + // since-cxx20-error@-1 {{redefinition of 'j3'}} + // since-cxx20-note@cwg1884_A.cppm:188 {{previous definition is here}} +}; +namespace j4 {} +// since-cxx20-error@-1 {{redefinition of 'j4' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:190 {{previous definition is here}} +struct j5; +// since-cxx20-error@-1 {{redefinition of 'j5' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:192 {{previous definition is here}} +template <typename> +class j6; +// since-cxx20-error@-1 {{redefinition of 'j6' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:194 {{previous definition is here}} +template <typename> +void j7(int); +// since-cxx20-error@-1 {{redefinition of 'j7' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:196 {{previous definition is here}} +template <typename, typename> +int j8; +// since-cxx20-error@-1 {{redefinition of 'j8' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:198 {{previous definition is here}} +template <typename T> +int j9<T, int>; +// since-cxx20-error@-1 {{no variable template matches partial specialization}} +template <typename> +using j10 = int; +// since-cxx20-error@-1 {{redefinition of 'j10' as diff erent kind of symbol}} +// since-cxx20-note@cwg1884_A.cppm:202 {{previous definition is here}} diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index b059492637bd5c..0fd2cd6b2d870c 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -547,6 +547,8 @@ namespace cwg1881 { // cwg1881: 7 static_assert(!__is_standard_layout(D), ""); } +// cwg1884 is in cwg1884.cpp + namespace cwg1890 { // cwg1890: no drafting 2018-06-04 // FIXME: current consensus for CWG2335 is that the examples are well-formed. namespace ex1 { diff --git a/clang/test/CXX/drs/cwg279.cpp b/clang/test/CXX/drs/cwg279.cpp new file mode 100644 index 00000000000000..3c63486cc0dd5e --- /dev/null +++ b/clang/test/CXX/drs/cwg279.cpp @@ -0,0 +1,53 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file --leading-lines %s %t +// RUN: %clang_cc1 -std=c++20 -pedantic-errors -fexceptions -fcxx-exceptions %t/cwg279_A.cppm -triple x86_64-unknown-unknown -emit-module-interface -o %t/cwg279_A.pcm +// RUN: %clang_cc1 -std=c++20 -verify=since-cxx20 -pedantic-errors -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown %t/cwg279.cpp -fmodule-file=cwg279_A=%t/cwg279_A.pcm +// RUN: %clang_cc1 -std=c++23 -pedantic-errors -fexceptions -fcxx-exceptions %t/cwg279_A.cppm -triple x86_64-unknown-unknown -emit-module-interface -o %t/cwg279_A.pcm +// RUN: %clang_cc1 -std=c++23 -verify=since-cxx20 -pedantic-errors -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown %t/cwg279.cpp -fmodule-file=cwg279_A=%t/cwg279_A.pcm +// RUN: %clang_cc1 -std=c++2c -pedantic-errors -fexceptions -fcxx-exceptions %t/cwg279_A.cppm -triple x86_64-unknown-unknown -emit-module-interface -o %t/cwg279_A.pcm +// RUN: %clang_cc1 -std=c++2c -verify=since-cxx20 -pedantic-errors -fexceptions -fcxx-exceptions -triple x86_64-unknown-unknown %t/cwg279.cpp -fmodule-file=cwg279_A=%t/cwg279_A.pcm + +// cwg279: no + +//--- cwg279_A.cppm +export module cwg279_A; + +export { +struct S; // #cwg279-S +extern S *q; // #cwg279-q + +struct S2 {}; // #cwg279-S2 +extern S2 *q2; // #cwg279-q2 + +struct S3 {}; // #cwg279-S3 +extern S3 *q3; // #cwg279-q3 +} // export + +//--- cwg279.cpp +import cwg279_A; + +// FIXME: We should use markers instead. They are less fragile, +// but -verify doesn't support them across modules yet. +// FIXME: This is well-formed. Previous "definition" is actually just a declaration. +typedef struct {} S; +// since-cxx20-error@-1 {{typedef redefinition with diff erent types ('struct S' vs 'S')}} +// since-cxx20-note@cwg279_A.cppm:17 {{previous definition is here}} +extern S *q; +// since-cxx20-error@-1 {{declaration of 'q' in the global module follows declaration in module cwg279_A}} +// since-cxx20-note@cwg279_A.cppm:18 {{previous declaration is here}} + +typedef struct {} S2; +// since-cxx20-error@-1 {{typedef redefinition with diff erent types ('struct S2' vs 'S2')}} +// since-cxx20-note@cwg279_A.cppm:20 {{previous definition is here}} +extern S2 *q2; +// since-cxx20-error@-1 {{declaration of 'q2' in the global module follows declaration in module cwg279_A}} +// since-cxx20-note@cwg279_A.cppm:21 {{previous declaration is here}} + +// FIXME: This is well-formed, because [basic.def.odr]/15 is satisfied. +struct S3 {}; +// since-cxx20-error@-1 {{redefinition of 'S3'}} +// since-cxx20-note@cwg279_A.cppm:23 {{previous definition is here}} +extern S3 *q3; +// since-cxx20-error@-1 {{declaration of 'q3' in the global module follows declaration in module cwg279_A}} +// since-cxx20-note@cwg279_A.cppm:24 {{previous declaration is here}} diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index 926cb19596026b..ec37b420880e28 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -1032,6 +1032,8 @@ namespace cwg277 { // cwg277: 3.1 static_assert(__enable_constant_folding(!intp()), ""); } +// cwg279 is in cwg279.cpp + namespace cwg280 { // cwg280: 2.9 typedef void f0(); typedef void f1(int); diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp index f20054c3701b1c..10c8d86ed16a0d 100644 --- a/clang/test/CXX/drs/cwg3xx.cpp +++ b/clang/test/CXX/drs/cwg3xx.cpp @@ -637,6 +637,8 @@ namespace cwg337 { // cwg337: yes struct B { virtual ~B() = 0; }; } +// cwg338: dup 1884 + namespace cwg339 { // cwg339: 2.8 template <int I> struct A { static const int value = I; }; diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 6640ed477a241e..186f7cc0ace546 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -1721,7 +1721,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/279.html">279</a></td> <td>CD6</td> <td>Correspondence of "names for linkage purposes"</td> - <td class="unknown" align="center">Unknown</td> + <td class="none" align="center">No</td> </tr> <tr id="280"> <td><a href="https://cplusplus.github.io/CWG/issues/280.html">280</a></td> @@ -2075,7 +2075,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/338.html">338</a></td> <td>CD6</td> <td>Enumerator name with linkage used as class name in other translation unit</td> - <td class="unknown" align="center">Unknown</td> + <td class="partial" align="center">Duplicate of <a href="#1884">1884</a></td> </tr> <tr id="339"> <td><a href="https://cplusplus.github.io/CWG/issues/339.html">339</a></td> @@ -11131,7 +11131,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/1884.html">1884</a></td> <td>CD6</td> <td>Unclear requirements for same-named external-linkage entities</td> - <td class="unknown" align="center">Unknown</td> + <td class="partial" align="center">Partial</td> </tr> <tr id="1885"> <td><a href="https://cplusplus.github.io/CWG/issues/1885.html">1885</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits