Revert "DR2064: decltype(E) is only a dependent type if E is type-dependent, not
if E is merely instantiation-dependent."
This change leaves us unable to distinguish between different function
templates that differ in only instantiation-dependent ways, for example
template<typename T> decltype(int(T())) f();
template<typename T> decltype(int(T(0))) f();
We'll need substantially better support for types that are
instantiation-dependent but not dependent before we can go ahead with
this change.
This reverts commit e3065ce238
.
This commit is contained in:
parent
5a684b70dc
commit
da986511fb
|
@ -255,12 +255,6 @@ inline TypeDependence toTypeDependence(TemplateNameDependence D) {
|
|||
inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
|
||||
return Dependence(D).type();
|
||||
}
|
||||
/// Compute the dependence of a type that depends on the type of an expression,
|
||||
/// given the dependence of that expression and of its type.
|
||||
inline TypeDependence typeToTypeDependence(ExprDependence ED, TypeDependence TD) {
|
||||
return Dependence(ED & ~ExprDependence::Value).type() |
|
||||
(TD & TypeDependence::VariablyModified);
|
||||
}
|
||||
|
||||
inline NestedNameSpecifierDependence
|
||||
toNestedNameSpecifierDependendence(TypeDependence D) {
|
||||
|
|
|
@ -5383,10 +5383,10 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
|
|||
DecltypeType *dt;
|
||||
|
||||
// C++11 [temp.type]p2:
|
||||
// If an expression e is type-dependent, decltype(e) denotes a unique
|
||||
// dependent type. Two such decltype-specifiers refer to the same type only
|
||||
// if their expressions are equivalent (14.5.6.1).
|
||||
if (e->isTypeDependent()) {
|
||||
// If an expression e involves a template parameter, decltype(e) denotes a
|
||||
// unique dependent type. Two such decltype-specifiers refer to the same
|
||||
// type only if their expressions are equivalent (14.5.6.1).
|
||||
if (e->isInstantiationDependent()) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentDecltypeType::Profile(ID, *this, e);
|
||||
|
||||
|
|
|
@ -2578,11 +2578,6 @@ void CXXNameMangler::mangleType(QualType T) {
|
|||
if (!TST->isTypeAlias())
|
||||
break;
|
||||
|
||||
// Don't desugar instantiation-dependent decltype / typeof types. We need
|
||||
// to mangle the expression as written.
|
||||
if (isa<DecltypeType, TypeOfType>(T))
|
||||
break;
|
||||
|
||||
// FIXME: We presumably shouldn't strip off ElaboratedTypes with
|
||||
// instantation-dependent qualifiers. See
|
||||
// https://github.com/itanium-cxx-abi/cxx-abi/issues/114.
|
||||
|
@ -5612,11 +5607,12 @@ static bool hasMangledSubstitutionQualifiers(QualType T) {
|
|||
|
||||
bool CXXNameMangler::mangleSubstitution(QualType T) {
|
||||
if (!hasMangledSubstitutionQualifiers(T)) {
|
||||
if (const RecordType *RT = dyn_cast<RecordType>(T))
|
||||
if (const RecordType *RT = T->getAs<RecordType>())
|
||||
return mangleSubstitution(RT->getDecl());
|
||||
}
|
||||
|
||||
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||
|
||||
return mangleSubstitution(TypePtr);
|
||||
}
|
||||
|
||||
|
@ -5775,7 +5771,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
|||
|
||||
void CXXNameMangler::addSubstitution(QualType T) {
|
||||
if (!hasMangledSubstitutionQualifiers(T)) {
|
||||
if (const RecordType *RT = dyn_cast<RecordType>(T)) {
|
||||
if (const RecordType *RT = T->getAs<RecordType>()) {
|
||||
addSubstitution(RT->getDecl());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -125,7 +125,8 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can,
|
|||
// template<int ...N> int arr[] = {N...};
|
||||
: Type(tc, can,
|
||||
et->getDependence() |
|
||||
(sz ? toTypeDependence(sz->getDependence())
|
||||
(sz ? toTypeDependence(
|
||||
turnValueToTypeDependence(sz->getDependence()))
|
||||
: TypeDependence::None) |
|
||||
(tc == VariableArray ? TypeDependence::VariablyModified
|
||||
: TypeDependence::None) |
|
||||
|
@ -3395,8 +3396,9 @@ QualType MacroQualifiedType::getModifiedType() const {
|
|||
|
||||
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
|
||||
: Type(TypeOfExpr, can,
|
||||
typeToTypeDependence(E->getDependence(),
|
||||
E->getType()->getDependence())),
|
||||
toTypeDependence(E->getDependence()) |
|
||||
(E->getType()->getDependence() &
|
||||
TypeDependence::VariablyModified)),
|
||||
TOExpr(E) {}
|
||||
|
||||
bool TypeOfExprType::isSugared() const {
|
||||
|
@ -3416,12 +3418,18 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
|
|||
}
|
||||
|
||||
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
|
||||
// C++11 [temp.type]p2: "If an expression e involves a template parameter,
|
||||
// decltype(e) denotes a unique dependent type." Hence a decltype type is
|
||||
// type-dependent even if its expression is only instantiation-dependent.
|
||||
: Type(Decltype, can,
|
||||
typeToTypeDependence(E->getDependence(),
|
||||
E->getType()->getDependence())),
|
||||
toTypeDependence(E->getDependence()) |
|
||||
(E->isInstantiationDependent() ? TypeDependence::Dependent
|
||||
: TypeDependence::None) |
|
||||
(E->getType()->getDependence() &
|
||||
TypeDependence::VariablyModified)),
|
||||
E(E), UnderlyingType(underlyingType) {}
|
||||
|
||||
bool DecltypeType::isSugared() const { return !E->isTypeDependent(); }
|
||||
bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
|
||||
|
||||
QualType DecltypeType::desugar() const {
|
||||
if (isSugared())
|
||||
|
|
|
@ -49,18 +49,6 @@ namespace dr2026 { // dr2026: 11
|
|||
}
|
||||
}
|
||||
|
||||
namespace dr2064 { // dr2064: 12
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename T> struct X {
|
||||
template<typename U> struct Y {};
|
||||
};
|
||||
template<typename T> void f() {
|
||||
X<decltype(sizeof(T))>::Y<int> y; // ok
|
||||
return X<decltype(sizeof(T))>::f(); // expected-error {{no member named 'f' in 'dr2064::X<unsigned}}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace dr2082 { // dr2082: 11
|
||||
void test1(int x, int = sizeof(x)); // ok
|
||||
#if __cplusplus >= 201103L
|
||||
|
|
|
@ -96,14 +96,3 @@ typename X<T>::template Y<T>::type f(typename X<T>::template Y<T>::type2) { retu
|
|||
// CHECK: @_ZN12ManglePrefix1fIiEENS_1XIT_E1YIS2_E4typeENS5_5type2E
|
||||
template int f<int>(int);
|
||||
}
|
||||
|
||||
namespace InstantiationDependentDecltype {
|
||||
struct a { a(char); };
|
||||
struct b { a c(); };
|
||||
// FIXME: This mangling is incorrect; the second decltype type should be a
|
||||
// substitution for the first.
|
||||
// CHECK: @_ZN30InstantiationDependentDecltype1fINS_1bEEEvDTcvNS_1aEcldtcvT__E1cEEDTcvS2_cldtcvS3__E1cEES3_S3_S2_S2_
|
||||
// FIXME: @_ZN30InstantiationDependentDecltype1fINS_1bEEEvDTcvNS_1aEcldtcvT__E1cEES4_S3_S3_S2_S2_
|
||||
template<typename d> void f(decltype(a(d().c())), decltype(a(d().c())), d, d, a, a);
|
||||
void g(a a, b b) { f(a, a, b, b, a, a); }
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ template <typename T>
|
|||
auto func() {
|
||||
// error-bit should be propagated from TemplateArgument to NestNameSpecifier.
|
||||
class Base<decltype(Foo(T()))>::type C; // expected-error {{no matching function for call to 'Foo'}}
|
||||
// expected-error@-1 {{no class named 'type' in 'Base<bool>'}}
|
||||
return C;
|
||||
}
|
||||
struct Z {
|
||||
|
|
|
@ -1179,8 +1179,8 @@ struct TestType {
|
|||
static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
|
||||
auto TC = co_yield 0;
|
||||
using TCT = decltype(TC);
|
||||
static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
|
||||
static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
|
||||
static_assert(TCT::template MatchesArgs<const char *volatile &, unsigned>, "");
|
||||
static_assert(!TCT::template MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
|
||||
}
|
||||
|
||||
BadCoroMemberTag test_diagnostics() {
|
||||
|
@ -1263,31 +1263,31 @@ struct DepTestType {
|
|||
static CoroMemberTag test_static() {
|
||||
auto TC = co_yield 0;
|
||||
using TCT = decltype(TC);
|
||||
static_assert(TCT::MatchesArgs<>, "");
|
||||
static_assert(!TCT::MatchesArgs<DepTestType>, "");
|
||||
static_assert(!TCT::MatchesArgs<DepTestType &>, "");
|
||||
static_assert(!TCT::MatchesArgs<DepTestType *>, "");
|
||||
static_assert(TCT::template MatchesArgs<>, "");
|
||||
static_assert(!TCT::template MatchesArgs<DepTestType>, "");
|
||||
static_assert(!TCT::template MatchesArgs<DepTestType &>, "");
|
||||
static_assert(!TCT::template MatchesArgs<DepTestType *>, "");
|
||||
|
||||
// Ensure diagnostics are actually being generated here
|
||||
static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
|
||||
static_assert(TCT::template MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
|
||||
}
|
||||
|
||||
static CoroMemberTag test_static(volatile void *const, char &&) {
|
||||
auto TC = co_yield 0;
|
||||
using TCT = decltype(TC);
|
||||
static_assert(TCT::MatchesArgs<volatile void *const, char &&>, "");
|
||||
static_assert(TCT::template MatchesArgs<volatile void *const, char &&>, "");
|
||||
}
|
||||
|
||||
template <class Dummy>
|
||||
static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
|
||||
auto TC = co_yield 0;
|
||||
using TCT = decltype(TC);
|
||||
static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
|
||||
static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
|
||||
static_assert(TCT::template MatchesArgs<const char *volatile &, unsigned>, "");
|
||||
static_assert(!TCT::template MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
|
||||
}
|
||||
};
|
||||
|
||||
template struct DepTestType<int>; // expected-note {{requested here}}
|
||||
template struct DepTestType<int>; // expected-note 2{{requested here}}
|
||||
template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&;
|
||||
|
||||
template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);
|
||||
|
|
|
@ -12,11 +12,11 @@ void test() { Crash<int>(); } // expected-note {{in instantiation of template cl
|
|||
template <typename T>
|
||||
using Alias = decltype(Foo(T())); // expected-error {{no matching function for call to 'Foo'}}
|
||||
template <typename T>
|
||||
struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}} expected-error {{base specifier must name a class}}
|
||||
struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}}
|
||||
Crash2(){};
|
||||
};
|
||||
|
||||
void test2() { Crash2<int>(); } // expected-note 2{{in instantiation of template class 'Crash2<int>' requested here}}
|
||||
void test2() { Crash2<int>(); } // expected-note {{in instantiation of template class 'Crash2<int>' requested here}}
|
||||
|
||||
template <typename T>
|
||||
class Base {};
|
||||
|
|
|
@ -129,12 +129,7 @@ namespace PR45083 {
|
|||
template<typename> void f() {
|
||||
decltype(({})) x; // expected-error {{incomplete type}}
|
||||
}
|
||||
template void f<int>();
|
||||
|
||||
template<typename T> void f2() {
|
||||
decltype(({T();})) x; // expected-error {{incomplete type}}
|
||||
}
|
||||
template void f2<void>(); // expected-note {{instantiation of}}
|
||||
template void f<int>(); // expected-note {{instantiation of}}
|
||||
|
||||
template<typename> auto g() {
|
||||
auto c = [](auto, int) -> decltype(({})) {};
|
||||
|
|
|
@ -115,12 +115,6 @@ namespace Auto {
|
|||
|
||||
int n;
|
||||
template<auto A, decltype(A) B = &n> struct SubstFailure;
|
||||
TInt<SubstFailure> isf; // expected-error {{template template argument has different template parameters than its corresponding template template parameter}}
|
||||
TInt<SubstFailure> isf; // FIXME: this should be ill-formed
|
||||
TIntPtr<SubstFailure> ipsf;
|
||||
|
||||
template<template<auto A, auto B, decltype(A)> typename C> struct TAutoAutoFirst {};
|
||||
template<auto A, auto B, decltype(A)> struct AutoAutoFirst;
|
||||
template<auto A, auto B, decltype(B)> struct AutoAutoSecond;
|
||||
TAutoAutoFirst<AutoAutoFirst> aaf;
|
||||
TAutoAutoFirst<AutoAutoSecond> aas; // FIXME: this should be rejected due to parameter mismatch
|
||||
}
|
||||
|
|
|
@ -12198,7 +12198,7 @@ and <I>POD class</I></td>
|
|||
<td><a href="https://wg21.link/cwg2064">2064</a></td>
|
||||
<td>CD4</td>
|
||||
<td>Conflicting specifications for dependent <I>decltype-specifier</I>s</td>
|
||||
<td class="unreleased" align="center">Clang 12</td>
|
||||
<td class="none" align="center">Unknown</td>
|
||||
</tr>
|
||||
<tr class="open" id="2065">
|
||||
<td><a href="https://wg21.link/cwg2065">2065</a></td>
|
||||
|
|
Loading…
Reference in New Issue