-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang][NFC] Add test for CWG issues about linkage in cross-TU context #113736
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) ChangesCWG279 Correspondence of "names for linkage purposes"P1787R6: 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 and > they both declare names with external linkage parts. Which means that both pairs of declarations of Then cases diverge. > — Each such definition shall consist of the same sequence of tokens, <...> Because per [class.pre/2], class definition is class-specifier, which includes class-head, but class-head is different between definitions. CWG338 Enumerator name with linkage used as class name in other translation unitP1787R6: 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 Unclear requirements for same-named external-linkage entitiesP1787R6: [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. > 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 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 This is corresponding overloads now, defined in [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 tests [[basic.link]/11](https://eel.is/c++draft/basic.link#11) from the following standpoint: 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 Patch is 29.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113736.diff 6 Files Affected:
diff --git a/clang/test/CXX/drs/cwg1884.cpp b/clang/test/CXX/drs/cwg1884.cpp
new file mode 100644
index 00000000000000..d8fa9c4373765c
--- /dev/null
+++ b/clang/test/CXX/drs/cwg1884.cpp
@@ -0,0 +1,548 @@
+// 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
+
+// _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 different 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 differ 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 'k'.
+// 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 a;
+void b();
+enum E { c };
+namespace d {}
+struct e;
+class f;
+template <typename>
+class g;
+template <typename>
+void h(int);
+template <typename, typename>
+int i;
+template <typename>
+using j = int;
+template <typename>
+concept k = true;
+} // export
+
+
+//--- cwg1884.cpp
+import cwg1884_A;
+
+// int a;
+
+void a();
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+enum Ea {
+ a
+ // since-cxx20-error@-1 {{redefinition of 'a'}}
+ // since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+};
+namespace a {} // #cwg1884-namespace-a
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+struct a;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-a {{previous definition is here}}
+class a;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-a {{previous definition is here}}
+template <typename>
+class a;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+template <typename>
+void a(int);
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+template <typename, typename>
+int a;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+template <typename T>
+int a<T, int>;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+// since-cxx20-error@-3 {{expected ';' after top level declarator}}
+template <typename>
+using a = int;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+template <typename>
+concept a = true;
+// since-cxx20-error@-1 {{redefinition of 'a' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:42 {{previous definition is here}}
+
+
+// void b();
+
+int b;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:43 {{previous definition is here}}
+enum Eb {
+ b
+ // since-cxx20-error@-1 {{redefinition of 'b'}}
+ // since-cxx20-note@cwg1884_A.cppm:43 {{previous definition is here}}
+};
+namespace b {} // #cwg1884-namespace-b
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:43 {{previous definition is here}}
+struct b;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-b {{previous definition is here}}
+class b;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-b {{previous definition is here}}
+template <typename>
+class b;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:43 {{previous definition is here}}
+template <typename>
+void b(int); // #cwg1884-func-template-b
+// @-1 OK, a non-corresponding overload
+template <typename, typename>
+int b;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-func-template-b {{previous definition is here}}
+template <typename T>
+int b<T, int>;
+// since-cxx20-error@-1 {{no variable template matches specialization; did you mean to use 'b' as function template instead?}}
+template <typename>
+using b = int;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:43 {{previous definition is here}}
+template <typename>
+concept b = true;
+// since-cxx20-error@-1 {{redefinition of 'b' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-func-template-b {{previous definition is here}}
+
+
+// enum E { c };
+
+int c;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+void c();
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+namespace c {} // #cwg1884-namespace-c
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+struct c;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-c {{previous definition is here}}
+class c;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-c {{previous definition is here}}
+template <typename>
+class c;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+template <typename>
+void c(int);
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+template <typename, typename>
+int c;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+template <typename T>
+int c<T, int>;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+// since-cxx20-error@-3 {{expected ';' after top level declarator}}
+template <typename>
+using c = int;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+template <typename>
+concept c = true;
+// since-cxx20-error@-1 {{redefinition of 'c' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:44 {{previous definition is here}}
+
+
+// namespace d {};
+
+int d;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+void d();
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+enum Ed {
+ d
+ // since-cxx20-error@-1 {{redefinition of 'd'}}
+ // since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+};
+struct d;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+class d;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+template <typename>
+class d;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+template <typename>
+void d(int);
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+template <typename, typename>
+int d;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+template <typename T>
+int d<T, int>;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+// since-cxx20-error@-3 {{expected ';' after top level declarator}}
+template <typename>
+using d = int;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+template <typename>
+concept d = true;
+// since-cxx20-error@-1 {{redefinition of 'd' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:45 {{previous definition is here}}
+
+
+// struct e;
+
+int e; // #cwg1884-int-e
+// @-1 OK, types and variables do not correspond
+void e();
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+enum Ee {
+ e
+ // since-cxx20-error@-1 {{redefinition of 'e'}}
+ // since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+};
+namespace e {} // #cwg1884-namespace-e
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+class e;
+// since-cxx20-error@-1 {{declaration of 'e' in the global module follows declaration in module cwg1884_A}}
+// since-cxx20-note@cwg1884_A.cppm:46 {{previous declaration is here}}
+template <typename>
+class e;
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+template <typename>
+void e(int);
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+template <typename, typename>
+int e;
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+template <typename T>
+int e<T, int>;
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+// since-cxx20-error@-3 {{expected ';' after top level declarator}}
+template <typename>
+using e = int;
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+template <typename>
+concept e = true;
+// since-cxx20-error@-1 {{redefinition of 'e' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-e {{previous definition is here}}
+
+
+// class f;
+
+int f; // #cwg1884-int-f
+// @-1 OK, types and variables do not correspond
+void f();
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+enum Ef {
+ f
+ // since-cxx20-error@-1 {{redefinition of 'f'}}
+ // since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+};
+namespace f {} // #cwg1884-namespace-f
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+struct f;
+// since-cxx20-error@-1 {{declaration of 'f' in the global module follows declaration in module cwg1884_A}}
+// since-cxx20-note@cwg1884_A.cppm:47 {{previous declaration is here}}
+template <typename>
+class f;
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+template <typename>
+void f(int);
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+template <typename, typename>
+int f;
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+template <typename T>
+int f<T, int>;
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+// since-cxx20-error@-3 {{expected ';' after top level declarator}}
+template <typename>
+using f = int;
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+template <typename>
+concept f = true;
+// since-cxx20-error@-1 {{redefinition of 'f' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-int-f {{previous definition is here}}
+
+
+// template <typename>
+// class g;
+
+int g;
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+void g();
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+enum Eg {
+ g
+ // since-cxx20-error@-1 {{redefinition of 'g'}}
+ // since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+};
+namespace g {}
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+struct g;
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+class g;
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+template <typename>
+void g(int);
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+template <typename, typename>
+int g;
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+template <typename T>
+int g<T, int>;
+// since-cxx20-error@-1 {{no variable template matches partial specialization}}
+template <typename>
+using g = int;
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+template <typename>
+concept g = true;
+// since-cxx20-error@-1 {{redefinition of 'g' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:49 {{previous definition is here}}
+
+
+// template <typename>
+// void h(int);
+
+int h;
+// since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:51 {{previous definition is here}}
+void h(); // #cwg1884-function-f
+// @-1 OK, a non-corresponding overload
+enum Eh {
+ h
+ // FIXME-since-cxx20-error@-1 {{redefinition of 'h'}}
+ // FIXME-since-cxx20-note@cwg1884_A.cppm:51 {{previous definition is here}}
+};
+namespace h {} // #cwg1884-namespace-h
+// FIXME-since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// FIXME-since-cxx20-note@cwg1884_A.cppm:51 {{previous definition is here}}
+struct h;
+// since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-h {{previous definition is here}}
+class h;
+// since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-h {{previous definition is here}}
+template <typename>
+class h;
+// FIXME-since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// FIXME-since-cxx20-note@cwg1884_A.cppm:51 {{previous definition is here}}
+template <typename, typename>
+int h;
+// since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-namespace-h {{previous definition is here}}
+template <typename T>
+int h<T, int>;
+// since-cxx20-error@-1 {{no variable template matches specialization; did you mean to use 'h' as function template instead?}}
+template <typename>
+using h = int;
+// since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:51 {{previous definition is here}}
+template <typename>
+concept h = true;
+// since-cxx20-error@-1 {{redefinition of 'h' as different kind of symbol}}
+// since-cxx20-note@#cwg1884-function-f {{previous definition is here}}
+
+
+// template <typename, typename>
+// int i;
+
+int i;
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+void i();
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+enum Ei {
+ i
+ // since-cxx20-error@-1 {{redefinition of 'i'}}
+ // since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+};
+namespace i {}
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+struct i;
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+class i;
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+template <typename>
+class i;
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+template <typename>
+void i(int);
+// since-cxx20-error@-1 {{redefinition of 'i' as different kind of symbol}}
+// since-cxx20-note@cwg1884_A.cppm:53 {{previous definition is here}}
+template <typename T>
+int i<T, int>; // OK, partial specia...
[truncated]
|
@ChuanqiXu9 Can you take a quick look to make sure I'm not tripping over any modules mines in those tests? |
Also, having to use absolute line numbers in expected directives sucks. I hope I wouldn't need to change any comments at the top of CWG1884 test. At some point I'll make |
CWG279 Correspondence of "names for linkage purposes"
P1787R6:
In both cases discussed in the issue, declaration matching succeeds per [basic.link]/8, thanks to the
and
parts. Which means that both pairs of declarations of
S
andS2
declare the same entity. [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, hence it's well-formed. WhereasS2
is a pair of two definitions, so they are subjects to [basic.def.odr]/15, which they do not satisfy due to the violation of the following requirement:Because per [class.pre/2], class definition is class-specifier, which includes class-head, but class-head is different between definitions.
CWG338 Enumerator name with linkage used as class name in other translation unit
P1787R6:
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 Unclear requirements for same-named external-linkage entities
P1787R6:
[basic.link]/9 quoted in the issue is now split into several pieces.
I believe this is corresponding declarations now, defined in [basic.scope.scope]/4.
This is covered by [basic.link]/11 after it's determined by [basic.link]/8 that two declarations declare the same entity.
Most of this is covered by [basic.link]/8.
This is corresponding overloads now, defined in [basic.scope.scope]/4.
This is addressed by "have the same target scope" part of [basic.link]/8.
The tests basically tests [basic.link]/11 from the following standpoint:
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).