[llvm-branch-commits] [clang] 638867a - DR2064: decltype(E) is only a dependent type if E is type-dependent, not
Richard Smith via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 17 23:27:23 PST 2020
Author: Richard Smith
Date: 2020-12-17T23:23:05-08:00
New Revision: 638867afd4bce4a2c56dea041299428af3727d61
URL: https://github.com/llvm/llvm-project/commit/638867afd4bce4a2c56dea041299428af3727d61
DIFF: https://github.com/llvm/llvm-project/commit/638867afd4bce4a2c56dea041299428af3727d61.diff
LOG: DR2064: decltype(E) is only a dependent type if E is type-dependent, not
if E is merely instantiation-dependent.
Added:
Modified:
clang/include/clang/AST/DependenceFlags.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/Type.cpp
clang/test/CXX/drs/dr20xx.cpp
clang/test/Sema/invalid-bitwidth-expr.mm
clang/test/SemaCXX/invalid-template-base-specifier.cpp
clang/test/SemaTemplate/dependent-expr.cpp
clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
clang/www/cxx_dr_status.html
Removed:
################################################################################
diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
index ca96b65574bd..8c47047a7526 100644
--- a/clang/include/clang/AST/DependenceFlags.h
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -255,6 +255,12 @@ 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) {
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 44545f00b146..0190573fe36e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5383,10 +5383,10 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
DecltypeType *dt;
// C++11 [temp.type]p2:
- // 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()) {
+ // 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()) {
llvm::FoldingSetNodeID ID;
DependentDecltypeType::Profile(ID, *this, e);
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 6c8d5687c64a..01deb598a078 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2582,6 +2582,11 @@ void CXXNameMangler::mangleType(QualType T) {
// instantation-dependent qualifiers. See
// https://github.com/itanium-cxx-abi/cxx-abi/issues/114.
+ // Don't desugar instantiation-dependent decltype / typeof types. We need
+ // to mangle the expression as written.
+ if (isa<DecltypeType, TypeOfType>(T))
+ break;
+
QualType Desugared
= T.getSingleStepDesugaredType(Context.getASTContext());
if (Desugared == T)
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index af39b80ef9e4..e5811dbc44c5 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -125,8 +125,7 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can,
// template<int ...N> int arr[] = {N...};
: Type(tc, can,
et->getDependence() |
- (sz ? toTypeDependence(
- turnValueToTypeDependence(sz->getDependence()))
+ (sz ? toTypeDependence(sz->getDependence())
: TypeDependence::None) |
(tc == VariableArray ? TypeDependence::VariablyModified
: TypeDependence::None) |
@@ -3396,9 +3395,8 @@ QualType MacroQualifiedType::getModifiedType() const {
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
: Type(TypeOfExpr, can,
- toTypeDependence(E->getDependence()) |
- (E->getType()->getDependence() &
- TypeDependence::VariablyModified)),
+ typeToTypeDependence(E->getDependence(),
+ E->getType()->getDependence())),
TOExpr(E) {}
bool TypeOfExprType::isSugared() const {
@@ -3418,18 +3416,12 @@ 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,
- toTypeDependence(E->getDependence()) |
- (E->isInstantiationDependent() ? TypeDependence::Dependent
- : TypeDependence::None) |
- (E->getType()->getDependence() &
- TypeDependence::VariablyModified)),
+ typeToTypeDependence(E->getDependence(),
+ E->getType()->getDependence())),
E(E), UnderlyingType(underlyingType) {}
-bool DecltypeType::isSugared() const { return !E->isInstantiationDependent(); }
+bool DecltypeType::isSugared() const { return !E->isTypeDependent(); }
QualType DecltypeType::desugar() const {
if (isSugared())
diff --git a/clang/test/CXX/drs/dr20xx.cpp b/clang/test/CXX/drs/dr20xx.cpp
index 56cc1161a00c..6e1c0505a5ec 100644
--- a/clang/test/CXX/drs/dr20xx.cpp
+++ b/clang/test/CXX/drs/dr20xx.cpp
@@ -49,6 +49,18 @@ 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
diff --git a/clang/test/Sema/invalid-bitwidth-expr.mm b/clang/test/Sema/invalid-bitwidth-expr.mm
index 41ca9496de4f..8ce498feb4af 100644
--- a/clang/test/Sema/invalid-bitwidth-expr.mm
+++ b/clang/test/Sema/invalid-bitwidth-expr.mm
@@ -26,6 +26,7 @@ auto func() {
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 at -1 {{no class named 'type' in 'Base<bool>'}}
return C;
}
struct Z {
diff --git a/clang/test/SemaCXX/invalid-template-base-specifier.cpp b/clang/test/SemaCXX/invalid-template-base-specifier.cpp
index 7a1a7f801c45..77601402a85c 100644
--- a/clang/test/SemaCXX/invalid-template-base-specifier.cpp
+++ b/clang/test/SemaCXX/invalid-template-base-specifier.cpp
@@ -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}}
+struct Crash2 : decltype(Alias<T>()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}} expected-error {{base specifier must name a class}}
Crash2(){};
};
-void test2() { Crash2<int>(); } // expected-note {{in instantiation of template class 'Crash2<int>' requested here}}
+void test2() { Crash2<int>(); } // expected-note 2{{in instantiation of template class 'Crash2<int>' requested here}}
template <typename T>
class Base {};
diff --git a/clang/test/SemaTemplate/dependent-expr.cpp b/clang/test/SemaTemplate/dependent-expr.cpp
index abdb8e9c4a9f..dace7e28788d 100644
--- a/clang/test/SemaTemplate/dependent-expr.cpp
+++ b/clang/test/SemaTemplate/dependent-expr.cpp
@@ -129,7 +129,12 @@ namespace PR45083 {
template<typename> void f() {
decltype(({})) x; // expected-error {{incomplete type}}
}
- template void f<int>(); // expected-note {{instantiation of}}
+ 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<typename> auto g() {
auto c = [](auto, int) -> decltype(({})) {};
diff --git a/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
index 03ef78f8cf14..b9a1c933560d 100644
--- a/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp
@@ -115,6 +115,12 @@ namespace Auto {
int n;
template<auto A, decltype(A) B = &n> struct SubstFailure;
- TInt<SubstFailure> isf; // FIXME: this should be ill-formed
+ TInt<SubstFailure> isf; // expected-error {{template template argument has
diff erent template parameters than its corresponding template template parameter}}
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
}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index feac3c6dc2d0..b40d2c53bdec 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -12199,7 +12199,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<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="none" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 12</td>
</tr>
<tr class="open" id="2065">
<td><a href="https://wg21.link/cwg2065">2065</a></td>
More information about the llvm-branch-commits
mailing list