Skip to content

[ItaniumDemangle] Add customizable printLeft/printRight APIs to OutputBuffer #133249

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
Show file tree
Hide file tree
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
91 changes: 54 additions & 37 deletions libcxxabi/src/demangle/ItaniumDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,20 +283,11 @@ class Node {
}

void print(OutputBuffer &OB) const {
printLeft(OB);
OB.printLeft(*this);
if (RHSComponentCache != Cache::No)
printRight(OB);
OB.printRight(*this);
}

// Print the "left" side of this Node into OutputBuffer.
virtual void printLeft(OutputBuffer &) const = 0;

// Print the "right". This distinction is necessary to represent C++ types
// that appear on the RHS of their subtype, such as arrays or functions.
// Since most types don't have such a component, provide a default
// implementation.
virtual void printRight(OutputBuffer &) const {}

// Print an initializer list of this type. Returns true if we printed a custom
// representation, false if nothing has been printed and the default
// representation should be used.
Expand All @@ -312,6 +303,24 @@ class Node {
#ifndef NDEBUG
DEMANGLE_DUMP_METHOD void dump() const;
#endif

private:
friend class OutputBuffer;

// Print the "left" side of this Node into OutputBuffer.
//
// Note, should only be called from OutputBuffer implementations.
// Call \ref OutputBuffer::printLeft instead.
virtual void printLeft(OutputBuffer &) const = 0;

// Print the "right". This distinction is necessary to represent C++ types
// that appear on the RHS of their subtype, such as arrays or functions.
// Since most types don't have such a component, provide a default
// implementation.
//
// Note, should only be called from OutputBuffer implementations.
// Call \ref OutputBuffer::printRight instead.
virtual void printRight(OutputBuffer &) const {}
};

class NodeArray {
Expand Down Expand Up @@ -460,11 +469,11 @@ class QualType final : public Node {
}

void printLeft(OutputBuffer &OB) const override {
Child->printLeft(OB);
OB.printLeft(*Child);
printQuals(OB);
}

void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); }
};

