1313
1414#include " lldb/ValueObject/DILParser.h"
1515#include " lldb/Host/common/DiagnosticsRendering.h"
16+ #include " lldb/Symbol/CompileUnit.h"
1617#include " lldb/Target/ExecutionContextScope.h"
18+ #include " lldb/Target/LanguageRuntime.h"
1719#include " lldb/ValueObject/DILAST.h"
1820#include " lldb/ValueObject/DILEval.h"
1921#include " llvm/ADT/StringRef.h"
@@ -80,15 +82,63 @@ 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+ if (!CurToken ().Is (Token::l_paren))
97+ return ParseUnaryExpression ();
98+
99+ // This could be a type cast, try parsing the contents as a type declaration.
100+ Token token = CurToken ();
101+ uint32_t loc = token.GetLocation ();
102+
103+ // Enable lexer backtracking, so that we can rollback in case it's not
104+ // actually a type declaration.
105+
106+ // Start tentative parsing (save token location/idx, for possible rollback).
107+ uint32_t save_token_idx = m_dil_lexer.GetCurrentTokenIdx ();
108+
109+ // Consume the token only after enabling the backtracking.
110+ m_dil_lexer.Advance ();
111+
112+ // Try parsing the type declaration. If the returned value is not valid,
113+ // then we should rollback and try parsing the expression.
114+ auto type_id = ParseTypeId ();
115+ if (type_id) {
116+ // Successfully parsed the type declaration. Commit the backtracked
117+ // tokens and parse the cast_expression.
118+
119+ if (!type_id.value ().IsValid ())
120+ return std::make_unique<ErrorNode>();
121+
122+ Expect (Token::r_paren);
123+ m_dil_lexer.Advance ();
124+ auto rhs = ParseCastExpression ();
125+
126+ return std::make_unique<CastNode>(loc, type_id.value (), std::move (rhs),
127+ CastKind::eNone);
128+ }
129+
130+ // Failed to parse the contents of the parentheses as a type declaration.
131+ // Rollback the lexer and try parsing it as unary_expression.
132+ TentativeParsingRollback (save_token_idx);
133+
134+ return ParseUnaryExpression ();
135+ }
86136
87137// Parse an unary_expression.
88138//
89139// unary_expression:
90140// postfix_expression
91- // unary_operator expression
141+ // unary_operator cast_expression
92142//
93143// unary_operator:
94144// "&"
@@ -102,7 +152,7 @@ ASTNodeUP DILParser::ParseUnaryExpression() {
102152 Token token = CurToken ();
103153 uint32_t loc = token.GetLocation ();
104154 m_dil_lexer.Advance ();
105- auto rhs = ParseExpression ();
155+ auto rhs = ParseCastExpression ();
106156 switch (token.GetKind ()) {
107157 case Token::star:
108158 return std::make_unique<UnaryOpNode>(loc, UnaryOpKind::Deref,
@@ -282,6 +332,81 @@ std::string DILParser::ParseNestedNameSpecifier() {
282332 }
283333}
284334
335+ // Parse a type_id.
336+ //
337+ // type_id:
338+ // type_specifier_seq [abstract_declarator]
339+ //
340+ // type_specifier_seq:
341+ // type_specifier [type_specifier]
342+ //
343+ // type_specifier:
344+ // ["::"] [nested_name_specifier] type_name // not handled for now!
345+ // builtin_typename
346+ //
347+ std::optional<CompilerType> DILParser::ParseTypeId () {
348+ CompilerType type;
349+ // For now only allow builtin types -- will expand add to this later.
350+ auto maybe_builtin_type = ParseBuiltinType ();
351+ if (maybe_builtin_type) {
352+ type = *maybe_builtin_type;
353+ } else
354+ return {};
355+
356+ //
357+ // abstract_declarator:
358+ // ptr_operator [abstract_declarator]
359+ //
360+ std::vector<Token> ptr_operators;
361+ while (CurToken ().IsOneOf ({Token::star, Token::amp})) {
362+ Token tok = CurToken ();
363+ ptr_operators.push_back (std::move (tok));
364+ m_dil_lexer.Advance ();
365+ }
366+ type = ResolveTypeDeclarators (type, ptr_operators);
367+
368+ return type;
369+ }
370+
371+ // Parse a built-in type
372+ //
373+ // builtin_typename:
374+ // identifer_seq
375+ //
376+ // identifier_seq
377+ // identifer [identifier_seq]
378+ //
379+ // A built-in type can be a single identifier or a space-separated
380+ // list of identifiers (e.g. "short" or "long long").
381+ std::optional<CompilerType> DILParser::ParseBuiltinType () {
382+ std::string type_name = " " ;
383+ uint32_t save_token_idx = m_dil_lexer.GetCurrentTokenIdx ();
384+ bool first_word = true ;
385+ while (CurToken ().GetKind () == Token::identifier) {
386+ if (CurToken ().GetSpelling () == " const" ||
387+ CurToken ().GetSpelling () == " volatile" )
388+ continue ;
389+ if (!first_word)
390+ type_name.push_back (' ' );
391+ else
392+ first_word = false ;
393+ type_name.append (CurToken ().GetSpelling ());
394+ m_dil_lexer.Advance ();
395+ }
396+
397+ if (type_name.size () > 0 ) {
398+ lldb::TargetSP target_sp = m_ctx_scope->CalculateTarget ();
399+ ConstString const_type_name (type_name.c_str ());
400+ for (auto type_system_sp : target_sp->GetScratchTypeSystems ())
401+ if (auto compiler_type =
402+ type_system_sp->GetBuiltinTypeByName (const_type_name))
403+ return compiler_type;
404+ }
405+
406+ TentativeParsingRollback (save_token_idx);
407+ return {};
408+ }
409+
285410// Parse an id_expression.
286411//
287412// id_expression:
@@ -347,6 +472,40 @@ std::string DILParser::ParseUnqualifiedId() {
347472 return identifier;
348473}
349474
475+ CompilerType
476+ DILParser::ResolveTypeDeclarators (CompilerType type,
477+ const std::vector<Token> &ptr_operators) {
478+ // Resolve pointers/references.
479+ for (Token tk : ptr_operators) {
480+ uint32_t loc = tk.GetLocation ();
481+ if (tk.GetKind () == Token::star) {
482+ // Pointers to reference types are forbidden.
483+ if (type.IsReferenceType ()) {
484+ BailOut (llvm::formatv (" 'type name' declared as a pointer to a "
485+ " reference of type {0}" ,
486+ type.TypeDescription ()),
487+ loc, CurToken ().GetSpelling ().length ());
488+ return {};
489+ }
490+ // Get pointer type for the base type: e.g. int* -> int**.
491+ type = type.GetPointerType ();
492+
493+ } else if (tk.GetKind () == Token::amp) {
494+ // References to references are forbidden.
495+ // FIXME: In future we may want to allow rvalue references (i.e. &&).
496+ if (type.IsReferenceType ()) {
497+ BailOut (" type name declared as a reference to a reference" , loc,
498+ CurToken ().GetSpelling ().length ());
499+ return {};
500+ }
501+ // Get reference type for the base type: e.g. int -> int&.
502+ type = type.GetLValueReferenceType ();
503+ }
504+ }
505+
506+ return type;
507+ }
508+
350509// Parse an boolean_literal.
351510//
352511// boolean_literal:
0 commit comments