Author: Richard Smith Date: 2021-01-19T14:38:07-08:00 New Revision: 18e093faf726d15f210ab4917142beec51848258
URL: https://github.com/llvm/llvm-project/commit/18e093faf726d15f210ab4917142beec51848258 DIFF: https://github.com/llvm/llvm-project/commit/18e093faf726d15f210ab4917142beec51848258.diff LOG: [msabi] Mangle a template argument referring to array-to-pointer decay applied to an array the same as the array itself. This follows MS ABI, and corrects a regression from the implementation of generalized non-type template parameters, where we "forgot" how to mangle this case. Added: Modified: clang/lib/AST/MicrosoftMangle.cpp clang/test/CodeGenCXX/mangle-ms-templates.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 16e0aa2ae466..b9c289b6497a 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1466,6 +1466,21 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs( } } +/// If value V (with type T) represents a decayed pointer to the first element +/// of an array, return that array. +static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) { + // Must be a pointer... + if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() || + !V.getLValueBase()) + return nullptr; + // ... to element 0 of an array. + QualType BaseT = V.getLValueBase().getType(); + if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 || + V.getLValuePath()[0].getAsArrayIndex() != 0) + return nullptr; + return const_cast<ValueDecl*>(V.getLValueBase().dyn_cast<const ValueDecl*>()); +} + void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA, const NamedDecl *Parm) { @@ -1576,6 +1591,14 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, break; } case TemplateArgument::UncommonValue: + if (ValueDecl *D = getAsArrayToPointerDecayedDecl( + TA.getUncommonValueType(), TA.getAsUncommonValue())) { + // Mangle the result of array-to-pointer decay as if it were a reference + // to the original declaration, to match MSVC's behavior. This can result + // in mangling collisions in some cases! + return mangleTemplateArg( + TD, TemplateArgument(D, TA.getUncommonValueType()), Parm); + } Out << "$"; if (cast<NonTypeTemplateParmDecl>(Parm) ->getType() diff --git a/clang/test/CodeGenCXX/mangle-ms-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-templates.cpp index c9149a473b6f..a5ddb41461cc 100644 --- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-templates.cpp @@ -4,6 +4,20 @@ // RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s // RUN: %clang_cc1 -std=c++20 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix CXX20-X64 %s +// Check that array-to-pointer decay is mangled as the underlying declaration. +extern const char arr[4] = "foo"; +template<const char*> struct Decay1 {}; +// CHECK: "?decay1@@3U?$Decay1@$1?arr@@3QBDB@@A" +Decay1<arr> decay1; +#if __cplusplus >= 201702L +// Note that this mangling approach can lead to collisions. +template<const void*> struct Decay2 {}; +// CXX20-X64: "?decay2a@@3U?$Decay2@$1?arr@@3QBDB@@A" +Decay2<(const void*)arr> decay2a; +// CXX20-X64: "?decay2b@@3U?$Decay2@$1?arr@@3QBDB@@A" +Decay2<(const void*)&arr> decay2b; +#endif + template<typename T> class Class { public: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits