in clang/lib/AST/ItaniumMangle.cpp [4089:5072]
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
bool AsTemplateArg) {
// <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>
// ::= fpT # 'this' expression (part of <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
// ::= u <source-name> <template-arg>* E # vendor extended expression
// ::= <expr-primary>
// <expr-primary> ::= L <type> <value number> E # integer literal
// ::= L <type> <value float> E # floating literal
// ::= L <type> <string type> E # string literal
// ::= L <nullptr type> E # nullptr literal "LDnE"
// ::= L <pointer type> 0 E # null pointer template argument
// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C99); not used by clang
// ::= L <mangled-name> E # external name
QualType ImplicitlyConvertedToType;
// A top-level expression that's not <expr-primary> needs to be wrapped in
// X...E in a template arg.
bool IsPrimaryExpr = true;
auto NotPrimaryExpr = [&] {
if (AsTemplateArg && IsPrimaryExpr)
Out << 'X';
IsPrimaryExpr = false;
};
auto MangleDeclRefExpr = [&](const NamedDecl *D) {
switch (D->getKind()) {
default:
// <expr-primary> ::= L <mangled-name> E # external name
Out << 'L';
mangle(D);
Out << 'E';
break;
case Decl::ParmVar:
NotPrimaryExpr();
mangleFunctionParam(cast<ParmVarDecl>(D));
break;
case Decl::EnumConstant: {
// <expr-primary>
const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
mangleIntegerLiteral(ED->getType(), ED->getInitVal());
break;
}
case Decl::NonTypeTemplateParm:
NotPrimaryExpr();
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
mangleTemplateParameter(PD->getDepth(), PD->getIndex());
break;
}
};
// 'goto recurse' is used when handling a simple "unwrapping" node which
// produces no output, where ImplicitlyConvertedToType and AsTemplateArg need
// to be preserved.
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::ArrayInitLoopExprClass:
case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ParenListExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
case Expr::RecoveryExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
case Expr::ConstantExprClass:
E = cast<ConstantExpr>(E)->getSubExpr();
goto recurse;
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
case Expr::ChooseExprClass:
case Expr::CompoundLiteralExprClass:
case Expr::ExtVectorElementExprClass:
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::ObjCAvailabilityCheckExprClass:
case Expr::OffsetOfExprClass:
case Expr::PredefinedExprClass:
case Expr::ShuffleVectorExprClass:
case Expr::ConvertVectorExprClass:
case Expr::StmtExprClass:
case Expr::TypeTraitExprClass:
case Expr::RequiresExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
case Expr::VAArgExprClass:
case Expr::CUDAKernelCallExprClass:
case Expr::AsTypeExprClass:
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
case Expr::SourceLocExprClass:
case Expr::BuiltinBitCastExprClass:
{
NotPrimaryExpr();
if (!NullOut) {
// 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();
return;
}
break;
}
case Expr::CXXUuidofExprClass: {
NotPrimaryExpr();
const CXXUuidofExpr *UE = cast<CXXUuidofExpr>(E);
// As of clang 12, uuidof uses the vendor extended expression
// mangling. Previously, it used a special-cased nonstandard extension.
if (Context.getASTContext().getLangOpts().getClangABICompat() >
LangOptions::ClangABI::Ver11) {
Out << "u8__uuidof";
if (UE->isTypeOperand())
mangleType(UE->getTypeOperand(Context.getASTContext()));
else
mangleTemplateArgExpr(UE->getExprOperand());
Out << 'E';
} else {
if (UE->isTypeOperand()) {
QualType UuidT = UE->getTypeOperand(Context.getASTContext());
Out << "u8__uuidoft";
mangleType(UuidT);
} else {
Expr *UuidExp = UE->getExprOperand();
Out << "u8__uuidofz";
mangleExpression(UuidExp);
}
}
break;
}
// Even gcc-4.5 doesn't mangle this.
case Expr::BinaryConditionalOperatorClass: {
NotPrimaryExpr();
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();
return;
}
// 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: {
NotPrimaryExpr();
Out << "il";
mangleInitListElements(cast<InitListExpr>(E));
Out << "E";
break;
}
case Expr::DesignatedInitExprClass: {
NotPrimaryExpr();
auto *DIE = cast<DesignatedInitExpr>(E);
for (const auto &Designator : DIE->designators()) {
if (Designator.isFieldDesignator()) {
Out << "di";
mangleSourceName(Designator.getFieldName());
} else if (Designator.isArrayDesignator()) {
Out << "dx";
mangleExpression(DIE->getArrayIndex(Designator));
} else {
assert(Designator.isArrayRangeDesignator() &&
"unknown designator kind");
Out << "dX";
mangleExpression(DIE->getArrayRangeStart(Designator));
mangleExpression(DIE->getArrayRangeEnd(Designator));
}
}
mangleExpression(DIE->getInit());
break;
}
case Expr::CXXDefaultArgExprClass:
E = cast<CXXDefaultArgExpr>(E)->getExpr();
goto recurse;
case Expr::CXXDefaultInitExprClass:
E = cast<CXXDefaultInitExpr>(E)->getExpr();
goto recurse;
case Expr::CXXStdInitializerListExprClass:
E = cast<CXXStdInitializerListExpr>(E)->getSubExpr();
goto recurse;
case Expr::SubstNonTypeTemplateParmExprClass:
E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
goto recurse;
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: {
NotPrimaryExpr();
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: {
NotPrimaryExpr();
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: {
NotPrimaryExpr();
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
if (const Expr *Base = PDE->getBase())
mangleMemberExprBase(Base, PDE->isArrow());
NestedNameSpecifier *Qualifier = PDE->getQualifier();
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: {
NotPrimaryExpr();
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
ME->getMemberDecl()->getDeclName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
break;
}
case Expr::UnresolvedMemberExprClass: {
NotPrimaryExpr();
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
ME->getMemberName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
break;
}
case Expr::CXXDependentScopeMemberExprClass: {
NotPrimaryExpr();
const CXXDependentScopeMemberExpr *ME
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
ME->getFirstQualifierFoundInScope(),
ME->getMember(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
break;
}
case Expr::UnresolvedLookupExprClass: {
NotPrimaryExpr();
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(),
ULE->getTemplateArgs(), ULE->getNumTemplateArgs(),
Arity);
break;
}
case Expr::CXXUnresolvedConstructExprClass: {
NotPrimaryExpr();
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
unsigned N = CE->getNumArgs();
if (CE->isListInitialization()) {
assert(N == 1 && "unexpected form for list initialization");
auto *IL = cast<InitListExpr>(CE->getArg(0));
Out << "tl";
mangleType(CE->getType());
mangleInitListElements(IL);
Out << "E";
break;
}
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: {
// An implicit cast is silent, thus may contain <expr-primary>.
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");
E = cast<CXXConstructExpr>(E)->getArg(0);
goto recurse;
}
NotPrimaryExpr();
Out << "il";
for (auto *E : CE->arguments())
mangleExpression(E);
Out << "E";
break;
}
case Expr::CXXTemporaryObjectExprClass: {
NotPrimaryExpr();
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:
NotPrimaryExpr();
Out << "cv";
mangleType(E->getType());
Out << "_E";
break;
case Expr::CXXNoexceptExprClass:
NotPrimaryExpr();
Out << "nx";
mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
break;
case Expr::UnaryExprOrTypeTraitExprClass: {
// Non-instantiation-dependent traits are an <expr-primary> integer literal.
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;
}
NotPrimaryExpr(); // But otherwise, they are not.
auto MangleAlignofSizeofArg = [&] {
if (SAE->isArgumentType()) {
Out << 't';
mangleType(SAE->getArgumentType());
} else {
Out << 'z';
mangleExpression(SAE->getArgumentExpr());
}
};
switch(SAE->getKind()) {
case UETT_SizeOf:
Out << 's';
MangleAlignofSizeofArg();
break;
case UETT_PreferredAlignOf:
// As of clang 12, we mangle __alignof__ differently than alignof. (They
// have acted differently since Clang 8, but were previously mangled the
// same.)
if (Context.getASTContext().getLangOpts().getClangABICompat() >
LangOptions::ClangABI::Ver11) {
Out << "u11__alignof__";
if (SAE->isArgumentType())
mangleType(SAE->getArgumentType());
else
mangleTemplateArgExpr(SAE->getArgumentExpr());
Out << 'E';
break;
}
LLVM_FALLTHROUGH;
case UETT_AlignOf:
Out << 'a';
MangleAlignofSizeofArg();
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;
}
}
break;
}
case Expr::CXXThrowExprClass: {
NotPrimaryExpr();
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: {
NotPrimaryExpr();
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: {
NotPrimaryExpr();
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: {
NotPrimaryExpr();
const UnaryOperator *UO = cast<UnaryOperator>(E);
mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
/*Arity=*/1);
mangleExpression(UO->getSubExpr());
break;
}
case Expr::ArraySubscriptExprClass: {
NotPrimaryExpr();
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::MatrixSubscriptExprClass: {
NotPrimaryExpr();
const MatrixSubscriptExpr *ME = cast<MatrixSubscriptExpr>(E);
Out << "ixix";
mangleExpression(ME->getBase());
mangleExpression(ME->getRowIdx());
mangleExpression(ME->getColumnIdx());
break;
}
case Expr::CompoundAssignOperatorClass: // fallthrough
case Expr::BinaryOperatorClass: {
NotPrimaryExpr();
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::CXXRewrittenBinaryOperatorClass: {
NotPrimaryExpr();
// The mangled form represents the original syntax.
CXXRewrittenBinaryOperator::DecomposedForm Decomposed =
cast<CXXRewrittenBinaryOperator>(E)->getDecomposedForm();
mangleOperatorName(BinaryOperator::getOverloadedOperator(Decomposed.Opcode),
/*Arity=*/2);
mangleExpression(Decomposed.LHS);
mangleExpression(Decomposed.RHS);
break;
}
case Expr::ConditionalOperatorClass: {
NotPrimaryExpr();
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: {
NotPrimaryExpr();
// 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;
mangleCastExpression(E, "cv");
break;
}
case Expr::CStyleCastExprClass:
NotPrimaryExpr();
mangleCastExpression(E, "cv");
break;
case Expr::CXXFunctionalCastExprClass: {
NotPrimaryExpr();
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:
NotPrimaryExpr();
mangleCastExpression(E, "sc");
break;
case Expr::CXXDynamicCastExprClass:
NotPrimaryExpr();
mangleCastExpression(E, "dc");
break;
case Expr::CXXReinterpretCastExprClass:
NotPrimaryExpr();
mangleCastExpression(E, "rc");
break;
case Expr::CXXConstCastExprClass:
NotPrimaryExpr();
mangleCastExpression(E, "cc");
break;
case Expr::CXXAddrspaceCastExprClass:
NotPrimaryExpr();
mangleCastExpression(E, "ac");
break;
case Expr::CXXOperatorCallExprClass: {
NotPrimaryExpr();
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
unsigned NumArgs = CE->getNumArgs();
// A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax
// (the enclosing MemberExpr covers the syntactic portion).
if (CE->getOperator() != OO_Arrow)
mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
// Mangle the arguments.
for (unsigned i = 0; i != NumArgs; ++i)
mangleExpression(CE->getArg(i));
break;
}
case Expr::ParenExprClass:
E = cast<ParenExpr>(E)->getSubExpr();
goto recurse;
case Expr::ConceptSpecializationExprClass: {
// <expr-primary> ::= L <mangled-name> E # external name
Out << "L_Z";
auto *CSE = cast<ConceptSpecializationExpr>(E);
mangleTemplateName(CSE->getNamedConcept(),
CSE->getTemplateArguments().data(),
CSE->getTemplateArguments().size());
Out << 'E';
break;
}
case Expr::DeclRefExprClass:
// MangleDeclRefExpr helper handles primary-vs-nonprimary
MangleDeclRefExpr(cast<DeclRefExpr>(E)->getDecl());
break;
case Expr::SubstNonTypeTemplateParmPackExprClass:
NotPrimaryExpr();
// 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: {
NotPrimaryExpr();
// FIXME: not clear how to mangle this!
const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
Out << "v110_SUBSTPACK";
MangleDeclRefExpr(FPPE->getParameterPack());
break;
}
case Expr::DependentScopeDeclRefExprClass: {
NotPrimaryExpr();
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(),
DRE->getTemplateArgs(), DRE->getNumTemplateArgs(),
Arity);
break;
}
case Expr::CXXBindTemporaryExprClass:
E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
goto recurse;
case Expr::ExprWithCleanupsClass:
E = cast<ExprWithCleanups>(E)->getSubExpr();
goto recurse;
case Expr::FloatingLiteralClass: {
// <expr-primary>
const FloatingLiteral *FL = cast<FloatingLiteral>(E);
mangleFloatLiteral(FL->getType(), FL->getValue());
break;
}
case Expr::FixedPointLiteralClass:
// Currently unimplemented -- might be <expr-primary> in future?
mangleFixedPointLiteral();
break;
case Expr::CharacterLiteralClass:
// <expr-primary>
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:
// <expr-primary>
Out << "Lb";
Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
case Expr::CXXBoolLiteralExprClass:
// <expr-primary>
Out << "Lb";
Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
Out << 'E';
break;
case Expr::IntegerLiteralClass: {
// <expr-primary>
llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());
if (E->getType()->isSignedIntegerType())
Value.setIsSigned(true);
mangleIntegerLiteral(E->getType(), Value);
break;
}
case Expr::ImaginaryLiteralClass: {
// <expr-primary>
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: {
// <expr-primary>
// Revised proposal from David Vandervoorde, 2010.07.15.
Out << 'L';
assert(isa<ConstantArrayType>(E->getType()));
mangleType(E->getType());
Out << 'E';
break;
}
case Expr::GNUNullExprClass:
// <expr-primary>
// Mangle as if an integer literal 0.
mangleIntegerLiteral(E->getType(), llvm::APSInt(32));
break;
case Expr::CXXNullPtrLiteralExprClass: {
// <expr-primary>
Out << "LDnE";
break;
}
case Expr::LambdaExprClass: {
// A lambda-expression can't appear in the signature of an
// externally-visible declaration, so there's no standard mangling for
// this, but mangling as a literal of the closure type seems reasonable.
Out << "L";
mangleType(Context.getASTContext().getRecordType(cast<LambdaExpr>(E)->getLambdaClass()));
Out << "E";
break;
}
case Expr::PackExpansionExprClass:
NotPrimaryExpr();
Out << "sp";
mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
break;
case Expr::SizeOfPackExprClass: {
NotPrimaryExpr();
auto *SPE = cast<SizeOfPackExpr>(E);
if (SPE->isPartiallySubstituted()) {
Out << "sP";
for (const auto &A : SPE->getPartialArguments())
mangleTemplateArg(A, false);
Out << "E";
break;
}
Out << "sZ";
const NamedDecl *Pack = SPE->getPack();
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
else if (const NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Pack))
mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex());
else if (const TemplateTemplateParmDecl *TempTP
= dyn_cast<TemplateTemplateParmDecl>(Pack))
mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex());
else
mangleFunctionParam(cast<ParmVarDecl>(Pack));
break;
}
case Expr::MaterializeTemporaryExprClass:
E = cast<MaterializeTemporaryExpr>(E)->getSubExpr();
goto recurse;
case Expr::CXXFoldExprClass: {
NotPrimaryExpr();
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:
NotPrimaryExpr();
Out << "fpT";
break;
case Expr::CoawaitExprClass:
// FIXME: Propose a non-vendor mangling.
NotPrimaryExpr();
Out << "v18co_await";
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
break;
case Expr::DependentCoawaitExprClass:
// FIXME: Propose a non-vendor mangling.
NotPrimaryExpr();
Out << "v18co_await";
mangleExpression(cast<DependentCoawaitExpr>(E)->getOperand());
break;
case Expr::CoyieldExprClass:
// FIXME: Propose a non-vendor mangling.
NotPrimaryExpr();
Out << "v18co_yield";
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
break;
case Expr::SYCLUniqueStableNameExprClass: {
const auto *USN = cast<SYCLUniqueStableNameExpr>(E);
NotPrimaryExpr();
Out << "u33__builtin_sycl_unique_stable_name";
mangleType(USN->getTypeSourceInfo()->getType());
Out << "E";
break;
}
}
if (AsTemplateArg && !IsPrimaryExpr)
Out << 'E';
}