From 8d4b139e9dceb43aa91d0451f5458fd05a9fba33 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 12 Dec 2020 00:04:10 +0100 Subject: [PATCH] Revert "Consider reference, pointer, and pointer-to-member TemplateArguments to be different if they have different types." This reverts commit 7b3470baf8bab1919e3ad4c18e2b776c1f7be2d5. Causes a crash while building tramp3d-v4 from test-suite. --- clang/include/clang/Basic/LangOptions.h | 6 +- clang/lib/AST/ItaniumMangle.cpp | 323 ++++++--------------- clang/lib/AST/StmtProfile.cpp | 4 +- clang/lib/AST/TemplateBase.cpp | 1 - clang/test/CodeGenCXX/clang-abi-compat.cpp | 42 +-- clang/test/CodeGenCXX/mangle-class-nttp.cpp | 6 +- clang/test/CodeGenCXX/mangle-template.cpp | 76 ----- clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp | 11 - 8 files changed, 98 insertions(+), 371 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 251c9a9..203c45f 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -155,10 +155,8 @@ public: /// Attempt to be ABI-compatible with code generated by Clang 11.0.x /// (git 2e10b7a39b93). This causes clang to pass unions with a 256-bit - /// vector member on the stack instead of using registers, to not properly - /// mangle substitutions for template names in some cases, and to mangle - /// declaration template arguments without a cast to the parameter type - /// even when that can lead to mangling collisions. + /// vector member on the stack instead of using registers, and to not + /// properly mangle substitutions for template names in some cases. Ver11, /// Conform to the underlying platform's C and C++ ABIs as closely diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 77ecba66..f5a4f67 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -551,15 +551,13 @@ private: void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); void mangleCXXDtorType(CXXDtorType T); - void mangleTemplateArgs(TemplateName TN, - const TemplateArgumentLoc *TemplateArgs, + void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs); - void mangleTemplateArgs(TemplateName TN, const TemplateArgument *TemplateArgs, + void mangleTemplateArgs(const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void mangleTemplateArgs(TemplateName TN, const TemplateArgumentList &AL); - void mangleTemplateArg(TemplateArgument A, bool NeedExactType); - void mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel, - bool NeedExactType = false); + void mangleTemplateArgs(const TemplateArgumentList &AL); + void mangleTemplateArg(TemplateArgument A); + void mangleValueInTemplateArg(QualType T, const APValue &V); void mangleTemplateParameter(unsigned Depth, unsigned Index); @@ -825,11 +823,6 @@ isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) { return GlobalDecl(); } -static TemplateName asTemplateName(GlobalDecl GD) { - const TemplateDecl *TD = dyn_cast_or_null(GD.getDecl()); - return TemplateName(const_cast(TD)); -} - void CXXNameMangler::mangleName(GlobalDecl GD) { const NamedDecl *ND = cast(GD.getDecl()); if (const VarDecl *VD = dyn_cast(ND)) { @@ -906,7 +899,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) { mangleUnscopedTemplateName(TD, AdditionalAbiTags); - mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); + mangleTemplateArgs(*TemplateArgs); return; } @@ -959,7 +952,7 @@ void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD, nullptr); - mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs); + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); } else { mangleNestedName(TD, TemplateArgs, NumTemplateArgs); } @@ -1109,8 +1102,7 @@ void CXXNameMangler::manglePrefix(QualType type) { // FIXME: GCC does not appear to mangle the template arguments when // the template in question is a dependent template name. Should we // emulate that badness? - mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(), - TST->getNumArgs()); + mangleTemplateArgs(TST->getArgs(), TST->getNumArgs()); addSubstitution(QualType(TST, 0)); } } else if (const auto *DTST = @@ -1123,7 +1115,7 @@ void CXXNameMangler::manglePrefix(QualType type) { // FIXME: GCC does not appear to mangle the template arguments when // the template in question is a dependent template name. Should we // emulate that badness? - mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs()); + mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs()); addSubstitution(QualType(DTST, 0)); } } else { @@ -1266,7 +1258,7 @@ void CXXNameMangler::mangleUnresolvedName( // The and on productions end in an optional // . if (TemplateArgs) - mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs); + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); } void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, @@ -1311,9 +1303,10 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, if (auto *TPO = dyn_cast(ND)) { // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63. - Out << "TA"; + Out << "TAX"; mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(), - TPO->getValue(), /*TopLevel=*/true); + TPO->getValue()); + Out << "E"; break; } @@ -1465,13 +1458,10 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, case DeclarationName::CXXConstructorName: { const CXXRecordDecl *InheritedFrom = nullptr; - TemplateName InheritedTemplateName; const TemplateArgumentList *InheritedTemplateArgs = nullptr; if (auto Inherited = cast(ND)->getInheritedConstructor()) { InheritedFrom = Inherited.getConstructor()->getParent(); - InheritedTemplateName = - TemplateName(Inherited.getConstructor()->getPrimaryTemplate()); InheritedTemplateArgs = Inherited.getConstructor()->getTemplateSpecializationArgs(); } @@ -1488,7 +1478,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, // FIXME: The template arguments are part of the enclosing prefix or // nested-name, but it's more convenient to mangle them here. if (InheritedTemplateArgs) - mangleTemplateArgs(InheritedTemplateName, *InheritedTemplateArgs); + mangleTemplateArgs(*InheritedTemplateArgs); writeAbiTags(ND, AdditionalAbiTags); break; @@ -1577,7 +1567,7 @@ void CXXNameMangler::mangleNestedName(GlobalDecl GD, const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) { mangleTemplatePrefix(TD, NoFunction); - mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); + mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(DC, NoFunction); @@ -1594,7 +1584,7 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, Out << 'N'; mangleTemplatePrefix(TD); - mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs); + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); Out << 'E'; } @@ -1821,8 +1811,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { = cast(Context)->getIdentifier()) { mangleSourceName(Name); const TemplateArgumentList *TemplateArgs = nullptr; - if (GlobalDecl TD = isTemplate(cast(Context), TemplateArgs)) - mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); + if (isTemplate(cast(Context), TemplateArgs)) + mangleTemplateArgs(*TemplateArgs); Out << 'M'; } } @@ -1913,7 +1903,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); - mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); + mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND, nullptr); @@ -2172,7 +2162,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, } } - mangleTemplateArgs(TN, TST->getArgs(), TST->getNumArgs()); + mangleTemplateArgs(TST->getArgs(), TST->getNumArgs()); break; } @@ -2188,10 +2178,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::DependentTemplateSpecialization: { const DependentTemplateSpecializationType *DTST = cast(Ty); - TemplateName Template = getASTContext().getDependentTemplateName( - DTST->getQualifier(), DTST->getIdentifier()); mangleSourceName(DTST->getIdentifier()); - mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs()); + mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs()); break; } @@ -3519,8 +3507,8 @@ void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) { Out << "u" << VendorQualifier.size() << VendorQualifier; Out << "I"; - mangleTemplateArg(T->getRowExpr(), false); - mangleTemplateArg(T->getColumnExpr(), false); + mangleTemplateArg(T->getRowExpr()); + mangleTemplateArg(T->getColumnExpr()); mangleType(T->getElementType()); Out << "E"; } @@ -3593,7 +3581,7 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { // FIXME: GCC does not appear to mangle the template arguments when // the template in question is a dependent template name. Should we // emulate that badness? - mangleTemplateArgs(T->getTemplateName(), T->getArgs(), T->getNumArgs()); + mangleTemplateArgs(T->getArgs(), T->getNumArgs()); addSubstitution(QualType(T, 0)); } } @@ -3645,7 +3633,7 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) { // FIXME: GCC does not appear to mangle the template arguments when // the template in question is a dependent template name. Should we // emulate that badness? - mangleTemplateArgs(Prefix, T->getArgs(), T->getNumArgs()); + mangleTemplateArgs(T->getArgs(), T->getNumArgs()); Out << 'E'; } @@ -3745,7 +3733,7 @@ void CXXNameMangler::mangleType(const ExtIntType *T) { llvm::APSInt BW(32, true); BW = T->getNumBits(); TemplateArgument TA(Context.getASTContext(), BW, getASTContext().IntTy); - mangleTemplateArgs(TemplateName(), &TA, 1); + mangleTemplateArgs(&TA, 1); if (T->isUnsigned()) Out << "j"; else @@ -3755,7 +3743,7 @@ void CXXNameMangler::mangleType(const ExtIntType *T) { void CXXNameMangler::mangleType(const DependentExtIntType *T) { Out << "U7_ExtInt"; TemplateArgument TA(T->getNumBitsExpr()); - mangleTemplateArgs(TemplateName(), &TA, 1); + mangleTemplateArgs(&TA, 1); if (T->isUnsigned()) Out << "j"; else @@ -4644,7 +4632,7 @@ recurse: if (SPE->isPartiallySubstituted()) { Out << "sP"; for (const auto &A : SPE->getPartialArguments()) - mangleTemplateArg(A, false); + mangleTemplateArg(A); Out << "E"; break; } @@ -4832,95 +4820,33 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { } } -namespace { -// Helper to provide ancillary information on a template used to mangle its -// arguments. -struct TemplateArgManglingInfo { - TemplateDecl *ResolvedTemplate = nullptr; - bool SeenPackExpansionIntoNonPack = false; - - TemplateArgManglingInfo(TemplateName TN) { - if (TemplateDecl *TD = TN.getAsTemplateDecl()) - ResolvedTemplate = TD; - } - - /// Do we need to mangle template arguments with exactly correct types? - /// - /// This should be called exactly once for each parameter / argument pair, in - /// order. - bool needExactType(unsigned ParamIdx, const TemplateArgument &Arg) { - // We need correct types when the template-name is unresolved or when it - // names a template that is able to be overloaded. - if (!ResolvedTemplate || SeenPackExpansionIntoNonPack) - return true; - - // If we encounter a pack argument that is expanded into a non-pack - // parameter, we can no longer track parameter / argument correspondence, - // and need to use exact types from this point onwards. - assert(ParamIdx < ResolvedTemplate->getTemplateParameters()->size() && - "no parameter for argument"); - const NamedDecl *Param = - ResolvedTemplate->getTemplateParameters()->getParam(ParamIdx); - if (!Param->isParameterPack() && Arg.isPackExpansion()) { - SeenPackExpansionIntoNonPack = true; - return true; - } - - assert(Param->isParameterPack() == - (Arg.getKind() == TemplateArgument::Pack) && - "should have formed pack argument for pack parameter"); - - // We need exact types for function template arguments because they might be - // overloaded on template parameter type. As a special case, a member - // function template of a generic lambda is not overloadable. - if (auto *FTD = dyn_cast(ResolvedTemplate)) { - auto *RD = dyn_cast(FTD->getDeclContext()); - if (!RD || !RD->isGenericLambda()) - return true; - } - - // Otherwise, we only need a correct type if the parameter has a deduced - // type. - auto *NTTP = dyn_cast(Param); - return NTTP && NTTP->getType()->getContainedDeducedType(); - } -}; -} - -void CXXNameMangler::mangleTemplateArgs(TemplateName TN, - const TemplateArgumentLoc *TemplateArgs, +void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs) { // ::= I + E Out << 'I'; - TemplateArgManglingInfo Info(TN); for (unsigned i = 0; i != NumTemplateArgs; ++i) - mangleTemplateArg(TemplateArgs[i].getArgument(), - Info.needExactType(i, TemplateArgs[i].getArgument())); + mangleTemplateArg(TemplateArgs[i].getArgument()); Out << 'E'; } -void CXXNameMangler::mangleTemplateArgs(TemplateName TN, - const TemplateArgumentList &AL) { +void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) { // ::= I + E Out << 'I'; - TemplateArgManglingInfo Info(TN); for (unsigned i = 0, e = AL.size(); i != e; ++i) - mangleTemplateArg(AL[i], Info.needExactType(i, AL[i])); + mangleTemplateArg(AL[i]); Out << 'E'; } -void CXXNameMangler::mangleTemplateArgs(TemplateName TN, - const TemplateArgument *TemplateArgs, +void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { // ::= I + E Out << 'I'; - TemplateArgManglingInfo Info(TN); for (unsigned i = 0; i != NumTemplateArgs; ++i) - mangleTemplateArg(TemplateArgs[i], Info.needExactType(i, TemplateArgs[i])); + mangleTemplateArg(TemplateArgs[i]); Out << 'E'; } -void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { +void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { // ::= # type or template // ::= X E # expression // ::= # simple expressions @@ -4974,34 +4900,28 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { // Template parameter objects are modeled by reproducing a source form // produced as if by aggregate initialization. if (A.getParamTypeForDecl()->isRecordType()) { + Out << 'X'; auto *TPO = cast(D); mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(), - TPO->getValue(), /*TopLevel=*/true, - NeedExactType); + TPO->getValue()); + Out << 'E'; break; } - ASTContext &Ctx = Context.getASTContext(); - APValue Value; - if (D->isCXXInstanceMember()) - // Simple pointer-to-member with no conversion. - Value = APValue(D, /*IsDerivedMember=*/false, /*Path=*/{}); - else if (D->getType()->isArrayType() && - Ctx.hasSimilarType(Ctx.getDecayedType(D->getType()), - A.getParamTypeForDecl()) && - Ctx.getLangOpts().getClangABICompat() > - LangOptions::ClangABI::Ver11) - // Build a value corresponding to this implicit array-to-pointer decay. - Value = APValue(APValue::LValueBase(D), CharUnits::Zero(), - {APValue::LValuePathEntry::ArrayIndex(0)}, - /*OnePastTheEnd=*/false); - else - // Regular pointer or reference to a declaration. - Value = APValue(APValue::LValueBase(D), CharUnits::Zero(), - ArrayRef(), - /*OnePastTheEnd=*/false); - mangleValueInTemplateArg(A.getParamTypeForDecl(), Value, /*TopLevel=*/true, - NeedExactType); + // Clang produces AST's where pointer-to-member-function expressions + // and pointer-to-function expressions are represented as a declaration not + // an expression. We compensate for it here to produce the correct mangling. + bool compensateMangling = !A.getParamTypeForDecl()->isReferenceType(); + if (compensateMangling) { + Out << 'X'; + mangleOperatorName(OO_Amp, 1); + } + + mangleDeclRefExpr(D); + + if (compensateMangling) + Out << 'E'; + break; } case TemplateArgument::NullPtr: { @@ -5012,7 +4932,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { // ::= J * E Out << 'J'; for (const auto &P : A.pack_elements()) - mangleTemplateArg(P, NeedExactType); + mangleTemplateArg(P); Out << 'E'; } } @@ -5108,36 +5028,11 @@ static bool isZeroInitialized(QualType T, const APValue &V) { llvm_unreachable("Unhandled APValue::ValueKind enum"); } -static QualType getLValueType(ASTContext &Ctx, const APValue &LV) { - QualType T = LV.getLValueBase().getType(); - for (APValue::LValuePathEntry E : LV.getLValuePath()) { - if (const ArrayType *AT = Ctx.getAsArrayType(T)) - T = AT->getElementType(); - else if (const FieldDecl *FD = - dyn_cast(E.getAsBaseOrMember().getPointer())) - T = FD->getType(); - else - T = Ctx.getRecordType( - cast(E.getAsBaseOrMember().getPointer())); - } - return T; -} - -void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, - bool TopLevel, - bool NeedExactType) { +void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V) { // Ignore all top-level cv-qualifiers, to match GCC. Qualifiers Quals; T = getASTContext().getUnqualifiedArrayType(T, Quals); - // A top-level expression that's not a primary expression is wrapped in X...E. - bool IsPrimaryExpr = true; - auto NotPrimaryExpr = [&] { - if (TopLevel && IsPrimaryExpr) - Out << 'X'; - IsPrimaryExpr = false; - }; - // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63. switch (V.getKind()) { case APValue::None: @@ -5145,7 +5040,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, Out << 'L'; mangleType(T); Out << 'E'; - break; + return; case APValue::AddrLabelDiff: llvm_unreachable("unexpected value kind in template argument"); @@ -5173,20 +5068,18 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, } // ::= tl * E - NotPrimaryExpr(); Out << "tl"; mangleType(T); for (unsigned I = 0, N = Bases.size(); I != N; ++I) - mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I), false); + mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I)); for (unsigned I = 0, N = Fields.size(); I != N; ++I) { if (Fields[I]->isUnnamedBitfield()) continue; mangleValueInTemplateArg(Fields[I]->getType(), - V.getStructField(Fields[I]->getFieldIndex()), - false); + V.getStructField(Fields[I]->getFieldIndex())); } Out << 'E'; - break; + return; } case APValue::Union: { @@ -5197,26 +5090,24 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, Out << 'L'; mangleType(T); Out << 'E'; - break; + return; } // ::= di - NotPrimaryExpr(); Out << "tl"; mangleType(T); if (!isZeroInitialized(T, V)) { Out << "di"; mangleSourceName(FD->getIdentifier()); - mangleValueInTemplateArg(FD->getType(), V.getUnionValue(), false); + mangleValueInTemplateArg(FD->getType(), V.getUnionValue()); } Out << 'E'; - break; + return; } case APValue::Array: { QualType ElemT(T->getArrayElementTypeNoTypeQual(), 0); - NotPrimaryExpr(); Out << "tl"; mangleType(T); @@ -5232,42 +5123,40 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, const APValue &Elem = I < V.getArrayInitializedElts() ? V.getArrayInitializedElt(I) : V.getArrayFiller(); - mangleValueInTemplateArg(ElemT, Elem, false); + mangleValueInTemplateArg(ElemT, Elem); } Out << 'E'; - break; + return; } case APValue::Vector: { const VectorType *VT = T->castAs(); - NotPrimaryExpr(); Out << "tl"; mangleType(T); unsigned N = V.getVectorLength(); while (N && isZeroInitialized(VT->getElementType(), V.getVectorElt(N - 1))) --N; for (unsigned I = 0; I != N; ++I) - mangleValueInTemplateArg(VT->getElementType(), V.getVectorElt(I), false); + mangleValueInTemplateArg(VT->getElementType(), V.getVectorElt(I)); Out << 'E'; - break; + return; } case APValue::Int: mangleIntegerLiteral(T, V.getInt()); - break; + return; case APValue::Float: mangleFloatLiteral(T, V.getFloat()); - break; + return; case APValue::FixedPoint: mangleFixedPointLiteral(); - break; + return; case APValue::ComplexFloat: { const ComplexType *CT = T->castAs(); - NotPrimaryExpr(); Out << "tl"; mangleType(T); if (!V.getComplexFloatReal().isPosZero() || @@ -5276,12 +5165,11 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, if (!V.getComplexFloatImag().isPosZero()) mangleFloatLiteral(CT->getElementType(), V.getComplexFloatImag()); Out << 'E'; - break; + return; } case APValue::ComplexInt: { const ComplexType *CT = T->castAs(); - NotPrimaryExpr(); Out << "tl"; mangleType(T); if (V.getComplexIntReal().getBoolValue() || @@ -5290,7 +5178,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, if (V.getComplexIntImag().getBoolValue()) mangleIntegerLiteral(CT->getElementType(), V.getComplexIntImag()); Out << 'E'; - break; + return; } case APValue::LValue: { @@ -5300,7 +5188,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, if (V.isNullPointer()) { mangleNullPointer(T); - break; + return; } APValue::LValueBase B = V.getLValueBase(); @@ -5311,82 +5199,54 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, if (Offset.isZero()) { // This is reinterpret_cast(0), not a null pointer. Mangle this as // a cast, because L 0 E means something else. - NotPrimaryExpr(); Out << "rc"; mangleType(T); Out << "Li0E"; - if (TopLevel) - Out << 'E'; } else { Out << "L"; mangleType(T); Out << Offset.getQuantity() << 'E'; } - break; + return; } - ASTContext &Ctx = Context.getASTContext(); - enum { Base, Offset, Path } Kind; if (!V.hasLValuePath()) { // Mangle as (T*)((char*)&base + N). if (T->isReferenceType()) { - NotPrimaryExpr(); Out << "decvP"; mangleType(T->getPointeeType()); } else { - NotPrimaryExpr(); Out << "cv"; mangleType(T); } Out << "plcvPcad"; Kind = Offset; } else { + if (T->isPointerType()) + Out << "ad"; if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) { - NotPrimaryExpr(); - // A final conversion to the template parameter's type is usually - // folded into the 'so' mangling, but we can't do that for 'void*' - // parameters without introducing collisions. - if (NeedExactType && T->isVoidPointerType()) { - Out << "cv"; - mangleType(T); - } - if (T->isPointerType()) - Out << "ad"; Out << "so"; - mangleType(T->isVoidPointerType() - ? getLValueType(Ctx, V).getUnqualifiedType() - : T->getPointeeType()); + mangleType(T->getPointeeType()); Kind = Path; } else { - if (NeedExactType && - !Ctx.hasSameType(T->getPointeeType(), getLValueType(Ctx, V)) && - Ctx.getLangOpts().getClangABICompat() > - LangOptions::ClangABI::Ver11) { - NotPrimaryExpr(); - Out << "cv"; - mangleType(T); - } - if (T->isPointerType()) { - NotPrimaryExpr(); - Out << "ad"; - } Kind = Base; } } - QualType TypeSoFar = B.getType(); + QualType TypeSoFar; if (auto *VD = B.dyn_cast()) { Out << 'L'; mangle(VD); Out << 'E'; + TypeSoFar = VD->getType(); } else if (auto *E = B.dyn_cast()) { - NotPrimaryExpr(); mangleExpression(E); + TypeSoFar = E->getType(); } else if (auto TI = B.dyn_cast()) { - NotPrimaryExpr(); Out << "ti"; mangleType(QualType(TI.getType(), 0)); + TypeSoFar = B.getTypeInfoType(); } else { // We should never see dynamic allocations here. llvm_unreachable("unexpected lvalue base kind in template argument"); @@ -5398,7 +5258,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, case Offset: Out << 'L'; - mangleType(Ctx.getPointerDiffType()); + mangleType(Context.getASTContext().getPointerDiffType()); mangleNumber(V.getLValueOffset().getQuantity()); Out << 'E'; break; @@ -5429,7 +5289,8 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, } TypeSoFar = FD->getType(); } else { - TypeSoFar = Ctx.getRecordType(cast(D)); + TypeSoFar = + Context.getASTContext().getRecordType(cast(D)); } } } @@ -5440,30 +5301,19 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, break; } - break; + return; } case APValue::MemberPointer: // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47. if (!V.getMemberPointerDecl()) { mangleNullPointer(T); - break; + return; } - ASTContext &Ctx = Context.getASTContext(); - - NotPrimaryExpr(); if (!V.getMemberPointerPath().empty()) { Out << "mc"; mangleType(T); - } else if (NeedExactType && - !Ctx.hasSameType( - T->castAs()->getPointeeType(), - V.getMemberPointerDecl()->getType()) && - Ctx.getLangOpts().getClangABICompat() > - LangOptions::ClangABI::Ver11) { - Out << "cv"; - mangleType(T); } Out << "adL"; mangle(V.getMemberPointerDecl()); @@ -5475,11 +5325,8 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V, mangleNumber(Offset.getQuantity()); Out << 'E'; } - break; + return; } - - if (TopLevel && !IsPrimaryExpr) - Out << 'E'; } void CXXNameMangler::mangleTemplateParameter(unsigned Depth, unsigned Index) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index a27de70..bf3b43b 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2193,8 +2193,6 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { break; case TemplateArgument::Declaration: - VisitType(Arg.getParamTypeForDecl()); - // FIXME: Do we need to recursively decompose template parameter objects? VisitDecl(Arg.getAsDecl()); break; @@ -2203,8 +2201,8 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { break; case TemplateArgument::Integral: - VisitType(Arg.getIntegralType()); Arg.getAsIntegral().Profile(ID); + VisitType(Arg.getIntegralType()); break; case TemplateArgument::Expression: diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index b6af655..dd898b2 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -244,7 +244,6 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, break; case Declaration: - getParamTypeForDecl().Profile(ID); ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr); break; diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index 46e7ed8..7943cad 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -1,12 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s -// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s -// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,V5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=V11,V5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=V39,V5,V12 %s typedef __attribute__((vector_size(8))) long long v1xi64; void clang39(v1xi64) {} @@ -29,29 +27,3 @@ namespace mangle_template_prefix { void g() { f(1, 2); } } -int arg; -template struct clang12_unchanged {}; -// CHECK: @_Z4test17clang12_unchangedIXadL_Z3argEEE -void test(clang12_unchanged<&arg>) {} - -#if __cplusplus >= 201703L -// PRE12-CXX17: @_Z4test15clang12_changedIXadL_Z3argEEE -// V12-CXX17: @_Z4test15clang12_changedIXcvPKiadL_Z3argEEE -template struct clang12_changed {}; -void test(clang12_changed<(const int*)&arg>) {} -#endif - -// PRE12: @_Z9clang12_aIXadL_Z3argEEEvv -// V12: @_Z9clang12_aIXcvPKiadL_Z3argEEEvv -template void clang12_a() {} -template void clang12_a<&arg>(); - -// PRE12: @_Z9clang12_bIXadL_Z3arrEEEvv -// V12: @_Z9clang12_bIXadsoKcL_Z3arrEEEEvv -extern const char arr[6] = "hello"; -template void clang12_b() {} -template void clang12_b(); - -// CHECK: @_Z9clang12_cIXadL_Z3arrEEEvv -template void clang12_c() {} -template void clang12_c<&arr>(); diff --git a/clang/test/CodeGenCXX/mangle-class-nttp.cpp b/clang/test/CodeGenCXX/mangle-class-nttp.cpp index 70e5be8..81107c4 100644 --- a/clang/test/CodeGenCXX/mangle-class-nttp.cpp +++ b/clang/test/CodeGenCXX/mangle-class-nttp.cpp @@ -124,7 +124,7 @@ union E { template void f() {} // Union members. -// CHECK: define weak_odr void @_Z1fIL1EEEvv( +// CHECK: define weak_odr void @_Z1fIXL1EEEEvv( // MSABI: define {{.*}} @"??$f@$7TE@@@@@YAXXZ" template void f(); // CHECK: define weak_odr void @_Z1fIXtl1EEEEvv( @@ -214,10 +214,10 @@ template

