r185454 - [ms-cxxabi] Mangle variadic template parameter packs

Reid Kleckner reid at kleckner.net
Tue Jul 2 11:10:08 PDT 2013


Author: rnk
Date: Tue Jul  2 13:10:07 2013
New Revision: 185454

URL: http://llvm.org/viewvc/llvm-project?rev=185454&view=rev
Log:
[ms-cxxabi] Mangle variadic template parameter packs

Unlike Itanium, there is no code to indicate the beginning of a
parameter pack.  I tested this with MSVC 2013, which is the only version
that implements variadic templates so far.

This is needed to compile APInt.cpp for the MS C++ ABI.

Reviewers: timurrrr

Differential Revision: http://llvm-reviews.chandlerc.com/D1077

Modified:
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=185454&r1=185453&r2=185454&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Jul  2 13:10:07 2013
@@ -134,7 +134,8 @@ private:
 
   void mangleTemplateArgs(const TemplateDecl *TD,
                           const TemplateArgumentList &TemplateArgs);
-
+  void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
+                         int ArgIndex);
 };
 
 /// MicrosoftMangleContext - Overrides the default MangleContext for the
@@ -848,44 +849,57 @@ MicrosoftCXXNameMangler::mangleTemplateA
   unsigned NumTemplateArgs = TemplateArgs.size();
   for (unsigned i = 0; i < NumTemplateArgs; ++i) {
     const TemplateArgument &TA = TemplateArgs[i];
-    switch (TA.getKind()) {
-    case TemplateArgument::Null:
-      llvm_unreachable("Can't mangle null template arguments!");
-    case TemplateArgument::Type: {
-      QualType T = TA.getAsType();
-      mangleType(T, SourceRange(), QMM_Escape);
-      break;
-    }
-    case TemplateArgument::Declaration:
-      mangle(cast<NamedDecl>(TA.getAsDecl()), "$1?");
-      break;
-    case TemplateArgument::Integral:
-      mangleIntegerLiteral(TA.getAsIntegral(),
-                           TA.getIntegralType()->isBooleanType());
-      break;
-    case TemplateArgument::Expression:
-      mangleExpression(TA.getAsExpr());
-      break;
-    case TemplateArgument::Template:
-    case TemplateArgument::TemplateExpansion:
-    case TemplateArgument::NullPtr:
-    case TemplateArgument::Pack: {
-      // Issue a diagnostic.
-      DiagnosticsEngine &Diags = Context.getDiags();
-      unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-        "cannot mangle template argument %0 of kind %select{ERROR|ERROR|"
-        "pointer/reference|nullptr|integral|template|template pack expansion|"
-        "ERROR|parameter pack}1 yet");
-      Diags.Report(TD->getLocation(), DiagID)
-        << i + 1
-        << TA.getKind()
-        << TD->getSourceRange();
-    }
-    }
+    mangleTemplateArg(TD, TA, i);
   }
   Out << '@';
 }
 
+void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
+                                                const TemplateArgument &TA,
+                                                int ArgIndex) {
+  switch (TA.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Can't mangle null template arguments!");
+  case TemplateArgument::Type: {
+    QualType T = TA.getAsType();
+    mangleType(T, SourceRange(), QMM_Escape);
+    break;
+  }
+  case TemplateArgument::Declaration:
+    mangle(cast<NamedDecl>(TA.getAsDecl()), "$1?");
+    break;
+  case TemplateArgument::Integral:
+    mangleIntegerLiteral(TA.getAsIntegral(),
+                         TA.getIntegralType()->isBooleanType());
+    break;
+  case TemplateArgument::Expression:
+    mangleExpression(TA.getAsExpr());
+    break;
+  case TemplateArgument::Pack:
+    // Unlike Itanium, there is no character code to indicate an argument pack.
+    // FIXME: ArgIndex will be off, but we only use if for diagnostics that
+    // should ultimately be removed.
+    for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end();
+         I != E; ++I)
+      mangleTemplateArg(TD, *I, ArgIndex);
+    break;
+  case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
+  case TemplateArgument::NullPtr: {
+    // Issue a diagnostic.
+    DiagnosticsEngine &Diags = Context.getDiags();
+    unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+      "cannot mangle template argument %0 of kind %select{ERROR|ERROR|"
+      "pointer/reference|nullptr|integral|template|template pack expansion|"
+      "ERROR|parameter pack}1 yet");
+    Diags.Report(TD->getLocation(), DiagID)
+      << ArgIndex + 1
+      << TA.getKind()
+      << TD->getSourceRange();
+  }
+  }
+}
+
 void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
                                                bool IsMember) {
   // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp?rev=185454&r1=185453&r2=185454&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp Tue Jul  2 13:10:07 2013
@@ -133,3 +133,26 @@ void spam() {
 // CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
 // X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
 }
+
+// Unlike Itanium, there is no character code to indicate an argument pack.
+// Tested with MSVC 2013, the first version which supports variadic templates.
+
+template <typename ...Ts> void variadic_fn_template(const Ts &...args) { }
+void variadic_fn_instantiate() {
+  variadic_fn_template(0, 1, 3, 4);
+  variadic_fn_template(0, 1, 'a', "b");
+}
+// CHECK: "\01??$variadic_fn_template at HHHH@@YAXABH000 at Z"
+// CHECK: "\01??$variadic_fn_template at HHD$$BY01D@@YAXABH0ABDAAY01$$CBD at Z"
+
+template <typename ...Ts>
+struct VariadicClass {
+  VariadicClass() { }
+  int x;
+};
+void variadic_class_instantiate() {
+  VariadicClass<int, char, bool> a;
+  VariadicClass<bool, char, int> b;
+}
+// CHECK: call {{.*}} @"\01??0?$VariadicClass at HD_N@@QAE at XZ"
+// CHECK: call {{.*}} @"\01??0?$VariadicClass at _NDH@@QAE at XZ"





More information about the cfe-commits mailing list