From 7a0ba875a7dcee94ec74fa79b7f8a247d200a76c Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 15 May 2009 16:09:15 +0000 Subject: [PATCH] Name mangling for class template specializations and template arguments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71861 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/Mangle.cpp | 66 ++++++++++++++++++++++++++++++++++++-- test/CodeGenCXX/mangle.cpp | 28 +++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 036389d4c0..6f4ec0bd57 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" @@ -67,6 +68,9 @@ namespace { void mangleExpression(Expr *E); void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); + + void mangleTemplateArgumentList(const TemplateArgumentList &L); + void mangleTemplateArgument(const TemplateArgument &A); }; } @@ -290,8 +294,13 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { if (const NamespaceDecl *Namespace = dyn_cast(DC)) mangleSourceName(Namespace->getIdentifier()); - else if (const RecordDecl *Record = dyn_cast(DC)) - mangleSourceName(Record->getIdentifier()); + else if (const RecordDecl *Record = dyn_cast(DC)) { + if (const ClassTemplateSpecializationDecl *D = + dyn_cast(Record)) { + mangleType(QualType(D->getTypeForDecl(), 0)); + } else + mangleSourceName(Record->getIdentifier()); + } } void @@ -571,6 +580,12 @@ void CXXNameMangler::mangleType(const TagType *T) { mangleName(T->getDecl()->getTypedefForAnonDecl()); else mangleName(T->getDecl()); + + // If this is a class template specialization, mangle the template + // arguments. + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(T->getDecl())) + mangleTemplateArgumentList(Spec->getTemplateArgs()); } void CXXNameMangler::mangleType(const ArrayType *T) { @@ -649,6 +664,53 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { } } +void CXXNameMangler::mangleTemplateArgumentList(const TemplateArgumentList &L) { + // ::= I + E + Out << "I"; + + for (unsigned i = 0, e = L.size(); i != e; ++i) { + const TemplateArgument &A = L[i]; + + mangleTemplateArgument(A); + } + + Out << "E"; +} + +void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { + // ::= # type or template + // ::= X E # expression + // ::= # simple expressions + // ::= I * E # argument pack + // ::= sp # pack expansion of (C++0x) + switch (A.getKind()) { + default: + assert(0 && "Unknown template argument kind!"); + case TemplateArgument::Type: + mangleType(A.getAsType()); + break; + case TemplateArgument::Integral: + // ::= L E # integer literal + + Out << 'L'; + + mangleType(A.getIntegralType()); + + const llvm::APSInt *Integral = A.getAsIntegral(); + if (A.getIntegralType()->isBooleanType()) { + // Boolean values are encoded as 0/1. + Out << (Integral->getBoolValue() ? '1' : '0'); + } else { + if (Integral->isNegative()) + Out << 'n'; + Integral->abs().print(Out, false); + } + + Out << 'E'; + break; + } +} + namespace clang { /// \brief Mangles the name of the declaration D and emits that name /// to the given output stream. diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index c49abeb7ef..3f4d6fb706 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -49,5 +49,31 @@ namespace N { int f(int, int) { static int b; return b; } } // RUN: grep "_ZGVZN1N1gEvE1a =" %t | count 1 && namespace N { int h(); void g() { static int a = h(); } } -// RUN: grep "_Z1fno" %t | count 1 +// RUN: grep "_Z1fno" %t | count 1 && void f(__int128_t, __uint128_t) { } + +template struct S1 {}; + +// RUN: grep "_Z1f2S1IiE" %t | count 1 && +void f(S1) {} + +// RUN: grep "_Z1f2S1IdE" %t | count 1 && +void f(S1) {} + +template struct S2 {}; +// RUN: grep "_Z1f2S2ILi100EE" %t | count 1 && +void f(S2<100>) {} + +// RUN: grep "_Z1f2S2ILin100EE" %t | count 1 && +void f(S2<-100>) {} + +template struct S3 {}; + +// RUN: grep "_Z1f2S3ILb1EE" %t | count 1 && +void f(S3) {} + +// RUN: grep "_Z1f2S3ILb0EE" %t | count 1 && +void f(S3) {} + +// RUN: grep "_Z2f22S3ILb1EE" %t | count 1 +void f2(S3<100>) {} -- 2.40.0