Skip to content

Commit 03a4172

Browse files
committed
[llvm][ItaniumDemangle] Add function name location tracking
1 parent 0a21ef9 commit 03a4172

File tree

5 files changed

+439
-32
lines changed

5 files changed

+439
-32
lines changed

libcxxabi/src/demangle/ItaniumDemangle.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,11 +851,13 @@ class FunctionType final : public Node {
851851
// by printing out the return types's left, then print our parameters, then
852852
// finally print right of the return type.
853853
void printLeft(OutputBuffer &OB) const override {
854+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
854855
Ret->printLeft(OB);
855856
OB += " ";
856857
}
857858

858859
void printRight(OutputBuffer &OB) const override {
860+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
859861
OB.printOpen();
860862
Params.printWithComma(OB);
861863
OB.printClose();
@@ -976,13 +978,26 @@ class FunctionEncoding final : public Node {
976978
if (!Ret->hasRHSComponent(OB))
977979
OB += " ";
978980
}
981+
982+
// Nested FunctionEncoding parsing can happen with following productions:
983+
// * <local-name>
984+
// * <expr-primary>
985+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
986+
OB.FunctionInfo.updateScopeStart(OB);
987+
979988
Name->print(OB);
980989
}
981990

982991
void printRight(OutputBuffer &OB) const override {
992+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
993+
OB.FunctionInfo.finalizeStart(OB);
994+
983995
OB.printOpen();
984996
Params.printWithComma(OB);
985997
OB.printClose();
998+
999+
OB.FunctionInfo.finalizeArgumentEnd(OB);
1000+
9861001
if (Ret)
9871002
Ret->printRight(OB);
9881003

@@ -1005,6 +1020,8 @@ class FunctionEncoding final : public Node {
10051020
OB += " requires ";
10061021
Requires->print(OB);
10071022
}
1023+
1024+
OB.FunctionInfo.finalizeEnd(OB);
10081025
}
10091026
};
10101027

@@ -1072,7 +1089,9 @@ struct NestedName : Node {
10721089
void printLeft(OutputBuffer &OB) const override {
10731090
Qual->print(OB);
10741091
OB += "::";
1092+
OB.FunctionInfo.updateScopeEnd(OB);
10751093
Name->print(OB);
1094+
OB.FunctionInfo.updateBasenameEnd(OB);
10761095
}
10771096
};
10781097

@@ -1633,6 +1652,7 @@ struct NameWithTemplateArgs : Node {
16331652

16341653
void printLeft(OutputBuffer &OB) const override {
16351654
Name->print(OB);
1655+
OB.FunctionInfo.updateBasenameEnd(OB);
16361656
TemplateArgs->print(OB);
16371657
}
16381658
};

libcxxabi/src/demangle/Utility.h

Lines changed: 147 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@
2727

2828
DEMANGLE_NAMESPACE_BEGIN
2929

