[clang] Fix assertion failure during conversion function overload resolution. (PR #98671)

Daniel M. Katz via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 22 06:04:04 PDT 2024


katzdm wrote:

Looking further into this, I think this is a narrow problem that arises when selecting a function from an overload set which includes a specialization of a conversion function template.

Consider a class:
```cpp
struct S {
  template <typename> void fn();
  template <typename T> operator T();
};
```

When looking up `&S::fn<int>`, the associated `LookupResult` will be a singleton containing the `FunctionTemplateDecl` for `fn`, _not_ the function template specialization `fn<int>`. The `AddressOfFunctionResolver` in `SemaOverload.cpp` will then call `Sema::ResolveSingleFunctionTemplateSpecialization`, which will use template argument deduction machinery to instantiate `fn<int>`.

Looking up `&S::operator int`, however, is something stranger: Because there are no apparent template-arguments, the specialization is resolved [during lookup](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaLookup.cpp#L1174-L1207) instead of afterwards. This is necessary because the information needed to select the specialization is encoded in the unqualified-id itself, rather than in names and expressions that are parsed thereafter. From what I've been able to tell, this situation seems unique to conversion-function-templates, and I haven't found other cases where the `LookupResult` directly contains a function template specialization.

>From here, deducing the placeholder type for `auto r = &S::operator int;` uses [`Sema::resolveAddressOfSingleOverloadCandidate`](https://github.com/llvm/llvm-project/blob/5b8479bc28a8641f02be3d64f87770b9e0b1a427/clang/lib/Sema/SemaOverload.cpp#L13208-L13291) to try to narrow to a single candidate. In the presence of constraints, this calls [`Sema::getMoreConstrainedFunction`](https://github.com/llvm/llvm-project/blob/5b8479bc28a8641f02be3d64f87770b9e0b1a427/clang/lib/Sema/SemaOverload.cpp#L13285) to select a "best viable function."

The implementation of `Sema::getMoreConstrainedFunction` [already](https://github.com/llvm/llvm-project/blob/5b8479bc28a8641f02be3d64f87770b9e0b1a427/clang/lib/Sema/SemaTemplateDeduction.cpp#L5828-L5832) attempts to map instantiated member-functions back to their "pattern declarations" (which will have type `TK_FunctionTemplate`) before calling `Sema::IsAtLeastAsConstrained`. This handles cases like:

```cpp
template <typename>
struct S {
  void fn();
};
```

but not our conversion-function-template. Since I believe that specializations of conversion-function-templates are the only specializations that can appear in the `LookupResult`, I suggest a narrow carve-out to handle this case, and an assertion to alert us if there are any other such cases which we aren't aware of. All tests seem to pass.

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


More information about the cfe-commits mailing list