Author: Matheus Izvekov Date: 2026-05-14T15:05:03-03:00 New Revision: 28749538069bb018f1f327b2fe757e216ac80cf1
URL: https://github.com/llvm/llvm-project/commit/28749538069bb018f1f327b2fe757e216ac80cf1 DIFF: https://github.com/llvm/llvm-project/commit/28749538069bb018f1f327b2fe757e216ac80cf1.diff LOG: [clang] NFC: add new test cases involving bugs in getTemplateInstantiationArgs (#197755) The new test files come from 2bb3d3a3f32ffaef3d9b6a27db7f1941f0cb1136, which was reverted a long time ago. These have a couple I had to #ifdef out because they expose crashes. The other test cases are preparatory for a future PR. Also some changes are pure whitespace cleanup. Added: clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp Modified: clang/test/AST/ast-dump-linkage-internal.cpp clang/test/AST/ast-dump-linkage.cpp clang/test/SemaCXX/friend.cpp clang/test/SemaTemplate/concepts-out-of-line-def.cpp clang/test/SemaTemplate/friend.cpp Removed: ################################################################################ diff --git a/clang/test/AST/ast-dump-linkage-internal.cpp b/clang/test/AST/ast-dump-linkage-internal.cpp index 49f5b3124450b..6b961301c4abb 100644 --- a/clang/test/AST/ast-dump-linkage-internal.cpp +++ b/clang/test/AST/ast-dump-linkage-internal.cpp @@ -91,7 +91,7 @@ int TemplatedVarSpec = TemplatedVar<int>; void FuncDef() { // CHECK: | |-FunctionDecl {{.*}} FuncDef 'void ()' internal-linkage - + extern int Int; // CHECK: | | | `-VarDecl {{.*}} Int 'int' extern internal-linkage extern const int ConstInt; @@ -176,7 +176,7 @@ struct Struct { friend struct Known::FriendStruct; // CHECK: | | |-FriendDecl {{.*}} 'struct Known::FriendStruct' - + template <typename> friend struct Known::FriendStructTemplate; // CHECK: | | |-FriendDecl {{.*}} col:{{[0-9]*$}} @@ -215,7 +215,7 @@ struct Struct { friend void Known::FuncDecl(); // CHECK: | | |-FriendDecl {{.*}} col:{{[0-9]*$}} // CHECK: | | | `-FunctionDecl {{.*}} friend FuncDecl 'void ()' internal-linkage - + template <typename> friend void Known::TemplatedFuncDecl(); // CHECK: | | |-FriendDecl {{.*}} col:{{[0-9]*$}} @@ -333,7 +333,7 @@ struct StructTemplate { friend struct Known::FriendStruct; // CHECK: | | |-FriendDecl {{.*}} 'struct Known::FriendStruct' - + template <typename> friend struct Known::FriendStructTemplate; // CHECK: | | |-FriendDecl {{.*}} col:{{[0-9]*$}} @@ -376,7 +376,7 @@ struct StructTemplate { // CHECK: | | | `-FunctionDecl {{.*}} friend_undeclared FuncDecl 'void ()' internal-linkage // FIXME: friend_undeclared is the wrong answer; friends with qualified-id // have to correspond to one or more declarations found by name lookup. - + template <typename> friend void Known::TemplatedFuncDecl(); // CHECK: | | |-FriendDecl {{.*}} col:{{[0-9]*$}} diff --git a/clang/test/AST/ast-dump-linkage.cpp b/clang/test/AST/ast-dump-linkage.cpp index 98ff532be0f03..18228eb4e8c21 100644 --- a/clang/test/AST/ast-dump-linkage.cpp +++ b/clang/test/AST/ast-dump-linkage.cpp @@ -88,7 +88,7 @@ int TemplatedVarSpec = TemplatedVar<int>; void FuncDef() { // CHECK: |-FunctionDecl {{.*}} FuncDef 'void ()' external-linkage - + extern int Int; // CHECK: | | `-VarDecl {{.*}} Int 'int' extern external-linkage extern const int ConstInt; @@ -170,11 +170,11 @@ struct Struct { // CHECK: | | `-ClassTemplateDecl {{.*}} friend_undeclared UnknownFriendStructTemplate external-linkage // CHECK: | | `-CXXRecordDecl {{.*}} struct UnknownFriendStructTemplate // FIXME: Friend declarations do not bind names, so they cannot have linkage. - + friend struct Known::FriendStruct; // CHECK: | |-FriendDecl {{.*}} 'struct Known::FriendStruct' // FIXME: Where is CXXRecordDecl? - + template <typename> friend struct Known::FriendStructTemplate; // CHECK: | |-FriendDecl {{.*}} col:{{[0-9]*$}} @@ -336,10 +336,10 @@ struct StructTemplate { // CHECK: | | `-ClassTemplateDecl {{.*}} friend_undeclared UnknownFriendStructTemplate external-linkage // CHECK: | | `-CXXRecordDecl {{.*}} struct UnknownFriendStructTemplate // FIXME: Friend declarations do not bind names, so they cannot have linkage. - + friend struct Known::FriendStruct; // CHECK: | |-FriendDecl {{.*}} 'struct Known::FriendStruct' - + template <typename> friend struct Known::FriendStructTemplate; // CHECK: | |-FriendDecl {{.*}} col:{{[0-9]*$}} diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp new file mode 100644 index 0000000000000..fefe86a448b18 --- /dev/null +++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp @@ -0,0 +1,188 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s + +template<typename T> +concept D = true; + +template<typename T> +struct A { // expected-note {{defined here}} + template<typename U, bool V> + void f() requires V; + + template<> + void f<short, true>(); + + template<D U> + void g(); + + template<typename U, bool V> requires V + struct B; + // expected-note@-2 {{previous template declaration is here}} + + template<typename U, bool V> requires V + struct B<U*, V>; + + template<> + struct B<short, true>; + + template<D U> + struct C; + // expected-note@-2 {{previous template declaration is here}} + + template<D U> + struct C<U*>; + + template<typename U, bool V> requires V + static int x; + // expected-note@-2 {{previous template declaration is here}} + + template<typename U, bool V> requires V + static int x<U*, V>; + + template<> + int x<short, true>; + + template<D U> + static int y; + // expected-note@-2 {{previous template declaration is here}} + + template<D U> + static int y<U*>; +}; + +template<typename T> +template<typename U, bool V> +void A<T>::f() requires V { } + +template<typename T> +template<D U> +void A<T>::g() { } + +template<typename T> +template<typename U, bool V> requires V +struct A<T>::B { }; + +template<typename T> +template<typename U, bool V> requires V +struct A<T>::B<U*, V> { }; + +template<typename T> +template<typename U, bool V> requires V +struct A<T>::B<U&, V> { }; + +template<typename T> +template<D U> +struct A<T>::C { }; + +template<typename T> +template<D U> +struct A<T>::C<U*> { }; + +template<typename T> +template<typename U, bool V> requires V +int A<T>::x = 0; + +template<typename T> +template<typename U, bool V> requires V +int A<T>::x<U*, V> = 0; + +template<typename T> +template<typename U, bool V> requires V +int A<T>::x<U&, V> = 0; + +template<typename T> +template<D U> +int A<T>::y = 0; + +template<typename T> +template<D U> +int A<T>::y<U*> = 0; + +// FIXME: This should be accepted. +template<> +template<typename U, bool V> +void A<short>::f() requires V; +// expected-error@-1 {{out-of-line declaration of 'f' does not match any declaration in 'A<short>'}} + +template<> +template<> +void A<short>::f<int, true>(); + +template<> +template<> +void A<void>::f<int, true>(); + +template<> +template<D U> +void A<short>::g(); + +// FIXME: This should be accepted. +template<> +template<typename U, bool V> requires V +struct A<int>::B; +// expected-error@-2 {{requires clause diff ers in template redeclaration}} + +template<> +template<> +struct A<int>::B<int, true>; + +template<> +template<> +struct A<void>::B<int, true>; + +template<> +template<typename U, bool V> requires V +struct A<int>::B<U*, V>; + +template<> +template<typename U, bool V> requires V +struct A<int>::B<U&, V>; + +// FIXME: This should be accepted. +template<> +template<D U> +struct A<int>::C; +// expected-error@-2 {{type constraint diff ers in template redeclaration}} + +template<> +template<D U> +struct A<int>::C<U*>; + +template<> +template<D U> +struct A<int>::C<U&>; + +// FIXME: This should be accepted. +template<> +template<typename U, bool V> requires V +int A<long>::x; +// expected-error@-2 {{requires clause diff ers in template redeclaration}} + +template<> +template<> +int A<long>::x<int, true>; + +template<> +template<> +int A<void>::x<int, true>; + +template<> +template<typename U, bool V> requires V +int A<long>::x<U*, V>; + +template<> +template<typename U, bool V> requires V +int A<long>::x<U&, V>; + +// FIXME: This should be accepted. +template<> +template<D U> +int A<long>::y; +// expected-error@-2 {{type constraint diff ers in template redeclaration}} + +template<> +template<D U> +int A<long>::y<U*>; + +template<> +template<D U> +int A<long>::y<U&>; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp new file mode 100644 index 0000000000000..5bb5de88a6fc2 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp @@ -0,0 +1,234 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +namespace Undefined { + template<typename T> + struct A { + template<typename U> + static constexpr int f(); // expected-note {{declared here}} + + template<typename U> + static const int x; // expected-note {{declared here}} + + template<typename U> + static const int x<U*>; // expected-note {{declared here}} + + template<typename U> + struct B; // expected-note {{template is declared here}} + + template<typename U> + struct B<U*>; // expected-note {{template is declared here}} + }; + + template<> + template<typename U> + constexpr int A<short>::f() { + return A<long>::f<U>(); + } + + template<> + template<typename U> + constexpr int A<short>::x = A<long>::x<U>; + + template<> + template<typename U> + constexpr int A<short>::x<U*> = A<long>::x<U*>; + + template<> + template<typename U> + struct A<short>::B<U*> { + static constexpr int y = A<long>::B<U*>::y; + }; + + template<> + template<typename U> + struct A<short>::B { + static constexpr int y = A<long>::B<U>::y; + }; + + template<> + template<typename U> + constexpr int A<long>::f() { + return 1; + } + + template<> + template<typename U> + constexpr int A<long>::x = 1; + + template<> + template<typename U> + constexpr int A<long>::x<U*> = 2; + + template<> + template<typename U> + struct A<long>::B { + static constexpr int y = 1; + }; + + template<> + template<typename U> + struct A<long>::B<U*> { + static constexpr int y = 2; + }; + + static_assert(A<int>::f<int>() == 0); // expected-error {{static assertion expression is not an integral constant expression}} + // expected-note@-1 {{undefined function 'f<int>' cannot be used in a constant expression}} + static_assert(A<int>::x<int> == 0); // expected-error {{static assertion expression is not an integral constant expression}} + // expected-note@-1 {{initializer of 'x<int>' is unknown}} + static_assert(A<int>::x<int*> == 0); // expected-error {{static assertion expression is not an integral constant expression}} + // expected-note@-1 {{initializer of 'x<int *>' is unknown}} + static_assert(A<int>::B<int>::y == 0); // expected-error {{implicit instantiation of undefined template 'Undefined::A<int>::B<int>'}} + static_assert(A<int>::B<int*>::y == 0); // expected-error {{implicit instantiation of undefined template 'Undefined::A<int>::B<int *>'}} + + static_assert(A<short>::f<int>() == 1); + static_assert(A<short>::x<int> == 1); + static_assert(A<short>::x<int*> == 2); +#if 0 + // FIXME: crashes + static_assert(A<short>::B<int>::y == 1); + static_assert(A<short>::B<int*>::y == 2); +#endif +} // namespace Undefined + +namespace Defined { + template<typename T> + struct A { + template<typename U> + static constexpr int f() { + return 0; + }; + + template<typename U> + static const int x = 0; + + template<typename U> + static const int x<U*> = 0; + + template<typename U> + struct B { + static constexpr int y = 0; + }; + + template<typename U> + struct B<U*> { + static constexpr int y = 0; + }; + }; + + template<> + template<typename U> + constexpr int A<short>::f() { + return A<long>::f<U>(); + } + + template<> + template<typename U> + constexpr int A<short>::x = A<long>::x<U>; + + template<> + template<typename U> + constexpr int A<short>::x<U*> = A<long>::x<U*>; + + template<> + template<typename U> + struct A<short>::B<U*> { + static constexpr int y = A<long>::B<U*>::y; + }; + + template<> + template<typename U> + struct A<short>::B { + static constexpr int y = A<long>::B<U>::y; + }; + + template<> + template<typename U> + constexpr int A<long>::f() { + return 1; + } + + template<> + template<typename U> + constexpr int A<long>::x = 1; + + template<> + template<typename U> + constexpr int A<long>::x<U*> = 2; + + template<> + template<typename U> + struct A<long>::B { + static constexpr int y = 1; + }; + + template<> + template<typename U> + struct A<long>::B<U*> { + static constexpr int y = 2; + }; + + static_assert(A<int>::f<int>() == 0); + static_assert(A<int>::x<int> == 0); + static_assert(A<int>::x<int*> == 0); + static_assert(A<int>::B<int>::y == 0); + static_assert(A<int>::B<int*>::y == 0); + + static_assert(A<short>::f<int>() == 1); + static_assert(A<short>::x<int> == 1); + static_assert(A<short>::x<int*> == 2); + static_assert(A<short>::B<int>::y == 1); + static_assert(A<short>::B<int*>::y == 2); +} // namespace Defined + +namespace Dependent { + template<int I> + struct A { + template<int J> + static constexpr int f(); + + template<int J> + static const int x; + + template<int J> + struct B; + }; + + template<> + template<int J> + constexpr int A<0>::f() { + return A<1>::f<J>(); + } + + template<> + template<int J> + constexpr int A<1>::f() { + return J; + } + + template<> + template<int J> + constexpr int A<0>::x = A<1>::x<J>; + + template<> + template<int J> + constexpr int A<1>::x = J; + + template<> + template<int J> + struct A<0>::B { + static constexpr int y = A<1>::B<J>::y; + }; + + template<> + template<int J> + struct A<1>::B { + static constexpr int y = J; + }; + + static_assert(A<0>::f<2>() == 2); + static_assert(A<0>::x<2> == 2); +#if 0 + // FIXME: crashes + static_assert(A<0>::B<2>::y == 2); +#endif +} // namespace Dependent diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp index 53e6bbfcf42a8..e644cab67b2b2 100644 --- a/clang/test/SemaCXX/friend.cpp +++ b/clang/test/SemaCXX/friend.cpp @@ -130,6 +130,20 @@ namespace test6_3 { v.f(); } } +namespace test6_4 { + template<class T> struct vector { + constexpr vector(int i) {} + constexpr int f(const T& t = T()) const { return T().v; } + }; + class A { + friend constexpr int vector<A>::f(const A&) const; + static constexpr int v = 2; + }; + void f() { + constexpr vector<A> v(1); + static_assert(v.f() == 2, ""); + } +} // namespace test6_4 namespace test7 { extern "C" { diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index 9cc53237461f3..6c41853cf3b4f 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -836,11 +836,11 @@ auto TplClass<int>::buggy() -> void {} } -namespace PackIndexExpr { +namespace PackIndexExpr1 { template <int... T> concept C = true; -template <typename...> struct TplClass { // #TplClassDef +template <typename...> struct TplClass { // #PackIndexExpr1-TplClassDef template <int... Ts> requires C<Ts...[0]> static auto buggy() -> void; @@ -852,9 +852,84 @@ requires C<Ts...[0]> auto TplClass<int>::buggy() -> void {} // FIXME: These shouldn't diagnose, but are a result of a revert: #193558 // expected-error@-2{{does not match any declaration in}} -// expected-note@#TplClassDef{{TplClass defined here}} -// -} +// expected-note@#PackIndexExpr1-TplClassDef{{TplClass defined here}} +} // namespace PackIndexExpr1 + +namespace PackIndexExpr2 { + template <int... T> concept C = true; + + namespace t1 { + template <int...> struct TplClass { // expected-note {{defined here}} + template <int... Ts, int... Us> + requires C<Ts...[0]> + static auto buggy() -> void; + }; + + template <> + template <int... Ts, int... Us> + requires C<Us...[0]> + auto TplClass<0>::buggy() -> void {} + // expected-error@-1 {{out-of-line definition of 'buggy' does not match any declaration}} + } // namespace t1 + namespace t2 { + template <int...> struct TplClass { // expected-note {{defined here}} + template <int... Ts> + requires C<Ts...[0]> + static auto buggy() -> void; + }; + + template <> + template <int... Ts> + requires C<Ts...[1]> + auto TplClass<0>::buggy() -> void {} + // expected-error@-1 {{out-of-line definition of 'buggy' does not match any declaration}} + } // namespace t2 + namespace t3 { + template <int... Us> struct TplClass { // expected-note {{defined here}} + template <int... Ts> + requires C<Us...[0]> + static auto buggy() -> void; + }; + + template <> + template <int... Ts> + requires C<Ts...[0]> + auto TplClass<0>::buggy() -> void {} + // expected-error@-1 {{out-of-line definition of 'buggy' does not match any declaration}} + } // namespace t3 +} // namespace PackIndexExpr2 + +namespace FuncTemplateInClass { + template <int T> concept C = true; + + namespace t1 { + template <int> struct TplClass { // expected-note {{defined here}} + template <int Ts> + requires C<Ts> + static auto buggy() -> void; + }; + + // FIXME: This should be accepted. + template <> + template <int Ts> + requires C<Ts> + auto TplClass<0>::buggy() -> void {} + // expected-error@-1 {{out-of-line definition of 'buggy' does not match any declaration}} + } //namespace t1 + namespace t2 { + template <int> struct TplClass { // expected-note {{defined here}} + template <int Ts, int Us> + requires C<Ts> + static auto buggy() -> void; + }; + + template <> + template <int Ts, int Us> + requires C<Us> + auto TplClass<0>::buggy() -> void {} + // expected-error@-1 {{out-of-line definition of 'buggy' does not match any declaration}} + } //namespace t2 +} // namespace FuncTemplateInClass namespace GH139476 { @@ -905,3 +980,13 @@ namespace NoDiagnosticsInNormalization { template<class> void S<int>::f() requires (sizeof(int) > 1) {} } // namespace NoDiagnosticsInNormalization + +namespace GH193558 { + template<class T> class A; + template<class T> struct A<T*> { + template<class> requires (T()) void f(); + }; + template<class T> template<class> + requires (T()) + void A<T*>::f() {} +} // namespace GH193558 diff --git a/clang/test/SemaTemplate/friend.cpp b/clang/test/SemaTemplate/friend.cpp index 9a1ed46812ca9..aef2faced6a96 100644 --- a/clang/test/SemaTemplate/friend.cpp +++ b/clang/test/SemaTemplate/friend.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s template<typename T> struct A { struct B { }; - + friend struct B; }; @@ -19,7 +19,7 @@ namespace PR6770 { } using namespace N; - namespace M { + namespace M { float f1(float); } using M::f1; @@ -166,3 +166,17 @@ void foobar() { A::Bar<int> b; } } + +namespace InstQualifier1 { + template <class> struct A { + template <class T> void f(T); + }; + void g() { + A<int>().f(0); + } + template <class T> template <class U> void A<T>::f(U) { + struct B { + B() {} + }; + } +} // namespace InstQualifier1 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
