[llvm] r338324 - [MS Demangler] Add rudimentary C++11 Support
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 30 16:02:10 PDT 2018
Author: zturner
Date: Mon Jul 30 16:02:10 2018
New Revision: 338324
URL: http://llvm.org/viewvc/llvm-project?rev=338324&view=rev
Log:
[MS Demangler] Add rudimentary C++11 Support
This patch adds support for demangling r-value references, new
operators such as the ""_foo operator, lambdas, alias types,
nullptr_t, and various other C++11'isms.
There is 1 failing test remaining in this file, which appears to
be related to back-referencing. This type of problem has the
potential to get ugly so I'd rather fix it in a separate patch.
Differential Revision: https://reviews.llvm.org/D50013
Added:
llvm/trunk/test/Demangle/ms-cxx11.test
Modified:
llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=338324&r1=338323&r2=338324&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Mon Jul 30 16:02:10 2018
@@ -139,7 +139,7 @@ enum class StorageClass : uint8_t {
enum class QualifierMangleMode { Drop, Mangle, Result };
-enum class PointerAffinity { Pointer, Reference };
+enum class PointerAffinity { Pointer, Reference, RValueReference };
// Calling conventions
enum class CallingConv : uint8_t {
@@ -163,7 +163,6 @@ enum class PrimTy : uint8_t {
None,
Function,
Ptr,
- Ref,
MemberPtr,
Array,
@@ -177,6 +176,8 @@ enum class PrimTy : uint8_t {
Char,
Schar,
Uchar,
+ Char16,
+ Char32,
Short,
Ushort,
Int,
@@ -189,6 +190,7 @@ enum class PrimTy : uint8_t {
Float,
Double,
Ldouble,
+ Nullptr
};
// Function classes
@@ -205,14 +207,20 @@ enum FuncClass : uint8_t {
namespace {
struct Type;
+struct Name;
// Represents a list of parameters (template params or function arguments.
// It's represented as a linked list.
struct ParamList {
bool IsVariadic = false;
+ // If this is a type, Current will be valid and AliasName will be null.
Type *Current = nullptr;
+ // If this is an alias (e.g. using X = Y), Current will be null and AliasName
+ // will be valid.
+ Name *AliasName = nullptr;
+
ParamList *Next = nullptr;
};
@@ -254,7 +262,7 @@ struct Name {
StringView Operator;
// Template parameters. Null if not a template.
- ParamList TemplateParams;
+ ParamList *TemplateParams = nullptr;
// Nested BackReferences (e.g. "A::B::C") are represented as a linked list.
Name *Next = nullptr;
@@ -265,6 +273,8 @@ struct PointerType : public Type {
void outputPre(OutputStream &OS) override;
void outputPost(OutputStream &OS) override;
+ PointerAffinity Affinity;
+
// Represents a type X in "a pointer to X", "a reference to X",
// "an array of X", or "a function returning X".
Type *Pointee = nullptr;
@@ -324,9 +334,13 @@ struct ArrayType : public Type {
static bool isMemberPointer(StringView MangledName) {
switch (MangledName.popFront()) {
+ case '$':
+ // This is probably an rvalue reference (e.g. $$Q), and you cannot have an
+ // rvalue reference to a member.
+ return false;
case 'A':
// 'A' indicates a reference, and you cannot have a reference to a member
- // function or member variable.
+ // function or member.
return false;
case 'P':
case 'Q':
@@ -449,17 +463,25 @@ static bool startsWithLocalScopePattern(
return true;
}
+static void outputName(OutputStream &OS, const Name *TheName);
+
// Write a function or template parameter list.
-static void outputParameterList(OutputStream &OS, const ParamList &Params) {
- if (!Params.Current) {
- OS << "void";
+static void outputParameterList(OutputStream &OS, const ParamList &Params,
+ bool EmptyAsVoid) {
+ if (!Params.Current && !Params.AliasName) {
+ if (EmptyAsVoid)
+ OS << "void";
return;
}
const ParamList *Head = &Params;
while (Head) {
- Type::outputPre(OS, *Head->Current);
- Type::outputPost(OS, *Head->Current);
+ if (Head->Current) {
+ Type::outputPre(OS, *Head->Current);
+ Type::outputPost(OS, *Head->Current);
+ } else if (Head->AliasName) {
+ outputName(OS, Head->AliasName);
+ }
Head = Head->Next;
@@ -469,11 +491,11 @@ static void outputParameterList(OutputSt
}
static void outputTemplateParams(OutputStream &OS, const Name &TheName) {
- if (!TheName.TemplateParams.Current)
+ if (!TheName.TemplateParams)
return;
OS << "<";
- outputParameterList(OS, TheName.TemplateParams);
+ outputParameterList(OS, *TheName.TemplateParams, false);
OS << ">";
}
@@ -577,6 +599,12 @@ void Type::outputPre(OutputStream &OS) {
case PrimTy::Uchar:
OS << "unsigned char";
break;
+ case PrimTy::Char16:
+ OS << "char16_t";
+ break;
+ case PrimTy::Char32:
+ OS << "char32_t";
+ break;
case PrimTy::Short:
OS << "short";
break;
@@ -613,6 +641,9 @@ void Type::outputPre(OutputStream &OS) {
case PrimTy::Ldouble:
OS << "long double";
break;
+ case PrimTy::Nullptr:
+ OS << "std::nullptr_t";
+ break;
default:
assert(false && "Invalid primitive type!");
}
@@ -647,8 +678,10 @@ static void outputPointerIndicator(Outpu
if (Affinity == PointerAffinity::Pointer)
OS << "*";
- else
+ else if (Affinity == PointerAffinity::Reference)
OS << "&";
+ else
+ OS << "&&";
}
void PointerType::outputPre(OutputStream &OS) {
@@ -659,9 +692,6 @@ void PointerType::outputPre(OutputStream
if (Quals & Q_Unaligned)
OS << "__unaligned ";
- PointerAffinity Affinity = (Prim == PrimTy::Ptr) ? PointerAffinity::Pointer
- : PointerAffinity::Reference;
-
outputPointerIndicator(OS, Affinity, nullptr, Pointee);
// FIXME: We should output this, but it requires updating lots of tests.
@@ -725,12 +755,21 @@ void FunctionType::outputPre(OutputStrea
void FunctionType::outputPost(OutputStream &OS) {
OS << "(";
- outputParameterList(OS, Params);
+ outputParameterList(OS, Params, true);
OS << ")";
if (Quals & Q_Const)
OS << " const";
if (Quals & Q_Volatile)
OS << " volatile";
+ if (Quals & Q_Restrict)
+ OS << " __restrict";
+ if (Quals & Q_Unaligned)
+ OS << " __unaligned";
+
+ if (RefKind == ReferenceKind::LValueRef)
+ OS << " &";
+ else if (RefKind == ReferenceKind::RValueRef)
+ OS << " &&";
if (ReturnType)
Type::outputPost(OS, *ReturnType);
@@ -820,7 +859,7 @@ private:
ArrayType *demangleArrayType(StringView &MangledName);
- ParamList demangleTemplateParameterList(StringView &MangledName);
+ ParamList *demangleTemplateParameterList(StringView &MangledName);
ParamList demangleFunctionParameterList(StringView &MangledName);
int demangleNumber(StringView &MangledName);
@@ -846,7 +885,8 @@ private:
Name *demangleAnonymousNamespaceName(StringView &MangledName);
Name *demangleLocallyScopedNamePiece(StringView &MangledName);
- void demangleOperator(StringView &MangledName, Name *);
+ StringView demangleSimpleString(StringView &MangledName, bool Memorize);
+
FuncClass demangleFunctionClass(StringView &MangledName);
CallingConv demangleCallingConvention(StringView &MangledName);
StorageClass demangleVariableStorageClass(StringView &MangledName);
@@ -931,7 +971,6 @@ Type *Demangler::demangleVariableEncodin
// ::= <type> <pointee-cvr-qualifiers> # pointers, references
switch (Ty->Prim) {
case PrimTy::Ptr:
- case PrimTy::Ref:
case PrimTy::MemberPtr: {
Qualifiers ExtraChildQuals = Q_None;
Ty->Quals =
@@ -1148,6 +1187,19 @@ Name *Demangler::demangleOperatorName(St
case '_':
if (MangledName.consumeFront("L"))
return " co_await";
+ if (MangledName.consumeFront("K")) {
+ size_t EndPos = MangledName.find('@');
+ if (EndPos == StringView::npos)
+ break;
+ StringView OpName = demangleSimpleString(MangledName, false);
+ size_t FullSize = OpName.size() + 3; // <space>""OpName
+ char *Buffer = Arena.allocUnalignedBuffer(FullSize);
+ Buffer[0] = ' ';
+ Buffer[1] = '"';
+ Buffer[2] = '"';
+ std::memcpy(Buffer + 3, OpName.begin(), OpName.size());
+ return {Buffer, FullSize};
+ }
}
}
}
@@ -1161,20 +1213,31 @@ Name *Demangler::demangleOperatorName(St
}
Name *Demangler::demangleSimpleName(StringView &MangledName, bool Memorize) {
+ StringView S = demangleSimpleString(MangledName, Memorize);
+ if (Error)
+ return nullptr;
+
Name *Node = Arena.alloc<Name>();
+ Node->Str = S;
+ return Node;
+}
+
+StringView Demangler::demangleSimpleString(StringView &MangledName,
+ bool Memorize) {
+ StringView S;
for (size_t i = 0; i < MangledName.size(); ++i) {
if (MangledName[i] != '@')
continue;
- Node->Str = MangledName.substr(0, i);
+ S = MangledName.substr(0, i);
MangledName = MangledName.dropFront(i + 1);
if (Memorize)
- memorizeString(Node->Str);
- return Node;
+ memorizeString(S);
+ return S;
}
Error = true;
- return nullptr;
+ return {};
}
Name *Demangler::demangleAnonymousNamespaceName(StringView &MangledName) {
@@ -1429,6 +1492,38 @@ Demangler::demangleQualifiers(StringView
return std::make_pair(Q_None, false);
}
+static bool isTagType(StringView S) {
+ switch (S.front()) {
+ case 'T': // union
+ case 'U': // struct
+ case 'V': // class
+ case 'W': // enum
+ return true;
+ }
+ return false;
+}
+
+static bool isPointerType(StringView S) {
+ if (S.startsWith("$$Q")) // foo &&
+ return true;
+
+ switch (S.front()) {
+ case 'A': // foo &
+ case 'P': // foo *
+ case 'Q': // foo *const
+ case 'R': // foo *volatile
+ case 'S': // foo *const volatile
+ return true;
+ }
+ return false;
+}
+
+static bool isArrayType(StringView S) { return S[0] == 'Y'; }
+
+static bool isFunctionType(StringView S) {
+ return S.startsWith("$$A8@@") || S.startsWith("$$A6");
+}
+
// <variable-type> ::= <type> <cvr-qualifiers>
// ::= <type> <pointee-cvr-qualifiers> # pointers, references
Type *Demangler::demangleType(StringView &MangledName,
@@ -1447,32 +1542,33 @@ Type *Demangler::demangleType(StringView
}
Type *Ty = nullptr;
- switch (MangledName.front()) {
- case 'T': // union
- case 'U': // struct
- case 'V': // class
- case 'W': // enum
+ if (isTagType(MangledName))
Ty = demangleClassType(MangledName);
- break;
- case 'A': // foo &
- case 'P': // foo *
- case 'Q': // foo *const
- case 'R': // foo *volatile
- case 'S': // foo *const volatile
+ else if (isPointerType(MangledName)) {
if (!IsMemberKnown)
IsMember = isMemberPointer(MangledName);
+
if (IsMember)
Ty = demangleMemberPointerType(MangledName);
else
Ty = demanglePointerType(MangledName);
- break;
- case 'Y':
+ } else if (isArrayType(MangledName))
Ty = demangleArrayType(MangledName);
- break;
- default:
+ else if (isFunctionType(MangledName)) {
+ if (MangledName.consumeFront("$$A8@@"))
+ Ty = demangleFunctionType(MangledName, true, false);
+ else {
+ assert(MangledName.startsWith("$$A6"));
+ MangledName.consumeFront("$$A6");
+ Ty = demangleFunctionType(MangledName, false, false);
+ }
+ } else {
Ty = demangleBasicType(MangledName);
- break;
+ assert(Ty && !Error);
+ if (!Ty || Error)
+ return Ty;
}
+
Ty->Quals = Qualifiers(Ty->Quals | Quals);
return Ty;
}
@@ -1535,6 +1631,11 @@ Type *Demangler::demangleFunctionEncodin
Type *Demangler::demangleBasicType(StringView &MangledName) {
Type *Ty = Arena.alloc<Type>();
+ if (MangledName.consumeFront("$$T")) {
+ Ty->Prim = PrimTy::Nullptr;
+ return Ty;
+ }
+
switch (MangledName.popFront()) {
case 'X':
Ty->Prim = PrimTy::Void;
@@ -1593,11 +1694,21 @@ Type *Demangler::demangleBasicType(Strin
case 'W':
Ty->Prim = PrimTy::Wchar;
break;
+ case 'S':
+ Ty->Prim = PrimTy::Char16;
+ break;
+ case 'U':
+ Ty->Prim = PrimTy::Char32;
+ break;
default:
- assert(false);
+ Error = true;
+ return nullptr;
}
break;
}
+ default:
+ Error = true;
+ return nullptr;
}
return Ty;
}
@@ -1632,6 +1743,9 @@ UdtType *Demangler::demangleClassType(St
static std::pair<Qualifiers, PointerAffinity>
demanglePointerCVQualifiers(StringView &MangledName) {
+ if (MangledName.consumeFront("$$Q"))
+ return std::make_pair(Q_None, PointerAffinity::RValueReference);
+
switch (MangledName.popFront()) {
case 'A':
return std::make_pair(Q_None, PointerAffinity::Reference);
@@ -1655,11 +1769,10 @@ demanglePointerCVQualifiers(StringView &
PointerType *Demangler::demanglePointerType(StringView &MangledName) {
PointerType *Pointer = Arena.alloc<PointerType>();
- PointerAffinity Affinity;
- std::tie(Pointer->Quals, Affinity) = demanglePointerCVQualifiers(MangledName);
+ std::tie(Pointer->Quals, Pointer->Affinity) =
+ demanglePointerCVQualifiers(MangledName);
- Pointer->Prim =
- (Affinity == PointerAffinity::Pointer) ? PrimTy::Ptr : PrimTy::Ref;
+ Pointer->Prim = PrimTy::Ptr;
if (MangledName.consumeFront("6")) {
Pointer->Pointee = demangleFunctionType(MangledName, false, true);
return Pointer;
@@ -1805,14 +1918,26 @@ ParamList Demangler::demangleFunctionPar
return {};
}
-ParamList Demangler::demangleTemplateParameterList(StringView &MangledName) {
+ParamList *Demangler::demangleTemplateParameterList(StringView &MangledName) {
ParamList *Head;
ParamList **Current = &Head;
while (!Error && !MangledName.startsWith('@')) {
-
// Template parameter lists don't participate in back-referencing.
*Current = Arena.alloc<ParamList>();
- (*Current)->Current = demangleType(MangledName, QualifierMangleMode::Drop);
+
+ // Empty parameter pack.
+ if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
+ MangledName.consumeFront("$$$V")) {
+ if (!MangledName.startsWith('@'))
+ Error = true;
+ continue;
+ }
+
+ if (MangledName.consumeFront("$$Y"))
+ (*Current)->AliasName = demangleFullyQualifiedTypeName(MangledName);
+ else
+ (*Current)->Current =
+ demangleType(MangledName, QualifierMangleMode::Drop);
Current = &(*Current)->Next;
}
@@ -1823,7 +1948,7 @@ ParamList Demangler::demangleTemplatePar
// Template parameter lists cannot be variadic, so it can only be terminated
// by @.
if (MangledName.consumeFront('@'))
- return *Head;
+ return Head;
Error = true;
return {};
}
Added: llvm/trunk/test/Demangle/ms-cxx11.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-cxx11.test?rev=338324&view=auto
==============================================================================
--- llvm/trunk/test/Demangle/ms-cxx11.test (added)
+++ llvm/trunk/test/Demangle/ms-cxx11.test Mon Jul 30 16:02:10 2018
@@ -0,0 +1,146 @@
+; RUN: llvm-undname < %s | FileCheck %s
+
+; CHECK-NOT: Invalid mangled name
+
+?a at FTypeWithQuals@@3U?$S@$$A8@@BAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) const> FTypeWithQuals::a
+
+?b at FTypeWithQuals@@3U?$S@$$A8@@CAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) volatile> FTypeWithQuals::b
+
+?c at FTypeWithQuals@@3U?$S@$$A8@@IAAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) __restrict> FTypeWithQuals::c
+
+?d at FTypeWithQuals@@3U?$S@$$A8@@GBAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) const &> FTypeWithQuals::d
+
+?e at FTypeWithQuals@@3U?$S@$$A8@@GCAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) volatile &> FTypeWithQuals::e
+
+?f at FTypeWithQuals@@3U?$S@$$A8@@IGAAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) __restrict &> FTypeWithQuals::f
+
+?g at FTypeWithQuals@@3U?$S@$$A8@@HBAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) const &&> FTypeWithQuals::g
+
+?h at FTypeWithQuals@@3U?$S@$$A8@@HCAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) volatile &&> FTypeWithQuals::h
+
+?i at FTypeWithQuals@@3U?$S@$$A8@@IHAAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) __restrict &&> FTypeWithQuals::i
+
+?j at FTypeWithQuals@@3U?$S@$$A6AHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void)> FTypeWithQuals::j
+
+?k at FTypeWithQuals@@3U?$S@$$A8@@GAAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) &> FTypeWithQuals::k
+
+?l at FTypeWithQuals@@3U?$S@$$A8@@HAAHXZ at 1@A
+; CHECK: struct FTypeWithQuals::S<int __cdecl(void) &&> FTypeWithQuals::l
+
+?Char16Var@@3_SA
+; CHECK: char16_t Char16Var
+
+?Char32Var@@3_UA
+; CHECK: char32_t Char32Var
+
+?LRef@@YAXAAH at Z
+; CHECK: void __cdecl LRef(int &)
+
+?RRef@@YAH$$QAH at Z
+; CHECK: int __cdecl RRef(int &&)
+
+?Null@@YAX$$T at Z
+; CHECK: void __cdecl Null(std::nullptr_t)
+
+?fun at PR18022@@YA?AU<unnamed-type-a>@1 at U21@0 at Z
+; CHECK: struct PR18022::<unnamed-type-a> __cdecl PR18022::fun(struct PR18022::<unnamed-type-a>, struct PR18022::<unnamed-type-a>)
+
+; First, we have the static local variable of type "<lambda_1>" inside of "define_lambda".
+; decltype(lambda), where lambda = [] { static int local=42; return 42; };
+?lambda@?1??define_lambda@@YAHXZ at 4V<lambda_1>@?0??1 at YAHXZ@A
+; CHECK: class `int __cdecl define_lambda(void)'::`1'::<lambda_1> `int __cdecl define_lambda(void)'::`2'::lambda
+
+; Next, we have the "operator()" for "<lambda_1>" which is inside of "define_lambda".
+??R<lambda_1>@?0??define_lambda@@YAHXZ at QBE@XZ
+; CHECK: __thiscall `int __cdecl define_lambda(void)'::`1'::<lambda_1>::operator()(void) const
+
+; Finally, we have the local which is inside of "<lambda_1>" which is inside of "define_lambda".
+?local@?2???R<lambda_1>@?0??define_lambda@@YAHXZ at QBE@XZ at 4HA
+; CHECK: __thiscall `int __cdecl define_lambda(void)'::`1'::<lambda_1>::operator()(void) const
+
+??$use_lambda_arg at V<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@@YAXV<lambda_1>@?0??call_with_lambda_arg1@@YAXXZ@@Z
+; CHECK: void __cdecl use_lambda_arg<class `void __cdecl call_with_lambda_arg1(void)'::`1'::<lambda_1>>(class `void __cdecl call_with_lambda_arg1(void)'::`1'::<lambda_1>)
+
+?foo at A@PR19361@@QIGAEXXZ
+; CHECK: void __thiscall PR19361::A::foo(void) __restrict &
+
+?foo at A@PR19361@@QIHAEXXZ
+; CHECK: void __thiscall PR19361::A::foo(void) __restrict &&
+
+??__K_deg@@YAHO at Z
+; CHECK: int __cdecl operator ""_deg(long double)
+
+??$templ_fun_with_pack@$S@@YAXXZ
+; CHECK: void __cdecl templ_fun_with_pack<>(void)
+
+??$templ_fun_with_ty_pack@$$$V@@YAXXZ
+; CHECK: void __cdecl templ_fun_with_ty_pack<>(void)
+??$templ_fun_with_ty_pack@$$V@@YAXXZ
+; CHECK: void __cdecl templ_fun_with_ty_pack<>(void)
+
+??$f@$$YAliasA at PR20047@@@PR20047@@YAXXZ
+; CHECK: void __cdecl PR20047::f<PR20047::AliasA>(void)
+
+?f at UnnamedType@@YAXAAU<unnamed-type-TD>@A at 1@@Z
+; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::A::<unnamed-type-TD> &)
+
+?f at UnnamedType@@YAXPAW4<unnamed-type-e>@?$B at H@1@@Z
+; CHECK: void __cdecl UnnamedType::f(enum UnnamedType::B<int>::<unnamed-type-e> *)
+
+??$f at W4<unnamed-type-E>@?1??g at PR24651@@YAXXZ@@PR24651@@YAXW4<unnamed-type-E>@?1??g at 0@YAXXZ@@Z
+; We have a back-referencing problem here, we print `void __cdecl <unnamed-type-E>::g(void)`
+; for the second occurrence of g.
+; FIXME: void __cdecl PR24651::f<enum `void __cdecl PR24651::g(void)'::`2'::<unnamed-type-E>>(enum `void __cdecl PR24651::g(void)'::`2'::<unnamed-type-E>)
+
+??$f at T<unnamed-type-$S1>@PR18204@@@PR18204@@YAHPAT<unnamed-type-$S1>@0@@Z
+; FIXME: int __cdecl PR18204::f<union PR18204::<unnamed-type-$S1>>(union PR18204::<unnamed-type-$S1> *)
+
+??R<lambda_0>@?0??PR26105@@YAHXZ at QBE@H at Z
+; CHECK: __thiscall `int __cdecl PR26105(void)'::`1'::<lambda_0>::operator()(int) const
+
+??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ at QBE@H at Z@QBE at H@Z
+; CHECK: __thiscall `__thiscall `int __cdecl PR26105(void)'::`1'::<lambda_0>::operator()(int) const'::`1'::<lambda_1>::operator()(int) const
+
+?unaligned_foo1@@YAPFAHXZ
+; CHECK: int __unaligned * __cdecl unaligned_foo1(void)
+
+?unaligned_foo2@@YAPFAPFAHXZ
+; CHECK: int __unaligned *__unaligned * __cdecl unaligned_foo2(void)
+
+?unaligned_foo3@@YAHXZ
+; CHECK: int __cdecl unaligned_foo3(void)
+
+?unaligned_foo4@@YAXPFAH at Z
+; CHECK: void __cdecl unaligned_foo4(int __unaligned *)
+
+?unaligned_foo5@@YAXPIFAH at Z
+; CHECK: void __cdecl unaligned_foo5(int __unaligned *__restrict)
+
+??$unaligned_foo6 at PAH@@YAPAHPAH at Z
+; CHECK: int * __cdecl unaligned_foo6<int *>(int *)
+
+??$unaligned_foo6 at PFAH@@YAPFAHPFAH at Z
+; CHECK: int __unaligned * __cdecl unaligned_foo6<int __unaligned *>(int __unaligned *)
+
+?unaligned_foo8 at unaligned_foo8_S@@QFCEXXZ
+; CHECK: void __thiscall unaligned_foo8_S::unaligned_foo8(void) volatile __unaligned
+
+??R<lambda_1>@x at A@PR31197@@QBE at XZ
+; CHECK: __thiscall PR31197::A::x::<lambda_1>::operator()(void) const
+
+?white@?1???R<lambda_1>@x at A@PR31197@@QBE at XZ@4HA
+; CHECK: int `__thiscall PR31197::A::x::<lambda_1>::operator()(void) const'::`2'::white
+
+?f@@YAXW4<unnamed-enum-enumerator>@@@Z
+; CHECK: void __cdecl f(enum <unnamed-enum-enumerator>)
More information about the llvm-commits
mailing list