in tools/clang/lib/AST/ItaniumMangle.cpp [2674:3428]
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <trinary operator-name> <expression> <expression> <expression>
// ::= cv <type> expression # conversion with one argument
// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
// ::= dc <type> <expression> # dynamic_cast<type> (expression)
// ::= sc <type> <expression> # static_cast<type> (expression)
// ::= cc <type> <expression> # const_cast<type> (expression)
// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
// ::= st <type> # sizeof (a type)
// ::= at <type> # alignof (a type)
// ::= <template-param>
// ::= <function-param>
// ::= sr <type> <unqualified-name> # dependent name
// ::= sr <type> <unqualified-name> <template-args> # dependent template-id
// ::= ds <expression> <expression> # expr.*expr
// ::= sZ <template-param> # size of a parameter pack
// ::= sZ <function-param> # size of a function parameter pack
// ::= <expr-primary>
// <expr-primary> ::= L <type> <value number> E # integer literal
// ::= L <type <value float> E # floating literal
// ::= L <mangled-name> E # external name
// ::= fpT # 'this' expression
QualType ImplicitlyConvertedToType;
recurse:
switch (E->getStmtClass()) {
case Expr::NoStmtClass:
#define ABSTRACT_STMT(Type)
#define EXPR(Type, Base)
#define STMT(Type, Base) \
case Expr::Type##Class:
#include "clang/AST/StmtNodes.inc"
// fallthrough
// These all can only appear in local or variable-initialization
// contexts and so should never appear in a mangling.
case Expr::AddrLabelExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
case Expr::NoInitExprClass:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
llvm_unreachable("unexpected statement kind");
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
case Expr::ChooseExprClass:
case Expr::CompoundLiteralExprClass:
case Expr::DesignatedInitExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::ExtMatrixElementExprClass: // HLSL Change
case Expr::HLSLVectorElementExprClass: // HLSL Change
case Expr::GenericSelectionExprClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCIsaExprClass:
case Expr::ObjCIvarRefExprClass:
case Expr::ObjCMessageExprClass:
case Expr::ObjCPropertyRefExprClass:
case Expr::ObjCProtocolExprClass:
case Expr::ObjCSelectorExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCBoxedExprClass:
case Expr::ObjCArrayLiteralClass:
case Expr::ObjCDictionaryLiteralClass:
case Expr::ObjCSubscriptRefExprClass:
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::OffsetOfExprClass:
case Expr::PredefinedExprClass:
case Expr::ShuffleVectorExprClass:
case Expr::ConvertVectorExprClass:
case Expr::StmtExprClass:
case Expr::TypeTraitExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
case Expr::VAArgExprClass:
case Expr::CUDAKernelCallExprClass:
case Expr::AsTypeExprClass:
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
{
// As bad as this diagnostic is, it's better than crashing.
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot yet mangle expression type %0");
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
break;
}
case Expr::CXXUuidofExprClass: {
const CXXUuidofExpr *UE = cast<CXXUuidofExpr>(E);
if (UE->isTypeOperand()) {
QualType UuidT = UE->getTypeOperand(Context.getASTContext());
Out << "u8__uuidoft";
mangleType(UuidT);
} else {
Expr *UuidExp = UE->getExprOperand();
Out << "u8__uuidofz";
mangleExpression(UuidExp, Arity);
}
break;
}
// Even gcc-4.5 doesn't mangle this.
case Expr::BinaryConditionalOperatorClass: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID =
Diags.getCustomDiagID(DiagnosticsEngine::Error,
"?: operator with omitted middle operand cannot be mangled");
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
break;
}
// These are used for internal purposes and cannot be meaningfully mangled.
case Expr::OpaqueValueExprClass:
llvm_unreachable("cannot mangle opaque value; mangling wrong thing?");
case Expr::InitListExprClass: {
Out << "il";
mangleInitListElements(cast<InitListExpr>(E));
Out << "E";
break;
}
case Expr::CXXDefaultArgExprClass:
mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
break;
case Expr::CXXDefaultInitExprClass:
mangleExpression(cast<CXXDefaultInitExpr>(E)->getExpr(), Arity);
break;
case Expr::CXXStdInitializerListExprClass:
mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity);
break;
case Expr::SubstNonTypeTemplateParmExprClass:
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
Arity);
break;
case Expr::UserDefinedLiteralClass:
// We follow g++'s approach of mangling a UDL as a call to the literal
// operator.
case Expr::CXXMemberCallExprClass: // fallthrough
case Expr::CallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
// <expression> ::= cp <simple-id> <expression>* E
// We use this mangling only when the call would use ADL except
// for being parenthesized. Per discussion with David
// Vandervoorde, 2011.04.25.
if (isParenthesizedADLCallee(CE)) {
Out << "cp";
// The callee here is a parenthesized UnresolvedLookupExpr with
// no qualifier and should always get mangled as a <simple-id>
// anyway.
// <expression> ::= cl <expression>* E
} else {
Out << "cl";
}
unsigned CallArity = CE->getNumArgs();
for (const Expr *Arg : CE->arguments())
if (isa<PackExpansionExpr>(Arg))
CallArity = UnknownArity;
mangleExpression(CE->getCallee(), CallArity);
for (const Expr *Arg : CE->arguments())
mangleExpression(Arg);
Out << 'E';
break;
}
case Expr::CXXNewExprClass: {
const CXXNewExpr *New = cast<CXXNewExpr>(E);
if (New->isGlobalNew()) Out << "gs";
Out << (New->isArray() ? "na" : "nw");
for (CXXNewExpr::const_arg_iterator I = New->placement_arg_begin(),
E = New->placement_arg_end(); I != E; ++I)
mangleExpression(*I);
Out << '_';
mangleType(New->getAllocatedType());
if (New->hasInitializer()) {
if (New->getInitializationStyle() == CXXNewExpr::ListInit)
Out << "il";
else
Out << "pi";
const Expr *Init = New->getInitializer();
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
// Directly inline the initializers.
for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
E = CCE->arg_end();
I != E; ++I)
mangleExpression(*I);
} else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
mangleExpression(PLE->getExpr(i));
} else if (New->getInitializationStyle() == CXXNewExpr::ListInit &&
isa<InitListExpr>(Init)) {
// Only take InitListExprs apart for list-initialization.
mangleInitListElements(cast<InitListExpr>(Init));
} else
mangleExpression(Init);
}
Out << 'E';
break;
}
case Expr::CXXPseudoDestructorExprClass: {
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
NestedNameSpecifier *Qualifier = PDE->getQualifier();
QualType ScopeType;
if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
if (Qualifier) {
mangleUnresolvedPrefix(Qualifier,
/*Recursive=*/true);
mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
Out << 'E';
} else {
Out << "sr";
if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
Out << 'E';
}
} else if (Qualifier) {
mangleUnresolvedPrefix(Qualifier);
}
// <base-unresolved-name> ::= dn <destructor-name>
Out << "dn";
QualType DestroyedType = PDE->getDestroyedType();
mangleUnresolvedTypeOrSimpleId(DestroyedType);
break;
}
case Expr::MemberExprClass: {
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
ME->getMemberDecl()->getDeclName(), Arity);
break;
}
case Expr::UnresolvedMemberExprClass: {
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
ME->getMemberName(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
}
case Expr::CXXDependentScopeMemberExprClass: {
const CXXDependentScopeMemberExpr *ME
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
ME->getFirstQualifierFoundInScope(),
ME->getMember(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
}
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
// onto the end.
if (ULE->hasExplicitTemplateArgs())
mangleTemplateArgs(ULE->getExplicitTemplateArgs());
break;
}
case Expr::CXXUnresolvedConstructExprClass: {
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
unsigned N = CE->arg_size();
Out << "cv";
mangleType(CE->getType());
if (N != 1) Out << '_';
for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
if (N != 1) Out << 'E';
break;
}
case Expr::CXXConstructExprClass: {
const auto *CE = cast<CXXConstructExpr>(E);
if (!CE->isListInitialization() || CE->isStdInitListInitialization()) {
assert(
CE->getNumArgs() >= 1 &&
(CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) &&
"implicit CXXConstructExpr must have one argument");
return mangleExpression(cast<CXXConstructExpr>(E)->getArg(0));
}
Out << "il";
for (auto *E : CE->arguments())
mangleExpression(E);
Out << "E";
break;
}
case Expr::CXXTemporaryObjectExprClass: {
const auto *CE = cast<CXXTemporaryObjectExpr>(E);
unsigned N = CE->getNumArgs();
bool List = CE->isListInitialization();
if (List)
Out << "tl";
else
Out << "cv";
mangleType(CE->getType());
if (!List && N != 1)
Out << '_';
if (CE->isStdInitListInitialization()) {
// We implicitly created a std::initializer_list<T> for the first argument
// of a constructor of type U in an expression of the form U{a, b, c}.
// Strip all the semantic gunk off the initializer list.
auto *SILE =
cast<CXXStdInitializerListExpr>(CE->getArg(0)->IgnoreImplicit());
auto *ILE = cast<InitListExpr>(SILE->getSubExpr()->IgnoreImplicit());
mangleInitListElements(ILE);
} else {
for (auto *E : CE->arguments())
mangleExpression(E);
}
if (List || N != 1)
Out << 'E';
break;
}
case Expr::CXXScalarValueInitExprClass:
Out << "cv";
mangleType(E->getType());
Out << "_E";
break;
case Expr::CXXNoexceptExprClass:
Out << "nx";
mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
break;
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
if (!SAE->isInstantiationDependent()) {
// Itanium C++ ABI:
// If the operand of a sizeof or alignof operator is not
// instantiation-dependent it is encoded as an integer literal
// reflecting the result of the operator.
//
// If the result of the operator is implicitly converted to a known
// integer type, that type is used for the literal; otherwise, the type
// of std::size_t or std::ptrdiff_t is used.
QualType T = (ImplicitlyConvertedToType.isNull() ||
!ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
: ImplicitlyConvertedToType;
llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());
mangleIntegerLiteral(T, V);
break;
}
switch(SAE->getKind()) {
case UETT_SizeOf:
Out << 's';
break;
case UETT_AlignOf:
Out << 'a';
break;
case UETT_VecStep: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot yet mangle vec_step expression");
Diags.Report(DiagID);
return;
}
case UETT_OpenMPRequiredSimdAlign: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot yet mangle __builtin_omp_required_simd_align expression");
Diags.Report(DiagID);
return;
}
// HLSL Change Begins
case UETT_ArrayLength: {
DiagnosticsEngine & Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot yet mangle .Length expression");
Diags.Report(DiagID);
return;
}
// HLSL Change Begins
}
if (SAE->isArgumentType()) {
Out << 't';
mangleType(SAE->getArgumentType());
} else {
Out << 'z';
mangleExpression(SAE->getArgumentExpr());
}
break;
}
case Expr::CXXThrowExprClass: {
const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);
// <expression> ::= tw <expression> # throw expression
// ::= tr # rethrow
if (TE->getSubExpr()) {
Out << "tw";
mangleExpression(TE->getSubExpr());
} else {
Out << "tr";
}
break;
}
case Expr::CXXTypeidExprClass: {
const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);
// <expression> ::= ti <type> # typeid (type)
// ::= te <expression> # typeid (expression)
if (TIE->isTypeOperand()) {
Out << "ti";
mangleType(TIE->getTypeOperand(Context.getASTContext()));
} else {
Out << "te";
mangleExpression(TIE->getExprOperand());
}
break;
}
case Expr::CXXDeleteExprClass: {
const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);
// <expression> ::= [gs] dl <expression> # [::] delete expr
// ::= [gs] da <expression> # [::] delete [] expr
if (DE->isGlobalDelete()) Out << "gs";
Out << (DE->isArrayForm() ? "da" : "dl");
mangleExpression(DE->getArgument());
break;
}
case Expr::UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(E);
mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
/*Arity=*/1);
mangleExpression(UO->getSubExpr());
break;
}
case Expr::ArraySubscriptExprClass: {
const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(E);
// Array subscript is treated as a syntactically weird form of
// binary operator.
Out << "ix";
mangleExpression(AE->getLHS());
mangleExpression(AE->getRHS());
break;
}
case Expr::CompoundAssignOperatorClass: // fallthrough
case Expr::BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(E);
if (BO->getOpcode() == BO_PtrMemD)
Out << "ds";
else
mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
/*Arity=*/2);
mangleExpression(BO->getLHS());
mangleExpression(BO->getRHS());
break;
}
case Expr::ConditionalOperatorClass: {
const ConditionalOperator *CO = cast<ConditionalOperator>(E);
mangleOperatorName(OO_Conditional, /*Arity=*/3);
mangleExpression(CO->getCond());
mangleExpression(CO->getLHS(), Arity);
mangleExpression(CO->getRHS(), Arity);
break;
}
case Expr::ImplicitCastExprClass: {
ImplicitlyConvertedToType = E->getType();
E = cast<ImplicitCastExpr>(E)->getSubExpr();
goto recurse;
}
case Expr::ObjCBridgedCastExprClass: {
// Mangle ownership casts as a vendor extended operator __bridge,
// __bridge_transfer, or __bridge_retain.
StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
Out << "v1U" << Kind.size() << Kind;
}
// Fall through to mangle the cast itself.
case Expr::CStyleCastExprClass:
mangleCastExpression(E, "cv");
break;
case Expr::CXXFunctionalCastExprClass: {
auto *Sub = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreImplicit();
// FIXME: Add isImplicit to CXXConstructExpr.
if (auto *CCE = dyn_cast<CXXConstructExpr>(Sub))
if (CCE->getParenOrBraceRange().isInvalid())
Sub = CCE->getArg(0)->IgnoreImplicit();
if (auto *StdInitList = dyn_cast<CXXStdInitializerListExpr>(Sub))
Sub = StdInitList->getSubExpr()->IgnoreImplicit();
if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
Out << "tl";
mangleType(E->getType());
mangleInitListElements(IL);
Out << "E";
} else {
mangleCastExpression(E, "cv");
}
break;
}
case Expr::CXXStaticCastExprClass:
mangleCastExpression(E, "sc");
break;
case Expr::CXXDynamicCastExprClass:
mangleCastExpression(E, "dc");
break;
case Expr::CXXReinterpretCastExprClass:
mangleCastExpression(E, "rc");
break;
case Expr::CXXConstCastExprClass:
mangleCastExpression(E, "cc");
break;
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
unsigned NumArgs = CE->getNumArgs();
mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
// Mangle the arguments.
for (unsigned i = 0; i != NumArgs; ++i)
mangleExpression(CE->getArg(i));
break;
}
case Expr::ParenExprClass:
mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);
break;
case Expr::DeclRefExprClass: {
const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
switch (D->getKind()) {
default:
// <expr-primary> ::= L <mangled-name> E # external name
Out << 'L';
mangle(D);
Out << 'E';
break;
case Decl::ParmVar:
mangleFunctionParam(cast<ParmVarDecl>(D));
break;
case Decl::EnumConstant: {
const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
mangleIntegerLiteral(ED->getType(), ED->getInitVal());
break;
}
case Decl::NonTypeTemplateParm: {
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
mangleTemplateParameter(PD->getIndex());
break;
}
}
break;
}
case Expr::SubstNonTypeTemplateParmPackExprClass:
// FIXME: not clear how to mangle this!
// template <unsigned N...> class A {
// template <class U...> void foo(U (&x)[N]...);
// };
Out << "_SUBSTPACK_";
break;
case Expr::FunctionParmPackExprClass: {
// FIXME: not clear how to mangle this!
const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
Out << "v110_SUBSTPACK";
mangleFunctionParam(FPPE->getParameterPack());
break;
}
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
// All the <unresolved-name> productions end in a
// base-unresolved-name, where <template-args> are just tacked
// onto the end.
if (DRE->hasExplicitTemplateArgs())
mangleTemplateArgs(DRE->getExplicitTemplateArgs());
break;
}
case Expr::CXXBindTemporaryExprClass:
mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());
break;
case Expr::ExprWithCleanupsClass:
mangleExpression(cast<ExprWithCleanups>(E)->getSubExpr(), Arity);
break;
case Expr::FloatingLiteralClass: {
const FloatingLiteral *FL = cast<FloatingLiteral>(E);
Out << 'L';
mangleType(FL->getType());
mangleFloat(FL->getValue());
Out << 'E';
break;
}
case Expr::CharacterLiteralClass:
Out << 'L';
mangleType(E->getType());
Out << cast<CharacterLiteral>(E)->getValue();
Out << 'E';
break;
// FIXME. __objc_yes/__objc_no are mangled same as true/false
case Expr::ObjCBoolLiteralExprClass:
Out << "Lb";
Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
case Expr::CXXBoolLiteralExprClass:
Out << "Lb";
Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
case Expr::IntegerLiteralClass: {
llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());
if (E->getType()->isSignedIntegerType())
Value.setIsSigned(true);
mangleIntegerLiteral(E->getType(), Value);
break;
}
case Expr::ImaginaryLiteralClass: {
const ImaginaryLiteral *IE = cast<ImaginaryLiteral>(E);
// Mangle as if a complex literal.
// Proposal from David Vandevoorde, 2010.06.30.
Out << 'L';
mangleType(E->getType());
if (const FloatingLiteral *Imag =
dyn_cast<FloatingLiteral>(IE->getSubExpr())) {
// Mangle a floating-point zero of the appropriate type.
mangleFloat(llvm::APFloat(Imag->getValue().getSemantics()));
Out << '_';
mangleFloat(Imag->getValue());
} else {
Out << "0_";
llvm::APSInt Value(cast<IntegerLiteral>(IE->getSubExpr())->getValue());
if (IE->getSubExpr()->getType()->isSignedIntegerType())
Value.setIsSigned(true);
mangleNumber(Value);
}
Out << 'E';
break;
}
case Expr::StringLiteralClass: {
// Revised proposal from David Vandervoorde, 2010.07.15.
Out << 'L';
assert(isa<ConstantArrayType>(E->getType()));
mangleType(E->getType());
Out << 'E';
break;
}
case Expr::GNUNullExprClass:
// FIXME: should this really be mangled the same as nullptr?
// fallthrough
case Expr::CXXNullPtrLiteralExprClass: {
Out << "LDnE";
break;
}
case Expr::PackExpansionExprClass:
Out << "sp";
mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
break;
case Expr::SizeOfPackExprClass: {
Out << "sZ";
const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack();
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
mangleTemplateParameter(TTP->getIndex());
else if (const NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Pack))
mangleTemplateParameter(NTTP->getIndex());
else if (const TemplateTemplateParmDecl *TempTP
= dyn_cast<TemplateTemplateParmDecl>(Pack))
mangleTemplateParameter(TempTP->getIndex());
else
mangleFunctionParam(cast<ParmVarDecl>(Pack));
break;
}
case Expr::MaterializeTemporaryExprClass: {
mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
break;
}
case Expr::CXXFoldExprClass: {
auto *FE = cast<CXXFoldExpr>(E);
if (FE->isLeftFold())
Out << (FE->getInit() ? "fL" : "fl");
else
Out << (FE->getInit() ? "fR" : "fr");
if (FE->getOperator() == BO_PtrMemD)
Out << "ds";
else
mangleOperatorName(
BinaryOperator::getOverloadedOperator(FE->getOperator()),
/*Arity=*/2);
if (FE->getLHS())
mangleExpression(FE->getLHS());
if (FE->getRHS())
mangleExpression(FE->getRHS());
break;
}
case Expr::CXXThisExprClass:
Out << "fpT";
break;
}
}