30+
template <class T> class ScopedOverride {
31+
T &Loc;
32+
T Original;
33+
34+
public:
35+
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
36+
37+
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
38+
Loc_ = std::move(NewVal);
39+
}
40+
~ScopedOverride() { Loc = std::move(Original); }
41+
42+
ScopedOverride(const ScopedOverride &) = delete;
43+
ScopedOverride &operator=(const ScopedOverride &) = delete;
44+
};
45+
3046
// Stream that AST nodes write their string representation into after the AST
3147
// has been parsed.
3248
class OutputBuffer {
@@ -83,6 +99,127 @@ class OutputBuffer {
8399
return std::string_view(Buffer, CurrentPosition);
84100
}
85101

102+
// Stores information about parts of a demangled function name.
103+
struct FunctionNameInfo {
104+
///< A [start, end) pair for the function basename.
105+
///< The basename is the name without scope qualifiers
106+
///< and without template parameters. E.g.,
107+
///< \code{.cpp}
108+
///< void foo::bar<int>::someFunc<float>(int) const &&
109+
///< ^ ^
110+
///< Start End
111+
///< \endcode
112+
std::pair<size_t, size_t> BasenameLocs;
113+
114+
///< A [start, end) pair for the function scope qualifiers.
115+
///< E.g., for
116+
///< \code{.cpp}
117+
///< void foo::bar<int>::qux<float>(int) const &&
118+
///< ^ ^
119+
///< Start End
120+
///< \endcode
121+
std::pair<size_t, size_t> ScopeLocs;
122+
123+
///< Indicates the [start, end) of the function argument lits.
124+
///< E.g.,
125+
///< \code{.cpp}
126+
///< int (*getFunc<float>(float, double))(int, int)
127+
///< ^ ^
128+
///< start end
129+
///< \endcode
130+
std::pair<size_t, size_t> ArgumentLocs;
131+
132+
bool startedPrintingArguments() const { return ArgumentLocs.first > 0; }
133+
134+
bool shouldTrack(OutputBuffer &OB) const {
135+
if (OB.isPrintingNestedFunctionType())
136+
return false;
137+
138+
if (OB.isGtInsideTemplateArgs())
139+
return false;
140+
141+
if (startedPrintingArguments())
142+
return false;
143+
144+
return true;
145+
}
146+
147+
bool canFinalize(OutputBuffer &OB) const {
148+
if (OB.isPrintingNestedFunctionType())
149+
return false;
150+
151+
if (OB.isGtInsideTemplateArgs())
152+
return false;
153+
154+
if (!startedPrintingArguments())
155+
return false;
156+
157+
return true;
158+
}
159+
160+
void updateBasenameEnd(OutputBuffer &OB) {
161+
if (!shouldTrack(OB))
162+
return;
163+
164+
BasenameLocs.second = OB.getCurrentPosition();
165+
}
166+
167+
void updateScopeStart(OutputBuffer &OB) {
168+
if (!shouldTrack(OB))
169+
return;
170+
171+
ScopeLocs.first = OB.getCurrentPosition();
172+
}
173+
174+
void updateScopeEnd(OutputBuffer &OB) {
175+
if (!shouldTrack(OB))
176+
return;
177+
178+
ScopeLocs.second = OB.getCurrentPosition();
179+
}
180+
181+
void finalizeArgumentEnd(OutputBuffer &OB) {
182+
if (!canFinalize(OB))
183+
return;
184+
185+
OB.FunctionInfo.ArgumentLocs.second = OB.getCurrentPosition();
186+
}
187+
188+
void finalizeStart(OutputBuffer &OB) {
189+
if (!shouldTrack(OB))
190+
return;
191+
192+
OB.FunctionInfo.ArgumentLocs.first = OB.getCurrentPosition();
193+
194+
// If nothing has set the end of the basename yet (for example when
195+
// printing templates), then the beginning of the arguments is the end of
196+
// the basename.
197+
if (BasenameLocs.second == 0)
198+
OB.FunctionInfo.BasenameLocs.second = OB.getCurrentPosition();
199+
200+
DEMANGLE_ASSERT(!shouldTrack(OB), "");
201+
DEMANGLE_ASSERT(canFinalize(OB), "");
202+
}
203+
204+
void finalizeEnd(OutputBuffer &OB) {
205+
if (!canFinalize(OB))
206+
return;
207+
208+
if (ScopeLocs.first > OB.FunctionInfo.ScopeLocs.second)
209+
ScopeLocs.second = OB.FunctionInfo.ScopeLocs.first;
210+
BasenameLocs.first = OB.FunctionInfo.ScopeLocs.second;
211+
}
212+
213+
ScopedOverride<unsigned> enterFunctionTypePrinting(OutputBuffer &OB) {
214+
return {OB.FunctionPrintingDepth, OB.FunctionPrintingDepth + 1};
215+
}
216+
217+
bool hasBasename() const {
218+
return BasenameLocs.first != BasenameLocs.second &&
219+
BasenameLocs.second > 0;
220+
}
221+
};
222+
86223
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
87224
/// into the pack that we're currently printing.
88225
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
@@ -92,8 +229,18 @@ class OutputBuffer {
92229
/// Use a counter so we can simply increment inside parentheses.
93230
unsigned GtIsGt = 1;
94231

232+
///< When a function type is being printed this value is incremented.
233+
///< When printing of the type is finished the value is decremented.
234+
unsigned FunctionPrintingDepth = 0;
235+
236+
FunctionNameInfo FunctionInfo;
237+
95238
bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
96239

240+
bool isPrintingNestedFunctionType() const {
241+
return FunctionPrintingDepth != 1;
242+
}
243+
97244
void printOpen(char Open = '(') {
98245
GtIsGt++;
99246
*this += Open;
@@ -182,22 +329,6 @@ class OutputBuffer {
182329
size_t getBufferCapacity() const { return BufferCapacity; }
183330
};
184331

185-
template <class T> class ScopedOverride {
186-
T &Loc;
187-
T Original;
188-
189-
public:
190-
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
191-
192-
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
193-
Loc_ = std::move(NewVal);
194-
}
195-
~ScopedOverride() { Loc = std::move(Original); }
196-
197-
ScopedOverride(const ScopedOverride &) = delete;
198-
ScopedOverride &operator=(const ScopedOverride &) = delete;
199-
};
200-
201332
DEMANGLE_NAMESPACE_END
202333

203334
#endif

llvm/include/llvm/Demangle/ItaniumDemangle.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,11 +851,13 @@ class FunctionType final : public Node {
851851
// by printing out the return types's left, then print our parameters, then
852852
// finally print right of the return type.
853853
void printLeft(OutputBuffer &OB) const override {
854+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
854855
Ret->printLeft(OB);
855856
OB += " ";
856857
}
857858

858859
void printRight(OutputBuffer &OB) const override {
860+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
859861
OB.printOpen();
860862
Params.printWithComma(OB);
861863
OB.printClose();
@@ -976,13 +978,26 @@ class FunctionEncoding final : public Node {
976978
if (!Ret->hasRHSComponent(OB))
977979
OB += " ";
978980
}
981+
982+
// Nested FunctionEncoding parsing can happen with following productions:
983+
// * <local-name>
984+
// * <expr-primary>
985+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
986+
OB.FunctionInfo.updateScopeStart(OB);
987+
979988
Name->print(OB);
980989
}
981990

982991
void printRight(OutputBuffer &OB) const override {
992+
auto Scoped = OB.FunctionInfo.enterFunctionTypePrinting(OB);
993+
OB.FunctionInfo.finalizeStart(OB);
994+
983995
OB.printOpen();
984996
Params.printWithComma(OB);
985997
OB.printClose();
998+
999+
OB.FunctionInfo.finalizeArgumentEnd(OB);
1000+
9861001
if (Ret)
9871002
Ret->printRight(OB);
9881003

@@ -1005,6 +1020,8 @@ class FunctionEncoding final : public Node {
10051020
OB += " requires ";
10061021
Requires->print(OB);
10071022
}
1023+
1024+
OB.FunctionInfo.finalizeEnd(OB);
10081025
}
10091026
};
10101027

@@ -1072,7 +1089,9 @@ struct NestedName : Node {
10721089
void printLeft(OutputBuffer &OB) const override {
10731090
Qual->print(OB);
10741091
OB += "::";
1092+
OB.FunctionInfo.updateScopeEnd(OB);
10751093
Name->print(OB);
1094+
OB.FunctionInfo.updateBasenameEnd(OB);
10761095
}
10771096
};
10781097

@@ -1633,6 +1652,7 @@ struct NameWithTemplateArgs : Node {
16331652

16341653
void printLeft(OutputBuffer &OB) const override {
16351654
Name->print(OB);
1655+
OB.FunctionInfo.updateBasenameEnd(OB);
16361656
TemplateArgs->print(OB);
16371657
}
16381658
};

0 commit comments

Comments
 (0)