21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallString.h"
29bool Parser::MayBeDesignationStart() {
74 RevertingTentativeParsingAction Tentative(*
this);
77 LambdaIntroducerTentativeParse ParseResult;
78 if (ParseLambdaIntroducer(Intro, &ParseResult)) {
84 switch (ParseResult) {
85 case LambdaIntroducerTentativeParse::Success:
86 case LambdaIntroducerTentativeParse::Incomplete:
92 case LambdaIntroducerTentativeParse::MessageSend:
93 case LambdaIntroducerTentativeParse::Invalid:
104 return Tok.
is(tok::equal);
115 P.Diag(Loc, diag::ext_gnu_missing_equal_designator);
117 P.Diag(Loc, diag::err_expected_equal_designator);
162ExprResult Parser::ParseInitializerWithPotentialDesignator(
163 DesignatorCompletionInfo DesignatorCompletion) {
168 if (Tok.
is(tok::identifier)) {
172 llvm::raw_svector_ostream(NewSyntax) <<
'.' << FieldName->
getName()
177 assert(Tok.
is(tok::colon) &&
"MayBeDesignationStart not working properly!");
180 Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
188 Tok.
getLocation(), DesignatorCompletion.PreferredBaseType, D);
199 while (Tok.
is(tok::period) || Tok.
is(tok::l_square)) {
200 if (Tok.
is(tok::period)) {
204 if (Tok.
is(tok::code_completion)) {
207 DesignatorCompletion.InitExprs, Desig);
210 if (Tok.
isNot(tok::identifier)) {
222 assert(Tok.
is(tok::l_square) &&
"Unexpected token!");
259 return ParseAssignmentExprWithObjCMessageExprStart(
266 if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
275 return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
295 NextToken().is(tok::period), ReceiverType)) {
298 return ParseAssignmentExprWithObjCMessageExprStart(
310 if (Tok.
is(tok::less)) {
313 = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType,
321 ReceiverType = NewReceiverType.
get();
324 return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
357 Tok.
isNot(tok::r_square)) {
359 return ParseAssignmentExprWithObjCMessageExprStart(
364 if (Tok.
isNot(tok::ellipsis)) {
369 Diag(Tok, diag::ext_gnu_array_range);
373 if (RHS.isInvalid()) {
378 Idx.
get(), RHS.get(), StartLoc, EllipsisLoc));
383 T.getCloseLocation());
390 assert(!Desig.
empty() &&
"Designator is empty?");
393 if (Tok.
is(tok::equal)) {
396 Tok.
getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
406 Tok.
getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
408 ParseBraceInitializer());
418 Diag(Tok, diag::ext_gnu_missing_equal_designator)
421 true, ParseInitializer());
424 Diag(Tok, diag::err_expected_equal_designator);
449 ExprVector InitExprs;
451 if (Tok.
is(tok::r_brace)) {
455 ? diag::warn_c23_compat_empty_initializer
456 : diag::ext_c_empty_initializer);
459 return Actions.
ActOnInitList(LBraceLoc, std::nullopt, ConsumeBrace());
466 bool InitExprsOk =
true;
467 QualType LikelyType = PreferredType.
get(T.getOpenLocation());
468 DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};
469 bool CalledSignatureHelp =
false;
470 auto RunSignatureHelp = [&] {
475 InitExprs, T.getOpenLocation(),
true);
476 CalledSignatureHelp =
true;
477 return PreferredType;
481 PreferredType.enterFunctionArgument(Tok.
getLocation(), RunSignatureHelp);
484 if (
getLangOpts().MicrosoftExt && (Tok.
is(tok::kw___if_exists) ||
485 Tok.
is(tok::kw___if_not_exists))) {
486 if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {
487 if (Tok.
isNot(tok::comma))
break;
490 if (Tok.
is(tok::r_brace))
break;
499 if (MayBeDesignationStart())
500 SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
502 SubElt = ParseInitializer();
504 if (Tok.
is(tok::ellipsis))
511 InitExprs.push_back(SubElt.
get());
523 if (Tok.
isNot(tok::comma)) {
530 if (Tok.
isNot(tok::comma))
break;
536 if (Tok.
is(tok::r_brace))
break;
539 bool closed = !T.consumeClose();
541 if (InitExprsOk && closed)
543 T.getCloseLocation());
551bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
553 bool trailingComma =
false;
555 if (ParseMicrosoftIfExistsCondition(
Result))
559 if (Braces.consumeOpen()) {
560 Diag(Tok, diag::err_expected) << tok::l_brace;
564 switch (
Result.Behavior) {
570 Diag(
Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
580 DesignatorCompletionInfo DesignatorCompletion{
582 PreferredType.get(Braces.getOpenLocation()),
584 while (!isEofOrEom()) {
585 trailingComma =
false;
589 if (MayBeDesignationStart())
590 SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
592 SubElt = ParseInitializer();
594 if (Tok.
is(tok::ellipsis))
599 InitExprs.push_back(SubElt.
get());
603 if (Tok.
is(tok::comma)) {
605 trailingComma =
true;
608 if (Tok.
is(tok::r_brace))
612 Braces.consumeClose();
614 return !trailingComma;
static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, Designation &Desig)
Defines the clang::TokenKind enum and support functions.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Designation - Represent a full designation, which is a sequence of designators.
const Designator & getDesignator(unsigned Idx) const
unsigned getNumDesignators() const
void AddDesignator(Designator D)
AddDesignator - Add a designator to the end of this list.
bool isArrayDesignator() const
static Designator CreateArrayRangeDesignator(Expr *Start, Expr *End, SourceLocation LBracketLoc, SourceLocation EllipsisLoc)
Creates a GNU array-range designator.
static Designator CreateArrayDesignator(Expr *Index, SourceLocation LBracketLoc)
Creates an array designator.
void setRBracketLoc(SourceLocation RBracketLoc) const
bool isArrayRangeDesignator() const
static Designator CreateFieldDesignator(const IdentifierInfo *FieldName, SourceLocation DotLoc, SourceLocation FieldLoc)
Creates a field designator.
RAII object that enters a new expression evaluation context.
This represents one expression.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
static OpaquePtr getFromOpaquePtr(void *P)
Parser - This implements a parser for the C family of languages.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
ExprResult ParseConstantExpression()
Scope * getCurScope() const
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
const LangOptions & getLangOpts() const
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
@ StopAtSemi
Stop skipping at semicolon.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
void enterDesignatedInitializer(SourceLocation Tok, QualType BaseType, const Designation &D)
Handles e.g. BaseType{ .D = Tok...
QualType get(SourceLocation Tok) const
Get the expected type associated with this location, if any.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
const LangOptions & getLangOpts() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, ArrayRef< Expr * > Args, SourceLocation OpenParLoc, bool Braced)
ExprResult ActOnDesignatedInitializer(Designation &Desig, SourceLocation EqualOrColonLoc, bool GNUSyntax, ExprResult Init)
void CodeCompleteDesignator(const QualType BaseType, llvm::ArrayRef< Expr * > InitExprs, const Designation &D)
Trigger code completion for a record of BaseType.
ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name, SourceLocation NameLoc, bool IsSuper, bool HasTrailingDot, ParsedType &ReceiverType)
ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg, SourceLocation EllipsisLoc)
Invoked when parsing a template argument followed by an ellipsis, which creates a pack expansion.
@ ObjCSuperMessage
The message is sent to 'super'.
@ ObjCClassMessage
The message is a class message, and the identifier is a type name.
@ ObjCInstanceMessage
The message is an instance message.
ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, SourceLocation RBraceLoc)
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
Encodes a location in the source.
A trivial tuple used to represent a source range.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isNot(tok::TokenKind K) const
QualType getCanonicalTypeInternal() const
@ Result
The result type of a method or function.
ActionResult< Expr * > ExprResult
Represents a complete lambda introducer.