Skip to content

First attempt at __unique_stable_name #250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 5, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 73 additions & 13 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1787,10 +1787,16 @@ class StringLiteral final
}
};

union PredefExprStorage {
Stmt *S;
Expr *E;
TypeSourceInfo *T;
};

/// [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr final
: public Expr,
private llvm::TrailingObjects<PredefinedExpr, Stmt *> {
private llvm::TrailingObjects<PredefinedExpr, PredefExprStorage> {
friend class ASTStmtReader;
friend TrailingObjects;

Expand All @@ -1809,12 +1815,18 @@ class PredefinedExpr final
PrettyFunction,
/// The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
PrettyFunctionNoVirtual
PrettyFunctionNoVirtual,
UniqueStableNameType,
UniqueStableNameExpr,
};

private:
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
StringLiteral *SL);
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
TypeSourceInfo *Info);
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
Expr *E);

explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);

Expand All @@ -1824,14 +1836,33 @@ class PredefinedExpr final
void setFunctionName(StringLiteral *SL) {
assert(hasFunctionName() &&
"This PredefinedExpr has no storage for a function name!");
*getTrailingObjects<Stmt *>() = SL;
getTrailingObjects<PredefExprStorage>()->S = SL;
}

void setTypeSourceInfo(TypeSourceInfo *Info) {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
getTrailingObjects<PredefExprStorage>()->T = Info;
}
void setExpr(Expr *E) {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr &&
"Expr only valid for UniqueStableName of an Expression.");
getTrailingObjects<PredefExprStorage>()->E = E;
}

public:
/// Create a PredefinedExpr.
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK, StringLiteral *SL);

static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
QualType FnTy, IdentKind IK, StringLiteral *SL,
TypeSourceInfo *Info);

static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
QualType FnTy, IdentKind IK, StringLiteral *SL,
Expr *E);

/// Create an empty PredefinedExpr.
static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
bool HasFunctionName);
Expand All @@ -1843,20 +1874,47 @@ class PredefinedExpr final
SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; }

TypeSourceInfo *getTypeSourceInfo() {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return getTrailingObjects<PredefExprStorage>()->T;
}

const TypeSourceInfo *getTypeSourceInfo() const {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return getTrailingObjects<PredefExprStorage>()->T;
}

Expr *getExpr() {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr &&
"Expr only valid for UniqueStableName of an Expression.");
return getTrailingObjects<PredefExprStorage>()->E;
}

const Expr *getExpr() const {
assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr &&
"TypeSourceInfo only valid for UniqueStableName of a Type");
return getTrailingObjects<PredefExprStorage>()->E;
}


StringLiteral *getFunctionName() {
return hasFunctionName()
? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
: nullptr;
return hasFunctionName() ? static_cast<StringLiteral *>(
getTrailingObjects<PredefExprStorage>()->S)
: nullptr;
}

const StringLiteral *getFunctionName() const {
return hasFunctionName()
? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
: nullptr;
return hasFunctionName() ? static_cast<StringLiteral *>(
getTrailingObjects<PredefExprStorage>()->S)
: nullptr;
}

static StringRef getIdentKindName(IdentKind IK);
static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);
static std::string ComputeName(ASTContext &Ctx, IdentKind IK,
const QualType Ty);

SourceLocation getBeginLoc() const { return getLocation(); }
SourceLocation getEndLoc() const { return getLocation(); }
Expand All @@ -1867,13 +1925,15 @@ class PredefinedExpr final

// Iterators
child_range children() {
return child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + hasFunctionName());
return child_range(&getTrailingObjects<PredefExprStorage>()->S,
&getTrailingObjects<PredefExprStorage>()->S +
hasFunctionName());
}

const_child_range children() const {
return const_child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + hasFunctionName());
return const_child_range(&getTrailingObjects<PredefExprStorage>()->S,
&getTrailingObjects<PredefExprStorage>()->S +
hasFunctionName());
}
};

Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/AST/Mangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,14 @@ class MangleContext {
};

class ItaniumMangleContext : public MangleContext {
bool IsUniqueNameMangler = false;
public:
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
: MangleContext(C, D, MK_Itanium) {}
explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
bool IsUniqueNameMangler)
: MangleContext(C, D, MK_Itanium),
IsUniqueNameMangler(IsUniqueNameMangler) {}

virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
Expand All @@ -170,12 +175,17 @@ class ItaniumMangleContext : public MangleContext {
virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
raw_ostream &) = 0;

bool isUniqueNameMangler() { return IsUniqueNameMangler; }

static bool classof(const MangleContext *C) {
return C->getKind() == MK_Itanium;
}

static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags);
static ItaniumMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags,
bool IsUniqueNameMangler);
};

