Author: Matheus Izvekov Date: 2026-03-17T13:30:18-03:00 New Revision: cb3e9eec5fe08a781e7c9838c72dbff10e799984
URL: https://github.com/llvm/llvm-project/commit/cb3e9eec5fe08a781e7c9838c72dbff10e799984 DIFF: https://github.com/llvm/llvm-project/commit/cb3e9eec5fe08a781e7c9838c72dbff10e799984.diff LOG: [clang] DeducedTypes deduction kind fix and improvement (#186727) This is a small refactor of how DeducedType and it's derived types are represented. The different deduction kinds are spelled out in an enum, and how this is tracked is simplified, to allow easier profiling. How these types are constructed and canonicalized is also brought more in line with how it works for the other types. This fixes a crash reported here: https://github.com/llvm/llvm-project/issues/167513#issuecomment-3692962115 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/AST/ASTContext.h clang/include/clang/AST/PropertiesBase.td clang/include/clang/AST/TextNodeDumper.h clang/include/clang/AST/TypeBase.h clang/include/clang/AST/TypeProperties.td clang/lib/AST/ASTContext.cpp clang/lib/AST/ASTImporter.cpp clang/lib/AST/TextNodeDumper.cpp clang/lib/AST/Type.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateDeductionGuide.cpp clang/lib/Sema/SemaType.cpp clang/lib/Sema/TreeTransform.h clang/test/AST/ast-dump-concepts.cpp clang/test/SemaTemplate/ctad.cpp clang/unittests/AST/ProfilingTest.cpp lldb/unittests/Symbol/TestTypeSystemClang.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7ed56ce6ae6a6..3dabf951661e5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -348,6 +348,7 @@ Bug Fixes to C++ Support - Fixed an incorrect template argument deduction when matching packs of template template parameters when one of its parameters is also a pack. (#GH181166) - Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639) +- Fixed an alias template CTAD crash. - Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741) - Fixed a crash when instantiating an invalid out-of-line static data member definition in a local class. (#GH176152) - Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8a3d202871cf8..40091acd878fd 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1840,12 +1840,6 @@ class ASTContext : public RefCountedBase<ASTContext> { QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args, const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const; - QualType - getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent, bool IsPack = false, - TemplateDecl *TypeConstraintConcept = nullptr, - ArrayRef<TemplateArgument> TypeConstraintArgs = {}, - bool IsCanon = false) const; public: QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, @@ -2085,8 +2079,7 @@ class ASTContext : public RefCountedBase<ASTContext> { /// C++11 deduced auto type. QualType - getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent, - bool IsPack = false, + getAutoType(DeducedKind DK, QualType DeducedAsType, AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept = nullptr, ArrayRef<TemplateArgument> TypeConstraintArgs = {}) const; @@ -2101,17 +2094,11 @@ class ASTContext : public RefCountedBase<ASTContext> { QualType getUnconstrainedType(QualType T) const; /// C++17 deduced class template specialization type. - QualType getDeducedTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - TemplateName Template, - QualType DeducedType, - bool IsDependent) const; - -private: - QualType getDeducedTemplateSpecializationTypeInternal( - ElaboratedTypeKeyword Keyword, TemplateName Template, - QualType DeducedType, bool IsDependent, QualType Canon) const; + QualType getDeducedTemplateSpecializationType(DeducedKind DK, + QualType DeducedAsType, + ElaboratedTypeKeyword Keyword, + TemplateName Template) const; -public: /// Return the unique type for "size_t" (C99 7.17), defined in /// <stddef.h>. /// diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 0011e57ed5ef7..fd3cce10be303 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -77,6 +77,7 @@ def APValueKind : EnumPropertyType<"APValue::ValueKind">; def ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">; def AttrKind : EnumPropertyType<"attr::Kind">; def Attr : PropertyType<"const Attr *">; +def DeducedKind : EnumPropertyType; def AutoTypeKeyword : EnumPropertyType; def Bool : PropertyType<"bool">; def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">; diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index ba68063eeae75..32e83ebb5c8eb 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -343,6 +343,7 @@ class TextNodeDumper void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); void VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); + void VisitDeducedType(const DeducedType *T); void VisitAutoType(const AutoType *T); void VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *T); diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index ec7845c3b3adb..8802b15d99034 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -1794,6 +1794,33 @@ enum RefQualifierKind { RQ_RValue }; +// The kind of type deduction represented by a DeducedType (ie AutoType). +enum class DeducedKind { + /// Not deduced yet. This is for example an 'auto' which was just parsed. + Undeduced, + + /// The normal deduced case. For example, an 'auto' which has been deduced to + /// 'int' will be of this kind, with 'int' as the deduced-as type. This is the + /// only case where the node is sugar. + Deduced, + + /// This is a special case where the initializer is dependent, so we can't + /// deduce a type yet. For example, 'auto x = V' where 'V' is a + /// value-dependent expression. + /// Formally we can't deduce an initializer which is dependent, because for + /// one reason it might be non-instantiable (ie it can contain a placeholder + /// dependent type such as DependentTy, which cannot be instantiated). + /// In general TreeTransform will turn these back to 'Undeduced' so we can try + /// to deduce them again. + DeducedAsDependent, + + /// Same as above, but additionally this represents a case where the deduced + /// entity itself is a pack. + /// This currently only happens for a lambda init-capture pack, which always + /// uses AutoType. + DeducedAsPack, +}; + /// Which keyword(s) were used to create an AutoType. enum class AutoTypeKeyword { /// auto @@ -2108,11 +2135,25 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { unsigned AttrKind : 32 - NumTypeBits; }; + class DeducedTypeBitfields { + friend class DeducedType; + + // One of the base classes uses the KeywordWrapper, so reserve those bits. + LLVM_PREFERRED_TYPE(KeywordWrapperBitfields) + unsigned : NumTypeWithKeywordBits; + + /// The kind of deduction this type represents, ie 'undeduced' or otherwise. + LLVM_PREFERRED_TYPE(DeducedKind) + unsigned Kind : 2; + }; + + static constexpr int NumDeducedTypeBits = NumTypeBits + 2; + class AutoTypeBitfields { friend class AutoType; - LLVM_PREFERRED_TYPE(TypeBitfields) - unsigned : NumTypeBits; + LLVM_PREFERRED_TYPE(DeducedTypeBitfields) + unsigned : NumDeducedTypeBits; /// Was this placeholder type spelled as 'auto', 'decltype(auto)', /// or '__auto_type'? AutoTypeKeyword value. @@ -2320,6 +2361,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { ArrayTypeBitfields ArrayTypeBits; ConstantArrayTypeBitfields ConstantArrayTypeBits; AttributedTypeBitfields AttributedTypeBits; + DeducedTypeBitfields DeducedTypeBits; AutoTypeBitfields AutoTypeBits; TypeOfBitfields TypeOfBits; TypedefBitfields TypedefBits; @@ -7232,17 +7274,20 @@ class DeducedType : public Type { QualType DeducedAsType; protected: - DeducedType(TypeClass TC, QualType DeducedAsType, - TypeDependence ExtraDependence, QualType Canon) - : Type(TC, Canon, - ExtraDependence | (DeducedAsType.isNull() - ? TypeDependence::None - : DeducedAsType->getDependence() & - ~TypeDependence::VariablyModified)), - DeducedAsType(DeducedAsType) {} + DeducedType(TypeClass TC, DeducedKind DK, QualType DeducedAsTypeOrCanon); + + static void Profile(llvm::FoldingSetNodeID &ID, DeducedKind DK, + QualType Deduced) { + ID.AddInteger(llvm::to_underlying(DK)); + Deduced.Profile(ID); + } public: - bool isSugared() const { return !DeducedAsType.isNull(); } + DeducedKind getDeducedKind() const { + return static_cast<DeducedKind>(DeducedTypeBits.Kind); + } + + bool isSugared() const { return getDeducedKind() == DeducedKind::Deduced; } QualType desugar() const { return isSugared() ? DeducedAsType : QualType(this, 0); } @@ -7250,9 +7295,7 @@ class DeducedType : public Type { /// Get the type deduced for this placeholder type, or null if it /// has not been deduced. QualType getDeducedType() const { return DeducedAsType; } - bool isDeduced() const { - return !DeducedAsType.isNull() || isDependentType(); - } + bool isDeduced() const { return getDeducedKind() != DeducedKind::Undeduced; } static bool classof(const Type *T) { return T->getTypeClass() == Auto || @@ -7262,13 +7305,13 @@ class DeducedType : public Type { /// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained /// by a type-constraint. -class AutoType : public DeducedType { +class AutoType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these TemplateDecl *TypeConstraintConcept; - AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, - TypeDependence ExtraDependence, QualType Canon, TemplateDecl *CD, + AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon, + AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs); public: @@ -7299,9 +7342,8 @@ class AutoType : public DeducedType { void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context); static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - QualType Deduced, AutoTypeKeyword Keyword, - bool IsDependent, TemplateDecl *CD, - ArrayRef<TemplateArgument> Arguments); + DeducedKind DK, QualType Deduced, AutoTypeKeyword Keyword, + TemplateDecl *CD, ArrayRef<TemplateArgument> Arguments); static bool classof(const Type *T) { return T->getTypeClass() == Auto; @@ -7316,34 +7358,35 @@ class DeducedTemplateSpecializationType : public KeywordWrapper<DeducedType>, /// The name of the template whose arguments will be deduced. TemplateName Template; - DeducedTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - TemplateName Template, - QualType DeducedAsType, - bool IsDeducedAsDependent, QualType Canon) - : KeywordWrapper(Keyword, DeducedTemplateSpecialization, DeducedAsType, - toTypeDependence(Template.getDependence()) | - (IsDeducedAsDependent - ? TypeDependence::DependentInstantiation - : TypeDependence::None), - Canon), - Template(Template) {} + DeducedTemplateSpecializationType(DeducedKind DK, + QualType DeducedAsTypeOrCanon, + ElaboratedTypeKeyword Keyword, + TemplateName Template) + : KeywordWrapper(Keyword, DeducedTemplateSpecialization, DK, + DeducedAsTypeOrCanon), + Template(Template) { + auto Dep = toTypeDependence(Template.getDependence()); + // A deduced AutoType only syntactically depends on its template name. + if (DK == DeducedKind::Deduced) + Dep = toSyntacticDependence(Dep); + addDependence(Dep); + } public: /// Retrieve the name of the template that we are deducing. TemplateName getTemplateName() const { return Template; } void Profile(llvm::FoldingSetNodeID &ID) const { - Profile(ID, getKeyword(), getTemplateName(), getDeducedType(), - isDependentType()); + Profile(ID, getDeducedKind(), getDeducedType(), getKeyword(), + getTemplateName()); } - static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - TemplateName Template, QualType Deduced, - bool IsDependent) { + static void Profile(llvm::FoldingSetNodeID &ID, DeducedKind DK, + QualType Deduced, ElaboratedTypeKeyword Keyword, + TemplateName Template) { + DeducedType::Profile(ID, DK, Deduced); ID.AddInteger(llvm::to_underlying(Keyword)); Template.Profile(ID); - Deduced.Profile(ID); - ID.AddBoolean(IsDependent || Template.isDependent()); } static bool classof(const Type *T) { diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index 350b748b804a3..0f3722b36774a 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -513,6 +513,9 @@ let Class = UnaryTransformType in { } let Class = AutoType in { + def : Property<"deducedKind", DeducedKind> { + let Read = [{ node->getDeducedKind() }]; + } def : Property<"deducedType", Optional<QualType>> { let Read = [{ makeOptionalFromNullable(node->getDeducedType()) }]; } @@ -526,18 +529,9 @@ let Class = AutoType in { def : Property<"typeConstraintArguments", Array<TemplateArgument>> { let Read = [{ node->getTypeConstraintArguments() }]; } - // FIXME: better enumerated value - // Only really required when the deduced type is null - def : Property<"dependence", UInt32> { - let Read = [{ !node->getDeducedType().isNull() ? 0 : - node->containsUnexpandedParameterPack() ? 2 : - node->isDependentType() ? 1 : 0 }]; - } def : Creator<[{ - return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword, - /*isDependentWithoutDeducedType*/ dependence > 0, - /*isPackWithoutDeducedType*/ dependence > 1, + return ctx.getAutoType(deducedKind, makeNullableFromOptional(deducedType), keyword, makePointerFromOptional(typeConstraintConcept), typeConstraintArguments); }]>; @@ -550,19 +544,16 @@ let Class = DeducedTemplateSpecializationType in { def : Property<"templateName", Optional<TemplateName>> { let Read = [{ makeOptionalFromNullable(node->getTemplateName()) }]; } + def : Property<"deducedKind", DeducedKind> { + let Read = [{ node->getDeducedKind() }]; + } def : Property<"deducedType", QualType> { let Read = [{ node->getDeducedType() }]; } - // Only really required when the deduced type is null - def : Property<"dependent", Bool> { - let Read = [{ !node->getDeducedType().isNull() - ? false : node->isDependentType() }]; - } def : Creator<[{ - return ctx.getDeducedTemplateSpecializationType(keyword, - makeNullableFromOptional(templateName), - deducedType, dependent); + return ctx.getDeducedTemplateSpecializationType(deducedKind, deducedType, keyword, + makeNullableFromOptional(templateName)); }]>; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 19e5609160a99..41852c960cc46 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6791,52 +6791,49 @@ ASTContext::getUnaryTransformType(QualType BaseType, QualType UnderlyingType, return QualType(UT, 0); } -QualType ASTContext::getAutoTypeInternal( - QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent, - bool IsPack, TemplateDecl *TypeConstraintConcept, - ArrayRef<TemplateArgument> TypeConstraintArgs, bool IsCanon) const { - if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && - !TypeConstraintConcept && !IsDependent) +/// getAutoType - Return the uniqued reference to the 'auto' type which has been +/// deduced to the given type, or to the canonical undeduced 'auto' type, or the +/// canonical deduced-but-dependent 'auto' type. +QualType +ASTContext::getAutoType(DeducedKind DK, QualType DeducedAsType, + AutoTypeKeyword Keyword, + TemplateDecl *TypeConstraintConcept, + ArrayRef<TemplateArgument> TypeConstraintArgs) const { + if (DK == DeducedKind::Undeduced && Keyword == AutoTypeKeyword::Auto && + !TypeConstraintConcept) { + assert(DeducedAsType.isNull() && ""); + assert(TypeConstraintArgs.empty() && ""); return getAutoDeductType(); + } // Look in the folding set for an existing type. llvm::FoldingSetNodeID ID; - bool IsDeducedDependent = - isa_and_nonnull<TemplateTemplateParmDecl>(TypeConstraintConcept) || - (!DeducedType.isNull() && DeducedType->isDependentType()); - AutoType::Profile(ID, *this, DeducedType, Keyword, - IsDependent || IsDeducedDependent, TypeConstraintConcept, - TypeConstraintArgs); + AutoType::Profile(ID, *this, DK, DeducedAsType, Keyword, + TypeConstraintConcept, TypeConstraintArgs); if (auto const AT_iter = AutoTypes.find(ID); AT_iter != AutoTypes.end()) return QualType(AT_iter->getSecond(), 0); - QualType Canon; - if (!IsCanon) { - if (!DeducedType.isNull()) { - Canon = DeducedType.getCanonicalType(); - } else if (TypeConstraintConcept) { + if (DK == DeducedKind::Deduced) { + assert(!DeducedAsType.isNull() && "deduced type must be provided"); + } else { + assert(DeducedAsType.isNull() && "deduced type must not be provided"); + if (TypeConstraintConcept) { bool AnyNonCanonArgs = false; auto *CanonicalConcept = cast<TemplateDecl>(TypeConstraintConcept->getCanonicalDecl()); auto CanonicalConceptArgs = ::getCanonicalTemplateArguments( *this, TypeConstraintArgs, AnyNonCanonArgs); - if (CanonicalConcept != TypeConstraintConcept || AnyNonCanonArgs) { - Canon = getAutoTypeInternal(QualType(), Keyword, IsDependent, IsPack, - CanonicalConcept, CanonicalConceptArgs, - /*IsCanon=*/true); - } + if (TypeConstraintConcept != CanonicalConcept || AnyNonCanonArgs) + DeducedAsType = getAutoType(DK, QualType(), Keyword, CanonicalConcept, + CanonicalConceptArgs); } } void *Mem = Allocate(sizeof(AutoType) + sizeof(TemplateArgument) * TypeConstraintArgs.size(), alignof(AutoType)); - auto *AT = new (Mem) AutoType( - DeducedType, Keyword, - (IsDependent ? TypeDependence::DependentInstantiation - : TypeDependence::None) | - (IsPack ? TypeDependence::UnexpandedPack : TypeDependence::None), - Canon, TypeConstraintConcept, TypeConstraintArgs); + auto *AT = new (Mem) AutoType(DK, DeducedAsType, Keyword, + TypeConstraintConcept, TypeConstraintArgs); #ifndef NDEBUG llvm::FoldingSetNodeID InsertedID; AT->Profile(InsertedID, *this); @@ -6847,21 +6844,6 @@ QualType ASTContext::getAutoTypeInternal( return QualType(AT, 0); } -/// getAutoType - Return the uniqued reference to the 'auto' type which has been -/// deduced to the given type, or to the canonical undeduced 'auto' type, or the -/// canonical deduced-but-dependent 'auto' type. -QualType -ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent, bool IsPack, - TemplateDecl *TypeConstraintConcept, - ArrayRef<TemplateArgument> TypeConstraintArgs) const { - assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack"); - assert((!IsDependent || DeducedType.isNull()) && - "A dependent auto should be undeduced"); - return getAutoTypeInternal(DeducedType, Keyword, IsDependent, IsPack, - TypeConstraintConcept, TypeConstraintArgs); -} - QualType ASTContext::getUnconstrainedType(QualType T) const { QualType CanonT = T.getNonPackExpansionType().getCanonicalType(); @@ -6869,10 +6851,9 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { if (auto *AT = CanonT->getAs<AutoType>()) { if (!AT->isConstrained()) return T; - return getQualifiedType(getAutoType(QualType(), AT->getKeyword(), - AT->isDependentType(), - AT->containsUnexpandedParameterPack()), - T.getQualifiers()); + return getQualifiedType( + getAutoType(AT->getDeducedKind(), QualType(), AT->getKeyword()), + T.getQualifiers()); } // FIXME: We only support constrained auto at the top level in the type of a @@ -6883,21 +6864,46 @@ QualType ASTContext::getUnconstrainedType(QualType T) const { return T; } -QualType ASTContext::getDeducedTemplateSpecializationTypeInternal( - ElaboratedTypeKeyword Keyword, TemplateName Template, QualType DeducedType, - bool IsDependent, QualType Canon) const { +/// Return the uniqued reference to the deduced template specialization type +/// which has been deduced to the given type, or to the canonical undeduced +/// such type, or the canonical deduced-but-dependent such type. +QualType ASTContext::getDeducedTemplateSpecializationType( + DeducedKind DK, QualType DeducedAsType, ElaboratedTypeKeyword Keyword, + TemplateName Template) const { + // DeducedAsPack only ever occurs for lambda init-capture pack, which always + // use AutoType. + assert(DK != DeducedKind::DeducedAsPack && + "unexpected DeducedAsPack for DeducedTemplateSpecializationType"); + // Look in the folding set for an existing type. void *InsertPos = nullptr; llvm::FoldingSetNodeID ID; - DeducedTemplateSpecializationType::Profile(ID, Keyword, Template, DeducedType, - IsDependent); + DeducedTemplateSpecializationType::Profile(ID, DK, DeducedAsType, Keyword, + Template); if (DeducedTemplateSpecializationType *DTST = DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(DTST, 0); + if (DK == DeducedKind::Deduced) { + assert(!DeducedAsType.isNull() && "deduced type must be provided"); + } else { + assert(DeducedAsType.isNull() && "deduced type must not be provided"); + TemplateName CanonTemplateName = getCanonicalTemplateName(Template); + // FIXME: Can this be formed from a DependentTemplateName, such that the + // keyword should be part of the canonical type? + if (Keyword != ElaboratedTypeKeyword::None || + Template != CanonTemplateName) { + DeducedAsType = getDeducedTemplateSpecializationType( + DK, QualType(), ElaboratedTypeKeyword::None, CanonTemplateName); + // Find the insertion position again. + [[maybe_unused]] DeducedTemplateSpecializationType *DTST = + DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!DTST && "broken canonicalization"); + } + } + auto *DTST = new (*this, alignof(DeducedTemplateSpecializationType)) - DeducedTemplateSpecializationType(Keyword, Template, DeducedType, - IsDependent, Canon); + DeducedTemplateSpecializationType(DK, DeducedAsType, Keyword, Template); #ifndef NDEBUG llvm::FoldingSetNodeID TempID; @@ -6909,26 +6915,6 @@ QualType ASTContext::getDeducedTemplateSpecializationTypeInternal( return QualType(DTST, 0); } -/// Return the uniqued reference to the deduced template specialization type -/// which has been deduced to the given type, or to the canonical undeduced -/// such type, or the canonical deduced-but-dependent such type. -QualType ASTContext::getDeducedTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, TemplateName Template, QualType DeducedType, - bool IsDependent) const { - // FIXME: This could save an extra hash table lookup if it handled all the - // parameters already being canonical. - // FIXME: Can this be formed from a DependentTemplateName, such that the - // keyword should be part of the canonical type? - QualType Canon = - DeducedType.isNull() - ? getDeducedTemplateSpecializationTypeInternal( - ElaboratedTypeKeyword::None, getCanonicalTemplateName(Template), - QualType(), IsDependent, QualType()) - : DeducedType.getCanonicalType(); - return getDeducedTemplateSpecializationTypeInternal( - Keyword, Template, DeducedType, IsDependent, Canon); -} - /// getAtomicType - Return the uniqued reference to the atomic type for /// the given value type. QualType ASTContext::getAtomicType(QualType T) const { @@ -6961,9 +6947,10 @@ QualType ASTContext::getAtomicType(QualType T) const { QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) AutoDeductTy = QualType(new (*this, alignof(AutoType)) - AutoType(QualType(), AutoTypeKeyword::Auto, - TypeDependence::None, QualType(), - /*concept*/ nullptr, /*args*/ {}), + AutoType(DeducedKind::Undeduced, QualType(), + AutoTypeKeyword::Auto, + /*TypeConstraintConcept=*/nullptr, + /*TypeConstraintArgs=*/{}), 0); return AutoDeductTy; } @@ -14286,19 +14273,20 @@ static QualType getCommonNonSugarTypeNode(const ASTContext &Ctx, const Type *X, case Type::Auto: { const auto *AX = cast<AutoType>(X), *AY = cast<AutoType>(Y); - assert(AX->getDeducedType().isNull()); - assert(AY->getDeducedType().isNull()); + assert(AX->getDeducedKind() == AY->getDeducedKind()); + assert(AX->getDeducedKind() != DeducedKind::Deduced); assert(AX->getKeyword() == AY->getKeyword()); - assert(AX->isInstantiationDependentType() == - AY->isInstantiationDependentType()); - auto As = getCommonTemplateArguments(Ctx, AX->getTypeConstraintArguments(), - AY->getTypeConstraintArguments()); - return Ctx.getAutoType(QualType(), AX->getKeyword(), - AX->isInstantiationDependentType(), - AX->containsUnexpandedParameterPack(), - getCommonDeclChecked(AX->getTypeConstraintConcept(), - AY->getTypeConstraintConcept()), - As); + TemplateDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(), + AY->getTypeConstraintConcept()); + SmallVector<TemplateArgument, 8> As; + if (CD && + getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(), + AY->getTypeConstraintArguments())) { + CD = nullptr; // The arguments diff er, so make it unconstrained. + As.clear(); + } + return Ctx.getAutoType(AX->getDeducedKind(), QualType(), AX->getKeyword(), + CD, As); } case Type::IncompleteArray: { const auto *AX = cast<IncompleteArrayType>(X), @@ -14672,6 +14660,8 @@ static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X, } case Type::Auto: { const auto *AX = cast<AutoType>(X), *AY = cast<AutoType>(Y); + assert(AX->getDeducedKind() == DeducedKind::Deduced); + assert(AY->getDeducedKind() == DeducedKind::Deduced); AutoTypeKeyword KW = AX->getKeyword(); if (KW != AY->getKeyword()) @@ -14689,8 +14679,9 @@ static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X, // Both auto types can't be dependent, otherwise they wouldn't have been // sugar. This implies they can't contain unexpanded packs either. - return Ctx.getAutoType(Ctx.getQualifiedType(Underlying), AX->getKeyword(), - /*IsDependent=*/false, /*IsPack=*/false, CD, As); + return Ctx.getAutoType(DeducedKind::Deduced, + Ctx.getQualifiedType(Underlying), AX->getKeyword(), + CD, As); } case Type::PackIndexing: case Type::Decltype: diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 340a0fb4fb5aa..df7c3928ae23c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1733,9 +1733,10 @@ ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { if (!ToDeducedTypeOrErr) return ToDeducedTypeOrErr.takeError(); - ExpectedDecl ToTypeConstraintConcept = import(T->getTypeConstraintConcept()); - if (!ToTypeConstraintConcept) - return ToTypeConstraintConcept.takeError(); + Expected<TemplateDecl *> ToTypeConstraint = + import(T->getTypeConstraintConcept()); + if (!ToTypeConstraint) + return ToTypeConstraint.takeError(); SmallVector<TemplateArgument, 2> ToTemplateArgs; if (Error Err = ImportTemplateArguments(T->getTypeConstraintArguments(), @@ -1743,9 +1744,8 @@ ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { return std::move(Err); return Importer.getToContext().getAutoType( - *ToDeducedTypeOrErr, T->getKeyword(), /*IsDependent*/false, - /*IsPack=*/false, cast_or_null<ConceptDecl>(*ToTypeConstraintConcept), - ToTemplateArgs); + T->getDeducedKind(), *ToDeducedTypeOrErr, T->getKeyword(), + *ToTypeConstraint, ToTemplateArgs); } ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType( @@ -1759,8 +1759,8 @@ ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType( return ToDeducedTypeOrErr.takeError(); return Importer.getToContext().getDeducedTemplateSpecializationType( - T->getKeyword(), *ToTemplateNameOrErr, *ToDeducedTypeOrErr, - T->isDependentType()); + T->getDeducedKind(), *ToDeducedTypeOrErr, T->getKeyword(), + *ToTemplateNameOrErr); } ExpectedType ASTNodeImporter::VisitTagType(const TagType *T) { diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 89d2a2691e8fb..250ec8b666e05 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -2227,17 +2227,33 @@ void TextNodeDumper::VisitSubstTemplateTypeParmPackType( VisitTemplateTypeParmDecl(T->getReplacedParameter()); } -void TextNodeDumper::VisitAutoType(const AutoType *T) { - if (T->isDecltypeAuto()) - OS << " decltype(auto)"; - if (!T->isDeduced()) +void TextNodeDumper::VisitDeducedType(const DeducedType *T) { + switch (T->getDeducedKind()) { + case DeducedKind::Undeduced: OS << " undeduced"; + break; + case DeducedKind::Deduced: + break; + case DeducedKind::DeducedAsDependent: + OS << " deduced-as-dependent"; + break; + case DeducedKind::DeducedAsPack: + OS << " deduced-as-pack"; + break; + } +} + +void TextNodeDumper::VisitAutoType(const AutoType *T) { + VisitDeducedType(T); + // Not necessary to dump the keyword since it's spelled plainly in the printed + // type anyway. if (T->isConstrained()) dumpDeclRef(T->getTypeConstraintConcept()); } void TextNodeDumper::VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *T) { + VisitDeducedType(T); dumpTemplateName(T->getTemplateName(), "name"); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 18695b7291440..a351bc34af798 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1327,11 +1327,11 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> { if (deducedType.isNull()) return {}; - if (deducedType.getAsOpaquePtr() == T->getDeducedType().getAsOpaquePtr()) + if (deducedType == T->getDeducedType()) return QualType(T, 0); - return Ctx.getAutoType(deducedType, T->getKeyword(), T->isDependentType(), - /*IsPack=*/false, T->getTypeConstraintConcept(), + return Ctx.getAutoType(T->getDeducedKind(), deducedType, T->getKeyword(), + T->getTypeConstraintConcept(), T->getTypeConstraintArguments()); } @@ -5545,46 +5545,74 @@ void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, llvm::APFixedPoint(Val, FXSema).toString(Str); } -AutoType::AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, - TypeDependence ExtraDependence, QualType Canon, - TemplateDecl *TypeConstraintConcept, +DeducedType::DeducedType(TypeClass TC, DeducedKind DK, + QualType DeducedAsTypeOrCanon) + : Type(TC, /*canon=*/DK == DeducedKind::Deduced + ? DeducedAsTypeOrCanon.getCanonicalType() + : DeducedAsTypeOrCanon, + TypeDependence::None) { + DeducedTypeBits.Kind = llvm::to_underlying(DK); + switch (DK) { + case DeducedKind::Undeduced: + break; + case DeducedKind::Deduced: + assert(!DeducedAsTypeOrCanon.isNull() && "Deduced type cannot be null"); + addDependence(DeducedAsTypeOrCanon->getDependence() & + ~TypeDependence::VariablyModified); + DeducedAsType = DeducedAsTypeOrCanon; + break; + case DeducedKind::DeducedAsPack: + addDependence(TypeDependence::UnexpandedPack); + [[fallthrough]]; + case DeducedKind::DeducedAsDependent: + addDependence(TypeDependence::DependentInstantiation); + break; + } + assert(getDeducedKind() == DK && "DeducedKind does not match the type state"); +} + +AutoType::AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon, + AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) - : DeducedType(Auto, DeducedAsType, ExtraDependence, Canon) { + : DeducedType(Auto, DK, DeducedAsTypeOrCanon) { AutoTypeBits.Keyword = llvm::to_underlying(Keyword); AutoTypeBits.NumArgs = TypeConstraintArgs.size(); this->TypeConstraintConcept = TypeConstraintConcept; assert(TypeConstraintConcept || AutoTypeBits.NumArgs == 0); if (TypeConstraintConcept) { - if (isa<TemplateTemplateParmDecl>(TypeConstraintConcept)) - addDependence(TypeDependence::DependentInstantiation); + auto Dep = TypeDependence::None; + if (const auto *TTP = + dyn_cast<TemplateTemplateParmDecl>(TypeConstraintConcept)) + Dep = TypeDependence::DependentInstantiation | + (TTP->isParameterPack() ? TypeDependence::UnexpandedPack + : TypeDependence::None); auto *ArgBuffer = const_cast<TemplateArgument *>(getTypeConstraintArguments().data()); for (const TemplateArgument &Arg : TypeConstraintArgs) { - // We only syntactically depend on the constraint arguments. They don't - // affect the deduced type, only its validity. - addDependence( - toSyntacticDependence(toTypeDependence(Arg.getDependence()))); - + Dep |= toTypeDependence(Arg.getDependence()); new (ArgBuffer++) TemplateArgument(Arg); } + // A deduced AutoType only syntactically depends on its constraints. + if (DK == DeducedKind::Deduced) + Dep = toSyntacticDependence(Dep); + addDependence(Dep); } } void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, - QualType Deduced, AutoTypeKeyword Keyword, - bool IsDependent, TemplateDecl *CD, + DeducedKind DK, QualType Deduced, + AutoTypeKeyword Keyword, TemplateDecl *CD, ArrayRef<TemplateArgument> Arguments) { - ID.AddPointer(Deduced.getAsOpaquePtr()); - ID.AddInteger((unsigned)Keyword); - ID.AddBoolean(IsDependent); + DeducedType::Profile(ID, DK, Deduced); + ID.AddInteger(llvm::to_underlying(Keyword)); ID.AddPointer(CD); for (const TemplateArgument &Arg : Arguments) Arg.Profile(ID, Context); } void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(), + Profile(ID, Context, getDeducedKind(), getDeducedType(), getKeyword(), getTypeConstraintConcept(), getTypeConstraintArguments()); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ac38f32882d9b..52946e0ca3cb1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -589,7 +589,8 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, SS ? SS->getScopeRep() : std::nullopt, /*TemplateKeyword=*/false, FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD)); QualType T = Context.getDeducedTemplateSpecializationType( - ElaboratedTypeKeyword::None, Template, QualType(), false); + DeducedKind::Undeduced, QualType(), ElaboratedTypeKeyword::None, + Template); auto TL = TLB.push<DeducedTemplateSpecializationTypeLoc>(T); TL.setElaboratedKeywordLoc(SourceLocation()); TL.setNameLoc(NameLoc); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9194ee5e2bee9..c3ff9f83be364 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -11419,7 +11419,8 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, QualifierLoc.getNestedNameSpecifier(), /*TemplateKeyword=*/false, TemplateName(TD)); return Context.getDeducedTemplateSpecializationType( - Keyword, Name, /*DeducedType=*/QualType(), /*IsDependent=*/false); + DeducedKind::Undeduced, /*DeducedAsType=*/QualType(), Keyword, + Name); } } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 477af31def50e..265e5f4d2491d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5042,21 +5042,27 @@ namespace { /// specifier within a type for a given replacement type. class SubstituteDeducedTypeTransform : public TreeTransform<SubstituteDeducedTypeTransform> { + DeducedKind DK; QualType Replacement; - bool ReplacementIsPack; bool UseTypeSugar; using inherited = TreeTransform<SubstituteDeducedTypeTransform>; public: SubstituteDeducedTypeTransform(Sema &SemaRef, DependentAuto DA) : TreeTransform<SubstituteDeducedTypeTransform>(SemaRef), - ReplacementIsPack(DA.IsPack), UseTypeSugar(true) {} + DK(DA.IsPack ? DeducedKind::DeducedAsPack + : DeducedKind::DeducedAsDependent), + UseTypeSugar(true) {} SubstituteDeducedTypeTransform(Sema &SemaRef, QualType Replacement, bool UseTypeSugar = true) : TreeTransform<SubstituteDeducedTypeTransform>(SemaRef), - Replacement(Replacement), ReplacementIsPack(false), - UseTypeSugar(UseTypeSugar) {} + DK(Replacement.isNull() ? DeducedKind::Undeduced + : DeducedKind::Deduced), + Replacement(Replacement), UseTypeSugar(UseTypeSugar) { + assert((!Replacement.isNull() || UseTypeSugar) && + "An undeduced auto type is never type sugar"); + } QualType TransformDesugared(TypeLocBuilder &TLB, DeducedTypeLoc TL) { assert(isa<TemplateTypeParmType>(Replacement) && @@ -5081,8 +5087,8 @@ namespace { return TransformDesugared(TLB, TL); QualType Result = SemaRef.Context.getAutoType( - Replacement, TL.getTypePtr()->getKeyword(), Replacement.isNull(), - ReplacementIsPack, TL.getTypePtr()->getTypeConstraintConcept(), + DK, Replacement, TL.getTypePtr()->getKeyword(), + TL.getTypePtr()->getTypeConstraintConcept(), TL.getTypePtr()->getTypeConstraintArguments()); auto NewTL = TLB.push<AutoTypeLoc>(Result); NewTL.copy(TL); @@ -5095,8 +5101,8 @@ namespace { return TransformDesugared(TLB, TL); QualType Result = SemaRef.Context.getDeducedTemplateSpecializationType( - TL.getTypePtr()->getKeyword(), TL.getTypePtr()->getTemplateName(), - Replacement, Replacement.isNull()); + DK, Replacement, TL.getTypePtr()->getKeyword(), + TL.getTypePtr()->getTemplateName()); auto NewTL = TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setNameLoc(TL.getNameLoc()); diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index ccac3d9ba0a72..8d55fb087193f 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -1027,9 +1027,9 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef, SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = { Context.getTrivialTypeSourceInfo( Context.getDeducedTemplateSpecializationType( - ElaboratedTypeKeyword::None, TemplateName(AliasTemplate), - /*DeducedType=*/QualType(), - /*IsDependent=*/true), + DeducedKind::DeducedAsDependent, + /*DeducedAsType=*/QualType(), ElaboratedTypeKeyword::None, + TemplateName(AliasTemplate)), AliasTemplate->getLocation()), // template specialization type whose // arguments will be deduced. Context.getTrivialTypeSourceInfo( diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 2918538ac0f64..846474fe94adf 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1338,14 +1338,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { declarator.setInvalidType(true); } } - Result = S.Context.getAutoType(QualType(), AutoKW, - /*IsDependent*/ false, /*IsPack=*/false, + Result = S.Context.getAutoType(DeducedKind::Undeduced, QualType(), AutoKW, TypeConstraintConcept, TemplateArgs); break; } case DeclSpec::TST_auto_type: - Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false); + Result = Context.getAutoType(DeducedKind::Undeduced, QualType(), + AutoTypeKeyword::GNUAutoType); break; case DeclSpec::TST_unknown_anytype: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b5272d262530c..8ae5df367e0dd 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1138,24 +1138,21 @@ class TreeTransform { /// Build a new C++11 auto type. /// /// By default, builds a new AutoType with the given deduced type. - QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword, + QualType RebuildAutoType(DeducedKind DK, QualType DeducedAsType, + AutoTypeKeyword Keyword, ConceptDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) { - // Note, IsDependent is always false here: we implicitly convert an 'auto' - // which has been deduced to a dependent type into an undeduced 'auto', so - // that we'll retry deduction after the transformation. - return SemaRef.Context.getAutoType(Deduced, Keyword, - /*IsDependent*/ false, /*IsPack=*/false, - TypeConstraintConcept, - TypeConstraintArgs); + return SemaRef.Context.getAutoType( + DK, DeducedAsType, Keyword, TypeConstraintConcept, TypeConstraintArgs); } /// By default, builds a new DeducedTemplateSpecializationType with the given /// deduced type. QualType RebuildDeducedTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, TemplateName Template, QualType Deduced) { + DeducedKind DK, QualType DeducedAsType, ElaboratedTypeKeyword Keyword, + TemplateName Template) { return SemaRef.Context.getDeducedTemplateSpecializationType( - Keyword, Template, Deduced, /*IsDependent*/ false); + DK, DeducedAsType, Keyword, Template); } /// Build a new template specialization type. @@ -5616,9 +5613,8 @@ QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T, Qs.removeObjCLifetime(); Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), Qs); - T = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(), - AutoTy->isDependentType(), - /*isPack=*/false, + T = SemaRef.Context.getAutoType(AutoTy->getDeducedKind(), Deduced, + AutoTy->getKeyword(), AutoTy->getTypeConstraintConcept(), AutoTy->getTypeConstraintArguments()); } else { @@ -7240,7 +7236,8 @@ QualType TreeTransform<Derived>::TransformDeducedTemplateSpecializationType( } QualType Result = getDerived().RebuildDeducedTemplateSpecializationType( - T->getKeyword(), TemplateName, NewDeduced); + NewDeduced.isNull() ? DeducedKind::Undeduced : DeducedKind::Deduced, + NewDeduced, T->getKeyword(), TemplateName); if (Result.isNull()) return QualType(); @@ -7581,8 +7578,9 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, NewArgList.reserve(NewTemplateArgs.size()); for (const auto &ArgLoc : NewTemplateArgs.arguments()) NewArgList.push_back(ArgLoc.getArgument()); - Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword(), NewCD, - NewArgList); + Result = getDerived().RebuildAutoType( + NewDeduced.isNull() ? DeducedKind::Undeduced : DeducedKind::Deduced, + NewDeduced, T->getKeyword(), NewCD, NewArgList); if (Result.isNull()) return QualType(); } diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 9419dba057a4e..5c99bd82a451f 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -4,6 +4,7 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -std=c++20 -triple x86_64-unknown-unknown -include-pch %t \ // RUN: -ast-dump-all -ast-dump-decl-types -ast-dump-filter Foo /dev/null \ +// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \ // RUN: | FileCheck --strict-whitespace %s template <typename T> @@ -19,7 +20,7 @@ template <typename T> struct Foo { // CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'binary_concept' // CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:13, col:31> 'bool' Concept {{.*}} 'binary_concept' - // CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:13:9> col:9 + // CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:{{.+}}:9> col:9 // CHECK-NEXT: | |-TemplateArgument type 'R' // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0 // CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'R' @@ -35,7 +36,7 @@ struct Foo { // CHECK: TemplateTypeParmDecl {{.*}} referenced Concept {{.*}} 'unary_concept' // CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:13> 'bool' - // CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:10:9> col:9 + // CHECK-NEXT: |-ImplicitConceptSpecializationDecl {{.*}} <line:{{.+}}:9> col:9 // CHECK-NEXT: | `-TemplateArgument type 'R' // CHECK-NEXT: | `-TemplateTypeParmType {{.*}} 'R' dependent {{.*}}depth 1 index 0 // CHECK-NEXT: | `-TemplateTypeParm {{.*}} 'R' @@ -58,7 +59,7 @@ struct Foo { // CHECK: CXXFoldExpr {{.*}} <col:13, col:34> template <variadic_concept<int>... Ts> Foo(); - + // CHECK:InjectedClassNameType // CHECK-NEXT: CXXRecord {{.*}} 'Foo' }; @@ -133,5 +134,10 @@ void g(C<T> auto Foo) {} // CHECK: TemplateTypeParmDecl {{.*}} depth 0 index 1 Foo:auto // CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:8, col:11> - } + +namespace constraint_auto_return { + template <class T, class K> concept D = true; + template<class T> D<T> auto Foo() { return T(); } + // CHECK: AutoType {{.*}} 'D<T> auto' dependent deduced-as-dependent +} // namespace constraint_auto_return diff --git a/clang/test/SemaTemplate/ctad.cpp b/clang/test/SemaTemplate/ctad.cpp index 60603f0c963a5..52ffef980fcdf 100644 --- a/clang/test/SemaTemplate/ctad.cpp +++ b/clang/test/SemaTemplate/ctad.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx17 %s +// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx17 %s -Wno-c++20-extensions // RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20 %s namespace pr41427 { @@ -116,3 +116,11 @@ template <class T, class> struct S { S<int, int>::I i; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'S<int, int>::I'}} \ // expected-note{{while building implicit deduction guide first needed here}} } + +namespace GH167513 { + template <class T, T> struct A { + A(T) {} + }; + template <class T> using AA = A<T, T{}>; + AA b{0}; +} // namespace GH167513 diff --git a/clang/unittests/AST/ProfilingTest.cpp b/clang/unittests/AST/ProfilingTest.cpp index b46bade186301..463e6bfee3152 100644 --- a/clang/unittests/AST/ProfilingTest.cpp +++ b/clang/unittests/AST/ProfilingTest.cpp @@ -64,10 +64,12 @@ TEST(Profiling, DeducedTemplateSpecializationType_Name) { auto *T1 = cast<DeducedTemplateSpecializationType>( Ctx.getDeducedTemplateSpecializationType( - ElaboratedTypeKeyword::None, TemplateName(CTD1), QualType(), false)); + DeducedKind::Undeduced, /*DeducedAsType=*/QualType(), + ElaboratedTypeKeyword::None, TemplateName(CTD1))); auto *T2 = cast<DeducedTemplateSpecializationType>( Ctx.getDeducedTemplateSpecializationType( - ElaboratedTypeKeyword::None, TemplateName(CTD2), QualType(), false)); + DeducedKind::Undeduced, /*DeducedAsType=*/QualType(), + ElaboratedTypeKeyword::None, TemplateName(CTD2))); testTypeNode(T1, T2); } diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index d8d95f17e5104..51fe871e89261 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -40,7 +40,6 @@ class TestTypeSystemClang : public testing::Test { } protected: - TypeSystemClang *m_ast = nullptr; std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder; @@ -747,8 +746,9 @@ TEST_F(TestTypeSystemClang, TemplateArguments) { CompilerType auto_type( m_ast->weak_from_this(), m_ast->getASTContext() - .getAutoType(ClangUtil::GetCanonicalQualType(typedef_type), - clang::AutoTypeKeyword::Auto, false) + .getAutoType(clang::DeducedKind::Deduced, + ClangUtil::GetCanonicalQualType(typedef_type), + clang::AutoTypeKeyword::Auto) .getAsOpaquePtr()); CompilerType int_type(m_ast->weak_from_this(), _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
