xref: /minix3/external/bsd/llvm/dist/clang/lib/Parse/ParseInit.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- ParseInit.cpp - Initializer Parsing ------------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements initializer parsing as specified by C99 6.7.8.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "clang/Parse/Parser.h"
15f4a2713aSLionel Sambuc #include "RAIIObjectsForParser.h"
16f4a2713aSLionel Sambuc #include "clang/Parse/ParseDiagnostic.h"
17f4a2713aSLionel Sambuc #include "clang/Sema/Designator.h"
18f4a2713aSLionel Sambuc #include "clang/Sema/Scope.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
20f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
21f4a2713aSLionel Sambuc using namespace clang;
22f4a2713aSLionel Sambuc 
23f4a2713aSLionel Sambuc 
24f4a2713aSLionel Sambuc /// MayBeDesignationStart - Return true if the current token might be the start
25f4a2713aSLionel Sambuc /// of a designator.  If we can tell it is impossible that it is a designator,
26f4a2713aSLionel Sambuc /// return false.
MayBeDesignationStart()27f4a2713aSLionel Sambuc bool Parser::MayBeDesignationStart() {
28f4a2713aSLionel Sambuc   switch (Tok.getKind()) {
29f4a2713aSLionel Sambuc   default:
30f4a2713aSLionel Sambuc     return false;
31f4a2713aSLionel Sambuc 
32f4a2713aSLionel Sambuc   case tok::period:      // designator: '.' identifier
33f4a2713aSLionel Sambuc     return true;
34f4a2713aSLionel Sambuc 
35f4a2713aSLionel Sambuc   case tok::l_square: {  // designator: array-designator
36f4a2713aSLionel Sambuc     if (!PP.getLangOpts().CPlusPlus11)
37f4a2713aSLionel Sambuc       return true;
38f4a2713aSLionel Sambuc 
39f4a2713aSLionel Sambuc     // C++11 lambda expressions and C99 designators can be ambiguous all the
40f4a2713aSLionel Sambuc     // way through the closing ']' and to the next character. Handle the easy
41f4a2713aSLionel Sambuc     // cases here, and fall back to tentative parsing if those fail.
42f4a2713aSLionel Sambuc     switch (PP.LookAhead(0).getKind()) {
43f4a2713aSLionel Sambuc     case tok::equal:
44f4a2713aSLionel Sambuc     case tok::r_square:
45f4a2713aSLionel Sambuc       // Definitely starts a lambda expression.
46f4a2713aSLionel Sambuc       return false;
47f4a2713aSLionel Sambuc 
48f4a2713aSLionel Sambuc     case tok::amp:
49f4a2713aSLionel Sambuc     case tok::kw_this:
50f4a2713aSLionel Sambuc     case tok::identifier:
51f4a2713aSLionel Sambuc       // We have to do additional analysis, because these could be the
52f4a2713aSLionel Sambuc       // start of a constant expression or a lambda capture list.
53f4a2713aSLionel Sambuc       break;
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc     default:
56f4a2713aSLionel Sambuc       // Anything not mentioned above cannot occur following a '[' in a
57f4a2713aSLionel Sambuc       // lambda expression.
58f4a2713aSLionel Sambuc       return true;
59f4a2713aSLionel Sambuc     }
60f4a2713aSLionel Sambuc 
61f4a2713aSLionel Sambuc     // Handle the complicated case below.
62f4a2713aSLionel Sambuc     break;
63f4a2713aSLionel Sambuc   }
64f4a2713aSLionel Sambuc   case tok::identifier:  // designation: identifier ':'
65f4a2713aSLionel Sambuc     return PP.LookAhead(0).is(tok::colon);
66f4a2713aSLionel Sambuc   }
67f4a2713aSLionel Sambuc 
68f4a2713aSLionel Sambuc   // Parse up to (at most) the token after the closing ']' to determine
69*0a6a1f1dSLionel Sambuc   // whether this is a C99 designator or a lambda.
70f4a2713aSLionel Sambuc   TentativeParsingAction Tentative(*this);
71f4a2713aSLionel Sambuc 
72*0a6a1f1dSLionel Sambuc   LambdaIntroducer Intro;
73*0a6a1f1dSLionel Sambuc   bool SkippedInits = false;
74*0a6a1f1dSLionel Sambuc   Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits));
75*0a6a1f1dSLionel Sambuc 
76*0a6a1f1dSLionel Sambuc   if (DiagID) {
77*0a6a1f1dSLionel Sambuc     // If this can't be a lambda capture list, it's a designator.
78f4a2713aSLionel Sambuc     Tentative.Revert();
79*0a6a1f1dSLionel Sambuc     return true;
80*0a6a1f1dSLionel Sambuc   }
81f4a2713aSLionel Sambuc 
82f4a2713aSLionel Sambuc   // Once we hit the closing square bracket, we look at the next
83f4a2713aSLionel Sambuc   // token. If it's an '=', this is a designator. Otherwise, it's a
84f4a2713aSLionel Sambuc   // lambda expression. This decision favors lambdas over the older
85f4a2713aSLionel Sambuc   // GNU designator syntax, which allows one to omit the '=', but is
86f4a2713aSLionel Sambuc   // consistent with GCC.
87f4a2713aSLionel Sambuc   tok::TokenKind Kind = Tok.getKind();
88*0a6a1f1dSLionel Sambuc   // FIXME: If we didn't skip any inits, parse the lambda from here
89*0a6a1f1dSLionel Sambuc   // rather than throwing away then reparsing the LambdaIntroducer.
90f4a2713aSLionel Sambuc   Tentative.Revert();
91f4a2713aSLionel Sambuc   return Kind == tok::equal;
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc 
CheckArrayDesignatorSyntax(Parser & P,SourceLocation Loc,Designation & Desig)94f4a2713aSLionel Sambuc static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
95f4a2713aSLionel Sambuc                                        Designation &Desig) {
96f4a2713aSLionel Sambuc   // If we have exactly one array designator, this used the GNU
97f4a2713aSLionel Sambuc   // 'designation: array-designator' extension, otherwise there should be no
98f4a2713aSLionel Sambuc   // designators at all!
99f4a2713aSLionel Sambuc   if (Desig.getNumDesignators() == 1 &&
100f4a2713aSLionel Sambuc       (Desig.getDesignator(0).isArrayDesignator() ||
101f4a2713aSLionel Sambuc        Desig.getDesignator(0).isArrayRangeDesignator()))
102f4a2713aSLionel Sambuc     P.Diag(Loc, diag::ext_gnu_missing_equal_designator);
103f4a2713aSLionel Sambuc   else if (Desig.getNumDesignators() > 0)
104f4a2713aSLionel Sambuc     P.Diag(Loc, diag::err_expected_equal_designator);
105f4a2713aSLionel Sambuc }
106f4a2713aSLionel Sambuc 
107f4a2713aSLionel Sambuc /// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production
108f4a2713aSLionel Sambuc /// checking to see if the token stream starts with a designator.
109f4a2713aSLionel Sambuc ///
110f4a2713aSLionel Sambuc ///       designation:
111f4a2713aSLionel Sambuc ///         designator-list '='
112f4a2713aSLionel Sambuc /// [GNU]   array-designator
113f4a2713aSLionel Sambuc /// [GNU]   identifier ':'
114f4a2713aSLionel Sambuc ///
115f4a2713aSLionel Sambuc ///       designator-list:
116f4a2713aSLionel Sambuc ///         designator
117f4a2713aSLionel Sambuc ///         designator-list designator
118f4a2713aSLionel Sambuc ///
119f4a2713aSLionel Sambuc ///       designator:
120f4a2713aSLionel Sambuc ///         array-designator
121f4a2713aSLionel Sambuc ///         '.' identifier
122f4a2713aSLionel Sambuc ///
123f4a2713aSLionel Sambuc ///       array-designator:
124f4a2713aSLionel Sambuc ///         '[' constant-expression ']'
125f4a2713aSLionel Sambuc /// [GNU]   '[' constant-expression '...' constant-expression ']'
126f4a2713aSLionel Sambuc ///
127f4a2713aSLionel Sambuc /// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an
128f4a2713aSLionel Sambuc /// initializer (because it is an expression).  We need to consider this case
129f4a2713aSLionel Sambuc /// when parsing array designators.
130f4a2713aSLionel Sambuc ///
ParseInitializerWithPotentialDesignator()131f4a2713aSLionel Sambuc ExprResult Parser::ParseInitializerWithPotentialDesignator() {
132f4a2713aSLionel Sambuc 
133f4a2713aSLionel Sambuc   // If this is the old-style GNU extension:
134f4a2713aSLionel Sambuc   //   designation ::= identifier ':'
135f4a2713aSLionel Sambuc   // Handle it as a field designator.  Otherwise, this must be the start of a
136f4a2713aSLionel Sambuc   // normal expression.
137f4a2713aSLionel Sambuc   if (Tok.is(tok::identifier)) {
138f4a2713aSLionel Sambuc     const IdentifierInfo *FieldName = Tok.getIdentifierInfo();
139f4a2713aSLionel Sambuc 
140f4a2713aSLionel Sambuc     SmallString<256> NewSyntax;
141f4a2713aSLionel Sambuc     llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
142f4a2713aSLionel Sambuc                                          << " = ";
143f4a2713aSLionel Sambuc 
144f4a2713aSLionel Sambuc     SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
145f4a2713aSLionel Sambuc 
146f4a2713aSLionel Sambuc     assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
147f4a2713aSLionel Sambuc     SourceLocation ColonLoc = ConsumeToken();
148f4a2713aSLionel Sambuc 
149f4a2713aSLionel Sambuc     Diag(NameLoc, diag::ext_gnu_old_style_field_designator)
150f4a2713aSLionel Sambuc       << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
151f4a2713aSLionel Sambuc                                       NewSyntax.str());
152f4a2713aSLionel Sambuc 
153f4a2713aSLionel Sambuc     Designation D;
154f4a2713aSLionel Sambuc     D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
155f4a2713aSLionel Sambuc     return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
156f4a2713aSLionel Sambuc                                               ParseInitializer());
157f4a2713aSLionel Sambuc   }
158f4a2713aSLionel Sambuc 
159f4a2713aSLionel Sambuc   // Desig - This is initialized when we see our first designator.  We may have
160f4a2713aSLionel Sambuc   // an objc message send with no designator, so we don't want to create this
161f4a2713aSLionel Sambuc   // eagerly.
162f4a2713aSLionel Sambuc   Designation Desig;
163f4a2713aSLionel Sambuc 
164f4a2713aSLionel Sambuc   // Parse each designator in the designator list until we find an initializer.
165f4a2713aSLionel Sambuc   while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
166f4a2713aSLionel Sambuc     if (Tok.is(tok::period)) {
167f4a2713aSLionel Sambuc       // designator: '.' identifier
168f4a2713aSLionel Sambuc       SourceLocation DotLoc = ConsumeToken();
169f4a2713aSLionel Sambuc 
170f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
171f4a2713aSLionel Sambuc         Diag(Tok.getLocation(), diag::err_expected_field_designator);
172f4a2713aSLionel Sambuc         return ExprError();
173f4a2713aSLionel Sambuc       }
174f4a2713aSLionel Sambuc 
175f4a2713aSLionel Sambuc       Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc,
176f4a2713aSLionel Sambuc                                                Tok.getLocation()));
177f4a2713aSLionel Sambuc       ConsumeToken(); // Eat the identifier.
178f4a2713aSLionel Sambuc       continue;
179f4a2713aSLionel Sambuc     }
180f4a2713aSLionel Sambuc 
181f4a2713aSLionel Sambuc     // We must have either an array designator now or an objc message send.
182f4a2713aSLionel Sambuc     assert(Tok.is(tok::l_square) && "Unexpected token!");
183f4a2713aSLionel Sambuc 
184f4a2713aSLionel Sambuc     // Handle the two forms of array designator:
185f4a2713aSLionel Sambuc     //   array-designator: '[' constant-expression ']'
186f4a2713aSLionel Sambuc     //   array-designator: '[' constant-expression '...' constant-expression ']'
187f4a2713aSLionel Sambuc     //
188f4a2713aSLionel Sambuc     // Also, we have to handle the case where the expression after the
189f4a2713aSLionel Sambuc     // designator an an objc message send: '[' objc-message-expr ']'.
190f4a2713aSLionel Sambuc     // Interesting cases are:
191f4a2713aSLionel Sambuc     //   [foo bar]         -> objc message send
192f4a2713aSLionel Sambuc     //   [foo]             -> array designator
193f4a2713aSLionel Sambuc     //   [foo ... bar]     -> array designator
194f4a2713aSLionel Sambuc     //   [4][foo bar]      -> obsolete GNU designation with objc message send.
195f4a2713aSLionel Sambuc     //
196f4a2713aSLionel Sambuc     // We do not need to check for an expression starting with [[ here. If it
197f4a2713aSLionel Sambuc     // contains an Objective-C message send, then it is not an ill-formed
198f4a2713aSLionel Sambuc     // attribute. If it is a lambda-expression within an array-designator, then
199f4a2713aSLionel Sambuc     // it will be rejected because a constant-expression cannot begin with a
200f4a2713aSLionel Sambuc     // lambda-expression.
201f4a2713aSLionel Sambuc     InMessageExpressionRAIIObject InMessage(*this, true);
202f4a2713aSLionel Sambuc 
203f4a2713aSLionel Sambuc     BalancedDelimiterTracker T(*this, tok::l_square);
204f4a2713aSLionel Sambuc     T.consumeOpen();
205f4a2713aSLionel Sambuc     SourceLocation StartLoc = T.getOpenLocation();
206f4a2713aSLionel Sambuc 
207f4a2713aSLionel Sambuc     ExprResult Idx;
208f4a2713aSLionel Sambuc 
209f4a2713aSLionel Sambuc     // If Objective-C is enabled and this is a typename (class message
210f4a2713aSLionel Sambuc     // send) or send to 'super', parse this as a message send
211f4a2713aSLionel Sambuc     // expression.  We handle C++ and C separately, since C++ requires
212f4a2713aSLionel Sambuc     // much more complicated parsing.
213f4a2713aSLionel Sambuc     if  (getLangOpts().ObjC1 && getLangOpts().CPlusPlus) {
214f4a2713aSLionel Sambuc       // Send to 'super'.
215f4a2713aSLionel Sambuc       if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
216f4a2713aSLionel Sambuc           NextToken().isNot(tok::period) &&
217f4a2713aSLionel Sambuc           getCurScope()->isInObjcMethodScope()) {
218f4a2713aSLionel Sambuc         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
219f4a2713aSLionel Sambuc         return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
220f4a2713aSLionel Sambuc                                                            ConsumeToken(),
221f4a2713aSLionel Sambuc                                                            ParsedType(),
222*0a6a1f1dSLionel Sambuc                                                            nullptr);
223f4a2713aSLionel Sambuc       }
224f4a2713aSLionel Sambuc 
225f4a2713aSLionel Sambuc       // Parse the receiver, which is either a type or an expression.
226f4a2713aSLionel Sambuc       bool IsExpr;
227f4a2713aSLionel Sambuc       void *TypeOrExpr;
228f4a2713aSLionel Sambuc       if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
229f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
230f4a2713aSLionel Sambuc         return ExprError();
231f4a2713aSLionel Sambuc       }
232f4a2713aSLionel Sambuc 
233f4a2713aSLionel Sambuc       // If the receiver was a type, we have a class message; parse
234f4a2713aSLionel Sambuc       // the rest of it.
235f4a2713aSLionel Sambuc       if (!IsExpr) {
236f4a2713aSLionel Sambuc         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
237f4a2713aSLionel Sambuc         return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
238f4a2713aSLionel Sambuc                                                            SourceLocation(),
239f4a2713aSLionel Sambuc                                    ParsedType::getFromOpaquePtr(TypeOrExpr),
240*0a6a1f1dSLionel Sambuc                                                            nullptr);
241f4a2713aSLionel Sambuc       }
242f4a2713aSLionel Sambuc 
243f4a2713aSLionel Sambuc       // If the receiver was an expression, we still don't know
244f4a2713aSLionel Sambuc       // whether we have a message send or an array designator; just
245f4a2713aSLionel Sambuc       // adopt the expression for further analysis below.
246f4a2713aSLionel Sambuc       // FIXME: potentially-potentially evaluated expression above?
247f4a2713aSLionel Sambuc       Idx = ExprResult(static_cast<Expr*>(TypeOrExpr));
248f4a2713aSLionel Sambuc     } else if (getLangOpts().ObjC1 && Tok.is(tok::identifier)) {
249f4a2713aSLionel Sambuc       IdentifierInfo *II = Tok.getIdentifierInfo();
250f4a2713aSLionel Sambuc       SourceLocation IILoc = Tok.getLocation();
251f4a2713aSLionel Sambuc       ParsedType ReceiverType;
252f4a2713aSLionel Sambuc       // Three cases. This is a message send to a type: [type foo]
253f4a2713aSLionel Sambuc       // This is a message send to super:  [super foo]
254f4a2713aSLionel Sambuc       // This is a message sent to an expr:  [super.bar foo]
255f4a2713aSLionel Sambuc       switch (Sema::ObjCMessageKind Kind
256f4a2713aSLionel Sambuc                 = Actions.getObjCMessageKind(getCurScope(), II, IILoc,
257f4a2713aSLionel Sambuc                                              II == Ident_super,
258f4a2713aSLionel Sambuc                                              NextToken().is(tok::period),
259f4a2713aSLionel Sambuc                                              ReceiverType)) {
260f4a2713aSLionel Sambuc       case Sema::ObjCSuperMessage:
261f4a2713aSLionel Sambuc       case Sema::ObjCClassMessage:
262f4a2713aSLionel Sambuc         CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
263f4a2713aSLionel Sambuc         if (Kind == Sema::ObjCSuperMessage)
264f4a2713aSLionel Sambuc           return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
265f4a2713aSLionel Sambuc                                                              ConsumeToken(),
266f4a2713aSLionel Sambuc                                                              ParsedType(),
267*0a6a1f1dSLionel Sambuc                                                              nullptr);
268f4a2713aSLionel Sambuc         ConsumeToken(); // the identifier
269f4a2713aSLionel Sambuc         if (!ReceiverType) {
270f4a2713aSLionel Sambuc           SkipUntil(tok::r_square, StopAtSemi);
271f4a2713aSLionel Sambuc           return ExprError();
272f4a2713aSLionel Sambuc         }
273f4a2713aSLionel Sambuc 
274f4a2713aSLionel Sambuc         return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
275f4a2713aSLionel Sambuc                                                            SourceLocation(),
276f4a2713aSLionel Sambuc                                                            ReceiverType,
277*0a6a1f1dSLionel Sambuc                                                            nullptr);
278f4a2713aSLionel Sambuc 
279f4a2713aSLionel Sambuc       case Sema::ObjCInstanceMessage:
280f4a2713aSLionel Sambuc         // Fall through; we'll just parse the expression and
281f4a2713aSLionel Sambuc         // (possibly) treat this like an Objective-C message send
282f4a2713aSLionel Sambuc         // later.
283f4a2713aSLionel Sambuc         break;
284f4a2713aSLionel Sambuc       }
285f4a2713aSLionel Sambuc     }
286f4a2713aSLionel Sambuc 
287f4a2713aSLionel Sambuc     // Parse the index expression, if we haven't already gotten one
288f4a2713aSLionel Sambuc     // above (which can only happen in Objective-C++).
289f4a2713aSLionel Sambuc     // Note that we parse this as an assignment expression, not a constant
290f4a2713aSLionel Sambuc     // expression (allowing *=, =, etc) to handle the objc case.  Sema needs
291f4a2713aSLionel Sambuc     // to validate that the expression is a constant.
292f4a2713aSLionel Sambuc     // FIXME: We also need to tell Sema that we're in a
293f4a2713aSLionel Sambuc     // potentially-potentially evaluated context.
294f4a2713aSLionel Sambuc     if (!Idx.get()) {
295f4a2713aSLionel Sambuc       Idx = ParseAssignmentExpression();
296f4a2713aSLionel Sambuc       if (Idx.isInvalid()) {
297f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
298f4a2713aSLionel Sambuc         return Idx;
299f4a2713aSLionel Sambuc       }
300f4a2713aSLionel Sambuc     }
301f4a2713aSLionel Sambuc 
302f4a2713aSLionel Sambuc     // Given an expression, we could either have a designator (if the next
303f4a2713aSLionel Sambuc     // tokens are '...' or ']' or an objc message send.  If this is an objc
304f4a2713aSLionel Sambuc     // message send, handle it now.  An objc-message send is the start of
305f4a2713aSLionel Sambuc     // an assignment-expression production.
306f4a2713aSLionel Sambuc     if (getLangOpts().ObjC1 && Tok.isNot(tok::ellipsis) &&
307f4a2713aSLionel Sambuc         Tok.isNot(tok::r_square)) {
308f4a2713aSLionel Sambuc       CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);
309f4a2713aSLionel Sambuc       return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
310f4a2713aSLionel Sambuc                                                          SourceLocation(),
311f4a2713aSLionel Sambuc                                                          ParsedType(),
312*0a6a1f1dSLionel Sambuc                                                          Idx.get());
313f4a2713aSLionel Sambuc     }
314f4a2713aSLionel Sambuc 
315f4a2713aSLionel Sambuc     // If this is a normal array designator, remember it.
316f4a2713aSLionel Sambuc     if (Tok.isNot(tok::ellipsis)) {
317*0a6a1f1dSLionel Sambuc       Desig.AddDesignator(Designator::getArray(Idx.get(), StartLoc));
318f4a2713aSLionel Sambuc     } else {
319f4a2713aSLionel Sambuc       // Handle the gnu array range extension.
320f4a2713aSLionel Sambuc       Diag(Tok, diag::ext_gnu_array_range);
321f4a2713aSLionel Sambuc       SourceLocation EllipsisLoc = ConsumeToken();
322f4a2713aSLionel Sambuc 
323f4a2713aSLionel Sambuc       ExprResult RHS(ParseConstantExpression());
324f4a2713aSLionel Sambuc       if (RHS.isInvalid()) {
325f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
326f4a2713aSLionel Sambuc         return RHS;
327f4a2713aSLionel Sambuc       }
328*0a6a1f1dSLionel Sambuc       Desig.AddDesignator(Designator::getArrayRange(Idx.get(),
329*0a6a1f1dSLionel Sambuc                                                     RHS.get(),
330f4a2713aSLionel Sambuc                                                     StartLoc, EllipsisLoc));
331f4a2713aSLionel Sambuc     }
332f4a2713aSLionel Sambuc 
333f4a2713aSLionel Sambuc     T.consumeClose();
334f4a2713aSLionel Sambuc     Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(
335f4a2713aSLionel Sambuc                                                         T.getCloseLocation());
336f4a2713aSLionel Sambuc   }
337f4a2713aSLionel Sambuc 
338f4a2713aSLionel Sambuc   // Okay, we're done with the designator sequence.  We know that there must be
339f4a2713aSLionel Sambuc   // at least one designator, because the only case we can get into this method
340f4a2713aSLionel Sambuc   // without a designator is when we have an objc message send.  That case is
341f4a2713aSLionel Sambuc   // handled and returned from above.
342f4a2713aSLionel Sambuc   assert(!Desig.empty() && "Designator is empty?");
343f4a2713aSLionel Sambuc 
344f4a2713aSLionel Sambuc   // Handle a normal designator sequence end, which is an equal.
345f4a2713aSLionel Sambuc   if (Tok.is(tok::equal)) {
346f4a2713aSLionel Sambuc     SourceLocation EqualLoc = ConsumeToken();
347f4a2713aSLionel Sambuc     return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,
348f4a2713aSLionel Sambuc                                               ParseInitializer());
349f4a2713aSLionel Sambuc   }
350f4a2713aSLionel Sambuc 
351f4a2713aSLionel Sambuc   // We read some number of designators and found something that isn't an = or
352f4a2713aSLionel Sambuc   // an initializer.  If we have exactly one array designator, this
353f4a2713aSLionel Sambuc   // is the GNU 'designation: array-designator' extension.  Otherwise, it is a
354f4a2713aSLionel Sambuc   // parse error.
355f4a2713aSLionel Sambuc   if (Desig.getNumDesignators() == 1 &&
356f4a2713aSLionel Sambuc       (Desig.getDesignator(0).isArrayDesignator() ||
357f4a2713aSLionel Sambuc        Desig.getDesignator(0).isArrayRangeDesignator())) {
358f4a2713aSLionel Sambuc     Diag(Tok, diag::ext_gnu_missing_equal_designator)
359f4a2713aSLionel Sambuc       << FixItHint::CreateInsertion(Tok.getLocation(), "= ");
360f4a2713aSLionel Sambuc     return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(),
361f4a2713aSLionel Sambuc                                               true, ParseInitializer());
362f4a2713aSLionel Sambuc   }
363f4a2713aSLionel Sambuc 
364f4a2713aSLionel Sambuc   Diag(Tok, diag::err_expected_equal_designator);
365f4a2713aSLionel Sambuc   return ExprError();
366f4a2713aSLionel Sambuc }
367f4a2713aSLionel Sambuc 
368f4a2713aSLionel Sambuc 
369f4a2713aSLionel Sambuc /// ParseBraceInitializer - Called when parsing an initializer that has a
370f4a2713aSLionel Sambuc /// leading open brace.
371f4a2713aSLionel Sambuc ///
372f4a2713aSLionel Sambuc ///       initializer: [C99 6.7.8]
373f4a2713aSLionel Sambuc ///         '{' initializer-list '}'
374f4a2713aSLionel Sambuc ///         '{' initializer-list ',' '}'
375f4a2713aSLionel Sambuc /// [GNU]   '{' '}'
376f4a2713aSLionel Sambuc ///
377f4a2713aSLionel Sambuc ///       initializer-list:
378f4a2713aSLionel Sambuc ///         designation[opt] initializer ...[opt]
379f4a2713aSLionel Sambuc ///         initializer-list ',' designation[opt] initializer ...[opt]
380f4a2713aSLionel Sambuc ///
ParseBraceInitializer()381f4a2713aSLionel Sambuc ExprResult Parser::ParseBraceInitializer() {
382f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, false);
383f4a2713aSLionel Sambuc 
384f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_brace);
385f4a2713aSLionel Sambuc   T.consumeOpen();
386f4a2713aSLionel Sambuc   SourceLocation LBraceLoc = T.getOpenLocation();
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc   /// InitExprs - This is the actual list of expressions contained in the
389f4a2713aSLionel Sambuc   /// initializer.
390f4a2713aSLionel Sambuc   ExprVector InitExprs;
391f4a2713aSLionel Sambuc 
392f4a2713aSLionel Sambuc   if (Tok.is(tok::r_brace)) {
393f4a2713aSLionel Sambuc     // Empty initializers are a C++ feature and a GNU extension to C.
394f4a2713aSLionel Sambuc     if (!getLangOpts().CPlusPlus)
395f4a2713aSLionel Sambuc       Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
396f4a2713aSLionel Sambuc     // Match the '}'.
397f4a2713aSLionel Sambuc     return Actions.ActOnInitList(LBraceLoc, None, ConsumeBrace());
398f4a2713aSLionel Sambuc   }
399f4a2713aSLionel Sambuc 
400f4a2713aSLionel Sambuc   bool InitExprsOk = true;
401f4a2713aSLionel Sambuc 
402f4a2713aSLionel Sambuc   while (1) {
403f4a2713aSLionel Sambuc     // Handle Microsoft __if_exists/if_not_exists if necessary.
404f4a2713aSLionel Sambuc     if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
405f4a2713aSLionel Sambuc         Tok.is(tok::kw___if_not_exists))) {
406f4a2713aSLionel Sambuc       if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {
407f4a2713aSLionel Sambuc         if (Tok.isNot(tok::comma)) break;
408f4a2713aSLionel Sambuc         ConsumeToken();
409f4a2713aSLionel Sambuc       }
410f4a2713aSLionel Sambuc       if (Tok.is(tok::r_brace)) break;
411f4a2713aSLionel Sambuc       continue;
412f4a2713aSLionel Sambuc     }
413f4a2713aSLionel Sambuc 
414f4a2713aSLionel Sambuc     // Parse: designation[opt] initializer
415f4a2713aSLionel Sambuc 
416f4a2713aSLionel Sambuc     // If we know that this cannot be a designation, just parse the nested
417f4a2713aSLionel Sambuc     // initializer directly.
418f4a2713aSLionel Sambuc     ExprResult SubElt;
419f4a2713aSLionel Sambuc     if (MayBeDesignationStart())
420f4a2713aSLionel Sambuc       SubElt = ParseInitializerWithPotentialDesignator();
421f4a2713aSLionel Sambuc     else
422f4a2713aSLionel Sambuc       SubElt = ParseInitializer();
423f4a2713aSLionel Sambuc 
424f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis))
425f4a2713aSLionel Sambuc       SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
426f4a2713aSLionel Sambuc 
427*0a6a1f1dSLionel Sambuc     SubElt = Actions.CorrectDelayedTyposInExpr(SubElt.get());
428*0a6a1f1dSLionel Sambuc 
429f4a2713aSLionel Sambuc     // If we couldn't parse the subelement, bail out.
430*0a6a1f1dSLionel Sambuc     if (SubElt.isUsable()) {
431*0a6a1f1dSLionel Sambuc       InitExprs.push_back(SubElt.get());
432f4a2713aSLionel Sambuc     } else {
433f4a2713aSLionel Sambuc       InitExprsOk = false;
434f4a2713aSLionel Sambuc 
435f4a2713aSLionel Sambuc       // We have two ways to try to recover from this error: if the code looks
436f4a2713aSLionel Sambuc       // grammatically ok (i.e. we have a comma coming up) try to continue
437f4a2713aSLionel Sambuc       // parsing the rest of the initializer.  This allows us to emit
438f4a2713aSLionel Sambuc       // diagnostics for later elements that we find.  If we don't see a comma,
439f4a2713aSLionel Sambuc       // assume there is a parse error, and just skip to recover.
440f4a2713aSLionel Sambuc       // FIXME: This comment doesn't sound right. If there is a r_brace
441f4a2713aSLionel Sambuc       // immediately, it can't be an error, since there is no other way of
442f4a2713aSLionel Sambuc       // leaving this loop except through this if.
443f4a2713aSLionel Sambuc       if (Tok.isNot(tok::comma)) {
444f4a2713aSLionel Sambuc         SkipUntil(tok::r_brace, StopBeforeMatch);
445f4a2713aSLionel Sambuc         break;
446f4a2713aSLionel Sambuc       }
447f4a2713aSLionel Sambuc     }
448f4a2713aSLionel Sambuc 
449f4a2713aSLionel Sambuc     // If we don't have a comma continued list, we're done.
450f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma)) break;
451f4a2713aSLionel Sambuc 
452f4a2713aSLionel Sambuc     // TODO: save comma locations if some client cares.
453f4a2713aSLionel Sambuc     ConsumeToken();
454f4a2713aSLionel Sambuc 
455f4a2713aSLionel Sambuc     // Handle trailing comma.
456f4a2713aSLionel Sambuc     if (Tok.is(tok::r_brace)) break;
457f4a2713aSLionel Sambuc   }
458f4a2713aSLionel Sambuc 
459f4a2713aSLionel Sambuc   bool closed = !T.consumeClose();
460f4a2713aSLionel Sambuc 
461f4a2713aSLionel Sambuc   if (InitExprsOk && closed)
462f4a2713aSLionel Sambuc     return Actions.ActOnInitList(LBraceLoc, InitExprs,
463f4a2713aSLionel Sambuc                                  T.getCloseLocation());
464f4a2713aSLionel Sambuc 
465f4a2713aSLionel Sambuc   return ExprError(); // an error occurred.
466f4a2713aSLionel Sambuc }
467f4a2713aSLionel Sambuc 
468f4a2713aSLionel Sambuc 
469f4a2713aSLionel Sambuc // Return true if a comma (or closing brace) is necessary after the
470f4a2713aSLionel Sambuc // __if_exists/if_not_exists statement.
ParseMicrosoftIfExistsBraceInitializer(ExprVector & InitExprs,bool & InitExprsOk)471f4a2713aSLionel Sambuc bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
472f4a2713aSLionel Sambuc                                                     bool &InitExprsOk) {
473f4a2713aSLionel Sambuc   bool trailingComma = false;
474f4a2713aSLionel Sambuc   IfExistsCondition Result;
475f4a2713aSLionel Sambuc   if (ParseMicrosoftIfExistsCondition(Result))
476f4a2713aSLionel Sambuc     return false;
477f4a2713aSLionel Sambuc 
478f4a2713aSLionel Sambuc   BalancedDelimiterTracker Braces(*this, tok::l_brace);
479f4a2713aSLionel Sambuc   if (Braces.consumeOpen()) {
480*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::l_brace;
481f4a2713aSLionel Sambuc     return false;
482f4a2713aSLionel Sambuc   }
483f4a2713aSLionel Sambuc 
484f4a2713aSLionel Sambuc   switch (Result.Behavior) {
485f4a2713aSLionel Sambuc   case IEB_Parse:
486f4a2713aSLionel Sambuc     // Parse the declarations below.
487f4a2713aSLionel Sambuc     break;
488f4a2713aSLionel Sambuc 
489f4a2713aSLionel Sambuc   case IEB_Dependent:
490f4a2713aSLionel Sambuc     Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
491f4a2713aSLionel Sambuc       << Result.IsIfExists;
492f4a2713aSLionel Sambuc     // Fall through to skip.
493f4a2713aSLionel Sambuc 
494f4a2713aSLionel Sambuc   case IEB_Skip:
495f4a2713aSLionel Sambuc     Braces.skipToEnd();
496f4a2713aSLionel Sambuc     return false;
497f4a2713aSLionel Sambuc   }
498f4a2713aSLionel Sambuc 
499*0a6a1f1dSLionel Sambuc   while (!isEofOrEom()) {
500f4a2713aSLionel Sambuc     trailingComma = false;
501f4a2713aSLionel Sambuc     // If we know that this cannot be a designation, just parse the nested
502f4a2713aSLionel Sambuc     // initializer directly.
503f4a2713aSLionel Sambuc     ExprResult SubElt;
504f4a2713aSLionel Sambuc     if (MayBeDesignationStart())
505f4a2713aSLionel Sambuc       SubElt = ParseInitializerWithPotentialDesignator();
506f4a2713aSLionel Sambuc     else
507f4a2713aSLionel Sambuc       SubElt = ParseInitializer();
508f4a2713aSLionel Sambuc 
509f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis))
510f4a2713aSLionel Sambuc       SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
511f4a2713aSLionel Sambuc 
512f4a2713aSLionel Sambuc     // If we couldn't parse the subelement, bail out.
513f4a2713aSLionel Sambuc     if (!SubElt.isInvalid())
514*0a6a1f1dSLionel Sambuc       InitExprs.push_back(SubElt.get());
515f4a2713aSLionel Sambuc     else
516f4a2713aSLionel Sambuc       InitExprsOk = false;
517f4a2713aSLionel Sambuc 
518f4a2713aSLionel Sambuc     if (Tok.is(tok::comma)) {
519f4a2713aSLionel Sambuc       ConsumeToken();
520f4a2713aSLionel Sambuc       trailingComma = true;
521f4a2713aSLionel Sambuc     }
522f4a2713aSLionel Sambuc 
523f4a2713aSLionel Sambuc     if (Tok.is(tok::r_brace))
524f4a2713aSLionel Sambuc       break;
525f4a2713aSLionel Sambuc   }
526f4a2713aSLionel Sambuc 
527f4a2713aSLionel Sambuc   Braces.consumeClose();
528f4a2713aSLionel Sambuc 
529f4a2713aSLionel Sambuc   return !trailingComma;
530f4a2713aSLionel Sambuc }
531