xref: /freebsd/contrib/llvm-project/clang/lib/Parse/ParseInit.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===--- ParseInit.cpp - Initializer Parsing ------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements initializer parsing as specified by C99 6.7.8.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Basic/TokenKinds.h"
14 #include "clang/Parse/ParseDiagnostic.h"
15 #include "clang/Parse/Parser.h"
16 #include "clang/Parse/RAIIObjectsForParser.h"
17 #include "clang/Sema/Designator.h"
18 #include "clang/Sema/EnterExpressionEvaluationContext.h"
19 #include "clang/Sema/Ownership.h"
20 #include "clang/Sema/Scope.h"
21 #include "clang/Sema/SemaCodeCompletion.h"
22 #include "clang/Sema/SemaObjC.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SmallString.h"
25 using namespace clang;
26 
27 
28 /// MayBeDesignationStart - Return true if the current token might be the start
29 /// of a designator.  If we can tell it is impossible that it is a designator,
30 /// return false.
MayBeDesignationStart()31 bool Parser::MayBeDesignationStart() {
32   switch (Tok.getKind()) {
33   default:
34     return false;
35 
36   case tok::period:      // designator: '.' identifier
37     return true;
38 
39   case tok::l_square: {  // designator: array-designator
40     if (!PP.getLangOpts().CPlusPlus)
41       return true;
42 
43     // C++11 lambda expressions and C99 designators can be ambiguous all the
44     // way through the closing ']' and to the next character. Handle the easy
45     // cases here, and fall back to tentative parsing if those fail.
46     switch (PP.LookAhead(0).getKind()) {
47     case tok::equal:
48     case tok::ellipsis:
49     case tok::r_square:
50       // Definitely starts a lambda expression.
51       return false;
52 
53     case tok::amp:
54     case tok::kw_this:
55     case tok::star:
56     case tok::identifier:
57       // We have to do additional analysis, because these could be the
58       // start of a constant expression or a lambda capture list.
59       break;
60 
61     default:
62       // Anything not mentioned above cannot occur following a '[' in a
63       // lambda expression.
64       return true;
65     }
66 
67     // Handle the complicated case below.
68     break;
69   }
70   case tok::identifier:  // designation: identifier ':'
71     return PP.LookAhead(0).is(tok::colon);
72   }
73 
74   // Parse up to (at most) the token after the closing ']' to determine
75   // whether this is a C99 designator or a lambda.
76   RevertingTentativeParsingAction Tentative(*this);
77 
78   LambdaIntroducer Intro;
79   LambdaIntroducerTentativeParse ParseResult;
80   if (ParseLambdaIntroducer(Intro, &ParseResult)) {
81     // Hit and diagnosed an error in a lambda.
82     // FIXME: Tell the caller this happened so they can recover.
83     return true;
84   }
85 
86   switch (ParseResult) {
87   case LambdaIntroducerTentativeParse::Success:
88   case LambdaIntroducerTentativeParse::Incomplete:
89     // Might be a lambda-expression. Keep looking.
90     // FIXME: If our tentative parse was not incomplete, parse the lambda from
91     // here rather than throwing away then reparsing the LambdaIntroducer.
92     break;
93 
94   case LambdaIntroducerTentativeParse::MessageSend:
95   case LambdaIntroducerTentativeParse::Invalid:
96     // Can't be a lambda-expression. Treat it as a designator.
97     // FIXME: Should we disambiguate against a message-send?
98     return true;
99   }
100 
101   // Once we hit the closing square bracket, we look at the next
102   // token. If it's an '=', this is a designator. Otherwise, it's a
103   // lambda expression. This decision favors lambdas over the older
104   // GNU designator syntax, which allows one to omit the '=', but is
105   // consistent with GCC.
106   return Tok.is(tok::equal);
107 }
108 
CheckArrayDesignatorSyntax(Parser & P,SourceLocation Loc,Designation & Desig)109 static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
110                                        Designation &Desig) {
111   // If we have exactly one array designator, this used the GNU
112   // 'designation: array-designator' extension, otherwise there should be no
113   // designators at all!
114   if (Desig.getNumDesignators() == 1 &&
115       (Desig.getDesignator(0).isArrayDesignator() ||
116        Desig.getDesignator(0).isArrayRangeDesignator()))
117     P.Diag(Loc, diag::ext_gnu_missing_equal_designator);
118   else if (Desig.getNumDesignators() > 0)
119     P.Diag(Loc, diag::err_expected_equal_designator);
120 }
121 
122 /// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production
123 /// checking to see if the token stream starts with a designator.
124 ///
125 /// C99:
126 ///
127 ///       designation:
128 ///         designator-list '='
129 /// [GNU]   array-designator
130 /// [GNU]   identifier ':'
131 ///
132 ///       designator-list:
133 ///         designator
134 ///         designator-list designator
135 ///
136 ///       designator:
137 ///         array-designator
138 ///         '.' identifier
139 ///
140 ///       array-designator:
141 ///         '[' constant-expression ']'
142 /// [GNU]   '[' constant-expression '...' constant-expression ']'
143 ///
144 /// C++20:
145 ///
146 ///       designated-initializer-list:
147 ///         designated-initializer-clause
148 ///         designated-initializer-list ',' designated-initializer-clause
149 ///
150 ///       designated-initializer-clause:
151 ///         designator brace-or-equal-initializer
152 ///
153 ///       designator:
154 ///         '.' identifier
155 ///
156 /// We allow the C99 syntax extensions in C++20, but do not allow the C++20
157 /// extension (a braced-init-list after the designator with no '=') in C99.
158 ///
159 /// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an
160 /// initializer (because it is an expression).  We need to consider this case
161 /// when parsing array designators.
162 ///
163 /// \p CodeCompleteCB is called with Designation parsed so far.
ParseInitializerWithPotentialDesignator(DesignatorCompletionInfo DesignatorCompletion)164 ExprResult Parser::ParseInitializerWithPotentialDesignator(
165     DesignatorCompletionInfo DesignatorCompletion) {
166   // If this is the old-style GNU extension:
167   //   designation ::= identifier ':'
168   // Handle it as a field designator.  Otherwise, this must be the start of a
169   // normal expression.
170   if (Tok.is(tok::identifier)) {
171     const IdentifierInfo *FieldName = Tok.getIdentifierInfo();
172 
173     SmallString<256> NewSyntax;
174     llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
175                                          << " = ";
176 
177     SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
178 
179     assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
180     SourceLocation ColonLoc = ConsumeToken();
181 
182     Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
183       << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
184                                       NewSyntax);
185 
186     Designation D;
187     D.AddDesignator(Designator::CreateFieldDesignator(
188         FieldName, SourceLocation(), NameLoc));
189     PreferredType.enterDesignatedInitializer(
190         Tok.getLocation(), DesignatorCompletion.PreferredBaseType, D);
191     return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
192                                               ParseInitializer());
193   }
194 
195   // Desig - This is initialized when we see our first designator.  We may have
196   // an objc message send with no designator, so we don't want to create this
197   // eagerly.
198   Designation Desig;
199 
200   // Parse each designator in the designator list until we find an initializer.
201   while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
202     if (Tok.is(tok::period)) {
203       // designator: '.' identifier
204       SourceLocation DotLoc = ConsumeToken();
205 
206       if (Tok.is(tok::code_completion)) {
207         cutOffParsing();
208         Actions.CodeCompletion().CodeCompleteDesignator(
209             DesignatorCompletion.PreferredBaseType,
210             DesignatorCompletion.InitExprs, Desig);
211         return ExprError();
212       }
213       if (Tok.isNot(tok::identifier)) {
214         Diag(Tok.getLocation(), diag::err_expected_field_designator);
215         return ExprError();
216       }
217 
218       Desig.AddDesignator(Designator::CreateFieldDesignator(
219           Tok.getIdentifierInfo(), DotLoc, Tok.getLocation()));
220       ConsumeToken(); // Eat the identifier.
221       continue;
222     }
223 
224     // We must have either an array designator now or an objc message send.
225     assert(Tok.is(tok::l_square) && "Unexpected token!");
226 
227     // Handle the two forms of array designator:
228     //   array-designator: '[' constant-expression ']'
229     //   array-designator: '[' constant-expression '...' constant-expression ']'
230     //
231     // Also, we have to handle the case where the expression after the
232     // designator an an objc message send: '[' objc-message-expr ']'.
233     // Interesting cases are:
234     //   [foo bar]         -> objc message send
235     //   [foo]             -> array designator
236     //   [foo ... bar]     -> array designator
237     //   [4][foo bar]      -> obsolete GNU designation with objc message send.
238     //
239     // We do not need to check for an expression starting with [[ here. If it
240     // contains an Objective-C message send, then it is not an ill-formed
241     // attribute. If it is a lambda-expression within an array-designator, then
242     // it will be rejected because a constant-expression cannot begin with a
243     // lambda-expression.
244     InMessageExpressionRAIIObject InMessage(*this, true);
245 
246     BalancedDelimiterTracker T(*this, tok::l_square);
247     T.consumeOpen();
248     SourceLocation StartLoc = T.getOpenLocation();
249 
250     ExprResult Idx;
251 
252     // If Objective-C is enabled and this is a typename (class message
253     // send) or send to 'super', parse this as a message send
254     // expression.  We handle C++ and C separately, since C++ requires
255     // much more complicated parsing.
256     if  (getLangOpts().ObjC && getLangOpts().CPlusPlus) {
257       // Send to 'super'.
258       if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
259           NextToken().isNot(tok::period) &&
260           getCurScope()->isInObjcMethodScope()) {
261         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
262         return ParseAssignmentExprWithObjCMessageExprStart(
263             StartLoc, ConsumeToken(), nullptr, nullptr);
264       }
265 
266       // Parse the receiver, which is either a type or an expression.
267       bool IsExpr;
268       void *TypeOrExpr;
269       if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
270         SkipUntil(tok::r_square, StopAtSemi);
271         return ExprError();
272       }
273 
274       // If the receiver was a type, we have a class message; parse
275       // the rest of it.
276       if (!IsExpr) {
277         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
278         return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
279                                                            SourceLocation(),
280                                    ParsedType::getFromOpaquePtr(TypeOrExpr),
281                                                            nullptr);
282       }
283 
284       // If the receiver was an expression, we still don't know
285       // whether we have a message send or an array designator; just
286       // adopt the expression for further analysis below.
287       // FIXME: potentially-potentially evaluated expression above?
288       Idx = ExprResult(static_cast<Expr*>(TypeOrExpr));
289     } else if (getLangOpts().ObjC && Tok.is(tok::identifier)) {
290       IdentifierInfo *II = Tok.getIdentifierInfo();
291       SourceLocation IILoc = Tok.getLocation();
292       ParsedType ReceiverType;
293       // Three cases. This is a message send to a type: [type foo]
294       // This is a message send to super:  [super foo]
295       // This is a message sent to an expr:  [super.bar foo]
296       switch (Actions.ObjC().getObjCMessageKind(
297           getCurScope(), II, IILoc, II == Ident_super,
298           NextToken().is(tok::period), ReceiverType)) {
299       case SemaObjC::ObjCSuperMessage:
300         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
301         return ParseAssignmentExprWithObjCMessageExprStart(
302             StartLoc, ConsumeToken(), nullptr, nullptr);
303 
304       case SemaObjC::ObjCClassMessage:
305         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
306         ConsumeToken(); // the identifier
307         if (!ReceiverType) {
308           SkipUntil(tok::r_square, StopAtSemi);
309           return ExprError();
310         }
311 
312         // Parse type arguments and protocol qualifiers.
313         if (Tok.is(tok::less)) {
314           SourceLocation NewEndLoc;
315           TypeResult NewReceiverType
316             = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType,
317                                                      /*consumeLastToken=*/true,
318                                                      NewEndLoc);
319           if (!NewReceiverType.isUsable()) {
320             SkipUntil(tok::r_square, StopAtSemi);
321             return ExprError();
322           }
323 
324           ReceiverType = NewReceiverType.get();
325         }
326 
327         return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
328                                                            SourceLocation(),
329                                                            ReceiverType,
330                                                            nullptr);
331 
332       case SemaObjC::ObjCInstanceMessage:
333         // Fall through; we'll just parse the expression and
334         // (possibly) treat this like an Objective-C message send
335         // later.
336         break;
337       }
338     }
339 
340     // Parse the index expression, if we haven't already gotten one
341     // above (which can only happen in Objective-C++).
342     // Note that we parse this as an assignment expression, not a constant
343     // expression (allowing *=, =, etc) to handle the objc case.  Sema needs
344     // to validate that the expression is a constant.
345     // FIXME: We also need to tell Sema that we're in a
346     // potentially-potentially evaluated context.
347     if (!Idx.get()) {
348       Idx = ParseAssignmentExpression();
349       if (Idx.isInvalid()) {
350         SkipUntil(tok::r_square, StopAtSemi);
351         return Idx;
352       }
353     }
354 
355     // Given an expression, we could either have a designator (if the next
356     // tokens are '...' or ']' or an objc message send.  If this is an objc
357     // message send, handle it now.  An objc-message send is the start of
358     // an assignment-expression production.
359     if (getLangOpts().ObjC && Tok.isNot(tok::ellipsis) &&
360         Tok.isNot(tok::r_square)) {
361       CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);
362       return ParseAssignmentExprWithObjCMessageExprStart(
363           StartLoc, SourceLocation(), nullptr, Idx.get());
364     }
365 
366     // If this is a normal array designator, remember it.
367     if (Tok.isNot(tok::ellipsis)) {
368       Desig.AddDesignator(Designator::CreateArrayDesignator(Idx.get(),
369                                                             StartLoc));
370     } else {
371       // Handle the gnu array range extension.
372       Diag(Tok, diag::ext_gnu_array_range);
373       SourceLocation EllipsisLoc = ConsumeToken();
374 
375       ExprResult RHS(ParseConstantExpression());
376       if (RHS.isInvalid()) {
377         SkipUntil(tok::r_square, StopAtSemi);
378         return RHS;
379       }
380       Desig.AddDesignator(Designator::CreateArrayRangeDesignator(
381           Idx.get(), RHS.get(), StartLoc, EllipsisLoc));
382     }
383 
384     T.consumeClose();
385     Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(
386                                                         T.getCloseLocation());
387   }
388 
389   // Okay, we're done with the designator sequence.  We know that there must be
390   // at least one designator, because the only case we can get into this method
391   // without a designator is when we have an objc message send.  That case is
392   // handled and returned from above.
393   assert(!Desig.empty() && "Designator is empty?");
394 
395   // Handle a normal designator sequence end, which is an equal.
396   if (Tok.is(tok::equal)) {
397     SourceLocation EqualLoc = ConsumeToken();
398     PreferredType.enterDesignatedInitializer(
399         Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
400     return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,
401                                               ParseInitializer());
402   }
403 
404   // Handle a C++20 braced designated initialization, which results in
405   // direct-list-initialization of the aggregate element. We allow this as an
406   // extension from C++11 onwards (when direct-list-initialization was added).
407   if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus11) {
408     PreferredType.enterDesignatedInitializer(
409         Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
410     return Actions.ActOnDesignatedInitializer(Desig, SourceLocation(), false,
411                                               ParseBraceInitializer());
412   }
413 
414   // We read some number of designators and found something that isn't an = or
415   // an initializer.  If we have exactly one array designator, this
416   // is the GNU 'designation: array-designator' extension.  Otherwise, it is a
417   // parse error.
418   if (Desig.getNumDesignators() == 1 &&
419       (Desig.getDesignator(0).isArrayDesignator() ||
420        Desig.getDesignator(0).isArrayRangeDesignator())) {
421     Diag(Tok, diag::ext_gnu_missing_equal_designator)
422       << FixItHint::CreateInsertion(Tok.getLocation(), "= ");
423     return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(),
424                                               true, ParseInitializer());
425   }
426 
427   Diag(Tok, diag::err_expected_equal_designator);
428   return ExprError();
429 }
430 
createEmbedExpr()431 ExprResult Parser::createEmbedExpr() {
432   assert(Tok.getKind() == tok::annot_embed);
433   EmbedAnnotationData *Data =
434       reinterpret_cast<EmbedAnnotationData *>(Tok.getAnnotationValue());
435   ExprResult Res;
436   ASTContext &Context = Actions.getASTContext();
437   SourceLocation StartLoc = ConsumeAnnotationToken();
438   if (Data->BinaryData.size() == 1) {
439     Res = IntegerLiteral::Create(Context,
440                                  llvm::APInt(CHAR_BIT, Data->BinaryData.back()),
441                                  Context.UnsignedCharTy, StartLoc);
442   } else {
443     auto CreateStringLiteralFromStringRef = [&](StringRef Str, QualType Ty) {
444       llvm::APSInt ArraySize =
445           Context.MakeIntValue(Str.size(), Context.getSizeType());
446       QualType ArrayTy = Context.getConstantArrayType(
447           Ty, ArraySize, nullptr, ArraySizeModifier::Normal, 0);
448       return StringLiteral::Create(Context, Str, StringLiteralKind::Ordinary,
449                                    false, ArrayTy, StartLoc);
450     };
451 
452     StringLiteral *BinaryDataArg = CreateStringLiteralFromStringRef(
453         Data->BinaryData, Context.UnsignedCharTy);
454     Res = Actions.ActOnEmbedExpr(StartLoc, BinaryDataArg);
455   }
456   return Res;
457 }
458 
459 /// ParseBraceInitializer - Called when parsing an initializer that has a
460 /// leading open brace.
461 ///
462 ///       initializer: [C99 6.7.8]
463 ///         '{' initializer-list '}'
464 ///         '{' initializer-list ',' '}'
465 /// [C23]   '{' '}'
466 ///
467 ///       initializer-list:
468 ///         designation[opt] initializer ...[opt]
469 ///         initializer-list ',' designation[opt] initializer ...[opt]
470 ///
ParseBraceInitializer()471 ExprResult Parser::ParseBraceInitializer() {
472   InMessageExpressionRAIIObject InMessage(*this, false);
473 
474   BalancedDelimiterTracker T(*this, tok::l_brace);
475   T.consumeOpen();
476   SourceLocation LBraceLoc = T.getOpenLocation();
477 
478   /// InitExprs - This is the actual list of expressions contained in the
479   /// initializer.
480   ExprVector InitExprs;
481 
482   if (Tok.is(tok::r_brace)) {
483     // Empty initializers are a C++ feature and a GNU extension to C before C23.
484     if (!getLangOpts().CPlusPlus) {
485       Diag(LBraceLoc, getLangOpts().C23
486                           ? diag::warn_c23_compat_empty_initializer
487                           : diag::ext_c_empty_initializer);
488     }
489     // Match the '}'.
490     return Actions.ActOnInitList(LBraceLoc, std::nullopt, ConsumeBrace());
491   }
492 
493   // Enter an appropriate expression evaluation context for an initializer list.
494   EnterExpressionEvaluationContext EnterContext(
495       Actions, EnterExpressionEvaluationContext::InitList);
496 
497   bool InitExprsOk = true;
498   QualType LikelyType = PreferredType.get(T.getOpenLocation());
499   DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};
500   bool CalledSignatureHelp = false;
501   auto RunSignatureHelp = [&] {
502     QualType PreferredType;
503     if (!LikelyType.isNull())
504       PreferredType = Actions.CodeCompletion().ProduceConstructorSignatureHelp(
505           LikelyType->getCanonicalTypeInternal(), T.getOpenLocation(),
506           InitExprs, T.getOpenLocation(), /*Braced=*/true);
507     CalledSignatureHelp = true;
508     return PreferredType;
509   };
510 
511   while (true) {
512     PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
513 
514     // Handle Microsoft __if_exists/if_not_exists if necessary.
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;
519         ConsumeToken();
520       }
521       if (Tok.is(tok::r_brace)) break;
522       continue;
523     }
524 
525     // Parse: designation[opt] initializer
526 
527     // If we know that this cannot be a designation, just parse the nested
528     // initializer directly.
529     ExprResult SubElt;
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))
538       SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
539 
540     SubElt = Actions.CorrectDelayedTyposInExpr(SubElt.get());
541 
542     // If we couldn't parse the subelement, bail out.
543     if (SubElt.isUsable()) {
544       InitExprs.push_back(SubElt.get());
545     } else {
546       InitExprsOk = false;
547 
548       // We have two ways to try to recover from this error: if the code looks
549       // grammatically ok (i.e. we have a comma coming up) try to continue
550       // parsing the rest of the initializer.  This allows us to emit
551       // diagnostics for later elements that we find.  If we don't see a comma,
552       // assume there is a parse error, and just skip to recover.
553       // FIXME: This comment doesn't sound right. If there is a r_brace
554       // immediately, it can't be an error, since there is no other way of
555       // leaving this loop except through this if.
556       if (Tok.isNot(tok::comma)) {
557         SkipUntil(tok::r_brace, StopBeforeMatch);
558         break;
559       }
560     }
561 
562     // If we don't have a comma continued list, we're done.
563     if (Tok.isNot(tok::comma)) break;
564 
565     // TODO: save comma locations if some client cares.
566     ConsumeToken();
567 
568     // Handle trailing comma.
569     if (Tok.is(tok::r_brace)) break;
570   }
571 
572   bool closed = !T.consumeClose();
573 
574   if (InitExprsOk && closed)
575     return Actions.ActOnInitList(LBraceLoc, InitExprs,
576                                  T.getCloseLocation());
577 
578   return ExprError(); // an error occurred.
579 }
580 
581 
582 // Return true if a comma (or closing brace) is necessary after the
583 // __if_exists/if_not_exists statement.
ParseMicrosoftIfExistsBraceInitializer(ExprVector & InitExprs,bool & InitExprsOk)584 bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
585                                                     bool &InitExprsOk) {
586   bool trailingComma = false;
587   IfExistsCondition Result;
588   if (ParseMicrosoftIfExistsCondition(Result))
589     return false;
590 
591   BalancedDelimiterTracker Braces(*this, tok::l_brace);
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     // Parse the declarations below.
600     break;
601 
602   case IEB_Dependent:
603     Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
604       << Result.IsIfExists;
605     // Fall through to skip.
606     [[fallthrough]];
607 
608   case IEB_Skip:
609     Braces.skipToEnd();
610     return false;
611   }
612 
613   DesignatorCompletionInfo DesignatorCompletion{
614       InitExprs,
615       PreferredType.get(Braces.getOpenLocation()),
616   };
617   while (!isEofOrEom()) {
618     trailingComma = false;
619     // If we know that this cannot be a designation, just parse the nested
620     // initializer directly.
621     ExprResult SubElt;
622     if (MayBeDesignationStart())
623       SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
624     else
625       SubElt = ParseInitializer();
626 
627     if (Tok.is(tok::ellipsis))
628       SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
629 
630     // If we couldn't parse the subelement, bail out.
631     if (!SubElt.isInvalid())
632       InitExprs.push_back(SubElt.get());
633     else
634       InitExprsOk = false;
635 
636     if (Tok.is(tok::comma)) {
637       ConsumeToken();
638       trailingComma = true;
639     }
640 
641     if (Tok.is(tok::r_brace))
642       break;
643   }
644 
645   Braces.consumeClose();
646 
647   return !trailingComma;
648 }
649