diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h index 683b5c0bb5a7..6a546ade484f 100644 --- a/lldb/include/lldb/ValueObject/DILAST.h +++ b/lldb/include/lldb/ValueObject/DILAST.h @@ -25,9 +25,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/Support/Casting.h" -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { /// Struct to hold information about member fields. Used by the parser for the /// Data Inspection Language (DIL). @@ -142,7 +140,7 @@ enum class UnaryOpKind { /// Translates DIL tokens to BinaryOpKind. BinaryOpKind - dil_token_kind_to_binary_op_kind(dil::TokenKind token_kind); + dil_token_kind_to_binary_op_kind(Token::Kind token_kind); /// Returns bool indicating whether or not the input kind is an assignment. bool binary_op_kind_is_comp_assign(BinaryOpKind kind); @@ -745,8 +743,6 @@ class Visitor { virtual void Visit(const TernaryOpNode *node) = 0; }; -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil #endif // LLDB_VALUEOBJECT_DILAST_H diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 3646eae48398..80fc41bf3053 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_VALUEOBJECT_DILEVAL_H_ -#define LLDB_VALUEOBJECT_DILEVAL_H_ +#ifndef LLDB_VALUEOBJECT_DILEVAL_H +#define LLDB_VALUEOBJECT_DILEVAL_H #include #include @@ -15,9 +15,7 @@ #include "lldb/ValueObject/DILAST.h" #include "lldb/ValueObject/DILParser.h" -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { class FlowAnalysis { public: @@ -33,13 +31,10 @@ class FlowAnalysis { class DILInterpreter : Visitor { public: - DILInterpreter(lldb::TargetSP target, - std::shared_ptr sm); - DILInterpreter(lldb::TargetSP target, - std::shared_ptr sm, + DILInterpreter(lldb::TargetSP target, llvm::StringRef expr); + DILInterpreter(lldb::TargetSP target, llvm::StringRef expr, lldb::ValueObjectSP scope); - DILInterpreter(lldb::TargetSP target, - std::shared_ptr sm, + DILInterpreter(lldb::TargetSP target, llvm::StringRef expr, lldb::DynamicValueType use_dynamic); lldb::ValueObjectSP DILEval(const DILASTNode* tree, lldb::TargetSP target_sp, @@ -139,7 +134,7 @@ class DILInterpreter : Visitor { // Used by the interpreter to create objects, perform casts, etc. lldb::TargetSP m_target; - std::shared_ptr m_sm; + llvm::StringRef m_expr; // Flow analysis chain represents the expression evaluation flow for the // current code branch. Each node in the chain corresponds to an AST node, @@ -162,8 +157,6 @@ class DILInterpreter : Visitor { Status m_error; }; -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil -#endif // LLDB_VALUEOBJECT_DILEVAL_H_ +#endif // LLDB_VALUEOBJECT_DILEVAL_H diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h index 4e5c53431327..02c4e4611e02 100644 --- a/lldb/include/lldb/ValueObject/DILLexer.h +++ b/lldb/include/lldb/ValueObject/DILLexer.h @@ -6,108 +6,20 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_VALUEOBJECT_DILLEXER_H_ -#define LLDB_VALUEOBJECT_DILLEXER_H_ +#ifndef LLDB_VALUEOBJECT_DILLEXER_H +#define LLDB_VALUEOBJECT_DILLEXER_H +#include "llvm/ADT/StringRef.h" #include "llvm/TargetParser/Host.h" - +#include "llvm/Support/Error.h" #include #include -#include #include #include #include -#include "llvm/ADT/StringRef.h" -namespace lldb_private { - -namespace dil { - -enum class TokenKind { - amp, - ampamp, - ampequal, - arrow, - caret, - caretequal, - char_constant, - colon, - coloncolon, - comma, - eof, - equal, - equalequal, - exclaim, - exclaimequal, - flt, - greater, - greaterequal, - greatergreater, - greatergreaterequal, - identifier, - integer, - invalid, - kw_bool, - kw_char, - kw_char16_t, - kw_char32_t, - kw_const, - kw_double, - kw_dynamic_cast, - kw_false, - kw_float, - kw_int, - kw_long, - kw_namespace, - kw_nullptr, - kw_reinterpret_cast, - kw_short, - kw_signed, - kw_sizeof, - kw_static_cast, - kw_this, - kw_true, - kw_unsigned, - kw_void, - kw_volatile, - kw_wchar_t, - l_paren, - l_square, - less, - lessequal, - lessless, - lesslessequal, - minus, - minusequal, - minusminus, - none, - numeric_constant, - percent, - percentequal, - period, - pipe, - pipeequal, - pipepipe, - plus, - plusequal, - plusplus, - question, - r_paren, - r_square, - slash, - slashequal, - star, - starequal, - string_literal, - tilde, - unknown, - utf8_char_constant, - utf8_string_literal, - wide_char_constant, - wide_string_literal, - word, -}; +namespace lldb_private::dil { enum class TypeSpecifier { kBool, @@ -137,170 +49,205 @@ enum class NumberKind { eNone }; -class DILToken { +class Token { public: - DILToken (dil::TokenKind kind, std::string spelling, uint32_t start, - uint32_t len) : - m_kind(kind), m_spelling(spelling), m_start_pos(start), m_length(len) {} - - DILToken () : - m_kind(dil::TokenKind::none), m_spelling(""), m_start_pos(0), - m_length(0) {} - - void setKind(dil::TokenKind kind) { m_kind = kind; } - dil::TokenKind getKind() const { return m_kind; } - - std::string getSpelling() const { return m_spelling; } - - uint32_t getLength() const { return m_length; } - - bool is (dil::TokenKind kind) const { return m_kind == kind; } - - bool isNot(dil::TokenKind kind) const { return m_kind != kind; } - - bool isOneOf(dil::TokenKind kind1, dil::TokenKind kind2) const { - return is(kind1) || is(kind2); + enum Kind { + amp, + ampamp, + ampequal, + arrow, + caret, + caretequal, + char_constant, + colon, + coloncolon, + comma, + eof, + equal, + equalequal, + exclaim, + exclaimequal, + flt, + greater, + greaterequal, + greatergreater, + greatergreaterequal, + identifier, + integer, + kw_bool, + kw_char, + kw_char16_t, + kw_char32_t, + kw_const, + kw_double, + kw_dynamic_cast, + kw_false, + kw_float, + kw_int, + kw_long, + kw_namespace, + kw_nullptr, + kw_reinterpret_cast, + kw_short, + kw_signed, + kw_sizeof, + kw_static_cast, + kw_this, + kw_true, + kw_unsigned, + kw_void, + kw_volatile, + kw_wchar_t, + l_paren, + l_square, + less, + lessequal, + lessless, + lesslessequal, + minus, + minusequal, + minusminus, + numeric_constant, + percent, + percentequal, + period, + pipe, + pipeequal, + pipepipe, + plus, + plusequal, + plusplus, + question, + r_paren, + r_square, + slash, + slashequal, + star, + starequal, + string_literal, + tilde, + utf8_char_constant, + utf8_string_literal, + wide_char_constant, + wide_string_literal, + }; + + Token (Kind kind, std::string spelling, uint32_t start) : + m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {} + + Kind GetKind() const { return m_kind; } + + std::string GetSpelling() const { return m_spelling; } + + bool Is (Kind kind) const { return m_kind == kind; } + + bool IsNot(Kind kind) const { return m_kind != kind; } + + bool IsOneOf(Kind kind1, Kind kind2) const { + return Is(kind1) || Is(kind2); } - template bool isOneOf(dil::TokenKind kind, Ts... Ks) const { - return is(kind) || isOneOf(Ks...); + template bool IsOneOf(Kind kind, Ts... Ks) const { + return Is(kind) || IsOneOf(Ks...); } - uint32_t getLocation() const { return m_start_pos; } + uint32_t GetLocation() const { return m_start_pos; } - void setValues (dil::TokenKind kind, std::string spelling, - uint32_t start, uint32_t len) { - m_kind = kind; - m_spelling = spelling; - m_start_pos = start; - m_length = len; - } - - static const std::string getTokenName(dil::TokenKind kind); + static llvm::StringRef GetTokenName(Kind kind); private: - dil::TokenKind m_kind; + Kind m_kind; std::string m_spelling; uint32_t m_start_pos; // within entire expression string - uint32_t m_length; }; -class DILSourceManager { - public: - static std::shared_ptr Create(std::string expr); - - // This class cannot be safely moved because of the dependency between - // `m_expr` and `m_smff`. Users are supposed to pass around the shared - // pointer. - DILSourceManager(DILSourceManager&&) = delete; - DILSourceManager(const DILSourceManager&) = delete; - DILSourceManager& operator=(DILSourceManager const&) = delete; - - llvm::StringRef GetSource() { return m_expr; } - -private: - explicit DILSourceManager(std::string expr) : m_expr(std::move(expr)) {} - - private: - // Store the expression, since SourceManagerForFile doesn't take the - // ownership. - std::string m_expr; -}; - - +/// Class for doing the simple lexing required by DIL. class DILLexer { - public: - DILLexer(std::shared_ptr dil_sm) : - m_expr(dil_sm->GetSource()) { - m_cur_pos = m_expr.begin(); - // Use UINT_MAX to indicate invalid/uninitialized value. - m_tokens_idx = UINT_MAX; - } - - bool Lex(DILToken &result, bool look_ahead=false); + friend class DILParser; + friend class NumericLiteralParser; + friend class CharLiteralParser; + friend class StringLiteralParser; - bool Is_Word(std::string::iterator start, uint32_t& length); + public: - void ConsumeNumberBody(uint32_t &length, char &prev_ch); - bool Is_Number(std::string::iterator start, uint32_t& length, - dil::NumberKind& kind); + /// Lexes all the tokens in expr and calls the private constructor + /// with the lexed tokens. + static llvm::Expected Create(llvm::StringRef expr); - bool isStringLiteral(dil::TokenKind kind) { - return (kind == dil::TokenKind::string_literal || - kind == dil::TokenKind::wide_string_literal || - kind == dil::TokenKind::utf8_string_literal); + /// Return the current token to be handled by the DIL parser. + const Token& GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; } + + /// Advance the current token position by N. + void Advance(uint32_t N = 1) { + if (m_tokens_idx + N >= m_lexed_tokens.size()) + // N is too large; advance to the end of the lexed tokens. + m_tokens_idx = m_lexed_tokens.size() - 1; + else + m_tokens_idx += N; } - uint32_t GetLocation() { return m_cur_pos - m_expr.begin(); } - - /// Update 'result' with the other paremeter values, create a - /// duplicate token, and push the duplicate token onto the vector of - /// lexed tokens. - void UpdateLexedTokens (DILToken &result, dil::TokenKind tok_kind, - std::string tok_str, uint32_t tok_pos, - uint32_t tok_len); - - /// Return the lexed token N+1 positions ahead of the 'current' token + /// Return the lexed token N positions ahead of the 'current' token /// being handled by the DIL parser. - const DILToken &LookAhead(uint32_t N); + const Token &LookAhead(uint32_t N) { + if (m_tokens_idx + N < m_lexed_tokens.size()) + return m_lexed_tokens[m_tokens_idx + N]; - const DILToken &AcceptLookAhead(uint32_t N); + // Last token should be an 'eof' token. + return m_lexed_tokens.back(); + } /// Return the index for the 'current' token being handled by the DIL parser. uint32_t GetCurrentTokenIdx() { return m_tokens_idx; } - /// Return the current token to be handled by the DIL parser. - DILToken& GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; } - - /// Update the index for the 'current' token, to point to the next lexed - /// token. - bool IncrementTokenIdx() { - if (m_tokens_idx >= m_lexed_tokens.size() - 1) - return false; - - m_tokens_idx++; - return true; - } - /// Set the index for the 'current' token (to be handled by the parser) /// to a particular position. Used for either committing 'look ahead' parsing /// or rolling back tentative parsing. - bool ResetTokenIdx(uint32_t new_value) { - if (new_value > m_lexed_tokens.size() - 1) - return false; - + void ResetTokenIdx(uint32_t new_value) { + assert(new_value < m_lexed_tokens.size()); m_tokens_idx = new_value; - return true; } - uint32_t getCharWidth() { return 8; } - uint32_t getIntWidth() { return 32; } - uint32_t getWCharWidth() { return 16; } + uint32_t GetCharWidth() { return 8; } + uint32_t GetIntWidth() { return 32; } + uint32_t GetWCharWidth() { return 16; } + + uint32_t NumLexedTokens() { return m_lexed_tokens.size(); } + /// Insert a new token into the vector of lexed tokens, just after the current + /// index position. Used when splitting apart a multi-character token. + void InsertToken(Token new_token) { + std::vector::iterator iter = m_lexed_tokens.begin() + m_tokens_idx + + 1; + m_lexed_tokens.insert(iter, new_token); + } private: - // The input string we are lexing & parsing. - std::string m_expr; + DILLexer(llvm::StringRef dil_expr, std::vector lexed_tokens) : + m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)), + m_tokens_idx(0) {} - // The current position of the lexer within m_expr (the character position, - // within the string, of the next item to be lexed). - std::string::iterator m_cur_pos; + static llvm::Expected Lex(llvm::StringRef expr, + llvm::StringRef &remainder); + + bool IsStringLiteral(Token::Kind kind) { + return (kind == Token::string_literal || + kind == Token::wide_string_literal || + kind == Token::utf8_string_literal); + } + + // The input string we are lexing & parsing. + llvm::StringRef m_expr; // Holds all of the tokens lexed so far. - std::vector m_lexed_tokens; + std::vector m_lexed_tokens; // Index into m_lexed_tokens; indicates which token the DIL parser is // currently trying to parse/handle. uint32_t m_tokens_idx; - - // "invalid" token; to be returned by lexer when 'look ahead' fails. - DILToken m_invalid_token; }; -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil -#endif // LLDB_VALUEOBJECT_DILLEXER_H_ +#endif // LLDB_VALUEOBJECT_DILLEXER_H diff --git a/lldb/include/lldb/ValueObject/DILLiteralParsers.h b/lldb/include/lldb/ValueObject/DILLiteralParsers.h index f355327965dc..9df7bba1e25c 100644 --- a/lldb/include/lldb/ValueObject/DILLiteralParsers.h +++ b/lldb/include/lldb/ValueObject/DILLiteralParsers.h @@ -18,9 +18,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { class NumericLiteralParser { public: @@ -144,19 +142,19 @@ class NumericLiteralParser { class CharLiteralParser { private: uint64_t Value; - dil::TokenKind Kind; + Token::Kind Kind; bool IsMultiChar; bool HadError; public: CharLiteralParser(const char *begin, const char *end, unsigned Loc, DILLexer &lexer, - dil::TokenKind kind); + Token::Kind kind); bool hadError() const { return HadError; } - bool isOrdinary() const { return Kind == dil::TokenKind::char_constant; } - bool isWide() const { return Kind == dil::TokenKind::wide_char_constant; } - bool isUTF8() const { return Kind == dil::TokenKind::utf8_char_constant; } + bool isOrdinary() const { return Kind == Token::char_constant; } + bool isWide() const { return Kind == Token::wide_char_constant; } + bool isUTF8() const { return Kind == Token::utf8_char_constant; } bool isMultiChar() const { return IsMultiChar; } uint64_t getValue() const { return Value; } }; @@ -170,14 +168,14 @@ class StringLiteralParser { unsigned MaxTokenLength; unsigned SizeBound; unsigned CharByteWidth; - dil::TokenKind Kind; + Token::Kind Kind; llvm::SmallString<512> ResultBuf; char *ResultPtr; // cursor StringLiteralEvalMethod EvalMethod; DILLexer &m_lexer; public: - StringLiteralParser(llvm::ArrayRef StringToks, + StringLiteralParser(llvm::ArrayRef StringToks, DILLexer &lexer, StringLiteralEvalMethod EvalMethod = StringLiteralEvalMethod::Evaluated); @@ -198,26 +196,24 @@ class StringLiteralParser { /// /// If the Diagnostics pointer is non-null, then this will do semantic /// checking of the string literal and emit errors and warnings. - unsigned getOffsetOfStringByte(const DILToken &TheTok, + unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const; - bool isOrdinary() const { return Kind == dil::TokenKind::string_literal; } - bool isWide() const { return Kind == dil::TokenKind::wide_string_literal; } - bool isUTF8() const { return Kind == dil::TokenKind::utf8_string_literal; } + bool isOrdinary() const { return Kind == Token::string_literal; } + bool isWide() const { return Kind == Token::wide_string_literal; } + bool isUTF8() const { return Kind == Token::utf8_string_literal; } bool isUnevaluated() const { return EvalMethod == StringLiteralEvalMethod::Unevaluated; } private: - void init(llvm::ArrayRef StringToks, + void init(llvm::ArrayRef StringToks, DILLexer &lexer); - bool CopyStringFragment(const DILToken &Tok, const char *TokBegin, + bool CopyStringFragment(const Token &Tok, const char *TokBegin, llvm::StringRef Fragment); void DiagnoseLexingError(unsigned Loc); }; -} // end namespace dil - -} // end namespace lldb_private +} // end namespace lldb_private::dil #endif // LLDB_VALUEOBJECT_DILLiteralParsers_H diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h index 376033ac2cb7..ac58c57cb648 100644 --- a/lldb/include/lldb/ValueObject/DILParser.h +++ b/lldb/include/lldb/ValueObject/DILParser.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_VALUEOBJECT_DILPARSER_H_ -#define LLDB_VALUEOBJECT_DILPARSER_H_ +#ifndef LLDB_VALUEOBJECT_DILPARSER_H +#define LLDB_VALUEOBJECT_DILPARSER_H #include #include @@ -21,9 +21,7 @@ #include "lldb/ValueObject/DILLexer.h" #include "lldb/ValueObject/DILLiteralParsers.h" -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { /// Finds the member field with the given name and type, stores the child index /// corresponding to the field in the idx vector and returns a MemberInfo @@ -59,8 +57,8 @@ enum class ErrorCode : unsigned char { kUnknown, }; -std::string FormatDiagnostics(DILSourceManager &sm, const std::string &message, - uint32_t loc); +std::string FormatDiagnostics(llvm::StringRef input_expr, + const std::string& message, uint32_t loc); void SetUbStatus(Status& error, ErrorCode code); @@ -140,7 +138,7 @@ class BuiltinFunctionDef { /// EBNF grammar for the parser is described in lldb/docs/dil-expr-lang.ebnf class DILParser { public: - explicit DILParser(std::shared_ptr dil_sm, + explicit DILParser(llvm::StringRef dil_input_expr, DILLexer lexer, std::shared_ptr exe_ctx_scope, lldb::DynamicValueType use_dynamic, bool use_synthetic, bool fragile_ivar, @@ -154,7 +152,7 @@ class DILParser { lldb::DynamicValueType UseDynamic() { return m_use_dynamic; } - using PtrOperator = std::tuple; + using PtrOperator = std::tuple; private: DILASTNodeUP ParseExpression(); @@ -188,9 +186,9 @@ class DILParser { CompilerType type, const std::vector& ptr_operators); - bool IsSimpleTypeSpecifierKeyword(DILToken token) const; - bool IsCvQualifier(DILToken token) const; - bool IsPtrOperator(DILToken token) const; + bool IsSimpleTypeSpecifierKeyword(Token token) const; + bool IsCvQualifier(Token token) const; + bool IsPtrOperator(Token token) const; bool HandleSimpleTypeSpecifier(TypeDeclaration* type_decl); std::string ParseIdExpression(); @@ -202,9 +200,9 @@ class DILParser { DILASTNodeUP ParsePointerLiteral(); DILASTNodeUP ParseNumericConstant(); DILASTNodeUP ParseFloatingLiteral(NumericLiteralParser& literal, - DILToken& token); + Token& token); DILASTNodeUP ParseIntegerLiteral(NumericLiteralParser& literal, - DILToken& token); + Token& token); DILASTNodeUP ParseBuiltinFunction(uint32_t loc, std::unique_ptr func_def); @@ -219,17 +217,17 @@ class DILParser { void BailOut(Status error); - void Expect(dil::TokenKind kind); + void Expect(Token::Kind kind); - std::string TokenDescription(const DILToken& token); + std::string TokenDescription(const Token& token); template - void ExpectOneOf(dil::TokenKind k, Ts... ks); + void ExpectOneOf(Token::Kind k, Ts... ks); DILASTNodeUP BuildCStyleCast(CompilerType type, DILASTNodeUP rhs, uint32_t location); - DILASTNodeUP BuildCxxCast(dil::TokenKind kind, CompilerType type, - DILASTNodeUP rhs, uint32_t location); + DILASTNodeUP BuildCxxCast(Token::Kind kind, CompilerType type, + DILASTNodeUP rhs, uint32_t location); DILASTNodeUP BuildCxxDynamicCast(CompilerType type, DILASTNodeUP rhs, uint32_t location); DILASTNodeUP BuildCxxStaticCast(CompilerType type, DILASTNodeUP rhs, @@ -305,9 +303,11 @@ class DILParser { // context will outlive the parser. std::shared_ptr m_ctx_scope; - std::shared_ptr m_sm; + llvm::StringRef m_input_expr; + + DILLexer m_dil_lexer; // The token lexer is stopped at (aka "current token"). - DILToken m_dil_token; + Token m_dil_token; // Holds an error if it occures during parsing. Status m_error; @@ -317,11 +317,8 @@ class DILParser { bool m_use_synthetic; bool m_fragile_ivar; bool m_check_ptr_vs_member; - DILLexer m_dil_lexer; }; // class DILParser -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil -#endif // LLDB_VALUEOBJECT_DILPARSER_H_ +#endif // LLDB_VALUEOBJECT_DILPARSER_H diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 97e2f5b14ac2..306b829f741d 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -32,6 +32,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/ValueObject/DILEval.h" +#include "lldb/ValueObject/DILLexer.h" #include "lldb/ValueObject/DILParser.h" #include "lldb/ValueObject/ValueObjectConstResult.h" #include "lldb/ValueObject/ValueObjectMemory.h" @@ -530,7 +531,6 @@ ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath( uint32_t options, lldb::VariableSP &var_sp, Status &error) { ValueObjectSP ret_val; - auto source = dil::DILSourceManager::Create(var_expr.data()); const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0; @@ -539,9 +539,17 @@ ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath( const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0; + // Lex the expression + auto lex_or_err = dil::DILLexer::Create(var_expr); + if (!lex_or_err) { + error = Status::FromError(lex_or_err.takeError()); + return ValueObjectSP(); + } + dil::DILLexer lexer = *lex_or_err; + // Parse the expression. Status parse_error, eval_error; - dil::DILParser parser(source, shared_from_this(), use_dynamic, + dil::DILParser parser(var_expr, lexer, shared_from_this(), use_dynamic, !no_synth_child, !no_fragile_ivar, check_ptr_vs_member); dil::DILASTNodeUP tree = parser.Run(parse_error); if (parse_error.Fail()) { @@ -551,7 +559,7 @@ ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath( // Evaluate the parsed expression. lldb::TargetSP target = this->CalculateTarget(); - dil::DILInterpreter interpreter(target, source, use_dynamic); + dil::DILInterpreter interpreter(target, var_expr, use_dynamic); ret_val = interpreter.DILEval(tree.get(), target, eval_error); if (eval_error.Fail()) { diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp index 0bdd6742dbde..c45eec51dcd2 100644 --- a/lldb/source/ValueObject/DILAST.cpp +++ b/lldb/source/ValueObject/DILAST.cpp @@ -19,9 +19,7 @@ #include -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { lldb::ValueObjectSP GetDynamicOrSyntheticValue(lldb::ValueObjectSP in_valobj_sp, @@ -59,66 +57,65 @@ GetDynamicOrSyntheticValue(lldb::ValueObjectSP in_valobj_sp, return value_sp; } -BinaryOpKind -dil_token_kind_to_binary_op_kind(dil::TokenKind token_kind) { +BinaryOpKind dil_token_kind_to_binary_op_kind(Token::Kind token_kind) { switch (token_kind) { - case dil::TokenKind::star: + case Token::star: return BinaryOpKind::Mul; - case dil::TokenKind::amp: + case Token::amp: return BinaryOpKind::And; - case dil::TokenKind::minus: + case Token::minus: return BinaryOpKind::Sub; - case dil::TokenKind::slash: + case Token::slash: return BinaryOpKind::Div; - case dil::TokenKind::percent: + case Token::percent: return BinaryOpKind::Rem; - case dil::TokenKind::plus: + case Token::plus: return BinaryOpKind::Add; - case dil::TokenKind::lessless: + case Token::lessless: return BinaryOpKind::Shl; - case dil::TokenKind::greatergreater: + case Token::greatergreater: return BinaryOpKind::Shr; - case dil::TokenKind::less: + case Token::less: return BinaryOpKind::LT; - case dil::TokenKind::greater: + case Token::greater: return BinaryOpKind::GT; - case dil::TokenKind::lessequal: + case Token::lessequal: return BinaryOpKind::LE; - case dil::TokenKind::greaterequal: + case Token::greaterequal: return BinaryOpKind::GE; - case dil::TokenKind::equalequal: + case Token::equalequal: return BinaryOpKind::EQ; - case dil::TokenKind::exclaimequal: + case Token::exclaimequal: return BinaryOpKind::NE; - case dil::TokenKind::caret: + case Token::caret: return BinaryOpKind::Xor; - case dil::TokenKind::pipe: + case Token::pipe: return BinaryOpKind::Or; - case dil::TokenKind::ampamp: + case Token::ampamp: return BinaryOpKind::LAnd; - case dil::TokenKind::pipepipe: + case Token::pipepipe: return BinaryOpKind::LOr; - case dil::TokenKind::equal: + case Token::equal: return BinaryOpKind::Assign; - case dil::TokenKind::starequal: + case Token::starequal: return BinaryOpKind::MulAssign; - case dil::TokenKind::slashequal: + case Token::slashequal: return BinaryOpKind::DivAssign; - case dil::TokenKind::percentequal: + case Token::percentequal: return BinaryOpKind::RemAssign; - case dil::TokenKind::plusequal: + case Token::plusequal: return BinaryOpKind::AddAssign; - case dil::TokenKind::minusequal: + case Token::minusequal: return BinaryOpKind::SubAssign; - case dil::TokenKind::lesslessequal: + case Token::lesslessequal: return BinaryOpKind::ShlAssign; - case dil::TokenKind::greatergreaterequal: + case Token::greatergreaterequal: return BinaryOpKind::ShrAssign; - case dil::TokenKind::ampequal: + case Token::ampequal: return BinaryOpKind::AndAssign; - case dil::TokenKind::caretequal: + case Token::caretequal: return BinaryOpKind::XorAssign; - case dil::TokenKind::pipeequal: + case Token::pipeequal: return BinaryOpKind::OrAssign; default: break; @@ -405,6 +402,10 @@ ResolveTypeByName(const std::string &name, if (full_match.IsValid()) return full_match; + // If we have partial matches, pick a "random" one. + if (partial_matches.size() > 0) + return partial_matches.back(); + return {}; } @@ -635,6 +636,4 @@ void UnaryOpNode::Accept(Visitor *v) const { v->Visit(this); } void TernaryOpNode::Accept(Visitor *v) const { v->Visit(this); } -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index 90a72b393ad8..d34877d38902 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -17,9 +17,7 @@ #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { template bool Compare(BinaryOpKind kind, const T& l, const T& r) { @@ -270,22 +268,22 @@ void SetUbStatus(Status& error, ErrorCode code) { } DILInterpreter::DILInterpreter(lldb::TargetSP target, - std::shared_ptr sm) - : m_target(std::move(target)), m_sm(std::move(sm)) + llvm::StringRef expr) + : m_target(std::move(target)), m_expr(expr) { m_default_dynamic = lldb::eNoDynamicValues; } DILInterpreter::DILInterpreter(lldb::TargetSP target, - std::shared_ptr sm, + llvm::StringRef expr, lldb::DynamicValueType use_dynamic) - : m_target(std::move(target)), m_sm(std::move(sm)), + : m_target(std::move(target)), m_expr(expr), m_default_dynamic(use_dynamic) {} DILInterpreter::DILInterpreter(lldb::TargetSP target, - std::shared_ptr sm, + llvm::StringRef expr, lldb::ValueObjectSP scope) - : m_target(std::move(target)), m_sm(std::move(sm)), + : m_target(std::move(target)), m_expr(expr), m_scope(std::move(scope)) { m_default_dynamic = lldb::eNoDynamicValues; @@ -332,8 +330,7 @@ lldb::ValueObjectSP DILInterpreter::DILEvalNode(const DILASTNode* node, void DILInterpreter::SetError(ErrorCode code, std::string error, uint32_t loc) { assert(m_error.Success() && "interpreter can error only once"); - m_error = Status((uint32_t)code, lldb::eErrorTypeGeneric, - FormatDiagnostics(*m_sm, error, loc)); + m_error = Status(FormatDiagnostics(m_expr, error, loc)); } void DILInterpreter::Visit(const ErrorNode* node) { @@ -1877,6 +1874,4 @@ lldb::ValueObjectSP DILInterpreter::ResolveContextVar( return it != m_context_vars.end() ? it->second : lldb::ValueObjectSP(); } -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp index e7cb8d2281f7..f41889fef921 100644 --- a/lldb/source/ValueObject/DILLexer.cpp +++ b/lldb/source/ValueObject/DILLexer.cpp @@ -12,479 +12,332 @@ //===----------------------------------------------------------------------===// #include "lldb/ValueObject/DILLexer.h" -#include "llvm/ADT/StringMap.h" +//#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSwitch.h" -namespace lldb_private { +namespace lldb_private::dil { -namespace dil { +/* +const llvm::StringMap Keywords = { + {"bool", Token::kw_bool}, + {"char", Token::kw_char}, + {"char16_t", Token::kw_char16_t}, + {"char32_t", Token::kw_char32_t}, + {"const", Token::kw_const}, + {"double", Token::kw_double}, + {"dynamic_cast", Token::kw_dynamic_cast}, + {"false", Token::kw_false}, + {"float", Token::kw_float}, + {"int", Token::kw_int}, + {"long", Token::kw_long}, + {"namespace", Token::kw_namespace}, + {"nullptr", Token::kw_nullptr}, + {"reinterpret_cast", Token::kw_reinterpret_cast}, + {"short", Token::kw_short}, + {"signed", Token::kw_signed}, + {"sizeof", Token::kw_sizeof}, + {"static_cast", Token::kw_static_cast}, + {"this", Token::kw_this}, + {"true", Token::kw_true}, + {"unsigned", Token::kw_unsigned}, + {"void", Token::kw_void}, + {"volatile", Token::kw_volatile}, + {"wchar_t", Token::kw_wchar_t}}; +*/ -const llvm::StringMap Keywords = { - {"bool", dil::TokenKind::kw_bool}, - {"char", dil::TokenKind::kw_char}, - {"char16_t", dil::TokenKind::kw_char16_t}, - {"char32_t", dil::TokenKind::kw_char32_t}, - {"const", dil::TokenKind::kw_const}, - {"double", dil::TokenKind::kw_double}, - {"dynamic_cast", dil::TokenKind::kw_dynamic_cast}, - {"false", dil::TokenKind::kw_false}, - {"float", dil::TokenKind::kw_float}, - {"int", dil::TokenKind::kw_int}, - {"long", dil::TokenKind::kw_long}, - {"namespace", dil::TokenKind::kw_namespace}, - {"nullptr", dil::TokenKind::kw_nullptr}, - {"reinterpret_cast", dil::TokenKind::kw_reinterpret_cast}, - {"short", dil::TokenKind::kw_short}, - {"signed", dil::TokenKind::kw_signed}, - {"sizeof", dil::TokenKind::kw_sizeof}, - {"static_cast", dil::TokenKind::kw_static_cast}, - {"this", dil::TokenKind::kw_this}, - {"true", dil::TokenKind::kw_true}, - {"unsigned", dil::TokenKind::kw_unsigned}, - {"void", dil::TokenKind::kw_void}, - {"volatile", dil::TokenKind::kw_volatile}, - {"wchar_t", dil::TokenKind::kw_wchar_t}}; - -const std::string DILToken::getTokenName(dil::TokenKind kind) { - std::string retval; +llvm::StringRef Token::GetTokenName(Kind kind) { switch (kind){ - case dil::TokenKind::amp: retval = "amp"; break; - case dil::TokenKind::ampamp: retval = "ampamp"; break; - case dil::TokenKind::ampequal: retval = "ampequal"; break; - case dil::TokenKind::arrow: retval = "arrow"; break; - case dil::TokenKind::caret: retval = "caret"; break; - case dil::TokenKind::caretequal: retval = "caretequal"; break; - case dil::TokenKind::colon: retval = "colon"; break; - case dil::TokenKind::coloncolon: retval = "coloncolon"; break; - case dil::TokenKind::comma: retval = "comma"; break; - case dil::TokenKind::eof: retval = "eof"; break; - case dil::TokenKind::equalequal: retval = "equalequal"; break; - case dil::TokenKind::exclaim: retval = "exclaim"; break; - case dil::TokenKind::exclaimequal: retval = "exclaimequal"; break; - case dil::TokenKind::flt: retval = "flt"; break; - case dil::TokenKind::greater: retval = "greater"; break; - case dil::TokenKind::greaterequal: retval = "greaterequal"; break; - case dil::TokenKind::greatergreater: retval = "greatergreater"; break; - case dil::TokenKind::greatergreaterequal: retval = "greatergreaterequal"; - break; - case dil::TokenKind::identifier: retval = "identifier"; break; - case dil::TokenKind::integer: retval = "integer"; break; - case dil::TokenKind::less: retval = "less"; break; - case dil::TokenKind::lessequal: retval = "lessequal"; break; - case dil::TokenKind::lessless: retval = "lessless"; break; - case dil::TokenKind::lesslessequal: retval = "lesslessequal"; break; - case dil::TokenKind::l_square: retval = "l_square"; break; - case dil::TokenKind::l_paren: retval = "l_paren"; break; - case dil::TokenKind::minus: retval = "minus"; break; - case dil::TokenKind::minusequal: retval = "minusequal"; break; - case dil::TokenKind::minusminus: retval = "minusminus"; break; - case dil::TokenKind::numeric_constant: retval = "numeric_constant"; break; - case dil::TokenKind::percent: retval = "percent"; break; - case dil::TokenKind::percentequal: retval = "percentequal"; break; - case dil::TokenKind::period: retval = "period"; break; - case dil::TokenKind::pipe: retval = "pipe"; break; - case dil::TokenKind::pipeequal: retval = "pipeequal"; break; - case dil::TokenKind::pipepipe: retval = "pipepipe"; break; - case dil::TokenKind::plus: retval = "plus"; break; - case dil::TokenKind::plusequal: retval = "plusequal"; break; - case dil::TokenKind::plusplus: retval = "plusplus"; break; - case dil::TokenKind::question: retval = "question"; break; - case dil::TokenKind::r_paren: retval = "r_paren"; break; - case dil::TokenKind::r_square: retval = "r_square"; break; - case dil::TokenKind::slash: retval = "slash"; break; - case dil::TokenKind::slashequal: retval = "slashequal"; break; - case dil::TokenKind::star: retval = "star"; break; - case dil::TokenKind::starequal: retval = "starequal"; break; - case dil::TokenKind::string_literal: retval = "string_literal"; break; - case dil::TokenKind::tilde: retval = "tilde"; break; - case dil::TokenKind::utf8_string_literal: retval = "utf8_string_literal"; - break; - case dil::TokenKind::wide_string_literal: retval = "wide_string_literal"; - break; - case dil::TokenKind::word: retval = "word"; break; - case dil::TokenKind::char_constant: retval = "char_constant"; break; - case dil::TokenKind::wide_char_constant: retval = "wide_char_constant"; - break; - case dil::TokenKind::utf8_char_constant: retval = "utf8_char_constant"; - break; - default: - retval = "token_name"; - break; + case Token::amp: return "amp"; + case Token::ampamp: return "ampamp"; + case Token::ampequal: return "ampequal"; + case Token::arrow: return "arrow"; + case Token::caret: return "caret"; + case Token::caretequal: return "caretequal"; + case Token::colon: return "colon"; + case Token::coloncolon: return "coloncolon"; + case Token::comma: return "comma"; + case Token::eof: return "eof"; + case Token::equal: + return "equal"; + case Token::equalequal: return "equalequal"; + case Token::exclaim: return "exclaim"; + case Token::exclaimequal: return "exclaimequal"; + case Token::flt: return "flt"; + case Token::greater: return "greater"; + case Token::greaterequal: return "greaterequal"; + case Token::greatergreater: return "greatergreater"; + case Token::greatergreaterequal: return "greatergreaterequal"; + case Token::identifier: return "identifier"; + case Token::integer: return "integer"; + case Token::kw_bool: + return "bool"; + case Token::kw_char: + return "char"; + case Token::kw_char16_t: + return "char16_t"; + case Token::kw_char32_t: + return "char32_t"; + case Token::kw_const: + return "const"; + case Token::kw_double: + return "double"; + case Token::kw_dynamic_cast: + return "dynamic_cast"; + case Token::kw_false: + return "false"; + case Token::kw_float: + return "float"; + case Token::kw_int: + return "int"; + case Token::kw_long: + return "long"; + case Token::kw_namespace: + return "namespace"; + case Token::kw_nullptr: + return "nullptr"; + case Token::kw_reinterpret_cast: + return "reinterpret_cast"; + case Token::kw_short: + return "short"; + case Token::kw_signed: + return "signed"; + case Token::kw_sizeof: + return "sizeof"; + case Token::kw_static_cast: + return "static_cast"; + case Token::kw_this: + return "this"; + case Token::kw_true: + return "true"; + case Token::kw_unsigned: + return "unsigned"; + case Token::kw_void: + return "void"; + case Token::kw_volatile: + return "volatile"; + case Token::kw_wchar_t: + return "wchar_t"; + case Token::less: return "less"; + case Token::lessequal: return "lessequal"; + case Token::lessless: return "lessless"; + case Token::lesslessequal: return "lesslessequal"; + case Token::l_square: return "l_square"; + case Token::l_paren: return "l_paren"; + case Token::minus: return "minus"; + case Token::minusequal: return "minusequal"; + case Token::minusminus: return "minusminus"; + case Token::numeric_constant: return "numeric_constant"; + case Token::percent: return "percent"; + case Token::percentequal: return "percentequal"; + case Token::period: return "period"; + case Token::pipe: return "pipe"; + case Token::pipeequal: return "pipeequal"; + case Token::pipepipe: return "pipepipe"; + case Token::plus: return "plus"; + case Token::plusequal: return "plusequal"; + case Token::plusplus: return "plusplus"; + case Token::question: return "question"; + case Token::r_paren: return "r_paren"; + case Token::r_square: return "r_square"; + case Token::slash: return "slash"; + case Token::slashequal: return "slashequal"; + case Token::star: return "star"; + case Token::starequal: return "starequal"; + case Token::string_literal: return "string_literal"; + case Token::tilde: return "tilde"; + case Token::utf8_string_literal: return "utf8_string_literal"; + case Token::wide_string_literal: return "wide_string_literal"; + case Token::char_constant: return "char_constant"; + case Token::wide_char_constant: return "wide_char_constant"; + case Token::utf8_char_constant: return "utf8_char_constant"; } - return retval; } -static bool Is_Letter (char c) { - if (('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z')) - return true; - return false; +static bool IsLetter (char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); } -static bool Is_Digit (char c) { - return ('0' <= c && c <= '9'); -} +static bool IsDigit (char c) { return ('0' <= c && c <= '9'); } -bool DILLexer::Is_Word(std::string::iterator start, uint32_t& length) { - bool done = false; - for ( ; m_cur_pos != m_expr.end() && !done; ++m_cur_pos) { - char c = *m_cur_pos; - if (!Is_Letter(c) && !Is_Digit(c) && c != '_') { - done = true; - break; - } else - length++; - } - if (length > 0) - return true; - else - m_cur_pos = start; - return false; +static std::optional IsWord(llvm::StringRef expr, + llvm::StringRef &remainder) { + // Find the longest prefix consisting of letters, digits, underscors and + // '$'. If it doesn't start with a digit, then it's a word. + llvm::StringRef candidate = remainder.take_while( + [](char c) { return IsDigit(c) || IsLetter(c) || c == '_' || c == '$'; }); + if (candidate.empty() || IsDigit(candidate[0])) + return std::nullopt; + remainder = remainder.drop_front(candidate.size()); + return candidate; } -void DILLexer::ConsumeNumberBody(uint32_t &length, char &prev_ch) { - while (m_cur_pos != m_expr.end() && - (Is_Digit(*m_cur_pos) || Is_Letter(*m_cur_pos) || *m_cur_pos == '_')) { - prev_ch = *m_cur_pos; +static void ConsumeNumberBody(uint32_t &length, char &prev_ch, + llvm::StringRef::iterator &cur_pos, + llvm::StringRef expr) { + while (cur_pos != expr.end() && + (IsDigit(*cur_pos) || IsLetter(*cur_pos) || *cur_pos == '_')) { + prev_ch = *cur_pos; length++; - m_cur_pos++; + cur_pos++; } } -bool DILLexer::Is_Number(std::string::iterator start, uint32_t& length, - dil::NumberKind& kind) { +static std::optional IsNumber(llvm::StringRef expr, + llvm::StringRef &remainder) { + llvm::StringRef::iterator cur_pos = remainder.begin(); + llvm::StringRef::iterator start = cur_pos; + uint32_t length = 0; char prev_ch = 0; - kind = dil::NumberKind::eInteger; + dil::NumberKind kind = dil::NumberKind::eInteger; if (*start == '.') { auto next_pos = start + 1; - if (next_pos == m_expr.end() || !Is_Digit(*next_pos)) - return false; + if (next_pos == expr.end() || !IsDigit(*next_pos)) + return std::nullopt; } - if (Is_Digit(*start) || *start == '.') { - ConsumeNumberBody(length, prev_ch); + if (IsDigit(*start) || *start == '.') { + ConsumeNumberBody(length, prev_ch, cur_pos, expr); // We're not at the end of the string, and we should be looking at a '.' - if (*m_cur_pos == '.') { + if (*cur_pos == '.') { kind = dil::NumberKind::eFloat; - prev_ch = *m_cur_pos; + prev_ch = *cur_pos; length++; - m_cur_pos++; - ConsumeNumberBody(length, prev_ch); + cur_pos++; + ConsumeNumberBody(length, prev_ch, cur_pos, expr); } // Check the exponent part - if ((*m_cur_pos == '-' || *m_cur_pos == '+') && + if ((*cur_pos == '-' || *cur_pos == '+') && (prev_ch == 'E' || prev_ch == 'e' || prev_ch == 'P' || prev_ch == 'p')) { - prev_ch = *m_cur_pos; + prev_ch = *cur_pos; length++; - m_cur_pos++; - ConsumeNumberBody(length, prev_ch); + cur_pos++; + ConsumeNumberBody(length, prev_ch, cur_pos, expr); } - return true; + llvm::StringRef number = expr.substr(start - expr.begin(), + cur_pos - start); + if (remainder.consume_front(number)) + return number; } - return false; + return std::nullopt; } -void DILLexer::UpdateLexedTokens(DILToken &result, dil::TokenKind tok_kind, - std::string tok_str, uint32_t tok_pos, - uint32_t tok_len) { - DILToken new_token; - result.setValues(tok_kind, tok_str, tok_pos, tok_len); - new_token = result; - m_lexed_tokens.push_back(std::move(new_token)); +llvm::Expected DILLexer::Create(llvm::StringRef expr) { + std::vector tokens; + llvm::StringRef remainder = expr; + do { + if (llvm::Expected t = Lex(expr, remainder)) { + tokens.push_back(std::move(*t)); + } else { + return t.takeError(); + } + } while (tokens.back().GetKind() != Token::eof); + return DILLexer(expr, std::move(tokens)); } -bool DILLexer::Lex(DILToken &result, bool look_ahead) { - bool retval = true; - - if (!look_ahead) { - // We're being asked for the 'next' token, and not a part of a LookAhead. - // Check to see if we've already lexed it and pushed it onto our tokens - // vector; if so, return the next token from the vector, rather than doing - // more lexing. - if ((m_tokens_idx != UINT_MAX) && - (m_tokens_idx < m_lexed_tokens.size() - 1)) { - result = m_lexed_tokens[m_tokens_idx + 1]; - return retval; - } - } +llvm::Expected DILLexer::Lex(llvm::StringRef expr, + llvm::StringRef &remainder) { // Skip over whitespace (spaces). - while (m_cur_pos != m_expr.end() && *m_cur_pos == ' ') - m_cur_pos++; + remainder = remainder.ltrim(); + llvm::StringRef::iterator cur_pos = remainder.begin(); // Check to see if we've reached the end of our input string. - if (m_cur_pos == m_expr.end()) { - UpdateLexedTokens(result, dil::TokenKind::eof, "", m_expr.length(), 0); - return retval; - } + if (remainder.empty()) + return Token(Token::eof, "", (uint32_t)expr.size()); - uint32_t position = m_cur_pos - m_expr.begin();; - std::string::iterator start = m_cur_pos; - uint32_t length = 0; - dil::NumberKind kind = dil::NumberKind::eNone; - if (Is_Number(start, length, kind)) { - std::string number = m_expr.substr(position, length); - if (kind == dil::NumberKind::eInteger) { - UpdateLexedTokens(result, dil::TokenKind::numeric_constant, number, - position, length); - return true; - } else if (kind == dil::NumberKind::eFloat) { - UpdateLexedTokens(result, dil::TokenKind::numeric_constant, number, - position, length); - return true; + uint32_t position = cur_pos - expr.begin();; + llvm::StringRef::iterator start = cur_pos; + std::optional maybe_number = IsNumber(expr, remainder); + if (maybe_number) { + std::string number = (*maybe_number).str(); + return Token(Token::numeric_constant, number, position); + } else { + std::optional maybe_word = IsWord(expr, remainder); + if (maybe_word) { + llvm::StringRef word = *maybe_word; + Token::Kind kind = llvm::StringSwitch(word) + .Case("bool", Token::kw_bool) + .Case("char", Token::kw_char) + .Case("char16_t", Token::kw_char16_t) + .Case("char32_t", Token::kw_char32_t) + .Case("const", Token::kw_const) + .Case("double", Token::kw_double) + .Case("dynamic_cast", Token::kw_dynamic_cast) + .Case("false", Token::kw_false) + .Case("float", Token::kw_float) + .Case("int", Token::kw_int) + .Case("long", Token::kw_long) + .Case("namespace", Token::kw_namespace) + .Case("nullptr", Token::kw_nullptr) + .Case("reinterpret_cast", Token::kw_reinterpret_cast) + .Case("short", Token::kw_short) + .Case("signed", Token::kw_signed) + .Case("sizeof", Token::kw_sizeof) + .Case("static_cast", Token::kw_static_cast) + .Case("this", Token::kw_this) + .Case("true", Token::kw_true) + .Case("unsigned", Token::kw_unsigned) + .Case("void", Token::kw_void) + .Case("volatile", Token::kw_volatile) + .Case("wchar_t", Token::kw_wchar_t) + .Default(Token::identifier); + return Token(kind, word.str(), (uint32_t)position); } - } else if (Is_Word(start, length)) { - dil::TokenKind kind; - std::string word = m_expr.substr(position, length); - auto iter = Keywords.find(word); - if (iter != Keywords.end()) - kind = iter->second; - else - kind = dil::TokenKind::identifier; - UpdateLexedTokens(result, kind, word, position, - length); - return true; } - m_cur_pos = start; - switch (*m_cur_pos) { - case '[': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::l_square, "[", position, 1); - return true; - case ']': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::r_square, "]", position, 1); - return true; - case '(': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::l_paren, "(", position, 1); - return true; - case ')': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::r_paren, ")", position, 1); - return true; - case '&': - if (position+1 < m_expr.size() && - ((m_expr[position+1] == '=') || (m_expr[position+1] == '&'))) { - m_cur_pos += 2; - if (m_expr[position+1] == '&') - UpdateLexedTokens(result, dil::TokenKind::ampamp, "&&", position, 2); - else - UpdateLexedTokens(result, dil::TokenKind::ampequal, "&=", position, 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::amp, "&", position, 1); - return true; - case '|': - if (position+1 < m_expr.size() && - ((m_expr[position+1] == '=') || (m_expr[position+1] == '|'))) { - m_cur_pos += 2; - if (m_expr[position+1] == '|') - UpdateLexedTokens(result, dil::TokenKind::pipepipe, "||", position, 2); - else - UpdateLexedTokens(result, dil::TokenKind::pipeequal, "|=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::pipe, "|", position, 1); - return true; - case '+': - if (position+1 < m_expr.size() && - ((m_expr[position+1] == '=') || (m_expr[position+1] == '+'))) { - m_cur_pos += 2; - if (m_expr[position+1] == '+') - UpdateLexedTokens(result, dil::TokenKind::plusplus, "++", position, 2); - else - UpdateLexedTokens(result, dil::TokenKind::plusequal, "+=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::plus, "+", position, 1); - return true; - case '-': - if (position+1 < m_expr.size() && - ((m_expr[position+1] == '=') || (m_expr[position+1] == '-') || - (m_expr[position+1] == '>'))) { - m_cur_pos += 2; - if (m_expr[position+1] == '-') - UpdateLexedTokens(result, dil::TokenKind::minusminus, "--", position, - 2); - else if (m_expr[position+1] == '>') - UpdateLexedTokens(result, dil::TokenKind::arrow, "->", position, 2); - else - UpdateLexedTokens(result, dil::TokenKind::minusequal, "-=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::minus, "-", position, 1); - return true; - case '^': - if (position+1 < m_expr.size() && m_expr[position+1] == '=') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::caretequal, "^=", position, 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::caret, "^", position, 1); - return true; - case '=': - if (position+1 < m_expr.size() && m_expr[position+1] == '=') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::equalequal, "==", position, 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::equal, "=", position, 1); - return true; - case '!': - if (position+1 < m_expr.size() && m_expr[position+1] == '=') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::exclaimequal, "!=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::exclaim, "!", position, 1); - return true; - case '%': - if (position+1 < m_expr.size() && m_expr[position+1] == '=') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::percentequal, "%=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::percent, "%", position, 1); - return true; - case '/': - if (position+1 < m_expr.size() && m_expr[position+1] == '=') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::slashequal, "/=", position, 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::slash, "/", position, 1); - return true; - case '*': - if (position+1 < m_expr.size() && m_expr[position+1] == '=') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::starequal, "*=", position, 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::star, "*", position, 1); - return true; - case ':': - if (position+1 < m_expr.size() && m_expr[position+1] == ':') { - m_cur_pos += 2; - UpdateLexedTokens(result, dil::TokenKind::coloncolon, "::", position, 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::colon, ":", position, 1); - return true; - case '<': - if (position+2 < m_expr.size() && m_expr[position+1] == '<' && - m_expr[position+2] == '=') { - m_cur_pos += 3; - UpdateLexedTokens(result, dil::TokenKind::lesslessequal, "<<=", position, - 3); - return true; - } else if (position+1 < m_expr.size() && - ((m_expr[position+1] == '<') || (m_expr[position+1] == '='))){ - m_cur_pos += 2; - if (m_expr[position+1] == '<') - UpdateLexedTokens(result, dil::TokenKind::lessless, "<<", position, 2); - else - UpdateLexedTokens(result, dil::TokenKind::lessequal, "<=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::less, "<", position, 1); - return true; - case '>': - if (position+2 < m_expr.size() && m_expr[position+1] == '>' && - m_expr[position+2] == '=') { - m_cur_pos += 3; - UpdateLexedTokens(result, dil::TokenKind::greatergreaterequal, ">>=", - position, 3); - return true; - } else if (position+1 < m_expr.size() && - ((m_expr[position+1] == '>') || (m_expr[position+1] == '='))){ - m_cur_pos += 2; - if (m_expr[position+1] == '>') - UpdateLexedTokens(result, dil::TokenKind::greatergreater, ">>", - position, 2); - else - UpdateLexedTokens(result, dil::TokenKind::greaterequal, ">=", position, - 2); - return true; - } - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::greater, ">", position, 1); - return true; - case '.': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::period, ".", position, 1); - return true; - case '?': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::question, "?", position, 1); - return true; - case ',': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::comma, ",", position, 1); - return true; - case '~': - m_cur_pos++; - UpdateLexedTokens(result, dil::TokenKind::tilde, ",", position, 1); - return true; - default: - break; - } - // Empty Token - result.setValues(dil::TokenKind::none, "", m_expr.length(), 0); - return false; -} - -const DILToken &DILLexer::LookAhead(uint32_t N) { - uint32_t extra_lexed_tokens = m_lexed_tokens.size() - m_tokens_idx - 1; - - if (N+1 < extra_lexed_tokens) - return m_lexed_tokens[m_tokens_idx + N + 1]; - - uint32_t remaining_tokens = (m_tokens_idx + N + 1) - - m_lexed_tokens.size() + 1; - - bool done = false; - bool look_ahead = true; - while (!done && remaining_tokens > 0) { - DILToken tok; - Lex(tok, look_ahead); - if (tok.getKind() == dil::TokenKind::eof) - done = true; - remaining_tokens--; + cur_pos = start; + constexpr std::pair operators[] = { + {Token::l_square, "["}, + {Token::r_square, "]"}, + {Token::l_paren, "("}, + {Token::r_paren, ")"}, + {Token::ampamp, "&&"}, + {Token::ampequal, "&="}, + {Token::amp, "&"}, + {Token::pipepipe, "||"}, + {Token::pipeequal, "|="}, + {Token::pipe, "|"}, + {Token::plusplus, "++"}, + {Token::plusequal, "+="}, + {Token::plus, "+"}, + {Token::minusminus, "--"}, + {Token::minusequal, "-="}, + {Token::arrow, "->"}, + {Token::minus, "-"}, + {Token::caretequal, "^="}, + {Token::caret, "^"}, + {Token::equalequal, "=="}, + {Token::equal, "="}, + {Token::exclaimequal, "!="}, + {Token::exclaim, "!"}, + {Token::percentequal, "%="}, + {Token::percent, "%"}, + {Token::slashequal, "/="}, + {Token::slash, "/"}, + {Token::starequal, "*="}, + {Token::star, "*"}, + {Token::coloncolon, "::"}, + {Token::colon, ":"}, + {Token::lesslessequal, "<<="}, + {Token::lessless, "<<"}, + {Token::lessequal, "<="}, + {Token::less, "<"}, + {Token::greatergreaterequal, ">>="}, + {Token::greatergreater, ">>"}, + {Token::greaterequal, ">="}, + {Token::greater, ">"}, + {Token::period, "."}, + {Token::question, "?"}, + {Token::comma, ","}, + {Token::tilde, "~"}, }; - if (remaining_tokens > 0) { - m_invalid_token.setValues(dil::TokenKind::invalid, "", 0, 0); - return m_invalid_token; - } else - return m_lexed_tokens[m_tokens_idx + N + 1]; -} - -const DILToken &DILLexer::AcceptLookAhead(uint32_t N) { - if (m_tokens_idx + N + 1 > m_lexed_tokens.size()) - return m_invalid_token; + for (auto [kind, str] : operators) { + if (remainder.consume_front(str)) + return Token(kind, str, position); + } - m_tokens_idx += N + 1; - return m_lexed_tokens[m_tokens_idx]; + // Unrecognized character(s) in string; unable to lex it. + return llvm::createStringError("Unable to lex input string"); } -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILLiteralParsers.cpp b/lldb/source/ValueObject/DILLiteralParsers.cpp index 14f32aace777..746822376685 100644 --- a/lldb/source/ValueObject/DILLiteralParsers.cpp +++ b/lldb/source/ValueObject/DILLiteralParsers.cpp @@ -28,9 +28,7 @@ #include #include -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { enum class diag { // errs @@ -88,16 +86,16 @@ static void Diags_Report(uint32_t loc, dil::diag diag_id, std::string diag_msg) } -static unsigned getCharWidth(dil::TokenKind kind) { +static unsigned getCharWidth(Token::Kind kind) { switch (kind) { default: llvm_unreachable("Unknown token type!"); - case dil::TokenKind::char_constant: - case dil::TokenKind::string_literal: - case dil::TokenKind::utf8_char_constant: - case dil::TokenKind::utf8_string_literal: + case Token::char_constant: + case Token::string_literal: + case Token::utf8_char_constant: + case Token::utf8_string_literal: return 8; - case dil::TokenKind::wide_char_constant: - case dil::TokenKind::wide_string_literal: + case Token::wide_char_constant: + case Token::wide_string_literal: return 16; } } @@ -206,19 +204,6 @@ NumericLiteralParser::NumericLiteralParser(llvm::StringRef TokSpelling, break; HasSize = true; - // CUDA host and device may have different _Float16 support, therefore - // allows f16 literals to avoid false alarm. - // When we compile for OpenMP target offloading on NVPTX, f16 suffix - // should also be supported. - // ToDo: more precise check for CUDA. - // TODO: AMDGPU might also support it in the future. - //if ((lexer.getTargetInfo().hasFloat16Type() || - // lexer.getTargetInfo().getTriple().isNVPTX()) && - // s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') { - // s += 2; // success, eat up 2 characters. - // isFloat16 = true; - // continue; - //} isFloat = true; continue; // Success. @@ -365,8 +350,6 @@ NumericLiteralParser::NumericLiteralParser(llvm::StringRef TokSpelling, llvm::StringRef(SuffixBegin, ThisTokEnd - SuffixBegin).str(); err_msg += (isFixedPointConstant ? "2" : (isFPConstant ? "1" : "0")); - //Diags_Report(Lexer::AdvanceToTokenCharacter( - // TokLoc, SuffixBegin - ThisTokBegin, SM, LangOpts), Diags_Report(SuffixBegin - ThisTokBegin - TokLoc, diag::err_invalid_suffix_constant, err_msg); hadError = true; @@ -501,8 +484,6 @@ void NumericLiteralParser::ParseNumberStartingWithZero(unsigned TokLoc, } if (!HasSignificandDigits) { - //Diags_Report(Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, - // LangOpts), Diags_Report(s - ThisTokBegin - TokLoc, diag::err_hex_constant_requires, "1"); hadError = true; @@ -520,8 +501,6 @@ void NumericLiteralParser::ParseNumberStartingWithZero(unsigned TokLoc, const char *first_non_digit = SkipDigits(s); if (!containsDigits(s, first_non_digit)) { if (!hadError) { - //Diags_Report(Lexer::AdvanceToTokenCharacter( - // TokLoc, Exponent - ThisTokBegin, SM, LangOpts), Diags_Report(Exponent - ThisTokBegin - TokLoc, diag::err_exponent_has_no_digits, ""); hadError = true; @@ -534,8 +513,6 @@ void NumericLiteralParser::ParseNumberStartingWithZero(unsigned TokLoc, if (!AllowHexFloats) Diags_Report(TokLoc, diag::ext_hex_literal_invalid, ""); } else if (saw_period) { - //Diags_Report(Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, - // LangOpts), Diags_Report(s - ThisTokBegin - TokLoc, diag::err_hex_constant_requires, "0"); hadError = true; @@ -558,8 +535,6 @@ void NumericLiteralParser::ParseNumberStartingWithZero(unsigned TokLoc, // Done. } else if (isHexDigit(*s)) { std::string err_msg = llvm::StringRef(s, 1).str() + "2"; - //Diags_Report(Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, - // LangOpts), Diags_Report(s - ThisTokBegin - TokLoc, diag::err_invalid_digit, err_msg); hadError = true; @@ -604,7 +579,6 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(unsigned TokLoc) { std::string err_msg = llvm::StringRef(s, 1).str(); err_msg += (radix == 8 ? "1" : "0"); Diags_Report( - //Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, LangOpts), s - ThisTokBegin - TokLoc, diag::err_invalid_digit, err_msg); hadError = true; @@ -632,8 +606,6 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(unsigned TokLoc) { s = first_non_digit; } else { if (!hadError) { - //Diags_Report(Lexer::AdvanceToTokenCharacter( - // TokLoc, Exponent - ThisTokBegin, SM, LangOpts), Diags_Report(Exponent - ThisTokBegin - TokLoc, diag::err_exponent_has_no_digits, ""); hadError = true; @@ -653,8 +625,6 @@ void NumericLiteralParser::CheckSeparator(unsigned TokLoc, const char *Pos, return; if (isDigitSeparator(*Pos)) { - //Diags_Report(Lexer::AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin, SM, - // LangOpts), Diags_Report(Pos - ThisTokBegin - TokLoc, diag::err_digit_separator_not_between_digits, (IsAfterDigits ? "true" : "false")); @@ -1122,7 +1092,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, if (Delimited) { if (!EndDelimiterFound) Diags_Report(Loc, - diag::err_expected, "dil::TokenKind::r_brace"); + diag::err_expected, "Token::r_brace"); else if (!HadError) { Diags_Report(Loc, diag::ext_delimited_escape_sequence, ""); @@ -1142,7 +1112,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, CharLiteralParser::CharLiteralParser(const char *begin, const char *end, unsigned Loc, DILLexer &lexer, - dil::TokenKind kind) { + Token::Kind kind) { // At this point we know that the character matches the regex "(L|u|U)?'.*'". HadError = false; @@ -1151,9 +1121,9 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, const char *TokBegin = begin; // Skip over wide character determinant. - if (Kind != dil::TokenKind::char_constant) + if (Kind != Token::char_constant) ++begin; - if (Kind == dil::TokenKind::utf8_char_constant) + if (Kind == Token::utf8_char_constant) ++begin; // Skip over the entry quote. @@ -1172,12 +1142,12 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, // FIXME: The "Value" is an uint64_t so we can handle char literals of // up to 64-bits. // FIXME: This extensively assumes that 'char' is 8-bits. - assert(lexer.getCharWidth() == 8 && + assert(lexer.GetCharWidth() == 8 && "Assumes char is 8 bits"); - assert(lexer.getIntWidth() <= 64 && - (lexer.getIntWidth() & 7) == 0 && + assert(lexer.GetIntWidth() <= 64 && + (lexer.GetIntWidth() & 7) == 0 && "Assumes sizeof(int) on target is <= 64 and a multiple of char"); - assert(lexer.getWCharWidth() <= 64 && + assert(lexer.GetWCharWidth() <= 64 && "Assumes sizeof(wchar) on target is <= 64"); llvm::SmallVector codepoint_buffer; @@ -1189,10 +1159,10 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, // represented in a single code unit are disallowed in character literals // by this implementation. uint32_t largest_character_for_kind; - if (dil::TokenKind::wide_char_constant == Kind) { + if (Token::wide_char_constant == Kind) { largest_character_for_kind = - 0xFFFFFFFFu >> (lexer.getWCharWidth()); - } else if (dil::TokenKind::utf8_char_constant == Kind) { + 0xFFFFFFFFu >> (lexer.GetWCharWidth()); + } else if (Token::utf8_char_constant == Kind) { largest_character_for_kind = 0x7F; } else { largest_character_for_kind = 0x7Fu; @@ -1279,7 +1249,7 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, IsMultiChar = false; } - llvm::APInt LitVal(lexer.getIntWidth(), 0); + llvm::APInt LitVal(lexer.GetIntWidth(), 0); // Narrow character literals act as though their value is concatenated // in this implementation, but warn on overflow. @@ -1313,61 +1283,64 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end, } -StringLiteralParser::StringLiteralParser(llvm::ArrayRef StringToks, +StringLiteralParser::StringLiteralParser(llvm::ArrayRef StringToks, DILLexer &lexer, StringLiteralEvalMethod EvalMethod) : MaxTokenLength(0), SizeBound(0), CharByteWidth(0), - Kind(dil::TokenKind::unknown), ResultPtr(ResultBuf.data()), + //Kind(Token::unknown), + ResultPtr(ResultBuf.data()), EvalMethod(EvalMethod), m_lexer(lexer), hadError(false) { init(StringToks, lexer); } -void StringLiteralParser::init(llvm::ArrayRef StringToks, +void StringLiteralParser::init(llvm::ArrayRef StringToks, DILLexer &lexer) { // The literal token may have come from an invalid source location (e.g. due // to a PCH error), in which case the token length will be 0. - if (StringToks.empty() || StringToks[0].getLength() < 2) - return DiagnoseLexingError(lexer.GetLocation()); + if (StringToks.empty()) + return DiagnoseLexingError(0); + if (StringToks[0].GetSpelling().size() < 2) + return DiagnoseLexingError(StringToks[0].GetLocation()); // Scan all of the string portions, remember the max individual token length, // computing a bound on the concatenated string length, and see whether any // piece is a wide-string. If any of the string portions is a wide-string // literal, the result is a wide-string literal [C99 6.4.5p4]. assert(!StringToks.empty() && "expected at least one token"); - MaxTokenLength = StringToks[0].getLength(); - assert(StringToks[0].getLength() >= 2 && "literal token is invalid!"); - SizeBound = StringToks[0].getLength() - 2; // -2 for "". + MaxTokenLength = StringToks[0].GetSpelling().size(); + assert(StringToks[0].GetSpelling().size() >= 2 && "literal token is invalid!"); + SizeBound = StringToks[0].GetSpelling().size() - 2; // -2 for "". hadError = false; // Determines the kind of string from the prefix - Kind = dil::TokenKind::string_literal; + Kind = Token::string_literal; /// (C99 5.1.1.2p1). The common case is only one string fragment. - for (const DILToken &Tok : StringToks) { - if (Tok.getLength() < 2) - return DiagnoseLexingError(Tok.getLocation()); + for (const Token &Tok : StringToks) { + if (Tok.GetSpelling().size() < 2) + return DiagnoseLexingError(Tok.GetLocation()); // The string could be shorter than this if it needs cleaning, but this is a // reasonable bound, which is all we need. - assert(Tok.getLength() >= 2 && "literal token is invalid!"); - SizeBound += Tok.getLength() - 2; // -2 for "". + assert(Tok.GetSpelling().size() >= 2 && "literal token is invalid!"); + SizeBound += Tok.GetSpelling().size() - 2; // -2 for "". // Remember maximum string piece length. - if (Tok.getLength() > MaxTokenLength) - MaxTokenLength = Tok.getLength(); + if (Tok.GetSpelling().size() > MaxTokenLength) + MaxTokenLength = Tok.GetSpelling().size(); // Remember if we see any wide or utf-8/16/32 strings. // Also check for illegal concatenations. - if (isUnevaluated() && Tok.getKind() != dil::TokenKind::string_literal) { - Diags_Report(Tok.getLocation(), + if (isUnevaluated() && Tok.GetKind() != Token::string_literal) { + Diags_Report(Tok.GetLocation(), diag::warn_unevaluated_string_prefix, ""); hadError = true; - } else if (Tok.isNot(Kind) && Tok.isNot(dil::TokenKind::string_literal)) { + } else if (Tok.IsNot(Kind) && Tok.IsNot(Token::string_literal)) { if (isOrdinary()) { - Kind = Tok.getKind(); + Kind = Tok.GetKind(); } else { - Diags_Report(Tok.getLocation(), diag::err_unsupported_string_concat, + Diags_Report(Tok.GetLocation(), diag::err_unsupported_string_concat, ""); hadError = true; } @@ -1405,13 +1378,10 @@ void StringLiteralParser::init(llvm::ArrayRef StringToks, // that ThisTokBuf points to a buffer that is big enough for the whole token // and 'spelled' tokens can only shrink. bool StringInvalid = false; - //unsigned ThisTokLen = // CAROLINE!! - // Lexer::getSpelling(StringToks[i], ThisTokBuf, SM, Features, - // &StringInvalid); - ThisTokBuf = StringToks[i].getSpelling().data(); - unsigned ThisTokLen = StringToks[i].getLength(); + ThisTokBuf = StringToks[i].GetSpelling().data(); + unsigned ThisTokLen = StringToks[i].GetSpelling().size(); if (StringInvalid) - return DiagnoseLexingError(StringToks[i].getLocation()); + return DiagnoseLexingError(StringToks[i].GetLocation()); const char *ThisTokBegin = ThisTokBuf; const char *ThisTokEnd = ThisTokBuf+ThisTokLen; @@ -1434,7 +1404,7 @@ void StringLiteralParser::init(llvm::ArrayRef StringToks, if (ThisTokBuf[1] != '"') { // The file may have come from PCH and then changed after loading the // PCH; Fail gracefully. - return DiagnoseLexingError(StringToks[i].getLocation()); + return DiagnoseLexingError(StringToks[i].GetLocation()); } ThisTokBuf += 2; // skip R" @@ -1447,13 +1417,13 @@ void StringLiteralParser::init(llvm::ArrayRef StringToks, ThisTokBuf[0] != '(') ++ThisTokBuf; if (ThisTokBuf[0] != '(') - return DiagnoseLexingError(StringToks[i].getLocation()); + return DiagnoseLexingError(StringToks[i].GetLocation()); ++ThisTokBuf; // skip '(' // Remove same number of characters from the end ThisTokEnd -= ThisTokBuf - Prefix; if (ThisTokEnd < ThisTokBuf) - return DiagnoseLexingError(StringToks[i].getLocation()); + return DiagnoseLexingError(StringToks[i].GetLocation()); // C++14 [lex.string]p4: A source-file new-line in a raw string literal // results in a new-line in the resulting execution string-literal. @@ -1476,7 +1446,7 @@ void StringLiteralParser::init(llvm::ArrayRef StringToks, if (ThisTokBuf[0] != '"') { // The file may have come from PCH and then changed after loading the // PCH; Fail gracefully. - return DiagnoseLexingError(StringToks[i].getLocation()); + return DiagnoseLexingError(StringToks[i].GetLocation()); } ++ThisTokBuf; // skip " @@ -1499,14 +1469,14 @@ void StringLiteralParser::init(llvm::ArrayRef StringToks, ThisTokBuf[1] == 'N') { EncodeUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, ResultPtr, hadError, - StringToks[i].getLocation(), + StringToks[i].GetLocation(), CharByteWidth); continue; } // Otherwise, this is a non-UCN escape character. Process it. unsigned ResultChar = ProcessCharEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, hadError, - StringToks[i].getLocation(), + StringToks[i].GetLocation(), CharByteWidth * 8, EvalMethod); if (CharByteWidth == 4) { @@ -1533,7 +1503,7 @@ void StringLiteralParser::init(llvm::ArrayRef StringToks, unsigned MaxChars = 65536; if (GetNumStringChars() > MaxChars) - Diags_Report(StringToks.front().getLocation(), + Diags_Report(StringToks.front().GetLocation(), diag::ext_string_too_long,""); } @@ -1581,18 +1551,16 @@ static int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, } -unsigned StringLiteralParser::getOffsetOfStringByte(const DILToken &Tok, +unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok, unsigned ByteNo) const { // Get the spelling of the token. llvm::SmallString<32> SpellingBuffer; - SpellingBuffer.resize(Tok.getLength()); + SpellingBuffer.resize(Tok.GetSpelling().size()); bool StringInvalid = false; const char *SpellingPtr = &SpellingBuffer[0]; - SpellingPtr = Tok.getSpelling().data(); - unsigned TokLen = Tok.getLength(); - //unsigned TokLen = Lexer::getSpelling(Tok, SpellingPtr, SM, Features, - // &StringInvalid); + SpellingPtr = Tok.GetSpelling().data(); + unsigned TokLen = Tok.GetSpelling().size(); if (StringInvalid) return 0; @@ -1650,7 +1618,7 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const DILToken &Tok, ByteNo -= Len; } else { ProcessCharEscape(SpellingStart, SpellingPtr, SpellingEnd, HadError, - Tok.getLocation(), CharByteWidth * 8, + Tok.GetLocation(), CharByteWidth * 8, StringLiteralEvalMethod::Evaluated); --ByteNo; } @@ -1661,7 +1629,7 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const DILToken &Tok, } -bool StringLiteralParser::CopyStringFragment(const DILToken &Tok, +bool StringLiteralParser::CopyStringFragment(const Token &Tok, const char *TokBegin, llvm::StringRef Fragment) { const llvm::UTF8 *ErrorPtrTmp; @@ -1679,7 +1647,7 @@ bool StringLiteralParser::CopyStringFragment(const DILToken &Tok, const char *ErrorPtr = reinterpret_cast(ErrorPtrTmp); - uint32_t SourceLoc = Tok.getLocation(); + uint32_t SourceLoc = Tok.GetLocation(); Diags_Report(SourceLoc, NoErrorOnBadEncoding ? diag::warn_bad_string_encoding : diag::err_bad_string_encoding, ""); @@ -1707,6 +1675,4 @@ void StringLiteralParser::DiagnoseLexingError(unsigned Loc) { Diags_Report(Loc, diag::err_lexing_string, ""); } -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index 7070df7edb9b..1be388ca13db 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -54,17 +54,15 @@ constexpr unsigned type_width() { } // namespace -namespace lldb_private { - -namespace dil { +namespace lldb_private::dil { inline void TokenKindsJoinImpl(std::ostringstream& os, - dil::TokenKind k) { - os << "'" << DILToken::getTokenName(k) << "'"; + Token::Kind k) { + os << "'" << Token::GetTokenName(k).str() << "'"; } template -inline void TokenKindsJoinImpl(std::ostringstream& os, dil::TokenKind k, +inline void TokenKindsJoinImpl(std::ostringstream& os, Token::Kind k, Ts... ks) { TokenKindsJoinImpl(os, k); os << ", "; @@ -72,7 +70,7 @@ inline void TokenKindsJoinImpl(std::ostringstream& os, dil::TokenKind k, } template -inline std::string TokenKindsJoin(dil::TokenKind k, Ts... ks) { +inline std::string TokenKindsJoin(Token::Kind k, Ts... ks) { std::ostringstream os; TokenKindsJoinImpl(os, k, ks...); @@ -195,11 +193,6 @@ static bool GetPathToBaseType(CompilerType type, CompilerType target_base, return false; } -std::shared_ptr DILSourceManager::Create(std::string expr) { - return std::shared_ptr(new DILSourceManager( - std::move(expr))); -}; - static const char* ToString(TypeDeclaration::TypeSpecifier type_spec) { using TypeSpecifier = TypeDeclaration::TypeSpecifier; switch (type_spec) { @@ -233,11 +226,11 @@ static const char* ToString(TypeDeclaration::SignSpecifier sign_spec) { } } -static bool TokenEndsTemplateArgumentList(const DILToken& token) { +static bool TokenEndsTemplateArgumentList(const Token& token) { // Note: in C++11 ">>" can be treated as "> >" and thus be a valid token // for the template argument list. - return token.isOneOf(dil::TokenKind::comma, dil::TokenKind::greater, - dil::TokenKind::greatergreater); + return token.IsOneOf(Token::comma, Token::greater, + Token::greatergreater); } static DILASTNodeUP InsertArrayToPointerConversion(DILASTNodeUP expr) { @@ -561,21 +554,20 @@ static CompilerType UsualArithmeticConversions( return lhs->GetDereferencedResultType().GetCanonicalType(); } -static TypeDeclaration::TypeSpecifier ToTypeSpecifier( - dil::TokenKind kind) { +static TypeDeclaration::TypeSpecifier ToTypeSpecifier(Token::Kind kind) { using TypeSpecifier = TypeDeclaration::TypeSpecifier; switch (kind) { - case dil::TokenKind::kw_void: return TypeSpecifier::kVoid; - case dil::TokenKind::kw_bool: return TypeSpecifier::kBool; - case dil::TokenKind::kw_char: return TypeSpecifier::kChar; - case dil::TokenKind::kw_short: return TypeSpecifier::kShort; - case dil::TokenKind::kw_int: return TypeSpecifier::kInt; - case dil::TokenKind::kw_long: return TypeSpecifier::kLong; - case dil::TokenKind::kw_float: return TypeSpecifier::kFloat; - case dil::TokenKind::kw_double: return TypeSpecifier::kDouble; - case dil::TokenKind::kw_wchar_t: return TypeSpecifier::kWChar; - case dil::TokenKind::kw_char16_t: return TypeSpecifier::kChar16; - case dil::TokenKind::kw_char32_t: return TypeSpecifier::kChar32; + case Token::kw_void: return TypeSpecifier::kVoid; + case Token::kw_bool: return TypeSpecifier::kBool; + case Token::kw_char: return TypeSpecifier::kChar; + case Token::kw_short: return TypeSpecifier::kShort; + case Token::kw_int: return TypeSpecifier::kInt; + case Token::kw_long: return TypeSpecifier::kLong; + case Token::kw_float: return TypeSpecifier::kFloat; + case Token::kw_double: return TypeSpecifier::kDouble; + case Token::kw_wchar_t: return TypeSpecifier::kWChar; + case Token::kw_char16_t: return TypeSpecifier::kChar16; + case Token::kw_char32_t: return TypeSpecifier::kChar32; default: assert(false && "invalid type specifier token"); return TypeSpecifier::kUnknown; @@ -679,11 +671,10 @@ lldb::BasicType PickCharType(const dil::StringLiteralParser& literal) { return lldb::eBasicTypeChar; } -std::string FormatDiagnostics(DILSourceManager &sm, const std::string &message, +std::string FormatDiagnostics(llvm::StringRef text, const std::string& message, uint32_t loc) { - // Get the source buffer and the location of the current token. - llvm::StringRef text = sm.GetSource(); - size_t loc_offset = (size_t)loc; + // Get the location of the current token. + size_t loc_offset = (size_t) loc; // Look for the start of the line. size_t line_start = text.rfind('\n', loc_offset); @@ -703,31 +694,28 @@ std::string FormatDiagnostics(DILSourceManager &sm, const std::string &message, size_t expr_rpad = std::max(0, arrow - static_cast(line.size())); size_t arrow_rpad = std::max(0, static_cast(line.size()) - arrow); - return llvm::formatv(":1:{0}: {1}\n{2}\n{3}", loc + 1, message, - llvm::fmt_pad(line, 0, expr_rpad), + return llvm::formatv(": {1}\n{2}\n{3}", loc + 1, + message, llvm::fmt_pad(line, 0, expr_rpad), llvm::fmt_pad("^", arrow - 1, arrow_rpad)); } -DILParser::DILParser(std::shared_ptr dil_sm, +DILParser::DILParser(llvm::StringRef dil_input_expr, DILLexer lexer, std::shared_ptr exe_ctx_scope, lldb::DynamicValueType use_dynamic, bool use_synthetic, bool fragile_ivar, bool check_ptr_vs_member) - : m_ctx_scope(exe_ctx_scope), m_sm(dil_sm), m_use_dynamic(use_dynamic), + : m_ctx_scope(exe_ctx_scope), m_input_expr(dil_input_expr), + m_dil_lexer(lexer), m_dil_token(lexer.GetCurrentToken()), + m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic), m_fragile_ivar(fragile_ivar), - m_check_ptr_vs_member(check_ptr_vs_member), - m_dil_lexer(DILLexer(dil_sm)) + m_check_ptr_vs_member(check_ptr_vs_member) { - // Initialize the token. - m_dil_token.setKind(dil::TokenKind::unknown); } DILASTNodeUP DILParser::Run(Status& error) { - ConsumeToken(); - DILASTNodeUP expr; - if (m_dil_lexer.isStringLiteral(m_dil_token.getKind()) && - m_dil_lexer.LookAhead(0).is(dil::TokenKind::eof)) { + if (m_dil_lexer.IsStringLiteral(m_dil_token.GetKind()) && + m_dil_lexer.LookAhead(1).Is(Token::eof)) { // A special case to handle a single string-literal token. expr = ParseStringLiteral(); } else { @@ -735,7 +723,7 @@ DILASTNodeUP DILParser::Run(Status& error) { } - Expect(dil::TokenKind::eof); + Expect(Token::eof); error = std::move(m_error); m_error.Clear(); @@ -756,7 +744,7 @@ CompilerType DILParser::ResolveTypeDeclarators( CompilerType bad_type; // Resolve pointers/references. for (auto& [tk, loc] : ptr_operators) { - if (tk == dil::TokenKind::star) { + if (tk == Token::star) { // Pointers to reference types are forbidden. if (type.IsReferenceType()) { BailOut(ErrorCode::kInvalidOperandType, @@ -769,7 +757,7 @@ CompilerType DILParser::ResolveTypeDeclarators( // Get pointer type for the base type: e.g. int* -> int**. type = type.GetPointerType(); - } else if (tk == dil::TokenKind::amp) { + } else if (tk == Token::amp) { // References to references are forbidden. if (type.IsReferenceType()) { BailOut(ErrorCode::kInvalidOperandType, @@ -784,21 +772,21 @@ CompilerType DILParser::ResolveTypeDeclarators( return type; } -bool DILParser::IsSimpleTypeSpecifierKeyword(DILToken token) const { - return token.isOneOf( - dil::TokenKind::kw_char, dil::TokenKind::kw_char16_t, dil::TokenKind::kw_char32_t, - dil::TokenKind::kw_wchar_t, dil::TokenKind::kw_bool, dil::TokenKind::kw_short, - dil::TokenKind::kw_int, dil::TokenKind::kw_long, dil::TokenKind::kw_signed, - dil::TokenKind::kw_unsigned, dil::TokenKind::kw_float, dil::TokenKind::kw_double, - dil::TokenKind::kw_void); +bool DILParser::IsSimpleTypeSpecifierKeyword(Token token) const { + return token.IsOneOf( + Token::kw_char, Token::kw_char16_t, Token::kw_char32_t, + Token::kw_wchar_t, Token::kw_bool, Token::kw_short, + Token::kw_int, Token::kw_long, Token::kw_signed, + Token::kw_unsigned, Token::kw_float, Token::kw_double, + Token::kw_void); } -bool DILParser::IsCvQualifier(DILToken token) const { - return token.isOneOf(dil::TokenKind::kw_const, dil::TokenKind::kw_volatile); +bool DILParser::IsCvQualifier(Token token) const { + return token.IsOneOf(Token::kw_const, Token::kw_volatile); } -bool DILParser::IsPtrOperator(DILToken token) const { - return token.isOneOf(dil::TokenKind::star, dil::TokenKind::amp); +bool DILParser::IsPtrOperator(Token token) const { + return token.IsOneOf(Token::star, Token::amp); } bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { @@ -806,11 +794,11 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { using SignSpecifier = TypeDeclaration::SignSpecifier; TypeSpecifier type_spec = type_decl->m_type_specifier; - uint32_t loc = m_dil_token.getLocation(); - dil::TokenKind kind = m_dil_token.getKind(); + uint32_t loc = m_dil_token.GetLocation(); + Token::Kind kind = m_dil_token.GetKind(); switch (kind) { - case dil::TokenKind::kw_int: { + case Token::kw_int: { // "int" can have signedness and be combined with "short", "long" and // "long long" (but not with another "int"). if (type_decl->m_has_int_specifier) { @@ -837,7 +825,7 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return false; } - case dil::TokenKind::kw_long: { + case Token::kw_long: { // "long" can have signedness and be combined with "int" or "long" to // form "long long". if (type_spec == TypeSpecifier::kUnknown || @@ -859,7 +847,7 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return false; } - case dil::TokenKind::kw_short: { + case Token::kw_short: { // "short" can have signedness and be combined with "int". if (type_spec == TypeSpecifier::kUnknown || type_spec == TypeSpecifier::kInt) { @@ -874,7 +862,7 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return false; } - case dil::TokenKind::kw_char: { + case Token::kw_char: { // "char" can have signedness, but it cannot be combined with any other // type specifier. if (type_spec == TypeSpecifier::kUnknown) { @@ -889,7 +877,7 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return false; } - case dil::TokenKind::kw_double: { + case Token::kw_double: { // "double" can be combined with "long" to form "long double", but it // cannot be combined with signedness specifier. if (type_decl->m_sign_specifier != SignSpecifier::kUnknown) { @@ -912,12 +900,12 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return false; } - case dil::TokenKind::kw_bool: - case dil::TokenKind::kw_void: - case dil::TokenKind::kw_float: - case dil::TokenKind::kw_wchar_t: - case dil::TokenKind::kw_char16_t: - case dil::TokenKind::kw_char32_t: { + case Token::kw_bool: + case Token::kw_void: + case Token::kw_float: + case Token::kw_wchar_t: + case Token::kw_char16_t: + case Token::kw_char32_t: { // These types cannot have signedness or be combined with any other type // specifiers. if (type_decl->m_sign_specifier != SignSpecifier::kUnknown) { @@ -938,8 +926,8 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return true; } - case dil::TokenKind::kw_signed: - case dil::TokenKind::kw_unsigned: { + case Token::kw_signed: + case Token::kw_unsigned: { // "signed" and "unsigned" cannot be combined with another signedness // specifier. if (type_decl->m_sign_specifier != SignSpecifier::kUnknown) { @@ -965,7 +953,7 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { return false; } - type_decl->m_sign_specifier = (kind == dil::TokenKind::kw_signed) + type_decl->m_sign_specifier = (kind == Token::kw_signed) ? SignSpecifier::kSigned : SignSpecifier::kUnsigned; return true; @@ -978,14 +966,14 @@ bool DILParser::HandleSimpleTypeSpecifier(TypeDeclaration* type_decl) { } DILASTNodeUP DILParser::ParseStringLiteral() { - ExpectOneOf(dil::TokenKind::string_literal, dil::TokenKind::wide_string_literal, - dil::TokenKind::utf8_string_literal); - uint32_t loc = m_dil_token.getLocation(); + ExpectOneOf(Token::string_literal, Token::wide_string_literal, + Token::utf8_string_literal); + uint32_t loc = m_dil_token.GetLocation(); // TODO: Support parsing of joined string-literals (e.g. "abc" "def"). // Currently, only a single token can be parsed into a string. dil::StringLiteralParser string_literal( - llvm::ArrayRef(m_dil_token), m_dil_lexer); + llvm::ArrayRef(m_dil_token), m_dil_lexer); if (string_literal.hadError) { // TODO: Use ErrorCode::kInvalidStringLiteral in the future. @@ -1049,30 +1037,30 @@ DILASTNodeUP DILParser::ParseAssignmentExpression() { auto lhs = ParseLogicalOrExpression(); // Check if it's an assignment expression. - if (m_dil_token.isOneOf(dil::TokenKind::equal, dil::TokenKind::starequal, - dil::TokenKind::slashequal, dil::TokenKind::percentequal, - dil::TokenKind::plusequal, dil::TokenKind::minusequal, - dil::TokenKind::greatergreaterequal, dil::TokenKind::lesslessequal, - dil::TokenKind::ampequal, dil::TokenKind::caretequal, - dil::TokenKind::pipeequal)) { + if (m_dil_token.IsOneOf(Token::equal, Token::starequal, + Token::slashequal, Token::percentequal, + Token::plusequal, Token::minusequal, + Token::greatergreaterequal, Token::lesslessequal, + Token::ampequal, Token::caretequal, + Token::pipeequal)) { // That's an assignment! - DILToken token = m_dil_token; + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseAssignmentExpression(); - lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.getKind()), - std::move(lhs), std::move(rhs), token.getLocation()); + lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.GetKind()), + std::move(lhs), std::move(rhs), token.GetLocation()); } // Check if it's a conditional expression. - if (m_dil_token.is(dil::TokenKind::question)) { - DILToken token = m_dil_token; + if (m_dil_token.Is(Token::question)) { + Token token = m_dil_token; ConsumeToken(); auto true_val = ParseExpression(); - Expect(dil::TokenKind::colon); + Expect(Token::colon); ConsumeToken(); auto false_val = ParseAssignmentExpression(); lhs = BuildTernaryOp(std::move(lhs), std::move(true_val), - std::move(false_val), token.getLocation()); + std::move(false_val), token.GetLocation()); } return lhs; @@ -1086,12 +1074,12 @@ DILASTNodeUP DILParser::ParseAssignmentExpression() { DILASTNodeUP DILParser::ParseLogicalOrExpression() { auto lhs = ParseLogicalAndExpression(); - while (m_dil_token.is(dil::TokenKind::pipepipe)) { - DILToken token = m_dil_token; + while (m_dil_token.Is(Token::pipepipe)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseLogicalAndExpression(); lhs = BuildBinaryOp(BinaryOpKind::LOr, std::move(lhs), std::move(rhs), - token.getLocation()); + token.GetLocation()); } return lhs; @@ -1105,12 +1093,12 @@ DILASTNodeUP DILParser::ParseLogicalOrExpression() { DILASTNodeUP DILParser::ParseLogicalAndExpression() { auto lhs = ParseInclusiveOrExpression(); - while (m_dil_token.is(dil::TokenKind::ampamp)) { - DILToken token = m_dil_token; + while (m_dil_token.Is(Token::ampamp)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseInclusiveOrExpression(); lhs = BuildBinaryOp(BinaryOpKind::LAnd, std::move(lhs), std::move(rhs), - token.getLocation()); + token.GetLocation()); } return lhs; @@ -1124,12 +1112,12 @@ DILASTNodeUP DILParser::ParseLogicalAndExpression() { DILASTNodeUP DILParser::ParseInclusiveOrExpression() { auto lhs = ParseExclusiveOrExpression(); - while (m_dil_token.is(dil::TokenKind::pipe)) { - DILToken token = m_dil_token; + while (m_dil_token.Is(Token::pipe)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseExclusiveOrExpression(); lhs = BuildBinaryOp(BinaryOpKind::Or, std::move(lhs), std::move(rhs), - token.getLocation()); + token.GetLocation()); } return lhs; @@ -1143,12 +1131,12 @@ DILASTNodeUP DILParser::ParseInclusiveOrExpression() { DILASTNodeUP DILParser::ParseExclusiveOrExpression() { auto lhs = ParseAndExpression(); - while (m_dil_token.is(dil::TokenKind::caret)) { - DILToken token = m_dil_token; + while (m_dil_token.Is(Token::caret)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseAndExpression(); lhs = BuildBinaryOp(BinaryOpKind::Xor, std::move(lhs), std::move(rhs), - token.getLocation()); + token.GetLocation()); } return lhs; @@ -1162,12 +1150,12 @@ DILASTNodeUP DILParser::ParseExclusiveOrExpression() { DILASTNodeUP DILParser::ParseAndExpression() { auto lhs = ParseEqualityExpression(); - while (m_dil_token.is(dil::TokenKind::amp)) { - DILToken token = m_dil_token; + while (m_dil_token.Is(Token::amp)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseEqualityExpression(); lhs = BuildBinaryOp(BinaryOpKind::And, std::move(lhs), std::move(rhs), - token.getLocation()); + token.GetLocation()); } return lhs; @@ -1182,12 +1170,12 @@ DILASTNodeUP DILParser::ParseAndExpression() { DILASTNodeUP DILParser::ParseEqualityExpression() { auto lhs = ParseRelationalExpression(); - while (m_dil_token.isOneOf(dil::TokenKind::equalequal, dil::TokenKind::exclaimequal)) { - DILToken token = m_dil_token; + while (m_dil_token.IsOneOf(Token::equalequal, Token::exclaimequal)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseRelationalExpression(); - lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.getKind()), - std::move(lhs), std::move(rhs), token.getLocation()); + lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.GetKind()), + std::move(lhs), std::move(rhs), token.GetLocation()); } return lhs; @@ -1204,13 +1192,13 @@ DILASTNodeUP DILParser::ParseEqualityExpression() { DILASTNodeUP DILParser::ParseRelationalExpression() { auto lhs = ParseShiftExpression(); - while (m_dil_token.isOneOf(dil::TokenKind::less, dil::TokenKind::greater, - dil::TokenKind::lessequal, dil::TokenKind::greaterequal)) { - DILToken token = m_dil_token; + while (m_dil_token.IsOneOf(Token::less, Token::greater, + Token::lessequal, Token::greaterequal)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseShiftExpression(); - lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.getKind()), - std::move(lhs), std::move(rhs), token.getLocation()); + lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.GetKind()), + std::move(lhs), std::move(rhs), token.GetLocation()); } return lhs; @@ -1225,12 +1213,12 @@ DILASTNodeUP DILParser::ParseRelationalExpression() { DILASTNodeUP DILParser::ParseShiftExpression() { auto lhs = ParseAdditiveExpression(); - while (m_dil_token.isOneOf(dil::TokenKind::lessless, dil::TokenKind::greatergreater)) { - DILToken token = m_dil_token; + while (m_dil_token.IsOneOf(Token::lessless, Token::greatergreater)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseAdditiveExpression(); - lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.getKind()), - std::move(lhs), std::move(rhs), token.getLocation()); + lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.GetKind()), + std::move(lhs), std::move(rhs), token.GetLocation()); } return lhs; @@ -1245,12 +1233,12 @@ DILASTNodeUP DILParser::ParseShiftExpression() { DILASTNodeUP DILParser::ParseAdditiveExpression() { auto lhs = ParseMultiplicativeExpression(); - while (m_dil_token.isOneOf(dil::TokenKind::plus, dil::TokenKind::minus)) { - DILToken token = m_dil_token; + while (m_dil_token.IsOneOf(Token::plus, Token::minus)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseMultiplicativeExpression(); - lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.getKind()), - std::move(lhs), std::move(rhs), token.getLocation()); + lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.GetKind()), + std::move(lhs), std::move(rhs), token.GetLocation()); } return lhs; @@ -1266,13 +1254,13 @@ DILASTNodeUP DILParser::ParseAdditiveExpression() { DILASTNodeUP DILParser::ParseMultiplicativeExpression() { auto lhs = ParseCastExpression(); - while (m_dil_token.isOneOf(dil::TokenKind::star, dil::TokenKind::slash, - dil::TokenKind::percent)) { - DILToken token = m_dil_token; + while (m_dil_token.IsOneOf(Token::star, Token::slash, + Token::percent)) { + Token token = m_dil_token; ConsumeToken(); auto rhs = ParseCastExpression(); - lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.getKind()), - std::move(lhs), std::move(rhs), token.getLocation()); + lhs = BuildBinaryOp(dil_token_kind_to_binary_op_kind(token.GetKind()), + std::move(lhs), std::move(rhs), token.GetLocation()); } return lhs; @@ -1288,8 +1276,8 @@ DILASTNodeUP DILParser::ParseMultiplicativeExpression() { // DILASTNodeUP DILParser::ParseCastExpression() { // This can be a C-style cast, try parsing the contents as a type declaration. - if (m_dil_token.is(dil::TokenKind::l_paren)) { - DILToken token = m_dil_token; + if (m_dil_token.Is(Token::l_paren)) { + Token token = m_dil_token; // Enable lexer backtracking, so that we can rollback in case it's not // actually a type declaration. @@ -1312,12 +1300,12 @@ DILASTNodeUP DILParser::ParseCastExpression() { return std::make_unique(bad_type); } - Expect(dil::TokenKind::r_paren); + Expect(Token::r_paren); ConsumeToken(); auto rhs = ParseCastExpression(); return BuildCStyleCast(type_id.value(), std::move(rhs), - token.getLocation()); + token.GetLocation()); } // Failed to parse the contents of the parentheses as a type declaration. @@ -1349,31 +1337,31 @@ DILASTNodeUP DILParser::ParseCastExpression() { // "!" // DILASTNodeUP DILParser::ParseUnaryExpression() { - if (m_dil_token.isOneOf(dil::TokenKind::plusplus, dil::TokenKind::minusminus, - dil::TokenKind::star, dil::TokenKind::amp, dil::TokenKind::plus, - dil::TokenKind::minus, dil::TokenKind::exclaim, - dil::TokenKind::tilde)) { - DILToken token = m_dil_token; - uint32_t loc = token.getLocation(); + if (m_dil_token.IsOneOf(Token::plusplus, Token::minusminus, + Token::star, Token::amp, Token::plus, + Token::minus, Token::exclaim, + Token::tilde)) { + Token token = m_dil_token; + uint32_t loc = token.GetLocation(); ConsumeToken(); auto rhs = ParseCastExpression(); - switch (token.getKind()) { - case dil::TokenKind::plusplus: + switch (token.GetKind()) { + case Token::plusplus: return BuildUnaryOp(UnaryOpKind::PreInc, std::move(rhs), loc); - case dil::TokenKind::minusminus: + case Token::minusminus: return BuildUnaryOp(UnaryOpKind::PreDec, std::move(rhs), loc); - case dil::TokenKind::star: + case Token::star: return BuildUnaryOp(UnaryOpKind::Deref, std::move(rhs), loc); - case dil::TokenKind::amp: + case Token::amp: return BuildUnaryOp(UnaryOpKind::AddrOf, std::move(rhs), loc); - case dil::TokenKind::plus: + case Token::plus: return BuildUnaryOp(UnaryOpKind::Plus, std::move(rhs), loc); - case dil::TokenKind::minus: + case Token::minus: return BuildUnaryOp(UnaryOpKind::Minus, std::move(rhs), loc); - case dil::TokenKind::tilde: + case Token::tilde: return BuildUnaryOp(UnaryOpKind::Not, std::move(rhs), loc); - case dil::TokenKind::exclaim: + case Token::exclaim: return BuildUnaryOp(UnaryOpKind::LNot, std::move(rhs), loc); default: @@ -1381,8 +1369,8 @@ DILASTNodeUP DILParser::ParseUnaryExpression() { } } - if (m_dil_token.is(dil::TokenKind::kw_sizeof)) { - uint32_t sizeof_loc = m_dil_token.getLocation(); + if (m_dil_token.Is(Token::kw_sizeof)) { + uint32_t sizeof_loc = m_dil_token.GetLocation(); ConsumeToken(); // [expr.sizeof](http://eel.is/c++draft/expr.sizeof#1) @@ -1395,19 +1383,19 @@ DILASTNodeUP DILParser::ParseUnaryExpression() { CompilerType operand; // `(` can mean either a type_id or a parenthesized expression. - if (m_dil_token.is(dil::TokenKind::l_paren)) { + if (m_dil_token.Is(Token::l_paren)) { // Start tentative parsing (save token location/idx, for possible // rollback). uint32_t save_token_idx = m_dil_lexer.GetCurrentTokenIdx(); - Expect(dil::TokenKind::l_paren); + Expect(Token::l_paren); ConsumeToken(); // Parse the type definition and resolve the type. auto type_id = ParseTypeId(); if (type_id) { // type_id requires parentheses, so there must be a closing one. - Expect(dil::TokenKind::r_paren); + Expect(Token::r_paren); ConsumeToken(); operand = type_id.value(); @@ -1466,16 +1454,16 @@ DILASTNodeUP DILParser::ParsePostfixExpression() { CompilerType bad_type; // C++-style cast. - if (m_dil_token.isOneOf(dil::TokenKind::kw_static_cast, dil::TokenKind::kw_dynamic_cast, - dil::TokenKind::kw_reinterpret_cast)) { - dil::TokenKind cast_kind = m_dil_token.getKind(); - uint32_t cast_loc = m_dil_token.getLocation(); + if (m_dil_token.IsOneOf(Token::kw_static_cast, Token::kw_dynamic_cast, + Token::kw_reinterpret_cast)) { + Token::Kind cast_kind = m_dil_token.GetKind(); + uint32_t cast_loc = m_dil_token.GetLocation(); ConsumeToken(); - Expect(dil::TokenKind::less); + Expect(Token::less); ConsumeToken(); - uint32_t loc = m_dil_token.getLocation(); + uint32_t loc = m_dil_token.GetLocation(); // Parse the type definition and resolve the type. auto type_id = ParseTypeId(/*must_be_type_id*/ true); @@ -1488,13 +1476,13 @@ DILASTNodeUP DILParser::ParsePostfixExpression() { return std::make_unique(bad_type); } - Expect(dil::TokenKind::greater); + Expect(Token::greater); ConsumeToken(); - Expect(dil::TokenKind::l_paren); + Expect(Token::l_paren); ConsumeToken(); auto rhs = ParseExpression(); - Expect(dil::TokenKind::r_paren); + Expect(Token::r_paren); ConsumeToken(); lhs = BuildCxxCast(cast_kind, type_id.value(), std::move(rhs), cast_loc); @@ -1505,46 +1493,46 @@ DILASTNodeUP DILParser::ParsePostfixExpression() { } assert(lhs && "LHS of the postfix_expression can't be NULL."); - while (m_dil_token.isOneOf(dil::TokenKind::l_square, dil::TokenKind::period, - dil::TokenKind::arrow, dil::TokenKind::plusplus, - dil::TokenKind::minusminus)) { - DILToken token = m_dil_token; - switch (token.getKind()) { - case dil::TokenKind::period: - case dil::TokenKind::arrow: { + while (m_dil_token.IsOneOf(Token::l_square, Token::period, + Token::arrow, Token::plusplus, + Token::minusminus)) { + Token token = m_dil_token; + switch (token.GetKind()) { + case Token::period: + case Token::arrow: { ConsumeToken(); - DILToken member_token = m_dil_token; + Token member_token = m_dil_token; auto member_id = ParseIdExpression(); // Check if this is a function call. - if (m_dil_token.is(dil::TokenKind::l_paren)) { + if (m_dil_token.Is(Token::l_paren)) { // TODO: Check if `member_id` is actually a member function of `lhs`. // If not, produce a more accurate diagnostic. BailOut(ErrorCode::kNotImplemented, "member function calls are not supported", - m_dil_token.getLocation()); + m_dil_token.GetLocation()); } lhs = BuildMemberOf(std::move(lhs), std::move(member_id), - token.getKind() == dil::TokenKind::arrow, - member_token.getLocation()); + token.GetKind() == Token::arrow, + member_token.GetLocation()); break; } - case dil::TokenKind::plusplus: { + case Token::plusplus: { ConsumeToken(); return BuildUnaryOp(UnaryOpKind::PostInc, std::move(lhs), - token.getLocation()); + token.GetLocation()); } - case dil::TokenKind::minusminus: { + case Token::minusminus: { ConsumeToken(); return BuildUnaryOp(UnaryOpKind::PostDec, std::move(lhs), - token.getLocation()); + token.GetLocation()); } - case dil::TokenKind::l_square: { + case Token::l_square: { ConsumeToken(); auto rhs = ParseExpression(); - Expect(dil::TokenKind::r_square); + Expect(Token::r_square); ConsumeToken(); lhs = BuildBinarySubscript(std::move(lhs), std::move(rhs), - token.getLocation()); + token.GetLocation()); break; } @@ -1569,28 +1557,28 @@ DILASTNodeUP DILParser::ParsePostfixExpression() { // DILASTNodeUP DILParser::ParsePrimaryExpression() { CompilerType bad_type; - if (m_dil_token.is(dil::TokenKind::numeric_constant)) { + if (m_dil_token.Is(Token::numeric_constant)) { return ParseNumericLiteral(); - } else if (m_dil_token.isOneOf(dil::TokenKind::kw_true, dil::TokenKind::kw_false)) { + } else if (m_dil_token.IsOneOf(Token::kw_true, Token::kw_false)) { return ParseBooleanLiteral(); - } else if (m_dil_token.isOneOf(dil::TokenKind::char_constant, - dil::TokenKind::wide_char_constant, - dil::TokenKind::utf8_char_constant)) { + } else if (m_dil_token.IsOneOf(Token::char_constant, + Token::wide_char_constant, + Token::utf8_char_constant)) { return ParseCharLiteral(); - } else if (m_dil_lexer.isStringLiteral(m_dil_token.getKind())) { + } else if (m_dil_lexer.IsStringLiteral(m_dil_token.GetKind())) { // Note: Only expressions that consist of a single string literal can be // handled by DIL. BailOut(ErrorCode::kNotImplemented, "string literals are not supported", - m_dil_token.getLocation()); + m_dil_token.GetLocation()); return std::make_unique(bad_type); - } else if (m_dil_token.is(dil::TokenKind::kw_nullptr)) { + } else if (m_dil_token.Is(Token::kw_nullptr)) { return ParsePointerLiteral(); - } else if (m_dil_token.isOneOf(dil::TokenKind::coloncolon, dil::TokenKind::identifier)) { + } else if (m_dil_token.IsOneOf(Token::coloncolon, Token::identifier)) { // Save the source location for the diagnostics message. - uint32_t loc = m_dil_token.getLocation(); + uint32_t loc = m_dil_token.GetLocation(); auto identifier = ParseIdExpression(); // Check if this is a function call. - if (m_dil_token.is(dil::TokenKind::l_paren)) { + if (m_dil_token.Is(Token::l_paren)) { auto func_def = GetBuiltinFunctionDef(m_ctx_scope, identifier); if (!func_def) { BailOut( @@ -1615,9 +1603,9 @@ DILASTNodeUP DILParser::ParsePrimaryExpression() { return std::make_unique(loc, identifier, std::move(value), /*is_rvalue*/ false, IsContextVar(identifier)); - } else if (m_dil_token.is(dil::TokenKind::kw_this)) { + } else if (m_dil_token.Is(Token::kw_this)) { // Save the source location for the diagnostics message. - uint32_t loc = m_dil_token.getLocation(); + uint32_t loc = m_dil_token.GetLocation(); ConsumeToken(); auto value = LookupIdentifier("this", m_ctx_scope, m_use_dynamic); if (!value) { @@ -1630,28 +1618,29 @@ DILASTNodeUP DILParser::ParsePrimaryExpression() { return std::make_unique(loc, "this", std::move(value), /*is_rvalue*/ true, /*is_context_var*/ false); - } else if (m_dil_token.is(dil::TokenKind::l_paren)) { + } else if (m_dil_token.Is(Token::l_paren)) { // Check in case this is an anonynmous namespace - if (m_dil_lexer.LookAhead(0).is(dil::TokenKind::identifier) - && (((DILToken)m_dil_lexer.LookAhead(0)).getSpelling() == "anonymous") - && m_dil_lexer.LookAhead(1).is(dil::TokenKind::kw_namespace) - && m_dil_lexer.LookAhead(2).is(dil::TokenKind::r_paren) - && m_dil_lexer.LookAhead(3).is(dil::TokenKind::coloncolon)) { - m_dil_token = m_dil_lexer.AcceptLookAhead(3); + if (m_dil_lexer.LookAhead(1).Is(Token::identifier) + && (((Token)m_dil_lexer.LookAhead(1)).GetSpelling() == "anonymous") + && m_dil_lexer.LookAhead(2).Is(Token::kw_namespace) + && m_dil_lexer.LookAhead(3).Is(Token::r_paren) + && m_dil_lexer.LookAhead(4).Is(Token::coloncolon)) { + m_dil_lexer.Advance(4); + m_dil_token = m_dil_lexer.GetCurrentToken(); std::string identifier = "(anonymous namespace)"; - Expect(dil::TokenKind::coloncolon); + Expect(Token::coloncolon); // Save the source location for the diagnostics message. - uint32_t loc = m_dil_token.getLocation(); + uint32_t loc = m_dil_token.GetLocation(); ConsumeToken(); - assert ((m_dil_token.is(dil::TokenKind::identifier) || - m_dil_token.is(dil::TokenKind::l_paren)) && + assert ((m_dil_token.Is(Token::identifier) || + m_dil_token.Is(Token::l_paren)) && "Expected an identifier or anonymous namespeace, but not found."); std::string identifier2 = ParseNestedNameSpecifier(); if (identifier2.empty()) { // There was only an identifer, no more levels of nesting. Or there // was an invalid expression starting with a left parenthesis. - Expect(dil::TokenKind::identifier); - identifier2 = m_dil_token.getSpelling(); + Expect(Token::identifier); + identifier2 = m_dil_token.GetSpelling(); ConsumeToken(); } identifier = identifier + "::" + identifier2; @@ -1668,7 +1657,7 @@ DILASTNodeUP DILParser::ParsePrimaryExpression() { } else { ConsumeToken(); auto expr = ParseExpression(); - Expect(dil::TokenKind::r_paren); + Expect(Token::r_paren); ConsumeToken(); return expr; } @@ -1676,7 +1665,7 @@ DILASTNodeUP DILParser::ParsePrimaryExpression() { BailOut(ErrorCode::kInvalidExpressionSyntax, llvm::formatv("Unexpected token: {0}", TokenDescription(m_dil_token)), - m_dil_token.getLocation()); + m_dil_token.GetLocation()); return std::make_unique(bad_type); } @@ -1686,7 +1675,7 @@ DILASTNodeUP DILParser::ParsePrimaryExpression() { // type_specifier_seq [abstract_declarator] // std::optional DILParser::ParseTypeId(bool must_be_type_id) { - uint32_t type_loc = m_dil_token.getLocation(); + uint32_t type_loc = m_dil_token.GetLocation(); TypeDeclaration type_decl; CompilerType bad_type; @@ -1812,7 +1801,7 @@ bool DILParser::ParseTypeSpecifier(TypeDeclaration* type_decl) { if (type_decl->m_is_user_type) { BailOut(ErrorCode::kInvalidOperandType, "cannot combine with previous declaration specifier", - m_dil_token.getLocation()); + m_dil_token.GetLocation()); type_decl->m_has_error = true; return false; } @@ -1834,12 +1823,12 @@ bool DILParser::ParseTypeSpecifier(TypeDeclaration* type_decl) { { // Try parsing optional global scope operator. bool global_scope = false; - if (m_dil_token.is(dil::TokenKind::coloncolon)) { + if (m_dil_token.Is(Token::coloncolon)) { global_scope = true; ConsumeToken(); } - uint32_t loc = m_dil_token.getLocation(); + uint32_t loc = m_dil_token.GetLocation(); // Try parsing optional nested_name_specifier. auto nested_name_specifier = ParseNestedNameSpecifier(); @@ -1890,8 +1879,8 @@ bool DILParser::ParseTypeSpecifier(TypeDeclaration* type_decl) { std::string DILParser::ParseNestedNameSpecifier() { // The first token in nested_name_specifier is always an identifier, or // '(anonymous namespace)'. - if (m_dil_token.isNot(dil::TokenKind::identifier) && - m_dil_token.isNot(dil::TokenKind::l_paren)) { + if (m_dil_token.IsNot(Token::identifier) && + m_dil_token.IsNot(Token::l_paren)) { return ""; } @@ -1899,24 +1888,25 @@ std::string DILParser::ParseNestedNameSpecifier() { // the the string '(anonymous namespace)', which has a space in it (throwing // off normal parsing) and is not actually proper C++> Check to see if we're // looking at '(anonymous namespace)::...' - if (m_dil_token.is(dil::TokenKind::l_paren)) { + if (m_dil_token.Is(Token::l_paren)) { // Look for all the pieces, in order: // l_paren 'anonymous' 'namespace' r_paren coloncolon - if (m_dil_lexer.LookAhead(0).is(dil::TokenKind::identifier) - && (((DILToken)m_dil_lexer.LookAhead(0)).getSpelling() == "anonymous") - && m_dil_lexer.LookAhead(1).is(dil::TokenKind::kw_namespace) - && m_dil_lexer.LookAhead(2).is(dil::TokenKind::r_paren) - && m_dil_lexer.LookAhead(3).is(dil::TokenKind::coloncolon)) { - m_dil_token = m_dil_lexer.AcceptLookAhead(3); - - assert ((m_dil_token.is(dil::TokenKind::identifier) - || m_dil_token.is(dil::TokenKind::l_paren)) && + if (m_dil_lexer.LookAhead(1).Is(Token::identifier) + && (((Token)m_dil_lexer.LookAhead(1)).GetSpelling() == "anonymous") + && m_dil_lexer.LookAhead(2).Is(Token::kw_namespace) + && m_dil_lexer.LookAhead(3).Is(Token::r_paren) + && m_dil_lexer.LookAhead(4).Is(Token::coloncolon)) { + m_dil_lexer.Advance(4); + m_dil_token = m_dil_lexer.GetCurrentToken(); + + assert ((m_dil_token.Is(Token::identifier) + || m_dil_token.Is(Token::l_paren)) && "Expected an identifier or anonymous namespace, but not found."); // Continue parsing the nested_namespace_specifier. std::string identifier2 = ParseNestedNameSpecifier(); if (identifier2.empty()) { - Expect(dil::TokenKind::identifier); - identifier2 = m_dil_token.getSpelling(); + Expect(Token::identifier); + identifier2 = m_dil_token.GetSpelling(); ConsumeToken(); } return "(anonymous namespace)::" + identifier2; @@ -1927,11 +1917,12 @@ std::string DILParser::ParseNestedNameSpecifier() { // If the next token is scope ("::"), then this is indeed a // nested_name_specifier - if (m_dil_lexer.LookAhead(0).is(dil::TokenKind::coloncolon)) { + if (m_dil_lexer.LookAhead(1).Is(Token::coloncolon)) { // This nested_name_specifier is a single identifier. - std::string identifier = m_dil_token.getSpelling(); - m_dil_token = m_dil_lexer.AcceptLookAhead(0); - Expect(dil::TokenKind::coloncolon); + std::string identifier = m_dil_token.GetSpelling(); + m_dil_lexer.Advance(1); + m_dil_token = m_dil_lexer.GetCurrentToken(); + Expect(Token::coloncolon); ConsumeToken(); // Continue parsing the nested_name_specifier. return identifier + "::" + ParseNestedNameSpecifier(); @@ -1939,7 +1930,7 @@ std::string DILParser::ParseNestedNameSpecifier() { // If the next token starts a template argument list, then we have a // simple_template_id here. - if (m_dil_lexer.LookAhead(0).is(dil::TokenKind::less)) { + if (m_dil_lexer.LookAhead(1).Is(Token::less)) { // We don't know whether this will be a nested_name_identifier or just a // type_name. Prepare to rollback if this is not a nested_name_identifier. @@ -1952,8 +1943,8 @@ std::string DILParser::ParseNestedNameSpecifier() { // If we did parse the type_name successfully and it's followed by the scope // operator ("::"), then this is indeed a nested_name_specifier. Continue // parsing nested_name_specifier. - if (!type_name.empty() && m_dil_token.is(dil::TokenKind::coloncolon)) { - m_dil_lexer.IncrementTokenIdx(); + if (!type_name.empty() && m_dil_token.Is(Token::coloncolon)) { + m_dil_lexer.Advance(); m_dil_token = m_dil_lexer.GetCurrentToken(); // Continue parsing the nested_name_specifier. return type_name + "::" + ParseNestedNameSpecifier(); @@ -1990,21 +1981,22 @@ std::string DILParser::ParseNestedNameSpecifier() { // std::string DILParser::ParseTypeName() { // Typename always starts with an identifier. - if (m_dil_token.isNot(dil::TokenKind::identifier)) { + if (m_dil_token.IsNot(Token::identifier)) { return ""; } // If the next token starts a template argument list, parse this type_name as // a simple_template_id. - if (m_dil_lexer.LookAhead(0).is(dil::TokenKind::less)) { + if (m_dil_lexer.LookAhead(1).Is(Token::less)) { // Parse the template_name. In this case it's just an identifier. - std::string template_name = m_dil_token.getSpelling(); - m_dil_token = m_dil_lexer.AcceptLookAhead(0); + std::string template_name = m_dil_token.GetSpelling(); + m_dil_lexer.Advance(1); + m_dil_token = m_dil_lexer.GetCurrentToken(); // Consume the "<" token. ConsumeToken(); // Short-circuit for missing template_argument_list. - if (m_dil_token.is(dil::TokenKind::greater)) { + if (m_dil_token.Is(Token::greater)) { ConsumeToken(); return llvm::formatv("{0}<>", template_name); } @@ -2012,17 +2004,19 @@ std::string DILParser::ParseTypeName() { // Try parsing template_argument_list. auto template_argument_list = ParseTemplateArgumentList(); - if (m_dil_token.is(dil::TokenKind::greater)) { + if (m_dil_token.Is(Token::greater)) { // Single closing angle bracket is a valid end of the template argument // list, just consume it. ConsumeToken(); - } else if (m_dil_token.is(dil::TokenKind::greatergreater)) { + } else if (m_dil_token.Is(Token::greatergreater)) { // C++11 allows using ">>" in nested template argument lists and C++-style // casts. In this case we alter change the token type to ">", but don't // consume it -- it will be done on the outer level when completing the // outer template argument list or C++-style cast. - m_dil_token.setKind(dil::TokenKind::greater); + uint32_t loc = m_dil_token.GetLocation(); + m_dil_token = Token(Token::greater, ">", loc); + m_dil_lexer.InsertToken(Token(Token::greater, ">", loc+1)); } else { // Not a valid end of the template argument list, failed to parse a @@ -2034,7 +2028,7 @@ std::string DILParser::ParseTypeName() { } // Otherwise look for a class_name, enum_name or a typedef_name. - std::string identifier = m_dil_token.getSpelling(); + std::string identifier = m_dil_token.GetSpelling(); ConsumeToken(); return identifier; @@ -2065,7 +2059,7 @@ std::string DILParser::ParseTemplateArgumentList() { arguments.push_back(argument); - } while (m_dil_token.is(dil::TokenKind::comma)); + } while (m_dil_token.Is(Token::comma)); // Internally in LLDB/Clang nested template type names have extra spaces to // avoid having ">>". Add the extra space before the closing ">" if the @@ -2120,10 +2114,10 @@ std::string DILParser::ParseTemplateArgument() { uint32_t save_token_idx = m_dil_lexer.GetCurrentTokenIdx(); // Parse a numeric_literal. - if (m_dil_token.is(dil::TokenKind::numeric_constant)) { + if (m_dil_token.Is(Token::numeric_constant)) { // TODO: Actually parse the literal, check if it's valid and // canonize it (e.g. 8LL -> 8). - std::string numeric_literal = m_dil_token.getSpelling(); + std::string numeric_literal = m_dil_token.GetSpelling(); ConsumeToken(); if (TokenEndsTemplateArgumentList(m_dil_token)) { @@ -2169,11 +2163,11 @@ std::string DILParser::ParseTemplateArgument() { // "&" // DILParser::PtrOperator DILParser::ParsePtrOperator() { - ExpectOneOf(dil::TokenKind::star, dil::TokenKind::amp); + ExpectOneOf(Token::star, Token::amp); PtrOperator ptr_operator; - if (m_dil_token.is(dil::TokenKind::star)) { - ptr_operator = std::make_tuple(dil::TokenKind::star, m_dil_token.getLocation()); + if (m_dil_token.Is(Token::star)) { + ptr_operator = std::make_tuple(Token::star, m_dil_token.GetLocation()); ConsumeToken(); // @@ -2189,8 +2183,8 @@ DILParser::PtrOperator DILParser::ParsePtrOperator() { ConsumeToken(); } - } else if (m_dil_token.is(dil::TokenKind::amp)) { - ptr_operator = std::make_tuple(dil::TokenKind::amp, m_dil_token.getLocation()); + } else if (m_dil_token.Is(Token::amp)) { + ptr_operator = std::make_tuple(Token::amp, m_dil_token.GetLocation()); ConsumeToken(); } @@ -2208,12 +2202,12 @@ DILParser::PtrOperator DILParser::ParsePtrOperator() { // ["::"] identifier // // identifier: -// ? dil::TokenKind::identifier ? +// ? Token::identifier ? // std::string DILParser::ParseIdExpression() { // Try parsing optional global scope operator. bool global_scope = false; - if (m_dil_token.is(dil::TokenKind::coloncolon)) { + if (m_dil_token.Is(Token::coloncolon)) { global_scope = true; ConsumeToken(); } @@ -2234,8 +2228,8 @@ std::string DILParser::ParseIdExpression() { // No nested_name_specifier, but with global scope -- this is also a // qualified_id production. Follow the second production rule. else if (global_scope) { - Expect(dil::TokenKind::identifier); - std::string identifier = m_dil_token.getSpelling(); + Expect(Token::identifier); + std::string identifier = m_dil_token.GetSpelling(); ConsumeToken(); return llvm::formatv("{0}{1}", global_scope ? "::" : "", identifier); } @@ -2250,11 +2244,11 @@ std::string DILParser::ParseIdExpression() { // identifier // // identifier: -// ? dil::TokenKind::identifier ? +// ? Token::identifier ? // std::string DILParser::ParseUnqualifiedId() { - Expect(dil::TokenKind::identifier); - std::string identifier = m_dil_token.getSpelling(); + Expect(Token::identifier); + std::string identifier = m_dil_token.GetSpelling(); ConsumeToken(); return identifier; } @@ -2262,10 +2256,10 @@ std::string DILParser::ParseUnqualifiedId() { // Parse a numeric_literal. // // numeric_literal: -// ? dil::TokenKind::numeric_constant ? +// ? Token::numeric_constant ? // DILASTNodeUP DILParser::ParseNumericLiteral() { - Expect(dil::TokenKind::numeric_constant); + Expect(Token::numeric_constant); DILASTNodeUP numeric_constant = ParseNumericConstant(); ConsumeToken(); return numeric_constant; @@ -2278,9 +2272,9 @@ DILASTNodeUP DILParser::ParseNumericLiteral() { // "false" // DILASTNodeUP DILParser::ParseBooleanLiteral() { - ExpectOneOf(dil::TokenKind::kw_true, dil::TokenKind::kw_false); - uint32_t loc = m_dil_token.getLocation(); - bool literal_value = m_dil_token.is(dil::TokenKind::kw_true); + ExpectOneOf(Token::kw_true, Token::kw_false); + uint32_t loc = m_dil_token.GetLocation(); + bool literal_value = m_dil_token.Is(Token::kw_true); ConsumeToken(); Scalar scalar_value(static_cast(literal_value)); return std::make_unique( @@ -2288,24 +2282,24 @@ DILASTNodeUP DILParser::ParseBooleanLiteral() { } DILASTNodeUP DILParser::ParseCharLiteral() { - ExpectOneOf(dil::TokenKind::char_constant, - dil::TokenKind::wide_char_constant, - dil::TokenKind::utf8_char_constant); - uint32_t loc = m_dil_token.getLocation(); + ExpectOneOf(Token::char_constant, + Token::wide_char_constant, + Token::utf8_char_constant); + uint32_t loc = m_dil_token.GetLocation(); - std::string token_spelling = m_dil_token.getSpelling(); + std::string token_spelling = m_dil_token.GetSpelling(); const char* token_begin = token_spelling.c_str(); dil::CharLiteralParser char_literal(token_begin, token_begin + token_spelling.size(), - loc, m_dil_lexer, m_dil_token.getKind()); + loc, m_dil_lexer, m_dil_token.GetKind()); if (char_literal.hadError()) { // TODO: Add new ErrorCode kInvalidCharLiteral and use it BailOut(ErrorCode::kInvalidNumericLiteral, llvm::formatv("Failed to parse token as char-constant: {0}", TokenDescription(m_dil_token)), - m_dil_token.getLocation()); + m_dil_token.GetLocation()); CompilerType bad_type; return std::make_unique(bad_type); } @@ -2328,8 +2322,8 @@ DILASTNodeUP DILParser::ParseCharLiteral() { // "nullptr" // DILASTNodeUP DILParser::ParsePointerLiteral() { - Expect(dil::TokenKind::kw_nullptr); - uint32_t loc = m_dil_token.getLocation(); + Expect(Token::kw_nullptr); + uint32_t loc = m_dil_token.GetLocation(); ConsumeToken(); llvm::APInt raw_value(type_width(), 0); Scalar scalar_value(raw_value); @@ -2340,12 +2334,12 @@ DILASTNodeUP DILParser::ParsePointerLiteral() { DILASTNodeUP DILParser::ParseNumericConstant() { CompilerType bad_type; // Parse numeric constant, it can be either integer or float. - std::string tok_spelling = m_dil_token.getSpelling(); + std::string tok_spelling = m_dil_token.GetSpelling(); llvm::StringRef tok_spelling_ref(tok_spelling); lldb::TargetSP target_sp = m_ctx_scope->CalculateTarget(); dil::NumericLiteralParser literal( - tok_spelling_ref, m_dil_token.getLocation(), /*AllowHalfType=*/true, + tok_spelling_ref, m_dil_token.GetLocation(), /*AllowHalfType=*/true, m_dil_lexer, /*AllowMicrosoftExt=*/true); @@ -2354,7 +2348,7 @@ DILASTNodeUP DILParser::ParseNumericConstant() { ErrorCode::kInvalidNumericLiteral, "Failed to parse token as numeric-constant: " + TokenDescription(m_dil_token), - m_dil_token.getLocation()); + m_dil_token.GetLocation()); return std::make_unique(bad_type); } @@ -2371,13 +2365,13 @@ DILASTNodeUP DILParser::ParseNumericConstant() { BailOut(ErrorCode::kInvalidNumericLiteral, "numeric-constant should be either float or integer literal: " + TokenDescription(m_dil_token), - m_dil_token.getLocation()); + m_dil_token.GetLocation()); return std::make_unique(bad_type); } DILASTNodeUP DILParser::ParseFloatingLiteral( dil::NumericLiteralParser& literal, - DILToken& token) { + Token& token) { const llvm::fltSemantics& format = literal.isFloat ? llvm::APFloat::IEEEsingle() : llvm::APFloat::IEEEdouble(); @@ -2392,7 +2386,7 @@ DILASTNodeUP DILParser::ParseFloatingLiteral( BailOut(ErrorCode::kInvalidNumericLiteral, llvm::formatv("float underflow/overflow happened: {0}", TokenDescription(token)), - token.getLocation()); + token.GetLocation()); CompilerType bad_type; return std::make_unique(bad_type); } @@ -2401,11 +2395,11 @@ DILASTNodeUP DILParser::ParseFloatingLiteral( literal.isFloat ? lldb::eBasicTypeFloat : lldb::eBasicTypeDouble; Scalar scalar_value(raw_value); return std::make_unique( - token.getLocation(), GetBasicType(m_ctx_scope, basic_type), scalar_value); + token.GetLocation(), GetBasicType(m_ctx_scope, basic_type), scalar_value); } DILASTNodeUP DILParser::ParseIntegerLiteral(dil::NumericLiteralParser& literal, - DILToken& token) { + Token& token) { // Create a value big enough to fit all valid numbers. llvm::APInt raw_value(type_width(), 0); @@ -2414,7 +2408,7 @@ DILASTNodeUP DILParser::ParseIntegerLiteral(dil::NumericLiteralParser& literal, llvm::formatv("integer literal is too large to be represented in " "any integer type: {0}", TokenDescription(token)), - token.getLocation()); + token.GetLocation()); CompilerType bad_type; return std::make_unique(bad_type); } @@ -2422,7 +2416,7 @@ DILASTNodeUP DILParser::ParseIntegerLiteral(dil::NumericLiteralParser& literal, auto [type, is_unsigned] = PickIntegerType(m_ctx_scope, literal, raw_value); Scalar scalar_value(raw_value); - return std::make_unique(token.getLocation(), + return std::make_unique(token.GetLocation(), GetBasicType(m_ctx_scope, type), scalar_value); } @@ -2444,13 +2438,13 @@ DILASTNodeUP DILParser::ParseIntegerLiteral(dil::NumericLiteralParser& literal, // DILASTNodeUP DILParser::ParseBuiltinFunction( uint32_t loc, std::unique_ptr func_def) { - Expect(dil::TokenKind::l_paren); + Expect(Token::l_paren); ConsumeToken(); std::vector arguments; CompilerType bad_type; - if (m_dil_token.is(dil::TokenKind::r_paren)) { + if (m_dil_token.Is(Token::r_paren)) { // Empty argument list, nothing to do here. ConsumeToken(); } else { @@ -2470,9 +2464,9 @@ DILASTNodeUP DILParser::ParseBuiltinFunction( arguments.push_back(std::move(argument)); - } while (m_dil_token.is(dil::TokenKind::comma)); + } while (m_dil_token.Is(Token::comma)); - Expect(dil::TokenKind::r_paren); + Expect(Token::r_paren); ConsumeToken(); } @@ -2621,22 +2615,22 @@ DILASTNodeUP DILParser::BuildCStyleCast(CompilerType type, DILASTNodeUP rhs, return std::make_unique(location, type, std::move(rhs), promo_kind); } -DILASTNodeUP DILParser::BuildCxxCast(dil::TokenKind kind, CompilerType type, +DILASTNodeUP DILParser::BuildCxxCast(Token::Kind kind, CompilerType type, DILASTNodeUP rhs, uint32_t location) { - assert((kind == dil::TokenKind::kw_static_cast || - kind == dil::TokenKind::kw_dynamic_cast || - kind == dil::TokenKind::kw_reinterpret_cast) && + assert((kind == Token::kw_static_cast || + kind == Token::kw_dynamic_cast || + kind == Token::kw_reinterpret_cast) && "invalid C++-style cast type"); // TODO: Implement custom builders for all C++-style casts. - if (kind == dil::TokenKind::kw_dynamic_cast) { + if (kind == Token::kw_dynamic_cast) { return BuildCxxDynamicCast(type, std::move(rhs), location); } - if (kind == dil::TokenKind::kw_reinterpret_cast) { + if (kind == Token::kw_reinterpret_cast) { return BuildCxxReinterpretCast(type, std::move(rhs), location); } - if (kind == dil::TokenKind::kw_static_cast) { + if (kind == Token::kw_static_cast) { return BuildCxxStaticCast(type, std::move(rhs), location); } return BuildCStyleCast(type, std::move(rhs), location); @@ -3602,26 +3596,26 @@ DILASTNodeUP DILParser::BuildMemberOf(DILASTNodeUP lhs, std::string member_id, member.val_obj_sp); } -void DILParser::Expect(dil::TokenKind kind) { - if (m_dil_token.isNot(kind)) { +void DILParser::Expect(Token::Kind kind) { + if (m_dil_token.IsNot(kind)) { BailOut(ErrorCode::kUnknown, llvm::formatv("expected {0}, got: {1}", TokenKindsJoin(kind), TokenDescription(m_dil_token)), - m_dil_token.getLocation()); + m_dil_token.GetLocation()); } } template -void DILParser::ExpectOneOf(dil::TokenKind k, Ts... ks) { - static_assert((std::is_same_v && ...), + void DILParser::ExpectOneOf(Token::Kind k, Ts... ks) { + static_assert((std::is_same_v && ...), "ExpectOneOf can be only called with values of type " - "dil::TokenKind"); + "Kind"); - if (!m_dil_token.isOneOf(k, ks...)) { + if (!m_dil_token.IsOneOf(k, ks...)) { BailOut(ErrorCode::kUnknown, llvm::formatv("expected any of ({0}), got: {1}", TokenKindsJoin(k, ks...), TokenDescription(m_dil_token)), - m_dil_token.getLocation()); + m_dil_token.GetLocation()); } } @@ -4039,8 +4033,8 @@ void DILParser::BailOut(ErrorCode code, const std::string& error, } m_error = Status((uint32_t) code, lldb::eErrorTypeGeneric, - FormatDiagnostics(*m_sm, error, loc)); - m_dil_token.setKind(dil::TokenKind::eof); + FormatDiagnostics(m_input_expr, error, loc)); + m_dil_token = Token(Token::eof, "", 0); } void DILParser::BailOut(Status error) { @@ -4050,29 +4044,23 @@ void DILParser::BailOut(Status error) { return; } m_error = std::move(error); - m_dil_token.setKind(dil::TokenKind::eof); + m_dil_token = Token(Token::eof, "", 0); } void DILParser::ConsumeToken() { - if (m_dil_token.is(dil::TokenKind::eof)) { + if (m_dil_token.Is(Token::eof)) { // Don't do anything if we're already at eof. This can happen if an error // occurred during parsing and we're trying to bail out. return; } - bool all_ok; - m_dil_lexer.Lex(m_dil_token); - if (m_dil_lexer.GetCurrentTokenIdx() == UINT_MAX) - all_ok = m_dil_lexer.ResetTokenIdx(0); - else - all_ok = m_dil_lexer.IncrementTokenIdx(); - if (!all_ok) - BailOut(ErrorCode::kUnknown, "Invalid lexer token index", 0); + m_dil_lexer.Advance(); + m_dil_token = m_dil_lexer.GetCurrentToken(); } -std::string DILParser::TokenDescription(const DILToken& token) { - const auto& spelling = ((DILToken)token).getSpelling(); - const std::string kind_name = DILToken::getTokenName(((DILToken)token).getKind()); - return llvm::formatv("<'{0}' ({1})>", spelling, kind_name); +std::string DILParser::TokenDescription(const Token& token) { + const auto& spelling = ((Token)token).GetSpelling(); + llvm::StringRef kind_name = Token::GetTokenName(((Token)token).GetKind());; + return llvm::formatv("<'{0}' ({1})>", spelling, kind_name.str()); } bool DILParser::ImplicitConversionIsAllowed(CompilerType src, CompilerType dst, @@ -4185,6 +4173,4 @@ lldb::BasicType TypeDeclaration::GetBasicType() const { return lldb::eBasicTypeInvalid; } -} // namespace dil - -} // namespace lldb_private +} // namespace lldb_private::dil diff --git a/lldb/unittests/DIL/CMakeLists.txt b/lldb/unittests/DIL/CMakeLists.txt index 454aa5208fb4..cd9daf154702 100644 --- a/lldb/unittests/DIL/CMakeLists.txt +++ b/lldb/unittests/DIL/CMakeLists.txt @@ -1,10 +1,12 @@ add_lldb_unittest(DILTests DILTests.cpp + DILLexerTests.cpp Runner.cpp LINK_LIBS liblldb lldbUtilityHelpers + lldbValueObject LLVMTestingSupport ) add_subdirectory(Inputs) diff --git a/lldb/unittests/DIL/DILLexerTests.cpp b/lldb/unittests/DIL/DILLexerTests.cpp new file mode 100644 index 000000000000..026a092aa9e8 --- /dev/null +++ b/lldb/unittests/DIL/DILLexerTests.cpp @@ -0,0 +1,149 @@ +//===-- DILLexerTests.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/ValueObject/DILLexer.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest.h" +#include + +using llvm::StringRef; + +using namespace lldb_private::dil; + +llvm::Expected>> +ExtractTokenData(llvm::StringRef input_expr) { + + llvm::Expected maybe_lexer = DILLexer::Create(input_expr); + if (!maybe_lexer) + return maybe_lexer.takeError(); + DILLexer lexer(*maybe_lexer); + + if (lexer.NumLexedTokens() == 0) + return llvm::createStringError("No lexed tokens"); + + lexer.ResetTokenIdx(0); + std::vector> data; + do { + Token tok = lexer.GetCurrentToken(); + data.push_back(std::make_pair(tok.GetKind(), tok.GetSpelling())); + lexer.Advance(); + } while (data.back().first != Token::eof); + // Don't return the eof token. + data.pop_back(); + return data; +} + +TEST(DILLexerTests, SimpleTest) { + StringRef input_expr("simple_var"); + llvm::Expected maybe_lexer = DILLexer::Create(input_expr); + ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded()); + DILLexer lexer(*maybe_lexer); + Token token = lexer.GetCurrentToken(); + + EXPECT_EQ(token.GetKind(), Token::identifier); + EXPECT_EQ(token.GetSpelling(), "simple_var"); + lexer.Advance(); + token = lexer.GetCurrentToken(); + EXPECT_EQ(token.GetKind(), Token::eof); +} + +TEST(DILLexerTests, TokenKindTest) { + Token token = Token(Token::identifier, "ident", 0); + + EXPECT_TRUE(token.Is(Token::identifier)); + EXPECT_FALSE(token.Is(Token::l_paren)); + EXPECT_TRUE(token.IsOneOf(Token::eof, Token::identifier)); + EXPECT_FALSE(token.IsOneOf(Token::l_paren, Token::r_paren, Token::coloncolon, + Token::eof)); +} + +TEST(DILLexerTests, LookAheadTest) { + StringRef input_expr("(anonymous kw_namespace)::some_var"); + llvm::Expected maybe_lexer = DILLexer::Create(input_expr); + ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded()); + DILLexer lexer(*maybe_lexer); + Token token = lexer.GetCurrentToken(); + + // Current token is '('; check the next 4 tokens, to make + // sure they are the identifier 'anonymous', the identifier 'kw_namespace' + // ')' and '::', in that order. + EXPECT_EQ(token.GetKind(), Token::l_paren); + EXPECT_EQ(lexer.LookAhead(1).GetKind(), Token::identifier); + EXPECT_EQ(lexer.LookAhead(1).GetSpelling(), "anonymous"); + EXPECT_EQ(lexer.LookAhead(2).GetKind(), Token::identifier); + EXPECT_EQ(lexer.LookAhead(2).GetSpelling(), "kw_namespace"); + EXPECT_EQ(lexer.LookAhead(3).GetKind(), Token::r_paren); + EXPECT_EQ(lexer.LookAhead(4).GetKind(), Token::coloncolon); + + // Our current index should still be 0, as we only looked ahead; we are still + // officially on the '('. + EXPECT_EQ(lexer.GetCurrentTokenIdx(), 0u); + + // Accept the 'lookahead', so our current token is '::', which has the index + // 4 in our vector of tokens (which starts at zero). + lexer.Advance(4); + token = lexer.GetCurrentToken(); + EXPECT_EQ(token.GetKind(), Token::coloncolon); + EXPECT_EQ(lexer.GetCurrentTokenIdx(), 4u); + + lexer.Advance(); + token = lexer.GetCurrentToken(); + EXPECT_EQ(token.GetKind(), Token::identifier); + EXPECT_EQ(token.GetSpelling(), "some_var"); + EXPECT_EQ(lexer.GetCurrentTokenIdx(), 5u); + EXPECT_EQ(token.GetLocation(), strlen("(anonymous kw_namespace)::")); + + lexer.Advance(); + token = lexer.GetCurrentToken(); + EXPECT_EQ(token.GetKind(), Token::eof); +} + +TEST(DILLexerTests, MultiTokenLexTest) { + EXPECT_THAT_EXPECTED( + ExtractTokenData("This string has (several ) ::identifiers"), + llvm::HasValue(testing::ElementsAre( + testing::Pair(Token::identifier, "This"), + testing::Pair(Token::identifier, "string"), + testing::Pair(Token::identifier, "has"), + testing::Pair(Token::l_paren, "("), + testing::Pair(Token::identifier, "several"), + testing::Pair(Token::r_paren, ")"), + testing::Pair(Token::coloncolon, "::"), + testing::Pair(Token::identifier, "identifiers")))); +} + +TEST(DILLexerTests, IdentifiersTest) { + // These strings should lex into identifier tokens. + std::vector valid_identifiers = { + "$My_name1", "$pc", "abcd", "_", "_a", "_a_", "$", + "a_b", "kw_this", "self", "a", "MyName", "kw_namespace"}; + + // The lexer can lex these strings, but they should not be identifiers. + std::vector invalid_identifiers = {"", "::", "(", ")", "234", "2"}; + + // Verify that all of the valid identifiers come out as identifier tokens. + for (auto &str : valid_identifiers) { + SCOPED_TRACE(str); + EXPECT_THAT_EXPECTED(ExtractTokenData(str), + llvm::HasValue(testing::ElementsAre( + testing::Pair(Token::identifier, str)))); + } + + // Verify that none of the invalid identifiers come out as identifier tokens. + for (auto &str : invalid_identifiers) { + SCOPED_TRACE(str); + llvm::Expected maybe_lexer = DILLexer::Create(str); + EXPECT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded()); + DILLexer lexer(*maybe_lexer); + Token token = lexer.GetCurrentToken(); + EXPECT_TRUE(token.IsNot(Token::identifier)); + EXPECT_TRUE(token.IsOneOf(Token::eof, Token::coloncolon, Token::l_paren, + Token::r_paren, Token::numeric_constant)); + } +} diff --git a/lldb/unittests/DIL/DILTests.cpp b/lldb/unittests/DIL/DILTests.cpp index 4fa2440fc234..8a3dda6494ed 100644 --- a/lldb/unittests/DIL/DILTests.cpp +++ b/lldb/unittests/DIL/DILTests.cpp @@ -352,7 +352,6 @@ class IsEqualMatcher : public MatcherInterface { } } } - return true; } @@ -1003,7 +1002,7 @@ TEST_F(EvalTest, TestMemberOf) { EXPECT_THAT( Eval("sp->4"), IsError( - ":1:5: expected 'identifier', got: <'4' (numeric_constant)>\n" + ": expected 'identifier', got: <'4' (numeric_constant)>\n" "sp->4\n" " ^")); EXPECT_THAT(Eval("sp->foo"), IsError("no member named 'foo' in 'Sx'")); @@ -1274,7 +1273,7 @@ TEST_F(EvalTest, TestCStyleCastBuiltins) { EXPECT_THAT( Eval("(long 1)1"), - IsError(":1:7: expected 'r_paren', got: <'1' (numeric_constant)>\n" + IsError(": expected 'r_paren', got: <'1' (numeric_constant)>\n" "(long 1)1\n" " ^")); } @@ -2070,27 +2069,21 @@ TEST_F(EvalTest, TestTemplateTypes) { #endif EXPECT_THAT( Eval("ns::T_1 >::cx"), - XFail(IsError( - "use of undeclared identifier 'ns::T_1 >::cx'"))); + IsError("use of undeclared identifier 'ns::T_1 >::cx'")); EXPECT_THAT(Eval("T_1::cx"), XFail(IsEqual("24"))); EXPECT_THAT(Eval("T_1::cx"), XFail(IsEqual("42"))); - EXPECT_THAT(Eval("ns::T_1::cx"), XFail(IsEqual("64"))); + EXPECT_THAT(Eval("ns::T_1::cx"), IsEqual("64")); for (std::string arg : {"int", "int*", "int**", "int&", "int*&"}) { - EXPECT_THAT(Eval("(T_1<" + arg + ">::myint)1.2"), XFail(IsEqual("1.2"))); - EXPECT_THAT(Eval("(::T_1<" + arg + ">::myint)1.2"), XFail(IsEqual("1.2"))); - EXPECT_THAT(Eval("(T_1 >::myint)1.2"), - XFail(IsEqual("1.2"))); - EXPECT_THAT(Eval("(::T_1 >::myint)1.2"), - XFail(IsEqual("1.2"))); - - EXPECT_THAT(Eval("(ns::T_1<" + arg + ">::myint)1.1"), XFail(IsEqual("1"))); - EXPECT_THAT(Eval("(::ns::T_1<" + arg + ">::myint)1.1"), - XFail(IsEqual("1"))); - EXPECT_THAT(Eval("(ns::T_1 >::myint)1.1"), - XFail(IsEqual("1"))); - EXPECT_THAT(Eval("(::ns::T_1 >::myint)1.1"), - XFail(IsEqual("1"))); + EXPECT_THAT(Eval("(T_1<" + arg + ">::myint)1.2"), IsEqual("1.2")); + EXPECT_THAT(Eval("(::T_1<" + arg + ">::myint)1.2"), IsEqual("1.2")); + EXPECT_THAT(Eval("(T_1 >::myint)1.2"), IsEqual("1.2")); + EXPECT_THAT(Eval("(::T_1 >::myint)1.2"), IsEqual("1.2")); + + EXPECT_THAT(Eval("(ns::T_1<" + arg + ">::myint)1.1"), IsEqual("1")); + EXPECT_THAT(Eval("(::ns::T_1<" + arg + ">::myint)1.1"), IsEqual("1")); + EXPECT_THAT(Eval("(ns::T_1 >::myint)1.1"), IsEqual("1")); + EXPECT_THAT(Eval("(::ns::T_1 >::myint)1.1"), IsEqual("1")); } EXPECT_THAT( @@ -2108,18 +2101,14 @@ TEST_F(EvalTest, TestTemplateTypes) { IsError("use of undeclared identifier '::ns::T_1'")); } - EXPECT_THAT(Eval("(T_2::myint)1.1f"), - XFail(IsEqual("1.10000002"))); - EXPECT_THAT(Eval("(::T_2::myint)1.1f"), - XFail(IsEqual("1.10000002"))); - EXPECT_THAT(Eval("(T_2::myint)1.1f"), - XFail(IsEqual("1.10000002"))); - EXPECT_THAT(Eval("(::T_2::myint)1.1f"), - XFail(IsEqual("1.10000002"))); + EXPECT_THAT(Eval("(T_2::myint)1.1f"), IsEqual("1.10000002")); + EXPECT_THAT(Eval("(::T_2::myint)1.1f"), IsEqual("1.10000002")); + EXPECT_THAT(Eval("(T_2::myint)1.1f"), IsEqual("1.10000002")); + EXPECT_THAT(Eval("(::T_2::myint)1.1f"), IsEqual("1.10000002")); EXPECT_THAT(Eval("(T_2 >, T_1 >::myint)1.1"), - XFail(IsEqual("1.10000002"))); + IsEqual("1.10000002")); EXPECT_THAT(Eval("(::T_2 >, T_1 >::myint)1.1"), - XFail(IsEqual("1.10000002"))); + IsEqual("1.10000002")); } TEST_F(EvalTest, TestTemplateCpp11) { @@ -2133,7 +2122,9 @@ TEST_F(EvalTest, TestTemplateCpp11) { // Here T_1 is a local variable. EXPECT_THAT(Eval("T_1<2>1"), IsEqual("false")); // (p < 2) > 1 - EXPECT_THAT(Eval("T_1<2>>1"), IsEqual("false")); // (p < 2) >> 1 + // EXPECT_THAT(Eval("T_1<2>>1"), IsEqual("false")); // (p < 2) >> 1 + EXPECT_THAT(Eval("T_1<2>>1"), + IsError(": Unexpected token: <'>' (greater)>")); // And here it's a template. EXPECT_THAT(Eval("T_1::cx + 1"), XFail(IsEqual("25"))); } @@ -2145,7 +2136,7 @@ TEST_F(EvalTest, TestTemplateWithNumericArguments) { EXPECT_THAT(Eval("(Allocator<4>*)0"), IsEqual(Is32Bit() ? "0x00000000" : "0x0000000000000000")); EXPECT_THAT(Eval("(TArray >::ElementType*)0"), - XFail(IsEqual(Is32Bit() ? "0x00000000" : "0x0000000000000000"))); + IsEqual(Is32Bit() ? "0x00000000" : "0x0000000000000000")); // Test C++11's ">>" syntax. EXPECT_THAT(Eval("(TArray>::ElementType*)0"), XFail(IsEqual(Is32Bit() ? "0x00000000" : "0x0000000000000000")));