diff options
22 files changed, 224 insertions, 316 deletions
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 5b10127..f5cc1ba 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -785,14 +785,9 @@ let Class = PropertyTypeCase<TemplateArgument, "Null"> in { }]>; } let Class = PropertyTypeCase<TemplateArgument, "Type"> in { - def : Property<"type", QualType> { - let Read = [{ node.getAsType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } + def : Property<"type", QualType> { let Read = [{ node.getAsType() }]; } def : Creator<[{ - return TemplateArgument(type, /* isNullPtr */ false, isDefaulted); + return TemplateArgument(type, /* isNullPtr=*/false); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in { @@ -802,36 +797,23 @@ let Class = PropertyTypeCase<TemplateArgument, "Declaration"> in { def : Property<"parameterType", QualType> { let Read = [{ node.getParamTypeForDecl() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(declaration, parameterType, isDefaulted); + return TemplateArgument(declaration, parameterType); }]>; } let Class = PropertyTypeCase<TemplateArgument, "NullPtr"> in { - def : Property<"type", QualType> { - let Read = [{ node.getNullPtrType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } + def : Property<"type", QualType> { let Read = [{ node.getNullPtrType() }]; } def : Creator<[{ - return TemplateArgument(type, /*nullptr*/ true, isDefaulted); + return TemplateArgument(type, /*IsNullPtr=*/true); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Integral"> in { def : Property<"value", APSInt> { let Read = [{ node.getAsIntegral() }]; } - def : Property<"type", QualType> { - let Read = [{ node.getIntegralType() }]; - } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } + def : Property<"type", QualType> { let Read = [{ node.getIntegralType() }]; } def : Creator<[{ - return TemplateArgument(ctx, value, type, isDefaulted); + return TemplateArgument(ctx, value, type); }]>; } let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { @@ -841,22 +823,16 @@ let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in { def : Property<"type", QualType> { let Read = [{ node.getStructuralValueType() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(ctx, type, value, isDefaulted); + return TemplateArgument(ctx, type, value); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Template"> in { def : Property<"name", TemplateName> { let Read = [{ node.getAsTemplateOrTemplatePattern() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(name, isDefaulted); + return TemplateArgument(name); }]>; } let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in { @@ -868,11 +844,8 @@ let Class = PropertyTypeCase<TemplateArgument, "TemplateExpansion"> in { node.getNumTemplateExpansions() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(name, numExpansions, isDefaulted); + return TemplateArgument(name, numExpansions); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Expression"> in { @@ -882,11 +855,8 @@ let Class = PropertyTypeCase<TemplateArgument, "Expression"> in { def : Property<"IsCanonical", Bool> { let Read = [{ node.isCanonicalExpr() }]; } - def : Property<"isDefaulted", Bool> { - let Read = [{ node.getIsDefaulted() }]; - } def : Creator<[{ - return TemplateArgument(expression, IsCanonical, isDefaulted); + return TemplateArgument(expression, IsCanonical); }]>; } let Class = PropertyTypeCase<TemplateArgument, "Pack"> in { diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index 69481e8..46e8437 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -113,8 +113,6 @@ private: struct DA { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; void *QT; ValueDecl *D; }; @@ -122,13 +120,11 @@ private: LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; + unsigned IsUnsigned : 1; // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple // TemplateArgument instances. unsigned BitWidth : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsUnsigned : 1; union { /// Used to store the <= 64 bits integer value. uint64_t VAL; @@ -141,24 +137,18 @@ private: struct V { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; APValue *Value; void *Type; }; struct A { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; unsigned NumArgs; const TemplateArgument *Args; }; struct TA { LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; - LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; UnsignedOrNone NumExpansions; void *Name; }; @@ -166,8 +156,6 @@ private: LLVM_PREFERRED_TYPE(ArgKind) unsigned Kind : 31; LLVM_PREFERRED_TYPE(bool) - unsigned IsDefaulted : 1; - LLVM_PREFERRED_TYPE(bool) unsigned IsCanonicalExpr : 1; uintptr_t V; }; @@ -180,38 +168,46 @@ private: struct TV TypeOrValue; }; - void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted); - void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted); + void initFromType(QualType T, bool IsNullPtr) { + TypeOrValue.Kind = IsNullPtr ? NullPtr : Type; + TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + } + + void initFromDeclaration(ValueDecl *D, QualType QT) { + assert(D && "Expected decl"); + DeclArg.Kind = Declaration; + DeclArg.QT = QT.getAsOpaquePtr(); + DeclArg.D = D; + } + void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted); + QualType Type); void initFromStructural(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted); + const APValue &V); public: /// Construct an empty, invalid template argument. constexpr TemplateArgument() - : TypeOrValue{Null, /*IsDefaulted=*/0, /*IsCanonicalExpr=*/0, /*V=*/0} {} + : TypeOrValue{Null, /*IsCanonicalExpr=*/false, /*V=*/0} {} /// Construct a template type argument. - TemplateArgument(QualType T, bool isNullPtr = false, - bool IsDefaulted = false) { - initFromType(T, isNullPtr, IsDefaulted); + TemplateArgument(QualType T, bool isNullPtr = false) { + initFromType(T, isNullPtr); } /// Construct a template argument that refers to a (non-dependent) /// declaration. - TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) { - initFromDeclaration(D, QT, IsDefaulted); - } + TemplateArgument(ValueDecl *D, QualType QT) { initFromDeclaration(D, QT); } /// Construct an integral constant template argument. The memory to /// store the value is allocated with Ctx. TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted = false); + QualType Type) { + initFromIntegral(Ctx, Value, Type); + } /// Construct a template argument from an arbitrary constant value. - TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value, - bool IsDefaulted = false); + TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value); /// Construct an integral constant template argument with the same /// value as Other but a different type. @@ -228,12 +224,8 @@ public: /// is taken. /// /// \param Name The template name. - /// - /// \param IsDefaulted If 'true', implies that this TemplateArgument - /// corresponds to a default template parameter - TemplateArgument(TemplateName Name, bool IsDefaulted = false) { + TemplateArgument(TemplateName Name) { TemplateArg.Kind = Template; - TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = std::nullopt; } @@ -249,13 +241,8 @@ public: /// /// \param NumExpansions The number of expansions that will be generated by /// instantiating - /// - /// \param IsDefaulted If 'true', implies that this TemplateArgument - /// corresponds to a default template parameter - TemplateArgument(TemplateName Name, UnsignedOrNone NumExpansions, - bool IsDefaulted = false) { + TemplateArgument(TemplateName Name, UnsignedOrNone NumExpansions) { TemplateArg.Kind = TemplateExpansion; - TemplateArg.IsDefaulted = IsDefaulted; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = NumExpansions; } @@ -265,9 +252,8 @@ public: /// This form of template argument only occurs in template argument /// lists used for dependent types and for expression; it will not /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E, bool IsCanonical, bool IsDefaulted = false) { + TemplateArgument(Expr *E, bool IsCanonical) { TypeOrValue.Kind = Expression; - TypeOrValue.IsDefaulted = IsDefaulted; TypeOrValue.IsCanonicalExpr = IsCanonical; TypeOrValue.V = reinterpret_cast<uintptr_t>(E); } @@ -278,7 +264,6 @@ public: /// outlives the TemplateArgument itself. explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { this->Args.Kind = Pack; - this->Args.IsDefaulted = false; this->Args.Args = Args.data(); this->Args.NumArgs = Args.size(); } @@ -387,14 +372,6 @@ public: Integer.Type = T.getAsOpaquePtr(); } - /// Set to 'true' if this TemplateArgument corresponds to a - /// default template parameter. - void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } - - /// If returns 'true', this TemplateArgument corresponds to a - /// default template parameter. - bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } - /// Get the value of a StructuralValue. const APValue &getAsStructuralValue() const { return *Value.Value; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index bbb9570..2f33ea8 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7945,27 +7945,24 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { return Arg; case TemplateArgument::Expression: - return TemplateArgument(Arg.getAsExpr(), /*IsCanonical=*/true, - Arg.getIsDefaulted()); + return TemplateArgument(Arg.getAsExpr(), /*IsCanonical=*/true); case TemplateArgument::Declaration: { auto *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl()); - return TemplateArgument(D, getCanonicalType(Arg.getParamTypeForDecl()), - Arg.getIsDefaulted()); + return TemplateArgument(D, getCanonicalType(Arg.getParamTypeForDecl())); } case TemplateArgument::NullPtr: return TemplateArgument(getCanonicalType(Arg.getNullPtrType()), - /*isNullPtr*/ true, Arg.getIsDefaulted()); + /*isNullPtr=*/true); case TemplateArgument::Template: - return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()), - Arg.getIsDefaulted()); + return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); case TemplateArgument::TemplateExpansion: return TemplateArgument( getCanonicalTemplateName(Arg.getAsTemplateOrTemplatePattern()), - Arg.getNumTemplateExpansions(), Arg.getIsDefaulted()); + Arg.getNumTemplateExpansions()); case TemplateArgument::Integral: return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType())); @@ -7973,11 +7970,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::StructuralValue: return TemplateArgument(*this, getCanonicalType(Arg.getStructuralValueType()), - Arg.getAsStructuralValue(), Arg.getIsDefaulted()); + Arg.getAsStructuralValue()); case TemplateArgument::Type: return TemplateArgument(getCanonicalType(Arg.getAsType()), - /*isNullPtr*/ false, Arg.getIsDefaulted()); + /*isNullPtr=*/false); case TemplateArgument::Pack: { bool AnyNonCanonArgs = false; @@ -7987,7 +7984,6 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { return Arg; auto NewArg = TemplateArgument::CreatePackCopy( const_cast<ASTContext &>(*this), CanonArgs); - NewArg.setIsDefaulted(Arg.getIsDefaulted()); return NewArg; } } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 6299efa..617aff4 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -848,8 +848,7 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getAsType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ false, - From.getIsDefaulted()); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr=*/false); } case TemplateArgument::Integral: { @@ -867,15 +866,14 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTypeOrErr) return ToTypeOrErr.takeError(); return TemplateArgument(dyn_cast<ValueDecl>((*ToOrErr)->getCanonicalDecl()), - *ToTypeOrErr, From.getIsDefaulted()); + *ToTypeOrErr); } case TemplateArgument::NullPtr: { ExpectedType ToTypeOrErr = import(From.getNullPtrType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ true, - From.getIsDefaulted()); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr=*/true); } case TemplateArgument::StructuralValue: { @@ -894,7 +892,7 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument(*ToTemplateOrErr, From.getIsDefaulted()); + return TemplateArgument(*ToTemplateOrErr); } case TemplateArgument::TemplateExpansion: { @@ -903,14 +901,12 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions(), - From.getIsDefaulted()); + return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions()); } case TemplateArgument::Expression: if (ExpectedExpr ToExpr = import(From.getAsExpr())) - return TemplateArgument(*ToExpr, From.isCanonicalExpr(), - From.getIsDefaulted()); + return TemplateArgument(*ToExpr, From.isCanonicalExpr()); else return ToExpr.takeError(); diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 76050ce..6ab364a 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -157,27 +157,10 @@ static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) { // TemplateArgument Implementation //===----------------------------------------------------------------------===// -void TemplateArgument::initFromType(QualType T, bool IsNullPtr, - bool IsDefaulted) { - TypeOrValue.Kind = IsNullPtr ? NullPtr : Type; - TypeOrValue.IsDefaulted = IsDefaulted; - TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); -} - -void TemplateArgument::initFromDeclaration(ValueDecl *D, QualType QT, - bool IsDefaulted) { - assert(D && "Expected decl"); - DeclArg.Kind = Declaration; - DeclArg.IsDefaulted = IsDefaulted; - DeclArg.QT = QT.getAsOpaquePtr(); - DeclArg.D = D; -} - void TemplateArgument::initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value, - QualType Type, bool IsDefaulted) { + QualType Type) { Integer.Kind = Integral; - Integer.IsDefaulted = IsDefaulted; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned(); @@ -195,20 +178,13 @@ void TemplateArgument::initFromIntegral(const ASTContext &Ctx, } void TemplateArgument::initFromStructural(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted) { + const APValue &V) { Value.Kind = StructuralValue; - Value.IsDefaulted = IsDefaulted; Value.Value = new (Ctx) APValue(V); Ctx.addDestruction(Value.Value); Value.Type = Type.getAsOpaquePtr(); } -TemplateArgument::TemplateArgument(const ASTContext &Ctx, - const llvm::APSInt &Value, QualType Type, - bool IsDefaulted) { - initFromIntegral(Ctx, Value, Type, IsDefaulted); -} - static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx, QualType T, const APValue &V) { // Pointers to members are relatively easy. @@ -236,17 +212,17 @@ static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx, } TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type, - const APValue &V, bool IsDefaulted) { + const APValue &V) { if (Type->isIntegralOrEnumerationType() && V.isInt()) - initFromIntegral(Ctx, V.getInt(), Type, IsDefaulted); + initFromIntegral(Ctx, V.getInt(), Type); else if ((V.isLValue() && V.isNullPointer()) || (V.isMemberPointer() && !V.getMemberPointerDecl())) - initFromType(Type, /*isNullPtr=*/true, IsDefaulted); + initFromType(Type, /*IsNullPtr=*/true); else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, Type, V)) // FIXME: The Declaration form should expose a const ValueDecl*. - initFromDeclaration(const_cast<ValueDecl *>(VD), Type, IsDefaulted); + initFromDeclaration(const_cast<ValueDecl *>(VD), Type); else - initFromStructural(Ctx, Type, V, IsDefaulted); + initFromStructural(Ctx, Type, V); } TemplateArgument diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 52ff0d5..1402fea 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1413,6 +1413,7 @@ void TypePrinter::printDeducedTemplateSpecializationBefore( Name.print(OS, Policy); } if (DeducedTD) { + DefaultTemplateArgsPolicyRAII _1(Policy); printTemplateArgumentList(OS, Args, Policy, DeducedTD->getTemplateParameters()); } @@ -2547,7 +2548,11 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy, llvm::SmallVector<TemplateArgument, 8> OrigArgs; for (const TA &A : Args) OrigArgs.push_back(getArgument(A)); - while (!Args.empty() && getArgument(Args.back()).getIsDefaulted()) + ASTContext &Ctx = TPL->getParam(0)->getASTContext(); + while (!Args.empty() && + isSubstitutedDefaultArgument(Ctx, getArgument(Args.back()), + TPL->getParam(Args.size() - 1), + OrigArgs, TPL->getDepth())) Args = Args.drop_back(); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c44fea3..e46a2ee 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1318,9 +1318,10 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { return Tag; } -llvm::DICompositeType * -CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, - llvm::DIScope *Ctx) { +llvm::DICompositeType *CGDebugInfo::getOrCreateRecordFwdDecl( + const RecordType *Ty, llvm::DIScope *Ctx, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); if (llvm::DIType *T = getTypeOrNull(QualType(Ty, 0))) return cast<llvm::DICompositeType>(T); @@ -1354,12 +1355,19 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, Flags, Identifier); - if (CGM.getCodeGenOpts().DebugFwdTemplateParams) - if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - DBuilder.replaceArrays(RetTy, llvm::DINodeArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); + if (CGM.getCodeGenOpts().DebugFwdTemplateParams) { + if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + DBuilder.replaceArrays( + RetTy, llvm::DINodeArray(), + CollectTemplateParams(GetTemplateArgs(TSpecial, AsWrittenArgsOrNone), + DefUnit)); + } else { + assert(!AsWrittenArgsOrNone); + } + } + ReplaceMap.emplace_back( - std::piecewise_construct, std::make_tuple(Ty), + std::piecewise_construct, std::make_tuple(OrigTy), std::make_tuple(static_cast<llvm::Metadata *>(RetTy))); return RetTy; } @@ -1536,7 +1544,10 @@ GetTemplateArgs(const TemplateDecl *TD, const TemplateSpecializationType *Ty) { llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, llvm::DIFile *Unit) { - assert(Ty->isTypeAlias()); + if (!Ty->isTypeAlias()) + return CreateType(cast<RecordType>(Ty->desugar()), Ty->template_arguments(), + Ty); + llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit); const TemplateDecl *TD = Ty->getTemplateName().getAsTemplateDecl(); @@ -1557,7 +1568,6 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, if (CGM.getCodeGenOpts().DebugTemplateAlias) { auto ArgVector = ::GetTemplateArgs(TD, Ty); - TemplateArgs Args = {TD->getTemplateParameters(), ArgVector}; // FIXME: Respect DebugTemplateNameKind::Mangled, e.g. by using GetName. // Note we can't use GetName without additional work: TypeAliasTemplateDecl @@ -1569,8 +1579,12 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty, TD->getNameForDiagnostic(OS, PP, /*Qualified=*/false); if (CGM.getCodeGenOpts().getDebugSimpleTemplateNames() != llvm::codegenoptions::DebugTemplateNamesKind::Simple || - !HasReconstitutableArgs(Args.Args)) - printTemplateArgumentList(OS, Args.Args, PP); + !HasReconstitutableArgs(ArgVector)) + printTemplateArgumentList(OS, ArgVector, PP); + + TemplateArgs Args = {TD->getTemplateParameters(), + /*AsWrittenArgs=*/ArgVector, + /*ConvertedArgs=*/{}}; llvm::DIDerivedType *AliasTy = DBuilder.createTemplateAlias( Src, Name, getOrCreateFile(Loc), getLineNumber(Loc), @@ -2403,14 +2417,31 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, llvm::DIFile *Unit) { if (!OArgs) return llvm::DINodeArray(); - TemplateArgs &Args = *OArgs; + auto [TList, AsWrittenArgs, ConvertedArgs] = *OArgs; + + SmallVector<TemplateArgument> UnpackedArgs; + if (!ConvertedArgs.empty() && + ConvertedArgs.back().getKind() == TemplateArgument::Pack) { + UnpackedArgs.resize(ConvertedArgs.size()); + unsigned NumPackedArgs = + int32_t(AsWrittenArgs.size()) - int32_t(ConvertedArgs.size() - 1); + assert(NumPackedArgs >= 0); + llvm::copy(AsWrittenArgs.drop_back(NumPackedArgs), UnpackedArgs.data()); + UnpackedArgs.back() = TemplateArgument::CreatePackCopy( + CGM.getContext(), AsWrittenArgs.take_back(NumPackedArgs)); + AsWrittenArgs = UnpackedArgs; + } + SmallVector<llvm::Metadata *, 16> TemplateParams; - for (unsigned i = 0, e = Args.Args.size(); i != e; ++i) { - const TemplateArgument &TA = Args.Args[i]; - StringRef Name; - const bool defaultParameter = TA.getIsDefaulted(); - if (Args.TList) - Name = Args.TList->getParam(i)->getName(); + for (unsigned i = 0, e = ConvertedArgs.empty() ? AsWrittenArgs.size() + : ConvertedArgs.size(); + i != e; ++i) { + auto [TA, defaultParameter] = i < AsWrittenArgs.size() + ? std::make_tuple(AsWrittenArgs[i], false) + : std::make_tuple(ConvertedArgs[i], true); + StringRef Name = + TList ? TList->getParam(std::min(i, TList->size() - 1))->getName() + : StringRef(); switch (TA.getKind()) { case TemplateArgument::Type: { @@ -2510,7 +2541,10 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs, case TemplateArgument::Pack: TemplateParams.push_back(DBuilder.createTemplateParameterPack( TheCU, Name, nullptr, - CollectTemplateParams({{nullptr, TA.getPackAsArray()}}, Unit))); + CollectTemplateParams( + {{nullptr, /*AsWrittenArgs=*/TA.getPackAsArray(), + /*ConvertedArgs=*/{}}}, + Unit))); break; case TemplateArgument::Expression: { const Expr *E = TA.getAsExpr(); @@ -2540,7 +2574,9 @@ CGDebugInfo::GetTemplateArgs(const FunctionDecl *FD) const { const TemplateParameterList *TList = FD->getTemplateSpecializationInfo() ->getTemplate() ->getTemplateParameters(); - return {{TList, FD->getTemplateSpecializationArgs()->asArray()}}; + return {{TList, + /*AsWrittenArgs=*/FD->getTemplateSpecializationArgs()->asArray(), + /*ConvertedArgs=*/{}}}; } return std::nullopt; } @@ -2555,10 +2591,11 @@ CGDebugInfo::GetTemplateArgs(const VarDecl *VD) const { VarTemplateDecl *T = TS->getSpecializedTemplate(); const TemplateParameterList *TList = T->getTemplateParameters(); auto TA = TS->getTemplateArgs().asArray(); - return {{TList, TA}}; + return {{TList, TA, /*ConvertedArgs=*/{}}}; } -std::optional<CGDebugInfo::TemplateArgs> -CGDebugInfo::GetTemplateArgs(const RecordDecl *RD) const { +std::optional<CGDebugInfo::TemplateArgs> CGDebugInfo::GetTemplateArgs( + const RecordDecl *RD, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone) const { if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { // Always get the full list of parameters, not just the ones from the // specialization. A partial specialization may have fewer parameters than @@ -2566,7 +2603,12 @@ CGDebugInfo::GetTemplateArgs(const RecordDecl *RD) const { TemplateParameterList *TPList = TSpecial->getSpecializedTemplate()->getTemplateParameters(); const TemplateArgumentList &TAList = TSpecial->getTemplateArgs(); - return {{TPList, TAList.asArray()}}; + return {{TPList, + /*AsWrittenArgs=*/ + AsWrittenArgsOrNone ? *AsWrittenArgsOrNone : TAList.asArray(), + /*ConvertedArgs=*/ + AsWrittenArgsOrNone ? TAList.asArray() + : ArrayRef<TemplateArgument>()}}; } return std::nullopt; } @@ -2582,11 +2624,6 @@ llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL, return CollectTemplateParams(GetTemplateArgs(VL), Unit); } -llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD, - llvm::DIFile *Unit) { - return CollectTemplateParams(GetTemplateArgs(RD), Unit); -} - llvm::DINodeArray CGDebugInfo::CollectBTFDeclTagAnnotations(const Decl *D) { if (!D->hasAttr<BTFDeclTagAttr>()) return nullptr; @@ -2913,7 +2950,9 @@ void CGDebugInfo::completeClass(const RecordDecl *RD) { // We want the canonical definition of the structure to not // be the typedef. Since that would lead to circular typedef // metadata. - auto [Res, PrefRes] = CreateTypeDefinition(dyn_cast<RecordType>(Ty)); + auto [Res, PrefRes] = CreateTypeDefinition( + dyn_cast<RecordType>(Ty), /*AsWrittenArgsOrNone=*/std::nullopt, + /*OrigTy=*/Ty->getTypePtr()); assert(!Res->isForwardDecl()); TypeCache[TyPtr].reset(Res); } @@ -3023,17 +3062,21 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { completeClassData(RD); } -llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { +llvm::DIType *CGDebugInfo::CreateType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0))); if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) { if (!T) - T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD)); + T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD), + AsWrittenArgsOrNone, OrigTy); return T; } - auto [Def, Pref] = CreateTypeDefinition(Ty); + auto [Def, Pref] = CreateTypeDefinition(Ty, AsWrittenArgsOrNone, OrigTy); return Pref ? Pref : Def; } @@ -3050,8 +3093,10 @@ llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD, return getOrCreateType(PNA->getTypedefType(), Unit); } -std::pair<llvm::DIType *, llvm::DIType *> -CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { +std::pair<llvm::DIType *, llvm::DIType *> CGDebugInfo::CreateTypeDefinition( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. @@ -3063,7 +3108,8 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. - llvm::DICompositeType *FwdDecl = getOrCreateLimitedType(Ty); + llvm::DICompositeType *FwdDecl = + getOrCreateLimitedType(Ty, AsWrittenArgsOrNone, OrigTy); const RecordDecl *D = RD->getDefinition(); if (!D || !D->isCompleteDefinition()) @@ -3822,11 +3868,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { return C.getQualifiedType(T->getCanonicalTypeUnqualified().getTypePtr(), Quals); case Type::TemplateSpecialization: { - const auto *Spec = cast<TemplateSpecializationType>(T); - if (Spec->isTypeAlias()) - return C.getQualifiedType(T.getTypePtr(), Quals); - T = Spec->desugar(); - break; + return C.getQualifiedType(T.getTypePtr(), Quals); } case Type::TypeOfExpr: T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType(); @@ -4012,7 +4054,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit); case Type::Record: - return CreateType(cast<RecordType>(Ty)); + return CreateType(cast<RecordType>(Ty), + /*AsWrittenArgsOrNone=*/std::nullopt, + /*OrigTy=*/Ty.getTypePtr()); case Type::Enum: return CreateEnumType(cast<EnumType>(Ty)); case Type::FunctionProto: @@ -4070,8 +4114,10 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { llvm_unreachable("type should have been unwrapped!"); } -llvm::DICompositeType * -CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { +llvm::DICompositeType *CGDebugInfo::getOrCreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { QualType QTy(Ty, 0); auto *T = cast_or_null<llvm::DICompositeType>(getTypeOrNull(QTy)); @@ -4083,7 +4129,8 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { return T; // Otherwise create the type. - llvm::DICompositeType *Res = CreateLimitedType(Ty); + llvm::DICompositeType *Res = + CreateLimitedType(Ty, AsWrittenArgsOrNone, OrigTy); // Propagate members from the declaration to the definition // CreateType(const RecordType*) will overwrite this with the members in the @@ -4096,7 +4143,10 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { } // TODO: Currently used for context chains when limiting debug info. -llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { +llvm::DICompositeType *CGDebugInfo::CreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy) { RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. @@ -4122,7 +4172,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // appropriately marked node and just return it. const RecordDecl *D = RD->getDefinition(); if (!D || !D->isCompleteDefinition()) - return getOrCreateRecordFwdDecl(Ty, RDContext); + return getOrCreateRecordFwdDecl(Ty, RDContext, AsWrittenArgsOrNone, OrigTy); uint64_t Size = CGM.getContext().getTypeSize(Ty); // __attribute__((aligned)) can increase or decrease alignment *except* on a @@ -4195,8 +4245,10 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(), - CollectCXXTemplateParams(TSpecial, DefUnit)); + DBuilder.replaceArrays( + RealDecl, llvm::DINodeArray(), + CollectTemplateParams(GetTemplateArgs(TSpecial, AsWrittenArgsOrNone), + DefUnit)); return RealDecl; } @@ -5819,7 +5871,7 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { bool IsOperatorOverload = false; // isa<CXXConversionDecl>(ND); if (auto *RD = dyn_cast<CXXRecordDecl>(ND)) { - Args = GetTemplateArgs(RD); + Args = GetTemplateArgs(RD, /*AsWrittenArgsOrNone=*/std::nullopt); } else if (auto *FD = dyn_cast<FunctionDecl>(ND)) { Args = GetTemplateArgs(FD); auto NameKind = ND->getDeclName().getNameKind(); @@ -5851,8 +5903,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { // Other operator overloads that aren't conversion operators could be // reconstituted but would require a bit more nuance about detecting the // difference between these different operators during that rebuilding. - bool Reconstitutable = - Args && HasReconstitutableArgs(Args->Args) && !IsOperatorOverload; + bool Reconstitutable = Args && HasReconstitutableArgs(Args->AsWrittenArgs) && + !IsOperatorOverload; PrintingPolicy PP = getPrintingPolicy(); @@ -5873,8 +5925,8 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { if (Mangled) { OS << "|"; - printTemplateArgumentList(OS, Args->Args, PP); - printTemplateArgumentList(EncodedOriginalNameOS, Args->Args, PP); + printTemplateArgumentList(OS, Args->AsWrittenArgs, PP); + printTemplateArgumentList(EncodedOriginalNameOS, Args->AsWrittenArgs, PP); #ifndef NDEBUG std::string CanonicalOriginalName; llvm::raw_string_ostream OriginalOS(CanonicalOriginalName); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index ff9c3cd..e7f3180 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -140,7 +140,7 @@ class CGDebugInfo { std::vector<void *> RetainedTypes; /// Cache of forward declared types to RAUW at the end of compilation. - std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap; + std::vector<std::pair<const Type *, llvm::TrackingMDRef>> ReplaceMap; /// Cache of replaceable forward declarations (functions and /// variables) to RAUW at the end of compilation. @@ -212,7 +212,10 @@ private: llvm::DIFile *F); llvm::DIType *CreateType(const HLSLInlineSpirvType *Ty, llvm::DIFile *F); /// Get structure or union type. - llvm::DIType *CreateType(const RecordType *Tyg); + llvm::DIType * + CreateType(const RecordType *Tyg, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); /// Create definition for the specified 'Ty'. /// @@ -220,9 +223,14 @@ private: /// of the 'Ty'. The second is the type specified by the preferred_name /// attribute on 'Ty', which can be a nullptr if no such attribute /// exists. - std::pair<llvm::DIType *, llvm::DIType *> - CreateTypeDefinition(const RecordType *Ty); - llvm::DICompositeType *CreateLimitedType(const RecordType *Ty); + std::pair<llvm::DIType *, llvm::DIType *> CreateTypeDefinition( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); + llvm::DICompositeType *CreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType *CT); /// Get Objective-C interface type. @@ -318,7 +326,8 @@ private: struct TemplateArgs { const TemplateParameterList *TList; - llvm::ArrayRef<TemplateArgument> Args; + llvm::ArrayRef<TemplateArgument> AsWrittenArgs; + llvm::ArrayRef<TemplateArgument> ConvertedArgs; }; /// A helper function to collect template parameters. llvm::DINodeArray CollectTemplateParams(std::optional<TemplateArgs> Args, @@ -334,14 +343,11 @@ private: llvm::DIFile *Unit); std::optional<TemplateArgs> GetTemplateArgs(const VarDecl *) const; - std::optional<TemplateArgs> GetTemplateArgs(const RecordDecl *) const; + std::optional<TemplateArgs> + GetTemplateArgs(const RecordDecl *, + std::optional<ArrayRef<TemplateArgument>>) const; std::optional<TemplateArgs> GetTemplateArgs(const FunctionDecl *) const; - /// A helper function to collect debug info for template - /// parameters. - llvm::DINodeArray CollectCXXTemplateParams(const RecordDecl *TS, - llvm::DIFile *F); - /// A helper function to collect debug info for btf_decl_tag annotations. llvm::DINodeArray CollectBTFDeclTagAnnotations(const Decl *D); @@ -724,8 +730,10 @@ private: llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl); /// Create a forward decl for a RecordType in a given context. - llvm::DICompositeType *getOrCreateRecordFwdDecl(const RecordType *, - llvm::DIScope *); + llvm::DICompositeType * + getOrCreateRecordFwdDecl(const RecordType *, llvm::DIScope *, + std::optional<ArrayRef<TemplateArgument>>, + const Type *OrigTy); /// Return current directory name. StringRef getCurrentDirname(); @@ -763,7 +771,10 @@ private: /// Get the type from the cache or create a new partial type if /// necessary. - llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty); + llvm::DICompositeType *getOrCreateLimitedType( + const RecordType *Ty, + std::optional<ArrayRef<TemplateArgument>> AsWrittenArgsOrNone, + const Type *OrigTy); /// Create type metadata for a source language type. llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg); diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 726581d..2277435 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -85,8 +85,7 @@ void HLSLExternalSemaSource::defineHLSLVectorAlias() { &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy, false, AST.getTrivialTypeSourceInfo(AST.IntTy)); llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4); - TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy, - /*IsDefaulted=*/true); + TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy); SizeParam->setDefaultArgument( AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy, SourceLocation(), SizeParam)); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 36bffc5..26563a7 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5914,10 +5914,6 @@ bool Sema::CheckTemplateArgumentList( CTAK_Specified)) return true; Arg = NewArgLoc.getArgument(); - CTAI.CanonicalConverted.back().setIsDefaulted( - clang::isSubstitutedDefaultArgument(Context, Arg, *Param, - CTAI.CanonicalConverted, - Params->getDepth())); } ArgLoc = TemplateArgumentLoc(TemplateArgument::CreatePackCopy(Context, Args), @@ -5928,10 +5924,6 @@ bool Sema::CheckTemplateArgumentList( RAngleLoc, SugaredArgumentPack.size(), CTAI, CTAK_Specified)) return true; - CTAI.CanonicalConverted.back().setIsDefaulted( - clang::isSubstitutedDefaultArgument(Context, ArgLoc.getArgument(), - *Param, CTAI.CanonicalConverted, - Params->getDepth())); if (ArgIsExpansion && NonPackParameter) { // CWG1430/CWG2686: we have a pack expansion as an argument to an // alias template or concept, and it's not part of a parameter pack. @@ -6078,9 +6070,6 @@ bool Sema::CheckTemplateArgumentList( CTAI, CTAK_Specified)) return true; - CTAI.SugaredConverted.back().setIsDefaulted(true); - CTAI.CanonicalConverted.back().setIsDefaulted(true); - // Core issue 150 (assumed resolution): if this is a template template // parameter, keep track of the default template arguments from the // template definition. diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ec3dda1..2e2c66b 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2403,7 +2403,6 @@ getFunctionDeclAbbrev(serialization::DeclCode Code) { Abv->Add(BitCodeAbbrevOp(TemplateArgument::Type)); // Template Argument Kind Abv->Add( BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template Argument Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is Defaulted Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(0)); diff --git a/clang/test/DebugInfo/CXX/template-parameter.cpp b/clang/test/DebugInfo/CXX/template-parameter.cpp index b2ca54a..fdcf290 100644 --- a/clang/test/DebugInfo/CXX/template-parameter.cpp +++ b/clang/test/DebugInfo/CXX/template-parameter.cpp @@ -4,15 +4,14 @@ // RUN: %clang_cc1 -emit-llvm %std_cxx11-14 -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,PRE17 // RUN: %clang_cc1 -emit-llvm %std_cxx17- -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,CXX17 // RUN: %clang_cc1 -emit-llvm %std_cxx17- -dwarf-version=4 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,CXX17 -// RUN: %clang_cc1 -emit-llvm %std_cxx20- -dwarf-version=5 -DCXX20=1 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefix=CHECK-CXX20 +// RUN: %clang_cc1 -emit-llvm %std_cxx20- -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK-CXX20 // CHECK: DILocalVariable(name: "f1", {{.*}}, type: ![[TEMPLATE_TYPE:[0-9]+]] // CHECK: [[TEMPLATE_TYPE]] = {{.*}}!DICompositeType({{.*}}, templateParams: ![[F1_TYPE:[0-9]+]] // CHECK: [[F1_TYPE]] = !{![[FIRST:[0-9]+]], ![[SECOND:[0-9]+]], ![[THIRD:[0-9]+]], ![[FORTH:[0-9]+]], ![[FIFTH:[0-9]+]]} // CHECK: [[FIRST]] = !DITemplateTypeParameter(name: "T", type: !{{[0-9]*}}) // CHECK: [[SECOND]] = !DITemplateValueParameter(name: "i", type: !{{[0-9]*}}, value: i32 6) -// PRE17: [[THIRD]] = !DITemplateValueParameter(name: "b", type: !{{[0-9]*}}, value: i8 0) -// CXX17: [[THIRD]] = !DITemplateValueParameter(name: "b", type: !{{[0-9]*}}, value: i1 false) +// CHECK: [[THIRD]] = !DITemplateValueParameter(name: "b", type: !{{[0-9]*}}, value: i1 false) // CHECK: [[FIFTH]] = !DITemplateTypeParameter(name: "d", type: !{{[0-9]*}}) // CHECK: DILocalVariable(name: "f2", {{.*}}, type: ![[TEMPLATE_TYPE:[0-9]+]] @@ -51,7 +50,7 @@ template <template <typename T> class CT = bar> class baz { }; -#ifdef CXX20 +#if __cplusplus >= 202002L struct non_empty { int mem; int mem2; } ne; template<float f = -1.5f, double d = 5.2, int * p = &ne.mem2> @@ -72,7 +71,7 @@ nttp<> n1; // CHECK-CXX20-SAME: defaulted: true // CHECK-CXX20-SAME: value: ptr getelementptr (i8, ptr @ne, i64 4) -#endif // CXX20 +#endif // C++20 int main() { foo<int, 6, false, 3, double> f1; diff --git a/clang/test/DebugInfo/CXX/template.cpp b/clang/test/DebugInfo/CXX/template.cpp index a5a17c9..5b25992 100644 --- a/clang/test/DebugInfo/CXX/template.cpp +++ b/clang/test/DebugInfo/CXX/template.cpp @@ -95,14 +95,15 @@ TC <int, // CHECK: [[TCNARG2]] = !DITemplateValueParameter(type: [[INT]], value: i32 -3) -3, -// CHECK: [[TCNARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR]], value: i8 0) +// CHECK: [[TCNARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR]], value: ptr null) nullptr, // The interesting null pointer: -1 for member data pointers (since they are // just an offset in an object, they can be zero and non-null for the first // member) -// CHECK: [[TCNARG4]] = !DITemplateValueParameter(name: "a", type: [[MEMINTPTR]], value: i64 -1) +// CHECK: [[TCNARG4]] = !DITemplateValueParameter(name: "a", type: [[FOO_MEM:![0-9]*]], value: i64 -1) +// CHECK: [[FOO_MEM]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo_mem", {{.*}}baseType: [[MEMINTPTR]]) nullptr, // // In some future iteration we could possibly emit the value of a null member @@ -110,9 +111,9 @@ TC // naturally from the LLVM CodeGen side once we decide how to handle non-null // member function pointers. For now, it's simpler just to emit the 'i8 0'. // -// CHECK: [[TCNARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR]], value: i8 0) +// CHECK: [[TCNARG5]] = !DITemplateValueParameter(name: "b", type: [[MEMFUNPTR]], value: { i64, i64 } zeroinitializer) nullptr, -// CHECK: [[TCNARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR]], value: i8 0) +// CHECK: [[TCNARG6]] = !DITemplateValueParameter(name: "f", type: [[FUNPTR]], value: ptr null) nullptr // CHECK: [[TCNARG7]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Is", value: [[EMPTY]]) > tcn; @@ -221,7 +222,7 @@ struct t1; // use this to ensure the type parameter doesn't shift due to other t template<typename T1, typename T2, typename T3, typename T4> void f1() { } template void f1<t1 () volatile, t1 () const volatile, t1 () &, t1 () &&>(); -// CHECK: !DISubprogram(name: "f1<RawFuncQual::t1 () volatile, RawFuncQual::t1 () const volatile, RawFuncQual::t1 () &, RawFuncQual::t1 () &&>", +// CHECK: !DISubprogram(name: "f1<RawFuncQual::t1 () volatile, RawFuncQual::t1 () const volatile, RawFuncQual::t1 () &, RawFuncQual::t1 () &&>", // CHECK-SAME: templateParams: ![[RAW_FUNC_QUAL_ARGS:[0-9]*]] // CHECK: ![[RAW_FUNC_QUAL_ARGS]] = !{![[RAW_FUNC_QUAL_T1:[0-9]*]], ![[RAW_FUNC_QUAL_T2:[0-9]*]], ![[RAW_FUNC_QUAL_T3:[0-9]*]], ![[RAW_FUNC_QUAL_T4:[0-9]*]]} diff --git a/clang/test/DebugInfo/Generic/preferred_name-chain.cpp b/clang/test/DebugInfo/Generic/preferred_name-chain.cpp index 3108cae..3cbd58d 100644 --- a/clang/test/DebugInfo/Generic/preferred_name-chain.cpp +++ b/clang/test/DebugInfo/Generic/preferred_name-chain.cpp @@ -48,7 +48,7 @@ int main() { // COMMON-SAME: templateParams: ![[PARAM:[0-9]+]] // COMMON: ![[PARAM]] = !{![[TEMPL_TYPE_PARAM:[0-9]+]]} // GDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) -// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) +// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[FOO_INT]]) Foo<Foo<char>> varFooChar; @@ -57,7 +57,7 @@ int main() { // COMMON-SAME: templateParams: ![[CHAR_PARAM:[0-9]+]] // COMMON: ![[CHAR_PARAM]] = !{![[CHAR_TEMPL_TYPE_PARAM:[0-9]+]]} // GDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_CHAR_TY]]) -// LLDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_CHAR_TY]]) +// LLDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[FOO_CHAR]]) return 0; } diff --git a/clang/test/DebugInfo/Generic/preferred_name.cpp b/clang/test/DebugInfo/Generic/preferred_name.cpp index 9b3f532..28a4fe6 100644 --- a/clang/test/DebugInfo/Generic/preferred_name.cpp +++ b/clang/test/DebugInfo/Generic/preferred_name.cpp @@ -53,7 +53,7 @@ int main() { // COMMON-SAME: templateParams: ![[PARAM:[0-9]+]] // COMMON: ![[PARAM]] = !{![[TEMPL_TYPE_PARAM:[0-9]+]]} // GDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) -// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) +// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_BASE]]) BarInt barInt; @@ -75,14 +75,10 @@ int main() { Bar<char> barChar; -// LLDB: ![[BAR_SHORT_TY_2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar<short>", file: ![[#]], line: [[#]], baseType: ![[BAR_SHORT_TY]]) - // LLDB: !DILocalVariable(name: "barChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TY_2:[0-9]+]]) // GDB: !DILocalVariable(name: "barChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TYPEDEF:[0-9]+]]) // GDB: ![[BAR_CHAR_TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar<char>" -// LLDB: ![[BAR_CHAR_TY_2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar<char>", file: ![[#]], line: [[#]], baseType: ![[BAR_CHAR_TY]]) - return 0; } diff --git a/clang/test/Modules/gmodules-preferred-name-typedef.cpp b/clang/test/Modules/gmodules-preferred-name-typedef.cpp index 1d2bbd7..cbd186f 100644 --- a/clang/test/Modules/gmodules-preferred-name-typedef.cpp +++ b/clang/test/Modules/gmodules-preferred-name-typedef.cpp @@ -12,4 +12,4 @@ #include "gmodules-preferred-name-typedef.h" // CHECK: ![[#]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[PREF_BASE:[0-9]+]]) -// CHECK: ![[PREF_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo<char>" +// CHECK: ![[PREF_BASE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo<char>" diff --git a/clang/test/SemaCXX/cxx14-compat.cpp b/clang/test/SemaCXX/cxx14-compat.cpp index d6396a7d..9492d92 100644 --- a/clang/test/SemaCXX/cxx14-compat.cpp +++ b/clang/test/SemaCXX/cxx14-compat.cpp @@ -16,7 +16,7 @@ namespace [[]] NS_with_attr {} // expected-warning {{incompatible with C++ stand enum { e [[]] }; // expected-warning {{incompatible with C++ standards before C++17}} template<typename T = int> struct X {}; -X x; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17; for compatibility, use explicit type name 'X<>'}} +X x; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17; for compatibility, use explicit type name 'X<int>' (aka 'X<>')}} template<template<typename> class> struct Y {}; Y<X> yx; // ok, not class template argument deduction diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 15df9af..0a93891 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -1248,26 +1248,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) { ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U); } -TEST_P(ASTImporterOptionSpecificTestBase, TemplateArgumentsDefaulted) { - Decl *FromTU = getTuDecl(R"( - template<typename T> struct X {}; - template<typename TP = double, - int NTTP = 50, - template<typename> typename TT = X> struct S {}; - S<> s; - )", - Lang_CXX17); - auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( - FromTU, classTemplateSpecializationDecl(hasName("S"))); - ASSERT_TRUE(FromSpec); - auto *ToSpec = Import(FromSpec, Lang_CXX03); - ASSERT_TRUE(ToSpec); - auto const &TList = ToSpec->getTemplateArgs(); - for (auto const &Arg : TList.asArray()) { - ASSERT_TRUE(Arg.getIsDefaulted()); - } -} - TEST_P(ASTImporterOptionSpecificTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) { Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX03); diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index 6b44391..6e3883c 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -509,37 +509,6 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { EXPECT_TRUE(AlignedArrayDelete->isFromExplicitGlobalModule()); } -TEST(Decl, TemplateArgumentDefaulted) { - llvm::Annotations Code(R"cpp( - template<typename T1, typename T2> - struct Alloc {}; - - template <typename T1, - typename T2 = double, - int T3 = 42, - typename T4 = Alloc<T1, T2>> - struct Foo { - }; - - Foo<char, int, 42, Alloc<char, int>> X; - )cpp"); - - auto AST = - tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"}); - ASTContext &Ctx = AST->getASTContext(); - - auto const *CTSD = selectFirst<ClassTemplateSpecializationDecl>( - "id", - match(classTemplateSpecializationDecl(hasName("Foo")).bind("id"), Ctx)); - ASSERT_NE(CTSD, nullptr); - auto const &ArgList = CTSD->getTemplateArgs(); - - EXPECT_FALSE(ArgList.get(0).getIsDefaulted()); - EXPECT_FALSE(ArgList.get(1).getIsDefaulted()); - EXPECT_TRUE(ArgList.get(2).getIsDefaulted()); - EXPECT_TRUE(ArgList.get(3).getIsDefaulted()); -} - TEST(Decl, CXXDestructorDeclsShouldHaveWellFormedNameInfoRanges) { // GH71161 llvm::Annotations Code(R"cpp( diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp index 9381a29..563449c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp @@ -239,8 +239,7 @@ std::optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); return std::nullopt; } - imported_args.push_back( - TemplateArgument(*type, /*isNullPtr*/ false, arg.getIsDefaulted())); + imported_args.push_back(TemplateArgument(*type, /*isNullPtr=*/false)); break; } case TemplateArgument::Integral: { @@ -251,8 +250,8 @@ std::optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); return std::nullopt; } - imported_args.push_back(TemplateArgument(d->getASTContext(), integral, - *type, arg.getIsDefaulted())); + imported_args.push_back( + TemplateArgument(d->getASTContext(), integral, *type)); break; } default: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index a429ea8..810ad91 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2074,7 +2074,6 @@ bool DWARFASTParserClang::ParseTemplateDIE( CompilerType clang_type; uint64_t uval64 = 0; bool uval64_valid = false; - bool is_default_template_arg = false; DWARFFormValue form_value; for (size_t i = 0; i < attributes.Size(); ++i) { const dw_attr_t attr = attributes.AttributeAtIndex(i); @@ -2106,7 +2105,8 @@ bool DWARFASTParserClang::ParseTemplateDIE( break; case DW_AT_default_value: if (attributes.ExtractFormValueAtIndex(i, form_value)) - is_default_template_arg = form_value.Boolean(); + if (form_value.Boolean()) + return true; break; default: break; @@ -2125,9 +2125,9 @@ bool DWARFASTParserClang::ParseTemplateDIE( if (tag == DW_TAG_template_value_parameter && uval64_valid) { if (auto value = MakeAPValue(ast, clang_type, uval64)) { template_param_infos.InsertArg( - name, clang::TemplateArgument( - ast, ClangUtil::GetQualType(clang_type), - std::move(*value), is_default_template_arg)); + name, + clang::TemplateArgument(ast, ClangUtil::GetQualType(clang_type), + std::move(*value))); return true; } } @@ -2136,13 +2136,11 @@ bool DWARFASTParserClang::ParseTemplateDIE( // a non-type template parameter. template_param_infos.InsertArg( name, clang::TemplateArgument(ClangUtil::GetQualType(clang_type), - /*isNullPtr*/ false, - is_default_template_arg)); + /*isNullPtr=*/false)); } else { auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name); template_param_infos.InsertArg( - name, clang::TemplateArgument(clang::TemplateName(tplt_type), - is_default_template_arg)); + name, clang::TemplateArgument(clang::TemplateName(tplt_type))); } } return true; diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp index 0cae01d..9baa387 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -584,10 +584,6 @@ TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) { auto const &args = ctsd->getTemplateArgs(); ASSERT_GT(args.size(), 0U); - - for (auto const &arg : args.asArray()) { - EXPECT_TRUE(arg.getIsDefaulted()); - } }; for (auto const &type_sp : types) { @@ -620,14 +616,14 @@ DWARF: debug_str: - Foo - debug_line: + debug_line: - Version: 4 MinInstLength: 1 MaxOpsPerInst: 1 DefaultIsStmt: 1 LineBase: 0 LineRange: 0 - Files: + Files: - Name: main.cpp DirIdx: 0 ModTime: 0 |