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) {
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);
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.
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);
}
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;
}
// 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) |
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 {
}
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())
}
}
-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
// 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); }
-}
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 {
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() {
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);
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 {};
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(({})) {};
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
}
<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>