1 //===-- CPlusPlusNameParser.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_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 10 #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 11 12 #include "clang/Lex/Lexer.h" 13 #include "llvm/ADT/SmallVector.h" 14 #include "llvm/ADT/StringRef.h" 15 16 #include "lldb/Utility/ConstString.h" 17 #include "lldb/lldb-private.h" 18 #include <optional> 19 20 namespace lldb_private { 21 22 // Helps to validate and obtain various parts of C++ definitions. 23 class CPlusPlusNameParser { 24 public: CPlusPlusNameParser(llvm::StringRef text)25 CPlusPlusNameParser(llvm::StringRef text) : m_text(text) { ExtractTokens(); } 26 27 struct ParsedName { 28 llvm::StringRef basename; 29 llvm::StringRef context; 30 }; 31 32 struct ParsedFunction { 33 ParsedName name; 34 llvm::StringRef arguments; 35 llvm::StringRef qualifiers; 36 llvm::StringRef return_type; 37 }; 38 39 // Treats given text as a function definition and parses it. 40 // Function definition might or might not have a return type and this should 41 // change parsing result. 42 // Examples: 43 // main(int, chat const*) 44 // T fun(int, bool) 45 // std::vector<int>::push_back(int) 46 // int& map<int, pair<short, int>>::operator[](short) const 47 // int (*get_function(const chat *))() 48 std::optional<ParsedFunction> ParseAsFunctionDefinition(); 49 50 // Treats given text as a potentially nested name of C++ entity (function, 51 // class, field) and parses it. 52 // Examples: 53 // main 54 // fun 55 // std::vector<int>::push_back 56 // map<int, pair<short, int>>::operator[] 57 // func<C>(int, C&)::nested_class::method 58 std::optional<ParsedName> ParseAsFullName(); 59 60 private: 61 // A C++ definition to parse. 62 llvm::StringRef m_text; 63 // Tokens extracted from m_text. 64 llvm::SmallVector<clang::Token, 30> m_tokens; 65 // Index of the next token to look at from m_tokens. 66 size_t m_next_token_index = 0; 67 68 // Range of tokens saved in m_next_token_index. 69 struct Range { 70 size_t begin_index = 0; 71 size_t end_index = 0; 72 73 Range() = default; RangeRange74 Range(size_t begin, size_t end) : begin_index(begin), end_index(end) { 75 assert(end >= begin); 76 } 77 sizeRange78 size_t size() const { return end_index - begin_index; } 79 emptyRange80 bool empty() const { return size() == 0; } 81 }; 82 83 struct ParsedNameRanges { 84 Range basename_range; 85 Range context_range; 86 }; 87 88 // Bookmark automatically restores parsing position (m_next_token_index) 89 // when destructed unless it's manually removed with Remove(). 90 class Bookmark { 91 public: Bookmark(size_t & position)92 Bookmark(size_t &position) 93 : m_position(position), m_position_value(position) {} 94 Bookmark(const Bookmark &) = delete; Bookmark(Bookmark && b)95 Bookmark(Bookmark &&b) 96 : m_position(b.m_position), m_position_value(b.m_position_value), 97 m_restore(b.m_restore) { 98 b.Remove(); 99 } 100 Bookmark &operator=(Bookmark &&) = delete; 101 Bookmark &operator=(const Bookmark &) = delete; 102 Remove()103 void Remove() { m_restore = false; } GetSavedPosition()104 size_t GetSavedPosition() { return m_position_value; } ~Bookmark()105 ~Bookmark() { 106 if (m_restore) { 107 m_position = m_position_value; 108 } 109 } 110 111 private: 112 size_t &m_position; 113 size_t m_position_value; 114 bool m_restore = true; 115 }; 116 117 bool HasMoreTokens(); 118 void Advance(); 119 void TakeBack(); 120 bool ConsumeToken(clang::tok::TokenKind kind); 121 122 template <typename... Ts> bool ConsumeToken(Ts... kinds); 123 Bookmark SetBookmark(); 124 size_t GetCurrentPosition(); 125 clang::Token &Peek(); 126 bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right); 127 128 std::optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type); 129 130 // Parses functions returning function pointers 'string (*f(int x))(float y)' 131 std::optional<ParsedFunction> ParseFuncPtr(bool expect_return_type); 132 133 // Consumes function arguments enclosed within '(' ... ')' 134 bool ConsumeArguments(); 135 136 // Consumes template arguments enclosed within '<' ... '>' 137 bool ConsumeTemplateArgs(); 138 139 // Consumes '(anonymous namespace)' 140 bool ConsumeAnonymousNamespace(); 141 142 // Consumes '{lambda ...}' 143 bool ConsumeLambda(); 144 145 // Consumes operator declaration like 'operator *' or 'operator delete []' 146 bool ConsumeOperator(); 147 148 // Skips 'const' and 'volatile' 149 void SkipTypeQualifiers(); 150 151 // Skips 'const', 'volatile', '&', '&&' in the end of the function. 152 void SkipFunctionQualifiers(); 153 154 // Consumes built-in types like 'int' or 'unsigned long long int' 155 bool ConsumeBuiltinType(); 156 157 // Consumes types defined via decltype keyword. 158 bool ConsumeDecltype(); 159 160 // Skips 'const' and 'volatile' 161 void SkipPtrsAndRefs(); 162 163 // Consumes things like 'const * const &' 164 bool ConsumePtrsAndRefs(); 165 166 // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass' 167 bool ConsumeTypename(); 168 169 /// Consumes ABI tags enclosed within '[abi:' ... ']' 170 /// 171 /// Since there is no restriction on what the ABI tag 172 /// string may contain, this API supports parsing a small 173 /// set of special characters. 174 /// 175 /// The following regex describes the set of supported characters: 176 /// [A-Za-z,.\s\d]+ 177 bool ConsumeAbiTag(); 178 179 std::optional<ParsedNameRanges> ParseFullNameImpl(); 180 llvm::StringRef GetTextForRange(const Range &range); 181 182 // Populate m_tokens by calling clang lexer on m_text. 183 void ExtractTokens(); 184 }; 185 186 } // namespace lldb_private 187 188 #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 189