2012-12-18 22:30:41 +08:00
|
|
|
//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2012-12-18 22:30:41 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Implements C++ name mangling according to the Itanium C++ ABI,
|
|
|
|
// which is used in GCC 3.2 and newer (and many compilers that are
|
|
|
|
// ABI-compatible with GCC):
|
|
|
|
//
|
2017-09-12 08:21:17 +08:00
|
|
|
// http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
|
2012-12-18 22:30:41 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2020-02-28 10:13:54 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
#include "clang/AST/Mangle.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/Attr.h"
|
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
2016-03-03 13:21:39 +08:00
|
|
|
#include "clang/AST/DeclOpenMP.h"
|
2012-12-18 22:30:41 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2014-03-25 05:43:36 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2020-01-18 15:11:43 +08:00
|
|
|
#include "clang/AST/ExprConcepts.h"
|
2012-12-18 22:30:41 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
|
#include "clang/AST/ExprObjC.h"
|
|
|
|
#include "clang/AST/TypeLoc.h"
|
|
|
|
#include "clang/Basic/ABI.h"
|
2020-02-28 10:13:54 +08:00
|
|
|
#include "clang/Basic/Module.h"
|
2012-12-18 22:30:41 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "clang/Basic/TargetInfo.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Retrieve the declaration context that should be used when mangling the given
|
|
|
|
/// declaration.
|
2012-12-18 22:30:41 +08:00
|
|
|
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
|
2018-07-31 03:24:48 +08:00
|
|
|
// The ABI assumes that lambda closure types that occur within
|
2012-12-18 22:30:41 +08:00
|
|
|
// default arguments live in the context of the function. However, due to
|
|
|
|
// the way in which Clang parses and creates function declarations, this is
|
2018-07-31 03:24:48 +08:00
|
|
|
// not the case: the lambda closure type ends up living in the context
|
2012-12-18 22:30:41 +08:00
|
|
|
// where the function itself resides, because the function declaration itself
|
|
|
|
// had not yet been created. Fix the context here.
|
|
|
|
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
if (RD->isLambda())
|
|
|
|
if (ParmVarDecl *ContextParam
|
|
|
|
= dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
|
|
|
|
return ContextParam->getDeclContext();
|
|
|
|
}
|
2013-07-10 09:33:19 +08:00
|
|
|
|
|
|
|
// Perform the same check for block literals.
|
|
|
|
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
|
|
|
if (ParmVarDecl *ContextParam
|
|
|
|
= dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
|
|
|
|
return ContextParam->getDeclContext();
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-07-03 01:52:28 +08:00
|
|
|
const DeclContext *DC = D->getDeclContext();
|
2019-02-02 04:25:04 +08:00
|
|
|
if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
|
|
|
|
isa<OMPDeclareMapperDecl>(DC)) {
|
2016-03-03 13:21:39 +08:00
|
|
|
return getEffectiveDeclContext(cast<Decl>(DC));
|
|
|
|
}
|
2013-07-03 01:52:28 +08:00
|
|
|
|
2015-02-19 03:08:11 +08:00
|
|
|
if (const auto *VD = dyn_cast<VarDecl>(D))
|
|
|
|
if (VD->isExternC())
|
|
|
|
return VD->getASTContext().getTranslationUnitDecl();
|
|
|
|
|
|
|
|
if (const auto *FD = dyn_cast<FunctionDecl>(D))
|
|
|
|
if (FD->isExternC())
|
|
|
|
return FD->getASTContext().getTranslationUnitDecl();
|
|
|
|
|
2016-04-29 09:23:20 +08:00
|
|
|
return DC->getRedeclContext();
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
|
|
|
|
return getEffectiveDeclContext(cast<Decl>(DC));
|
|
|
|
}
|
2013-07-03 01:52:28 +08:00
|
|
|
|
|
|
|
static bool isLocalContainerContext(const DeclContext *DC) {
|
|
|
|
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
|
|
|
|
}
|
|
|
|
|
2013-07-06 04:27:40 +08:00
|
|
|
static const RecordDecl *GetLocalClassDecl(const Decl *D) {
|
2013-07-02 10:01:18 +08:00
|
|
|
const DeclContext *DC = getEffectiveDeclContext(D);
|
2012-12-18 22:30:41 +08:00
|
|
|
while (!DC->isNamespace() && !DC->isTranslationUnit()) {
|
2013-07-03 01:52:28 +08:00
|
|
|
if (isLocalContainerContext(DC))
|
2013-07-06 04:27:40 +08:00
|
|
|
return dyn_cast<RecordDecl>(D);
|
2013-07-02 10:01:18 +08:00
|
|
|
D = cast<Decl>(DC);
|
|
|
|
DC = getEffectiveDeclContext(D);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const FunctionDecl *getStructor(const FunctionDecl *fn) {
|
|
|
|
if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
|
|
|
|
return ftd->getTemplatedDecl();
|
|
|
|
|
|
|
|
return fn;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const NamedDecl *getStructor(const NamedDecl *decl) {
|
|
|
|
const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl);
|
|
|
|
return (fn ? getStructor(fn) : decl);
|
|
|
|
}
|
2014-03-05 16:57:59 +08:00
|
|
|
|
|
|
|
static bool isLambda(const NamedDecl *ND) {
|
|
|
|
const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
|
|
|
|
if (!Record)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return Record->isLambda();
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
static const unsigned UnknownArity = ~0U;
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
class ItaniumMangleContextImpl : public ItaniumMangleContext {
|
2013-07-10 08:30:46 +08:00
|
|
|
typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy;
|
|
|
|
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
|
2012-12-18 22:30:41 +08:00
|
|
|
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
|
2014-12-13 00:17:46 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
public:
|
2013-10-03 14:26:13 +08:00
|
|
|
explicit ItaniumMangleContextImpl(ASTContext &Context,
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
DiagnosticsEngine &Diags,
|
|
|
|
bool IsUniqueNameMangler)
|
|
|
|
: ItaniumMangleContext(Context, Diags, IsUniqueNameMangler) {}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
/// @name Mangler Entry Points
|
|
|
|
/// @{
|
|
|
|
|
2014-03-11 14:22:39 +08:00
|
|
|
bool shouldMangleCXXName(const NamedDecl *D) override;
|
2014-03-25 05:43:36 +08:00
|
|
|
bool shouldMangleStringLiteral(const StringLiteral *) override {
|
|
|
|
return false;
|
|
|
|
}
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleCXXName(GlobalDecl GD, raw_ostream &) override;
|
2014-03-11 14:22:39 +08:00
|
|
|
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
|
|
|
|
raw_ostream &) override;
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
|
|
|
|
const ThisAdjustment &ThisAdjustment,
|
2014-03-11 14:22:39 +08:00
|
|
|
raw_ostream &) override;
|
2014-05-02 01:50:17 +08:00
|
|
|
void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber,
|
|
|
|
raw_ostream &) override;
|
2014-03-11 14:22:39 +08:00
|
|
|
void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override;
|
|
|
|
void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) override;
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
|
2014-03-11 14:22:39 +08:00
|
|
|
const CXXRecordDecl *Type, raw_ostream &) override;
|
|
|
|
void mangleCXXRTTI(QualType T, raw_ostream &) override;
|
|
|
|
void mangleCXXRTTIName(QualType T, raw_ostream &) override;
|
|
|
|
void mangleTypeName(QualType T, raw_ostream &) override;
|
|
|
|
|
2014-09-16 23:18:21 +08:00
|
|
|
void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override;
|
|
|
|
void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override;
|
2014-03-11 14:22:39 +08:00
|
|
|
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) override;
|
|
|
|
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
|
|
|
|
void mangleDynamicAtExitDestructor(const VarDecl *D,
|
|
|
|
raw_ostream &Out) override;
|
2020-05-28 05:04:43 +08:00
|
|
|
void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &Out) override;
|
Initial support for Win64 SEH IR emission
The lowering looks a lot like normal EH lowering, with the exception
that the exceptions are caught by executing filter expression code
instead of matching typeinfo globals. The filter expressions are
outlined into functions which are used in landingpad clauses where
typeinfo would normally go.
Major aspects that still need work:
- Non-call exceptions in __try bodies won't work yet. The plan is to
outline the __try block in the frontend to keep things simple.
- Filter expressions cannot use local variables until capturing is
implemented.
- __finally blocks will not run after exceptions. Fixing this requires
work in the LLVM SEH preparation pass.
The IR lowering looks like this:
// C code:
bool safe_div(int n, int d, int *r) {
__try {
*r = normal_div(n, d);
} __except(_exception_code() == EXCEPTION_INT_DIVIDE_BY_ZERO) {
return false;
}
return true;
}
; LLVM IR:
define i32 @filter(i8* %e, i8* %fp) {
%ehptrs = bitcast i8* %e to i32**
%ehrec = load i32** %ehptrs
%code = load i32* %ehrec
%matches = icmp eq i32 %code, i32 u0xC0000094
%matches.i32 = zext i1 %matches to i32
ret i32 %matches.i32
}
define i1 zeroext @safe_div(i32 %n, i32 %d, i32* %r) {
%rr = invoke i32 @normal_div(i32 %n, i32 %d)
to label %normal unwind to label %lpad
normal:
store i32 %rr, i32* %r
ret i1 1
lpad:
%ehvals = landingpad {i8*, i32} personality i32 (...)* @__C_specific_handler
catch i8* bitcast (i32 (i8*, i8*)* @filter to i8*)
%ehptr = extractvalue {i8*, i32} %ehvals, i32 0
%sel = extractvalue {i8*, i32} %ehvals, i32 1
%filter_sel = call i32 @llvm.eh.seh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @filter to i8*))
%matches = icmp eq i32 %sel, %filter_sel
br i1 %matches, label %eh.except, label %eh.resume
eh.except:
ret i1 false
eh.resume:
resume
}
Reviewers: rjmccall, rsmith, majnemer
Differential Revision: http://reviews.llvm.org/D5607
llvm-svn: 226760
2015-01-22 09:36:17 +08:00
|
|
|
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
|
|
|
|
raw_ostream &Out) override;
|
2015-04-15 04:59:00 +08:00
|
|
|
void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
|
|
|
|
raw_ostream &Out) override;
|
2014-03-11 14:22:39 +08:00
|
|
|
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
|
|
|
|
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
|
|
|
|
raw_ostream &) override;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2014-03-25 05:43:36 +08:00
|
|
|
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
|
|
|
|
|
2019-09-05 09:23:47 +08:00
|
|
|
void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override;
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
|
2013-07-10 08:30:46 +08:00
|
|
|
// Lambda closure types are already numbered.
|
2014-03-05 16:57:59 +08:00
|
|
|
if (isLambda(ND))
|
|
|
|
return false;
|
2013-07-10 08:30:46 +08:00
|
|
|
|
|
|
|
// Anonymous tags are already numbered.
|
|
|
|
if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
|
|
|
|
if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use the canonical number for externally visible decls.
|
|
|
|
if (ND->isExternallyVisible()) {
|
|
|
|
unsigned discriminator = getASTContext().getManglingNumber(ND);
|
|
|
|
if (discriminator == 1)
|
|
|
|
return false;
|
|
|
|
disc = discriminator - 2;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make up a reasonable number for internal decls.
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned &discriminator = Uniquifier[ND];
|
2013-07-10 08:30:46 +08:00
|
|
|
if (!discriminator) {
|
|
|
|
const DeclContext *DC = getEffectiveDeclContext(ND);
|
|
|
|
discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())];
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
if (discriminator == 1)
|
|
|
|
return false;
|
|
|
|
disc = discriminator-2;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/// @}
|
|
|
|
};
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Manage the mangling of a single name.
|
2012-12-18 22:30:41 +08:00
|
|
|
class CXXNameMangler {
|
2013-10-03 14:26:13 +08:00
|
|
|
ItaniumMangleContextImpl &Context;
|
2012-12-18 22:30:41 +08:00
|
|
|
raw_ostream &Out;
|
2016-06-30 17:40:38 +08:00
|
|
|
bool NullOut = false;
|
|
|
|
/// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated.
|
|
|
|
/// This mode is used when mangler creates another mangler recursively to
|
|
|
|
/// calculate ABI tags for the function return value or the variable type.
|
|
|
|
/// Also it is required to avoid infinite recursion in some cases.
|
|
|
|
bool DisableDerivedAbiTags = false;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
/// The "structor" is the top-level declaration being mangled, if
|
|
|
|
/// that's not a template specialization; otherwise it's the pattern
|
|
|
|
/// for that specialization.
|
|
|
|
const NamedDecl *Structor;
|
|
|
|
unsigned StructorType;
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// The next substitution sequence number.
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned SeqID;
|
|
|
|
|
|
|
|
class FunctionTypeDepthState {
|
|
|
|
unsigned Bits;
|
|
|
|
|
|
|
|
enum { InResultTypeMask = 1 };
|
|
|
|
|
|
|
|
public:
|
|
|
|
FunctionTypeDepthState() : Bits(0) {}
|
|
|
|
|
|
|
|
/// The number of function types we're inside.
|
|
|
|
unsigned getDepth() const {
|
|
|
|
return Bits >> 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// True if we're in the return type of the innermost function type.
|
|
|
|
bool isInResultType() const {
|
|
|
|
return Bits & InResultTypeMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionTypeDepthState push() {
|
|
|
|
FunctionTypeDepthState tmp = *this;
|
|
|
|
Bits = (Bits & ~InResultTypeMask) + 2;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void enterResultType() {
|
|
|
|
Bits |= InResultTypeMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
void leaveResultType() {
|
|
|
|
Bits &= ~InResultTypeMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pop(FunctionTypeDepthState saved) {
|
|
|
|
assert(getDepth() == saved.getDepth() + 1);
|
|
|
|
Bits = saved.Bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
} FunctionTypeDepth;
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
// abi_tag is a gcc attribute, taking one or more strings called "tags".
|
|
|
|
// The goal is to annotate against which version of a library an object was
|
|
|
|
// built and to be able to provide backwards compatibility ("dual abi").
|
|
|
|
// For more information see docs/ItaniumMangleAbiTags.rst.
|
|
|
|
typedef SmallVector<StringRef, 4> AbiTagList;
|
|
|
|
|
|
|
|
// State to gather all implicit and explicit tags used in a mangled name.
|
|
|
|
// Must always have an instance of this while emitting any name to keep
|
|
|
|
// track.
|
|
|
|
class AbiTagState final {
|
|
|
|
public:
|
|
|
|
explicit AbiTagState(AbiTagState *&Head) : LinkHead(Head) {
|
|
|
|
Parent = LinkHead;
|
|
|
|
LinkHead = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// No copy, no move.
|
|
|
|
AbiTagState(const AbiTagState &) = delete;
|
|
|
|
AbiTagState &operator=(const AbiTagState &) = delete;
|
|
|
|
|
|
|
|
~AbiTagState() { pop(); }
|
|
|
|
|
|
|
|
void write(raw_ostream &Out, const NamedDecl *ND,
|
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
|
|
|
ND = cast<NamedDecl>(ND->getCanonicalDecl());
|
|
|
|
if (!isa<FunctionDecl>(ND) && !isa<VarDecl>(ND)) {
|
|
|
|
assert(
|
|
|
|
!AdditionalAbiTags &&
|
|
|
|
"only function and variables need a list of additional abi tags");
|
|
|
|
if (const auto *NS = dyn_cast<NamespaceDecl>(ND)) {
|
|
|
|
if (const auto *AbiTag = NS->getAttr<AbiTagAttr>()) {
|
|
|
|
UsedAbiTags.insert(UsedAbiTags.end(), AbiTag->tags().begin(),
|
|
|
|
AbiTag->tags().end());
|
|
|
|
}
|
|
|
|
// Don't emit abi tags for namespaces.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AbiTagList TagList;
|
|
|
|
if (const auto *AbiTag = ND->getAttr<AbiTagAttr>()) {
|
|
|
|
UsedAbiTags.insert(UsedAbiTags.end(), AbiTag->tags().begin(),
|
|
|
|
AbiTag->tags().end());
|
|
|
|
TagList.insert(TagList.end(), AbiTag->tags().begin(),
|
|
|
|
AbiTag->tags().end());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (AdditionalAbiTags) {
|
|
|
|
UsedAbiTags.insert(UsedAbiTags.end(), AdditionalAbiTags->begin(),
|
|
|
|
AdditionalAbiTags->end());
|
|
|
|
TagList.insert(TagList.end(), AdditionalAbiTags->begin(),
|
|
|
|
AdditionalAbiTags->end());
|
|
|
|
}
|
|
|
|
|
2018-09-27 06:16:28 +08:00
|
|
|
llvm::sort(TagList);
|
2016-06-30 17:40:38 +08:00
|
|
|
TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end());
|
|
|
|
|
|
|
|
writeSortedUniqueAbiTags(Out, TagList);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AbiTagList &getUsedAbiTags() const { return UsedAbiTags; }
|
|
|
|
void setUsedAbiTags(const AbiTagList &AbiTags) {
|
|
|
|
UsedAbiTags = AbiTags;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AbiTagList &getEmittedAbiTags() const {
|
|
|
|
return EmittedAbiTags;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AbiTagList &getSortedUniqueUsedAbiTags() {
|
2018-09-27 06:16:28 +08:00
|
|
|
llvm::sort(UsedAbiTags);
|
2016-06-30 17:40:38 +08:00
|
|
|
UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()),
|
|
|
|
UsedAbiTags.end());
|
|
|
|
return UsedAbiTags;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
//! All abi tags used implicitly or explicitly.
|
|
|
|
AbiTagList UsedAbiTags;
|
|
|
|
//! All explicit abi tags (i.e. not from namespace).
|
|
|
|
AbiTagList EmittedAbiTags;
|
|
|
|
|
|
|
|
AbiTagState *&LinkHead;
|
|
|
|
AbiTagState *Parent = nullptr;
|
|
|
|
|
|
|
|
void pop() {
|
|
|
|
assert(LinkHead == this &&
|
|
|
|
"abi tag link head must point to us on destruction");
|
|
|
|
if (Parent) {
|
|
|
|
Parent->UsedAbiTags.insert(Parent->UsedAbiTags.end(),
|
|
|
|
UsedAbiTags.begin(), UsedAbiTags.end());
|
|
|
|
Parent->EmittedAbiTags.insert(Parent->EmittedAbiTags.end(),
|
|
|
|
EmittedAbiTags.begin(),
|
|
|
|
EmittedAbiTags.end());
|
|
|
|
}
|
|
|
|
LinkHead = Parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeSortedUniqueAbiTags(raw_ostream &Out, const AbiTagList &AbiTags) {
|
|
|
|
for (const auto &Tag : AbiTags) {
|
|
|
|
EmittedAbiTags.push_back(Tag);
|
|
|
|
Out << "B";
|
|
|
|
Out << Tag.size();
|
|
|
|
Out << Tag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
AbiTagState *AbiTags = nullptr;
|
|
|
|
AbiTagState AbiTagsRoot;
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
|
2017-09-04 13:37:53 +08:00
|
|
|
llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
ASTContext &getASTContext() const { return Context.getASTContext(); }
|
|
|
|
|
|
|
|
public:
|
2013-10-03 14:26:13 +08:00
|
|
|
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
|
2016-06-30 17:40:38 +08:00
|
|
|
const NamedDecl *D = nullptr, bool NullOut_ = false)
|
|
|
|
: Context(C), Out(Out_), NullOut(NullOut_), Structor(getStructor(D)),
|
|
|
|
StructorType(0), SeqID(0), AbiTagsRoot(AbiTags) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// These can't be mangled without a ctor type or dtor type.
|
|
|
|
assert(!D || (!isa<CXXDestructorDecl>(D) &&
|
|
|
|
!isa<CXXConstructorDecl>(D)));
|
|
|
|
}
|
2013-10-03 14:26:13 +08:00
|
|
|
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
|
2012-12-18 22:30:41 +08:00
|
|
|
const CXXConstructorDecl *D, CXXCtorType Type)
|
|
|
|
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
|
2016-06-30 17:40:38 +08:00
|
|
|
SeqID(0), AbiTagsRoot(AbiTags) { }
|
2013-10-03 14:26:13 +08:00
|
|
|
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
|
2012-12-18 22:30:41 +08:00
|
|
|
const CXXDestructorDecl *D, CXXDtorType Type)
|
|
|
|
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
|
2016-06-30 17:40:38 +08:00
|
|
|
SeqID(0), AbiTagsRoot(AbiTags) { }
|
|
|
|
|
|
|
|
CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_)
|
|
|
|
: Context(Outer.Context), Out(Out_), NullOut(false),
|
|
|
|
Structor(Outer.Structor), StructorType(Outer.StructorType),
|
2016-10-06 17:37:15 +08:00
|
|
|
SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
|
|
|
|
AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
|
2016-06-30 17:40:38 +08:00
|
|
|
|
|
|
|
CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_)
|
|
|
|
: Context(Outer.Context), Out(Out_), NullOut(true),
|
|
|
|
Structor(Outer.Structor), StructorType(Outer.StructorType),
|
2016-10-06 17:37:15 +08:00
|
|
|
SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
|
|
|
|
AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
raw_ostream &getStream() { return Out; }
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
void disableDerivedAbiTags() { DisableDerivedAbiTags = true; }
|
|
|
|
static bool shouldHaveAbiTags(ItaniumMangleContextImpl &C, const VarDecl *VD);
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangle(GlobalDecl GD);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
|
|
|
|
void mangleNumber(const llvm::APSInt &I);
|
|
|
|
void mangleNumber(int64_t Number);
|
|
|
|
void mangleFloat(const llvm::APFloat &F);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleFunctionEncoding(GlobalDecl GD);
|
2014-05-07 06:49:16 +08:00
|
|
|
void mangleSeqID(unsigned SeqID);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleName(GlobalDecl GD);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleType(QualType T);
|
|
|
|
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
|
2019-09-05 09:23:47 +08:00
|
|
|
void mangleLambdaSig(const CXXRecordDecl *Lambda);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
private:
|
2014-05-07 06:49:16 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
bool mangleSubstitution(const NamedDecl *ND);
|
|
|
|
bool mangleSubstitution(QualType T);
|
|
|
|
bool mangleSubstitution(TemplateName Template);
|
|
|
|
bool mangleSubstitution(uintptr_t Ptr);
|
|
|
|
|
|
|
|
void mangleExistingSubstitution(TemplateName name);
|
|
|
|
|
|
|
|
bool mangleStandardSubstitution(const NamedDecl *ND);
|
|
|
|
|
|
|
|
void addSubstitution(const NamedDecl *ND) {
|
|
|
|
ND = cast<NamedDecl>(ND->getCanonicalDecl());
|
|
|
|
|
|
|
|
addSubstitution(reinterpret_cast<uintptr_t>(ND));
|
|
|
|
}
|
|
|
|
void addSubstitution(QualType T);
|
|
|
|
void addSubstitution(TemplateName Template);
|
|
|
|
void addSubstitution(uintptr_t Ptr);
|
2016-09-21 16:27:03 +08:00
|
|
|
// Destructive copy substitutions from other mangler.
|
|
|
|
void extendSubstitutions(CXXNameMangler* Other);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
|
|
|
|
bool recursive = false);
|
|
|
|
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
|
|
|
|
DeclarationName name,
|
2016-10-25 04:47:04 +08:00
|
|
|
const TemplateArgumentLoc *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned KnownArity = UnknownArity);
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
void mangleFunctionEncodingBareType(const FunctionDecl *FD);
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleNameWithAbiTags(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags);
|
2017-09-04 13:37:53 +08:00
|
|
|
void mangleModuleName(const Module *M);
|
|
|
|
void mangleModuleNamePrefix(StringRef Name);
|
2016-06-30 17:40:38 +08:00
|
|
|
void mangleTemplateName(const TemplateDecl *TD,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleUnqualifiedName(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName(), UnknownArity,
|
2016-06-30 17:40:38 +08:00
|
|
|
AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name,
|
2016-06-30 17:40:38 +08:00
|
|
|
unsigned KnownArity,
|
|
|
|
const AbiTagList *AdditionalAbiTags);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleUnscopedName(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleUnscopedTemplateName(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags);
|
|
|
|
void mangleUnscopedTemplateName(TemplateName,
|
|
|
|
const AbiTagList *AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleSourceName(const IdentifierInfo *II);
|
2016-11-03 02:29:35 +08:00
|
|
|
void mangleRegCallName(const IdentifierInfo *II);
|
2020-03-06 01:59:33 +08:00
|
|
|
void mangleDeviceStubName(const IdentifierInfo *II);
|
2016-06-30 17:40:38 +08:00
|
|
|
void mangleSourceNameWithAbiTags(
|
|
|
|
const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleLocalName(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags);
|
2013-07-03 01:52:28 +08:00
|
|
|
void mangleBlockForPrefix(const BlockDecl *Block);
|
|
|
|
void mangleUnqualifiedBlock(const BlockDecl *Block);
|
2019-05-04 18:49:46 +08:00
|
|
|
void mangleTemplateParamDecl(const NamedDecl *Decl);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleLambda(const CXXRecordDecl *Lambda);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleNestedName(GlobalDecl GD, const DeclContext *DC,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags,
|
2012-12-18 22:30:41 +08:00
|
|
|
bool NoFunction=false);
|
|
|
|
void mangleNestedName(const TemplateDecl *TD,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
|
|
|
void manglePrefix(NestedNameSpecifier *qualifier);
|
|
|
|
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
|
|
|
|
void manglePrefix(QualType type);
|
2020-03-06 01:02:13 +08:00
|
|
|
void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleTemplatePrefix(TemplateName Template);
|
2015-02-19 10:16:16 +08:00
|
|
|
bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
|
|
|
|
StringRef Prefix = "");
|
2015-02-18 10:28:01 +08:00
|
|
|
void mangleOperatorName(DeclarationName Name, unsigned Arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
|
2016-03-02 06:18:03 +08:00
|
|
|
void mangleVendorQualifier(StringRef qualifier);
|
2017-10-02 14:25:51 +08:00
|
|
|
void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleRefQualifier(RefQualifierKind RefQualifier);
|
|
|
|
|
|
|
|
void mangleObjCMethodName(const ObjCMethodDecl *MD);
|
|
|
|
|
|
|
|
// Declare manglers for every type class.
|
|
|
|
#define ABSTRACT_TYPE(CLASS, PARENT)
|
|
|
|
#define NON_CANONICAL_TYPE(CLASS, PARENT)
|
|
|
|
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
|
2019-10-02 14:35:23 +08:00
|
|
|
#include "clang/AST/TypeNodes.inc"
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
void mangleType(const TagType*);
|
|
|
|
void mangleType(TemplateName);
|
2016-03-02 06:18:03 +08:00
|
|
|
static StringRef getCallingConvQualifierName(CallingConv CC);
|
|
|
|
void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info);
|
|
|
|
void mangleExtFunctionInfo(const FunctionType *T);
|
|
|
|
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
|
2015-12-03 05:58:08 +08:00
|
|
|
const FunctionDecl *FD = nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleNeonVectorType(const VectorType *T);
|
2018-07-14 03:46:04 +08:00
|
|
|
void mangleNeonVectorType(const DependentVectorType *T);
|
2013-08-01 17:23:19 +08:00
|
|
|
void mangleAArch64NeonVectorType(const VectorType *T);
|
2018-07-14 03:46:04 +08:00
|
|
|
void mangleAArch64NeonVectorType(const DependentVectorType *T);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
|
2015-02-14 21:23:54 +08:00
|
|
|
void mangleMemberExprBase(const Expr *base, bool isArrow);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleMemberExpr(const Expr *base, bool isArrow,
|
|
|
|
NestedNameSpecifier *qualifier,
|
|
|
|
NamedDecl *firstQualifierLookup,
|
|
|
|
DeclarationName name,
|
2016-10-25 04:47:04 +08:00
|
|
|
const TemplateArgumentLoc *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned knownArity);
|
2014-09-23 12:27:55 +08:00
|
|
|
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
|
2015-02-05 14:15:50 +08:00
|
|
|
void mangleInitListElements(const InitListExpr *InitList);
|
2019-05-22 04:10:50 +08:00
|
|
|
void mangleDeclRefExpr(const NamedDecl *D);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleCXXDtorType(CXXDtorType T);
|
|
|
|
|
2015-12-24 10:59:37 +08:00
|
|
|
void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
2012-12-18 22:30:41 +08:00
|
|
|
void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs);
|
|
|
|
void mangleTemplateArgs(const TemplateArgumentList &AL);
|
|
|
|
void mangleTemplateArg(TemplateArgument A);
|
|
|
|
|
2019-09-05 09:23:47 +08:00
|
|
|
void mangleTemplateParameter(unsigned Depth, unsigned Index);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
void mangleFunctionParam(const ParmVarDecl *parm);
|
2016-06-30 17:40:38 +08:00
|
|
|
|
|
|
|
void writeAbiTags(const NamedDecl *ND,
|
|
|
|
const AbiTagList *AdditionalAbiTags);
|
|
|
|
|
|
|
|
// Returns sorted unique list of ABI tags.
|
|
|
|
AbiTagList makeFunctionReturnTypeTags(const FunctionDecl *FD);
|
|
|
|
// Returns sorted unique list of ABI tags.
|
|
|
|
AbiTagList makeVariableTypeTags(const VarDecl *VD);
|
2012-12-18 22:30:41 +08:00
|
|
|
};
|
|
|
|
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2013-10-16 09:40:34 +08:00
|
|
|
bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
|
2012-12-18 22:30:41 +08:00
|
|
|
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
2013-02-14 09:47:04 +08:00
|
|
|
if (FD) {
|
|
|
|
LanguageLinkage L = FD->getLanguageLinkage();
|
|
|
|
// Overloadable functions need mangling.
|
|
|
|
if (FD->hasAttr<OverloadableAttr>())
|
|
|
|
return true;
|
|
|
|
|
2013-02-14 23:38:59 +08:00
|
|
|
// "main" is not mangled.
|
|
|
|
if (FD->isMain())
|
2013-02-14 09:47:04 +08:00
|
|
|
return false;
|
|
|
|
|
2018-07-16 13:42:25 +08:00
|
|
|
// The Windows ABI expects that we would never mangle "typical"
|
|
|
|
// user-defined entry points regardless of visibility or freestanding-ness.
|
|
|
|
//
|
|
|
|
// N.B. This is distinct from asking about "main". "main" has a lot of
|
|
|
|
// special rules associated with it in the standard while these
|
|
|
|
// user-defined entry points are outside of the purview of the standard.
|
|
|
|
// For example, there can be only one definition for "main" in a standards
|
|
|
|
// compliant program; however nothing forbids the existence of wmain and
|
|
|
|
// WinMain in the same translation unit.
|
|
|
|
if (FD->isMSVCRTEntryPoint())
|
|
|
|
return false;
|
|
|
|
|
2013-02-14 09:47:04 +08:00
|
|
|
// C++ functions and those whose names are not a simple identifier need
|
|
|
|
// mangling.
|
|
|
|
if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage)
|
|
|
|
return true;
|
2013-02-14 11:31:26 +08:00
|
|
|
|
2013-02-14 23:38:59 +08:00
|
|
|
// C functions are not mangled.
|
|
|
|
if (L == CLanguageLinkage)
|
2013-02-14 11:31:26 +08:00
|
|
|
return false;
|
2013-02-14 09:47:04 +08:00
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
// Otherwise, no mangling is done outside C++ mode.
|
|
|
|
if (!getASTContext().getLangOpts().CPlusPlus)
|
|
|
|
return false;
|
|
|
|
|
2013-02-14 09:47:04 +08:00
|
|
|
const VarDecl *VD = dyn_cast<VarDecl>(D);
|
2016-07-23 07:36:59 +08:00
|
|
|
if (VD && !isa<DecompositionDecl>(D)) {
|
2013-02-14 09:47:04 +08:00
|
|
|
// C variables are not mangled.
|
|
|
|
if (VD->isExternC())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Variables at global scope with non-internal linkage are not mangled
|
2012-12-18 22:30:41 +08:00
|
|
|
const DeclContext *DC = getEffectiveDeclContext(D);
|
|
|
|
// Check for extern variable declared locally.
|
|
|
|
if (DC->isFunctionOrMethod() && D->hasLinkage())
|
|
|
|
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
|
|
|
DC = getEffectiveParentContext(DC);
|
2013-08-06 09:03:05 +08:00
|
|
|
if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage &&
|
2016-06-30 17:40:38 +08:00
|
|
|
!CXXNameMangler::shouldHaveAbiTags(*this, VD) &&
|
2013-08-06 09:03:05 +08:00
|
|
|
!isa<VarTemplateSpecializationDecl>(D))
|
2012-12-18 22:30:41 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
void CXXNameMangler::writeAbiTags(const NamedDecl *ND,
|
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
|
|
|
assert(AbiTags && "require AbiTagState");
|
|
|
|
AbiTags->write(Out, ND, DisableDerivedAbiTags ? nullptr : AdditionalAbiTags);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleSourceNameWithAbiTags(
|
|
|
|
const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) {
|
|
|
|
mangleSourceName(ND->getIdentifier());
|
|
|
|
writeAbiTags(ND, AdditionalAbiTags);
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangle(GlobalDecl GD) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <mangled-name> ::= _Z <encoding>
|
|
|
|
// ::= <data name>
|
|
|
|
// ::= <special-name>
|
2015-02-18 15:47:09 +08:00
|
|
|
Out << "_Z";
|
2020-03-09 00:59:21 +08:00
|
|
|
if (isa<FunctionDecl>(GD.getDecl()))
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleFunctionEncoding(GD);
|
|
|
|
else if (const VarDecl *VD = dyn_cast<VarDecl>(GD.getDecl()))
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleName(VD);
|
2020-03-06 01:02:13 +08:00
|
|
|
else if (const IndirectFieldDecl *IFD =
|
|
|
|
dyn_cast<IndirectFieldDecl>(GD.getDecl()))
|
2013-10-24 04:52:43 +08:00
|
|
|
mangleName(IFD->getAnonField());
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 13:15:29 +08:00
|
|
|
else if (const FieldDecl *FD = dyn_cast<FieldDecl>(GD.getDecl()))
|
|
|
|
mangleName(FD);
|
|
|
|
else if (const MSGuidDecl *GuidD = dyn_cast<MSGuidDecl>(GD.getDecl()))
|
|
|
|
mangleName(GuidD);
|
2012-12-18 22:30:41 +08:00
|
|
|
else
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 13:15:29 +08:00
|
|
|
llvm_unreachable("unexpected kind of global decl");
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleFunctionEncoding(GlobalDecl GD) {
|
|
|
|
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
// <encoding> ::= <function name> <bare-function-type>
|
|
|
|
|
|
|
|
// Don't mangle in the type if this isn't a decl we should typically mangle.
|
2016-06-30 17:40:38 +08:00
|
|
|
if (!Context.shouldMangleDeclName(FD)) {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleName(GD);
|
2016-06-30 17:40:38 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
AbiTagList ReturnTypeAbiTags = makeFunctionReturnTypeTags(FD);
|
|
|
|
if (ReturnTypeAbiTags.empty()) {
|
|
|
|
// There are no tags for return type, the simplest case.
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleName(GD);
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleFunctionEncodingBareType(FD);
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
2016-06-30 17:40:38 +08:00
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
// Mangle function name and encoding to temporary buffer.
|
|
|
|
// We have to output name and encoding to the same mangler to get the same
|
|
|
|
// substitution as it will be in final mangling.
|
|
|
|
SmallString<256> FunctionEncodingBuf;
|
|
|
|
llvm::raw_svector_ostream FunctionEncodingStream(FunctionEncodingBuf);
|
|
|
|
CXXNameMangler FunctionEncodingMangler(*this, FunctionEncodingStream);
|
|
|
|
// Output name of the function.
|
|
|
|
FunctionEncodingMangler.disableDerivedAbiTags();
|
|
|
|
FunctionEncodingMangler.mangleNameWithAbiTags(FD, nullptr);
|
|
|
|
|
|
|
|
// Remember length of the function name in the buffer.
|
|
|
|
size_t EncodingPositionStart = FunctionEncodingStream.str().size();
|
|
|
|
FunctionEncodingMangler.mangleFunctionEncodingBareType(FD);
|
|
|
|
|
|
|
|
// Get tags from return type that are not present in function name or
|
|
|
|
// encoding.
|
|
|
|
const AbiTagList &UsedAbiTags =
|
|
|
|
FunctionEncodingMangler.AbiTagsRoot.getSortedUniqueUsedAbiTags();
|
|
|
|
AbiTagList AdditionalAbiTags(ReturnTypeAbiTags.size());
|
|
|
|
AdditionalAbiTags.erase(
|
|
|
|
std::set_difference(ReturnTypeAbiTags.begin(), ReturnTypeAbiTags.end(),
|
|
|
|
UsedAbiTags.begin(), UsedAbiTags.end(),
|
|
|
|
AdditionalAbiTags.begin()),
|
|
|
|
AdditionalAbiTags.end());
|
|
|
|
|
|
|
|
// Output name with implicit tags and function encoding from temporary buffer.
|
|
|
|
mangleNameWithAbiTags(FD, &AdditionalAbiTags);
|
|
|
|
Out << FunctionEncodingStream.str().substr(EncodingPositionStart);
|
2016-09-21 16:27:03 +08:00
|
|
|
|
|
|
|
// Function encoding could create new substitutions so we have to add
|
|
|
|
// temp mangled substitutions to main mangler.
|
|
|
|
extendSubstitutions(&FunctionEncodingMangler);
|
2016-06-30 17:40:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
|
2014-04-26 08:14:00 +08:00
|
|
|
if (FD->hasAttr<EnableIfAttr>()) {
|
|
|
|
FunctionTypeDepthState Saved = FunctionTypeDepth.push();
|
|
|
|
Out << "Ua9enable_ifI";
|
2018-08-03 09:21:16 +08:00
|
|
|
for (AttrVec::const_iterator I = FD->getAttrs().begin(),
|
|
|
|
E = FD->getAttrs().end();
|
2014-04-26 08:14:00 +08:00
|
|
|
I != E; ++I) {
|
|
|
|
EnableIfAttr *EIA = dyn_cast<EnableIfAttr>(*I);
|
|
|
|
if (!EIA)
|
|
|
|
continue;
|
|
|
|
Out << 'X';
|
|
|
|
mangleExpression(EIA->getCond());
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
Out << 'E';
|
|
|
|
FunctionTypeDepth.pop(Saved);
|
|
|
|
}
|
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
// When mangling an inheriting constructor, the bare function type used is
|
|
|
|
// that of the inherited constructor.
|
|
|
|
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
|
|
|
|
if (auto Inherited = CD->getInheritedConstructor())
|
|
|
|
FD = Inherited.getConstructor();
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Whether the mangling of a function type includes the return type depends on
|
|
|
|
// the context and the nature of the function. The rules for deciding whether
|
|
|
|
// the return type is included are:
|
|
|
|
//
|
|
|
|
// 1. Template functions (names or types) have return types encoded, with
|
|
|
|
// the exceptions listed below.
|
|
|
|
// 2. Function types not appearing as part of a function name mangling,
|
|
|
|
// e.g. parameters, pointer types, etc., have return type encoded, with the
|
|
|
|
// exceptions listed below.
|
|
|
|
// 3. Non-template function names do not have return types encoded.
|
|
|
|
//
|
|
|
|
// The exceptions mentioned in (1) and (2) above, for which the return type is
|
|
|
|
// never included, are
|
|
|
|
// 1. Constructors.
|
|
|
|
// 2. Destructors.
|
|
|
|
// 3. Conversion operator functions, e.g. operator int.
|
|
|
|
bool MangleReturnType = false;
|
|
|
|
if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) {
|
|
|
|
if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
|
|
|
|
isa<CXXConversionDecl>(FD)))
|
|
|
|
MangleReturnType = true;
|
|
|
|
|
|
|
|
// Mangle the type of the primary template.
|
|
|
|
FD = PrimaryTemplate->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
|
2016-03-02 06:18:03 +08:00
|
|
|
mangleBareFunctionType(FD->getType()->castAs<FunctionProtoType>(),
|
2015-12-03 05:58:08 +08:00
|
|
|
MangleReturnType, FD);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
|
|
|
|
while (isa<LinkageSpecDecl>(DC)) {
|
|
|
|
DC = getEffectiveParentContext(DC);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DC;
|
|
|
|
}
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Return whether a given namespace is the 'std' namespace.
|
2012-12-18 22:30:41 +08:00
|
|
|
static bool isStd(const NamespaceDecl *NS) {
|
|
|
|
if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
|
|
|
|
->isTranslationUnit())
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
|
|
|
|
return II && II->isStr("std");
|
|
|
|
}
|
|
|
|
|
|
|
|
// isStdNamespace - Return whether a given decl context is a toplevel 'std'
|
|
|
|
// namespace.
|
|
|
|
static bool isStdNamespace(const DeclContext *DC) {
|
|
|
|
if (!DC->isNamespace())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return isStd(cast<NamespaceDecl>(DC));
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
static const GlobalDecl
|
|
|
|
isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) {
|
|
|
|
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
// Check if we have a function template.
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
|
|
|
|
TemplateArgs = FD->getTemplateSpecializationArgs();
|
2020-03-06 01:02:13 +08:00
|
|
|
return GD.getWithDecl(TD);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we have a class template.
|
|
|
|
if (const ClassTemplateSpecializationDecl *Spec =
|
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
|
|
|
TemplateArgs = &Spec->getTemplateArgs();
|
2020-03-06 01:02:13 +08:00
|
|
|
return GD.getWithDecl(Spec->getSpecializedTemplate());
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2013-08-06 09:03:05 +08:00
|
|
|
// Check if we have a variable template.
|
|
|
|
if (const VarTemplateSpecializationDecl *Spec =
|
|
|
|
dyn_cast<VarTemplateSpecializationDecl>(ND)) {
|
|
|
|
TemplateArgs = &Spec->getTemplateArgs();
|
2020-03-06 01:02:13 +08:00
|
|
|
return GD.getWithDecl(Spec->getSpecializedTemplate());
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
return GlobalDecl();
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleName(GlobalDecl GD) {
|
|
|
|
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
2016-06-30 17:40:38 +08:00
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
|
|
|
|
// Variables should have implicit tags from its type.
|
|
|
|
AbiTagList VariableTypeAbiTags = makeVariableTypeTags(VD);
|
|
|
|
if (VariableTypeAbiTags.empty()) {
|
|
|
|
// Simple case no variable type tags.
|
|
|
|
mangleNameWithAbiTags(VD, nullptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mangle variable name to null stream to collect tags.
|
|
|
|
llvm::raw_null_ostream NullOutStream;
|
|
|
|
CXXNameMangler VariableNameMangler(*this, NullOutStream);
|
|
|
|
VariableNameMangler.disableDerivedAbiTags();
|
|
|
|
VariableNameMangler.mangleNameWithAbiTags(VD, nullptr);
|
|
|
|
|
|
|
|
// Get tags from variable type that are not present in its name.
|
|
|
|
const AbiTagList &UsedAbiTags =
|
|
|
|
VariableNameMangler.AbiTagsRoot.getSortedUniqueUsedAbiTags();
|
|
|
|
AbiTagList AdditionalAbiTags(VariableTypeAbiTags.size());
|
|
|
|
AdditionalAbiTags.erase(
|
|
|
|
std::set_difference(VariableTypeAbiTags.begin(),
|
|
|
|
VariableTypeAbiTags.end(), UsedAbiTags.begin(),
|
|
|
|
UsedAbiTags.end(), AdditionalAbiTags.begin()),
|
|
|
|
AdditionalAbiTags.end());
|
|
|
|
|
|
|
|
// Output name with implicit tags.
|
|
|
|
mangleNameWithAbiTags(VD, &AdditionalAbiTags);
|
|
|
|
} else {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleNameWithAbiTags(GD, nullptr);
|
2016-06-30 17:40:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
2017-09-04 13:37:53 +08:00
|
|
|
// <name> ::= [<module-name>] <nested-name>
|
|
|
|
// ::= [<module-name>] <unscoped-name>
|
|
|
|
// ::= [<module-name>] <unscoped-template-name> <template-args>
|
2012-12-18 22:30:41 +08:00
|
|
|
// ::= <local-name>
|
|
|
|
//
|
|
|
|
const DeclContext *DC = getEffectiveDeclContext(ND);
|
|
|
|
|
|
|
|
// If this is an extern variable declared locally, the relevant DeclContext
|
|
|
|
// is that of the containing namespace, or the translation unit.
|
|
|
|
// FIXME: This is a hack; extern variables declared locally should have
|
|
|
|
// a proper semantic declaration context!
|
2013-07-03 01:52:28 +08:00
|
|
|
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
|
2012-12-18 22:30:41 +08:00
|
|
|
while (!DC->isNamespace() && !DC->isTranslationUnit())
|
|
|
|
DC = getEffectiveParentContext(DC);
|
|
|
|
else if (GetLocalClassDecl(ND)) {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleLocalName(GD, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DC = IgnoreLinkageSpecDecls(DC);
|
|
|
|
|
2017-09-04 13:37:53 +08:00
|
|
|
if (isLocalContainerContext(DC)) {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleLocalName(GD, AdditionalAbiTags);
|
2017-09-04 13:37:53 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do not mangle the owning module for an external linkage declaration.
|
|
|
|
// This enables backwards-compatibility with non-modular code, and is
|
|
|
|
// a valid choice since conflicts are not permitted by C++ Modules TS
|
|
|
|
// [basic.def.odr]/6.2.
|
|
|
|
if (!ND->hasExternalFormalLinkage())
|
|
|
|
if (Module *M = ND->getOwningModuleForLinkage())
|
|
|
|
mangleModuleName(M);
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
|
|
|
// Check if we have a template.
|
2014-05-12 13:36:57 +08:00
|
|
|
const TemplateArgumentList *TemplateArgs = nullptr;
|
2020-03-06 01:02:13 +08:00
|
|
|
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleUnscopedTemplateName(TD, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnscopedName(GD, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleNestedName(GD, DC, AdditionalAbiTags);
|
2017-09-04 13:37:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleModuleName(const Module *M) {
|
|
|
|
// Implement the C++ Modules TS name mangling proposal; see
|
|
|
|
// https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile
|
|
|
|
//
|
|
|
|
// <module-name> ::= W <unscoped-name>+ E
|
|
|
|
// ::= W <module-subst> <unscoped-name>* E
|
|
|
|
Out << 'W';
|
|
|
|
mangleModuleNamePrefix(M->Name);
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
|
|
|
|
// <module-subst> ::= _ <seq-id> # 0 < seq-id < 10
|
|
|
|
// ::= W <seq-id - 10> _ # otherwise
|
|
|
|
auto It = ModuleSubstitutions.find(Name);
|
|
|
|
if (It != ModuleSubstitutions.end()) {
|
|
|
|
if (It->second < 10)
|
|
|
|
Out << '_' << static_cast<char>('0' + It->second);
|
|
|
|
else
|
|
|
|
Out << 'W' << (It->second - 10) << '_';
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-04 13:37:53 +08:00
|
|
|
// FIXME: Preserve hierarchy in module names rather than flattening
|
|
|
|
// them to strings; use Module*s as substitution keys.
|
|
|
|
auto Parts = Name.rsplit('.');
|
|
|
|
if (Parts.second.empty())
|
|
|
|
Parts.second = Parts.first;
|
|
|
|
else
|
|
|
|
mangleModuleNamePrefix(Parts.first);
|
|
|
|
|
|
|
|
Out << Parts.second.size() << Parts.second;
|
|
|
|
ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()});
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
2016-06-30 17:40:38 +08:00
|
|
|
|
|
|
|
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
2012-12-18 22:30:41 +08:00
|
|
|
const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
|
|
|
|
|
|
|
|
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleUnscopedTemplateName(TD, nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
|
|
|
|
} else {
|
|
|
|
mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleUnscopedName(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
// <unscoped-name> ::= <unqualified-name>
|
|
|
|
// ::= St <unqualified-name> # ::std::
|
|
|
|
|
|
|
|
if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))
|
|
|
|
Out << "St";
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GD, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
void CXXNameMangler::mangleUnscopedTemplateName(
|
2020-03-06 01:02:13 +08:00
|
|
|
GlobalDecl GD, const AbiTagList *AdditionalAbiTags) {
|
|
|
|
const TemplateDecl *ND = cast<TemplateDecl>(GD.getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
// <unscoped-template-name> ::= <unscoped-name>
|
|
|
|
// ::= <substitution>
|
|
|
|
if (mangleSubstitution(ND))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// <template-template-param> ::= <template-param>
|
2016-06-30 17:40:38 +08:00
|
|
|
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
|
|
|
|
assert(!AdditionalAbiTags &&
|
|
|
|
"template template param cannot have abi tags");
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
2019-10-17 08:16:01 +08:00
|
|
|
} else if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND)) {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnscopedName(GD, AdditionalAbiTags);
|
2016-06-30 17:40:38 +08:00
|
|
|
} else {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), AdditionalAbiTags);
|
2016-06-30 17:40:38 +08:00
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
addSubstitution(ND);
|
|
|
|
}
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
void CXXNameMangler::mangleUnscopedTemplateName(
|
|
|
|
TemplateName Template, const AbiTagList *AdditionalAbiTags) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <unscoped-template-name> ::= <unscoped-name>
|
|
|
|
// ::= <substitution>
|
|
|
|
if (TemplateDecl *TD = Template.getAsTemplateDecl())
|
2016-06-30 17:40:38 +08:00
|
|
|
return mangleUnscopedTemplateName(TD, AdditionalAbiTags);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
if (mangleSubstitution(Template))
|
|
|
|
return;
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
assert(!AdditionalAbiTags &&
|
|
|
|
"dependent template name cannot have abi tags");
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
|
|
|
|
assert(Dependent && "Not a dependent template name?");
|
|
|
|
if (const IdentifierInfo *Id = Dependent->getIdentifier())
|
|
|
|
mangleSourceName(Id);
|
|
|
|
else
|
|
|
|
mangleOperatorName(Dependent->getOperator(), UnknownArity);
|
2016-06-30 17:40:38 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
addSubstitution(Template);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
|
|
|
|
// ABI:
|
|
|
|
// Floating-point literals are encoded using a fixed-length
|
|
|
|
// lowercase hexadecimal string corresponding to the internal
|
|
|
|
// representation (IEEE on Itanium), high-order bytes first,
|
|
|
|
// without leading zeroes. For example: "Lf bf800000 E" is -1.0f
|
|
|
|
// on Itanium.
|
|
|
|
// The 'without leading zeroes' thing seems to be an editorial
|
|
|
|
// mistake; see the discussion on cxx-abi-dev beginning on
|
|
|
|
// 2012-01-16.
|
|
|
|
|
|
|
|
// Our requirements here are just barely weird enough to justify
|
|
|
|
// using a custom algorithm instead of post-processing APInt::toString().
|
|
|
|
|
|
|
|
llvm::APInt valueBits = f.bitcastToAPInt();
|
|
|
|
unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4;
|
|
|
|
assert(numCharacters != 0);
|
|
|
|
|
|
|
|
// Allocate a buffer of the right number of characters.
|
2015-08-04 21:34:50 +08:00
|
|
|
SmallVector<char, 20> buffer(numCharacters);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
// Fill the buffer left-to-right.
|
|
|
|
for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) {
|
|
|
|
// The bit-index of the next hex digit.
|
|
|
|
unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1);
|
|
|
|
|
|
|
|
// Project out 4 bits starting at 'digitIndex'.
|
2017-03-30 13:48:58 +08:00
|
|
|
uint64_t hexDigit = valueBits.getRawData()[digitBitIndex / 64];
|
|
|
|
hexDigit >>= (digitBitIndex % 64);
|
2012-12-18 22:30:41 +08:00
|
|
|
hexDigit &= 0xF;
|
|
|
|
|
|
|
|
// Map that over to a lowercase hex digit.
|
|
|
|
static const char charForHex[16] = {
|
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
|
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
|
|
|
};
|
|
|
|
buffer[stringIndex] = charForHex[hexDigit];
|
|
|
|
}
|
|
|
|
|
|
|
|
Out.write(buffer.data(), numCharacters);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
|
|
|
|
if (Value.isSigned() && Value.isNegative()) {
|
|
|
|
Out << 'n';
|
|
|
|
Value.abs().print(Out, /*signed*/ false);
|
|
|
|
} else {
|
|
|
|
Value.print(Out, /*signed*/ false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleNumber(int64_t Number) {
|
|
|
|
// <number> ::= [n] <non-negative decimal integer>
|
|
|
|
if (Number < 0) {
|
|
|
|
Out << 'n';
|
|
|
|
Number = -Number;
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << Number;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
|
|
|
|
// <call-offset> ::= h <nv-offset> _
|
|
|
|
// ::= v <v-offset> _
|
|
|
|
// <nv-offset> ::= <offset number> # non-virtual base override
|
|
|
|
// <v-offset> ::= <offset number> _ <virtual offset number>
|
|
|
|
// # virtual base override, with vcall offset
|
|
|
|
if (!Virtual) {
|
|
|
|
Out << 'h';
|
|
|
|
mangleNumber(NonVirtual);
|
|
|
|
Out << '_';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << 'v';
|
|
|
|
mangleNumber(NonVirtual);
|
|
|
|
Out << '_';
|
|
|
|
mangleNumber(Virtual);
|
|
|
|
Out << '_';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::manglePrefix(QualType type) {
|
2015-02-18 10:28:01 +08:00
|
|
|
if (const auto *TST = type->getAs<TemplateSpecializationType>()) {
|
2012-12-18 22:30:41 +08:00
|
|
|
if (!mangleSubstitution(QualType(TST, 0))) {
|
|
|
|
mangleTemplatePrefix(TST->getTemplateName());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// FIXME: GCC does not appear to mangle the template arguments when
|
|
|
|
// the template in question is a dependent template name. Should we
|
|
|
|
// emulate that badness?
|
|
|
|
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
|
|
|
|
addSubstitution(QualType(TST, 0));
|
|
|
|
}
|
2015-02-18 10:28:01 +08:00
|
|
|
} else if (const auto *DTST =
|
|
|
|
type->getAs<DependentTemplateSpecializationType>()) {
|
|
|
|
if (!mangleSubstitution(QualType(DTST, 0))) {
|
|
|
|
TemplateName Template = getASTContext().getDependentTemplateName(
|
|
|
|
DTST->getQualifier(), DTST->getIdentifier());
|
|
|
|
mangleTemplatePrefix(Template);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2015-02-18 10:28:01 +08:00
|
|
|
// FIXME: GCC does not appear to mangle the template arguments when
|
|
|
|
// the template in question is a dependent template name. Should we
|
|
|
|
// emulate that badness?
|
|
|
|
mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
|
|
|
|
addSubstitution(QualType(DTST, 0));
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
} else {
|
|
|
|
// We use the QualType mangle type variant here because it handles
|
|
|
|
// substitutions.
|
|
|
|
mangleType(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
|
|
|
|
///
|
|
|
|
/// \param recursive - true if this is being called recursively,
|
|
|
|
/// i.e. if there is more prefix "to the right".
|
|
|
|
void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
|
|
|
|
bool recursive) {
|
|
|
|
|
|
|
|
// x, ::x
|
|
|
|
// <unresolved-name> ::= [gs] <base-unresolved-name>
|
|
|
|
|
|
|
|
// T::x / decltype(p)::x
|
|
|
|
// <unresolved-name> ::= sr <unresolved-type> <base-unresolved-name>
|
|
|
|
|
|
|
|
// T::N::x /decltype(p)::N::x
|
|
|
|
// <unresolved-name> ::= srN <unresolved-type> <unresolved-qualifier-level>+ E
|
|
|
|
// <base-unresolved-name>
|
|
|
|
|
|
|
|
// A::x, N::y, A<T>::z; "gs" means leading "::"
|
|
|
|
// <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E
|
|
|
|
// <base-unresolved-name>
|
|
|
|
|
|
|
|
switch (qualifier->getKind()) {
|
|
|
|
case NestedNameSpecifier::Global:
|
|
|
|
Out << "gs";
|
|
|
|
|
|
|
|
// We want an 'sr' unless this is the entire NNS.
|
|
|
|
if (recursive)
|
|
|
|
Out << "sr";
|
|
|
|
|
|
|
|
// We never want an 'E' here.
|
|
|
|
return;
|
|
|
|
|
2014-09-26 08:28:20 +08:00
|
|
|
case NestedNameSpecifier::Super:
|
|
|
|
llvm_unreachable("Can't mangle __super specifier");
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case NestedNameSpecifier::Namespace:
|
|
|
|
if (qualifier->getPrefix())
|
2015-02-19 10:16:16 +08:00
|
|
|
mangleUnresolvedPrefix(qualifier->getPrefix(),
|
2012-12-18 22:30:41 +08:00
|
|
|
/*recursive*/ true);
|
|
|
|
else
|
|
|
|
Out << "sr";
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(qualifier->getAsNamespace());
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
case NestedNameSpecifier::NamespaceAlias:
|
|
|
|
if (qualifier->getPrefix())
|
2015-02-19 10:16:16 +08:00
|
|
|
mangleUnresolvedPrefix(qualifier->getPrefix(),
|
2012-12-18 22:30:41 +08:00
|
|
|
/*recursive*/ true);
|
|
|
|
else
|
|
|
|
Out << "sr";
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias());
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NestedNameSpecifier::TypeSpec:
|
|
|
|
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
|
|
|
const Type *type = qualifier->getAsType();
|
|
|
|
|
|
|
|
// We only want to use an unresolved-type encoding if this is one of:
|
|
|
|
// - a decltype
|
|
|
|
// - a template type parameter
|
|
|
|
// - a template template parameter with arguments
|
|
|
|
// In all of these cases, we should have no prefix.
|
|
|
|
if (qualifier->getPrefix()) {
|
2015-02-19 10:16:16 +08:00
|
|
|
mangleUnresolvedPrefix(qualifier->getPrefix(),
|
2012-12-18 22:30:41 +08:00
|
|
|
/*recursive*/ true);
|
|
|
|
} else {
|
|
|
|
// Otherwise, all the cases want this.
|
|
|
|
Out << "sr";
|
|
|
|
}
|
|
|
|
|
2015-02-19 10:16:16 +08:00
|
|
|
if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : ""))
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case NestedNameSpecifier::Identifier:
|
|
|
|
// Member expressions can have these without prefixes.
|
2015-02-19 10:16:16 +08:00
|
|
|
if (qualifier->getPrefix())
|
|
|
|
mangleUnresolvedPrefix(qualifier->getPrefix(),
|
2012-12-18 22:30:41 +08:00
|
|
|
/*recursive*/ true);
|
2015-02-19 10:16:16 +08:00
|
|
|
else
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << "sr";
|
|
|
|
|
|
|
|
mangleSourceName(qualifier->getAsIdentifier());
|
2016-06-30 17:40:38 +08:00
|
|
|
// An Identifier has no type information, so we can't emit abi tags for it.
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this was the innermost part of the NNS, and we fell out to
|
|
|
|
// here, append an 'E'.
|
|
|
|
if (!recursive)
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mangle an unresolved-name, which is generally used for names which
|
|
|
|
/// weren't resolved to specific entities.
|
2016-10-25 04:47:04 +08:00
|
|
|
void CXXNameMangler::mangleUnresolvedName(
|
|
|
|
NestedNameSpecifier *qualifier, DeclarationName name,
|
|
|
|
const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
|
|
|
|
unsigned knownArity) {
|
2015-02-19 10:16:16 +08:00
|
|
|
if (qualifier) mangleUnresolvedPrefix(qualifier);
|
2015-02-14 21:23:54 +08:00
|
|
|
switch (name.getNameKind()) {
|
|
|
|
// <base-unresolved-name> ::= <simple-id>
|
|
|
|
case DeclarationName::Identifier:
|
2015-02-18 10:28:01 +08:00
|
|
|
mangleSourceName(name.getAsIdentifierInfo());
|
|
|
|
break;
|
|
|
|
// <base-unresolved-name> ::= dn <destructor-name>
|
|
|
|
case DeclarationName::CXXDestructorName:
|
|
|
|
Out << "dn";
|
2015-02-19 10:16:16 +08:00
|
|
|
mangleUnresolvedTypeOrSimpleId(name.getCXXNameType());
|
2015-02-14 21:23:54 +08:00
|
|
|
break;
|
|
|
|
// <base-unresolved-name> ::= on <operator-name>
|
|
|
|
case DeclarationName::CXXConversionFunctionName:
|
|
|
|
case DeclarationName::CXXLiteralOperatorName:
|
|
|
|
case DeclarationName::CXXOperatorName:
|
|
|
|
Out << "on";
|
2015-02-18 10:28:01 +08:00
|
|
|
mangleOperatorName(name, knownArity);
|
2015-02-14 21:23:54 +08:00
|
|
|
break;
|
|
|
|
case DeclarationName::CXXConstructorName:
|
|
|
|
llvm_unreachable("Can't mangle a constructor name!");
|
|
|
|
case DeclarationName::CXXUsingDirective:
|
|
|
|
llvm_unreachable("Can't mangle a using directive name!");
|
2017-02-07 09:37:30 +08:00
|
|
|
case DeclarationName::CXXDeductionGuideName:
|
|
|
|
llvm_unreachable("Can't mangle a deduction guide name!");
|
2015-02-14 21:23:54 +08:00
|
|
|
case DeclarationName::ObjCMultiArgSelector:
|
|
|
|
case DeclarationName::ObjCOneArgSelector:
|
|
|
|
case DeclarationName::ObjCZeroArgSelector:
|
|
|
|
llvm_unreachable("Can't mangle Objective-C selector names here!");
|
|
|
|
}
|
2016-10-25 04:47:04 +08:00
|
|
|
|
|
|
|
// The <simple-id> and on <operator-name> productions end in an optional
|
|
|
|
// <template-args>.
|
|
|
|
if (TemplateArgs)
|
|
|
|
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
|
2012-12-18 22:30:41 +08:00
|
|
|
DeclarationName Name,
|
2016-06-30 17:40:38 +08:00
|
|
|
unsigned KnownArity,
|
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const NamedDecl *ND = cast_or_null<NamedDecl>(GD.getDecl());
|
2015-02-18 10:28:01 +08:00
|
|
|
unsigned Arity = KnownArity;
|
2012-12-18 22:30:41 +08:00
|
|
|
// <unqualified-name> ::= <operator-name>
|
|
|
|
// ::= <ctor-dtor-name>
|
|
|
|
// ::= <source-name>
|
|
|
|
switch (Name.getNameKind()) {
|
|
|
|
case DeclarationName::Identifier: {
|
2016-07-23 07:36:59 +08:00
|
|
|
const IdentifierInfo *II = Name.getAsIdentifierInfo();
|
|
|
|
|
2016-08-15 09:33:41 +08:00
|
|
|
// We mangle decomposition declarations as the names of their bindings.
|
2016-07-23 07:36:59 +08:00
|
|
|
if (auto *DD = dyn_cast<DecompositionDecl>(ND)) {
|
2016-08-15 09:33:41 +08:00
|
|
|
// FIXME: Non-standard mangling for decomposition declarations:
|
|
|
|
//
|
|
|
|
// <unqualified-name> ::= DC <source-name>* E
|
|
|
|
//
|
|
|
|
// These can never be referenced across translation units, so we do
|
|
|
|
// not need a cross-vendor mangling for anything other than demanglers.
|
|
|
|
// Proposed on cxx-abi-dev on 2016-08-12
|
|
|
|
Out << "DC";
|
|
|
|
for (auto *BD : DD->bindings())
|
|
|
|
mangleSourceName(BD->getDeclName().getAsIdentifierInfo());
|
|
|
|
Out << 'E';
|
|
|
|
writeAbiTags(ND, AdditionalAbiTags);
|
|
|
|
break;
|
2016-07-23 07:36:59 +08:00
|
|
|
}
|
|
|
|
|
Rework how UuidAttr, CXXUuidofExpr, and GUID template arguments and constants are represented.
Summary:
Previously, we treated CXXUuidofExpr as quite a special case: it was the
only kind of expression that could be a canonical template argument, it
could be a constant lvalue base object, and so on. In addition, we
represented the UUID value as a string, whose source form we did not
preserve faithfully, and that we partially parsed in multiple different
places.
With this patch, we create an MSGuidDecl object to represent the
implicit object of type 'struct _GUID' created by a UuidAttr. Each
UuidAttr holds a pointer to its 'struct _GUID' and its original
(as-written) UUID string. A non-value-dependent CXXUuidofExpr behaves
like a DeclRefExpr denoting that MSGuidDecl object. We cache an APValue
representation of the GUID on the MSGuidDecl and use it from constant
evaluation where needed.
This allows removing a lot of the special-case logic to handle these
expressions. Unfortunately, many parts of Clang assume there are only
a couple of interesting kinds of ValueDecl, so the total amount of
special-case logic is not really reduced very much.
This fixes a few bugs and issues:
* PR38490: we now support reading from GUID objects returned from
__uuidof during constant evaluation.
* Our Itanium mangling for a non-instantiation-dependent template
argument involving __uuidof no longer depends on which CXXUuidofExpr
template argument we happened to see first.
* We now predeclare ::_GUID, and permit use of __uuidof without
any header inclusion, better matching MSVC's behavior. We do not
predefine ::__s_GUID, though; that seems like a step too far.
* Our IR representation for GUID constants now uses the correct IR type
wherever possible. We will still fall back to using the
{i32, i16, i16, [8 x i8]}
layout if a definition of struct _GUID is not available. This is not
ideal: in principle the two layouts could have different padding.
Reviewers: rnk, jdoerfert
Subscribers: arphaman, cfe-commits, aeubanks
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78171
2020-04-12 13:15:29 +08:00
|
|
|
if (auto *GD = dyn_cast<MSGuidDecl>(ND)) {
|
|
|
|
// We follow MSVC in mangling GUID declarations as if they were variables
|
|
|
|
// with a particular reserved name. Continue the pretense here.
|
|
|
|
SmallString<sizeof("_GUID_12345678_1234_1234_1234_1234567890ab")> GUID;
|
|
|
|
llvm::raw_svector_ostream GUIDOS(GUID);
|
|
|
|
Context.mangleMSGuidDecl(GD, GUIDOS);
|
|
|
|
Out << GUID.size() << GUID;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-07-23 07:36:59 +08:00
|
|
|
if (II) {
|
2017-09-04 13:37:53 +08:00
|
|
|
// Match GCC's naming convention for internal linkage symbols, for
|
|
|
|
// symbols that are not actually visible outside of this TU. GCC
|
|
|
|
// distinguishes between internal and external linkage symbols in
|
|
|
|
// its mangling, to support cases like this that were valid C++ prior
|
|
|
|
// to DR426:
|
|
|
|
//
|
2012-12-18 22:30:41 +08:00
|
|
|
// void test() { extern void foo(); }
|
|
|
|
// static void foo();
|
2017-09-23 06:21:44 +08:00
|
|
|
//
|
|
|
|
// Don't bother with the L marker for names in anonymous namespaces; the
|
|
|
|
// 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
|
|
|
|
// matches GCC anyway, because GCC does not treat anonymous namespaces as
|
|
|
|
// implying internal linkage.
|
2013-05-13 08:12:11 +08:00
|
|
|
if (ND && ND->getFormalLinkage() == InternalLinkage &&
|
2017-09-04 13:37:53 +08:00
|
|
|
!ND->isExternallyVisible() &&
|
2017-09-23 06:21:44 +08:00
|
|
|
getEffectiveDeclContext(ND)->isFileContext() &&
|
|
|
|
!ND->isInAnonymousNamespace())
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'L';
|
|
|
|
|
2016-11-03 02:29:35 +08:00
|
|
|
auto *FD = dyn_cast<FunctionDecl>(ND);
|
|
|
|
bool IsRegCall = FD &&
|
|
|
|
FD->getType()->castAs<FunctionType>()->getCallConv() ==
|
|
|
|
clang::CC_X86RegCall;
|
2020-03-06 01:59:33 +08:00
|
|
|
bool IsDeviceStub =
|
|
|
|
FD && FD->hasAttr<CUDAGlobalAttr>() &&
|
|
|
|
GD.getKernelReferenceKind() == KernelReferenceKind::Stub;
|
|
|
|
if (IsDeviceStub)
|
|
|
|
mangleDeviceStubName(II);
|
|
|
|
else if (IsRegCall)
|
2016-11-03 02:29:35 +08:00
|
|
|
mangleRegCallName(II);
|
|
|
|
else
|
|
|
|
mangleSourceName(II);
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
writeAbiTags(ND, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, an anonymous entity. We must have a declaration.
|
|
|
|
assert(ND && "mangling empty name without declaration");
|
|
|
|
|
|
|
|
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
|
|
|
if (NS->isAnonymousNamespace()) {
|
|
|
|
// This is how gcc mangles these names.
|
|
|
|
Out << "12_GLOBAL__N_1";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
|
|
|
|
// We must have an anonymous union or struct declaration.
|
2019-10-03 19:22:48 +08:00
|
|
|
const RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();
|
2014-12-13 00:17:46 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Itanium C++ ABI 5.1.2:
|
|
|
|
//
|
|
|
|
// For the purposes of mangling, the name of an anonymous union is
|
|
|
|
// considered to be the name of the first named data member found by a
|
|
|
|
// pre-order, depth-first, declaration-order walk of the data members of
|
|
|
|
// the anonymous union. If there is no such data member (i.e., if all of
|
|
|
|
// the data members in the union are unnamed), then there is no way for
|
|
|
|
// a program to refer to the anonymous union, and there is therefore no
|
|
|
|
// need to mangle its name.
|
2014-12-13 00:17:46 +08:00
|
|
|
assert(RD->isAnonymousStructOrUnion()
|
|
|
|
&& "Expected anonymous struct or union!");
|
|
|
|
const FieldDecl *FD = RD->findFirstNamedDataMember();
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
// It's actually possible for various reasons for us to get here
|
|
|
|
// with an empty anonymous struct / union. Fortunately, it
|
|
|
|
// doesn't really matter what name we generate.
|
|
|
|
if (!FD) break;
|
|
|
|
assert(FD->getIdentifier() && "Data member name isn't an identifier!");
|
2014-12-13 00:17:46 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleSourceName(FD->getIdentifier());
|
2016-06-30 17:40:38 +08:00
|
|
|
// Not emitting abi tags: internal name anyway.
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-04-10 14:08:21 +08:00
|
|
|
|
|
|
|
// Class extensions have no name as a category, and it's possible
|
|
|
|
// for them to be the semantic parent of certain declarations
|
|
|
|
// (primarily, tag decls defined within declarations). Such
|
|
|
|
// declarations will always have internal linkage, so the name
|
|
|
|
// doesn't really matter, but we shouldn't crash on them. For
|
|
|
|
// safety, just handle all ObjC containers here.
|
|
|
|
if (isa<ObjCContainerDecl>(ND))
|
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// We must have an anonymous struct.
|
|
|
|
const TagDecl *TD = cast<TagDecl>(ND);
|
|
|
|
if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
|
|
|
|
assert(TD->getDeclContext() == D->getDeclContext() &&
|
|
|
|
"Typedef should not be in another decl context!");
|
|
|
|
assert(D->getDeclName().getAsIdentifierInfo() &&
|
|
|
|
"Typedef was not named!");
|
|
|
|
mangleSourceName(D->getDeclName().getAsIdentifierInfo());
|
2016-06-30 17:40:38 +08:00
|
|
|
assert(!AdditionalAbiTags && "Type cannot have additional abi tags");
|
|
|
|
// Explicit abi tags are still possible; take from underlying type, not
|
|
|
|
// from typedef.
|
|
|
|
writeAbiTags(TD, nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <unnamed-type-name> ::= <closure-type-name>
|
2018-07-31 03:24:48 +08:00
|
|
|
//
|
2012-12-18 22:30:41 +08:00
|
|
|
// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
|
2019-05-04 18:49:46 +08:00
|
|
|
// <lambda-sig> ::= <template-param-decl>* <parameter-type>+
|
|
|
|
// # Parameter types or 'v' for 'void'.
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
|
|
|
|
Context.isUniqueNameMangler())) {
|
2016-06-30 17:40:38 +08:00
|
|
|
assert(!AdditionalAbiTags &&
|
|
|
|
"Lambda type cannot have additional abi tags");
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleLambda(Record);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-10 08:30:46 +08:00
|
|
|
if (TD->isExternallyVisible()) {
|
|
|
|
unsigned UnnamedMangle = getASTContext().getManglingNumber(TD);
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << "Ut";
|
2013-07-10 08:30:46 +08:00
|
|
|
if (UnnamedMangle > 1)
|
2015-12-24 18:07:37 +08:00
|
|
|
Out << UnnamedMangle - 2;
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << '_';
|
2016-06-30 17:40:38 +08:00
|
|
|
writeAbiTags(TD, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
// Get a unique id for the anonymous struct. If it is not a real output
|
|
|
|
// ID doesn't matter so use fake one.
|
|
|
|
unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
// Mangle it as a source name in the form
|
|
|
|
// [n] $_<id>
|
|
|
|
// where n is the length of the string.
|
|
|
|
SmallString<8> Str;
|
|
|
|
Str += "$_";
|
|
|
|
Str += llvm::utostr(AnonStructId);
|
|
|
|
|
|
|
|
Out << Str.size();
|
2015-03-10 15:33:23 +08:00
|
|
|
Out << Str;
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case DeclarationName::ObjCZeroArgSelector:
|
|
|
|
case DeclarationName::ObjCOneArgSelector:
|
|
|
|
case DeclarationName::ObjCMultiArgSelector:
|
|
|
|
llvm_unreachable("Can't mangle Objective-C selector names here!");
|
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
case DeclarationName::CXXConstructorName: {
|
|
|
|
const CXXRecordDecl *InheritedFrom = nullptr;
|
|
|
|
const TemplateArgumentList *InheritedTemplateArgs = nullptr;
|
|
|
|
if (auto Inherited =
|
|
|
|
cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) {
|
|
|
|
InheritedFrom = Inherited.getConstructor()->getParent();
|
|
|
|
InheritedTemplateArgs =
|
|
|
|
Inherited.getConstructor()->getTemplateSpecializationArgs();
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
if (ND == Structor)
|
|
|
|
// If the named decl is the C++ constructor we're mangling, use the type
|
|
|
|
// we were given.
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
mangleCXXCtorType(static_cast<CXXCtorType>(StructorType), InheritedFrom);
|
2012-12-18 22:30:41 +08:00
|
|
|
else
|
|
|
|
// Otherwise, use the complete constructor name. This is relevant if a
|
|
|
|
// class with a constructor is declared within a constructor.
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
mangleCXXCtorType(Ctor_Complete, InheritedFrom);
|
|
|
|
|
|
|
|
// FIXME: The template arguments are part of the enclosing prefix or
|
|
|
|
// nested-name, but it's more convenient to mangle them here.
|
|
|
|
if (InheritedTemplateArgs)
|
|
|
|
mangleTemplateArgs(*InheritedTemplateArgs);
|
2016-06-30 17:40:38 +08:00
|
|
|
|
|
|
|
writeAbiTags(ND, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
case DeclarationName::CXXDestructorName:
|
|
|
|
if (ND == Structor)
|
|
|
|
// If the named decl is the C++ destructor we're mangling, use the type we
|
|
|
|
// were given.
|
|
|
|
mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
|
|
|
|
else
|
|
|
|
// Otherwise, use the complete destructor name. This is relevant if a
|
|
|
|
// class with a destructor is declared within a destructor.
|
|
|
|
mangleCXXDtorType(Dtor_Complete);
|
2016-06-30 17:40:38 +08:00
|
|
|
writeAbiTags(ND, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
|
2015-02-18 10:28:01 +08:00
|
|
|
case DeclarationName::CXXOperatorName:
|
|
|
|
if (ND && Arity == UnknownArity) {
|
2012-12-18 22:30:41 +08:00
|
|
|
Arity = cast<FunctionDecl>(ND)->getNumParams();
|
|
|
|
|
2015-02-18 10:28:01 +08:00
|
|
|
// If we have a member function, we need to include the 'this' pointer.
|
|
|
|
if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
|
|
|
|
if (!MD->isStatic())
|
|
|
|
Arity++;
|
|
|
|
}
|
2017-12-20 06:06:11 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2015-02-18 10:28:01 +08:00
|
|
|
case DeclarationName::CXXConversionFunctionName:
|
2012-12-18 22:30:41 +08:00
|
|
|
case DeclarationName::CXXLiteralOperatorName:
|
2015-02-18 10:28:01 +08:00
|
|
|
mangleOperatorName(Name, Arity);
|
2016-06-30 17:40:38 +08:00
|
|
|
writeAbiTags(ND, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
|
2017-02-07 09:37:30 +08:00
|
|
|
case DeclarationName::CXXDeductionGuideName:
|
|
|
|
llvm_unreachable("Can't mangle a deduction guide name!");
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case DeclarationName::CXXUsingDirective:
|
|
|
|
llvm_unreachable("Can't mangle a using directive name!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-03 02:29:35 +08:00
|
|
|
void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) {
|
|
|
|
// <source-name> ::= <positive length number> __regcall3__ <identifier>
|
|
|
|
// <number> ::= [n] <non-negative decimal integer>
|
|
|
|
// <identifier> ::= <unqualified source code identifier>
|
|
|
|
Out << II->getLength() + sizeof("__regcall3__") - 1 << "__regcall3__"
|
|
|
|
<< II->getName();
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:59:33 +08:00
|
|
|
void CXXNameMangler::mangleDeviceStubName(const IdentifierInfo *II) {
|
|
|
|
// <source-name> ::= <positive length number> __device_stub__ <identifier>
|
|
|
|
// <number> ::= [n] <non-negative decimal integer>
|
|
|
|
// <identifier> ::= <unqualified source code identifier>
|
|
|
|
Out << II->getLength() + sizeof("__device_stub__") - 1 << "__device_stub__"
|
|
|
|
<< II->getName();
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
|
|
|
|
// <source-name> ::= <positive length number> <identifier>
|
|
|
|
// <number> ::= [n] <non-negative decimal integer>
|
|
|
|
// <identifier> ::= <unqualified source code identifier>
|
|
|
|
Out << II->getLength() << II->getName();
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleNestedName(GlobalDecl GD,
|
2012-12-18 22:30:41 +08:00
|
|
|
const DeclContext *DC,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags,
|
2012-12-18 22:30:41 +08:00
|
|
|
bool NoFunction) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
|
2018-07-31 03:24:48 +08:00
|
|
|
// <nested-name>
|
2012-12-18 22:30:41 +08:00
|
|
|
// ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
|
2018-07-31 03:24:48 +08:00
|
|
|
// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
|
2012-12-18 22:30:41 +08:00
|
|
|
// <template-args> E
|
|
|
|
|
|
|
|
Out << 'N';
|
|
|
|
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
|
2019-01-28 19:37:49 +08:00
|
|
|
Qualifiers MethodQuals = Method->getMethodQualifiers();
|
2013-11-04 07:51:28 +08:00
|
|
|
// We do not consider restrict a distinguishing attribute for overloading
|
|
|
|
// purposes so we must not mangle it.
|
|
|
|
MethodQuals.removeRestrict();
|
|
|
|
mangleQualifiers(MethodQuals);
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleRefQualifier(Method->getRefQualifier());
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Check if we have a template.
|
2014-05-12 13:36:57 +08:00
|
|
|
const TemplateArgumentList *TemplateArgs = nullptr;
|
2020-03-06 01:02:13 +08:00
|
|
|
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
|
2013-07-06 02:41:30 +08:00
|
|
|
mangleTemplatePrefix(TD, NoFunction);
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
manglePrefix(DC, NoFunction);
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GD, AdditionalAbiTags);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
|
|
|
|
const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
|
|
|
// <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
|
|
|
|
|
|
|
|
Out << 'N';
|
|
|
|
|
|
|
|
mangleTemplatePrefix(TD);
|
|
|
|
mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
|
|
|
|
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
static GlobalDecl getParentOfLocalEntity(const DeclContext *DC) {
|
|
|
|
GlobalDecl GD;
|
|
|
|
// The Itanium spec says:
|
|
|
|
// For entities in constructors and destructors, the mangling of the
|
|
|
|
// complete object constructor or destructor is used as the base function
|
|
|
|
// name, i.e. the C1 or D1 version.
|
|
|
|
if (auto *CD = dyn_cast<CXXConstructorDecl>(DC))
|
|
|
|
GD = GlobalDecl(CD, Ctor_Complete);
|
|
|
|
else if (auto *DD = dyn_cast<CXXDestructorDecl>(DC))
|
|
|
|
GD = GlobalDecl(DD, Dtor_Complete);
|
2020-03-18 13:43:20 +08:00
|
|
|
else
|
|
|
|
GD = GlobalDecl(cast<FunctionDecl>(DC));
|
2020-03-06 01:02:13 +08:00
|
|
|
return GD;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleLocalName(GlobalDecl GD,
|
2016-06-30 17:40:38 +08:00
|
|
|
const AbiTagList *AdditionalAbiTags) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const Decl *D = GD.getDecl();
|
2012-12-18 22:30:41 +08:00
|
|
|
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
|
|
|
|
// := Z <function encoding> E s [<discriminator>]
|
2018-07-31 03:24:48 +08:00
|
|
|
// <local-name> := Z <function encoding> E d [ <parameter number> ]
|
2012-12-18 22:30:41 +08:00
|
|
|
// _ <entity name>
|
|
|
|
// <discriminator> := _ <non-negative number>
|
2013-07-03 01:52:28 +08:00
|
|
|
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
|
2013-07-06 04:27:40 +08:00
|
|
|
const RecordDecl *RD = GetLocalClassDecl(D);
|
2013-07-03 01:52:28 +08:00
|
|
|
const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
Out << 'Z';
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
{
|
|
|
|
AbiTagState LocalAbiTags(AbiTags);
|
|
|
|
|
|
|
|
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
|
|
|
|
mangleObjCMethodName(MD);
|
|
|
|
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC))
|
|
|
|
mangleBlockForPrefix(BD);
|
|
|
|
else
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleFunctionEncoding(getParentOfLocalEntity(DC));
|
2016-06-30 17:40:38 +08:00
|
|
|
|
|
|
|
// Implicit ABI tags (from namespace) are not available in the following
|
|
|
|
// entity; reset to actually emitted tags, which are available.
|
|
|
|
LocalAbiTags.setUsedAbiTags(LocalAbiTags.getEmittedAbiTags());
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2013-07-02 10:01:18 +08:00
|
|
|
Out << 'E';
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
// GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to
|
|
|
|
// be a bug that is fixed in trunk.
|
|
|
|
|
2013-07-02 10:01:18 +08:00
|
|
|
if (RD) {
|
2018-07-31 03:24:48 +08:00
|
|
|
// The parameter number is omitted for the last parameter, 0 for the
|
|
|
|
// second-to-last parameter, 1 for the third-to-last parameter, etc. The
|
|
|
|
// <entity name> will of course contain a <closure-type-name>: Its
|
2012-12-18 22:30:41 +08:00
|
|
|
// numbering will be local to the particular argument in which it appears
|
|
|
|
// -- other default arguments do not affect its encoding.
|
2013-07-06 04:27:40 +08:00
|
|
|
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
|
2016-07-19 06:37:35 +08:00
|
|
|
if (CXXRD && CXXRD->isLambda()) {
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const ParmVarDecl *Parm
|
2013-07-06 04:27:40 +08:00
|
|
|
= dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) {
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const FunctionDecl *Func
|
|
|
|
= dyn_cast<FunctionDecl>(Parm->getDeclContext())) {
|
|
|
|
Out << 'd';
|
|
|
|
unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex();
|
|
|
|
if (Num > 1)
|
|
|
|
mangleNumber(Num - 2);
|
|
|
|
Out << '_';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Mangle the name relative to the closest enclosing function.
|
2013-07-03 01:52:28 +08:00
|
|
|
// equality ok because RD derived from ND above
|
|
|
|
if (D == RD) {
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleUnqualifiedName(RD, AdditionalAbiTags);
|
2013-07-03 01:52:28 +08:00
|
|
|
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
|
|
|
manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
|
2016-06-30 17:40:38 +08:00
|
|
|
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
|
2013-07-03 01:52:28 +08:00
|
|
|
mangleUnqualifiedBlock(BD);
|
|
|
|
} else {
|
|
|
|
const NamedDecl *ND = cast<NamedDecl>(D);
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags,
|
2016-06-30 17:40:38 +08:00
|
|
|
true /*NoFunction*/);
|
2013-07-03 01:52:28 +08:00
|
|
|
}
|
2013-07-10 09:33:19 +08:00
|
|
|
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
|
|
|
|
// Mangle a block in a default parameter; see above explanation for
|
|
|
|
// lambdas.
|
|
|
|
if (const ParmVarDecl *Parm
|
|
|
|
= dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl())) {
|
|
|
|
if (const FunctionDecl *Func
|
|
|
|
= dyn_cast<FunctionDecl>(Parm->getDeclContext())) {
|
|
|
|
Out << 'd';
|
|
|
|
unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex();
|
|
|
|
if (Num > 1)
|
|
|
|
mangleNumber(Num - 2);
|
|
|
|
Out << '_';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
|
2013-07-10 09:33:19 +08:00
|
|
|
mangleUnqualifiedBlock(BD);
|
2013-07-10 08:30:46 +08:00
|
|
|
} else {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GD, AdditionalAbiTags);
|
2013-07-10 08:30:46 +08:00
|
|
|
}
|
2013-07-10 09:33:19 +08:00
|
|
|
|
2013-07-10 08:30:46 +08:00
|
|
|
if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) {
|
|
|
|
unsigned disc;
|
|
|
|
if (Context.getNextDiscriminator(ND, disc)) {
|
|
|
|
if (disc < 10)
|
|
|
|
Out << '_' << disc;
|
|
|
|
else
|
|
|
|
Out << "__" << disc << '_';
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
2013-07-03 01:52:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
|
|
|
|
if (GetLocalClassDecl(Block)) {
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
2013-07-03 01:52:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
const DeclContext *DC = getEffectiveDeclContext(Block);
|
|
|
|
if (isLocalContainerContext(DC)) {
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
|
2013-07-03 01:52:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
manglePrefix(getEffectiveDeclContext(Block));
|
|
|
|
mangleUnqualifiedBlock(Block);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
|
|
|
|
if (Decl *Context = Block->getBlockManglingContextDecl()) {
|
|
|
|
if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
|
|
|
|
Context->getDeclContext()->isRecord()) {
|
2016-06-30 17:40:38 +08:00
|
|
|
const auto *ND = cast<NamedDecl>(Context);
|
|
|
|
if (ND->getIdentifier()) {
|
|
|
|
mangleSourceNameWithAbiTags(ND);
|
|
|
|
Out << 'M';
|
2013-07-03 01:52:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a block mangling number, use it.
|
|
|
|
unsigned Number = Block->getBlockManglingNumber();
|
|
|
|
// Otherwise, just make up a number. It doesn't matter what it is because
|
|
|
|
// the symbol in question isn't externally visible.
|
|
|
|
if (!Number)
|
|
|
|
Number = Context.getBlockId(Block, false);
|
2017-09-07 13:41:24 +08:00
|
|
|
else {
|
|
|
|
// Stored mangling numbers are 1-based.
|
|
|
|
--Number;
|
|
|
|
}
|
2013-07-03 01:52:28 +08:00
|
|
|
Out << "Ub";
|
2014-08-04 14:16:50 +08:00
|
|
|
if (Number > 0)
|
|
|
|
Out << Number - 1;
|
2013-07-03 01:52:28 +08:00
|
|
|
Out << '_';
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
// <template-param-decl>
|
|
|
|
// ::= Ty # template type parameter
|
|
|
|
// ::= Tn <type> # template non-type parameter
|
|
|
|
// ::= Tt <template-param-decl>* E # template template parameter
|
2019-09-07 04:32:01 +08:00
|
|
|
// ::= Tp <template-param-decl> # template parameter pack
|
2019-05-04 18:49:46 +08:00
|
|
|
void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) {
|
2019-09-05 09:23:47 +08:00
|
|
|
if (auto *Ty = dyn_cast<TemplateTypeParmDecl>(Decl)) {
|
|
|
|
if (Ty->isParameterPack())
|
|
|
|
Out << "Tp";
|
2019-05-04 18:49:46 +08:00
|
|
|
Out << "Ty";
|
|
|
|
} else if (auto *Tn = dyn_cast<NonTypeTemplateParmDecl>(Decl)) {
|
2019-09-05 09:23:47 +08:00
|
|
|
if (Tn->isExpandedParameterPack()) {
|
|
|
|
for (unsigned I = 0, N = Tn->getNumExpansionTypes(); I != N; ++I) {
|
|
|
|
Out << "Tn";
|
|
|
|
mangleType(Tn->getExpansionType(I));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
QualType T = Tn->getType();
|
|
|
|
if (Tn->isParameterPack()) {
|
|
|
|
Out << "Tp";
|
2019-09-10 08:39:53 +08:00
|
|
|
if (auto *PackExpansion = T->getAs<PackExpansionType>())
|
|
|
|
T = PackExpansion->getPattern();
|
2019-09-05 09:23:47 +08:00
|
|
|
}
|
|
|
|
Out << "Tn";
|
|
|
|
mangleType(T);
|
|
|
|
}
|
2019-05-04 18:49:46 +08:00
|
|
|
} else if (auto *Tt = dyn_cast<TemplateTemplateParmDecl>(Decl)) {
|
2019-09-05 09:23:47 +08:00
|
|
|
if (Tt->isExpandedParameterPack()) {
|
|
|
|
for (unsigned I = 0, N = Tt->getNumExpansionTemplateParameters(); I != N;
|
|
|
|
++I) {
|
|
|
|
Out << "Tt";
|
|
|
|
for (auto *Param : *Tt->getExpansionTemplateParameters(I))
|
|
|
|
mangleTemplateParamDecl(Param);
|
|
|
|
Out << "E";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Tt->isParameterPack())
|
|
|
|
Out << "Tp";
|
|
|
|
Out << "Tt";
|
|
|
|
for (auto *Param : *Tt->getTemplateParameters())
|
|
|
|
mangleTemplateParamDecl(Param);
|
|
|
|
Out << "E";
|
|
|
|
}
|
2019-05-04 18:49:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
// Handles the __builtin_unique_stable_name feature for lambdas. Instead of the
|
|
|
|
// ordinal of the lambda in its mangling, this does line/column to uniquely and
|
|
|
|
// reliably identify the lambda. Additionally, macro expansions are expressed
|
|
|
|
// as well to prevent macros causing duplicates.
|
|
|
|
static void mangleUniqueNameLambda(CXXNameMangler &Mangler, SourceManager &SM,
|
|
|
|
raw_ostream &Out,
|
|
|
|
const CXXRecordDecl *Lambda) {
|
|
|
|
SourceLocation Loc = Lambda->getLocation();
|
|
|
|
|
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
|
|
|
Mangler.mangleNumber(PLoc.getLine());
|
2020-04-17 22:52:50 +08:00
|
|
|
Out << "_";
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
Mangler.mangleNumber(PLoc.getColumn());
|
|
|
|
|
|
|
|
while(Loc.isMacroID()) {
|
|
|
|
SourceLocation SLToPrint = Loc;
|
|
|
|
if (SM.isMacroArgExpansion(Loc))
|
|
|
|
SLToPrint = SM.getImmediateExpansionRange(Loc).getBegin();
|
|
|
|
|
|
|
|
PLoc = SM.getPresumedLoc(SM.getSpellingLoc(SLToPrint));
|
2020-04-17 22:52:50 +08:00
|
|
|
Out << "m";
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
Mangler.mangleNumber(PLoc.getLine());
|
2020-04-17 22:52:50 +08:00
|
|
|
Out << "_";
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
Mangler.mangleNumber(PLoc.getColumn());
|
|
|
|
|
|
|
|
Loc = SM.getImmediateMacroCallerLoc(Loc);
|
|
|
|
if (Loc.isFileID())
|
|
|
|
Loc = SM.getImmediateMacroCallerLoc(SLToPrint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
|
2018-07-31 03:24:48 +08:00
|
|
|
// If the context of a closure type is an initializer for a class member
|
|
|
|
// (static or nonstatic), it is encoded in a qualified name with a final
|
2012-12-18 22:30:41 +08:00
|
|
|
// <prefix> of the form:
|
|
|
|
//
|
|
|
|
// <data-member-prefix> := <member source-name> M
|
|
|
|
//
|
|
|
|
// Technically, the data-member-prefix is part of the <prefix>. However,
|
|
|
|
// since a closure type will always be mangled with a prefix, it's easier
|
|
|
|
// to emit that last part of the prefix here.
|
|
|
|
if (Decl *Context = Lambda->getLambdaContextDecl()) {
|
|
|
|
if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
|
2017-09-22 12:25:05 +08:00
|
|
|
!isa<ParmVarDecl>(Context)) {
|
|
|
|
// FIXME: 'inline auto [a, b] = []{ return ... };' does not get a
|
|
|
|
// reasonable mangling here.
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const IdentifierInfo *Name
|
|
|
|
= cast<NamedDecl>(Context)->getIdentifier()) {
|
|
|
|
mangleSourceName(Name);
|
2017-09-22 12:25:05 +08:00
|
|
|
const TemplateArgumentList *TemplateArgs = nullptr;
|
2017-09-23 00:26:17 +08:00
|
|
|
if (isTemplate(cast<NamedDecl>(Context), TemplateArgs))
|
2017-09-22 12:25:05 +08:00
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
2016-06-30 17:40:38 +08:00
|
|
|
Out << 'M';
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << "Ul";
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleLambdaSig(Lambda);
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << "E";
|
2018-07-31 03:24:48 +08:00
|
|
|
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
if (Context.isUniqueNameMangler()) {
|
|
|
|
mangleUniqueNameLambda(
|
|
|
|
*this, Context.getASTContext().getSourceManager(), Out, Lambda);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
// The number is omitted for the first closure type with a given
|
|
|
|
// <lambda-sig> in a given context; it is n-2 for the nth closure type
|
2012-12-18 22:30:41 +08:00
|
|
|
// (in lexical order) with that same <lambda-sig> and context.
|
|
|
|
//
|
|
|
|
// The AST keeps track of the number for us.
|
|
|
|
unsigned Number = Lambda->getLambdaManglingNumber();
|
|
|
|
assert(Number > 0 && "Lambda should be mangled as an unnamed class");
|
|
|
|
if (Number > 1)
|
|
|
|
mangleNumber(Number - 2);
|
2018-07-31 03:24:48 +08:00
|
|
|
Out << '_';
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2019-09-05 09:23:47 +08:00
|
|
|
void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
|
|
|
|
for (auto *D : Lambda->getLambdaExplicitTemplateParameters())
|
|
|
|
mangleTemplateParamDecl(D);
|
2020-03-05 23:28:43 +08:00
|
|
|
auto *Proto =
|
|
|
|
Lambda->getLambdaTypeInfo()->getType()->castAs<FunctionProtoType>();
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
|
|
|
|
Lambda->getLambdaStaticInvoker());
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
|
|
|
|
switch (qualifier->getKind()) {
|
|
|
|
case NestedNameSpecifier::Global:
|
|
|
|
// nothing
|
|
|
|
return;
|
|
|
|
|
2014-09-26 08:28:20 +08:00
|
|
|
case NestedNameSpecifier::Super:
|
|
|
|
llvm_unreachable("Can't mangle __super specifier");
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case NestedNameSpecifier::Namespace:
|
|
|
|
mangleName(qualifier->getAsNamespace());
|
|
|
|
return;
|
|
|
|
|
|
|
|
case NestedNameSpecifier::NamespaceAlias:
|
|
|
|
mangleName(qualifier->getAsNamespaceAlias()->getNamespace());
|
|
|
|
return;
|
|
|
|
|
|
|
|
case NestedNameSpecifier::TypeSpec:
|
|
|
|
case NestedNameSpecifier::TypeSpecWithTemplate:
|
|
|
|
manglePrefix(QualType(qualifier->getAsType(), 0));
|
|
|
|
return;
|
|
|
|
|
|
|
|
case NestedNameSpecifier::Identifier:
|
|
|
|
// Member expressions can have these without prefixes, but that
|
|
|
|
// should end up in mangleUnresolvedPrefix instead.
|
|
|
|
assert(qualifier->getPrefix());
|
|
|
|
manglePrefix(qualifier->getPrefix());
|
|
|
|
|
|
|
|
mangleSourceName(qualifier->getAsIdentifier());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("unexpected nested name specifier");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
|
|
|
// <prefix> ::= <prefix> <unqualified-name>
|
|
|
|
// ::= <template-prefix> <template-args>
|
|
|
|
// ::= <template-param>
|
|
|
|
// ::= # empty
|
|
|
|
// ::= <substitution>
|
|
|
|
|
|
|
|
DC = IgnoreLinkageSpecDecls(DC);
|
|
|
|
|
|
|
|
if (DC->isTranslationUnit())
|
|
|
|
return;
|
|
|
|
|
2013-07-03 01:52:28 +08:00
|
|
|
if (NoFunction && isLocalContainerContext(DC))
|
2013-05-10 03:17:11 +08:00
|
|
|
return;
|
2013-07-03 01:52:28 +08:00
|
|
|
|
|
|
|
assert(!isLocalContainerContext(DC));
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
const NamedDecl *ND = cast<NamedDecl>(DC);
|
2012-12-18 22:30:41 +08:00
|
|
|
if (mangleSubstitution(ND))
|
|
|
|
return;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Check if we have a template.
|
2014-05-12 13:36:57 +08:00
|
|
|
const TemplateArgumentList *TemplateArgs = nullptr;
|
2020-03-06 01:02:13 +08:00
|
|
|
if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleTemplatePrefix(TD);
|
|
|
|
mangleTemplateArgs(*TemplateArgs);
|
2013-07-03 01:52:28 +08:00
|
|
|
} else {
|
2012-12-18 22:30:41 +08:00
|
|
|
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleUnqualifiedName(ND, nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
addSubstitution(ND);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
|
|
|
|
// <template-prefix> ::= <prefix> <template unqualified-name>
|
|
|
|
// ::= <template-param>
|
|
|
|
// ::= <substitution>
|
|
|
|
if (TemplateDecl *TD = Template.getAsTemplateDecl())
|
|
|
|
return mangleTemplatePrefix(TD);
|
|
|
|
|
|
|
|
if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
|
|
|
|
manglePrefix(Qualified->getQualifier());
|
2016-06-30 17:40:38 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
if (OverloadedTemplateStorage *Overloaded
|
|
|
|
= Template.getAsOverloadedTemplate()) {
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GlobalDecl(), (*Overloaded->begin())->getDeclName(),
|
2016-06-30 17:40:38 +08:00
|
|
|
UnknownArity, nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
|
|
|
}
|
2016-06-30 17:40:38 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
|
|
|
|
assert(Dependent && "Unknown template name kind?");
|
2015-02-14 21:23:54 +08:00
|
|
|
if (NestedNameSpecifier *Qualifier = Dependent->getQualifier())
|
|
|
|
manglePrefix(Qualifier);
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleUnscopedTemplateName(Template, /* AdditionalAbiTags */ nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD,
|
2013-07-06 02:41:30 +08:00
|
|
|
bool NoFunction) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const TemplateDecl *ND = cast<TemplateDecl>(GD.getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
// <template-prefix> ::= <prefix> <template unqualified-name>
|
|
|
|
// ::= <template-param>
|
|
|
|
// ::= <substitution>
|
|
|
|
// <template-template-param> ::= <template-param>
|
|
|
|
// <substitution>
|
|
|
|
|
|
|
|
if (mangleSubstitution(ND))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// <template-template-param> ::= <template-param>
|
2014-10-25 04:22:57 +08:00
|
|
|
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
2014-10-25 04:22:57 +08:00
|
|
|
} else {
|
|
|
|
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
|
2019-10-17 08:16:01 +08:00
|
|
|
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GD, nullptr);
|
2016-07-13 00:48:17 +08:00
|
|
|
else
|
2020-03-06 01:02:13 +08:00
|
|
|
mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), nullptr);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
addSubstitution(ND);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mangles a template name under the production <type>. Required for
|
|
|
|
/// template template arguments.
|
|
|
|
/// <type> ::= <class-enum-type>
|
|
|
|
/// ::= <template-param>
|
|
|
|
/// ::= <substitution>
|
|
|
|
void CXXNameMangler::mangleType(TemplateName TN) {
|
|
|
|
if (mangleSubstitution(TN))
|
|
|
|
return;
|
2014-05-12 13:36:57 +08:00
|
|
|
|
|
|
|
TemplateDecl *TD = nullptr;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
switch (TN.getKind()) {
|
|
|
|
case TemplateName::QualifiedTemplate:
|
|
|
|
TD = TN.getAsQualifiedTemplateName()->getTemplateDecl();
|
|
|
|
goto HaveDecl;
|
|
|
|
|
|
|
|
case TemplateName::Template:
|
|
|
|
TD = TN.getAsTemplateDecl();
|
|
|
|
goto HaveDecl;
|
|
|
|
|
|
|
|
HaveDecl:
|
2019-09-05 09:23:47 +08:00
|
|
|
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD))
|
|
|
|
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
2012-12-18 22:30:41 +08:00
|
|
|
else
|
|
|
|
mangleName(TD);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateName::OverloadedTemplate:
|
2019-05-09 11:31:27 +08:00
|
|
|
case TemplateName::AssumedTemplate:
|
2012-12-18 22:30:41 +08:00
|
|
|
llvm_unreachable("can't mangle an overloaded template name as a <type>");
|
|
|
|
|
|
|
|
case TemplateName::DependentTemplate: {
|
|
|
|
const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
|
|
|
|
assert(Dependent->isIdentifier());
|
|
|
|
|
|
|
|
// <class-enum-type> ::= <name>
|
|
|
|
// <name> ::= <nested-name>
|
2015-02-19 13:51:14 +08:00
|
|
|
mangleUnresolvedPrefix(Dependent->getQualifier());
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleSourceName(Dependent->getIdentifier());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateName::SubstTemplateTemplateParm: {
|
|
|
|
// Substituted template parameters are mangled as the substituted
|
|
|
|
// template. This will check for the substitution twice, which is
|
|
|
|
// fine, but we have to return early so that we don't try to *add*
|
|
|
|
// the substitution twice.
|
|
|
|
SubstTemplateTemplateParmStorage *subst
|
|
|
|
= TN.getAsSubstTemplateTemplateParm();
|
|
|
|
mangleType(subst->getReplacement());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateName::SubstTemplateTemplateParmPack: {
|
|
|
|
// FIXME: not clear how to mangle this!
|
|
|
|
// template <template <class> class T...> class A {
|
|
|
|
// template <template <class> class U...> void foo(B<T,U> x...);
|
|
|
|
// };
|
|
|
|
Out << "_SUBSTPACK_";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addSubstitution(TN);
|
|
|
|
}
|
|
|
|
|
2015-02-19 10:16:16 +08:00
|
|
|
bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
|
|
|
|
StringRef Prefix) {
|
|
|
|
// Only certain other types are valid as prefixes; enumerate them.
|
|
|
|
switch (Ty->getTypeClass()) {
|
|
|
|
case Type::Builtin:
|
|
|
|
case Type::Complex:
|
|
|
|
case Type::Adjusted:
|
|
|
|
case Type::Decayed:
|
|
|
|
case Type::Pointer:
|
|
|
|
case Type::BlockPointer:
|
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference:
|
|
|
|
case Type::MemberPointer:
|
|
|
|
case Type::ConstantArray:
|
|
|
|
case Type::IncompleteArray:
|
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::DependentSizedArray:
|
2017-10-02 14:25:51 +08:00
|
|
|
case Type::DependentAddressSpace:
|
2018-07-14 03:46:04 +08:00
|
|
|
case Type::DependentVector:
|
2015-02-19 10:16:16 +08:00
|
|
|
case Type::DependentSizedExtVector:
|
|
|
|
case Type::Vector:
|
|
|
|
case Type::ExtVector:
|
2020-05-12 00:45:51 +08:00
|
|
|
case Type::ConstantMatrix:
|
|
|
|
case Type::DependentSizedMatrix:
|
2015-02-19 10:16:16 +08:00
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::FunctionNoProto:
|
|
|
|
case Type::Paren:
|
|
|
|
case Type::Attributed:
|
|
|
|
case Type::Auto:
|
2017-01-27 04:40:47 +08:00
|
|
|
case Type::DeducedTemplateSpecialization:
|
2015-02-19 10:16:16 +08:00
|
|
|
case Type::PackExpansion:
|
|
|
|
case Type::ObjCObject:
|
|
|
|
case Type::ObjCInterface:
|
|
|
|
case Type::ObjCObjectPointer:
|
2016-09-14 01:25:08 +08:00
|
|
|
case Type::ObjCTypeParam:
|
2015-02-19 10:16:16 +08:00
|
|
|
case Type::Atomic:
|
2016-01-09 20:53:17 +08:00
|
|
|
case Type::Pipe:
|
2019-05-07 11:20:17 +08:00
|
|
|
case Type::MacroQualified:
|
2020-04-18 01:44:19 +08:00
|
|
|
case Type::ExtInt:
|
|
|
|
case Type::DependentExtInt:
|
2015-02-19 10:16:16 +08:00
|
|
|
llvm_unreachable("type is illegal as a nested name specifier");
|
|
|
|
|
|
|
|
case Type::SubstTemplateTypeParmPack:
|
|
|
|
// FIXME: not clear how to mangle this!
|
|
|
|
// template <class T...> class A {
|
|
|
|
// template <class U...> void foo(decltype(T::foo(U())) x...);
|
|
|
|
// };
|
|
|
|
Out << "_SUBSTPACK_";
|
|
|
|
break;
|
|
|
|
|
|
|
|
// <unresolved-type> ::= <template-param>
|
|
|
|
// ::= <decltype>
|
|
|
|
// ::= <template-template-param> <template-args>
|
|
|
|
// (this last is not official yet)
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
case Type::TypeOf:
|
|
|
|
case Type::Decltype:
|
|
|
|
case Type::TemplateTypeParm:
|
|
|
|
case Type::UnaryTransform:
|
|
|
|
case Type::SubstTemplateTypeParm:
|
|
|
|
unresolvedType:
|
|
|
|
// Some callers want a prefix before the mangled type.
|
|
|
|
Out << Prefix;
|
|
|
|
|
|
|
|
// This seems to do everything we want. It's not really
|
|
|
|
// sanctioned for a substituted template parameter, though.
|
|
|
|
mangleType(Ty);
|
|
|
|
|
|
|
|
// We never want to print 'E' directly after an unresolved-type,
|
|
|
|
// so we return directly.
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case Type::Typedef:
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(cast<TypedefType>(Ty)->getDecl());
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::UnresolvedUsing:
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(
|
|
|
|
cast<UnresolvedUsingType>(Ty)->getDecl());
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::Enum:
|
|
|
|
case Type::Record:
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(cast<TagType>(Ty)->getDecl());
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::TemplateSpecialization: {
|
|
|
|
const TemplateSpecializationType *TST =
|
|
|
|
cast<TemplateSpecializationType>(Ty);
|
2015-02-18 10:28:01 +08:00
|
|
|
TemplateName TN = TST->getTemplateName();
|
2015-02-19 10:16:16 +08:00
|
|
|
switch (TN.getKind()) {
|
|
|
|
case TemplateName::Template:
|
|
|
|
case TemplateName::QualifiedTemplate: {
|
|
|
|
TemplateDecl *TD = TN.getAsTemplateDecl();
|
|
|
|
|
|
|
|
// If the base is a template template parameter, this is an
|
|
|
|
// unresolved type.
|
|
|
|
assert(TD && "no template for template specialization type");
|
|
|
|
if (isa<TemplateTemplateParmDecl>(TD))
|
|
|
|
goto unresolvedType;
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(TD);
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateName::OverloadedTemplate:
|
2019-05-09 11:31:27 +08:00
|
|
|
case TemplateName::AssumedTemplate:
|
2015-02-19 10:16:16 +08:00
|
|
|
case TemplateName::DependentTemplate:
|
|
|
|
llvm_unreachable("invalid base for a template specialization type");
|
|
|
|
|
|
|
|
case TemplateName::SubstTemplateTemplateParm: {
|
|
|
|
SubstTemplateTemplateParmStorage *subst =
|
|
|
|
TN.getAsSubstTemplateTemplateParm();
|
|
|
|
mangleExistingSubstitution(subst->getReplacement());
|
|
|
|
break;
|
2015-02-18 10:28:01 +08:00
|
|
|
}
|
2015-02-19 10:16:16 +08:00
|
|
|
|
|
|
|
case TemplateName::SubstTemplateTemplateParmPack: {
|
|
|
|
// FIXME: not clear how to mangle this!
|
|
|
|
// template <template <class U> class T...> class A {
|
|
|
|
// template <class U...> void foo(decltype(T<U>::foo) x...);
|
|
|
|
// };
|
|
|
|
Out << "_SUBSTPACK_";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-18 10:28:01 +08:00
|
|
|
mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Type::InjectedClassName:
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleSourceNameWithAbiTags(
|
|
|
|
cast<InjectedClassNameType>(Ty)->getDecl());
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::DependentName:
|
|
|
|
mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::DependentTemplateSpecialization: {
|
|
|
|
const DependentTemplateSpecializationType *DTST =
|
|
|
|
cast<DependentTemplateSpecializationType>(Ty);
|
|
|
|
mangleSourceName(DTST->getIdentifier());
|
2015-02-18 10:28:01 +08:00
|
|
|
mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
|
2015-02-19 10:16:16 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Type::Elaborated:
|
|
|
|
return mangleUnresolvedTypeOrSimpleId(
|
|
|
|
cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
|
2015-02-18 10:28:01 +08:00
|
|
|
}
|
2015-02-19 10:16:16 +08:00
|
|
|
|
|
|
|
return false;
|
2015-02-18 10:28:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) {
|
|
|
|
switch (Name.getNameKind()) {
|
|
|
|
case DeclarationName::CXXConstructorName:
|
|
|
|
case DeclarationName::CXXDestructorName:
|
2017-02-07 09:37:30 +08:00
|
|
|
case DeclarationName::CXXDeductionGuideName:
|
2015-02-18 10:28:01 +08:00
|
|
|
case DeclarationName::CXXUsingDirective:
|
|
|
|
case DeclarationName::Identifier:
|
|
|
|
case DeclarationName::ObjCMultiArgSelector:
|
|
|
|
case DeclarationName::ObjCOneArgSelector:
|
|
|
|
case DeclarationName::ObjCZeroArgSelector:
|
|
|
|
llvm_unreachable("Not an operator name");
|
|
|
|
|
|
|
|
case DeclarationName::CXXConversionFunctionName:
|
|
|
|
// <operator-name> ::= cv <type> # (cast)
|
|
|
|
Out << "cv";
|
|
|
|
mangleType(Name.getCXXNameType());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DeclarationName::CXXLiteralOperatorName:
|
|
|
|
Out << "li";
|
|
|
|
mangleSourceName(Name.getCXXLiteralIdentifier());
|
|
|
|
return;
|
|
|
|
|
|
|
|
case DeclarationName::CXXOperatorName:
|
|
|
|
mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void
|
|
|
|
CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
|
|
|
|
switch (OO) {
|
|
|
|
// <operator-name> ::= nw # new
|
|
|
|
case OO_New: Out << "nw"; break;
|
|
|
|
// ::= na # new[]
|
|
|
|
case OO_Array_New: Out << "na"; break;
|
|
|
|
// ::= dl # delete
|
|
|
|
case OO_Delete: Out << "dl"; break;
|
|
|
|
// ::= da # delete[]
|
|
|
|
case OO_Array_Delete: Out << "da"; break;
|
|
|
|
// ::= ps # + (unary)
|
|
|
|
// ::= pl # + (binary or unknown)
|
|
|
|
case OO_Plus:
|
|
|
|
Out << (Arity == 1? "ps" : "pl"); break;
|
|
|
|
// ::= ng # - (unary)
|
|
|
|
// ::= mi # - (binary or unknown)
|
|
|
|
case OO_Minus:
|
|
|
|
Out << (Arity == 1? "ng" : "mi"); break;
|
|
|
|
// ::= ad # & (unary)
|
|
|
|
// ::= an # & (binary or unknown)
|
|
|
|
case OO_Amp:
|
|
|
|
Out << (Arity == 1? "ad" : "an"); break;
|
|
|
|
// ::= de # * (unary)
|
|
|
|
// ::= ml # * (binary or unknown)
|
|
|
|
case OO_Star:
|
|
|
|
// Use binary when unknown.
|
|
|
|
Out << (Arity == 1? "de" : "ml"); break;
|
|
|
|
// ::= co # ~
|
|
|
|
case OO_Tilde: Out << "co"; break;
|
|
|
|
// ::= dv # /
|
|
|
|
case OO_Slash: Out << "dv"; break;
|
|
|
|
// ::= rm # %
|
|
|
|
case OO_Percent: Out << "rm"; break;
|
|
|
|
// ::= or # |
|
|
|
|
case OO_Pipe: Out << "or"; break;
|
|
|
|
// ::= eo # ^
|
|
|
|
case OO_Caret: Out << "eo"; break;
|
|
|
|
// ::= aS # =
|
|
|
|
case OO_Equal: Out << "aS"; break;
|
|
|
|
// ::= pL # +=
|
|
|
|
case OO_PlusEqual: Out << "pL"; break;
|
|
|
|
// ::= mI # -=
|
|
|
|
case OO_MinusEqual: Out << "mI"; break;
|
|
|
|
// ::= mL # *=
|
|
|
|
case OO_StarEqual: Out << "mL"; break;
|
|
|
|
// ::= dV # /=
|
|
|
|
case OO_SlashEqual: Out << "dV"; break;
|
|
|
|
// ::= rM # %=
|
|
|
|
case OO_PercentEqual: Out << "rM"; break;
|
|
|
|
// ::= aN # &=
|
|
|
|
case OO_AmpEqual: Out << "aN"; break;
|
|
|
|
// ::= oR # |=
|
|
|
|
case OO_PipeEqual: Out << "oR"; break;
|
|
|
|
// ::= eO # ^=
|
|
|
|
case OO_CaretEqual: Out << "eO"; break;
|
|
|
|
// ::= ls # <<
|
|
|
|
case OO_LessLess: Out << "ls"; break;
|
|
|
|
// ::= rs # >>
|
|
|
|
case OO_GreaterGreater: Out << "rs"; break;
|
|
|
|
// ::= lS # <<=
|
|
|
|
case OO_LessLessEqual: Out << "lS"; break;
|
|
|
|
// ::= rS # >>=
|
|
|
|
case OO_GreaterGreaterEqual: Out << "rS"; break;
|
|
|
|
// ::= eq # ==
|
|
|
|
case OO_EqualEqual: Out << "eq"; break;
|
|
|
|
// ::= ne # !=
|
|
|
|
case OO_ExclaimEqual: Out << "ne"; break;
|
|
|
|
// ::= lt # <
|
|
|
|
case OO_Less: Out << "lt"; break;
|
|
|
|
// ::= gt # >
|
|
|
|
case OO_Greater: Out << "gt"; break;
|
|
|
|
// ::= le # <=
|
|
|
|
case OO_LessEqual: Out << "le"; break;
|
|
|
|
// ::= ge # >=
|
|
|
|
case OO_GreaterEqual: Out << "ge"; break;
|
|
|
|
// ::= nt # !
|
|
|
|
case OO_Exclaim: Out << "nt"; break;
|
|
|
|
// ::= aa # &&
|
|
|
|
case OO_AmpAmp: Out << "aa"; break;
|
|
|
|
// ::= oo # ||
|
|
|
|
case OO_PipePipe: Out << "oo"; break;
|
|
|
|
// ::= pp # ++
|
|
|
|
case OO_PlusPlus: Out << "pp"; break;
|
|
|
|
// ::= mm # --
|
|
|
|
case OO_MinusMinus: Out << "mm"; break;
|
|
|
|
// ::= cm # ,
|
|
|
|
case OO_Comma: Out << "cm"; break;
|
|
|
|
// ::= pm # ->*
|
|
|
|
case OO_ArrowStar: Out << "pm"; break;
|
|
|
|
// ::= pt # ->
|
|
|
|
case OO_Arrow: Out << "pt"; break;
|
|
|
|
// ::= cl # ()
|
|
|
|
case OO_Call: Out << "cl"; break;
|
|
|
|
// ::= ix # []
|
|
|
|
case OO_Subscript: Out << "ix"; break;
|
|
|
|
|
|
|
|
// ::= qu # ?
|
|
|
|
// The conditional operator can't be overloaded, but we still handle it when
|
|
|
|
// mangling expressions.
|
|
|
|
case OO_Conditional: Out << "qu"; break;
|
2015-10-22 13:12:22 +08:00
|
|
|
// Proposal on cxx-abi-dev, 2015-10-21.
|
|
|
|
// ::= aw # co_await
|
|
|
|
case OO_Coawait: Out << "aw"; break;
|
2017-12-01 10:13:10 +08:00
|
|
|
// Proposed in cxx-abi github issue 43.
|
|
|
|
// ::= ss # <=>
|
|
|
|
case OO_Spaceship: Out << "ss"; break;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
case OO_None:
|
|
|
|
case NUM_OVERLOADED_OPERATORS:
|
|
|
|
llvm_unreachable("Not an overloaded operator");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-02 14:25:51 +08:00
|
|
|
void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST) {
|
2017-06-02 15:14:34 +08:00
|
|
|
// Vendor qualifiers come first and if they are order-insensitive they must
|
|
|
|
// be emitted in reversed alphabetical order, see Itanium ABI 5.1.5.
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2017-10-02 14:25:51 +08:00
|
|
|
// <type> ::= U <addrspace-expr>
|
|
|
|
if (DAST) {
|
|
|
|
Out << "U2ASI";
|
|
|
|
mangleExpression(DAST->getAddrSpaceExpr());
|
|
|
|
Out << "E";
|
|
|
|
}
|
|
|
|
|
2016-03-02 06:18:03 +08:00
|
|
|
// Address space qualifiers start with an ordinary letter.
|
2012-12-18 22:30:41 +08:00
|
|
|
if (Quals.hasAddressSpace()) {
|
2013-09-13 20:04:22 +08:00
|
|
|
// Address space extension:
|
2012-12-18 22:30:41 +08:00
|
|
|
//
|
2013-09-13 20:04:22 +08:00
|
|
|
// <type> ::= U <target-addrspace>
|
|
|
|
// <type> ::= U <OpenCL-addrspace>
|
|
|
|
// <type> ::= U <CUDA-addrspace>
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
SmallString<64> ASString;
|
Convert clang::LangAS to a strongly typed enum
Summary:
Convert clang::LangAS to a strongly typed enum
Currently both clang AST address spaces and target specific address spaces
are represented as unsigned which can lead to subtle errors if the wrong
type is passed. It is especially confusing in the CodeGen files as it is
not possible to see what kind of address space should be passed to a
function without looking at the implementation.
I originally made this change for our LLVM fork for the CHERI architecture
where we make extensive use of address spaces to differentiate between
capabilities and pointers. When merging the upstream changes I usually
run into some test failures or runtime crashes because the wrong kind of
address space is passed to a function. By converting the LangAS enum to a
C++11 we can catch these errors at compile time. Additionally, it is now
obvious from the function signature which kind of address space it expects.
I found the following errors while writing this patch:
- ItaniumRecordLayoutBuilder::LayoutField was passing a clang AST address
space to TargetInfo::getPointer{Width,Align}()
- TypePrinter::printAttributedAfter() prints the numeric value of the
clang AST address space instead of the target address space.
However, this code is not used so I kept the current behaviour
- initializeForBlockHeader() in CGBlocks.cpp was passing
LangAS::opencl_generic to TargetInfo::getPointer{Width,Align}()
- CodeGenFunction::EmitBlockLiteral() was passing a AST address space to
TargetInfo::getPointerWidth()
- CGOpenMPRuntimeNVPTX::translateParameter() passed a target address space
to Qualifiers::addAddressSpace()
- CGOpenMPRuntimeNVPTX::getParameterAddress() was using
llvm::Type::getPointerTo() with a AST address space
- clang_getAddressSpace() returns either a LangAS or a target address
space. As this is exposed to C I have kept the current behaviour and
added a comment stating that it is probably not correct.
Other than this the patch should not cause any functional changes.
Reviewers: yaxunl, pcc, bader
Reviewed By: yaxunl, bader
Subscribers: jlebar, jholewinski, nhaehnle, Anastasia, cfe-commits
Differential Revision: https://reviews.llvm.org/D38816
llvm-svn: 315871
2017-10-16 02:48:14 +08:00
|
|
|
LangAS AS = Quals.getAddressSpace();
|
2013-09-13 20:04:22 +08:00
|
|
|
|
|
|
|
if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
|
|
|
|
// <target-addrspace> ::= "AS" <address-space-number>
|
|
|
|
unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
|
2017-10-13 11:37:48 +08:00
|
|
|
if (TargetAS != 0)
|
|
|
|
ASString = "AS" + llvm::utostr(TargetAS);
|
2013-09-13 20:04:22 +08:00
|
|
|
} else {
|
|
|
|
switch (AS) {
|
|
|
|
default: llvm_unreachable("Not a language specific address space");
|
2017-10-13 11:37:48 +08:00
|
|
|
// <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" |
|
|
|
|
// "private"| "generic" ]
|
2013-09-13 20:04:22 +08:00
|
|
|
case LangAS::opencl_global: ASString = "CLglobal"; break;
|
|
|
|
case LangAS::opencl_local: ASString = "CLlocal"; break;
|
|
|
|
case LangAS::opencl_constant: ASString = "CLconstant"; break;
|
2017-10-13 11:37:48 +08:00
|
|
|
case LangAS::opencl_private: ASString = "CLprivate"; break;
|
2017-03-10 23:23:07 +08:00
|
|
|
case LangAS::opencl_generic: ASString = "CLgeneric"; break;
|
2013-09-13 20:04:22 +08:00
|
|
|
// <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
|
|
|
|
case LangAS::cuda_device: ASString = "CUdevice"; break;
|
|
|
|
case LangAS::cuda_constant: ASString = "CUconstant"; break;
|
|
|
|
case LangAS::cuda_shared: ASString = "CUshared"; break;
|
Add support for the MS qualifiers __ptr32, __ptr64, __sptr, __uptr.
Summary:
This adds parsing of the qualifiers __ptr32, __ptr64, __sptr, and __uptr and
lowers them to the corresponding address space pointer for 32-bit and 64-bit pointers.
(32/64-bit pointers added in https://reviews.llvm.org/D69639)
A large part of this patch is making these pointers ignore the address space
when doing things like overloading and casting.
https://bugs.llvm.org/show_bug.cgi?id=42359
Reviewers: rnk, rsmith
Subscribers: jholewinski, jvesely, nhaehnle, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71039
2019-10-25 07:34:25 +08:00
|
|
|
// <ptrsize-addrspace> ::= [ "ptr32_sptr" | "ptr32_uptr" | "ptr64" ]
|
|
|
|
case LangAS::ptr32_sptr:
|
|
|
|
ASString = "ptr32_sptr";
|
|
|
|
break;
|
|
|
|
case LangAS::ptr32_uptr:
|
|
|
|
ASString = "ptr32_uptr";
|
|
|
|
break;
|
|
|
|
case LangAS::ptr64:
|
|
|
|
ASString = "ptr64";
|
|
|
|
break;
|
2013-09-13 20:04:22 +08:00
|
|
|
}
|
|
|
|
}
|
2017-10-13 11:37:48 +08:00
|
|
|
if (!ASString.empty())
|
|
|
|
mangleVendorQualifier(ASString);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
2016-03-02 06:18:03 +08:00
|
|
|
|
|
|
|
// The ARC ownership qualifiers start with underscores.
|
2012-12-18 22:30:41 +08:00
|
|
|
// Objective-C ARC Extension:
|
|
|
|
//
|
|
|
|
// <type> ::= U "__strong"
|
|
|
|
// <type> ::= U "__weak"
|
|
|
|
// <type> ::= U "__autoreleasing"
|
2017-06-02 15:14:34 +08:00
|
|
|
//
|
|
|
|
// Note: we emit __weak first to preserve the order as
|
|
|
|
// required by the Itanium ABI.
|
|
|
|
if (Quals.getObjCLifetime() == Qualifiers::OCL_Weak)
|
|
|
|
mangleVendorQualifier("__weak");
|
|
|
|
|
|
|
|
// __unaligned (from -fms-extensions)
|
|
|
|
if (Quals.hasUnaligned())
|
|
|
|
mangleVendorQualifier("__unaligned");
|
|
|
|
|
|
|
|
// Remaining ARC ownership qualifiers.
|
|
|
|
switch (Quals.getObjCLifetime()) {
|
2012-12-18 22:30:41 +08:00
|
|
|
case Qualifiers::OCL_None:
|
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Qualifiers::OCL_Weak:
|
2017-06-02 15:14:34 +08:00
|
|
|
// Do nothing as we already handled this case above.
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Qualifiers::OCL_Strong:
|
2016-03-02 06:18:03 +08:00
|
|
|
mangleVendorQualifier("__strong");
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Qualifiers::OCL_Autoreleasing:
|
2016-03-02 06:18:03 +08:00
|
|
|
mangleVendorQualifier("__autoreleasing");
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Qualifiers::OCL_ExplicitNone:
|
|
|
|
// The __unsafe_unretained qualifier is *not* mangled, so that
|
|
|
|
// __unsafe_unretained types in ARC produce the same manglings as the
|
|
|
|
// equivalent (but, naturally, unqualified) types in non-ARC, providing
|
|
|
|
// better ABI compatibility.
|
|
|
|
//
|
|
|
|
// It's safe to do this because unqualified 'id' won't show up
|
|
|
|
// in any type signatures that need to be mangled.
|
|
|
|
break;
|
|
|
|
}
|
2016-03-02 06:18:03 +08:00
|
|
|
|
|
|
|
// <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
|
|
|
|
if (Quals.hasRestrict())
|
|
|
|
Out << 'r';
|
|
|
|
if (Quals.hasVolatile())
|
|
|
|
Out << 'V';
|
|
|
|
if (Quals.hasConst())
|
|
|
|
Out << 'K';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleVendorQualifier(StringRef name) {
|
|
|
|
Out << 'U' << name.size() << name;
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
|
|
|
|
// <ref-qualifier> ::= R # lvalue reference
|
|
|
|
// ::= O # rvalue-reference
|
|
|
|
switch (RefQualifier) {
|
|
|
|
case RQ_None:
|
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case RQ_LValue:
|
|
|
|
Out << 'R';
|
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case RQ_RValue:
|
|
|
|
Out << 'O';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
|
|
|
|
Context.mangleObjCMethodName(MD, Out);
|
|
|
|
}
|
|
|
|
|
2018-04-28 10:40:28 +08:00
|
|
|
static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty,
|
|
|
|
ASTContext &Ctx) {
|
2014-11-29 06:22:46 +08:00
|
|
|
if (Quals)
|
|
|
|
return true;
|
|
|
|
if (Ty->isSpecificBuiltinType(BuiltinType::ObjCSel))
|
|
|
|
return true;
|
|
|
|
if (Ty->isOpenCLSpecificType())
|
|
|
|
return true;
|
|
|
|
if (Ty->isBuiltinType())
|
|
|
|
return false;
|
2018-04-28 10:40:28 +08:00
|
|
|
// Through to Clang 6.0, we accidentally treated undeduced auto types as
|
|
|
|
// substitution candidates.
|
|
|
|
if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver6 &&
|
|
|
|
isa<AutoType>(Ty))
|
|
|
|
return false;
|
2014-11-29 06:22:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleType(QualType T) {
|
|
|
|
// If our type is instantiation-dependent but not dependent, we mangle
|
2018-07-31 03:24:48 +08:00
|
|
|
// it as it was written in the source, removing any top-level sugar.
|
2012-12-18 22:30:41 +08:00
|
|
|
// Otherwise, use the canonical type.
|
|
|
|
//
|
2018-07-31 03:24:48 +08:00
|
|
|
// FIXME: This is an approximation of the instantiation-dependent name
|
2012-12-18 22:30:41 +08:00
|
|
|
// mangling rules, since we should really be using the type as written and
|
|
|
|
// augmented via semantic analysis (i.e., with implicit conversions and
|
2018-07-31 03:24:48 +08:00
|
|
|
// default template arguments) for any instantiation-dependent type.
|
2012-12-18 22:30:41 +08:00
|
|
|
// Unfortunately, that requires several changes to our AST:
|
2018-07-31 03:24:48 +08:00
|
|
|
// - Instantiation-dependent TemplateSpecializationTypes will need to be
|
2012-12-18 22:30:41 +08:00
|
|
|
// uniqued, so that we can handle substitutions properly
|
|
|
|
// - Default template arguments will need to be represented in the
|
|
|
|
// TemplateSpecializationType, since they need to be mangled even though
|
|
|
|
// they aren't written.
|
|
|
|
// - Conversions on non-type template arguments need to be expressed, since
|
|
|
|
// they can affect the mangling of sizeof/alignof.
|
2016-10-26 09:05:54 +08:00
|
|
|
//
|
|
|
|
// FIXME: This is wrong when mapping to the canonical type for a dependent
|
|
|
|
// type discards instantiation-dependent portions of the type, such as for:
|
|
|
|
//
|
|
|
|
// template<typename T, int N> void f(T (&)[sizeof(N)]);
|
|
|
|
// template<typename T> void f(T() throw(typename T::type)); (pre-C++17)
|
|
|
|
//
|
|
|
|
// It's also wrong in the opposite direction when instantiation-dependent,
|
|
|
|
// canonically-equivalent types differ in some irrelevant portion of inner
|
|
|
|
// type sugar. In such cases, we fail to form correct substitutions, eg:
|
|
|
|
//
|
|
|
|
// template<int N> void f(A<sizeof(N)> *, A<sizeof(N)> (*));
|
|
|
|
//
|
|
|
|
// We should instead canonicalize the non-instantiation-dependent parts,
|
|
|
|
// regardless of whether the type as a whole is dependent or instantiation
|
|
|
|
// dependent.
|
2012-12-18 22:30:41 +08:00
|
|
|
if (!T->isInstantiationDependentType() || T->isDependentType())
|
|
|
|
T = T.getCanonicalType();
|
|
|
|
else {
|
|
|
|
// Desugar any types that are purely sugar.
|
|
|
|
do {
|
|
|
|
// Don't desugar through template specialization types that aren't
|
|
|
|
// type aliases. We need to mangle the template arguments as written.
|
2018-07-31 03:24:48 +08:00
|
|
|
if (const TemplateSpecializationType *TST
|
2012-12-18 22:30:41 +08:00
|
|
|
= dyn_cast<TemplateSpecializationType>(T))
|
|
|
|
if (!TST->isTypeAlias())
|
|
|
|
break;
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
QualType Desugared
|
2012-12-18 22:30:41 +08:00
|
|
|
= T.getSingleStepDesugaredType(Context.getASTContext());
|
|
|
|
if (Desugared == T)
|
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
T = Desugared;
|
|
|
|
} while (true);
|
|
|
|
}
|
|
|
|
SplitQualType split = T.split();
|
|
|
|
Qualifiers quals = split.Quals;
|
|
|
|
const Type *ty = split.Ty;
|
|
|
|
|
2018-04-28 10:40:28 +08:00
|
|
|
bool isSubstitutable =
|
|
|
|
isTypeSubstitutable(quals, ty, Context.getASTContext());
|
2012-12-18 22:30:41 +08:00
|
|
|
if (isSubstitutable && mangleSubstitution(T))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If we're mangling a qualified array type, push the qualifiers to
|
|
|
|
// the element type.
|
|
|
|
if (quals && isa<ArrayType>(T)) {
|
|
|
|
ty = Context.getASTContext().getAsArrayType(T);
|
|
|
|
quals = Qualifiers();
|
|
|
|
|
|
|
|
// Note that we don't update T: we want to add the
|
|
|
|
// substitution at the original type.
|
|
|
|
}
|
|
|
|
|
2017-10-02 14:25:51 +08:00
|
|
|
if (quals || ty->isDependentAddressSpaceType()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
if (const DependentAddressSpaceType *DAST =
|
2017-10-02 14:25:51 +08:00
|
|
|
dyn_cast<DependentAddressSpaceType>(ty)) {
|
|
|
|
SplitQualType splitDAST = DAST->getPointeeType().split();
|
|
|
|
mangleQualifiers(splitDAST.Quals, DAST);
|
|
|
|
mangleType(QualType(splitDAST.Ty, 0));
|
|
|
|
} else {
|
|
|
|
mangleQualifiers(quals);
|
|
|
|
|
|
|
|
// Recurse: even if the qualified type isn't yet substitutable,
|
|
|
|
// the unqualified type might be.
|
|
|
|
mangleType(QualType(ty, 0));
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
} else {
|
|
|
|
switch (ty->getTypeClass()) {
|
|
|
|
#define ABSTRACT_TYPE(CLASS, PARENT)
|
|
|
|
#define NON_CANONICAL_TYPE(CLASS, PARENT) \
|
|
|
|
case Type::CLASS: \
|
|
|
|
llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
|
|
|
|
return;
|
|
|
|
#define TYPE(CLASS, PARENT) \
|
|
|
|
case Type::CLASS: \
|
|
|
|
mangleType(static_cast<const CLASS##Type*>(ty)); \
|
|
|
|
break;
|
2019-10-02 14:35:23 +08:00
|
|
|
#include "clang/AST/TypeNodes.inc"
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the substitution.
|
|
|
|
if (isSubstitutable)
|
|
|
|
addSubstitution(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
|
|
|
|
if (!mangleStandardSubstitution(ND))
|
|
|
|
mangleName(ND);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const BuiltinType *T) {
|
|
|
|
// <type> ::= <builtin-type>
|
|
|
|
// <builtin-type> ::= v # void
|
|
|
|
// ::= w # wchar_t
|
|
|
|
// ::= b # bool
|
|
|
|
// ::= c # char
|
|
|
|
// ::= a # signed char
|
|
|
|
// ::= h # unsigned char
|
|
|
|
// ::= s # short
|
|
|
|
// ::= t # unsigned short
|
|
|
|
// ::= i # int
|
|
|
|
// ::= j # unsigned int
|
|
|
|
// ::= l # long
|
|
|
|
// ::= m # unsigned long
|
|
|
|
// ::= x # long long, __int64
|
|
|
|
// ::= y # unsigned long long, __int64
|
|
|
|
// ::= n # __int128
|
2013-11-22 06:25:24 +08:00
|
|
|
// ::= o # unsigned __int128
|
2012-12-18 22:30:41 +08:00
|
|
|
// ::= f # float
|
|
|
|
// ::= d # double
|
|
|
|
// ::= e # long double, __float80
|
2016-05-09 16:52:33 +08:00
|
|
|
// ::= g # __float128
|
2012-12-18 22:30:41 +08:00
|
|
|
// UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
|
|
|
|
// UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
|
|
|
|
// UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
|
|
|
|
// ::= Dh # IEEE 754r half-precision floating point (16 bits)
|
2017-09-08 23:15:00 +08:00
|
|
|
// ::= DF <number> _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits);
|
2012-12-18 22:30:41 +08:00
|
|
|
// ::= Di # char32_t
|
|
|
|
// ::= Ds # char16_t
|
|
|
|
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
|
|
|
|
// ::= u <source-name> # vendor extended type
|
2016-04-08 21:40:33 +08:00
|
|
|
std::string type_name;
|
2012-12-18 22:30:41 +08:00
|
|
|
switch (T->getKind()) {
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::Void:
|
|
|
|
Out << 'v';
|
|
|
|
break;
|
|
|
|
case BuiltinType::Bool:
|
|
|
|
Out << 'b';
|
|
|
|
break;
|
|
|
|
case BuiltinType::Char_U:
|
|
|
|
case BuiltinType::Char_S:
|
|
|
|
Out << 'c';
|
|
|
|
break;
|
|
|
|
case BuiltinType::UChar:
|
|
|
|
Out << 'h';
|
|
|
|
break;
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
Out << 't';
|
|
|
|
break;
|
|
|
|
case BuiltinType::UInt:
|
|
|
|
Out << 'j';
|
|
|
|
break;
|
|
|
|
case BuiltinType::ULong:
|
|
|
|
Out << 'm';
|
|
|
|
break;
|
|
|
|
case BuiltinType::ULongLong:
|
|
|
|
Out << 'y';
|
|
|
|
break;
|
|
|
|
case BuiltinType::UInt128:
|
|
|
|
Out << 'o';
|
|
|
|
break;
|
|
|
|
case BuiltinType::SChar:
|
|
|
|
Out << 'a';
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
case BuiltinType::WChar_S:
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::WChar_U:
|
|
|
|
Out << 'w';
|
|
|
|
break;
|
2018-05-01 13:02:45 +08:00
|
|
|
case BuiltinType::Char8:
|
|
|
|
Out << "Du";
|
|
|
|
break;
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::Char16:
|
|
|
|
Out << "Ds";
|
|
|
|
break;
|
|
|
|
case BuiltinType::Char32:
|
|
|
|
Out << "Di";
|
|
|
|
break;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
Out << 's';
|
|
|
|
break;
|
|
|
|
case BuiltinType::Int:
|
|
|
|
Out << 'i';
|
|
|
|
break;
|
|
|
|
case BuiltinType::Long:
|
|
|
|
Out << 'l';
|
|
|
|
break;
|
|
|
|
case BuiltinType::LongLong:
|
|
|
|
Out << 'x';
|
|
|
|
break;
|
|
|
|
case BuiltinType::Int128:
|
|
|
|
Out << 'n';
|
|
|
|
break;
|
2017-09-08 23:15:00 +08:00
|
|
|
case BuiltinType::Float16:
|
|
|
|
Out << "DF16_";
|
|
|
|
break;
|
2018-06-05 00:07:52 +08:00
|
|
|
case BuiltinType::ShortAccum:
|
|
|
|
case BuiltinType::Accum:
|
|
|
|
case BuiltinType::LongAccum:
|
|
|
|
case BuiltinType::UShortAccum:
|
|
|
|
case BuiltinType::UAccum:
|
|
|
|
case BuiltinType::ULongAccum:
|
2018-06-14 22:53:51 +08:00
|
|
|
case BuiltinType::ShortFract:
|
|
|
|
case BuiltinType::Fract:
|
|
|
|
case BuiltinType::LongFract:
|
|
|
|
case BuiltinType::UShortFract:
|
|
|
|
case BuiltinType::UFract:
|
|
|
|
case BuiltinType::ULongFract:
|
|
|
|
case BuiltinType::SatShortAccum:
|
|
|
|
case BuiltinType::SatAccum:
|
|
|
|
case BuiltinType::SatLongAccum:
|
|
|
|
case BuiltinType::SatUShortAccum:
|
|
|
|
case BuiltinType::SatUAccum:
|
|
|
|
case BuiltinType::SatULongAccum:
|
|
|
|
case BuiltinType::SatShortFract:
|
|
|
|
case BuiltinType::SatFract:
|
|
|
|
case BuiltinType::SatLongFract:
|
|
|
|
case BuiltinType::SatUShortFract:
|
|
|
|
case BuiltinType::SatUFract:
|
|
|
|
case BuiltinType::SatULongFract:
|
2018-06-05 00:07:52 +08:00
|
|
|
llvm_unreachable("Fixed point types are disabled for c++");
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::Half:
|
|
|
|
Out << "Dh";
|
|
|
|
break;
|
|
|
|
case BuiltinType::Float:
|
|
|
|
Out << 'f';
|
|
|
|
break;
|
|
|
|
case BuiltinType::Double:
|
|
|
|
Out << 'd';
|
|
|
|
break;
|
2019-06-19 04:29:06 +08:00
|
|
|
case BuiltinType::LongDouble: {
|
2019-07-09 21:32:26 +08:00
|
|
|
const TargetInfo *TI = getASTContext().getLangOpts().OpenMP &&
|
|
|
|
getASTContext().getLangOpts().OpenMPIsDevice
|
|
|
|
? getASTContext().getAuxTargetInfo()
|
|
|
|
: &getASTContext().getTargetInfo();
|
|
|
|
Out << TI->getLongDoubleMangling();
|
2015-06-10 02:05:33 +08:00
|
|
|
break;
|
2019-06-19 04:29:06 +08:00
|
|
|
}
|
|
|
|
case BuiltinType::Float128: {
|
2019-07-09 21:32:26 +08:00
|
|
|
const TargetInfo *TI = getASTContext().getLangOpts().OpenMP &&
|
|
|
|
getASTContext().getLangOpts().OpenMPIsDevice
|
|
|
|
? getASTContext().getAuxTargetInfo()
|
|
|
|
: &getASTContext().getTargetInfo();
|
|
|
|
Out << TI->getFloat128Mangling();
|
2016-05-09 16:52:33 +08:00
|
|
|
break;
|
2019-06-19 04:29:06 +08:00
|
|
|
}
|
[ARM] Add __bf16 as new Bfloat16 C Type
Summary:
This patch upstreams support for a new storage only bfloat16 C type.
This type is used to implement primitive support for bfloat16 data, in
line with the Bfloat16 extension of the Armv8.6-a architecture, as
detailed here:
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a
The bfloat type, and its properties are specified in the Arm Architecture
Reference Manual:
https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
In detail this patch:
- introduces an opaque, storage-only C-type __bf16, which introduces a new bfloat IR type.
This is part of a patch series, starting with command-line and Bfloat16
assembly support. The subsequent patches will upstream intrinsics
support for BFloat16, followed by Matrix Multiplication and the
remaining Virtualization features of the armv8.6-a architecture.
The following people contributed to this patch:
- Luke Cheeseman
- Momchil Velikov
- Alexandros Lamprineas
- Luke Geeson
- Simon Tatham
- Ties Stuij
Reviewers: SjoerdMeijer, rjmccall, rsmith, liutianle, RKSimon, craig.topper, jfb, LukeGeeson, fpetrogalli
Reviewed By: SjoerdMeijer
Subscribers: labrinea, majnemer, asmith, dexonsmith, kristof.beyls, arphaman, danielkiss, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76077
2020-06-05 07:20:02 +08:00
|
|
|
case BuiltinType::BFloat16: {
|
|
|
|
const TargetInfo *TI = &getASTContext().getTargetInfo();
|
|
|
|
Out << TI->getBFloat16Mangling();
|
|
|
|
break;
|
|
|
|
}
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::NullPtr:
|
|
|
|
Out << "Dn";
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
#define BUILTIN_TYPE(Id, SingletonId)
|
|
|
|
#define PLACEHOLDER_TYPE(Id, SingletonId) \
|
|
|
|
case BuiltinType::Id:
|
|
|
|
#include "clang/AST/BuiltinTypes.def"
|
|
|
|
case BuiltinType::Dependent:
|
2016-06-30 17:40:38 +08:00
|
|
|
if (!NullOut)
|
|
|
|
llvm_unreachable("mangling a placeholder type");
|
|
|
|
break;
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::ObjCId:
|
|
|
|
Out << "11objc_object";
|
|
|
|
break;
|
|
|
|
case BuiltinType::ObjCClass:
|
|
|
|
Out << "10objc_class";
|
|
|
|
break;
|
|
|
|
case BuiltinType::ObjCSel:
|
|
|
|
Out << "13objc_selector";
|
|
|
|
break;
|
2016-04-08 21:40:33 +08:00
|
|
|
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
|
|
|
|
case BuiltinType::Id: \
|
|
|
|
type_name = "ocl_" #ImgType "_" #Suffix; \
|
|
|
|
Out << type_name.size() << type_name; \
|
2015-09-15 20:18:29 +08:00
|
|
|
break;
|
2016-04-13 16:33:41 +08:00
|
|
|
#include "clang/Basic/OpenCLImageTypes.def"
|
2015-09-15 20:18:29 +08:00
|
|
|
case BuiltinType::OCLSampler:
|
|
|
|
Out << "11ocl_sampler";
|
|
|
|
break;
|
|
|
|
case BuiltinType::OCLEvent:
|
|
|
|
Out << "9ocl_event";
|
|
|
|
break;
|
2015-09-15 19:18:52 +08:00
|
|
|
case BuiltinType::OCLClkEvent:
|
|
|
|
Out << "12ocl_clkevent";
|
|
|
|
break;
|
|
|
|
case BuiltinType::OCLQueue:
|
|
|
|
Out << "9ocl_queue";
|
|
|
|
break;
|
|
|
|
case BuiltinType::OCLReserveID:
|
|
|
|
Out << "13ocl_reserveid";
|
|
|
|
break;
|
2018-11-08 19:25:41 +08:00
|
|
|
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
|
|
|
|
case BuiltinType::Id: \
|
|
|
|
type_name = "ocl_" #ExtType; \
|
|
|
|
Out << type_name.size() << type_name; \
|
|
|
|
break;
|
|
|
|
#include "clang/Basic/OpenCLExtensionTypes.def"
|
2019-08-09 16:52:54 +08:00
|
|
|
// The SVE types are effectively target-specific. The mangling scheme
|
|
|
|
// is defined in the appendices to the Procedure Call Standard for the
|
|
|
|
// Arm Architecture.
|
2020-06-15 14:20:55 +08:00
|
|
|
#define SVE_VECTOR_TYPE(InternalName, MangledName, Id, SingletonId, NumEls, \
|
2020-06-16 04:48:13 +08:00
|
|
|
ElBits, IsSigned, IsFP, IsBF) \
|
2020-06-15 14:20:55 +08:00
|
|
|
case BuiltinType::Id: \
|
|
|
|
type_name = MangledName; \
|
|
|
|
Out << (type_name == InternalName ? "u" : "") << type_name.size() \
|
|
|
|
<< type_name; \
|
|
|
|
break;
|
|
|
|
#define SVE_PREDICATE_TYPE(InternalName, MangledName, Id, SingletonId, NumEls) \
|
|
|
|
case BuiltinType::Id: \
|
|
|
|
type_name = MangledName; \
|
|
|
|
Out << (type_name == InternalName ? "u" : "") << type_name.size() \
|
|
|
|
<< type_name; \
|
2019-08-09 16:52:54 +08:00
|
|
|
break;
|
|
|
|
#include "clang/Basic/AArch64SVEACLETypes.def"
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-02 06:18:03 +08:00
|
|
|
StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
|
|
|
|
switch (CC) {
|
|
|
|
case CC_C:
|
|
|
|
return "";
|
|
|
|
|
|
|
|
case CC_X86VectorCall:
|
|
|
|
case CC_X86Pascal:
|
2016-11-03 02:29:35 +08:00
|
|
|
case CC_X86RegCall:
|
2016-03-02 06:18:03 +08:00
|
|
|
case CC_AAPCS:
|
|
|
|
case CC_AAPCS_VFP:
|
2018-11-27 00:38:37 +08:00
|
|
|
case CC_AArch64VectorCall:
|
2016-03-02 06:18:03 +08:00
|
|
|
case CC_IntelOclBicc:
|
|
|
|
case CC_SpirFunction:
|
2016-06-30 17:06:33 +08:00
|
|
|
case CC_OpenCLKernel:
|
2016-03-17 02:00:46 +08:00
|
|
|
case CC_PreserveMost:
|
|
|
|
case CC_PreserveAll:
|
2016-03-02 06:18:03 +08:00
|
|
|
// FIXME: we should be mangling all of the above.
|
|
|
|
return "";
|
2016-03-03 14:39:32 +08:00
|
|
|
|
2018-12-21 09:40:29 +08:00
|
|
|
case CC_X86ThisCall:
|
|
|
|
// FIXME: To match mingw GCC, thiscall should only be mangled in when it is
|
|
|
|
// used explicitly. At this point, we don't have that much information in
|
|
|
|
// the AST, since clang tends to bake the convention into the canonical
|
|
|
|
// function type. thiscall only rarely used explicitly, so don't mangle it
|
|
|
|
// for now.
|
|
|
|
return "";
|
|
|
|
|
2018-12-15 07:42:59 +08:00
|
|
|
case CC_X86StdCall:
|
|
|
|
return "stdcall";
|
|
|
|
case CC_X86FastCall:
|
|
|
|
return "fastcall";
|
|
|
|
case CC_X86_64SysV:
|
|
|
|
return "sysv_abi";
|
|
|
|
case CC_Win64:
|
|
|
|
return "ms_abi";
|
2016-03-03 14:39:32 +08:00
|
|
|
case CC_Swift:
|
|
|
|
return "swiftcall";
|
2016-03-02 06:18:03 +08:00
|
|
|
}
|
|
|
|
llvm_unreachable("bad calling convention");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleExtFunctionInfo(const FunctionType *T) {
|
|
|
|
// Fast path.
|
|
|
|
if (T->getExtInfo() == FunctionType::ExtInfo())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Vendor-specific qualifiers are emitted in reverse alphabetical order.
|
|
|
|
// This will get more complicated in the future if we mangle other
|
|
|
|
// things here; but for now, since we mangle ns_returns_retained as
|
|
|
|
// a qualifier on the result type, we can get away with this:
|
|
|
|
StringRef CCQualifier = getCallingConvQualifierName(T->getExtInfo().getCC());
|
|
|
|
if (!CCQualifier.empty())
|
|
|
|
mangleVendorQualifier(CCQualifier);
|
|
|
|
|
|
|
|
// FIXME: regparm
|
|
|
|
// FIXME: noreturn
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
|
|
|
|
// Vendor-specific qualifiers are emitted in reverse alphabetical order.
|
|
|
|
|
|
|
|
// Note that these are *not* substitution candidates. Demanglers might
|
|
|
|
// have trouble with this if the parameter type is fully substituted.
|
|
|
|
|
2016-03-03 14:39:32 +08:00
|
|
|
switch (PI.getABI()) {
|
|
|
|
case ParameterABI::Ordinary:
|
|
|
|
break;
|
|
|
|
|
|
|
|
// All of these start with "swift", so they come before "ns_consumed".
|
|
|
|
case ParameterABI::SwiftContext:
|
|
|
|
case ParameterABI::SwiftErrorResult:
|
|
|
|
case ParameterABI::SwiftIndirectResult:
|
|
|
|
mangleVendorQualifier(getParameterABISpelling(PI.getABI()));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-03-02 06:18:03 +08:00
|
|
|
if (PI.isConsumed())
|
2016-03-03 14:39:32 +08:00
|
|
|
mangleVendorQualifier("ns_consumed");
|
2017-09-22 08:41:05 +08:00
|
|
|
|
|
|
|
if (PI.isNoEscape())
|
|
|
|
mangleVendorQualifier("noescape");
|
2016-03-02 06:18:03 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// <type> ::= <function-type>
|
|
|
|
// <function-type> ::= [<CV-qualifiers>] F [Y]
|
|
|
|
// <bare-function-type> [<ref-qualifier>] E
|
|
|
|
void CXXNameMangler::mangleType(const FunctionProtoType *T) {
|
2016-03-02 06:18:03 +08:00
|
|
|
mangleExtFunctionInfo(T);
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
|
|
|
|
// e.g. "const" in "int (A::*)() const".
|
2019-01-28 19:37:49 +08:00
|
|
|
mangleQualifiers(T->getMethodQuals());
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2016-10-26 09:05:54 +08:00
|
|
|
// Mangle instantiation-dependent exception-specification, if present,
|
|
|
|
// per cxx-abi-dev proposal on 2016-10-11.
|
|
|
|
if (T->hasInstantiationDependentExceptionSpec()) {
|
2018-05-03 11:58:32 +08:00
|
|
|
if (isComputedNoexcept(T->getExceptionSpecType())) {
|
2016-11-03 08:27:54 +08:00
|
|
|
Out << "DO";
|
2016-10-26 09:05:54 +08:00
|
|
|
mangleExpression(T->getNoexceptExpr());
|
|
|
|
Out << "E";
|
|
|
|
} else {
|
|
|
|
assert(T->getExceptionSpecType() == EST_Dynamic);
|
2016-11-03 08:27:54 +08:00
|
|
|
Out << "Dw";
|
2016-10-26 09:05:54 +08:00
|
|
|
for (auto ExceptTy : T->exceptions())
|
|
|
|
mangleType(ExceptTy);
|
|
|
|
Out << "E";
|
|
|
|
}
|
2018-05-03 11:58:32 +08:00
|
|
|
} else if (T->isNothrow()) {
|
2016-11-03 08:27:54 +08:00
|
|
|
Out << "Do";
|
2016-10-26 09:05:54 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'F';
|
|
|
|
|
|
|
|
// FIXME: We don't have enough information in the AST to produce the 'Y'
|
|
|
|
// encoding for extern "C" function types.
|
|
|
|
mangleBareFunctionType(T, /*MangleReturnType=*/true);
|
|
|
|
|
|
|
|
// Mangle the ref-qualifier, if present.
|
|
|
|
mangleRefQualifier(T->getRefQualifier());
|
|
|
|
|
|
|
|
Out << 'E';
|
|
|
|
}
|
2015-08-08 07:25:47 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
|
2015-08-08 07:25:47 +08:00
|
|
|
// Function types without prototypes can arise when mangling a function type
|
|
|
|
// within an overloadable function in C. We mangle these as the absence of any
|
|
|
|
// parameter types (not even an empty parameter list).
|
|
|
|
Out << 'F';
|
|
|
|
|
|
|
|
FunctionTypeDepthState saved = FunctionTypeDepth.push();
|
|
|
|
|
|
|
|
FunctionTypeDepth.enterResultType();
|
|
|
|
mangleType(T->getReturnType());
|
|
|
|
FunctionTypeDepth.leaveResultType();
|
|
|
|
|
|
|
|
FunctionTypeDepth.pop(saved);
|
|
|
|
Out << 'E';
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
2015-08-08 07:25:47 +08:00
|
|
|
|
2016-03-02 06:18:03 +08:00
|
|
|
void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
|
2015-12-03 05:58:08 +08:00
|
|
|
bool MangleReturnType,
|
|
|
|
const FunctionDecl *FD) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// Record that we're in a function type. See mangleFunctionParam
|
|
|
|
// for details on what we're trying to achieve here.
|
|
|
|
FunctionTypeDepthState saved = FunctionTypeDepth.push();
|
|
|
|
|
|
|
|
// <bare-function-type> ::= <signature type>+
|
|
|
|
if (MangleReturnType) {
|
|
|
|
FunctionTypeDepth.enterResultType();
|
2016-03-02 06:18:03 +08:00
|
|
|
|
|
|
|
// Mangle ns_returns_retained as an order-sensitive qualifier here.
|
2016-05-25 22:15:08 +08:00
|
|
|
if (Proto->getExtInfo().getProducesResult() && FD == nullptr)
|
2016-03-02 06:18:03 +08:00
|
|
|
mangleVendorQualifier("ns_returns_retained");
|
|
|
|
|
|
|
|
// Mangle the return type without any direct ARC ownership qualifiers.
|
|
|
|
QualType ReturnTy = Proto->getReturnType();
|
|
|
|
if (ReturnTy.getObjCLifetime()) {
|
|
|
|
auto SplitReturnTy = ReturnTy.split();
|
|
|
|
SplitReturnTy.Quals.removeObjCLifetime();
|
|
|
|
ReturnTy = getASTContext().getQualifiedType(SplitReturnTy);
|
|
|
|
}
|
|
|
|
mangleType(ReturnTy);
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
FunctionTypeDepth.leaveResultType();
|
|
|
|
}
|
|
|
|
|
2014-01-21 04:26:09 +08:00
|
|
|
if (Proto->getNumParams() == 0 && !Proto->isVariadic()) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <builtin-type> ::= v # void
|
|
|
|
Out << 'v';
|
|
|
|
|
|
|
|
FunctionTypeDepth.pop(saved);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-03 05:58:08 +08:00
|
|
|
assert(!FD || FD->getNumParams() == Proto->getNumParams());
|
|
|
|
for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) {
|
2016-03-02 06:18:03 +08:00
|
|
|
// Mangle extended parameter info as order-sensitive qualifiers here.
|
2016-05-25 22:15:08 +08:00
|
|
|
if (Proto->hasExtParameterInfos() && FD == nullptr) {
|
2016-03-02 06:18:03 +08:00
|
|
|
mangleExtParameterInfo(Proto->getExtParameterInfo(I));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mangle the type.
|
|
|
|
QualType ParamTy = Proto->getParamType(I);
|
2015-12-03 05:58:08 +08:00
|
|
|
mangleType(Context.getASTContext().getSignatureParameterType(ParamTy));
|
|
|
|
|
|
|
|
if (FD) {
|
|
|
|
if (auto *Attr = FD->getParamDecl(I)->getAttr<PassObjectSizeAttr>()) {
|
|
|
|
// Attr can only take 1 character, so we can hardcode the length below.
|
|
|
|
assert(Attr->getType() <= 9 && Attr->getType() >= 0);
|
2019-03-20 04:44:18 +08:00
|
|
|
if (Attr->isDynamic())
|
|
|
|
Out << "U25pass_dynamic_object_size" << Attr->getType();
|
|
|
|
else
|
|
|
|
Out << "U17pass_object_size" << Attr->getType();
|
2015-12-03 05:58:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
FunctionTypeDepth.pop(saved);
|
|
|
|
|
|
|
|
// <builtin-type> ::= z # ellipsis
|
|
|
|
if (Proto->isVariadic())
|
|
|
|
Out << 'z';
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= <class-enum-type>
|
|
|
|
// <class-enum-type> ::= <name>
|
|
|
|
void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
|
|
|
|
mangleName(T->getDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= <class-enum-type>
|
|
|
|
// <class-enum-type> ::= <name>
|
|
|
|
void CXXNameMangler::mangleType(const EnumType *T) {
|
|
|
|
mangleType(static_cast<const TagType*>(T));
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const RecordType *T) {
|
|
|
|
mangleType(static_cast<const TagType*>(T));
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const TagType *T) {
|
|
|
|
mangleName(T->getDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= <array-type>
|
|
|
|
// <array-type> ::= A <positive dimension number> _ <element type>
|
|
|
|
// ::= A [<dimension expression>] _ <element type>
|
|
|
|
void CXXNameMangler::mangleType(const ConstantArrayType *T) {
|
|
|
|
Out << 'A' << T->getSize() << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const VariableArrayType *T) {
|
|
|
|
Out << 'A';
|
|
|
|
// decayed vla types (size 0) will just be skipped.
|
|
|
|
if (T->getSizeExpr())
|
|
|
|
mangleExpression(T->getSizeExpr());
|
|
|
|
Out << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
|
|
|
|
Out << 'A';
|
|
|
|
mangleExpression(T->getSizeExpr());
|
|
|
|
Out << '_';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
|
|
|
|
Out << "A_";
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= <pointer-to-member-type>
|
|
|
|
// <pointer-to-member-type> ::= M <class type> <member type>
|
|
|
|
void CXXNameMangler::mangleType(const MemberPointerType *T) {
|
|
|
|
Out << 'M';
|
|
|
|
mangleType(QualType(T->getClass(), 0));
|
|
|
|
QualType PointeeType = T->getPointeeType();
|
|
|
|
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
|
|
|
|
mangleType(FPT);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Itanium C++ ABI 5.1.8:
|
|
|
|
//
|
|
|
|
// The type of a non-static member function is considered to be different,
|
|
|
|
// for the purposes of substitution, from the type of a namespace-scope or
|
|
|
|
// static member function whose type appears similar. The types of two
|
|
|
|
// non-static member functions are considered to be different, for the
|
|
|
|
// purposes of substitution, if the functions are members of different
|
2018-07-31 03:24:48 +08:00
|
|
|
// classes. In other words, for the purposes of substitution, the class of
|
|
|
|
// which the function is a member is considered part of the type of
|
2012-12-18 22:30:41 +08:00
|
|
|
// function.
|
|
|
|
|
|
|
|
// Given that we already substitute member function pointers as a
|
|
|
|
// whole, the net effect of this rule is just to unconditionally
|
|
|
|
// suppress substitution on the function type in a member pointer.
|
|
|
|
// We increment the SeqID here to emulate adding an entry to the
|
|
|
|
// substitution table.
|
|
|
|
++SeqID;
|
|
|
|
} else
|
|
|
|
mangleType(PointeeType);
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= <template-param>
|
|
|
|
void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(T->getDepth(), T->getIndex());
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= <template-param>
|
|
|
|
void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
|
|
|
|
// FIXME: not clear how to mangle this!
|
|
|
|
// template <class T...> class A {
|
|
|
|
// template <class U...> void foo(T(*)(U) x...);
|
|
|
|
// };
|
|
|
|
Out << "_SUBSTPACK_";
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= P <type> # pointer-to
|
|
|
|
void CXXNameMangler::mangleType(const PointerType *T) {
|
|
|
|
Out << 'P';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
|
|
|
|
Out << 'P';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= R <type> # reference-to
|
|
|
|
void CXXNameMangler::mangleType(const LValueReferenceType *T) {
|
|
|
|
Out << 'R';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= O <type> # rvalue reference-to (C++0x)
|
|
|
|
void CXXNameMangler::mangleType(const RValueReferenceType *T) {
|
|
|
|
Out << 'O';
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// <type> ::= C <type> # complex pair (C 2000)
|
|
|
|
void CXXNameMangler::mangleType(const ComplexType *T) {
|
|
|
|
Out << 'C';
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ARM's ABI for Neon vector types specifies that they should be mangled as
|
|
|
|
// if they are structs (to match ARM's initial implementation). The
|
|
|
|
// vector type must be one of the special types predefined by ARM.
|
|
|
|
void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
|
|
|
|
QualType EltType = T->getElementType();
|
|
|
|
assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");
|
2014-05-12 13:36:57 +08:00
|
|
|
const char *EltName = nullptr;
|
2012-12-18 22:30:41 +08:00
|
|
|
if (T->getVectorKind() == VectorType::NeonPolyVector) {
|
|
|
|
switch (cast<BuiltinType>(EltType)->getKind()) {
|
2014-03-29 23:09:45 +08:00
|
|
|
case BuiltinType::SChar:
|
|
|
|
case BuiltinType::UChar:
|
|
|
|
EltName = "poly8_t";
|
|
|
|
break;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
EltName = "poly16_t";
|
|
|
|
break;
|
[ARM] Add poly64_t on AArch32.
Summary:
The poly64 types are guarded with ifdefs for AArch64 only. This is wrong. This
was also incorrectly documented in the ACLE spec, but this has been rectified in
the latest release. See paragraph 13.1.2 "Vector data types":
https://developer.arm.com/docs/101028/latest
This patch was written by Alexandros Lamprineas.
Reviewers: ostannard, sdesmalen, fpetrogalli, labrinea, t.p.northover, LukeGeeson
Reviewed By: ostannard
Subscribers: pbarrio, LukeGeeson, kristof.beyls, danielkiss, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79711
2020-06-05 17:35:59 +08:00
|
|
|
case BuiltinType::LongLong:
|
2014-03-29 23:09:45 +08:00
|
|
|
case BuiltinType::ULongLong:
|
|
|
|
EltName = "poly64_t";
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
default: llvm_unreachable("unexpected Neon polynomial vector element type");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (cast<BuiltinType>(EltType)->getKind()) {
|
|
|
|
case BuiltinType::SChar: EltName = "int8_t"; break;
|
|
|
|
case BuiltinType::UChar: EltName = "uint8_t"; break;
|
|
|
|
case BuiltinType::Short: EltName = "int16_t"; break;
|
|
|
|
case BuiltinType::UShort: EltName = "uint16_t"; break;
|
|
|
|
case BuiltinType::Int: EltName = "int32_t"; break;
|
|
|
|
case BuiltinType::UInt: EltName = "uint32_t"; break;
|
|
|
|
case BuiltinType::LongLong: EltName = "int64_t"; break;
|
|
|
|
case BuiltinType::ULongLong: EltName = "uint64_t"; break;
|
2014-03-29 23:09:45 +08:00
|
|
|
case BuiltinType::Double: EltName = "float64_t"; break;
|
2012-12-18 22:30:41 +08:00
|
|
|
case BuiltinType::Float: EltName = "float32_t"; break;
|
[ARM] Add __bf16 as new Bfloat16 C Type
Summary:
This patch upstreams support for a new storage only bfloat16 C type.
This type is used to implement primitive support for bfloat16 data, in
line with the Bfloat16 extension of the Armv8.6-a architecture, as
detailed here:
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a
The bfloat type, and its properties are specified in the Arm Architecture
Reference Manual:
https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
In detail this patch:
- introduces an opaque, storage-only C-type __bf16, which introduces a new bfloat IR type.
This is part of a patch series, starting with command-line and Bfloat16
assembly support. The subsequent patches will upstream intrinsics
support for BFloat16, followed by Matrix Multiplication and the
remaining Virtualization features of the armv8.6-a architecture.
The following people contributed to this patch:
- Luke Cheeseman
- Momchil Velikov
- Alexandros Lamprineas
- Luke Geeson
- Simon Tatham
- Ties Stuij
Reviewers: SjoerdMeijer, rjmccall, rsmith, liutianle, RKSimon, craig.topper, jfb, LukeGeeson, fpetrogalli
Reviewed By: SjoerdMeijer
Subscribers: labrinea, majnemer, asmith, dexonsmith, kristof.beyls, arphaman, danielkiss, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76077
2020-06-05 07:20:02 +08:00
|
|
|
case BuiltinType::Half: EltName = "float16_t"; break;
|
|
|
|
case BuiltinType::BFloat16: EltName = "bfloat16_t"; break;
|
2013-08-01 17:23:19 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected Neon vector element type");
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
2014-05-12 13:36:57 +08:00
|
|
|
const char *BaseName = nullptr;
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned BitSize = (T->getNumElements() *
|
|
|
|
getASTContext().getTypeSize(EltType));
|
|
|
|
if (BitSize == 64)
|
|
|
|
BaseName = "__simd64_";
|
|
|
|
else {
|
|
|
|
assert(BitSize == 128 && "Neon vector type not 64 or 128 bits");
|
|
|
|
BaseName = "__simd128_";
|
|
|
|
}
|
|
|
|
Out << strlen(BaseName) + strlen(EltName);
|
|
|
|
Out << BaseName << EltName;
|
|
|
|
}
|
|
|
|
|
2018-07-14 03:46:04 +08:00
|
|
|
void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) {
|
|
|
|
DiagnosticsEngine &Diags = Context.getDiags();
|
|
|
|
unsigned DiagID = Diags.getCustomDiagID(
|
|
|
|
DiagnosticsEngine::Error,
|
|
|
|
"cannot mangle this dependent neon vector type yet");
|
|
|
|
Diags.Report(T->getAttributeLoc(), DiagID);
|
|
|
|
}
|
|
|
|
|
2013-08-01 17:23:19 +08:00
|
|
|
static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) {
|
|
|
|
switch (EltType->getKind()) {
|
|
|
|
case BuiltinType::SChar:
|
|
|
|
return "Int8";
|
|
|
|
case BuiltinType::Short:
|
|
|
|
return "Int16";
|
|
|
|
case BuiltinType::Int:
|
|
|
|
return "Int32";
|
2014-02-24 10:45:03 +08:00
|
|
|
case BuiltinType::Long:
|
2014-03-29 23:09:45 +08:00
|
|
|
case BuiltinType::LongLong:
|
2013-08-01 17:23:19 +08:00
|
|
|
return "Int64";
|
|
|
|
case BuiltinType::UChar:
|
|
|
|
return "Uint8";
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
return "Uint16";
|
|
|
|
case BuiltinType::UInt:
|
|
|
|
return "Uint32";
|
2014-02-24 10:45:03 +08:00
|
|
|
case BuiltinType::ULong:
|
2014-03-29 23:09:45 +08:00
|
|
|
case BuiltinType::ULongLong:
|
2013-08-01 17:23:19 +08:00
|
|
|
return "Uint64";
|
|
|
|
case BuiltinType::Half:
|
|
|
|
return "Float16";
|
|
|
|
case BuiltinType::Float:
|
|
|
|
return "Float32";
|
|
|
|
case BuiltinType::Double:
|
|
|
|
return "Float64";
|
[ARM] Add __bf16 as new Bfloat16 C Type
Summary:
This patch upstreams support for a new storage only bfloat16 C type.
This type is used to implement primitive support for bfloat16 data, in
line with the Bfloat16 extension of the Armv8.6-a architecture, as
detailed here:
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a
The bfloat type, and its properties are specified in the Arm Architecture
Reference Manual:
https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
In detail this patch:
- introduces an opaque, storage-only C-type __bf16, which introduces a new bfloat IR type.
This is part of a patch series, starting with command-line and Bfloat16
assembly support. The subsequent patches will upstream intrinsics
support for BFloat16, followed by Matrix Multiplication and the
remaining Virtualization features of the armv8.6-a architecture.
The following people contributed to this patch:
- Luke Cheeseman
- Momchil Velikov
- Alexandros Lamprineas
- Luke Geeson
- Simon Tatham
- Ties Stuij
Reviewers: SjoerdMeijer, rjmccall, rsmith, liutianle, RKSimon, craig.topper, jfb, LukeGeeson, fpetrogalli
Reviewed By: SjoerdMeijer
Subscribers: labrinea, majnemer, asmith, dexonsmith, kristof.beyls, arphaman, danielkiss, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76077
2020-06-05 07:20:02 +08:00
|
|
|
case BuiltinType::BFloat16:
|
|
|
|
return "BFloat16";
|
2013-08-01 17:23:19 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Unexpected vector element base type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AArch64's ABI for Neon vector types specifies that they should be mangled as
|
|
|
|
// the equivalent internal name. The vector type must be one of the special
|
|
|
|
// types predefined by ARM.
|
|
|
|
void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
|
|
|
|
QualType EltType = T->getElementType();
|
|
|
|
assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");
|
|
|
|
unsigned BitSize =
|
|
|
|
(T->getNumElements() * getASTContext().getTypeSize(EltType));
|
2013-08-01 18:30:11 +08:00
|
|
|
(void)BitSize; // Silence warning.
|
2013-08-01 17:23:19 +08:00
|
|
|
|
|
|
|
assert((BitSize == 64 || BitSize == 128) &&
|
|
|
|
"Neon vector type not 64 or 128 bits");
|
|
|
|
|
|
|
|
StringRef EltName;
|
|
|
|
if (T->getVectorKind() == VectorType::NeonPolyVector) {
|
|
|
|
switch (cast<BuiltinType>(EltType)->getKind()) {
|
|
|
|
case BuiltinType::UChar:
|
|
|
|
EltName = "Poly8";
|
|
|
|
break;
|
|
|
|
case BuiltinType::UShort:
|
|
|
|
EltName = "Poly16";
|
|
|
|
break;
|
2014-02-24 10:45:03 +08:00
|
|
|
case BuiltinType::ULong:
|
2015-05-14 16:18:05 +08:00
|
|
|
case BuiltinType::ULongLong:
|
2013-11-17 17:14:46 +08:00
|
|
|
EltName = "Poly64";
|
|
|
|
break;
|
2013-08-01 17:23:19 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected Neon polynomial vector element type");
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
EltName = mangleAArch64VectorBase(cast<BuiltinType>(EltType));
|
|
|
|
|
|
|
|
std::string TypeName =
|
2015-12-24 18:07:37 +08:00
|
|
|
("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str();
|
2013-08-01 17:23:19 +08:00
|
|
|
Out << TypeName.length() << TypeName;
|
|
|
|
}
|
2018-07-14 03:46:04 +08:00
|
|
|
void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) {
|
|
|
|
DiagnosticsEngine &Diags = Context.getDiags();
|
|
|
|
unsigned DiagID = Diags.getCustomDiagID(
|
|
|
|
DiagnosticsEngine::Error,
|
|
|
|
"cannot mangle this dependent neon vector type yet");
|
|
|
|
Diags.Report(T->getAttributeLoc(), DiagID);
|
|
|
|
}
|
2013-08-01 17:23:19 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// GNU extension: vector types
|
|
|
|
// <type> ::= <vector-type>
|
|
|
|
// <vector-type> ::= Dv <positive dimension number> _
|
|
|
|
// <extended element type>
|
|
|
|
// ::= Dv [<dimension expression>] _ <element type>
|
|
|
|
// <extended element type> ::= <element type>
|
|
|
|
// ::= p # AltiVec vector pixel
|
|
|
|
// ::= b # Altivec vector bool
|
|
|
|
void CXXNameMangler::mangleType(const VectorType *T) {
|
|
|
|
if ((T->getVectorKind() == VectorType::NeonVector ||
|
|
|
|
T->getVectorKind() == VectorType::NeonPolyVector)) {
|
2014-03-29 23:09:45 +08:00
|
|
|
llvm::Triple Target = getASTContext().getTargetInfo().getTriple();
|
2014-02-25 21:51:00 +08:00
|
|
|
llvm::Triple::ArchType Arch =
|
|
|
|
getASTContext().getTargetInfo().getTriple().getArch();
|
2014-05-24 20:51:25 +08:00
|
|
|
if ((Arch == llvm::Triple::aarch64 ||
|
2014-07-23 20:32:58 +08:00
|
|
|
Arch == llvm::Triple::aarch64_be) && !Target.isOSDarwin())
|
2013-08-01 17:23:19 +08:00
|
|
|
mangleAArch64NeonVectorType(T);
|
|
|
|
else
|
|
|
|
mangleNeonVectorType(T);
|
2012-12-18 22:30:41 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Out << "Dv" << T->getNumElements() << '_';
|
|
|
|
if (T->getVectorKind() == VectorType::AltiVecPixel)
|
|
|
|
Out << 'p';
|
|
|
|
else if (T->getVectorKind() == VectorType::AltiVecBool)
|
|
|
|
Out << 'b';
|
|
|
|
else
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
2018-07-14 03:46:04 +08:00
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const DependentVectorType *T) {
|
|
|
|
if ((T->getVectorKind() == VectorType::NeonVector ||
|
|
|
|
T->getVectorKind() == VectorType::NeonPolyVector)) {
|
|
|
|
llvm::Triple Target = getASTContext().getTargetInfo().getTriple();
|
|
|
|
llvm::Triple::ArchType Arch =
|
|
|
|
getASTContext().getTargetInfo().getTriple().getArch();
|
|
|
|
if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) &&
|
|
|
|
!Target.isOSDarwin())
|
|
|
|
mangleAArch64NeonVectorType(T);
|
|
|
|
else
|
|
|
|
mangleNeonVectorType(T);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << "Dv";
|
|
|
|
mangleExpression(T->getSizeExpr());
|
|
|
|
Out << '_';
|
|
|
|
if (T->getVectorKind() == VectorType::AltiVecPixel)
|
|
|
|
Out << 'p';
|
|
|
|
else if (T->getVectorKind() == VectorType::AltiVecBool)
|
|
|
|
Out << 'b';
|
|
|
|
else
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleType(const ExtVectorType *T) {
|
|
|
|
mangleType(static_cast<const VectorType*>(T));
|
|
|
|
}
|
|
|
|
void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
|
|
|
|
Out << "Dv";
|
|
|
|
mangleExpression(T->getSizeExpr());
|
|
|
|
Out << '_';
|
|
|
|
mangleType(T->getElementType());
|
2020-05-12 00:45:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const ConstantMatrixType *T) {
|
|
|
|
// Mangle matrix types using a vendor extended type qualifier:
|
|
|
|
// U<Len>matrix_type<Rows><Columns><element type>
|
|
|
|
StringRef VendorQualifier = "matrix_type";
|
|
|
|
Out << "U" << VendorQualifier.size() << VendorQualifier;
|
|
|
|
auto &ASTCtx = getASTContext();
|
|
|
|
unsigned BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType());
|
|
|
|
llvm::APSInt Rows(BitWidth);
|
|
|
|
Rows = T->getNumRows();
|
|
|
|
mangleIntegerLiteral(ASTCtx.getSizeType(), Rows);
|
|
|
|
llvm::APSInt Columns(BitWidth);
|
|
|
|
Columns = T->getNumColumns();
|
|
|
|
mangleIntegerLiteral(ASTCtx.getSizeType(), Columns);
|
|
|
|
mangleType(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) {
|
|
|
|
// U<Len>matrix_type<row expr><column expr><element type>
|
|
|
|
StringRef VendorQualifier = "matrix_type";
|
|
|
|
Out << "U" << VendorQualifier.size() << VendorQualifier;
|
|
|
|
mangleTemplateArg(T->getRowExpr());
|
|
|
|
mangleTemplateArg(T->getColumnExpr());
|
|
|
|
mangleType(T->getElementType());
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2017-10-02 14:25:51 +08:00
|
|
|
void CXXNameMangler::mangleType(const DependentAddressSpaceType *T) {
|
|
|
|
SplitQualType split = T->getPointeeType().split();
|
|
|
|
mangleQualifiers(split.Quals, T);
|
|
|
|
mangleType(QualType(split.Ty, 0));
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleType(const PackExpansionType *T) {
|
|
|
|
// <type> ::= Dp <type> # pack expansion (C++0x)
|
|
|
|
Out << "Dp";
|
|
|
|
mangleType(T->getPattern());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
|
|
|
|
mangleSourceName(T->getDecl()->getIdentifier());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const ObjCObjectType *T) {
|
2015-07-07 11:58:42 +08:00
|
|
|
// Treat __kindof as a vendor extended type qualifier.
|
|
|
|
if (T->isKindOfType())
|
|
|
|
Out << "U8__kindof";
|
|
|
|
|
2013-06-19 06:41:37 +08:00
|
|
|
if (!T->qual_empty()) {
|
|
|
|
// Mangle protocol qualifiers.
|
|
|
|
SmallString<64> QualStr;
|
|
|
|
llvm::raw_svector_ostream QualOS(QualStr);
|
|
|
|
QualOS << "objcproto";
|
2014-03-17 23:55:30 +08:00
|
|
|
for (const auto *I : T->quals()) {
|
|
|
|
StringRef name = I->getName();
|
2013-06-19 06:41:37 +08:00
|
|
|
QualOS << name.size() << name;
|
|
|
|
}
|
|
|
|
Out << 'U' << QualStr.size() << QualStr;
|
|
|
|
}
|
2015-07-07 11:58:42 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleType(T->getBaseType());
|
2015-07-07 11:58:42 +08:00
|
|
|
|
|
|
|
if (T->isSpecialized()) {
|
|
|
|
// Mangle type arguments as I <type>+ E
|
|
|
|
Out << 'I';
|
|
|
|
for (auto typeArg : T->getTypeArgs())
|
|
|
|
mangleType(typeArg);
|
|
|
|
Out << 'E';
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const BlockPointerType *T) {
|
|
|
|
Out << "U13block_pointer";
|
|
|
|
mangleType(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const InjectedClassNameType *T) {
|
|
|
|
// Mangle injected class name types as if the user had written the
|
|
|
|
// specialization out fully. It may not actually be possible to see
|
|
|
|
// this mangling, though.
|
|
|
|
mangleType(T->getInjectedSpecializationType());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
|
|
|
|
if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
|
2016-06-30 17:40:38 +08:00
|
|
|
mangleTemplateName(TD, T->getArgs(), T->getNumArgs());
|
2012-12-18 22:30:41 +08:00
|
|
|
} else {
|
|
|
|
if (mangleSubstitution(QualType(T, 0)))
|
|
|
|
return;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleTemplatePrefix(T->getTemplateName());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// FIXME: GCC does not appear to mangle the template arguments when
|
|
|
|
// the template in question is a dependent template name. Should we
|
|
|
|
// emulate that badness?
|
|
|
|
mangleTemplateArgs(T->getArgs(), T->getNumArgs());
|
|
|
|
addSubstitution(QualType(T, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const DependentNameType *T) {
|
2014-04-10 08:49:24 +08:00
|
|
|
// Proposal by cxx-abi-dev, 2014-03-26
|
|
|
|
// <class-enum-type> ::= <name> # non-dependent or dependent type name or
|
|
|
|
// # dependent elaborated type specifier using
|
2014-04-10 08:59:44 +08:00
|
|
|
// # 'typename'
|
2014-04-10 08:49:24 +08:00
|
|
|
// ::= Ts <name> # dependent elaborated type specifier using
|
2014-04-10 08:59:44 +08:00
|
|
|
// # 'struct' or 'class'
|
2014-04-10 08:49:24 +08:00
|
|
|
// ::= Tu <name> # dependent elaborated type specifier using
|
2014-04-10 08:59:44 +08:00
|
|
|
// # 'union'
|
2014-04-10 08:49:24 +08:00
|
|
|
// ::= Te <name> # dependent elaborated type specifier using
|
2014-04-10 08:59:44 +08:00
|
|
|
// # 'enum'
|
2014-04-10 08:49:24 +08:00
|
|
|
switch (T->getKeyword()) {
|
2017-01-21 02:50:12 +08:00
|
|
|
case ETK_None:
|
2014-04-10 08:49:24 +08:00
|
|
|
case ETK_Typename:
|
|
|
|
break;
|
|
|
|
case ETK_Struct:
|
|
|
|
case ETK_Class:
|
|
|
|
case ETK_Interface:
|
|
|
|
Out << "Ts";
|
|
|
|
break;
|
|
|
|
case ETK_Union:
|
|
|
|
Out << "Tu";
|
|
|
|
break;
|
|
|
|
case ETK_Enum:
|
|
|
|
Out << "Te";
|
|
|
|
break;
|
|
|
|
}
|
2014-04-15 13:51:25 +08:00
|
|
|
// Typename types are always nested
|
|
|
|
Out << 'N';
|
2012-12-18 22:30:41 +08:00
|
|
|
manglePrefix(T->getQualifier());
|
2014-04-10 08:49:24 +08:00
|
|
|
mangleSourceName(T->getIdentifier());
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
|
|
|
|
// Dependently-scoped template types are nested if they have a prefix.
|
|
|
|
Out << 'N';
|
|
|
|
|
|
|
|
// TODO: avoid making this TemplateName.
|
|
|
|
TemplateName Prefix =
|
|
|
|
getASTContext().getDependentTemplateName(T->getQualifier(),
|
|
|
|
T->getIdentifier());
|
|
|
|
mangleTemplatePrefix(Prefix);
|
|
|
|
|
|
|
|
// FIXME: GCC does not appear to mangle the template arguments when
|
|
|
|
// the template in question is a dependent template name. Should we
|
|
|
|
// emulate that badness?
|
2018-07-31 03:24:48 +08:00
|
|
|
mangleTemplateArgs(T->getArgs(), T->getNumArgs());
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const TypeOfType *T) {
|
|
|
|
// FIXME: this is pretty unsatisfactory, but there isn't an obvious
|
|
|
|
// "extension with parameters" mangling.
|
|
|
|
Out << "u6typeof";
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const TypeOfExprType *T) {
|
|
|
|
// FIXME: this is pretty unsatisfactory, but there isn't an obvious
|
|
|
|
// "extension with parameters" mangling.
|
|
|
|
Out << "u6typeof";
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const DecltypeType *T) {
|
|
|
|
Expr *E = T->getUnderlyingExpr();
|
|
|
|
|
|
|
|
// type ::= Dt <expression> E # decltype of an id-expression
|
|
|
|
// # or class member access
|
|
|
|
// ::= DT <expression> E # decltype of an expression
|
|
|
|
|
|
|
|
// This purports to be an exhaustive list of id-expressions and
|
|
|
|
// class member accesses. Note that we do not ignore parentheses;
|
|
|
|
// parentheses change the semantics of decltype for these
|
|
|
|
// expressions (and cause the mangler to use the other form).
|
|
|
|
if (isa<DeclRefExpr>(E) ||
|
|
|
|
isa<MemberExpr>(E) ||
|
|
|
|
isa<UnresolvedLookupExpr>(E) ||
|
|
|
|
isa<DependentScopeDeclRefExpr>(E) ||
|
|
|
|
isa<CXXDependentScopeMemberExpr>(E) ||
|
|
|
|
isa<UnresolvedMemberExpr>(E))
|
|
|
|
Out << "Dt";
|
|
|
|
else
|
|
|
|
Out << "DT";
|
|
|
|
mangleExpression(E);
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const UnaryTransformType *T) {
|
|
|
|
// If this is dependent, we need to record that. If not, we simply
|
|
|
|
// mangle it as the underlying type since they are equivalent.
|
|
|
|
if (T->isDependentType()) {
|
|
|
|
Out << 'U';
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
switch (T->getUTTKind()) {
|
|
|
|
case UnaryTransformType::EnumUnderlyingType:
|
|
|
|
Out << "3eut";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-08 08:34:15 +08:00
|
|
|
mangleType(T->getBaseType());
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const AutoType *T) {
|
2018-04-28 10:40:28 +08:00
|
|
|
assert(T->getDeducedType().isNull() &&
|
|
|
|
"Deduced AutoType shouldn't be handled here!");
|
|
|
|
assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType &&
|
|
|
|
"shouldn't need to mangle __auto_type!");
|
|
|
|
// <builtin-type> ::= Da # auto
|
|
|
|
// ::= Dc # decltype(auto)
|
|
|
|
Out << (T->isDecltypeAuto() ? "Dc" : "Da");
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2017-01-27 04:40:47 +08:00
|
|
|
void CXXNameMangler::mangleType(const DeducedTemplateSpecializationType *T) {
|
|
|
|
// FIXME: This is not the right mangling. We also need to include a scope
|
|
|
|
// here in some cases.
|
|
|
|
QualType D = T->getDeducedType();
|
|
|
|
if (D.isNull())
|
|
|
|
mangleUnscopedTemplateName(T->getTemplateName(), nullptr);
|
|
|
|
else
|
|
|
|
mangleType(D);
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleType(const AtomicType *T) {
|
2014-03-10 01:09:28 +08:00
|
|
|
// <type> ::= U <source-name> <type> # vendor extended type qualifier
|
2012-12-18 22:30:41 +08:00
|
|
|
// (Until there's a standardized mangling...)
|
|
|
|
Out << "U7_Atomic";
|
|
|
|
mangleType(T->getValueType());
|
|
|
|
}
|
|
|
|
|
2016-01-09 20:53:17 +08:00
|
|
|
void CXXNameMangler::mangleType(const PipeType *T) {
|
|
|
|
// Pipe type mangling rules are described in SPIR 2.0 specification
|
|
|
|
// A.1 Data types and A.3 Summary of changes
|
|
|
|
// <type> ::= 8ocl_pipe
|
|
|
|
Out << "8ocl_pipe";
|
|
|
|
}
|
|
|
|
|
2020-04-18 01:44:19 +08:00
|
|
|
void CXXNameMangler::mangleType(const ExtIntType *T) {
|
|
|
|
Out << "U7_ExtInt";
|
|
|
|
llvm::APSInt BW(32, true);
|
|
|
|
BW = T->getNumBits();
|
|
|
|
TemplateArgument TA(Context.getASTContext(), BW, getASTContext().IntTy);
|
|
|
|
mangleTemplateArgs(&TA, 1);
|
|
|
|
if (T->isUnsigned())
|
|
|
|
Out << "j";
|
|
|
|
else
|
|
|
|
Out << "i";
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleType(const DependentExtIntType *T) {
|
|
|
|
Out << "U7_ExtInt";
|
|
|
|
TemplateArgument TA(T->getNumBitsExpr());
|
|
|
|
mangleTemplateArgs(&TA, 1);
|
|
|
|
if (T->isUnsigned())
|
|
|
|
Out << "j";
|
|
|
|
else
|
|
|
|
Out << "i";
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleIntegerLiteral(QualType T,
|
|
|
|
const llvm::APSInt &Value) {
|
|
|
|
// <expr-primary> ::= L <type> <value number> E # integer literal
|
|
|
|
Out << 'L';
|
|
|
|
|
|
|
|
mangleType(T);
|
|
|
|
if (T->isBooleanType()) {
|
|
|
|
// Boolean values are encoded as 0/1.
|
|
|
|
Out << (Value.getBoolValue() ? '1' : '0');
|
|
|
|
} else {
|
|
|
|
mangleNumber(Value);
|
|
|
|
}
|
|
|
|
Out << 'E';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-02-14 21:23:54 +08:00
|
|
|
void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
|
|
|
|
// Ignore member expressions involving anonymous unions.
|
|
|
|
while (const auto *RT = Base->getType()->getAs<RecordType>()) {
|
|
|
|
if (!RT->getDecl()->isAnonymousStructOrUnion())
|
|
|
|
break;
|
|
|
|
const auto *ME = dyn_cast<MemberExpr>(Base);
|
|
|
|
if (!ME)
|
|
|
|
break;
|
|
|
|
Base = ME->getBase();
|
|
|
|
IsArrow = ME->isArrow();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Base->isImplicitCXXThis()) {
|
|
|
|
// Note: GCC mangles member expressions to the implicit 'this' as
|
|
|
|
// *this., whereas we represent them as this->. The Itanium C++ ABI
|
|
|
|
// does not specify anything here, so we follow GCC.
|
|
|
|
Out << "dtdefpT";
|
|
|
|
} else {
|
|
|
|
Out << (IsArrow ? "pt" : "dt");
|
|
|
|
mangleExpression(Base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
/// Mangles a member expression.
|
|
|
|
void CXXNameMangler::mangleMemberExpr(const Expr *base,
|
|
|
|
bool isArrow,
|
|
|
|
NestedNameSpecifier *qualifier,
|
|
|
|
NamedDecl *firstQualifierLookup,
|
|
|
|
DeclarationName member,
|
2016-10-25 04:47:04 +08:00
|
|
|
const TemplateArgumentLoc *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs,
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned arity) {
|
|
|
|
// <expression> ::= dt <expression> <unresolved-name>
|
|
|
|
// ::= pt <expression> <unresolved-name>
|
2015-02-14 21:23:54 +08:00
|
|
|
if (base)
|
|
|
|
mangleMemberExprBase(base, isArrow);
|
2016-10-25 04:47:04 +08:00
|
|
|
mangleUnresolvedName(qualifier, member, TemplateArgs, NumTemplateArgs, arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Look at the callee of the given call expression and determine if
|
|
|
|
/// it's a parenthesized id-expression which would have triggered ADL
|
|
|
|
/// otherwise.
|
|
|
|
static bool isParenthesizedADLCallee(const CallExpr *call) {
|
|
|
|
const Expr *callee = call->getCallee();
|
|
|
|
const Expr *fn = callee->IgnoreParens();
|
|
|
|
|
|
|
|
// Must be parenthesized. IgnoreParens() skips __extension__ nodes,
|
|
|
|
// too, but for those to appear in the callee, it would have to be
|
|
|
|
// parenthesized.
|
|
|
|
if (callee == fn) return false;
|
|
|
|
|
|
|
|
// Must be an unresolved lookup.
|
|
|
|
const UnresolvedLookupExpr *lookup = dyn_cast<UnresolvedLookupExpr>(fn);
|
|
|
|
if (!lookup) return false;
|
|
|
|
|
|
|
|
assert(!lookup->requiresADL());
|
|
|
|
|
|
|
|
// Must be an unqualified lookup.
|
|
|
|
if (lookup->getQualifier()) return false;
|
|
|
|
|
|
|
|
// Must not have found a class member. Note that if one is a class
|
|
|
|
// member, they're all class members.
|
|
|
|
if (lookup->getNumDecls() > 0 &&
|
|
|
|
(*lookup->decls_begin())->isCXXClassMember())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Otherwise, ADL would have been triggered.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-23 12:27:55 +08:00
|
|
|
void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding) {
|
|
|
|
const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
|
|
|
|
Out << CastEncoding;
|
|
|
|
mangleType(ECE->getType());
|
|
|
|
mangleExpression(ECE->getSubExpr());
|
|
|
|
}
|
|
|
|
|
2015-02-05 14:15:50 +08:00
|
|
|
void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) {
|
|
|
|
if (auto *Syntactic = InitList->getSyntacticForm())
|
|
|
|
InitList = Syntactic;
|
|
|
|
for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
|
|
|
|
mangleExpression(InitList->getInit(i));
|
|
|
|
}
|
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
void CXXNameMangler::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:
|
|
|
|
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);
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(PD->getDepth(), PD->getIndex());
|
2019-05-22 04:10:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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
|
2014-09-23 12:27:55 +08:00
|
|
|
// ::= 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)
|
2012-12-18 22:30:41 +08:00
|
|
|
// ::= 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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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:
|
2015-06-10 08:27:52 +08:00
|
|
|
case Expr::DesignatedInitUpdateExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::ImplicitValueInitExprClass:
|
2016-12-12 10:53:20 +08:00
|
|
|
case Expr::ArrayInitLoopExprClass:
|
|
|
|
case Expr::ArrayInitIndexExprClass:
|
2015-06-10 08:27:52 +08:00
|
|
|
case Expr::NoInitExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::ParenListExprClass:
|
|
|
|
case Expr::LambdaExprClass:
|
2013-04-16 15:28:30 +08:00
|
|
|
case Expr::MSPropertyRefExprClass:
|
2015-11-25 20:01:00 +08:00
|
|
|
case Expr::MSPropertySubscriptExprClass:
|
[AST] Add RecoveryExpr to retain expressions on semantic errors
Normally clang avoids creating expressions when it encounters semantic
errors, even if the parser knows which expression to produce.
This works well for the compiler. However, this is not ideal for
source-level tools that have to deal with broken code, e.g. clangd is
not able to provide navigation features even for names that compiler
knows how to resolve.
The new RecoveryExpr aims to capture the minimal set of information
useful for the tools that need to deal with incorrect code:
source range of the expression being dropped,
subexpressions of the expression.
We aim to make constructing RecoveryExprs as simple as possible to
ensure writing code to avoid dropping expressions is easy.
Producing RecoveryExprs can result in new code paths being taken in the
frontend. In particular, clang can produce some new diagnostics now and
we aim to suppress bogus ones based on Expr::containsErrors.
We deliberately produce RecoveryExprs only in the parser for now to
minimize the code affected by this patch. Producing RecoveryExprs in
Sema potentially allows to preserve more information (e.g. type of an
expression), but also results in more code being affected. E.g.
SFINAE checks will have to take presence of RecoveryExprs into account.
Initial implementation only works in C++ mode, as it relies on compiler
postponing diagnostics on dependent expressions. C and ObjC often do not
do this, so they require more work to make sure we do not produce too
many bogus diagnostics on the new expressions.
See documentation of RecoveryExpr for more details.
original patch from Ilya
This change is based on https://reviews.llvm.org/D61722
Reviewers: sammccall, rsmith
Reviewed By: sammccall, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69330
2020-03-19 23:30:40 +08:00
|
|
|
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
|
|
|
|
case Expr::RecoveryExprClass:
|
2015-08-25 22:24:04 +08:00
|
|
|
case Expr::OMPArraySectionExprClass:
|
[OPENMP50]Add basic support for array-shaping operation.
Summary:
Added basic representation and parsing/sema handling of array-shaping
operations. Array shaping expression is an expression of form ([s0]..[sn])base,
where s0, ..., sn must be a positive integer, base - a pointer. This
expression is a kind of cast operation that converts pointer expression
into an array-like kind of expression.
Reviewers: rjmccall, rsmith, jdoerfert
Subscribers: guansong, arphaman, cfe-commits, caomhin, kkwli0
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74144
2020-02-05 22:33:05 +08:00
|
|
|
case Expr::OMPArrayShapingExprClass:
|
2020-04-02 03:06:38 +08:00
|
|
|
case Expr::OMPIteratorExprClass:
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
case Expr::CXXInheritedCtorInitExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
llvm_unreachable("unexpected statement kind");
|
|
|
|
|
2018-10-31 11:48:47 +08:00
|
|
|
case Expr::ConstantExprClass:
|
|
|
|
E = cast<ConstantExpr>(E)->getSubExpr();
|
|
|
|
goto recurse;
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// 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:
|
2016-07-16 08:35:23 +08:00
|
|
|
case Expr::ObjCAvailabilityCheckExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::OffsetOfExprClass:
|
|
|
|
case Expr::PredefinedExprClass:
|
|
|
|
case Expr::ShuffleVectorExprClass:
|
2013-09-18 11:29:45 +08:00
|
|
|
case Expr::ConvertVectorExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::StmtExprClass:
|
|
|
|
case Expr::TypeTraitExprClass:
|
2020-01-18 15:11:43 +08:00
|
|
|
case Expr::RequiresExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::ArrayTypeTraitExprClass:
|
|
|
|
case Expr::ExpressionTraitExprClass:
|
|
|
|
case Expr::VAArgExprClass:
|
|
|
|
case Expr::CUDAKernelCallExprClass:
|
|
|
|
case Expr::AsTypeExprClass:
|
|
|
|
case Expr::PseudoObjectExprClass:
|
|
|
|
case Expr::AtomicExprClass:
|
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
2019-05-17 05:04:15 +08:00
|
|
|
case Expr::SourceLocExprClass:
|
2018-06-21 01:19:40 +08:00
|
|
|
case Expr::FixedPointLiteralClass:
|
2019-07-03 02:28:13 +08:00
|
|
|
case Expr::BuiltinBitCastExprClass:
|
2012-12-18 22:30:41 +08:00
|
|
|
{
|
2016-06-30 17:40:38 +08:00
|
|
|
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();
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-09-25 00:28:40 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// 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";
|
2015-02-05 14:15:50 +08:00
|
|
|
mangleInitListElements(cast<InitListExpr>(E));
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << "E";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-08-24 06:12:08 +08:00
|
|
|
case Expr::DesignatedInitExprClass: {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CXXDefaultArgExprClass:
|
|
|
|
mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
|
|
|
|
break;
|
|
|
|
|
2013-04-21 06:23:05 +08:00
|
|
|
case Expr::CXXDefaultInitExprClass:
|
|
|
|
mangleExpression(cast<CXXDefaultInitExpr>(E)->getExpr(), Arity);
|
|
|
|
break;
|
|
|
|
|
2013-06-13 06:31:48 +08:00
|
|
|
case Expr::CXXStdInitializerListExprClass:
|
|
|
|
mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity);
|
|
|
|
break;
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
2015-02-20 05:41:48 +08:00
|
|
|
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);
|
2012-12-18 22:30:41 +08:00
|
|
|
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.
|
2015-02-05 14:15:50 +08:00
|
|
|
mangleInitListElements(cast<InitListExpr>(Init));
|
2012-12-18 22:30:41 +08:00
|
|
|
} else
|
|
|
|
mangleExpression(Init);
|
|
|
|
}
|
|
|
|
Out << 'E';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-02-14 21:23:54 +08:00
|
|
|
case Expr::CXXPseudoDestructorExprClass: {
|
|
|
|
const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
|
|
|
|
if (const Expr *Base = PDE->getBase())
|
|
|
|
mangleMemberExprBase(Base, PDE->isArrow());
|
2015-02-19 10:16:16 +08:00
|
|
|
NestedNameSpecifier *Qualifier = PDE->getQualifier();
|
|
|
|
if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
|
|
|
|
if (Qualifier) {
|
|
|
|
mangleUnresolvedPrefix(Qualifier,
|
2019-07-16 12:46:31 +08:00
|
|
|
/*recursive=*/true);
|
2015-02-19 10:16:16 +08:00
|
|
|
mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
|
|
|
|
Out << 'E';
|
|
|
|
} else {
|
|
|
|
Out << "sr";
|
|
|
|
if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
} else if (Qualifier) {
|
|
|
|
mangleUnresolvedPrefix(Qualifier);
|
|
|
|
}
|
2015-02-14 21:23:54 +08:00
|
|
|
// <base-unresolved-name> ::= dn <destructor-name>
|
|
|
|
Out << "dn";
|
2015-02-18 10:28:01 +08:00
|
|
|
QualType DestroyedType = PDE->getDestroyedType();
|
2015-02-19 10:16:16 +08:00
|
|
|
mangleUnresolvedTypeOrSimpleId(DestroyedType);
|
2015-02-14 21:23:54 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::MemberExprClass: {
|
|
|
|
const MemberExpr *ME = cast<MemberExpr>(E);
|
|
|
|
mangleMemberExpr(ME->getBase(), ME->isArrow(),
|
2014-05-12 13:36:57 +08:00
|
|
|
ME->getQualifier(), nullptr,
|
2016-10-25 04:47:04 +08:00
|
|
|
ME->getMemberDecl()->getDeclName(),
|
|
|
|
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
|
|
|
|
Arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::UnresolvedMemberExprClass: {
|
|
|
|
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
|
2015-05-22 02:28:18 +08:00
|
|
|
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
|
|
|
|
ME->isArrow(), ME->getQualifier(), nullptr,
|
2016-10-25 04:47:04 +08:00
|
|
|
ME->getMemberName(),
|
|
|
|
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
|
|
|
|
Arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::CXXDependentScopeMemberExprClass: {
|
|
|
|
const CXXDependentScopeMemberExpr *ME
|
|
|
|
= cast<CXXDependentScopeMemberExpr>(E);
|
2015-05-22 02:28:18 +08:00
|
|
|
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
|
|
|
|
ME->isArrow(), ME->getQualifier(),
|
|
|
|
ME->getFirstQualifierFoundInScope(),
|
2016-10-25 04:47:04 +08:00
|
|
|
ME->getMember(),
|
|
|
|
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
|
|
|
|
Arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::UnresolvedLookupExprClass: {
|
|
|
|
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
|
2016-10-25 04:47:04 +08:00
|
|
|
mangleUnresolvedName(ULE->getQualifier(), ULE->getName(),
|
|
|
|
ULE->getTemplateArgs(), ULE->getNumTemplateArgs(),
|
|
|
|
Arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::CXXUnresolvedConstructExprClass: {
|
|
|
|
const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
|
|
|
|
unsigned N = CE->arg_size();
|
|
|
|
|
2017-08-24 06:12:08 +08:00
|
|
|
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";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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: {
|
2015-02-05 14:15:50 +08:00
|
|
|
const auto *CE = cast<CXXConstructExpr>(E);
|
2015-02-05 15:02:11 +08:00
|
|
|
if (!CE->isListInitialization() || CE->isStdInitListInitialization()) {
|
2015-02-05 14:15:50 +08:00
|
|
|
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);
|
2012-12-18 22:30:41 +08:00
|
|
|
unsigned N = CE->getNumArgs();
|
2015-02-05 14:15:50 +08:00
|
|
|
bool List = CE->isListInitialization();
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2015-02-05 14:15:50 +08:00
|
|
|
if (List)
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << "tl";
|
|
|
|
else
|
|
|
|
Out << "cv";
|
|
|
|
mangleType(CE->getType());
|
2015-02-05 14:15:50 +08:00
|
|
|
if (!List && N != 1)
|
|
|
|
Out << '_';
|
2015-02-05 15:02:11 +08:00
|
|
|
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);
|
|
|
|
}
|
2015-02-05 14:15:50 +08:00
|
|
|
if (List || N != 1)
|
|
|
|
Out << 'E';
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::CXXScalarValueInitExprClass:
|
2015-02-05 14:15:50 +08:00
|
|
|
Out << "cv";
|
2012-12-18 22:30:41 +08:00
|
|
|
mangleType(E->getType());
|
2015-02-05 14:15:50 +08:00
|
|
|
Out << "_E";
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Expr::CXXNoexceptExprClass:
|
|
|
|
Out << "nx";
|
|
|
|
mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Expr::UnaryExprOrTypeTraitExprClass: {
|
|
|
|
const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
if (!SAE->isInstantiationDependent()) {
|
|
|
|
// Itanium C++ ABI:
|
2018-07-31 03:24:48 +08:00
|
|
|
// If the operand of a sizeof or alignof operator is not
|
|
|
|
// instantiation-dependent it is encoded as an integer literal
|
2012-12-18 22:30:41 +08:00
|
|
|
// reflecting the result of the operator.
|
|
|
|
//
|
2018-07-31 03:24:48 +08:00
|
|
|
// If the result of the operator is implicitly converted to a known
|
|
|
|
// integer type, that type is used for the literal; otherwise, the type
|
2012-12-18 22:30:41 +08:00
|
|
|
// of std::size_t or std::ptrdiff_t is used.
|
2018-07-31 03:24:48 +08:00
|
|
|
QualType T = (ImplicitlyConvertedToType.isNull() ||
|
2012-12-18 22:30:41 +08:00
|
|
|
!ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
|
|
|
|
: ImplicitlyConvertedToType;
|
|
|
|
llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());
|
|
|
|
mangleIntegerLiteral(T, V);
|
|
|
|
break;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
switch(SAE->getKind()) {
|
|
|
|
case UETT_SizeOf:
|
|
|
|
Out << 's';
|
|
|
|
break;
|
2018-10-27 03:26:45 +08:00
|
|
|
case UETT_PreferredAlignOf:
|
2012-12-18 22:30:41 +08:00
|
|
|
case UETT_AlignOf:
|
|
|
|
Out << 'a';
|
|
|
|
break;
|
2015-07-02 11:40:19 +08:00
|
|
|
case UETT_VecStep: {
|
2012-12-18 22:30:41 +08:00
|
|
|
DiagnosticsEngine &Diags = Context.getDiags();
|
|
|
|
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
|
|
|
|
"cannot yet mangle vec_step expression");
|
2015-07-02 11:40:19 +08:00
|
|
|
Diags.Report(DiagID);
|
|
|
|
return;
|
|
|
|
}
|
2019-05-30 01:04:48 +08:00
|
|
|
case UETT_OpenMPRequiredSimdAlign: {
|
2015-07-02 11:40:19 +08:00
|
|
|
DiagnosticsEngine &Diags = Context.getDiags();
|
|
|
|
unsigned DiagID = Diags.getCustomDiagID(
|
|
|
|
DiagnosticsEngine::Error,
|
|
|
|
"cannot yet mangle __builtin_omp_required_simd_align expression");
|
2012-12-18 22:30:41 +08:00
|
|
|
Diags.Report(DiagID);
|
|
|
|
return;
|
|
|
|
}
|
2019-05-30 01:04:48 +08:00
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
if (SAE->isArgumentType()) {
|
|
|
|
Out << 't';
|
|
|
|
mangleType(SAE->getArgumentType());
|
|
|
|
} else {
|
|
|
|
Out << 'z';
|
|
|
|
mangleExpression(SAE->getArgumentExpr());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::CXXThrowExprClass: {
|
|
|
|
const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);
|
2013-08-27 09:03:46 +08:00
|
|
|
// <expression> ::= tw <expression> # throw expression
|
|
|
|
// ::= tr # rethrow
|
2012-12-18 22:30:41 +08:00
|
|
|
if (TE->getSubExpr()) {
|
|
|
|
Out << "tw";
|
|
|
|
mangleExpression(TE->getSubExpr());
|
|
|
|
} else {
|
|
|
|
Out << "tr";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::CXXTypeidExprClass: {
|
|
|
|
const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);
|
2013-08-27 09:03:46 +08:00
|
|
|
// <expression> ::= ti <type> # typeid (type)
|
|
|
|
// ::= te <expression> # typeid (expression)
|
2012-12-18 22:30:41 +08:00
|
|
|
if (TIE->isTypeOperand()) {
|
|
|
|
Out << "ti";
|
2013-09-27 15:04:31 +08:00
|
|
|
mangleType(TIE->getTypeOperand(Context.getASTContext()));
|
2012-12-18 22:30:41 +08:00
|
|
|
} else {
|
|
|
|
Out << "te";
|
|
|
|
mangleExpression(TIE->getExprOperand());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::CXXDeleteExprClass: {
|
|
|
|
const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);
|
2013-08-27 09:03:46 +08:00
|
|
|
// <expression> ::= [gs] dl <expression> # [::] delete expr
|
|
|
|
// ::= [gs] da <expression> # [::] delete [] expr
|
2012-12-18 22:30:41 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
[Matrix] Implement matrix index expressions ([][]).
This patch implements matrix index expressions
(matrix[RowIdx][ColumnIdx]).
It does so by introducing a new MatrixSubscriptExpr(Base, RowIdx, ColumnIdx).
MatrixSubscriptExprs are built in 2 steps in ActOnMatrixSubscriptExpr. First,
if the base of a subscript is of matrix type, we create a incomplete
MatrixSubscriptExpr(base, idx, nullptr). Second, if the base is an incomplete
MatrixSubscriptExpr, we create a complete
MatrixSubscriptExpr(base->getBase(), base->getRowIdx(), idx)
Similar to vector elements, it is not possible to take the address of
a MatrixSubscriptExpr.
For CodeGen, a new MatrixElt type is added to LValue, which is very
similar to VectorElt. The only difference is that we may need to cast
the type of the base from an array to a vector type when accessing it.
Reviewers: rjmccall, anemet, Bigcheese, rsmith, martong
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D76791
2020-06-02 02:42:03 +08:00
|
|
|
case Expr::MatrixSubscriptExprClass: {
|
|
|
|
const MatrixSubscriptExpr *ME = cast<MatrixSubscriptExpr>(E);
|
|
|
|
Out << "ixix";
|
|
|
|
mangleExpression(ME->getBase());
|
|
|
|
mangleExpression(ME->getRowIdx());
|
|
|
|
mangleExpression(ME->getColumnIdx());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-10-19 08:04:38 +08:00
|
|
|
case Expr::CXXRewrittenBinaryOperatorClass: {
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::ObjCBridgedCastExprClass: {
|
2018-07-31 03:24:48 +08:00
|
|
|
// Mangle ownership casts as a vendor extended operator __bridge,
|
2012-12-18 22:30:41 +08:00
|
|
|
// __bridge_transfer, or __bridge_retain.
|
|
|
|
StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
|
|
|
|
Out << "v1U" << Kind.size() << Kind;
|
|
|
|
}
|
|
|
|
// Fall through to mangle the cast itself.
|
2017-06-03 14:31:42 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CStyleCastExprClass:
|
2014-09-23 12:27:55 +08:00
|
|
|
mangleCastExpression(E, "cv");
|
|
|
|
break;
|
|
|
|
|
2015-02-05 14:15:50 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CXXStaticCastExprClass:
|
2014-09-23 12:27:55 +08:00
|
|
|
mangleCastExpression(E, "sc");
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CXXDynamicCastExprClass:
|
2014-09-23 12:27:55 +08:00
|
|
|
mangleCastExpression(E, "dc");
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CXXReinterpretCastExprClass:
|
2014-09-23 12:27:55 +08:00
|
|
|
mangleCastExpression(E, "rc");
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CXXConstCastExprClass:
|
2014-09-23 12:27:55 +08:00
|
|
|
mangleCastExpression(E, "cc");
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
2020-05-18 18:02:01 +08:00
|
|
|
case Expr::CXXAddrspaceCastExprClass:
|
|
|
|
mangleCastExpression(E, "ac");
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
case Expr::CXXOperatorCallExprClass: {
|
|
|
|
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
|
|
|
|
unsigned NumArgs = CE->getNumArgs();
|
2016-10-25 04:29:40 +08:00
|
|
|
// 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);
|
2012-12-18 22:30:41 +08:00
|
|
|
// 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;
|
|
|
|
|
2019-10-17 08:16:01 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
case Expr::DeclRefExprClass:
|
|
|
|
mangleDeclRefExpr(cast<DeclRefExpr>(E)->getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
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";
|
2019-05-22 04:10:50 +08:00
|
|
|
mangleDeclRefExpr(FPPE->getParameterPack());
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Expr::DependentScopeDeclRefExprClass: {
|
|
|
|
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
|
2016-10-25 04:47:04 +08:00
|
|
|
mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(),
|
|
|
|
DRE->getTemplateArgs(), DRE->getNumTemplateArgs(),
|
|
|
|
Arity);
|
2012-12-18 22:30:41 +08:00
|
|
|
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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
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:
|
2019-10-08 10:28:57 +08:00
|
|
|
// Mangle as if an integer literal 0.
|
|
|
|
Out << 'L';
|
|
|
|
mangleType(E->getType());
|
|
|
|
Out << "0E";
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
case Expr::CXXNullPtrLiteralExprClass: {
|
|
|
|
Out << "LDnE";
|
|
|
|
break;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::PackExpansionExprClass:
|
|
|
|
Out << "sp";
|
|
|
|
mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
|
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::SizeOfPackExprClass: {
|
2015-09-24 05:41:42 +08:00
|
|
|
auto *SPE = cast<SizeOfPackExpr>(E);
|
|
|
|
if (SPE->isPartiallySubstituted()) {
|
|
|
|
Out << "sP";
|
|
|
|
for (const auto &A : SPE->getPartialArguments())
|
|
|
|
mangleTemplateArg(A);
|
|
|
|
Out << "E";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << "sZ";
|
2015-09-24 05:41:42 +08:00
|
|
|
const NamedDecl *Pack = SPE->getPack();
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
|
2012-12-18 22:30:41 +08:00
|
|
|
else if (const NonTypeTemplateParmDecl *NTTP
|
|
|
|
= dyn_cast<NonTypeTemplateParmDecl>(Pack))
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex());
|
2012-12-18 22:30:41 +08:00
|
|
|
else if (const TemplateTemplateParmDecl *TempTP
|
|
|
|
= dyn_cast<TemplateTemplateParmDecl>(Pack))
|
2019-09-05 09:23:47 +08:00
|
|
|
mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex());
|
2012-12-18 22:30:41 +08:00
|
|
|
else
|
|
|
|
mangleFunctionParam(cast<ParmVarDecl>(Pack));
|
|
|
|
break;
|
|
|
|
}
|
2014-11-08 13:07:16 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::MaterializeTemporaryExprClass: {
|
2019-11-17 18:41:55 +08:00
|
|
|
mangleExpression(cast<MaterializeTemporaryExpr>(E)->getSubExpr());
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-11-08 13:07:16 +08:00
|
|
|
|
|
|
|
case Expr::CXXFoldExprClass: {
|
|
|
|
auto *FE = cast<CXXFoldExpr>(E);
|
2014-11-11 03:44:15 +08:00
|
|
|
if (FE->isLeftFold())
|
|
|
|
Out << (FE->getInit() ? "fL" : "fl");
|
2014-11-08 13:07:16 +08:00
|
|
|
else
|
2014-11-11 03:44:15 +08:00
|
|
|
Out << (FE->getInit() ? "fR" : "fr");
|
2014-11-08 13:07:16 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case Expr::CXXThisExprClass:
|
|
|
|
Out << "fpT";
|
|
|
|
break;
|
2015-10-27 14:02:45 +08:00
|
|
|
|
|
|
|
case Expr::CoawaitExprClass:
|
|
|
|
// FIXME: Propose a non-vendor mangling.
|
|
|
|
Out << "v18co_await";
|
|
|
|
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
|
|
|
|
break;
|
|
|
|
|
2017-03-07 07:38:15 +08:00
|
|
|
case Expr::DependentCoawaitExprClass:
|
|
|
|
// FIXME: Propose a non-vendor mangling.
|
|
|
|
Out << "v18co_await";
|
|
|
|
mangleExpression(cast<DependentCoawaitExpr>(E)->getOperand());
|
|
|
|
break;
|
|
|
|
|
2015-10-27 14:02:45 +08:00
|
|
|
case Expr::CoyieldExprClass:
|
|
|
|
// FIXME: Propose a non-vendor mangling.
|
|
|
|
Out << "v18co_yield";
|
|
|
|
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mangle an expression which refers to a parameter variable.
|
|
|
|
///
|
|
|
|
/// <expression> ::= <function-param>
|
|
|
|
/// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, I == 0
|
|
|
|
/// <function-param> ::= fp <top-level CV-qualifiers>
|
|
|
|
/// <parameter-2 non-negative number> _ # L == 0, I > 0
|
|
|
|
/// <function-param> ::= fL <L-1 non-negative number>
|
|
|
|
/// p <top-level CV-qualifiers> _ # L > 0, I == 0
|
|
|
|
/// <function-param> ::= fL <L-1 non-negative number>
|
|
|
|
/// p <top-level CV-qualifiers>
|
|
|
|
/// <I-1 non-negative number> _ # L > 0, I > 0
|
|
|
|
///
|
|
|
|
/// L is the nesting depth of the parameter, defined as 1 if the
|
|
|
|
/// parameter comes from the innermost function prototype scope
|
|
|
|
/// enclosing the current context, 2 if from the next enclosing
|
|
|
|
/// function prototype scope, and so on, with one special case: if
|
|
|
|
/// we've processed the full parameter clause for the innermost
|
|
|
|
/// function type, then L is one less. This definition conveniently
|
|
|
|
/// makes it irrelevant whether a function's result type was written
|
|
|
|
/// trailing or leading, but is otherwise overly complicated; the
|
|
|
|
/// numbering was first designed without considering references to
|
|
|
|
/// parameter in locations other than return types, and then the
|
|
|
|
/// mangling had to be generalized without changing the existing
|
|
|
|
/// manglings.
|
|
|
|
///
|
|
|
|
/// I is the zero-based index of the parameter within its parameter
|
|
|
|
/// declaration clause. Note that the original ABI document describes
|
|
|
|
/// this using 1-based ordinals.
|
|
|
|
void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
|
|
|
|
unsigned parmDepth = parm->getFunctionScopeDepth();
|
|
|
|
unsigned parmIndex = parm->getFunctionScopeIndex();
|
|
|
|
|
|
|
|
// Compute 'L'.
|
|
|
|
// parmDepth does not include the declaring function prototype.
|
|
|
|
// FunctionTypeDepth does account for that.
|
|
|
|
assert(parmDepth < FunctionTypeDepth.getDepth());
|
|
|
|
unsigned nestingDepth = FunctionTypeDepth.getDepth() - parmDepth;
|
|
|
|
if (FunctionTypeDepth.isInResultType())
|
|
|
|
nestingDepth--;
|
|
|
|
|
|
|
|
if (nestingDepth == 0) {
|
|
|
|
Out << "fp";
|
|
|
|
} else {
|
|
|
|
Out << "fL" << (nestingDepth - 1) << 'p';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Top-level qualifiers. We don't have to worry about arrays here,
|
|
|
|
// because parameters declared as arrays should already have been
|
|
|
|
// transformed to have pointer type. FIXME: apparently these don't
|
|
|
|
// get mangled if used as an rvalue of a known non-class type?
|
|
|
|
assert(!parm->getType()->isArrayType()
|
|
|
|
&& "parameter's type is still an array type?");
|
2017-10-02 14:25:51 +08:00
|
|
|
|
|
|
|
if (const DependentAddressSpaceType *DAST =
|
|
|
|
dyn_cast<DependentAddressSpaceType>(parm->getType())) {
|
|
|
|
mangleQualifiers(DAST->getPointeeType().getQualifiers(), DAST);
|
|
|
|
} else {
|
|
|
|
mangleQualifiers(parm->getType().getQualifiers());
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
// Parameter index.
|
|
|
|
if (parmIndex != 0) {
|
|
|
|
Out << (parmIndex - 1);
|
|
|
|
}
|
|
|
|
Out << '_';
|
|
|
|
}
|
|
|
|
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
void CXXNameMangler::mangleCXXCtorType(CXXCtorType T,
|
|
|
|
const CXXRecordDecl *InheritedFrom) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <ctor-dtor-name> ::= C1 # complete object constructor
|
|
|
|
// ::= C2 # base object constructor
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
// ::= CI1 <type> # complete inheriting constructor
|
|
|
|
// ::= CI2 <type> # base inheriting constructor
|
2012-12-18 22:30:41 +08:00
|
|
|
//
|
2014-09-16 23:18:21 +08:00
|
|
|
// In addition, C5 is a comdat name with C1 and C2 in it.
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
Out << 'C';
|
|
|
|
if (InheritedFrom)
|
|
|
|
Out << 'I';
|
2012-12-18 22:30:41 +08:00
|
|
|
switch (T) {
|
|
|
|
case Ctor_Complete:
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
Out << '1';
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
|
|
|
case Ctor_Base:
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
Out << '2';
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
2014-09-16 23:18:21 +08:00
|
|
|
case Ctor_Comdat:
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
Out << '5';
|
2012-12-18 22:30:41 +08:00
|
|
|
break;
|
2015-03-12 02:36:39 +08:00
|
|
|
case Ctor_DefaultClosure:
|
|
|
|
case Ctor_CopyingClosure:
|
|
|
|
llvm_unreachable("closure constructors don't exist for the Itanium ABI!");
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
2016-06-29 03:03:57 +08:00
|
|
|
if (InheritedFrom)
|
|
|
|
mangleName(InheritedFrom);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
|
|
|
|
// <ctor-dtor-name> ::= D0 # deleting destructor
|
|
|
|
// ::= D1 # complete object destructor
|
|
|
|
// ::= D2 # base object destructor
|
|
|
|
//
|
2014-09-16 23:18:21 +08:00
|
|
|
// In addition, D5 is a comdat name with D1, D2 and, if virtual, D0 in it.
|
2012-12-18 22:30:41 +08:00
|
|
|
switch (T) {
|
|
|
|
case Dtor_Deleting:
|
|
|
|
Out << "D0";
|
|
|
|
break;
|
|
|
|
case Dtor_Complete:
|
|
|
|
Out << "D1";
|
|
|
|
break;
|
|
|
|
case Dtor_Base:
|
|
|
|
Out << "D2";
|
|
|
|
break;
|
2014-09-16 23:18:21 +08:00
|
|
|
case Dtor_Comdat:
|
|
|
|
Out << "D5";
|
|
|
|
break;
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-24 10:59:37 +08:00
|
|
|
void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <template-args> ::= I <template-arg>+ E
|
|
|
|
Out << 'I';
|
2015-12-24 10:59:37 +08:00
|
|
|
for (unsigned i = 0; i != NumTemplateArgs; ++i)
|
|
|
|
mangleTemplateArg(TemplateArgs[i].getArgument());
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
|
|
|
|
// <template-args> ::= I <template-arg>+ E
|
|
|
|
Out << 'I';
|
|
|
|
for (unsigned i = 0, e = AL.size(); i != e; ++i)
|
|
|
|
mangleTemplateArg(AL[i]);
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs) {
|
|
|
|
// <template-args> ::= I <template-arg>+ E
|
|
|
|
Out << 'I';
|
|
|
|
for (unsigned i = 0; i != NumTemplateArgs; ++i)
|
|
|
|
mangleTemplateArg(TemplateArgs[i]);
|
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
|
|
|
|
// <template-arg> ::= <type> # type or template
|
|
|
|
// ::= X <expression> E # expression
|
|
|
|
// ::= <expr-primary> # simple expressions
|
|
|
|
// ::= J <template-arg>* E # argument pack
|
|
|
|
if (!A.isInstantiationDependent() || A.isDependent())
|
|
|
|
A = Context.getASTContext().getCanonicalTemplateArgument(A);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
switch (A.getKind()) {
|
|
|
|
case TemplateArgument::Null:
|
|
|
|
llvm_unreachable("Cannot mangle NULL template argument");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
case TemplateArgument::Type:
|
|
|
|
mangleType(A.getAsType());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Template:
|
|
|
|
// This is mangled as <type>.
|
|
|
|
mangleType(A.getAsTemplate());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::TemplateExpansion:
|
|
|
|
// <type> ::= Dp <type> # pack expansion (C++0x)
|
|
|
|
Out << "Dp";
|
|
|
|
mangleType(A.getAsTemplateOrTemplatePattern());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Expression: {
|
|
|
|
// It's possible to end up with a DeclRefExpr here in certain
|
|
|
|
// dependent cases, in which case we should mangle as a
|
|
|
|
// declaration.
|
2019-06-21 03:49:13 +08:00
|
|
|
const Expr *E = A.getAsExpr()->IgnoreParenImpCasts();
|
2012-12-18 22:30:41 +08:00
|
|
|
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
|
|
|
|
const ValueDecl *D = DRE->getDecl();
|
|
|
|
if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
|
2015-02-19 03:08:14 +08:00
|
|
|
Out << 'L';
|
2015-02-18 15:47:09 +08:00
|
|
|
mangle(D);
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'E';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'X';
|
|
|
|
mangleExpression(E);
|
|
|
|
Out << 'E';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Declaration: {
|
|
|
|
// <expr-primary> ::= L <mangled-name> E # external name
|
|
|
|
// Clang produces AST's where pointer-to-member-function expressions
|
|
|
|
// and pointer-to-function expressions are represented as a declaration not
|
|
|
|
// an expression. We compensate for it here to produce the correct mangling.
|
|
|
|
ValueDecl *D = A.getAsDecl();
|
2014-10-18 02:00:12 +08:00
|
|
|
bool compensateMangling = !A.getParamTypeForDecl()->isReferenceType();
|
2012-12-18 22:30:41 +08:00
|
|
|
if (compensateMangling) {
|
|
|
|
Out << 'X';
|
|
|
|
mangleOperatorName(OO_Amp, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << 'L';
|
|
|
|
// References to external entities use the mangled name; if the name would
|
2016-05-25 22:15:08 +08:00
|
|
|
// not normally be mangled then mangle it as unqualified.
|
2015-02-18 15:47:09 +08:00
|
|
|
mangle(D);
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'E';
|
|
|
|
|
|
|
|
if (compensateMangling)
|
|
|
|
Out << 'E';
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TemplateArgument::NullPtr: {
|
|
|
|
// <expr-primary> ::= L <type> 0 E
|
|
|
|
Out << 'L';
|
|
|
|
mangleType(A.getNullPtrType());
|
|
|
|
Out << "0E";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TemplateArgument::Pack: {
|
2013-08-27 09:03:46 +08:00
|
|
|
// <template-arg> ::= J <template-arg>* E
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'J';
|
2014-07-16 05:32:31 +08:00
|
|
|
for (const auto &P : A.pack_elements())
|
|
|
|
mangleTemplateArg(P);
|
2012-12-18 22:30:41 +08:00
|
|
|
Out << 'E';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-05 09:23:47 +08:00
|
|
|
void CXXNameMangler::mangleTemplateParameter(unsigned Depth, unsigned Index) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <template-param> ::= T_ # first template parameter
|
|
|
|
// ::= T <parameter-2 non-negative number> _
|
2019-09-05 09:23:47 +08:00
|
|
|
// ::= TL <L-1 non-negative number> __
|
|
|
|
// ::= TL <L-1 non-negative number> _
|
|
|
|
// <parameter-2 non-negative number> _
|
|
|
|
//
|
|
|
|
// The latter two manglings are from a proposal here:
|
|
|
|
// https://github.com/itanium-cxx-abi/cxx-abi/issues/31#issuecomment-528122117
|
|
|
|
Out << 'T';
|
|
|
|
if (Depth != 0)
|
|
|
|
Out << 'L' << (Depth - 1) << '_';
|
|
|
|
if (Index != 0)
|
|
|
|
Out << (Index - 1);
|
|
|
|
Out << '_';
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2014-05-07 06:49:16 +08:00
|
|
|
void CXXNameMangler::mangleSeqID(unsigned SeqID) {
|
|
|
|
if (SeqID == 1)
|
|
|
|
Out << '0';
|
|
|
|
else if (SeqID > 1) {
|
|
|
|
SeqID--;
|
|
|
|
|
|
|
|
// <seq-id> is encoded in base-36, using digits and upper case letters.
|
|
|
|
char Buffer[7]; // log(2**32) / log(36) ~= 7
|
2014-06-29 07:22:33 +08:00
|
|
|
MutableArrayRef<char> BufferRef(Buffer);
|
|
|
|
MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin();
|
2014-05-07 06:49:16 +08:00
|
|
|
|
|
|
|
for (; SeqID != 0; SeqID /= 36) {
|
|
|
|
unsigned C = SeqID % 36;
|
|
|
|
*I++ = (C < 10 ? '0' + C : 'A' + C - 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
Out.write(I.base(), I - BufferRef.rbegin());
|
|
|
|
}
|
|
|
|
Out << '_';
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) {
|
|
|
|
bool result = mangleSubstitution(tname);
|
|
|
|
assert(result && "no existing substitution for template name");
|
|
|
|
(void) result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <substitution> ::= S <seq-id> _
|
|
|
|
// ::= S_
|
|
|
|
bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
|
|
|
|
// Try one of the standard substitutions first.
|
|
|
|
if (mangleStandardSubstitution(ND))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
ND = cast<NamedDecl>(ND->getCanonicalDecl());
|
|
|
|
return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
|
|
|
|
}
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Determine whether the given type has any qualifiers that are relevant for
|
|
|
|
/// substitutions.
|
2012-12-18 22:30:41 +08:00
|
|
|
static bool hasMangledSubstitutionQualifiers(QualType T) {
|
|
|
|
Qualifiers Qs = T.getQualifiers();
|
2017-06-02 15:14:34 +08:00
|
|
|
return Qs.getCVRQualifiers() || Qs.hasAddressSpace() || Qs.hasUnaligned();
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXNameMangler::mangleSubstitution(QualType T) {
|
|
|
|
if (!hasMangledSubstitutionQualifiers(T)) {
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>())
|
|
|
|
return mangleSubstitution(RT->getDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
|
|
|
|
|
|
|
return mangleSubstitution(TypePtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXNameMangler::mangleSubstitution(TemplateName Template) {
|
|
|
|
if (TemplateDecl *TD = Template.getAsTemplateDecl())
|
|
|
|
return mangleSubstitution(TD);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
Template = Context.getASTContext().getCanonicalTemplateName(Template);
|
|
|
|
return mangleSubstitution(
|
|
|
|
reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
|
|
|
|
llvm::DenseMap<uintptr_t, unsigned>::iterator I = Substitutions.find(Ptr);
|
|
|
|
if (I == Substitutions.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
unsigned SeqID = I->second;
|
2014-05-07 06:49:16 +08:00
|
|
|
Out << 'S';
|
|
|
|
mangleSeqID(SeqID);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isCharType(QualType T) {
|
|
|
|
if (T.isNull())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
|
|
|
|
T->isSpecificBuiltinType(BuiltinType::Char_U);
|
|
|
|
}
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Returns whether a given type is a template specialization of a given name
|
|
|
|
/// with a single argument of type char.
|
2012-12-18 22:30:41 +08:00
|
|
|
static bool isCharSpecialization(QualType T, const char *Name) {
|
|
|
|
if (T.isNull())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const RecordType *RT = T->getAs<RecordType>();
|
|
|
|
if (!RT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const ClassTemplateSpecializationDecl *SD =
|
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
|
|
|
|
if (!SD)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isStdNamespace(getEffectiveDeclContext(SD)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
|
|
|
if (TemplateArgs.size() != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return SD->getIdentifier()->getName() == Name;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <std::size_t StrLen>
|
|
|
|
static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
|
|
|
|
const char (&Str)[StrLen]) {
|
|
|
|
if (!SD->getIdentifier()->isStr(Str))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
|
|
|
if (TemplateArgs.size() != 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
|
|
|
|
// <substitution> ::= St # ::std::
|
|
|
|
if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
|
|
|
|
if (isStd(NS)) {
|
|
|
|
Out << "St";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
|
|
|
|
if (!isStdNamespace(getEffectiveDeclContext(TD)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// <substitution> ::= Sa # ::std::allocator
|
|
|
|
if (TD->getIdentifier()->isStr("allocator")) {
|
|
|
|
Out << "Sa";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <<substitution> ::= Sb # ::std::basic_string
|
|
|
|
if (TD->getIdentifier()->isStr("basic_string")) {
|
|
|
|
Out << "Sb";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ClassTemplateSpecializationDecl *SD =
|
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
|
|
|
|
if (!isStdNamespace(getEffectiveDeclContext(SD)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// <substitution> ::= Ss # ::std::basic_string<char,
|
|
|
|
// ::std::char_traits<char>,
|
|
|
|
// ::std::allocator<char> >
|
|
|
|
if (SD->getIdentifier()->isStr("basic_string")) {
|
|
|
|
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
|
|
|
|
|
|
|
|
if (TemplateArgs.size() != 3)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharType(TemplateArgs[0].getAsType()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Out << "Ss";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <substitution> ::= Si # ::std::basic_istream<char,
|
|
|
|
// ::std::char_traits<char> >
|
|
|
|
if (isStreamCharSpecialization(SD, "basic_istream")) {
|
|
|
|
Out << "Si";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <substitution> ::= So # ::std::basic_ostream<char,
|
|
|
|
// ::std::char_traits<char> >
|
|
|
|
if (isStreamCharSpecialization(SD, "basic_ostream")) {
|
|
|
|
Out << "So";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <substitution> ::= Sd # ::std::basic_iostream<char,
|
|
|
|
// ::std::char_traits<char> >
|
|
|
|
if (isStreamCharSpecialization(SD, "basic_iostream")) {
|
|
|
|
Out << "Sd";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::addSubstitution(QualType T) {
|
|
|
|
if (!hasMangledSubstitutionQualifiers(T)) {
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>()) {
|
|
|
|
addSubstitution(RT->getDecl());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
|
|
|
addSubstitution(TypePtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::addSubstitution(TemplateName Template) {
|
|
|
|
if (TemplateDecl *TD = Template.getAsTemplateDecl())
|
|
|
|
return addSubstitution(TD);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
Template = Context.getASTContext().getCanonicalTemplateName(Template);
|
|
|
|
addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
|
|
|
|
assert(!Substitutions.count(Ptr) && "Substitution already exists!");
|
|
|
|
Substitutions[Ptr] = SeqID++;
|
|
|
|
}
|
|
|
|
|
2016-09-21 16:27:03 +08:00
|
|
|
void CXXNameMangler::extendSubstitutions(CXXNameMangler* Other) {
|
|
|
|
assert(Other->SeqID >= SeqID && "Must be superset of substitutions!");
|
|
|
|
if (Other->SeqID > SeqID) {
|
|
|
|
Substitutions.swap(Other->Substitutions);
|
|
|
|
SeqID = Other->SeqID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-30 17:40:38 +08:00
|
|
|
CXXNameMangler::AbiTagList
|
|
|
|
CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) {
|
|
|
|
// When derived abi tags are disabled there is no need to make any list.
|
|
|
|
if (DisableDerivedAbiTags)
|
|
|
|
return AbiTagList();
|
|
|
|
|
|
|
|
llvm::raw_null_ostream NullOutStream;
|
|
|
|
CXXNameMangler TrackReturnTypeTags(*this, NullOutStream);
|
|
|
|
TrackReturnTypeTags.disableDerivedAbiTags();
|
|
|
|
|
|
|
|
const FunctionProtoType *Proto =
|
|
|
|
cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
|
2017-06-14 17:47:47 +08:00
|
|
|
FunctionTypeDepthState saved = TrackReturnTypeTags.FunctionTypeDepth.push();
|
2016-06-30 17:40:38 +08:00
|
|
|
TrackReturnTypeTags.FunctionTypeDepth.enterResultType();
|
|
|
|
TrackReturnTypeTags.mangleType(Proto->getReturnType());
|
|
|
|
TrackReturnTypeTags.FunctionTypeDepth.leaveResultType();
|
2017-06-14 17:47:47 +08:00
|
|
|
TrackReturnTypeTags.FunctionTypeDepth.pop(saved);
|
2016-06-30 17:40:38 +08:00
|
|
|
|
|
|
|
return TrackReturnTypeTags.AbiTagsRoot.getSortedUniqueUsedAbiTags();
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXNameMangler::AbiTagList
|
|
|
|
CXXNameMangler::makeVariableTypeTags(const VarDecl *VD) {
|
|
|
|
// When derived abi tags are disabled there is no need to make any list.
|
|
|
|
if (DisableDerivedAbiTags)
|
|
|
|
return AbiTagList();
|
|
|
|
|
|
|
|
llvm::raw_null_ostream NullOutStream;
|
|
|
|
CXXNameMangler TrackVariableType(*this, NullOutStream);
|
|
|
|
TrackVariableType.disableDerivedAbiTags();
|
|
|
|
|
|
|
|
TrackVariableType.mangleType(VD->getType());
|
|
|
|
|
|
|
|
return TrackVariableType.AbiTagsRoot.getSortedUniqueUsedAbiTags();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C,
|
|
|
|
const VarDecl *VD) {
|
|
|
|
llvm::raw_null_ostream NullOutStream;
|
|
|
|
CXXNameMangler TrackAbiTags(C, NullOutStream, nullptr, true);
|
|
|
|
TrackAbiTags.mangle(VD);
|
|
|
|
return TrackAbiTags.AbiTagsRoot.getUsedAbiTags().size();
|
|
|
|
}
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
//
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Mangles the name of the declaration D and emits that name to the given
|
|
|
|
/// output stream.
|
2012-12-18 22:30:41 +08:00
|
|
|
///
|
|
|
|
/// If the declaration D requires a mangled name, this routine will emit that
|
|
|
|
/// mangled name to \p os and return true. Otherwise, \p os will be unchanged
|
|
|
|
/// and this routine will return false. In this case, the caller should just
|
|
|
|
/// emit the identifier of the declaration (\c D->getIdentifier()) as its
|
|
|
|
/// name.
|
2020-03-06 01:02:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXName(GlobalDecl GD,
|
2013-10-16 09:40:34 +08:00
|
|
|
raw_ostream &Out) {
|
2020-03-06 01:02:13 +08:00
|
|
|
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
|
2012-12-18 22:30:41 +08:00
|
|
|
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
|
|
|
|
"Invalid mangleName() call, argument is not a variable or function!");
|
|
|
|
|
|
|
|
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
|
|
|
|
getASTContext().getSourceManager(),
|
|
|
|
"Mangling declaration");
|
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
|
|
|
|
auto Type = GD.getCtorType();
|
|
|
|
CXXNameMangler Mangler(*this, Out, CD, Type);
|
|
|
|
return Mangler.mangle(GlobalDecl(CD, Type));
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
if (auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
|
|
|
|
auto Type = GD.getDtorType();
|
|
|
|
CXXNameMangler Mangler(*this, Out, DD, Type);
|
|
|
|
return Mangler.mangle(GlobalDecl(DD, Type));
|
|
|
|
}
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
CXXNameMangler Mangler(*this, Out, D);
|
|
|
|
Mangler.mangle(GD);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2014-09-16 23:18:21 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXCtorComdat(const CXXConstructorDecl *D,
|
|
|
|
raw_ostream &Out) {
|
|
|
|
CXXNameMangler Mangler(*this, Out, D, Ctor_Comdat);
|
2020-03-06 01:02:13 +08:00
|
|
|
Mangler.mangle(GlobalDecl(D, Ctor_Comdat));
|
2014-09-16 23:18:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ItaniumMangleContextImpl::mangleCXXDtorComdat(const CXXDestructorDecl *D,
|
|
|
|
raw_ostream &Out) {
|
|
|
|
CXXNameMangler Mangler(*this, Out, D, Dtor_Comdat);
|
2020-03-06 01:02:13 +08:00
|
|
|
Mangler.mangle(GlobalDecl(D, Dtor_Comdat));
|
2014-09-16 23:18:21 +08:00
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
|
|
|
|
const ThunkInfo &Thunk,
|
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= T <call-offset> <base encoding>
|
|
|
|
// # base is the nominal target function of thunk
|
|
|
|
// <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
|
|
|
|
// # base is the nominal target function of thunk
|
|
|
|
// # first call-offset is 'this' adjustment
|
|
|
|
// # second call-offset is result adjustment
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
assert(!isa<CXXDestructorDecl>(MD) &&
|
|
|
|
"Use mangleCXXDtor for destructor decls!");
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZT";
|
|
|
|
if (!Thunk.Return.isEmpty())
|
|
|
|
Mangler.getStream() << 'c';
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Mangle the 'this' pointer adjustment.
|
2013-11-06 14:24:31 +08:00
|
|
|
Mangler.mangleCallOffset(Thunk.This.NonVirtual,
|
|
|
|
Thunk.This.Virtual.Itanium.VCallOffsetOffset);
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
// Mangle the return pointer adjustment if there is one.
|
|
|
|
if (!Thunk.Return.isEmpty())
|
|
|
|
Mangler.mangleCallOffset(Thunk.Return.NonVirtual,
|
2013-10-30 19:55:43 +08:00
|
|
|
Thunk.Return.Virtual.Itanium.VBaseOffsetOffset);
|
|
|
|
|
2012-12-18 22:30:41 +08:00
|
|
|
Mangler.mangleFunctionEncoding(MD);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXDtorThunk(
|
|
|
|
const CXXDestructorDecl *DD, CXXDtorType Type,
|
|
|
|
const ThisAdjustment &ThisAdjustment, raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= T <call-offset> <base encoding>
|
|
|
|
// # base is the nominal target function of thunk
|
|
|
|
CXXNameMangler Mangler(*this, Out, DD, Type);
|
|
|
|
Mangler.getStream() << "_ZT";
|
|
|
|
|
|
|
|
// Mangle the 'this' pointer adjustment.
|
2018-07-31 03:24:48 +08:00
|
|
|
Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
|
2013-11-06 14:24:31 +08:00
|
|
|
ThisAdjustment.Virtual.Itanium.VCallOffsetOffset);
|
2012-12-18 22:30:41 +08:00
|
|
|
|
2020-03-06 01:02:13 +08:00
|
|
|
Mangler.mangleFunctionEncoding(GlobalDecl(DD, Type));
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2015-05-22 14:48:13 +08:00
|
|
|
/// Returns the mangled name for a guard variable for the passed in VarDecl.
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D,
|
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= GV <object name> # Guard variable for one-time
|
|
|
|
// # initialization
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
2016-06-30 17:40:38 +08:00
|
|
|
// GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to
|
|
|
|
// be a bug that is fixed in trunk.
|
2012-12-18 22:30:41 +08:00
|
|
|
Mangler.getStream() << "_ZGV";
|
|
|
|
Mangler.mangleName(D);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleDynamicInitializer(const VarDecl *MD,
|
|
|
|
raw_ostream &Out) {
|
2013-09-11 04:43:12 +08:00
|
|
|
// These symbols are internal in the Itanium ABI, so the names don't matter.
|
|
|
|
// Clang has traditionally used this symbol and allowed LLVM to adjust it to
|
|
|
|
// avoid duplicate symbols.
|
|
|
|
Out << "__cxx_global_var_init";
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
|
|
|
|
raw_ostream &Out) {
|
2013-09-11 04:14:30 +08:00
|
|
|
// Prefix the mangling of D with __dtor_.
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "__dtor_";
|
|
|
|
if (shouldMangleDeclName(D))
|
|
|
|
Mangler.mangle(D);
|
|
|
|
else
|
|
|
|
Mangler.getStream() << D->getName();
|
|
|
|
}
|
|
|
|
|
2020-05-28 05:04:43 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleDynamicStermFinalizer(const VarDecl *D,
|
|
|
|
raw_ostream &Out) {
|
|
|
|
// Clang generates these internal-linkage functions as part of its
|
|
|
|
// implementation of the XL ABI.
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "__finalize_";
|
|
|
|
if (shouldMangleDeclName(D))
|
|
|
|
Mangler.mangle(D);
|
|
|
|
else
|
|
|
|
Mangler.getStream() << D->getName();
|
|
|
|
}
|
|
|
|
|
Initial support for Win64 SEH IR emission
The lowering looks a lot like normal EH lowering, with the exception
that the exceptions are caught by executing filter expression code
instead of matching typeinfo globals. The filter expressions are
outlined into functions which are used in landingpad clauses where
typeinfo would normally go.
Major aspects that still need work:
- Non-call exceptions in __try bodies won't work yet. The plan is to
outline the __try block in the frontend to keep things simple.
- Filter expressions cannot use local variables until capturing is
implemented.
- __finally blocks will not run after exceptions. Fixing this requires
work in the LLVM SEH preparation pass.
The IR lowering looks like this:
// C code:
bool safe_div(int n, int d, int *r) {
__try {
*r = normal_div(n, d);
} __except(_exception_code() == EXCEPTION_INT_DIVIDE_BY_ZERO) {
return false;
}
return true;
}
; LLVM IR:
define i32 @filter(i8* %e, i8* %fp) {
%ehptrs = bitcast i8* %e to i32**
%ehrec = load i32** %ehptrs
%code = load i32* %ehrec
%matches = icmp eq i32 %code, i32 u0xC0000094
%matches.i32 = zext i1 %matches to i32
ret i32 %matches.i32
}
define i1 zeroext @safe_div(i32 %n, i32 %d, i32* %r) {
%rr = invoke i32 @normal_div(i32 %n, i32 %d)
to label %normal unwind to label %lpad
normal:
store i32 %rr, i32* %r
ret i1 1
lpad:
%ehvals = landingpad {i8*, i32} personality i32 (...)* @__C_specific_handler
catch i8* bitcast (i32 (i8*, i8*)* @filter to i8*)
%ehptr = extractvalue {i8*, i32} %ehvals, i32 0
%sel = extractvalue {i8*, i32} %ehvals, i32 1
%filter_sel = call i32 @llvm.eh.seh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @filter to i8*))
%matches = icmp eq i32 %sel, %filter_sel
br i1 %matches, label %eh.except, label %eh.resume
eh.except:
ret i1 false
eh.resume:
resume
}
Reviewers: rjmccall, rsmith, majnemer
Differential Revision: http://reviews.llvm.org/D5607
llvm-svn: 226760
2015-01-22 09:36:17 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleSEHFilterExpression(
|
|
|
|
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "__filt_";
|
|
|
|
if (shouldMangleDeclName(EnclosingDecl))
|
|
|
|
Mangler.mangle(EnclosingDecl);
|
|
|
|
else
|
|
|
|
Mangler.getStream() << EnclosingDecl->getName();
|
|
|
|
}
|
|
|
|
|
2015-04-15 04:59:00 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
|
|
|
|
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "__fin_";
|
|
|
|
if (shouldMangleDeclName(EnclosingDecl))
|
|
|
|
Mangler.mangle(EnclosingDecl);
|
|
|
|
else
|
|
|
|
Mangler.getStream() << EnclosingDecl->getName();
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D,
|
|
|
|
raw_ostream &Out) {
|
2013-04-20 00:42:07 +08:00
|
|
|
// <special-name> ::= TH <object name>
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTH";
|
|
|
|
Mangler.mangleName(D);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void
|
|
|
|
ItaniumMangleContextImpl::mangleItaniumThreadLocalWrapper(const VarDecl *D,
|
|
|
|
raw_ostream &Out) {
|
2013-04-20 00:42:07 +08:00
|
|
|
// <special-name> ::= TW <object name>
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTW";
|
|
|
|
Mangler.mangleName(D);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleReferenceTemporary(const VarDecl *D,
|
2014-05-02 01:50:17 +08:00
|
|
|
unsigned ManglingNumber,
|
2013-10-03 14:26:13 +08:00
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// We match the GCC mangling here.
|
|
|
|
// <special-name> ::= GR <object name>
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZGR";
|
|
|
|
Mangler.mangleName(D);
|
2014-05-02 01:50:17 +08:00
|
|
|
assert(ManglingNumber > 0 && "Reference temporary mangling number is zero!");
|
2014-05-07 06:49:16 +08:00
|
|
|
Mangler.mangleSeqID(ManglingNumber - 1);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD,
|
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= TV <type> # virtual table
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTV";
|
|
|
|
Mangler.mangleNameOrStandardSubstitution(RD);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXVTT(const CXXRecordDecl *RD,
|
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= TT <type> # VTT structure
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTT";
|
|
|
|
Mangler.mangleNameOrStandardSubstitution(RD);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD,
|
|
|
|
int64_t Offset,
|
|
|
|
const CXXRecordDecl *Type,
|
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= TC <type> <offset number> _ <base type>
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTC";
|
|
|
|
Mangler.mangleNameOrStandardSubstitution(RD);
|
|
|
|
Mangler.getStream() << Offset;
|
|
|
|
Mangler.getStream() << '_';
|
|
|
|
Mangler.mangleNameOrStandardSubstitution(Type);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= TI <type> # typeinfo structure
|
|
|
|
assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTI";
|
|
|
|
Mangler.mangleType(Ty);
|
|
|
|
}
|
|
|
|
|
2013-10-03 14:26:13 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleCXXRTTIName(QualType Ty,
|
|
|
|
raw_ostream &Out) {
|
2012-12-18 22:30:41 +08:00
|
|
|
// <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.getStream() << "_ZTS";
|
|
|
|
Mangler.mangleType(Ty);
|
|
|
|
}
|
|
|
|
|
2013-11-20 07:23:00 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
|
|
|
|
mangleCXXRTTIName(Ty, Out);
|
|
|
|
}
|
|
|
|
|
2014-03-25 05:43:36 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) {
|
|
|
|
llvm_unreachable("Can't mangle string literals");
|
|
|
|
}
|
|
|
|
|
2019-09-05 09:23:47 +08:00
|
|
|
void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda,
|
|
|
|
raw_ostream &Out) {
|
|
|
|
CXXNameMangler Mangler(*this, Out);
|
|
|
|
Mangler.mangleLambdaSig(Lambda);
|
|
|
|
}
|
|
|
|
|
[SYCL] Implement __builtin_unique_stable_name.
In order to support non-user-named kernels, SYCL needs some way in the
integration headers to name the kernel object themselves. Initially, the
design considered just RTTI naming of the lambdas, this results in a
quite unstable situation in light of some device/host macros.
Additionally, this ends up needing to use RTTI, which is a burden on the
implementation and typically unsupported.
Instead, we've introduced a builtin, __builtin_unique_stable_name, which
takes a type or expression, and results in a constexpr constant
character array that uniquely represents the type (or type of the
expression) being passed to it.
The implementation accomplishes that simply by using a slightly modified
version of the Itanium Mangling. The one exception is when mangling
lambdas, instead of appending the index of the lambda in the function,
it appends the macro-expansion back-trace of the lambda itself in the
form LINE->COL[~LINE->COL...].
Differential Revision: https://reviews.llvm.org/D76620
2020-03-19 04:45:58 +08:00
|
|
|
ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
|
|
|
|
DiagnosticsEngine &Diags,
|
|
|
|
bool IsUniqueNameMangler) {
|
|
|
|
return new ItaniumMangleContextImpl(Context, Diags, IsUniqueNameMangler);
|
2012-12-18 22:30:41 +08:00
|
|
|
}
|