Skip to content
Merged
Changes from all 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
72 changes: 29 additions & 43 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,42 +243,34 @@ class CXXNameMangler {
unsigned SeqID = 0;

class FunctionTypeDepthState {
unsigned Bits = 0;

enum { InResultTypeMask = 1 };
unsigned Depth : 31;
unsigned InFunctionDeclSuffix : 1;

public:
FunctionTypeDepthState() = default;

/// 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() : Depth(0), InFunctionDeclSuffix(0) {}

unsigned getNestingDepth(unsigned ParmDepth) const {
// ParmDepth does not include the declaring function prototype.
// FunctionTypeDepth does account for that.
assert(ParmDepth < Depth &&
"ParmVarDecl is not visible in current parameter environment");
return Depth - ParmDepth - InFunctionDeclSuffix;
}

FunctionTypeDepthState push() {
FunctionTypeDepthState tmp = *this;
Bits = (Bits & ~InResultTypeMask) + 2;
return tmp;
}

void enterResultType() {
Bits |= InResultTypeMask;
}

void leaveResultType() {
Bits &= ~InResultTypeMask;
FunctionTypeDepthState Saved = *this;
++Depth;
InFunctionDeclSuffix = 0;
Comment thread
shafik marked this conversation as resolved.
return Saved;
}

void pop(FunctionTypeDepthState saved) {
assert(getDepth() == saved.getDepth() + 1);
Bits = saved.Bits;
void pop(FunctionTypeDepthState Saved) {
assert(Depth == Saved.Depth + 1 && "unbalanced function type depth pop");
*this = Saved;
Comment thread
shafik marked this conversation as resolved.
}

void enterFunctionDeclSuffix() { InFunctionDeclSuffix = 1; }
void leaveFunctionDeclSuffix() { InFunctionDeclSuffix = 0; }
Comment on lines +272 to +273

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we guard against mismatched calls? e.g., assert that we cannot leave if we've not entered, and assert that we cannot enter if we're already entered?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this makes sense. Because every time FunctionTypeDepth.push() is called, InFunctionDeclSuffix is reset, and at the same depth, enterFunctionDeclSuffix should not be entered repeatedly. However, I'm not entirely sure if I've missed any details.

} FunctionTypeDepth;

// abi_tag is a gcc attribute, taking one or more strings called "tags".
Expand Down Expand Up @@ -3752,9 +3744,9 @@ void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {

FunctionTypeDepthState saved = FunctionTypeDepth.push();

FunctionTypeDepth.enterResultType();
FunctionTypeDepth.enterFunctionDeclSuffix();
mangleType(T->getReturnType());
FunctionTypeDepth.leaveResultType();
FunctionTypeDepth.leaveFunctionDeclSuffix();

FunctionTypeDepth.pop(saved);
Out << 'E';
Expand All @@ -3769,7 +3761,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,

// <bare-function-type> ::= <signature type>+
if (MangleReturnType) {
FunctionTypeDepth.enterResultType();
FunctionTypeDepth.enterFunctionDeclSuffix();

// Mangle ns_returns_retained as an order-sensitive qualifier here.
if (Proto->getExtInfo().getProducesResult() && FD == nullptr)
Expand All @@ -3784,7 +3776,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
}
mangleType(ReturnTy);

FunctionTypeDepth.leaveResultType();
FunctionTypeDepth.leaveFunctionDeclSuffix();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would it make sense to add an RAII object to do the enter/leave calls? I worry about the possibility of adding a return in here someday that breaks this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We could introduce an RAII object (because the missing leave below is actually omitted), but that might require guarding every call site.

}

if (Proto->getNumParams() == 0 && !Proto->isVariadic()) {
Expand Down Expand Up @@ -3821,7 +3813,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
}

if (FD) {
FunctionTypeDepth.enterResultType();
FunctionTypeDepth.enterFunctionDeclSuffix();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ohhh, RAII object might not make sense, what ends up leaving this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The state will be restored by the following FunctionTypeDepth.pop(saved), so leaveFunctionDeclSuffix can be omitted here.

mangleRequiresClause(FD->getTrailingRequiresClause().ConstraintExpr);
}

Expand Down Expand Up @@ -5716,7 +5708,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
Out << '_';

// The rest of the mangling is in the immediate scope of the parameters.
FunctionTypeDepth.enterResultType();
FunctionTypeDepth.enterFunctionDeclSuffix();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What ends up leaving this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same as above.

for (const concepts::Requirement *Req : RE->getRequirements())
mangleRequirement(RE->getExprLoc(), Req);
FunctionTypeDepth.pop(saved);
Expand Down Expand Up @@ -6013,14 +6005,8 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
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) {
if (unsigned nestingDepth = FunctionTypeDepth.getNestingDepth(parmDepth);
nestingDepth == 0) {
Out << "fp";
} else {
Out << "fL" << (nestingDepth - 1) << 'p';
Expand Down Expand Up @@ -7254,9 +7240,9 @@ CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) {
const FunctionProtoType *Proto =
cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
FunctionTypeDepthState saved = TrackReturnTypeTags.FunctionTypeDepth.push();
TrackReturnTypeTags.FunctionTypeDepth.enterResultType();
TrackReturnTypeTags.FunctionTypeDepth.enterFunctionDeclSuffix();
TrackReturnTypeTags.mangleType(Proto->getReturnType());
TrackReturnTypeTags.FunctionTypeDepth.leaveResultType();
TrackReturnTypeTags.FunctionTypeDepth.leaveFunctionDeclSuffix();
TrackReturnTypeTags.FunctionTypeDepth.pop(saved);

return TrackReturnTypeTags.AbiTagsRoot.getSortedUniqueUsedAbiTags();
Expand Down