From da986511fb9da1a46a0ca4dba2e49e2426036303 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 19 Jan 2021 11:54:06 -0800 Subject: [PATCH] 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 decltype(int(T())) f(); template 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 e3065ce238475ec202c707f4c58d90df171626ca. --- clang/include/clang/AST/DependenceFlags.h | 6 ------ clang/lib/AST/ASTContext.cpp | 8 ++++---- clang/lib/AST/ItaniumMangle.cpp | 10 +++------- clang/lib/AST/Type.cpp | 20 ++++++++++++++------ clang/test/CXX/drs/dr20xx.cpp | 12 ------------ clang/test/CodeGenCXX/mangle-subst.cpp | 11 ----------- clang/test/Sema/invalid-bitwidth-expr.mm | 1 - clang/test/SemaCXX/coroutines.cpp | 22 +++++++++++----------- .../SemaCXX/invalid-template-base-specifier.cpp | 4 ++-- clang/test/SemaTemplate/dependent-expr.cpp | 7 +------ .../test/SemaTemplate/temp_arg_template_cxx1z.cpp | 8 +------- clang/www/cxx_dr_status.html | 2 +- 12 files changed, 37 insertions(+), 74 deletions(-) diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h index 8c47047..ca96b65 100644 --- a/clang/include/clang/AST/DependenceFlags.h +++ b/clang/include/clang/AST/DependenceFlags.h @@ -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) { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d396f81..c482235 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 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); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index e7db8e2..27aa622 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -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(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(T)) + if (const RecordType *RT = T->getAs()) return mangleSubstitution(RT->getDecl()); } uintptr_t TypePtr = reinterpret_cast(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(T)) { + if (const RecordType *RT = T->getAs()) { addSubstitution(RT->getDecl()); return; } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 5dec80b..034e175 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -125,7 +125,8 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can, // template 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()) diff --git a/clang/test/CXX/drs/dr20xx.cpp b/clang/test/CXX/drs/dr20xx.cpp index 6e1c050..56cc116 100644 --- a/clang/test/CXX/drs/dr20xx.cpp +++ b/clang/test/CXX/drs/dr20xx.cpp @@ -49,18 +49,6 @@ namespace dr2026 { // dr2026: 11 } } -namespace dr2064 { // dr2064: 12 -#if __cplusplus >= 201103L - template struct X { - template struct Y {}; - }; - template void f() { - X::Y y; // ok - return X::f(); // expected-error {{no member named 'f' in 'dr2064::X= 201103L diff --git a/clang/test/CodeGenCXX/mangle-subst.cpp b/clang/test/CodeGenCXX/mangle-subst.cpp index 78b1408..20f33a7 100644 --- a/clang/test/CodeGenCXX/mangle-subst.cpp +++ b/clang/test/CodeGenCXX/mangle-subst.cpp @@ -96,14 +96,3 @@ typename X::template Y::type f(typename X::template Y::type2) { retu // CHECK: @_ZN12ManglePrefix1fIiEENS_1XIT_E1YIS2_E4typeENS5_5type2E template int f(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 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); } -} diff --git a/clang/test/Sema/invalid-bitwidth-expr.mm b/clang/test/Sema/invalid-bitwidth-expr.mm index 8ce498f..41ca949 100644 --- a/clang/test/Sema/invalid-bitwidth-expr.mm +++ b/clang/test/Sema/invalid-bitwidth-expr.mm @@ -26,7 +26,6 @@ template auto func() { // error-bit should be propagated from TemplateArgument to NestNameSpecifier. class Base::type C; // expected-error {{no matching function for call to 'Foo'}} - // expected-error@-1 {{no class named 'type' in 'Base'}} return C; } struct Z { diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index d7208f9..d6c67c0 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -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, ""); - static_assert(!TCT::MatchesArgs, ""); + static_assert(TCT::template MatchesArgs, ""); + static_assert(!TCT::template MatchesArgs, ""); } 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, ""); - static_assert(!TCT::MatchesArgs, ""); - static_assert(!TCT::MatchesArgs, ""); + static_assert(TCT::template MatchesArgs<>, ""); + static_assert(!TCT::template MatchesArgs, ""); + static_assert(!TCT::template MatchesArgs, ""); + static_assert(!TCT::template MatchesArgs, ""); // Ensure diagnostics are actually being generated here - static_assert(TCT::MatchesArgs, ""); // expected-error {{static_assert failed}} + static_assert(TCT::template MatchesArgs, ""); // 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, ""); + static_assert(TCT::template MatchesArgs, ""); } template static CoroMemberTag test_static_template(const char *volatile &, unsigned) { auto TC = co_yield 0; using TCT = decltype(TC); - static_assert(TCT::MatchesArgs, ""); - static_assert(!TCT::MatchesArgs, ""); + static_assert(TCT::template MatchesArgs, ""); + static_assert(!TCT::template MatchesArgs, ""); } }; -template struct DepTestType; // expected-note {{requested here}} +template struct DepTestType; // expected-note 2{{requested here}} template CoroMemberTag DepTestType::test_member_template(long, const char *) const &&; template CoroMemberTag DepTestType::test_static_template(const char *volatile &, unsigned); diff --git a/clang/test/SemaCXX/invalid-template-base-specifier.cpp b/clang/test/SemaCXX/invalid-template-base-specifier.cpp index 7760140..7a1a7f8 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(); } // expected-note {{in instantiation of template cl template using Alias = decltype(Foo(T())); // expected-error {{no matching function for call to 'Foo'}} template -struct Crash2 : decltype(Alias()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}} expected-error {{base specifier must name a class}} +struct Crash2 : decltype(Alias()) { // expected-note {{in instantiation of template type alias 'Alias' requested here}} Crash2(){}; }; -void test2() { Crash2(); } // expected-note 2{{in instantiation of template class 'Crash2' requested here}} +void test2() { Crash2(); } // expected-note {{in instantiation of template class 'Crash2' requested here}} template class Base {}; diff --git a/clang/test/SemaTemplate/dependent-expr.cpp b/clang/test/SemaTemplate/dependent-expr.cpp index dace7e2..abdb8e9 100644 --- a/clang/test/SemaTemplate/dependent-expr.cpp +++ b/clang/test/SemaTemplate/dependent-expr.cpp @@ -129,12 +129,7 @@ namespace PR45083 { template void f() { decltype(({})) x; // expected-error {{incomplete type}} } - template void f(); - - template void f2() { - decltype(({T();})) x; // expected-error {{incomplete type}} - } - template void f2(); // expected-note {{instantiation of}} + template void f(); // expected-note {{instantiation of}} template 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 b9a1c93..03ef78f 100644 --- a/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_template_cxx1z.cpp @@ -115,12 +115,6 @@ namespace Auto { int n; template struct SubstFailure; - TInt isf; // expected-error {{template template argument has different template parameters than its corresponding template template parameter}} + TInt isf; // FIXME: this should be ill-formed TIntPtr ipsf; - - template typename C> struct TAutoAutoFirst {}; - template struct AutoAutoFirst; - template struct AutoAutoSecond; - TAutoAutoFirst aaf; - TAutoAutoFirst 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 9be6f12..57093c1 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -12198,7 +12198,7 @@ and POD class 2064 CD4 Conflicting specifications for dependent decltype-specifiers - Clang 12 + Unknown 2065 -- 2.7.4