[clang] d83485a - [clang][NFC] Add test for CWG issues about linkage in cross-TU context (#113736)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 28 07:48:27 PDT 2024
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 at -1 {{redefinition of 'a1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:42 {{previous definition is here}}
+enum Ea {
+ a2
+ // since-cxx20-error at -1 {{redefinition of 'a2'}}
+ // since-cxx20-note at cwg1884_A.cppm:43 {{previous definition is here}}
+};
+namespace a3 {}
+// since-cxx20-error at -1 {{redefinition of 'a3' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'a5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:46 {{previous definition is here}}
+template <typename>
+void a6(int);
+// since-cxx20-error at -1 {{redefinition of 'a6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:47 {{previous definition is here}}
+template <typename, typename>
+int a7;
+// since-cxx20-error at -1 {{redefinition of 'a7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:48 {{previous definition is here}}
+template <typename T>
+int a8<T, int>;
+// since-cxx20-error at -1 {{redefinition of 'a8' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:49 {{previous definition is here}}
+// since-cxx20-error at -3 {{expected ';' after top level declarator}}
+template <typename>
+using a9 = int;
+// since-cxx20-error at -1 {{redefinition of 'a9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:50 {{previous definition is here}}
+template <typename>
+concept a10 = true;
+// since-cxx20-error at -1 {{redefinition of 'a10' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:51 {{previous definition is here}}
+// For variables, type has to match as well.
+long a11;
+// since-cxx20-error at -1 {{redefinition of 'a11' with a
diff erent type: 'long' vs 'int'}}
+// since-cxx20-note at cwg1884_A.cppm:52 {{previous definition is here}}
+
+
+// Part B: matching against `void b();`
+// ------------------------------------
+
+int b1;
+// since-cxx20-error at -1 {{redefinition of 'b1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:53 {{previous definition is here}}
+enum Eb {
+ b2
+ // since-cxx20-error at -1 {{redefinition of 'b2'}}
+ // since-cxx20-note at cwg1884_A.cppm:54 {{previous definition is here}}
+};
+namespace b3 {} // #cwg1884-namespace-b
+// since-cxx20-error at -1 {{redefinition of 'b3' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'b5' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'b7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:59 {{previous definition is here}}
+template <typename T>
+int b8<T, int>;
+// since-cxx20-error at -1 {{no variable template matches partial specialization}}
+template <typename>
+using b9 = int;
+// since-cxx20-error at -1 {{redefinition of 'b9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:61 {{previous definition is here}}
+template <typename>
+concept b10 = true;
+// since-cxx20-error at -1 {{redefinition of 'b10' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{declaration of 'b11' in the global module follows declaration in module cwg1884_A}}
+// since-cxx20-note at cwg1884_A.cppm:63 {{previous declaration is here}}
+
+
+// Part C: matching against `enum E { c };`
+// ----------------------------------------
+
+int c1;
+// since-cxx20-error at -1 {{redefinition of 'c1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:65 {{previous definition is here}}
+void c2();
+// since-cxx20-error at -1 {{redefinition of 'c2' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:66 {{previous definition is here}}
+namespace c3 {}
+// since-cxx20-error at -1 {{redefinition of 'c3' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'c5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:69 {{previous definition is here}}
+template <typename>
+void c6(int);
+// since-cxx20-error at -1 {{redefinition of 'c6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:70 {{previous definition is here}}
+template <typename, typename>
+int c7;
+// since-cxx20-error at -1 {{redefinition of 'c7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:71 {{previous definition is here}}
+template <typename T>
+int c8<T, int>;
+// since-cxx20-error at -1 {{redefinition of 'c8' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:72 {{previous definition is here}}
+// since-cxx20-error at -3 {{expected ';' after top level declarator}}
+template <typename>
+using c9 = int;
+// since-cxx20-error at -1 {{redefinition of 'c9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:73 {{previous definition is here}}
+template <typename>
+concept c10 = true;
+// since-cxx20-error at -1 {{redefinition of 'c10' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:74 {{previous definition is here}}
+
+
+// Part D: matching against `namespace d {};`
+// ------------------------------------------
+
+int d1;
+// since-cxx20-error at -1 {{redefinition of 'd1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:76 {{previous definition is here}}
+void d2();
+// since-cxx20-error at -1 {{redefinition of 'd2' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:77 {{previous definition is here}}
+enum Ed {
+ d3
+ // since-cxx20-error at -1 {{redefinition of 'd3'}}
+ // since-cxx20-note at cwg1884_A.cppm:78 {{previous definition is here}}
+};
+struct d4;
+// since-cxx20-error at -1 {{redefinition of 'd4' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:79 {{previous definition is here}}
+template <typename>
+class d5;
+// since-cxx20-error at -1 {{redefinition of 'd5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:80 {{previous definition is here}}
+template <typename>
+void d6(int);
+// since-cxx20-error at -1 {{redefinition of 'd6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:81 {{previous definition is here}}
+template <typename, typename>
+int d7;
+// since-cxx20-error at -1 {{redefinition of 'd7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:82 {{previous definition is here}}
+template <typename T>
+int d8<T, int>;
+// since-cxx20-error at -1 {{redefinition of 'd8' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:83 {{previous definition is here}}
+// since-cxx20-error at -3 {{expected ';' after top level declarator}}
+template <typename>
+using d9 = int;
+// since-cxx20-error at -1 {{redefinition of 'd9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:84 {{previous definition is here}}
+template <typename>
+concept d10 = true;
+// since-cxx20-error at -1 {{redefinition of 'd10' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'e4' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:89 {{previous definition is here}}
+template <typename>
+class e5;
+// since-cxx20-error at -1 {{redefinition of 'e5' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'e7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:92 {{previous definition is here}}
+template <typename T>
+int e8<T, int>;
+// since-cxx20-error at -1 {{redefinition of 'e8' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:93 {{previous definition is here}}
+// since-cxx20-error at -3 {{expected ';' after top level declarator}}
+template <typename>
+using e9 = int;
+// since-cxx20-error at -1 {{redefinition of 'e9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:94 {{previous definition is here}}
+template <typename>
+concept e10 = true;
+// since-cxx20-error at -1 {{redefinition of 'e10' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{declaration of 'e11' in the global module follows declaration in module cwg1884_A}}
+// since-cxx20-note at cwg1884_A.cppm:96 {{previous declaration is here}}
+union e12;
+// since-cxx20-error at -1 {{use of 'e12' with tag type that does not match previous declaration}}
+// since-cxx20-note at cwg1884_A.cppm:97 {{previous use is here}}
+// since-cxx20-error at -3 {{declaration of 'e12' in the global module follows declaration in module cwg1884_A}}
+// since-cxx20-note at cwg1884_A.cppm:97 {{previous declaration is here}}
+enum e13 {};
+// since-cxx20-error at -1 {{use of 'e13' with tag type that does not match previous declaration}}
+// since-cxx20-note at cwg1884_A.cppm:98 {{previous use is here}}
+
+
+// Part F: matching against `template <typename> class f;`
+// -------------------------------------------------------
+
+int f1;
+// since-cxx20-error at -1 {{redefinition of 'f1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:100 {{previous definition is here}}
+void f2();
+// since-cxx20-error at -1 {{redefinition of 'f2' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:102 {{previous definition is here}}
+enum Ef {
+ f3
+ // since-cxx20-error at -1 {{redefinition of 'f3'}}
+ // since-cxx20-note at cwg1884_A.cppm:104 {{previous definition is here}}
+};
+namespace f4 {}
+// since-cxx20-error at -1 {{redefinition of 'f4' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:106 {{previous definition is here}}
+struct f5;
+// since-cxx20-error at -1 {{redefinition of 'f5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:108 {{previous definition is here}}
+template <typename>
+void f6(int);
+// since-cxx20-error at -1 {{redefinition of 'f6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:110 {{previous definition is here}}
+template <typename, typename>
+int f7;
+// since-cxx20-error at -1 {{redefinition of 'f7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:112 {{previous definition is here}}
+template <typename T>
+int f8<T, int>;
+// since-cxx20-error at -1 {{no variable template matches partial specialization}}
+template <typename>
+using f9 = int;
+// since-cxx20-error at -1 {{redefinition of 'f9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:116 {{previous definition is here}}
+template <typename>
+concept f10 = true;
+// since-cxx20-error at -1 {{redefinition of 'f10' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:118 {{previous definition is here}}
+
+
+// Part G: matching against `template <typename> void g(int);`
+// -----------------------------------------------------------
+
+int g1;
+// since-cxx20-error at -1 {{redefinition of 'g1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:122 {{previous definition is here}}
+void g2();
+// @-1 OK, a non-corresponding overload
+enum Eg {
+ g3
+ // MISSING-since-cxx20-error at -1 {{redefinition of 'g3'}}
+ // MISSING-since-cxx20-note at cwg1884_A.cppm:126 {{previous definition is here}}
+};
+namespace g4 {}
+// MISSING-since-cxx20-error at -1 {{redefinition of 'g4' as
diff erent kind of symbol}}
+// MISSING-since-cxx20-note at 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 at -1 {{redefinition of 'g6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:132 {{previous definition is here}}
+template <typename, typename>
+int g7;
+// since-cxx20-error at -1 {{redefinition of 'g7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:134 {{previous definition is here}}
+template <typename T>
+int g8<T, int>;
+// since-cxx20-error at -1 {{no variable template matches specialization; did you mean to use 'g8' as function template instead?}}
+template <typename>
+using g9 = int;
+// since-cxx20-error at -1 {{redefinition of 'g9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:138 {{previous definition is here}}
+template <typename>
+concept g10 = true;
+// since-cxx20-error at -1 {{redefinition of 'g10' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:140 {{previous definition is here}}
+
+
+// Part H: matching against `template <typename, typename> int h;`
+// ---------------------------------------------------------------
+
+int h1;
+// since-cxx20-error at -1 {{redefinition of 'h1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:142 {{previous definition is here}}
+void h2();
+// since-cxx20-error at -1 {{redefinition of 'h2' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:144 {{previous definition is here}}
+enum Eh {
+ h3
+ // since-cxx20-error at -1 {{redefinition of 'h3'}}
+ // since-cxx20-note at cwg1884_A.cppm:146 {{previous definition is here}}
+};
+namespace h4 {}
+// since-cxx20-error at -1 {{redefinition of 'h4' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:148 {{previous definition is here}}
+struct h5;
+// since-cxx20-error at -1 {{redefinition of 'h5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:150 {{previous definition is here}}
+template <typename>
+class h6;
+// since-cxx20-error at -1 {{redefinition of 'h6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:152 {{previous definition is here}}
+template <typename>
+void h7(int);
+// since-cxx20-error at -1 {{redefinition of 'h7' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'h9' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:158 {{previous definition is here}}
+template <typename>
+concept h10 = true;
+// since-cxx20-error at -1 {{redefinition of 'h10' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:160 {{previous definition is here}}
+
+
+// Part I: matching against `template <typename> using i = int;`
+// -------------------------------------------------------------
+
+int i1;
+// since-cxx20-error at -1 {{redefinition of 'i1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:162 {{previous definition is here}}
+void i2();
+// since-cxx20-error at -1 {{redefinition of 'i2' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:164 {{previous definition is here}}
+enum Ei {
+ i3
+ // since-cxx20-error at -1 {{redefinition of 'i3'}}
+ // since-cxx20-note at cwg1884_A.cppm:166 {{previous definition is here}}
+};
+namespace i4 {}
+// since-cxx20-error at -1 {{redefinition of 'i4' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:168 {{previous definition is here}}
+struct i5;
+// since-cxx20-error at -1 {{redefinition of 'i5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:170 {{previous definition is here}}
+template <typename>
+class i6;
+// since-cxx20-error at -1 {{redefinition of 'i6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:172 {{previous definition is here}}
+template <typename>
+void i7(int);
+// since-cxx20-error at -1 {{redefinition of 'i7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:174 {{previous definition is here}}
+template <typename, typename>
+int i8;
+// since-cxx20-error at -1 {{redefinition of 'i8' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:176 {{previous definition is here}}
+template <typename T>
+int i9<T, int>;
+// since-cxx20-error at -1 {{no variable template matches partial specialization}}
+template <typename>
+concept i10 = true;
+// since-cxx20-error at -1 {{redefinition of 'i10' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:180 {{previous definition is here}}
+
+
+// Part J: matching against `template <typename> concept j = true;`
+// ----------------------------------------------------------------
+
+int j1;
+// since-cxx20-error at -1 {{redefinition of 'j1' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:184 {{previous definition is here}}
+void j2();
+// since-cxx20-error at -1 {{redefinition of 'j2' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:186 {{previous definition is here}}
+enum Ej {
+ j3
+ // since-cxx20-error at -1 {{redefinition of 'j3'}}
+ // since-cxx20-note at cwg1884_A.cppm:188 {{previous definition is here}}
+};
+namespace j4 {}
+// since-cxx20-error at -1 {{redefinition of 'j4' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:190 {{previous definition is here}}
+struct j5;
+// since-cxx20-error at -1 {{redefinition of 'j5' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:192 {{previous definition is here}}
+template <typename>
+class j6;
+// since-cxx20-error at -1 {{redefinition of 'j6' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:194 {{previous definition is here}}
+template <typename>
+void j7(int);
+// since-cxx20-error at -1 {{redefinition of 'j7' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:196 {{previous definition is here}}
+template <typename, typename>
+int j8;
+// since-cxx20-error at -1 {{redefinition of 'j8' as
diff erent kind of symbol}}
+// since-cxx20-note at cwg1884_A.cppm:198 {{previous definition is here}}
+template <typename T>
+int j9<T, int>;
+// since-cxx20-error at -1 {{no variable template matches partial specialization}}
+template <typename>
+using j10 = int;
+// since-cxx20-error at -1 {{redefinition of 'j10' as
diff erent kind of symbol}}
+// since-cxx20-note at 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 at -1 {{typedef redefinition with
diff erent types ('struct S' vs 'S')}}
+// since-cxx20-note at cwg279_A.cppm:17 {{previous definition is here}}
+extern S *q;
+// since-cxx20-error at -1 {{declaration of 'q' in the global module follows declaration in module cwg279_A}}
+// since-cxx20-note at cwg279_A.cppm:18 {{previous declaration is here}}
+
+typedef struct {} S2;
+// since-cxx20-error at -1 {{typedef redefinition with
diff erent types ('struct S2' vs 'S2')}}
+// since-cxx20-note at cwg279_A.cppm:20 {{previous definition is here}}
+extern S2 *q2;
+// since-cxx20-error at -1 {{declaration of 'q2' in the global module follows declaration in module cwg279_A}}
+// since-cxx20-note at 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 at -1 {{redefinition of 'S3'}}
+// since-cxx20-note at cwg279_A.cppm:23 {{previous definition is here}}
+extern S3 *q3;
+// since-cxx20-error at -1 {{declaration of 'q3' in the global module follows declaration in module cwg279_A}}
+// since-cxx20-note at 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>
More information about the cfe-commits
mailing list