xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Core/DemangledNameInfo.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- DemangledNameInfo.h -------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_CORE_DEMANGLEDNAMEINFO_H
10 #define LLDB_CORE_DEMANGLEDNAMEINFO_H
11 
12 #include "llvm/Demangle/ItaniumDemangle.h"
13 #include "llvm/Demangle/Utility.h"
14 
15 #include <cstddef>
16 #include <utility>
17 
18 namespace lldb_private {
19 
20 /// Stores information about where certain portions of a demangled
21 /// function name begin and end.
22 struct DemangledNameInfo {
23   /// A [start, end) pair for the function basename.
24   /// The basename is the name without scope qualifiers
25   /// and without template parameters. E.g.,
26   /// \code{.cpp}
27   ///    void foo::bar<int>::someFunc<float>(int) const &&
28   ///                        ^       ^
29   ///                      start    end
30   /// \endcode
31   std::pair<size_t, size_t> BasenameRange;
32 
33   /// A [start, end) pair for the function scope qualifiers.
34   /// E.g., for
35   /// \code{.cpp}
36   ///    void foo::bar<int>::qux<float>(int) const &&
37   ///         ^              ^
38   ///       start           end
39   /// \endcode
40   std::pair<size_t, size_t> ScopeRange;
41 
42   /// Indicates the [start, end) of the function argument list.
43   /// E.g.,
44   /// \code{.cpp}
45   ///    int (*getFunc<float>(float, double))(int, int)
46   ///                        ^              ^
47   ///                      start           end
48   /// \endcode
49   std::pair<size_t, size_t> ArgumentsRange;
50 
51   /// Indicates the [start, end) of the function qualifiers
52   /// (e.g., CV-qualifiers, reference qualifiers, requires clauses).
53   ///
54   /// E.g.,
55   /// \code{.cpp}
56   ///    void foo::bar<int>::qux<float>(int) const &&
57   ///                                       ^        ^
58   ///                                     start     end
59   /// \endcode
60   std::pair<size_t, size_t> QualifiersRange;
61 
62   /// Indicates the [start, end) of the function's prefix. This is a
63   /// catch-all range for anything that is not tracked by the rest of
64   /// the pairs.
65   std::pair<size_t, size_t> PrefixRange;
66 
67   /// Indicates the [start, end) of the function's suffix. This is a
68   /// catch-all range for anything that is not tracked by the rest of
69   /// the pairs.
70   std::pair<size_t, size_t> SuffixRange;
71 
72   /// Returns \c true if this object holds a valid basename range.
hasBasenameDemangledNameInfo73   bool hasBasename() const {
74     // A function always has a name.
75     return BasenameRange.second > BasenameRange.first;
76   }
77 
78   /// Returns \c true if this object holds a valid scope range.
hasScopeDemangledNameInfo79   bool hasScope() const { return ScopeRange.second >= ScopeRange.first; }
80 
81   /// Returns \c true if this object holds a valid arguments range.
hasArgumentsDemangledNameInfo82   bool hasArguments() const {
83     return ArgumentsRange.second >= ArgumentsRange.first;
84   }
85 
86   /// Returns \c true if this object holds a valid qualifiers range.
hasQualifiersDemangledNameInfo87   bool hasQualifiers() const {
88     return QualifiersRange.second >= QualifiersRange.first;
89   }
90 
91   /// Returns \c true if this object holds a valid prefix range.
hasPrefixDemangledNameInfo92   bool hasPrefix() const { return PrefixRange.second >= PrefixRange.first; }
93 
94   /// Returns \c true if this object holds a valid suffix range.
hasSuffixDemangledNameInfo95   bool hasSuffix() const { return SuffixRange.second >= SuffixRange.first; }
96 };
97 
98 /// An OutputBuffer which keeps a record of where certain parts of a
99 /// demangled name begin/end (e.g., basename, scope, argument list, etc.).
100 /// The tracking occurs during printing of the Itanium demangle tree.
101 ///
102 /// Usage:
103 /// \code{.cpp}
104 ///
105 /// Node *N = mangling_parser.parseType();
106 ///
107 /// TrackingOutputBuffer buffer;
108 /// N->printLeft(OB);
109 ///
110 /// assert (buffer.NameInfo.hasBasename());
111 ///
112 /// \endcode
113 struct TrackingOutputBuffer : public llvm::itanium_demangle::OutputBuffer {
114   using OutputBuffer::OutputBuffer;
115 
116   /// Holds information about the demangled name that is
117   /// being printed into this buffer.
118   DemangledNameInfo NameInfo;
119 
120   void printLeft(const llvm::itanium_demangle::Node &N) override;
121   void printRight(const llvm::itanium_demangle::Node &N) override;
122 
123 private:
124   void printLeftImpl(const llvm::itanium_demangle::FunctionType &N);
125   void printRightImpl(const llvm::itanium_demangle::FunctionType &N);
126 
127   void printLeftImpl(const llvm::itanium_demangle::FunctionEncoding &N);
128   void printRightImpl(const llvm::itanium_demangle::FunctionEncoding &N);
129 
130   void printLeftImpl(const llvm::itanium_demangle::NestedName &N);
131   void printLeftImpl(const llvm::itanium_demangle::NameWithTemplateArgs &N);
132 
133   /// Called whenever we start printing a function type in the Itanium
134   /// mangling scheme. Examples include \ref FunctionEncoding, \ref
135   /// FunctionType, etc.
136   ///
137   /// \returns A ScopedOverride which will update the nesting depth of
138   /// currently printed function types on destruction.
139   [[nodiscard]] llvm::itanium_demangle::ScopedOverride<unsigned>
140   enterFunctionTypePrinting();
141 
142   /// Returns \c true if we're not printing any nested function types,
143   /// just a \ref FunctionEncoding in the Itanium mangling scheme.
144   bool isPrintingTopLevelFunctionType() const;
145 
146   /// If this object \ref shouldTrack, then update the end of
147   /// the basename range to the current \c OB position.
148   void updateBasenameEnd();
149 
150   /// If this object \ref shouldTrack, then update the beginning
151   /// of the scope range to the current \c OB position.
152   void updateScopeStart();
153 
154   /// If this object \ref shouldTrack, then update the end of
155   /// the scope range to the current \c OB position.
156   void updateScopeEnd();
157 
158   /// Returns \c true if the members of this object can be
159   /// updated. E.g., when we're printing nested template
160   /// arguments, we don't need to be tracking basename
161   /// locations.
162   bool shouldTrack() const;
163 
164   /// Helpers called to track beginning and end of the function
165   /// arguments.
166   void finalizeArgumentEnd();
167   void finalizeStart();
168   void finalizeEnd();
169   void finalizeQualifiersStart();
170   void finalizeQualifiersEnd();
171 
172   /// Helper used in the finalize APIs.
173   bool canFinalize() const;
174 
175   /// Incremented each time we start printing a function type node
176   /// in the Itanium mangling scheme (e.g., \ref FunctionEncoding
177   /// or \ref FunctionType).
178   unsigned FunctionPrintingDepth = 0;
179 };
180 } // namespace lldb_private
181 
182 #endif // LLDB_CORE_DEMANGLEDNAMEINFO_H
183