llvm/llvm-project

[clang][C++] Bad error recovery when classes are defined inside template aliases

Open

#91.564 geöffnet am 9. Mai 2024

Auf GitHub ansehen
 (13 Kommentare) (0 Reaktionen) (0 zugewiesene Personen)C++ (10.782 Forks)batch import
clang:frontendcrash-on-invalidgood first issue

Repository-Metriken

Stars
 (26.378 Stars)
PR-Merge-Metriken
 (Durchschn. Merge 1T 2h) (1.000 gemergte PRs in 30 T)

Beschreibung

When classes are defined inside template aliases, they are currently recovered as non templated classes, as if they were defined in the template alias' context. However, these classes let escape any references to the template parameters.

Consider this example:

template <class T> using A = struct B {
  template <class> void f() requires (T()); // BAD: T aliases f's unnamed template parameter.
};
template void B::f<void>();

Produces:

test.cc:1:37: error: 'B' cannot be defined in a type alias template
    1 | template <class T> using A = struct B {
      |                                     ^
test.cc:2:39: error: atomic constraint must be of type 'bool' (found 'void')
    2 |   template <class> void f() requires (T());

This can easily lead to crashes as well:

template <class T> using A = struct B {
  using C = T;
};
template <class> void f() requires (B::C());
template void f<void>();

asserts in the constexpr evaluator:

Assertion failed: (!isValueDependent() && "Expression evaluator can't be called on a dependent expression."), function EvaluateAsConstantExpr, file ExprConstant.cpp, line 15953.

Probably a good strategy to fix this issue is to mark the alias' template parameters as invalid, and make sure their resulting type is something sensible for error recovery.

Contributor Guide