class ConversionOperatorType final : public Node {
Expand Down Expand Up @@ -493,7 +502,7 @@ class PostfixQualifiedType final : public Node {
template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }

void printLeft(OutputBuffer &OB) const override {
Ty->printLeft(OB);
OB.printLeft(*Ty);
OB += Postfix;
}
};
Expand Down Expand Up @@ -579,7 +588,7 @@ struct AbiTagAttr : Node {
std::string_view getBaseName() const override { return Base->getBaseName(); }

void printLeft(OutputBuffer &OB) const override {
Base->printLeft(OB);
OB.printLeft(*Base);
OB += "[abi:";
OB += Tag;
OB += "]";
Expand Down Expand Up @@ -646,7 +655,7 @@ class PointerType final : public Node {
// We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
if (Pointee->getKind() != KObjCProtoName ||
!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Pointee->printLeft(OB);
OB.printLeft(*Pointee);
if (Pointee->hasArray(OB))
OB += " ";
if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
Expand All @@ -665,7 +674,7 @@ class PointerType final : public Node {
!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
OB += ")";
Pointee->printRight(OB);
OB.printRight(*Pointee);
}
}
};
Expand Down Expand Up @@ -731,7 +740,7 @@ class ReferenceType : public Node {
std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
if (!Collapsed.second)
return;
Collapsed.second->printLeft(OB);
OB.printLeft(*Collapsed.second);
if (Collapsed.second->hasArray(OB))
OB += " ";
if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
Expand All @@ -748,7 +757,7 @@ class ReferenceType : public Node {
return;
if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
OB += ")";
Collapsed.second->printRight(OB);
OB.printRight(*Collapsed.second);
}
};

Expand All @@ -768,7 +777,7 @@ class PointerToMemberType final : public Node {
}

void printLeft(OutputBuffer &OB) const override {
MemberType->printLeft(OB);
OB.printLeft(*MemberType);
if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
OB += "(";
else
Expand All @@ -780,7 +789,7 @@ class PointerToMemberType final : public Node {
void printRight(OutputBuffer &OB) const override {
if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
OB += ")";
MemberType->printRight(OB);
OB.printRight(*MemberType);
}
};

Expand All @@ -800,7 +809,7 @@ class ArrayType final : public Node {
bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
bool hasArraySlow(OutputBuffer &) const override { return true; }

void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); }

void printRight(OutputBuffer &OB) const override {
if (OB.back() != ']')
Expand All @@ -809,7 +818,7 @@ class ArrayType final : public Node {
if (Dimension)
Dimension->print(OB);
OB += "]";
Base->printRight(OB);
OB.printRight(*Base);
}

bool printInitListAsType(OutputBuffer &OB,
Expand Down Expand Up @@ -853,15 +862,15 @@ class FunctionType final : public Node {
// by printing out the return types's left, then print our parameters, then
// finally print right of the return type.
void printLeft(OutputBuffer &OB) const override {
Ret->printLeft(OB);
OB.printLeft(*Ret);
OB += " ";
}

void printRight(OutputBuffer &OB) const override {
OB.printOpen();
Params.printWithComma(OB);
OB.printClose();
Ret->printRight(OB);
OB.printRight(*Ret);

if (CVQuals & QualConst)
OB += " const";
Expand Down Expand Up @@ -966,6 +975,8 @@ class FunctionEncoding final : public Node {
FunctionRefQual getRefQual() const { return RefQual; }
NodeArray getParams() const { return Params; }
const Node *getReturnType() const { return Ret; }
const Node *getAttrs() const { return Attrs; }
const Node *getRequires() const { return Requires; }

bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Expand All @@ -974,19 +985,21 @@ class FunctionEncoding final : public Node {

void printLeft(OutputBuffer &OB) const override {
if (Ret) {
Ret->printLeft(OB);
OB.printLeft(*Ret);
if (!Ret->hasRHSComponent(OB))
OB += " ";
}

Name->print(OB);
}

void printRight(OutputBuffer &OB) const override {
OB.printOpen();
Params.printWithComma(OB);
OB.printClose();

if (Ret)
Ret->printRight(OB);
OB.printRight(*Ret);

if (CVQuals & QualConst)
OB += " const";
Expand Down Expand Up @@ -1326,14 +1339,14 @@ class NonTypeTemplateParamDecl final : public Node {
template<typename Fn> void match(Fn F) const { F(Name, Type); }

void printLeft(OutputBuffer &OB) const override {
Type->printLeft(OB);
OB.printLeft(*Type);
if (!Type->hasRHSComponent(OB))
OB += " ";
}

void printRight(OutputBuffer &OB) const override {
Name->print(OB);
Type->printRight(OB);
OB.printRight(*Type);
}
};

Expand Down Expand Up @@ -1378,11 +1391,11 @@ class TemplateParamPackDecl final : public Node {
template<typename Fn> void match(Fn F) const { F(Param); }

void printLeft(OutputBuffer &OB) const override {
Param->printLeft(OB);
OB.printLeft(*Param);
OB += "...";
}

void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); }
};

/// An unexpanded parameter pack (either in the expression or type context). If
Expand Down Expand Up @@ -1447,13 +1460,13 @@ class ParameterPack final : public Node {
initializePackExpansion(OB);
size_t Idx = OB.CurrentPackIndex;
if (Idx < Data.size())
Data[Idx]->printLeft(OB);
OB.printLeft(*Data[Idx]);
}
void printRight(OutputBuffer &OB) const override {
initializePackExpansion(OB);
size_t Idx = OB.CurrentPackIndex;
if (Idx < Data.size())
Data[Idx]->printRight(OB);
OB.printRight(*Data[Idx]);
}
};

Expand Down Expand Up @@ -1611,13 +1624,13 @@ struct ForwardTemplateReference : Node {
if (Printing)
return;
ScopedOverride<bool> SavePrinting(Printing, true);
Ref->printLeft(OB);
OB.printLeft(*Ref);
}
void printRight(OutputBuffer &OB) const override {
if (Printing)
return;
ScopedOverride<bool> SavePrinting(Printing, true);
Ref->printRight(OB);
OB.printRight(*Ref);
}
};

Expand Down Expand Up @@ -1769,7 +1782,7 @@ class DtorName : public Node {

void printLeft(OutputBuffer &OB) const override {
OB += "~";
Base->printLeft(OB);
OB.printLeft(*Base);
}
};

Expand Down Expand Up @@ -2049,7 +2062,7 @@ class CastExpr : public Node {
{
ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
OB += "<";
To->printLeft(OB);
OB.printLeft(*To);
OB += ">";
}
OB.printOpen();
Expand Down Expand Up @@ -6180,6 +6193,10 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
Alloc>::AbstractManglingParser;
};

inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); }

inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); }

DEMANGLE_NAMESPACE_END

#if defined(__clang__)
Expand Down
26 changes: 25 additions & 1 deletion libcxxabi/src/demangle/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

DEMANGLE_NAMESPACE_BEGIN

class Node;

// Stream that AST nodes write their string representation into after the AST
// has been parsed.
class OutputBuffer {
Expand Down Expand Up @@ -79,10 +81,24 @@ class OutputBuffer {
OutputBuffer(const OutputBuffer &) = delete;
OutputBuffer &operator=(const OutputBuffer &) = delete;

virtual ~OutputBuffer() {}

operator std::string_view() const {
return std::string_view(Buffer, CurrentPosition);
}

/// Called by the demangler when printing the demangle tree. By
/// default calls into \c Node::print{Left|Right} but can be overriden
/// by clients to track additional state when printing the demangled name.
virtual void printLeft(const Node &N);
virtual void printRight(const Node &N);

/// Called when we write to this object anywhere other than the end.
virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {}

/// Called when we make the \c CurrentPosition of this object smaller.
virtual void notifyDeletion(size_t /*OldPos*/, size_t /*NewPos*/) {}

/// If a ParameterPackExpansion (or similar type) is encountered, the offset
/// into the pack that we're currently printing.
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
Expand Down Expand Up @@ -126,6 +142,8 @@ class OutputBuffer {
std::memcpy(Buffer, &*R.begin(), Size);
CurrentPosition += Size;

notifyInsertion(/*Position=*/0, /*Count=*/Size);

return *this;
}

Expand Down Expand Up @@ -161,14 +179,20 @@ class OutputBuffer {
DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
if (N == 0)
return;

grow(N);
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
std::memcpy(Buffer + Pos, S, N);
CurrentPosition += N;

notifyInsertion(Pos, N);
}

size_t getCurrentPosition() const { return CurrentPosition; }
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
void setCurrentPosition(size_t NewPos) {
notifyDeletion(CurrentPosition, NewPos);
CurrentPosition = NewPos;
}

char back() const {
DEMANGLE_ASSERT(CurrentPosition, "");
Expand Down
Loading
Loading