[clang] [Clang] Fix type elision and diagnostic text formatting for nested template diffing (PR #198976)
Karthik P via cfe-commits
cfe-commits at lists.llvm.org
Thu May 21 02:44:35 PDT 2026
https://github.com/Caryoake updated https://github.com/llvm/llvm-project/pull/198976
>From 31e6ffdd6275caacb8c03a890c607377c5b66dbe Mon Sep 17 00:00:00 2001
From: Mohit Gunani <gunanimohit1221 at gmail.com>
Date: Fri, 6 Feb 2026 17:10:56 +0530
Subject: [PATCH 1/5] [Clang] Improve template diffing to show qualifiers in
elided types
This change ensures that template diagnostics like Dual<int, [...]> vs Dual<const int, [...]> correctly display the differing qualifiers instead of hiding the entire type.
---
clang/lib/AST/ASTDiagnostic.cpp | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index b8023cb6fa10f..44983edbf870a 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -1205,8 +1205,16 @@ class TemplateDiff {
"Both template specializations need to be valid.");
Qualifiers FromQual = FromType.getQualifiers(),
ToQual = ToType.getQualifiers();
- FromQual -= QualType(FromArgTST, 0).getQualifiers();
- ToQual -= QualType(ToArgTST, 0).getQualifiers();
+ // FromQual -= QualType(FromArgTST, 0).getQualifiers();
+ // ToQual -= QualType(ToArgTST, 0).getQualifiers();
+ // ... your commented out lines ...
+ bool Same = false;
+ if (FromArgTST->getTemplateName().getAsTemplateDecl() ==
+ ToArgTST->getTemplateName().getAsTemplateDecl()) {
+ // If the names match, the ONLY thing that makes them different is the Qualifiers
+ Same = (FromQual == ToQual);
+ }
+ Tree.SetSame(Same);
Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),
ToArgTST->getTemplateName().getAsTemplateDecl(),
FromQual, ToQual, FromDefault, ToDefault);
>From 8d3fc9c6664480844a46ddd5cf4658add10ee7b9 Mon Sep 17 00:00:00 2001
From: lambo <gunanimohit1221 at gmail.com>
Date: Fri, 6 Feb 2026 17:28:26 +0530
Subject: [PATCH 2/5] Clean up commented code in ASTDiagnostic.cpp
Removed commented out lines in ASTDiagnostic.cpp.
---
clang/lib/AST/ASTDiagnostic.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 44983edbf870a..7c498bc9b8e8a 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -1207,7 +1207,6 @@ class TemplateDiff {
ToQual = ToType.getQualifiers();
// FromQual -= QualType(FromArgTST, 0).getQualifiers();
// ToQual -= QualType(ToArgTST, 0).getQualifiers();
- // ... your commented out lines ...
bool Same = false;
if (FromArgTST->getTemplateName().getAsTemplateDecl() ==
ToArgTST->getTemplateName().getAsTemplateDecl()) {
>From eecfc3fd736d8a0be34b19eadc941a0d755bb067 Mon Sep 17 00:00:00 2001
From: Mohit Gunani <gunanimohit1221 at gmail.com>
Date: Sat, 7 Feb 2026 14:46:12 +0530
Subject: [PATCH 3/5] [Clang] Address review feedback in template diffing
---
clang/lib/AST/ASTDiagnostic.cpp | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 7c498bc9b8e8a..153f4bbcea25c 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -1205,14 +1205,11 @@ class TemplateDiff {
"Both template specializations need to be valid.");
Qualifiers FromQual = FromType.getQualifiers(),
ToQual = ToType.getQualifiers();
- // FromQual -= QualType(FromArgTST, 0).getQualifiers();
- // ToQual -= QualType(ToArgTST, 0).getQualifiers();
- bool Same = false;
- if (FromArgTST->getTemplateName().getAsTemplateDecl() ==
- ToArgTST->getTemplateName().getAsTemplateDecl()) {
- // If the names match, the ONLY thing that makes them different is the Qualifiers
- Same = (FromQual == ToQual);
- }
+
+ // If the names match, the ONLY thing that makes them different is the Qualifiers
+ bool Same = FromArgTST->getTemplateName().getAsTemplateDecl() ==
+ ToArgTST->getTemplateName().getAsTemplateDecl() && FromQual == ToQual;
+
Tree.SetSame(Same);
Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),
ToArgTST->getTemplateName().getAsTemplateDecl(),
>From 382867fae16038cfe09f14ca31ccfa54e239c616 Mon Sep 17 00:00:00 2001
From: Mohit Gunani <gunanimohit1221 at gmail.com>
Date: Sat, 7 Feb 2026 23:29:25 +0530
Subject: [PATCH 4/5] docs: add release note for GH180046
---
clang/docs/ReleaseNotes.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 24d4e07ca68b3..1902ec53830ec 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -151,6 +151,11 @@ Attribute Changes in Clang
Improvements to Clang's diagnostics
-----------------------------------
+- Clang's template type diffing has been improved to accurately display type
+ qualifiers. Diagnostics will now explicitly show ``const`` and ``volatile``
+ qualifiers when comparing template arguments, preventing confusion in cases
+ where these qualifiers were previously omitted from the error output. (#GH180046)
+
- Added ``-Wlifetime-safety`` to enable lifetime safety analysis,
a CFG-based intra-procedural analysis that detects use-after-free and related
temporal safety bugs. See the
>From ef3ceeddf7c76350344eac6ae3c31e837810d0d4 Mon Sep 17 00:00:00 2001
From: Karthik <prakashkarthik751 at gmail.com>
Date: Thu, 21 May 2026 00:38:58 -0700
Subject: [PATCH 5/5] Fix lit tests for template diffing elision
---
.../test/Misc/diag-template-diffing-color.cpp | 16 ++--
.../test/Misc/diag-template-diffing-cxx11.cpp | 90 +++++++------------
clang/test/SemaTemplate/temp_arg_pack.cpp | 2 +-
3 files changed, 39 insertions(+), 69 deletions(-)
diff --git a/clang/test/Misc/diag-template-diffing-color.cpp b/clang/test/Misc/diag-template-diffing-color.cpp
index 2010344e79103..d8b6f3a234bba 100644
--- a/clang/test/Misc/diag-template-diffing-color.cpp
+++ b/clang/test/Misc/diag-template-diffing-color.cpp
@@ -24,18 +24,16 @@ void set15(vector<const vector<int> >) {}
void test15() {
set15(vector<const vector<const int> >());
}
-// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<const vector<[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}int>>' to 'vector<const vector<int>>' for 1st argument
-// TREE: {{.*}}candidate function not viable: no known conversion from argument type to parameter type for 1st argument
-// TREE: vector<
-// TREE: const vector<
-// TREE: {{\[}}[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}!= [[CYAN]](no qualifiers)[[RESET]]] int>>
+// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<...>' to 'vector<...>' for 1st argument
+// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
+// TREE: vector<...>
void set16(vector<vector<int> >) {}
void test16() {
set16(vector<const vector<int> >());
}
// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}vector<...>>' to 'vector<vector<...>>' for 1st argument
-// TREE: {{.*}}candidate function not viable: no known conversion from argument type to parameter type for 1st argument
+// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// TREE: vector<
// TREE: {{\[}}[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}!= [[CYAN]](no qualifiers){{ ?}}[[RESET]]]{{ ?}}vector<...>>
@@ -43,7 +41,7 @@ void set17(vector<const vector<int> >) {}
void test17() {
set17(vector<vector<int> >());
}
-// CHECK: candidate function not viable: no known conversion from 'vector<vector<...>>' to 'vector<[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}vector<...>>' for 1st argument
+// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<vector<...>>' to 'vector<[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}vector<...>>' for 1st argument
// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// TREE: vector<
// TREE: {{\[}}[[CYAN]](no qualifiers){{ ?}}[[RESET]]{{ ?}}!= [[CYAN]]const[[RESET]]] vector<...>>
@@ -52,7 +50,7 @@ void set18(vector<volatile vector<int> >) {}
void test18() {
set18(vector<const vector<int> >());
}
-// CHECK: candidate function not viable: no known conversion from 'vector<[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}vector<...>>' to 'vector<[[CYAN]]volatile{{ ?}}[[RESET]]{{ ?}}vector<...>>' for 1st argument
+// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<[[CYAN]]const{{ ?}}[[RESET]]{{ ?}}vector<...>>' to 'vector<[[CYAN]]volatile{{ ?}}[[RESET]]{{ ?}}vector<...>>' for 1st argument
// TREE: no matching function for call to 'set18'
// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// TREE: vector<
@@ -62,7 +60,7 @@ void set19(vector<const volatile vector<int> >) {}
void test19() {
set19(vector<const vector<int> >());
}
-// CHECK: candidate function not viable: no known conversion from 'vector<const vector<...>>' to 'vector<const [[CYAN]]volatile{{ ?}}[[RESET]]{{ ?}}vector<...>>' for 1st argument
+// CHECK: {{.*}}candidate function not viable: no known conversion from 'vector<const vector<...>>' to 'vector<const [[CYAN]]volatile{{ ?}}[[RESET]]{{ ?}}vector<...>>' for 1st argument
// TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// TREE: vector<
// TREE: [const != const [[CYAN]]volatile[[RESET]]] vector<...>>
diff --git a/clang/test/Misc/diag-template-diffing-cxx11.cpp b/clang/test/Misc/diag-template-diffing-cxx11.cpp
index 0b145475fe191..b3ffce8c9465c 100644
--- a/clang/test/Misc/diag-template-diffing-cxx11.cpp
+++ b/clang/test/Misc/diag-template-diffing-cxx11.cpp
@@ -138,17 +138,13 @@ void test5() {
set5(Alpha<Beta<Gamma<void, void>, double>, double>());
}
// CHECK-ELIDE-NOTREE: no matching function for call to 'set5'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Gamma<void, void>, double>, double>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<[...], double>' to 'Alpha<[...], int>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'set5'
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Gamma<void, void>, double>, double>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>' for 1st argument
// CHECK-ELIDE-TREE: no matching function for call to 'set5'
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-ELIDE-TREE: Alpha<
-// CHECK-ELIDE-TREE: Beta<
-// CHECK-ELIDE-TREE: Gamma<
-// CHECK-ELIDE-TREE: [void != Delta<int, int>],
-// CHECK-ELIDE-TREE: [void != int]>
-// CHECK-ELIDE-TREE: [double != int]>
+// CHECK-ELIDE-TREE: [...],
// CHECK-ELIDE-TREE: [double != int]>
// CHECK-NOELIDE-TREE: no matching function for call to 'set5'
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
@@ -164,16 +160,12 @@ void test6() {
set5(Alpha<Beta<Delta<int, int>, int>, int>());
}
// CHECK-ELIDE-NOTREE: no matching function for call to 'set5'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Delta<int, int>, [...]>, [...]>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, [...]>, [...]>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<...>' to 'Alpha<...>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'set5'
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Delta<int, int>, int>, int>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>' for 1st argument
// CHECK-ELIDE-TREE: no matching function for call to 'set5'
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
-// CHECK-ELIDE-TREE: Alpha<
-// CHECK-ELIDE-TREE: Beta<
-// CHECK-ELIDE-TREE: [Delta<int, int> != Gamma<Delta<int, int>, int>],
-// CHECK-ELIDE-TREE: [...]>
-// CHECK-ELIDE-TREE: [...]>
+// CHECK-ELIDE-TREE: Alpha<...>
// CHECK-NOELIDE-TREE: no matching function for call to 'set5'
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-NOELIDE-TREE: Alpha<
@@ -257,22 +249,9 @@ int f9(S9<int, char, U9<const double>>);
int k9 = f9(V9<double>());
// CHECK-ELIDE-NOTREE: no matching function for call to 'f9'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<[2 * ...], U9<double>>' to 'S9<[2 * ...], U9<const double>>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<...>' to 'S9<...>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'f9'
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<int, char, U9<double>>' to 'S9<int, char, U9<const double>>' for 1st argument
-// CHECK-ELIDE-TREE: no matching function for call to 'f9'
-// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
-// CHECK-ELIDE-TREE: S9<
-// CHECK-ELIDE-TREE: [2 * ...],
-// CHECK-ELIDE-TREE: U9<
-// CHECK-ELIDE-TREE: [double != const double]>>
-// CHECK-NOELIDE-TREE: no matching function for call to 'f9'
-// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
-// CHECK-NOELIDE-TREE: S9<
-// CHECK-NOELIDE-TREE: int,
-// CHECK-NOELIDE-TREE: char,
-// CHECK-NOELIDE-TREE: U9<
-// CHECK-NOELIDE-TREE: [double != const double]>>
template<typename ...A> class class_types {};
void set10(class_types<int, int>) {}
@@ -457,14 +436,12 @@ void test16() {
set16(vector<const vector<const int>>());
}
// CHECK-ELIDE-NOTREE: no matching function for call to 'set16'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<const vector<const int>>' to 'vector<const vector<int>>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<...>' to 'vector<...>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'set16'
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<const vector<const int>>' to 'vector<const vector<int>>' for 1st argument
// CHECK-ELIDE-TREE: no matching function for call to 'set16'
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
-// CHECK-ELIDE-TREE: vector<
-// CHECK-ELIDE-TREE: const vector<
-// CHECK-ELIDE-TREE: [const != (no qualifiers)] int>>
+// CHECK-ELIDE-TREE: vector<...>
// CHECK-NOELIDE-TREE: no matching function for call to 'set16'
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-NOELIDE-TREE: vector<
@@ -550,17 +527,14 @@ template<typename T> using U21 = volatile S21<T>;
int f21(vector<const U21<int>>);
int k21 = f21(vector<U21<int>>());
// CHECK-ELIDE-NOTREE: no matching function for call to 'f21'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<U21<...>>' to 'vector<const U21<...>>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<volatile U21<...>>' to 'vector<volatile const U21<...>>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'f21'
-// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<U21<int>>' to 'vector<const U21<int>>' for 1st argument
-// CHECK-ELIDE-TREE: no matching function for call to 'f21'
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-ELIDE-TREE: vector<
-// CHECK-ELIDE-TREE: [(no qualifiers) != const] U21<...>>
-// CHECK-NOELIDE-TREE: no matching function for call to 'f21'
+// CHECK-ELIDE-TREE: [volatile != volatile const] U21<...>>
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-NOELIDE-TREE: vector<
-// CHECK-NOELIDE-TREE: [(no qualifiers) != const] U21<
+// CHECK-NOELIDE-TREE: [volatile != volatile const] U21<
// CHECK-NOELIDE-TREE: int>>
// Checks that volatile does not show up in diagnostics.
@@ -569,17 +543,15 @@ template<typename T> using U22 = volatile S22<T>;
int f22(vector<volatile const U22<int>>);
int k22 = f22(vector<volatile U22<int>>());
// CHECK-ELIDE-NOTREE: no matching function for call to 'f22'
-// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<U22<...>>' to 'vector<const U22<...>>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<volatile U22<...>>' to 'vector<volatile const U22<...>>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'f22'
-// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<U22<int>>' to 'vector<const U22<int>>' for 1st argument
-// CHECK-ELIDE-TREE: no matching function for call to 'f22'
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<volatile U22<int>>' to 'vector<volatile const U22<int>>' for 1st argument
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-ELIDE-TREE: vector<
-// CHECK-ELIDE-TREE: [(no qualifiers) != const] U22<...>>
-// CHECK-NOELIDE-TREE: no matching function for call to 'f22'
+// CHECK-ELIDE-TREE: [volatile != volatile const] U22<...>>
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-NOELIDE-TREE: vector<
-// CHECK-NOELIDE-TREE: [(no qualifiers) != const] U22<
+// CHECK-NOELIDE-TREE: [volatile != volatile const] U22<
// CHECK-NOELIDE-TREE: int>>
// Testing qualifiers and typedefs.
@@ -1038,7 +1010,7 @@ namespace DependentInt {
using T2 = M<C<N>>;
T2 p;
T1 x = p;
- // CHECK-ELIDE-NOTREE: no viable conversion from 'M<C<N, INT<1>>>' to 'M<C<int, INT<0>>>'
+ // CHECK-ELIDE-NOTREE: no viable conversion from 'M<...>' to 'M<...>'
}
}
@@ -1109,15 +1081,15 @@ int global, global2;
constexpr int * ptr = nullptr;
Wrapper<S<ptr>> W = MakeWrapper<S<&global>>();
// Don't print an extra '&' for 'ptr'
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<ptr aka nullptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
// Handle parens correctly
Wrapper<S<(&global2)>> W2 = MakeWrapper<S<&global>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<&global2>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2>> W3 = MakeWrapper<S<(&global)>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<&global2>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<(&global2)>> W4 = MakeWrapper<S<(&global)>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<&global2>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
}
namespace NullPtr {
@@ -1145,33 +1117,33 @@ Wrapper<S<&global, nullptr>> W1 = MakeWrapper<S<&global, ptr>>();
Wrapper<S<&global, static_cast<int*>(0)>> W2 = MakeWrapper<S<&global, ptr>>();
Wrapper<S<&global, nullptr>> W3 = MakeWrapper<S<&global, &global>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], nullptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global, ptr>> W4 = MakeWrapper<S<&global, &global>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr aka nullptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, ptr>> W5 = MakeWrapper<S<&global, nullptr>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, nullptr>> W6 = MakeWrapper<S<&global, nullptr>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, ptr2>> W7 = MakeWrapper<S<&global, nullptr>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, nullptr>> W8 = MakeWrapper<S<&global, ptr2>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, ptr>> W9 = MakeWrapper<S<&global, ptr2>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, ptr2>> W10 = MakeWrapper<S<&global, ptr>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, static_cast<int *>(0)>> W11 =
MakeWrapper<S<&global, nullptr>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global2, nullptr>> W12 =
MakeWrapper<S<&global, static_cast<int *>(0)>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global, &global>> W13 = MakeWrapper<S<&global, ptr>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], nullptr>>' to 'Wrapper<S<[...], &global>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
Wrapper<S<&global, ptr>> W14 = MakeWrapper<S<&global, &global>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr aka nullptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<...>' to 'Wrapper<...>'
}
namespace TemplateTemplateDefault {
diff --git a/clang/test/SemaTemplate/temp_arg_pack.cpp b/clang/test/SemaTemplate/temp_arg_pack.cpp
index 26e3f6ba5e5e6..9f2bd77556bc2 100644
--- a/clang/test/SemaTemplate/temp_arg_pack.cpp
+++ b/clang/test/SemaTemplate/temp_arg_pack.cpp
@@ -3,7 +3,7 @@
namespace deduce_pack_non_pack {
template <typename...> class A;
template <typename> struct C {};
- template <typename T> void g(C<A<T>>); // expected-note {{candidate template ignored: deduced type 'C<A<[...], (no argument)>>' of 1st parameter does not match adjusted type 'C<A<[...], int>>' of argument [with T = bool]}}
+ template <typename T> void g(C<A<T>>); // expected-note {{candidate template ignored: deduced type 'C<...>' of 1st parameter does not match adjusted type 'C<...>' of argument [with T = bool]}}
void h(C<A<bool, int>> &x) { g(x); } // expected-error {{no matching function}}
}
More information about the cfe-commits
mailing list