void f() {} template

void f() {} template

void f() {} template

void f() {} -// CHECK: define weak_odr void @_Z1fIL2H1EEvv +// CHECK: define weak_odr void @_Z1fIXL2H1EEEvv // MSABI: define {{.*}} @"??$f@$7TH1@@@@@YAXXZ" template void f(); -// CHECK: define weak_odr void @_Z1fIL2H2EEvv +// CHECK: define weak_odr void @_Z1fIXL2H2EEEvv // MSABI: define {{.*}} @"??$f@$7TH2@@@@@YAXXZ" template void f(); // CHECK: define weak_odr void @_Z1fIXtl2H3EEEvv diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp index 84cf123..45868f5 100644 --- a/clang/test/CodeGenCXX/mangle-template.cpp +++ b/clang/test/CodeGenCXX/mangle-template.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++11 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s -// RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++20 -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s --check-prefixes=CHECK,CXX20 // expected-no-diagnostics namespace test1 { @@ -222,78 +221,3 @@ namespace test16 { void g() { f(1, 2); } } -#if __cplusplus >= 202002L -namespace cxx20 { - template struct A {}; - template struct B {}; - - int x; - // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1xEEEEE( - void f(A<&x>) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPiXadL_ZNS_1xEEEEE( - void f(B) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKiadL_ZNS_1xEEEEE( - void f(A<(const int*)&x>) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKiXadL_ZNS_1xEEEEE( - void f(B) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPvadL_ZNS_1xEEEEE( - void f(A<(void*)&x>) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPvXadL_ZNS_1xEEEEE( - void f(B) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKvadL_ZNS_1xEEEEE( - void f(A<(const void*)&x>) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadL_ZNS_1xEEEEE( - void f(B) {} - - struct Q { int x; }; - - // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1Q1xEEEEE( - void f(A<&Q::x>) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1QEiXadL_ZNS1_1xEEEEE - void f(B) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvMNS_1QEKiadL_ZNS1_1xEEEEE( - void f(A<(const int Q::*)&Q::x>) {} - // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1QEKiXadL_ZNS1_1xEEEEE( - void f(B) {} -} -#endif - -namespace test17 { - // Ensure we mangle the types for non-type template arguments if we've lost - // track of argument / parameter correspondence. - template struct X {}; - - // CHECK: define {{.*}} @_ZN6test171fILi1EJLi2ELi3ELi4EEEEvNS_1XIXT_EJLi5EXspT0_ELi6EEEE - template void f(X) {} - void g() { f<1, 2, 3, 4>({}); } - - // Note: there is no J...E here, because we can't form a pack argument, and - // the 5u and 6u are mangled with the original type 'j' (unsigned int) not - // with the resolved type 'i' (signed int). - // CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_EXLj5EEXT_EXLj6EEEE - template void h(X) {} - void i() { h<4, 1, 2, 3>({}); } - -#if __cplusplus >= 201402L - template struct Y {}; - int n; - // Case 1: &n is a resolved template argument, with a known parameter: - // mangled with no conversion. - // CXX20: define {{.*}} @_ZN6test172j1ILi1EEEvNS_1YIXT_EXadL_ZNS_1nEEEEE - template void j1(Y) {} - // Case 2: &n is an unresolved template argument, with an unknown - // corresopnding parameter: mangled as the source expression. - // CXX20: define {{.*}} @_ZN6test172j2IJLi1EEEEvNS_1YIXspT_EXcvPKiadL_ZNS_1nEEEEE - template void j2(Y) {} - // Case 3: &n is a resolved template argument, with a known parameter, but - // for a template that can be overloaded on type: mangled with the parameter type. - // CXX20: define {{.*}} @_ZN6test172j3ILi1EEEvDTplT_clL_ZNS_1yIXcvPVKiadL_ZNS_1nEEEEEivEEE - template int y(); - template void j3(decltype(N + y<(const int*)&n>())) {} - void k() { - j1<1>(Y<1, &n>()); - j2<1>(Y<1, &n>()); - j3<1>(0); - } -#endif -} diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index 0cfbfdc..cc19bce 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -187,11 +187,6 @@ namespace Auto { int &r = f(B<&a>()); float &s = f(B<&b>()); - void type_affects_identity(B<&a>) {} - void type_affects_identity(B<(const int*)&a>) {} - void type_affects_identity(B<(void*)&a>) {} - void type_affects_identity(B<(const void*)&a>) {} - // pointers to members template struct B

{}; template struct B

{}; @@ -203,12 +198,6 @@ namespace Auto { char &u = f(B<&X::p>()); short &v = f(B<&X::pp>()); - struct Y : X {}; - void type_affects_identity(B<&X::n>) {} - void type_affects_identity(B<(int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}} - void type_affects_identity(B<(const int X::*)&X::n>) {} - void type_affects_identity(B<(const int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}} - // A case where we need to do auto-deduction, and check whether the // resulting dependent types match during partial ordering. These // templates are not ordered due to the mismatching function parameter. -- 2.7.4