ParseInit.cpp revision 207619
1//===--- ParseInit.cpp - Initializer Parsing ------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements initializer parsing as specified by C99 6.7.8.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Designator.h"
15#include "clang/Parse/Parser.h"
16#include "clang/Parse/ParseDiagnostic.h"
17#include "clang/Parse/Scope.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/Support/raw_ostream.h"
20using namespace clang;
21
22
23/// MayBeDesignationStart - Return true if this token might be the start of a
24/// designator.  If we can tell it is impossible that it is a designator, return
25/// false.
26static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) {
27  switch (K) {
28  default: return false;
29  case tok::period:      // designator: '.' identifier
30  case tok::l_square:    // designator: array-designator
31      return true;
32  case tok::identifier:  // designation: identifier ':'
33    return PP.LookAhead(0).is(tok::colon);
34  }
35}
36
37static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
38                                       Designation &Desig) {
39  // If we have exactly one array designator, this used the GNU
40  // 'designation: array-designator' extension, otherwise there should be no
41  // designators at all!
42  if (Desig.getNumDesignators() == 1 &&
43      (Desig.getDesignator(0).isArrayDesignator() ||
44       Desig.getDesignator(0).isArrayRangeDesignator()))
45    P.Diag(Loc, diag::ext_gnu_missing_equal_designator);
46  else if (Desig.getNumDesignators() > 0)
47    P.Diag(Loc, diag::err_expected_equal_designator);
48}
49
50/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production
51/// checking to see if the token stream starts with a designator.
52///
53///       designation:
54///         designator-list '='
55/// [GNU]   array-designator
56/// [GNU]   identifier ':'
57///
58///       designator-list:
59///         designator
60///         designator-list designator
61///
62///       designator:
63///         array-designator
64///         '.' identifier
65///
66///       array-designator:
67///         '[' constant-expression ']'
68/// [GNU]   '[' constant-expression '...' constant-expression ']'
69///
70/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an
71/// initializer (because it is an expression).  We need to consider this case
72/// when parsing array designators.
73///
74Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
75
76  // If this is the old-style GNU extension:
77  //   designation ::= identifier ':'
78  // Handle it as a field designator.  Otherwise, this must be the start of a
79  // normal expression.
80  if (Tok.is(tok::identifier)) {
81    const IdentifierInfo *FieldName = Tok.getIdentifierInfo();
82
83    llvm::SmallString<256> NewSyntax;
84    llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
85                                         << " = ";
86
87    SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
88
89    assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
90    SourceLocation ColonLoc = ConsumeToken();
91
92    Diag(Tok, diag::ext_gnu_old_style_field_designator)
93      << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc),
94                                      NewSyntax.str());
95
96    Designation D;
97    D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
98    return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
99                                              ParseInitializer());
100  }
101
102  // Desig - This is initialized when we see our first designator.  We may have
103  // an objc message send with no designator, so we don't want to create this
104  // eagerly.
105  Designation Desig;
106
107  // Parse each designator in the designator list until we find an initializer.
108  while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
109    if (Tok.is(tok::period)) {
110      // designator: '.' identifier
111      SourceLocation DotLoc = ConsumeToken();
112
113      if (Tok.isNot(tok::identifier)) {
114        Diag(Tok.getLocation(), diag::err_expected_field_designator);
115        return ExprError();
116      }
117
118      Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc,
119                                               Tok.getLocation()));
120      ConsumeToken(); // Eat the identifier.
121      continue;
122    }
123
124    // We must have either an array designator now or an objc message send.
125    assert(Tok.is(tok::l_square) && "Unexpected token!");
126
127    // Handle the two forms of array designator:
128    //   array-designator: '[' constant-expression ']'
129    //   array-designator: '[' constant-expression '...' constant-expression ']'
130    //
131    // Also, we have to handle the case where the expression after the
132    // designator an an objc message send: '[' objc-message-expr ']'.
133    // Interesting cases are:
134    //   [foo bar]         -> objc message send
135    //   [foo]             -> array designator
136    //   [foo ... bar]     -> array designator
137    //   [4][foo bar]      -> obsolete GNU designation with objc message send.
138    //
139    SourceLocation StartLoc = ConsumeBracket();
140    OwningExprResult Idx(Actions);
141
142    // If Objective-C is enabled and this is a typename (class message
143    // send) or send to 'super', parse this as a message send
144    // expression.  We handle C++ and C separately, since C++ requires
145    // much more complicated parsing.
146    if  (getLang().ObjC1 && getLang().CPlusPlus) {
147      // Send to 'super'.
148      if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
149          NextToken().isNot(tok::period) && CurScope->isInObjcMethodScope()) {
150        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
151        return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
152                                                           ConsumeToken(), 0,
153                                                           ExprArg(Actions));
154      }
155
156      // Parse the receiver, which is either a type or an expression.
157      bool IsExpr;
158      void *TypeOrExpr;
159      if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
160        SkipUntil(tok::r_square);
161        return ExprError();
162      }
163
164      // If the receiver was a type, we have a class message; parse
165      // the rest of it.
166      if (!IsExpr) {
167        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
168        return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
169                                                           SourceLocation(),
170                                                           TypeOrExpr,
171                                                           ExprArg(Actions));
172      }
173
174      // If the receiver was an expression, we still don't know
175      // whether we have a message send or an array designator; just
176      // adopt the expression for further analysis below.
177      // FIXME: potentially-potentially evaluated expression above?
178      Idx = OwningExprResult(Actions, TypeOrExpr);
179    } else if (getLang().ObjC1 && Tok.is(tok::identifier)) {
180      IdentifierInfo *II = Tok.getIdentifierInfo();
181      SourceLocation IILoc = Tok.getLocation();
182      TypeTy *ReceiverType;
183      // Three cases. This is a message send to a type: [type foo]
184      // This is a message send to super:  [super foo]
185      // This is a message sent to an expr:  [super.bar foo]
186      switch (Action::ObjCMessageKind Kind
187                = Actions.getObjCMessageKind(CurScope, II, IILoc,
188                                             II == Ident_super,
189                                             NextToken().is(tok::period),
190                                             ReceiverType)) {
191      case Action::ObjCSuperMessage:
192      case Action::ObjCClassMessage:
193        CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
194        if (Kind == Action::ObjCSuperMessage)
195          return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
196                                                             ConsumeToken(),
197                                                             0,
198                                                             ExprArg(Actions));
199        ConsumeToken(); // the identifier
200        if (!ReceiverType) {
201          SkipUntil(tok::r_square);
202          return ExprError();
203        }
204
205        return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
206                                                           SourceLocation(),
207                                                           ReceiverType,
208                                                           ExprArg(Actions));
209
210      case Action::ObjCInstanceMessage:
211        // Fall through; we'll just parse the expression and
212        // (possibly) treat this like an Objective-C message send
213        // later.
214        break;
215      }
216    }
217
218    // Parse the index expression, if we haven't already gotten one
219    // above (which can only happen in Objective-C++).
220    // Note that we parse this as an assignment expression, not a constant
221    // expression (allowing *=, =, etc) to handle the objc case.  Sema needs
222    // to validate that the expression is a constant.
223    // FIXME: We also need to tell Sema that we're in a
224    // potentially-potentially evaluated context.
225    if (!Idx.get()) {
226      Idx = ParseAssignmentExpression();
227      if (Idx.isInvalid()) {
228        SkipUntil(tok::r_square);
229        return move(Idx);
230      }
231    }
232
233    // Given an expression, we could either have a designator (if the next
234    // tokens are '...' or ']' or an objc message send.  If this is an objc
235    // message send, handle it now.  An objc-message send is the start of
236    // an assignment-expression production.
237    if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) &&
238        Tok.isNot(tok::r_square)) {
239      CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);
240      return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
241                                                         SourceLocation(),
242                                                         0, move(Idx));
243    }
244
245    // If this is a normal array designator, remember it.
246    if (Tok.isNot(tok::ellipsis)) {
247      Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc));
248    } else {
249      // Handle the gnu array range extension.
250      Diag(Tok, diag::ext_gnu_array_range);
251      SourceLocation EllipsisLoc = ConsumeToken();
252
253      OwningExprResult RHS(ParseConstantExpression());
254      if (RHS.isInvalid()) {
255        SkipUntil(tok::r_square);
256        return move(RHS);
257      }
258      Desig.AddDesignator(Designator::getArrayRange(Idx.release(),
259                                                    RHS.release(),
260                                                    StartLoc, EllipsisLoc));
261    }
262
263    SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
264    Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(EndLoc);
265  }
266
267  // Okay, we're done with the designator sequence.  We know that there must be
268  // at least one designator, because the only case we can get into this method
269  // without a designator is when we have an objc message send.  That case is
270  // handled and returned from above.
271  assert(!Desig.empty() && "Designator is empty?");
272
273  // Handle a normal designator sequence end, which is an equal.
274  if (Tok.is(tok::equal)) {
275    SourceLocation EqualLoc = ConsumeToken();
276    return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,
277                                              ParseInitializer());
278  }
279
280  // We read some number of designators and found something that isn't an = or
281  // an initializer.  If we have exactly one array designator, this
282  // is the GNU 'designation: array-designator' extension.  Otherwise, it is a
283  // parse error.
284  if (Desig.getNumDesignators() == 1 &&
285      (Desig.getDesignator(0).isArrayDesignator() ||
286       Desig.getDesignator(0).isArrayRangeDesignator())) {
287    Diag(Tok, diag::ext_gnu_missing_equal_designator)
288      << FixItHint::CreateInsertion(Tok.getLocation(), "= ");
289    return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(),
290                                              true, ParseInitializer());
291  }
292
293  Diag(Tok, diag::err_expected_equal_designator);
294  return ExprError();
295}
296
297
298/// ParseBraceInitializer - Called when parsing an initializer that has a
299/// leading open brace.
300///
301///       initializer: [C99 6.7.8]
302///         '{' initializer-list '}'
303///         '{' initializer-list ',' '}'
304/// [GNU]   '{' '}'
305///
306///       initializer-list:
307///         designation[opt] initializer
308///         initializer-list ',' designation[opt] initializer
309///
310Parser::OwningExprResult Parser::ParseBraceInitializer() {
311  SourceLocation LBraceLoc = ConsumeBrace();
312
313  /// InitExprs - This is the actual list of expressions contained in the
314  /// initializer.
315  ExprVector InitExprs(Actions);
316
317  if (Tok.is(tok::r_brace)) {
318    // Empty initializers are a C++ feature and a GNU extension to C.
319    if (!getLang().CPlusPlus)
320      Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
321    // Match the '}'.
322    return Actions.ActOnInitList(LBraceLoc, Action::MultiExprArg(Actions),
323                                 ConsumeBrace());
324  }
325
326  bool InitExprsOk = true;
327
328  while (1) {
329    // Parse: designation[opt] initializer
330
331    // If we know that this cannot be a designation, just parse the nested
332    // initializer directly.
333    OwningExprResult SubElt(Actions);
334    if (MayBeDesignationStart(Tok.getKind(), PP))
335      SubElt = ParseInitializerWithPotentialDesignator();
336    else
337      SubElt = ParseInitializer();
338
339    // If we couldn't parse the subelement, bail out.
340    if (!SubElt.isInvalid()) {
341      InitExprs.push_back(SubElt.release());
342    } else {
343      InitExprsOk = false;
344
345      // We have two ways to try to recover from this error: if the code looks
346      // gramatically ok (i.e. we have a comma coming up) try to continue
347      // parsing the rest of the initializer.  This allows us to emit
348      // diagnostics for later elements that we find.  If we don't see a comma,
349      // assume there is a parse error, and just skip to recover.
350      // FIXME: This comment doesn't sound right. If there is a r_brace
351      // immediately, it can't be an error, since there is no other way of
352      // leaving this loop except through this if.
353      if (Tok.isNot(tok::comma)) {
354        SkipUntil(tok::r_brace, false, true);
355        break;
356      }
357    }
358
359    // If we don't have a comma continued list, we're done.
360    if (Tok.isNot(tok::comma)) break;
361
362    // TODO: save comma locations if some client cares.
363    ConsumeToken();
364
365    // Handle trailing comma.
366    if (Tok.is(tok::r_brace)) break;
367  }
368  if (InitExprsOk && Tok.is(tok::r_brace))
369    return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs),
370                                 ConsumeBrace());
371
372  // Match the '}'.
373  MatchRHSPunctuation(tok::r_brace, LBraceLoc);
374  return ExprError(); // an error occurred.
375}
376
377