1212// ===----------------------------------------------------------------------===//
1313
1414#include " lldb/ValueObject/DILParser.h"
15+ #include " lldb/Symbol/CompileUnit.h"
1516#include " lldb/Target/ExecutionContextScope.h"
17+ #include " lldb/Target/LanguageRuntime.h"
1618#include " lldb/Utility/DiagnosticsRendering.h"
1719#include " lldb/ValueObject/DILAST.h"
1820#include " lldb/ValueObject/DILEval.h"
@@ -80,15 +82,62 @@ ASTNodeUP DILParser::Run() {
8082// Parse an expression.
8183//
8284// expression:
83- // unary_expression
85+ // cast_expression
8486//
85- ASTNodeUP DILParser::ParseExpression () { return ParseUnaryExpression (); }
87+ ASTNodeUP DILParser::ParseExpression () { return ParseCastExpression (); }
88+
89+ // Parse a cast_expression.
90+ //
91+ // cast_expression:
92+ // unary_expression
93+ // "(" type_id ")" cast_expression
94+
95+ ASTNodeUP DILParser::ParseCastExpression () {
96+ // This can be a C-style cast, try parsing the contents as a type declaration.
97+ if (CurToken ().Is (Token::l_paren)) {
98+ Token token = CurToken ();
99+ uint32_t loc = token.GetLocation ();
100+
101+ // Enable lexer backtracking, so that we can rollback in case it's not
102+ // actually a type declaration.
103+
104+ // Start tentative parsing (save token location/idx, for possible rollback).
105+ uint32_t save_token_idx = m_dil_lexer.GetCurrentTokenIdx ();
106+
107+ // Consume the token only after enabling the backtracking.
108+ m_dil_lexer.Advance ();
109+
110+ // Try parsing the type declaration. If the returned value is not valid,
111+ // then we should rollback and try parsing the expression.
112+ auto type_id = ParseTypeId ();
113+ if (type_id) {
114+ // Successfully parsed the type declaration. Commit the backtracked
115+ // tokens and parse the cast_expression.
116+
117+ if (!type_id.value ().IsValid ())
118+ return std::make_unique<ErrorNode>();
119+
120+ Expect (Token::r_paren);
121+ m_dil_lexer.Advance ();
122+ auto rhs = ParseCastExpression ();
123+
124+ return std::make_unique<CStyleCastNode>(
125+ loc, type_id.value (), std::move (rhs), CStyleCastKind::eNone);
126+ }
127+
128+ // Failed to parse the contents of the parentheses as a type declaration.
129+ // Rollback the lexer and try parsing it as unary_expression.
130+ TentativeParsingRollback (save_token_idx);
131+ }
132+
133+ return ParseUnaryExpression ();
134+ }
86135
87136// Parse an unary_expression.
88137//
89138// unary_expression:
90139// postfix_expression
91- // unary_operator expression
140+ // unary_operator cast_expression
92141//
93142// unary_operator:
94143// "&"
@@ -99,7 +148,7 @@ ASTNodeUP DILParser::ParseUnaryExpression() {
99148 Token token = CurToken ();
100149 uint32_t loc = token.GetLocation ();
101150 m_dil_lexer.Advance ();
102- auto rhs = ParseExpression ();
151+ auto rhs = ParseCastExpression ();
103152 switch (token.GetKind ()) {
104153 case Token::star:
105154 return std::make_unique<UnaryOpNode>(loc, UnaryOpKind::Deref,
@@ -274,6 +323,81 @@ std::string DILParser::ParseNestedNameSpecifier() {
274323 }
275324}
276325
326+ // Parse a type_id.
327+ //
328+ // type_id:
329+ // type_specifier_seq [abstract_declarator]
330+ //
331+ // type_specifier_seq:
332+ // type_specifier [type_specifier]
333+ //
334+ // type_specifier:
335+ // ["::"] [nested_name_specifier] type_name // not handled for now!
336+ // builtin_typename
337+ //
338+ std::optional<CompilerType> DILParser::ParseTypeId () {
339+ CompilerType type;
340+ // For now only allow builtin types -- will expand add to this later.
341+ auto maybe_builtin_type = ParseBuiltinType ();
342+ if (maybe_builtin_type) {
343+ type = *maybe_builtin_type;
344+ } else
345+ return {};
346+
347+ //
348+ // abstract_declarator:
349+ // ptr_operator [abstract_declarator]
350+ //
351+ std::vector<Token> ptr_operators;
352+ while (CurToken ().IsOneOf ({Token::star, Token::amp})) {
353+ Token tok = CurToken ();
354+ ptr_operators.push_back (std::move (tok));
355+ m_dil_lexer.Advance ();
356+ }
357+ type = ResolveTypeDeclarators (type, ptr_operators);
358+
359+ return type;
360+ }
361+
362+ // Parse a built-in type
363+ //
364+ // builtin_typename:
365+ // identifer_seq
366+ //
367+ // identifier_seq
368+ // identifer [identifier_seq]
369+ //
370+ // A built-in type can be a single identifier or a space-separated
371+ // list of identifiers (e.g. "short" or "long long").
372+ std::optional<CompilerType> DILParser::ParseBuiltinType () {
373+ std::string type_name = " " ;
374+ uint32_t save_token_idx = m_dil_lexer.GetCurrentTokenIdx ();
375+ bool first_word = true ;
376+ while (CurToken ().GetKind () == Token::identifier) {
377+ if (CurToken ().GetSpelling () == " const" ||
378+ CurToken ().GetSpelling () == " volatile" )
379+ continue ;
380+ if (!first_word)
381+ type_name.push_back (' ' );
382+ else
383+ first_word = false ;
384+ type_name.append (CurToken ().GetSpelling ());
385+ m_dil_lexer.Advance ();
386+ }
387+
388+ if (type_name.size () > 0 ) {
389+ lldb::TargetSP target_sp = m_ctx_scope->CalculateTarget ();
390+ ConstString const_type_name (type_name.c_str ());
391+ for (auto type_system_sp : target_sp->GetScratchTypeSystems ())
392+ if (auto compiler_type =
393+ type_system_sp->GetBuiltinTypeByName (const_type_name))
394+ return compiler_type;
395+ }
396+
397+ TentativeParsingRollback (save_token_idx);
398+ return {};
399+ }
400+
277401// Parse an id_expression.
278402//
279403// id_expression:
@@ -339,6 +463,40 @@ std::string DILParser::ParseUnqualifiedId() {
339463 return identifier;
340464}
341465
466+ CompilerType
467+ DILParser::ResolveTypeDeclarators (CompilerType type,
468+ const std::vector<Token> &ptr_operators) {
469+ CompilerType bad_type;
470+ // Resolve pointers/references.
471+ for (Token tk : ptr_operators) {
472+ uint32_t loc = tk.GetLocation ();
473+ if (tk.GetKind () == Token::star) {
474+ // Pointers to reference types are forbidden.
475+ if (type.IsReferenceType ()) {
476+ BailOut (llvm::formatv (" 'type name' declared as a pointer to a "
477+ " reference of type {0}" ,
478+ type.TypeDescription ()),
479+ loc, CurToken ().GetSpelling ().length ());
480+ return bad_type;
481+ }
482+ // Get pointer type for the base type: e.g. int* -> int**.
483+ type = type.GetPointerType ();
484+
485+ } else if (tk.GetKind () == Token::amp) {
486+ // References to references are forbidden.
487+ if (type.IsReferenceType ()) {
488+ BailOut (" type name declared as a reference to a reference" , loc,
489+ CurToken ().GetSpelling ().length ());
490+ return bad_type;
491+ }
492+ // Get reference type for the base type: e.g. int -> int&.
493+ type = type.GetLValueReferenceType ();
494+ }
495+ }
496+
497+ return type;
498+ }
499+
342500// Parse an boolean_literal.
343501//
344502// boolean_literal:
0 commit comments