Skip to content
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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Endilll
Copy link
Contributor

@Endilll Endilll commented Oct 25, 2024

CWG279 Correspondence of "names for linkage purposes"

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, 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 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. Whereas S2 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:

— 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 unit

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 Unclear requirements for same-named external-linkage entities

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.

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 after it's determined by [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.

— 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.

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.

The tests basically tests [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).

@Endilll Endilll requested a review from cor3ntin October 25, 2024 20:06
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Oct 25, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 25, 2024

@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)

Changes

CWG279 Correspondence of "names for linkage purposes"

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 causes 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], 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:
> 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 Unclear requirements for same-named external-linkage entities

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.

> 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.

> 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:
> 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).


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:

  • (added) clang/test/CXX/drs/cwg1884.cpp (+548)
  • (modified) clang/test/CXX/drs/cwg18xx.cpp (+2)
  • (added) clang/test/CXX/drs/cwg279.cpp (+42)
  • (modified) clang/test/CXX/drs/cwg2xx.cpp (+2)
  • (modified) clang/test/CXX/drs/cwg3xx.cpp (+2)
  • (modified) clang/www/cxx_dr_status.html (+3-3)
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]

@Endilll
Copy link
Contributor Author

Endilll commented Oct 25, 2024

@ChuanqiXu9 Can you take a quick look to make sure I'm not tripping over any modules mines in those tests?
This is the PR I promised to pull you in almost 2 weeks ago (sorry for the delay 😄).

@Endilll
Copy link
Contributor Author

Endilll commented Oct 25, 2024

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 -verify markers work for cross-TU scenarios.

@Endilll Endilll added the c++ label Oct 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants