[clang] [clang][Sema] Improve template argument deduction diagnostic (PR #122754)

Aidan Goldfarb via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 31 09:55:03 PST 2025


================
@@ -4870,14 +4870,16 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
     "candidate template ignored: deduced values %diff{"
     "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
     "%1 and %3 of conflicting types for parameter %0}2,4">;
-def note_ovl_candidate_explicit_arg_mismatch_named : Note<
+def note_ovl_candidate_explicit_arg_mismatch : Note<
     "candidate template ignored: invalid explicitly-specified argument "
-    "for template parameter %0">;
+    "for %ordinal0 template parameter">;
+def note_ovl_candidate_explicit_arg_mismatch_detail : Note<
+    "%select{"
+    "|: expected a type, but got value '%1'"
+    "|: expected constant of type %3 but got type %1"
+    "|: could not convert '%1' from %2 to %3}0">;
----------------
AidanGoldfarb wrote:

Implemented. I put the `NoteTemplateParameterLocation` call after the diag, so it appears as:
```
source.cpp:80:5: error: no matching function for call to 'foo'
   80 |     foo<false>();
      |     ^~~~~~~~~~
3
source.cpp:77:13: note: candidate template ignored: invalid explicitly-specified argument: could not convert 'false' from 'bool' to 'endianness'
   77 | inline void foo() {}
      |             ^
source.cpp:76:22: note: template parameter is declared here
   76 | template <endianness e>
      |                      ^
```
Let me know if that looks good. 

Separately, I found an interesting case that I had not caught before due to the more generic `//expected-note {{invalid explicitly-specified argument}}` allowing the confusing error message seen below. The case from `clang/test/CXX/temp/temp.param/p8-cxx20.cpp`

```
namespace ConstDestruction {
  struct D {
    int n;
    bool can_destroy;

    constexpr ~D() {
      if (!can_destroy)
        throw "oh no"; // expected-note {{subexpression not valid}}
    }
  };

  template<D d> 
  void f() {} // expected-note 2{{invalid explicitly-specified argument}}

  void g() {
    f<D{0, true}>();
    f<D{0, false}>(); // expected-error {{no matching function}}
  }
}
```  
The root cause being an ill-formed constexpr. In this case, the diag message `candidate template ignored: invalid explicitly-specified argument: could not convert 'D{0, false}' from 'D' to 'D'` cannot be what we want. Although it is an invalid explicitly specified argument, it seems to be to be in a separate category from other tests. Should I look into emitting a unique error message along the lines of `template argument ‘D{0, false}’ is not a valid constant expression`?

https://github.com/llvm/llvm-project/pull/122754


More information about the cfe-commits mailing list