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/Optional.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/ADT/StringRef.h" 16 17 #include "lldb/Utility/ConstString.h" 18 #include "lldb/lldb-private.h" 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 }; 37 38 // Treats given text as a function definition and parses it. 39 // Function definition might or might not have a return type and this should 40 // change parsing result. 41 // Examples: 42 // main(int, chat const*) 43 // T fun(int, bool) 44 // std::vector<int>::push_back(int) 45 // int& map<int, pair<short, int>>::operator[](short) const 46 // int (*get_function(const chat *))() 47 llvm::Optional<ParsedFunction> ParseAsFunctionDefinition(); 48 49 // Treats given text as a potentially nested name of C++ entity (function, 50 // class, field) and parses it. 51 // Examples: 52 // main 53 // fun 54 // std::vector<int>::push_back 55 // map<int, pair<short, int>>::operator[] 56 // func<C>(int, C&)::nested_class::method 57 llvm::Optional<ParsedName> ParseAsFullName(); 58 59 private: 60 // A C++ definition to parse. 61 llvm::StringRef m_text; 62 // Tokens extracted from m_text. 63 llvm::SmallVector<clang::Token, 30> m_tokens; 64 // Index of the next token to look at from m_tokens. 65 size_t m_next_token_index = 0; 66 67 // Range of tokens saved in m_next_token_index. 68 struct Range { 69 size_t begin_index = 0; 70 size_t end_index = 0; 71 RangeRange72 Range() {} RangeRange73 Range(size_t begin, size_t end) : begin_index(begin), end_index(end) { 74 assert(end >= begin); 75 } 76 sizeRange77 size_t size() const { return end_index - begin_index; } 78 emptyRange79 bool empty() const { return size() == 0; } 80 }; 81 82 struct ParsedNameRanges { 83 Range basename_range; 84 Range context_range; 85 }; 86 87 // Bookmark automatically restores parsing position (m_next_token_index) 88 // when destructed unless it's manually removed with Remove(). 89 class Bookmark { 90 public: Bookmark(size_t & position)91 Bookmark(size_t &position) 92 : m_position(position), m_position_value(position) {} 93 Bookmark(const Bookmark &) = delete; Bookmark(Bookmark && b)94 Bookmark(Bookmark &&b) 95 : m_position(b.m_position), m_position_value(b.m_position_value), 96 m_restore(b.m_restore) { 97 b.Remove(); 98 } 99 Bookmark &operator=(Bookmark &&) = delete; 100 Bookmark &operator=(const Bookmark &) = delete; 101 Remove()102 void Remove() { m_restore = false; } GetSavedPosition()103 size_t GetSavedPosition() { return m_position_value; } ~Bookmark()104 ~Bookmark() { 105 if (m_restore) { 106 m_position = m_position_value; 107 } 108 } 109 110 private: 111 size_t &m_position; 112 size_t m_position_value; 113 bool m_restore = true; 114 }; 115 116 bool HasMoreTokens(); 117 void Advance(); 118 void TakeBack(); 119 bool ConsumeToken(clang::tok::TokenKind kind); 120 template <typename... Ts> bool ConsumeToken(Ts... kinds); 121 Bookmark SetBookmark(); 122 size_t GetCurrentPosition(); 123 clang::Token &Peek(); 124 bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right); 125 126 llvm::Optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type); 127 128 // Parses functions returning function pointers 'string (*f(int x))(float y)' 129 llvm::Optional<ParsedFunction> ParseFuncPtr(bool expect_return_type); 130 131 // Consumes function arguments enclosed within '(' ... ')' 132 bool ConsumeArguments(); 133 134 // Consumes template arguments enclosed within '<' ... '>' 135 bool ConsumeTemplateArgs(); 136 137 // Consumes '(anonymous namespace)' 138 bool ConsumeAnonymousNamespace(); 139 140 // Consumes '{lambda ...}' 141 bool ConsumeLambda(); 142 143 // Consumes operator declaration like 'operator *' or 'operator delete []' 144 bool ConsumeOperator(); 145 146 // Skips 'const' and 'volatile' 147 void SkipTypeQualifiers(); 148 149 // Skips 'const', 'volatile', '&', '&&' in the end of the function. 150 void SkipFunctionQualifiers(); 151 152 // Consumes built-in types like 'int' or 'unsigned long long int' 153 bool ConsumeBuiltinType(); 154 155 // Consumes types defined via decltype keyword. 156 bool ConsumeDecltype(); 157 158 // Skips 'const' and 'volatile' 159 void SkipPtrsAndRefs(); 160 161 // Consumes things like 'const * const &' 162 bool ConsumePtrsAndRefs(); 163 164 // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass' 165 bool ConsumeTypename(); 166 167 llvm::Optional<ParsedNameRanges> ParseFullNameImpl(); 168 llvm::StringRef GetTextForRange(const Range &range); 169 170 // Populate m_tokens by calling clang lexer on m_text. 171 void ExtractTokens(); 172 }; 173 174 } // namespace lldb_private 175 176 #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 177