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

Reply via email to