Skip to content

Commit 638867a

Browse files
committed
DR2064: decltype(E) is only a dependent type if E is type-dependent, not
if E is merely instantiation-dependent.
1 parent d599ed4 commit 638867a

File tree

10 files changed

+50
-23
lines changed

10 files changed

+50
-23
lines changed

clang/include/clang/AST/DependenceFlags.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,12 @@ inline TypeDependence toTypeDependence(TemplateNameDependence D) {
255255
inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
256256
return Dependence(D).type();
257257
}
258+
/// Compute the dependence of a type that depends on the type of an expression,
259+
/// given the dependence of that expression and of its type.
260+
inline TypeDependence typeToTypeDependence(ExprDependence ED, TypeDependence TD) {
261+
return Dependence(ED & ~ExprDependence::Value).type() |
262+
(TD & TypeDependence::VariablyModified);
263+
}
258264

259265
inline NestedNameSpecifierDependence
260266
toNestedNameSpecifierDependendence(TypeDependence D) {

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5383,10 +5383,10 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
53835383
DecltypeType *dt;
53845384

53855385
// C++11 [temp.type]p2:
5386-
// If an expression e involves a template parameter, decltype(e) denotes a
5387-
// unique dependent type. Two such decltype-specifiers refer to the same
5388-
// type only if their expressions are equivalent (14.5.6.1).
5389-
if (e->isInstantiationDependent()) {
5386+
// If an expression e is type-dependent, decltype(e) denotes a unique
5387+
// dependent type. Two such decltype-specifiers refer to the same type only
5388+
// if their expressions are equivalent (14.5.6.1).
5389+
if (e->isTypeDependent()) {
53905390
llvm::FoldingSetNodeID ID;
53915391
DependentDecltypeType::Profile(ID, *this, e);
53925392

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,6 +2582,11 @@ void CXXNameMangler::mangleType(QualType T) {
25822582
// instantation-dependent qualifiers. See
25832583
// https://github.com/itanium-cxx-abi/cxx-abi/issues/114.
25842584

2585+
// Don't desugar instantiation-dependent decltype / typeof types. We need
2586+
// to mangle the expression as written.
2587+
if (isa<DecltypeType, TypeOfType>(T))
2588+
break;
2589+
25852590
QualType Desugared
25862591
= T.getSingleStepDesugaredType(Context.getASTContext());
25872592
if (Desugared == T)

clang/lib/AST/Type.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can,
125125
// template<int ...N> int arr[] = {N...};
126126
: Type(tc, can,
127127
et->getDependence() |
128-
(sz ? toTypeDependence(
129-
turnValueToTypeDependence(sz->getDependence()))
128+
(sz ? toTypeDependence(sz->getDependence())
130129
: TypeDependence::None) |
131130
(tc == VariableArray ? TypeDependence::VariablyModified
132131
: TypeDependence::None) |
@@ -3396,9 +3395,8 @@ QualType MacroQualifiedType::getModifiedType() const {
33963395

33973396
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
33983397
: Type(TypeOfExpr, can,
3399-
toTypeDependence(E->getDependence()) |
3400-
(E->getType()->getDependence() &
3401-
TypeDependence::VariablyModified)),
3398+
typeToTypeDependence(E->getDependence(),
3399+
E->getType()->getDependence())),
34023400
TOExpr(E) {}
34033401

34043402
bool TypeOfExprType::isSugared() const {
@@ -3418,18 +3416,12 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
34183416
}
34193417

34203418
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
3421-
// C++11 [temp.type]p2: "If an expression e involves a template parameter,
3422-
// decltype(e) denotes a unique dependent type." Hence a decltype type is
3423-
// type-dependent even if its expression is only instantiation-dependent.
34243419
: Type(Decltype, can,
3425-
toTypeDependence(E->getDependence()) |
3426-
(E->isInstantiationDependent() ? TypeDependence::Dependent
3427-
: TypeDependence::None) |
3428-
(E->getType()->getDependence() &
3429-
TypeDependence::VariablyModified)),
3420+
typeToTypeDependence(E->getDependence(),
3421+
E->getType()->getDependence())),
34303422
E(E), UnderlyingType(underlyingType) {}
34313423

3432-
bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
3424+
bool DecltypeType::isSugared() const { return !E->isTypeDependent(); }
34333425

34343426
QualType DecltypeType::desugar() const {
34353427
if (isSugared())

clang/test/CXX/drs/dr20xx.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ namespace dr2026 { // dr2026: 11
4949
}
5050
}
5151

52+
namespace dr2064 { // dr2064: 12
53+
#if __cplusplus >= 201103L
54+
template<typename T> struct X {
55+
template<typename U> struct Y {};
56+
};
57+
template<typename T> void f() {
58+
X<decltype(sizeof(T))>::Y<int> y; // ok
59+
return X<decltype(sizeof(T))>::f(); // expected-error {{no member named 'f' in 'dr2064::X<unsigned}}
60+
}
61+
#endif
62+
}
63+
5264
namespace dr2082 { // dr2082: 11
5365
void test1(int x, int = sizeof(x)); // ok
5466
#if __cplusplus >= 201103L

clang/test/Sema/invalid-bitwidth-expr.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ auto func() {
2626
auto func() {
2727
// error-bit should be propagated from TemplateArgument to NestNameSpecifier.
2828
class Base<decltype(Foo(T()))>::type C; // expected-error {{no matching function for call to 'Foo'}}
29+
// expected-error@-1 {{no class named 'type' in 'Base<bool>'}}
2930
return C;
3031
}
3132
struct Z {

clang/test/SemaCXX/invalid-template-base-specifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ void test() { Crash<int>(); } // expected-note {{in instantiation of template cl
1212
template <typename T>
1313
using Alias = decltype(Foo(T())); // expected-error {{no matching function for call to 'Foo'}}
1414
template <typename T>
15-
struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}}
15+
struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}} expected-error {{base specifier must name a class}}
1616
Crash2(){};
1717
};
1818

19-
void test2() { Crash2<int>(); } // expected-note {{in instantiation of template class 'Crash2<int>' requested here}}
19+
void test2() { Crash2<int>(); } // expected-note 2{{in instantiation of template class 'Crash2<int>' requested here}}
2020

2121
template <typename T>
2222
class Base {};

clang/test/SemaTemplate/dependent-expr.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,12 @@ namespace PR45083 {
129129
template<typename> void f() {
130130
decltype(({})) x; // expected-error {{incomplete type}}
131131
}
132-
template void f<int>(); // expected-note {{instantiation of}}
132+
template void f<int>();
133+
134+
template<typename T> void f2() {
135+
decltype(({T();})) x; // expected-error {{incomplete type}}
136+
}
137+
template void f2<void>(); // expected-note {{instantiation of}}
133138

134139
template<typename> auto g() {
135140
auto c = [](auto, int) -> decltype(({})) {};

clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ namespace Auto {
115115

116116
int n;
117117
template<auto A, decltype(A) B = &n> struct SubstFailure;
118-
TInt<SubstFailure> isf; // FIXME: this should be ill-formed
118+
TInt<SubstFailure> isf; // expected-error {{template template argument has different template parameters than its corresponding template template parameter}}
119119
TIntPtr<SubstFailure> ipsf;
120+
121+
template<template<auto A, auto B, decltype(A)> typename C> struct TAutoAutoFirst {};
122+
template<auto A, auto B, decltype(A)> struct AutoAutoFirst;
123+
template<auto A, auto B, decltype(B)> struct AutoAutoSecond;
124+
TAutoAutoFirst<AutoAutoFirst> aaf;
125+
TAutoAutoFirst<AutoAutoSecond> aas; // FIXME: this should be rejected due to parameter mismatch
120126
}

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12199,7 +12199,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1219912199
<td><a href="https://wg21.link/cwg2064">2064</a></td>
1220012200
<td>CD4</td>
1220112201
<td>Conflicting specifications for dependent <I>decltype-specifier</I>s</td>
12202-
<td class="none" align="center">Unknown</td>
12202+
<td class="unreleased" align="center">Clang 12</td>
1220312203
</tr>
1220412204
<tr class="open" id="2065">
1220512205
<td><a href="https://wg21.link/cwg2065">2065</a></td>

0 commit comments

Comments
 (0)