class MicrosoftMangleContext : public MangleContext {
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,9 @@ KEYWORD(L__FUNCSIG__ , KEYMS)
TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)

// Extensions for SYCL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elaborate the comment to say what it does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a category heading, it isn't directly associated with the keyword itself. If you see the rest of the file, that is the format of comments in this file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, we can move this built-in to some "generic" clang built-ins category.

KEYWORD(__unique_stable_name , KEYSYCL)

// MSVC12.0 / VS2013 Type Traits
TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS)
TYPE_TRAIT_1(__is_trivially_destructible, IsTriviallyDestructible, KEYCXX)
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,7 @@ class Parser : public CodeCompletionHandler {
ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
ExprResult ParseUnaryExprOrTypeTraitExpression();
ExprResult ParseBuiltinPrimaryExpression();
ExprResult ParseUniqueStableNameExpression();

ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
bool &isCastExpr,
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4466,6 +4466,14 @@ class Sema {
ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);

ExprResult BuildUniqueStableName(SourceLocation OpLoc,
TypeSourceInfo *Operand);
ExprResult BuildUniqueStableName(SourceLocation OpLoc, Expr *E);
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation L,
SourceLocation R, ParsedType Ty);
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation L,
SourceLocation R, Expr *Operand);

bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);

ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);
Expand Down
80 changes: 77 additions & 3 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,36 @@ PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
setFunctionName(SL);
}

PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
TypeSourceInfo *Info)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
FNTy->isDependentType(), FNTy->isDependentType(),
FNTy->isInstantiationDependentType(),
/*ContainsUnexpandedParameterPack=*/false) {
PredefinedExprBits.Kind = IK;
assert((getIdentKind() == IK) &&
"IdentKind do not fit in PredefinedExprBitfields!");
assert(IK == UniqueStableNameType && "Wrong Thing!");
PredefinedExprBits.HasFunctionName = false;
PredefinedExprBits.Loc = L;
setTypeSourceInfo(Info);
}

PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
Expr *Info)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
FNTy->isDependentType(), FNTy->isDependentType(),
FNTy->isInstantiationDependentType(),
/*ContainsUnexpandedParameterPack=*/false) {
PredefinedExprBits.Kind = IK;
assert((getIdentKind() == IK) &&
"IdentKind do not fit in PredefinedExprBitfields!");
assert(IK == UniqueStableNameExpr && "Wrong Thing!");
PredefinedExprBits.HasFunctionName = false;
PredefinedExprBits.Loc = L;
setExpr(Info);
}

PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName)
: Expr(PredefinedExprClass, Empty) {
PredefinedExprBits.HasFunctionName = HasFunctionName;
Expand All @@ -498,14 +528,43 @@ PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK,
StringLiteral *SL) {
bool HasFunctionName = SL != nullptr;
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
alignof(PredefinedExpr));
void *Mem =
Ctx.Allocate(totalSizeToAlloc<PredefExprStorage>(HasFunctionName),
alignof(PredefinedExpr));
return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
}

PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK,
StringLiteral *SL,
TypeSourceInfo *Info) {
assert(IK == UniqueStableNameType && "Wrong Type");
bool HasFunctionName = SL != nullptr;
void *Mem =
Ctx.Allocate(totalSizeToAlloc<PredefExprStorage>(1),
alignof(PredefinedExpr));

if (HasFunctionName)
return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
return new (Mem) PredefinedExpr(L, FNTy, IK, Info);
}

PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK,
StringLiteral *SL, Expr *E) {
assert(IK == UniqueStableNameExpr && "Wrong Type");
bool HasFunctionName = SL != nullptr;
void *Mem =
Ctx.Allocate(totalSizeToAlloc<PredefExprStorage>(1),
alignof(PredefinedExpr));
if (HasFunctionName)
return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
return new (Mem) PredefinedExpr(L, FNTy, IK, E);
}

PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,
bool HasFunctionName) {
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
void *Mem = Ctx.Allocate(totalSizeToAlloc<PredefExprStorage>(HasFunctionName),
alignof(PredefinedExpr));
return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName);
}
Expand All @@ -526,12 +585,27 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
return "__FUNCSIG__";
case LFuncSig:
return "L__FUNCSIG__";
case UniqueStableNameType:
case UniqueStableNameExpr:
return "__unique_stable_name";
case PrettyFunctionNoVirtual:
break;
}
llvm_unreachable("Unknown ident kind for PredefinedExpr");
}

std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentKind IK,
QualType Ty) {
std::unique_ptr<MangleContext> Ctx{
ItaniumMangleContext::create(Context, Context.getDiagnostics(), true)};
Ty = Ty.getCanonicalType();

SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
Ctx->mangleTypeName(Ty, Out);
return Buffer.str();
}

// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
Expand Down
Loading