1 //===-- Mangled.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_MANGLED_H
10 #define LLDB_CORE_MANGLED_H
11 #if defined(__cplusplus)
12 
13 #include "lldb/lldb-enumerations.h"
14 #include "lldb/lldb-forward.h"
15 
16 #include "lldb/Utility/ConstString.h"
17 
18 #include "llvm/ADT/StringRef.h"
19 
20 #include <memory>
21 #include <stddef.h>
22 
23 namespace lldb_private {
24 
25 /// \class Mangled Mangled.h "lldb/Core/Mangled.h"
26 /// A class that handles mangled names.
27 ///
28 /// Designed to handle mangled names. The demangled version of any names will
29 /// be computed when the demangled name is accessed through the Demangled()
30 /// acccessor. This class can also tokenize the demangled version of the name
31 /// for powerful searches. Functions and symbols could make instances of this
32 /// class for their mangled names. Uniqued string pools are used for the
33 /// mangled, demangled, and token string values to allow for faster
34 /// comparisons and for efficient memory use.
35 class Mangled {
36 public:
37   enum NamePreference {
38     ePreferMangled,
39     ePreferDemangled,
40     ePreferDemangledWithoutArguments
41   };
42 
43   enum ManglingScheme {
44     eManglingSchemeNone = 0,
45     eManglingSchemeMSVC,
46     eManglingSchemeItanium
47   };
48 
49   /// Default constructor.
50   ///
51   /// Initialize with both mangled and demangled names empty.
52   Mangled() = default;
53 
54   /// Construct with name.
55   ///
56   /// Constructor with an optional string and auto-detect if \a name is
57   /// mangled or not.
58   ///
59   /// \param[in] name
60   ///     The already const name to copy into this object.
61   explicit Mangled(ConstString name);
62 
63   explicit Mangled(llvm::StringRef name);
64 
65   /// Convert to pointer operator.
66   ///
67   /// This allows code to check a Mangled object to see if it contains a valid
68   /// mangled name using code such as:
69   ///
70   /// \code
71   /// Mangled mangled(...);
72   /// if (mangled)
73   /// { ...
74   /// \endcode
75   ///
76   /// \return
77   ///     A pointer to this object if either the mangled or unmangled
78   ///     name is set, NULL otherwise.
79   operator void *() const;
80 
81   /// Logical NOT operator.
82   ///
83   /// This allows code to check a Mangled object to see if it contains an
84   /// empty mangled name using code such as:
85   ///
86   /// \code
87   /// Mangled mangled(...);
88   /// if (!mangled)
89   /// { ...
90   /// \endcode
91   ///
92   /// \return
93   ///     Returns \b true if the object has an empty mangled and
94   ///     unmangled name, \b false otherwise.
95   bool operator!() const;
96 
97   /// Clear the mangled and demangled values.
98   void Clear();
99 
100   /// Compare the mangled string values
101   ///
102   /// Compares the Mangled::GetName() string in \a lhs and \a rhs.
103   ///
104   /// \param[in] lhs
105   ///     A const reference to the Left Hand Side object to compare.
106   ///
107   /// \param[in] rhs
108   ///     A const reference to the Right Hand Side object to compare.
109   ///
110   /// \return
111   ///     -1 if \a lhs is less than \a rhs
112   ///     0 if \a lhs is equal to \a rhs
113   ///     1 if \a lhs is greater than \a rhs
114   static int Compare(const Mangled &lhs, const Mangled &rhs);
115 
116   /// Dump a description of this object to a Stream \a s.
117   ///
118   /// Dump a Mangled object to stream \a s. We don't force our demangled name
119   /// to be computed currently (we don't use the accessor).
120   ///
121   /// \param[in] s
122   ///     The stream to which to dump the object description.
123   void Dump(Stream *s) const;
124 
125   /// Dump a debug description of this object to a Stream \a s.
126   ///
127   /// \param[in] s
128   ///     The stream to which to dump the object description.
129   void DumpDebug(Stream *s) const;
130 
131   /// Demangled name get accessor.
132   ///
133   /// \return
134   ///     A const reference to the demangled name string object.
135   ConstString GetDemangledName() const;
136 
137   /// Display demangled name get accessor.
138   ///
139   /// \return
140   ///     A const reference to the display demangled name string object.
141   ConstString GetDisplayDemangledName() const;
142 
143   void SetDemangledName(ConstString name) { m_demangled = name; }
144 
145   void SetMangledName(ConstString name) { m_mangled = name; }
146 
147   /// Mangled name get accessor.
148   ///
149   /// \return
150   ///     A reference to the mangled name string object.
151   ConstString &GetMangledName() { return m_mangled; }
152 
153   /// Mangled name get accessor.
154   ///
155   /// \return
156   ///     A const reference to the mangled name string object.
157   ConstString GetMangledName() const { return m_mangled; }
158 
159   /// Best name get accessor.
160   ///
161   /// \param[in] preference
162   ///     Which name would you prefer to get?
163   ///
164   /// \return
165   ///     A const reference to the preferred name string object if this
166   ///     object has a valid name of that kind, else a const reference to the
167   ///     other name is returned.
168   ConstString GetName(NamePreference preference = ePreferDemangled) const;
169 
170   /// Check if "name" matches either the mangled or demangled name.
171   ///
172   /// \param[in] name
173   ///     A name to match against both strings.
174   ///
175   /// \return
176   ///     \b True if \a name matches either name, \b false otherwise.
177   bool NameMatches(ConstString name) const {
178     if (m_mangled == name)
179       return true;
180     return GetDemangledName() == name;
181   }
182   bool NameMatches(const RegularExpression &regex) const;
183 
184   /// Get the memory cost of this object.
185   ///
186   /// Return the size in bytes that this object takes in memory. This returns
187   /// the size in bytes of this object, not any shared string values it may
188   /// refer to.
189   ///
190   /// \return
191   ///     The number of bytes that this object occupies in memory.
192   ///
193   /// \see ConstString::StaticMemorySize ()
194   size_t MemorySize() const;
195 
196   /// Set the string value in this object.
197   ///
198   /// If \a is_mangled is \b true, then the mangled named is set to \a name,
199   /// else the demangled name is set to \a name.
200   ///
201   /// \param[in] name
202   ///     The already const version of the name for this object.
203   ///
204   /// \param[in] is_mangled
205   ///     If \b true then \a name is a mangled name, if \b false then
206   ///     \a name is demangled.
207   void SetValue(ConstString name, bool is_mangled);
208 
209   /// Set the string value in this object.
210   ///
211   /// This version auto detects if the string is mangled by inspecting the
212   /// string value and looking for common mangling prefixes.
213   ///
214   /// \param[in] name
215   ///     The already const version of the name for this object.
216   void SetValue(ConstString name);
217 
218   /// Try to guess the language from the mangling.
219   ///
220   /// For a mangled name to have a language it must have both a mangled and a
221   /// demangled name and it can be guessed from the mangling what the language
222   /// is.  Note: this will return C++ for any language that uses Itanium ABI
223   /// mangling.
224   ///
225   /// Standard C function names will return eLanguageTypeUnknown because they
226   /// aren't mangled and it isn't clear what language the name represents
227   /// (there will be no mangled name).
228   ///
229   /// \return
230   ///     The language for the mangled/demangled name, eLanguageTypeUnknown
231   ///     if there is no mangled or demangled counterpart.
232   lldb::LanguageType GuessLanguage() const;
233 
234   /// Function signature for filtering mangled names.
235   using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);
236 
237   /// Trigger explicit demangling to obtain rich mangling information. This is
238   /// optimized for batch processing while populating a name index. To get the
239   /// pure demangled name string for a single entity, use GetDemangledName()
240   /// instead.
241   ///
242   /// For names that match the Itanium mangling scheme, this uses LLVM's
243   /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
244   /// parser currently.
245   ///
246   /// This function is thread-safe when used with different \a context
247   /// instances in different threads.
248   ///
249   /// \param[in] context
250   ///     The context for this function. A single instance can be stack-
251   ///     allocated in the caller's frame and used for multiple calls.
252   ///
253   /// \param[in] skip_mangled_name
254   ///     A filtering function for skipping entities based on name and mangling
255   ///     scheme. This can be null if unused.
256   ///
257   /// \return
258   ///     True on success, false otherwise.
259   bool DemangleWithRichManglingInfo(RichManglingContext &context,
260                                     SkipMangledNameFn *skip_mangled_name);
261 
262   /// Try to identify the mangling scheme used.
263   /// \param[in] name
264   ///     The name we are attempting to identify the mangling scheme for.
265   ///
266   /// \return
267   ///     eManglingSchemeNone if no known mangling scheme could be identified
268   ///     for s, otherwise the enumerator for the mangling scheme detected.
269   static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);
270 
271 private:
272   /// Mangled member variables.
273   ConstString m_mangled;           ///< The mangled version of the name
274   mutable ConstString m_demangled; ///< Mutable so we can get it on demand with
275                                    ///a const version of this object
276 };
277 
278 Stream &operator<<(Stream &s, const Mangled &obj);
279 
280 } // namespace lldb_private
281 
282 #endif // #if defined(__cplusplus)
283 #endif // LLDB_CORE_MANGLED_H
284