clang: lib/Parse/ParseInit.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SmallString.h"
25using namespace clang;
26
27
28
29
30
31bool Parser::MayBeDesignationStart() {
33 default:
34 return false;
35
36 case tok::period:
37 return true;
38
39 case tok::l_square: {
41 return true;
42
43
44
45
47 case tok::equal:
48 case tok::ellipsis:
49 case tok::r_square:
50
51 return false;
52
53 case tok::amp:
54 case tok::kw_this:
55 case tok:⭐
56 case tok::identifier:
57
58
59 break;
60
61 default:
62
63
64 return true;
65 }
66
67
68 break;
69 }
70 case tok::identifier:
72 }
73
74
75
76 RevertingTentativeParsingAction Tentative(*this);
77
79 LambdaIntroducerTentativeParse ParseResult;
80 if (ParseLambdaIntroducer(Intro, &ParseResult)) {
81
82
83 return true;
84 }
85
86 switch (ParseResult) {
87 case LambdaIntroducerTentativeParse::Success:
88 case LambdaIntroducerTentativeParse::Incomplete:
89
90
91
92 break;
93
94 case LambdaIntroducerTentativeParse::MessageSend:
95 case LambdaIntroducerTentativeParse::Invalid:
96
97
98 return true;
99 }
100
101
102
103
104
105
106 return Tok.is(tok::equal);
107}
108
111
112
113
117 P.Diag(Loc, diag::ext_gnu_missing_equal_designator);
119 P.Diag(Loc, diag::err_expected_equal_designator);
120}
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164ExprResult Parser::ParseInitializerWithPotentialDesignator(
165 DesignatorCompletionInfo DesignatorCompletion) {
166
167
168
169
170 if (Tok.is(tok::identifier)) {
172
174 llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
175 << " = ";
176
178
179 assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
181
182 Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
184 NewSyntax);
185
190 Tok.getLocation(), DesignatorCompletion.PreferredBaseType, D);
192 ParseInitializer());
193 }
194
195
196
197
199
200
201 while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
202 if (Tok.is(tok::period)) {
203
205
206 if (Tok.is(tok::code_completion)) {
207 cutOffParsing();
209 DesignatorCompletion.PreferredBaseType,
210 DesignatorCompletion.InitExprs, Desig);
212 }
213 if (Tok.isNot(tok::identifier)) {
214 Diag(Tok.getLocation(), diag::err_expected_field_designator);
216 }
217
221 continue;
222 }
223
224
225 assert(Tok.is(tok::l_square) && "Unexpected token!");
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
245
247 T.consumeOpen();
249
251
252
253
254
255
257
259 NextToken().isNot(tok::period) &&
262 return ParseAssignmentExprWithObjCMessageExprStart(
264 }
265
266
267 bool IsExpr;
268 void *TypeOrExpr;
269 if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
272 }
273
274
275
276 if (!IsExpr) {
278 return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
281 nullptr);
282 }
283
284
285
286
287
293
294
295
297 getCurScope(), II, IILoc, II == Ident_super,
298 NextToken().is(tok::period), ReceiverType)) {
301 return ParseAssignmentExprWithObjCMessageExprStart(
303
307 if (!ReceiverType) {
310 }
311
312
313 if (Tok.is(tok::less)) {
316 = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType,
317 true,
318 NewEndLoc);
319 if (!NewReceiverType.isUsable()) {
322 }
323
324 ReceiverType = NewReceiverType.get();
325 }
326
327 return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
329 ReceiverType,
330 nullptr);
331
333
334
335
336 break;
337 }
338 }
339
340
341
342
343
344
345
346
347 if (!Idx.get()) {
351 return Idx;
352 }
353 }
354
355
356
357
358
360 Tok.isNot(tok::r_square)) {
362 return ParseAssignmentExprWithObjCMessageExprStart(
364 }
365
366
367 if (Tok.isNot(tok::ellipsis)) {
369 StartLoc));
370 } else {
371
372 Diag(Tok, diag::ext_gnu_array_range);
374
376 if (RHS.isInvalid()) {
378 return RHS;
379 }
381 Idx.get(), RHS.get(), StartLoc, EllipsisLoc));
382 }
383
384 T.consumeClose();
386 T.getCloseLocation());
387 }
388
389
390
391
392
393 assert(!Desig.empty() && "Designator is empty?");
394
395
396 if (Tok.is(tok::equal)) {
399 Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
401 ParseInitializer());
402 }
403
404
405
406
409 Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
411 ParseBraceInitializer());
412 }
413
414
415
416
417
421 Diag(Tok, diag::ext_gnu_missing_equal_designator)
424 true, ParseInitializer());
425 }
426
427 Diag(Tok, diag::err_expected_equal_designator);
429}
430
431ExprResult Parser::createEmbedExpr() {
432 assert(Tok.getKind() == tok::annot_embed);
438 if (Data->BinaryData.size() == 1) {
440 Context, llvm::APInt(CHAR_BIT, (unsigned char)Data->BinaryData.back()),
442 } else {
443 auto CreateStringLiteralFromStringRef = [&](StringRef Str, QualType Ty) {
444 llvm::APSInt ArraySize =
449 false, ArrayTy, StartLoc);
450 };
451
452 StringLiteral *BinaryDataArg = CreateStringLiteralFromStringRef(
454 Res = Actions.ActOnEmbedExpr(StartLoc, BinaryDataArg);
455 }
456 return Res;
457}
458
459
460
461
462
463
464
465
466
467
468
469
470
471ExprResult Parser::ParseBraceInitializer() {
473
475 T.consumeOpen();
477
478
479
480 ExprVector InitExprs;
481
482 if (Tok.is(tok::r_brace)) {
483
486 ? diag::warn_c23_compat_empty_initializer
487 : diag::ext_c_empty_initializer);
488 }
489
490 return Actions.ActOnInitList(LBraceLoc, {}, ConsumeBrace());
491 }
492
493
496
497 bool InitExprsOk = true;
498 QualType LikelyType = PreferredType.get(T.getOpenLocation());
499 DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};
500 bool CalledSignatureHelp = false;
501 auto RunSignatureHelp = [&] {
503 if (!LikelyType.isNull())
506 InitExprs, T.getOpenLocation(), true);
507 CalledSignatureHelp = true;
508 return PreferredType;
509 };
510
511 while (true) {
512 PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
513
514
515 if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
516 Tok.is(tok::kw___if_not_exists))) {
517 if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {
518 if (Tok.isNot(tok::comma)) break;
520 }
521 if (Tok.is(tok::r_brace)) break;
522 continue;
523 }
524
525
526
527
528
530 if (MayBeDesignationStart())
531 SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
532 else if (Tok.getKind() == tok::annot_embed)
533 SubElt = createEmbedExpr();
534 else
535 SubElt = ParseInitializer();
536
537 if (Tok.is(tok::ellipsis))
539
541
542
544 InitExprs.push_back(SubElt.get());
545 } else {
546 InitExprsOk = false;
547
548
549
550
551
552
553
554
555
556 if (Tok.isNot(tok::comma)) {
558 break;
559 }
560 }
561
562
563 if (Tok.isNot(tok::comma)) break;
564
565
567
568
569 if (Tok.is(tok::r_brace)) break;
570 }
571
572 bool closed = .consumeClose();
573
574 if (InitExprsOk && closed)
575 return Actions.ActOnInitList(LBraceLoc, InitExprs,
576 T.getCloseLocation());
577
578 return ExprError();
579}
580
581
582
583
584bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
585 bool &InitExprsOk) {
586 bool trailingComma = false;
587 IfExistsCondition Result;
588 if (ParseMicrosoftIfExistsCondition(Result))
589 return false;
590
592 if (Braces.consumeOpen()) {
593 Diag(Tok, diag::err_expected) << tok::l_brace;
594 return false;
595 }
596
597 switch (Result.Behavior) {
598 case IEB_Parse:
599
600 break;
601
602 case IEB_Dependent:
603 Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
604 << Result.IsIfExists;
605
606 [[fallthrough]];
607
608 case IEB_Skip:
610 return false;
611 }
612
613 DesignatorCompletionInfo DesignatorCompletion{
614 InitExprs,
615 PreferredType.get(Braces.getOpenLocation()),
616 };
617 while (!isEofOrEom()) {
618 trailingComma = false;
619
620
622 if (MayBeDesignationStart())
623 SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
624 else
625 SubElt = ParseInitializer();
626
627 if (Tok.is(tok::ellipsis))
629
630
632 InitExprs.push_back(SubElt.get());
633 else
634 InitExprsOk = false;
635
636 if (Tok.is(tok::comma)) {
638 trailingComma = true;
639 }
640
641 if (Tok.is(tok::r_brace))
642 break;
643 }
644
645 Braces.consumeClose();
646
647 return !trailingComma;
648}
static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, Designation &Desig)
This file declares facilities that support code completion.
This file declares semantic analysis for Objective-C.
Defines the clang::TokenKind enum and support functions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType UnsignedCharTy
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const
Make an APSInt of the appropriate width and signedness for the given Value and integer Type.
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 IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
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)
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)
@ ObjCClassMessage
The message is a class message, and the identifier is a type name.
@ ObjCInstanceMessage
The message is an instance message.
@ ObjCSuperMessage
The message is sent to 'super'.
ExprResult ActOnDesignatedInitializer(Designation &Desig, SourceLocation EqualOrColonLoc, bool GNUSyntax, ExprResult Init)
ASTContext & getASTContext() const
SemaCodeCompletion & CodeCompletion()
ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg, SourceLocation EllipsisLoc)
Invoked when parsing a template argument followed by an ellipsis, which creates a pack expansion.
ExprResult ActOnEmbedExpr(SourceLocation EmbedKeywordLoc, StringLiteral *BinaryData)
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.
StringLiteral - This represents a string literal expression, e.g.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated)
This is the "fully general" constructor that allows representation of strings formed from multiple co...
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)) {....
void * getAnnotationValue() const
tok::TokenKind getKind() const
bool isNot(tok::TokenKind K) const
QualType getCanonicalTypeInternal() const
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
ActionResult< Expr * > ExprResult
const FunctionProtoType * T
@ Braces
New-expression has a C++11 list-initializer.
Helper class to shuttle information about #embed directives from the preprocessor to the parser throu...
Represents a complete lambda introducer.