
Fixes https://github.com/llvm/llvm-project/issues/135032 Due to nested templates, when instantiating the outer layer (the template class), the inner layer (the template variable) uses delayed instantiation. This causes the declaration (VarDecl) of the template variable to retain the type from the original template declaration (i.e., auto), and it loses the initializer. Later, when instantiating the template variable, its VarTemplateSpecializationDecl type depends on the VarDecl type. Thus, the VarTemplateSpecializationDecl also has no initializer, and its type remains auto. Ultimately, when building the reference expression in Sema::BuildDeclarationNameExpr, the expression's type is auto and stays as auto until code generation, triggering llvm_unreachable in CodeGenTypes::ConvertType. Since I noticed that the deduction of auto type is caused by the initializer I plan to do special processing for template variables of type auto, that is, to prevent their delayed instantiation so that their initializers will not be lost when the outer template class is instantiated
42 lines
1.2 KiB
C++
42 lines
1.2 KiB
C++
// RUN: %clang_cc1 -std=c++17 -verify %s
|
|
// expected-no-diagnostics
|
|
template<bool> struct DominatorTreeBase {
|
|
static constexpr bool IsPostDominator = true;
|
|
};
|
|
extern template class DominatorTreeBase<false>;
|
|
constexpr bool k = DominatorTreeBase<false>::IsPostDominator;
|
|
|
|
namespace CompleteType {
|
|
template<unsigned N> constexpr int f(const bool (&)[N]) { return 0; }
|
|
|
|
template<bool ...V> struct X {
|
|
static constexpr bool arr[] = {V...};
|
|
static constexpr int value = f(arr);
|
|
};
|
|
|
|
constexpr int n = X<true>::value;
|
|
}
|
|
|
|
template <typename T> struct A {
|
|
static const int n;
|
|
static const int m;
|
|
constexpr int f() { return n; }
|
|
constexpr int g() { return n; }
|
|
};
|
|
template <typename T> constexpr int A<T>::n = sizeof(A) + sizeof(T);
|
|
template <typename T> inline constexpr int A<T>::m = sizeof(A) + sizeof(T);
|
|
static_assert(A<int>().f() == 5);
|
|
static_assert(A<int>().g() == 5);
|
|
|
|
template <typename T> struct InlineAuto {
|
|
template <typename G> inline static auto var = 5;
|
|
};
|
|
|
|
template <typename> struct PartialInlineAuto {
|
|
template <typename, typename> inline static auto var = 6;
|
|
template <typename T> inline static auto var<int, T> = 7;
|
|
};
|
|
|
|
int inlineauto = InlineAuto<int>::var<int>;
|
|
int partialinlineauto = PartialInlineAuto<int>::var<int, int>;
|