ParseInit.cpp revision 2f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96
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 "AstGuard.h"
17#include "clang/Basic/Diagnostic.h"
18#include "llvm/ADT/SmallString.h"
19using namespace clang;
20
21
22/// MayBeDesignationStart - Return true if this token might be the start of a
23/// designator.  If we can tell it is impossible that it is a designator, return
24/// false.
25static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) {
26  switch (K) {
27  default: return false;
28  case tok::period:      // designator: '.' identifier
29  case tok::l_square:    // designator: array-designator
30      return true;
31  case tok::identifier:  // designation: identifier ':'
32    return PP.LookAhead(0).is(tok::colon);
33  }
34}
35
36/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production
37/// checking to see if the token stream starts with a designator.
38///
39///       designation:
40///         designator-list '='
41/// [GNU]   array-designator
42/// [GNU]   identifier ':'
43///
44///       designator-list:
45///         designator
46///         designator-list designator
47///
48///       designator:
49///         array-designator
50///         '.' identifier
51///
52///       array-designator:
53///         '[' constant-expression ']'
54/// [GNU]   '[' constant-expression '...' constant-expression ']'
55///
56/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an
57/// initializer (because it is an expression).  We need to consider this case
58/// when parsing array designators.
59///
60Parser::ExprResult Parser::
61ParseInitializerWithPotentialDesignator(InitListDesignations &Designations,
62                                        unsigned InitNum) {
63
64  // If this is the old-style GNU extension:
65  //   designation ::= identifier ':'
66  // Handle it as a field designator.  Otherwise, this must be the start of a
67  // normal expression.
68  if (Tok.is(tok::identifier)) {
69    Diag(Tok, diag::ext_gnu_old_style_field_designator);
70
71    Designation &D = Designations.CreateDesignation(InitNum);
72    D.AddDesignator(Designator::getField(Tok.getIdentifierInfo()));
73    ConsumeToken(); // Eat the identifier.
74
75    assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
76    ConsumeToken();
77    return ParseInitializer();
78  }
79
80  // Desig - This is initialized when we see our first designator.  We may have
81  // an objc message send with no designator, so we don't want to create this
82  // eagerly.
83  Designation *Desig = 0;
84
85  // Parse each designator in the designator list until we find an initializer.
86  while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
87    if (Tok.is(tok::period)) {
88      // designator: '.' identifier
89      ConsumeToken();
90
91      // Create designation if we haven't already.
92      if (Desig == 0)
93        Desig = &Designations.CreateDesignation(InitNum);
94
95      if (Tok.isNot(tok::identifier)) {
96        Diag(Tok.getLocation(), diag::err_expected_field_designator);
97        return ExprResult(true);
98      }
99
100      Desig->AddDesignator(Designator::getField(Tok.getIdentifierInfo()));
101      ConsumeToken(); // Eat the identifier.
102      continue;
103    }
104
105    // We must have either an array designator now or an objc message send.
106    assert(Tok.is(tok::l_square) && "Unexpected token!");
107
108    // Handle the two forms of array designator:
109    //   array-designator: '[' constant-expression ']'
110    //   array-designator: '[' constant-expression '...' constant-expression ']'
111    //
112    // Also, we have to handle the case where the expression after the
113    // designator an an objc message send: '[' objc-message-expr ']'.
114    // Interesting cases are:
115    //   [foo bar]         -> objc message send
116    //   [foo]             -> array designator
117    //   [foo ... bar]     -> array designator
118    //   [4][foo bar]      -> obsolete GNU designation with objc message send.
119    //
120    SourceLocation StartLoc = ConsumeBracket();
121
122    // If Objective-C is enabled and this is a typename or other identifier
123    // receiver, parse this as a message send expression.
124    if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) {
125      // If we have exactly one array designator, this used the GNU
126      // 'designation: array-designator' extension, otherwise there should be no
127      // designators at all!
128      if (Desig) {
129        if (Desig->getNumDesignators() == 1 &&
130            (Desig->getDesignator(0).isArrayDesignator() ||
131             Desig->getDesignator(0).isArrayRangeDesignator()))
132          Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
133        else
134          Diag(Tok, diag::err_expected_equal_designator);
135      }
136
137      IdentifierInfo *Name = Tok.getIdentifierInfo();
138      SourceLocation NameLoc = ConsumeToken();
139      return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, NameLoc,
140                                                         Name, 0);
141    }
142
143    // Note that we parse this as an assignment expression, not a constant
144    // expression (allowing *=, =, etc) to handle the objc case.  Sema needs
145    // to validate that the expression is a constant.
146    OwningExprResult Idx(ParseAssignmentExpression());
147    if (Idx.isInvalid()) {
148      SkipUntil(tok::r_square);
149      return Idx.result();
150    }
151
152    // Given an expression, we could either have a designator (if the next
153    // tokens are '...' or ']' or an objc message send.  If this is an objc
154    // message send, handle it now.  An objc-message send is the start of
155    // an assignment-expression production.
156    if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) &&
157        Tok.isNot(tok::r_square)) {
158
159      // If we have exactly one array designator, this used the GNU
160      // 'designation: array-designator' extension, otherwise there should be no
161      // designators at all!
162      if (Desig) {
163        if (Desig->getNumDesignators() == 1 &&
164            (Desig->getDesignator(0).isArrayDesignator() ||
165             Desig->getDesignator(0).isArrayRangeDesignator()))
166          Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
167        else
168          Diag(Tok, diag::err_expected_equal_designator);
169      }
170
171      return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
172                                                         SourceLocation(),
173                                                         0, Idx.release());
174    }
175
176    // Create designation if we haven't already.
177    if (Desig == 0)
178      Desig = &Designations.CreateDesignation(InitNum);
179
180    // If this is a normal array designator, remember it.
181    if (Tok.isNot(tok::ellipsis)) {
182      Desig->AddDesignator(Designator::getArray(Idx.release()));
183    } else {
184      // Handle the gnu array range extension.
185      Diag(Tok, diag::ext_gnu_array_range);
186      ConsumeToken();
187
188      OwningExprResult RHS(ParseConstantExpression());
189      if (RHS.isInvalid()) {
190        SkipUntil(tok::r_square);
191        return RHS.result();
192      }
193      Desig->AddDesignator(Designator::getArrayRange(Idx.release(),
194                                                     RHS.release()));
195    }
196
197    MatchRHSPunctuation(tok::r_square, StartLoc);
198  }
199
200  // Okay, we're done with the designator sequence.  We know that there must be
201  // at least one designator, because the only case we can get into this method
202  // without a designator is when we have an objc message send.  That case is
203  // handled and returned from above.
204  assert(Desig && "Designator didn't get created?");
205
206  // Handle a normal designator sequence end, which is an equal.
207  if (Tok.is(tok::equal)) {
208    ConsumeToken();
209    return ParseInitializer();
210  }
211
212  // We read some number of designators and found something that isn't an = or
213  // an initializer.  If we have exactly one array designator, this
214  // is the GNU 'designation: array-designator' extension.  Otherwise, it is a
215  // parse error.
216  if (Desig->getNumDesignators() == 1 &&
217      (Desig->getDesignator(0).isArrayDesignator() ||
218       Desig->getDesignator(0).isArrayRangeDesignator())) {
219    Diag(Tok, diag::ext_gnu_missing_equal_designator);
220    return ParseInitializer();
221  }
222
223  Diag(Tok, diag::err_expected_equal_designator);
224  return true;
225}
226
227
228/// ParseBraceInitializer - Called when parsing an initializer that has a
229/// leading open brace.
230///
231///       initializer: [C99 6.7.8]
232///         '{' initializer-list '}'
233///         '{' initializer-list ',' '}'
234/// [GNU]   '{' '}'
235///
236///       initializer-list:
237///         designation[opt] initializer
238///         initializer-list ',' designation[opt] initializer
239///
240Parser::ExprResult Parser::ParseBraceInitializer() {
241  SourceLocation LBraceLoc = ConsumeBrace();
242
243  /// InitExprs - This is the actual list of expressions contained in the
244  /// initializer.
245  ExprVector InitExprs(Actions);
246
247  /// ExprDesignators - For each initializer, keep track of the designator that
248  /// was specified for it, if any.
249  InitListDesignations InitExprDesignations(Actions);
250
251  // We support empty initializers, but tell the user that they aren't using
252  // C99-clean code.
253  if (Tok.is(tok::r_brace)) {
254    Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
255    // Match the '}'.
256    return Actions.ActOnInitList(LBraceLoc, 0, 0, InitExprDesignations,
257                                 ConsumeBrace());
258  }
259
260  bool InitExprsOk = true;
261
262  while (1) {
263    // Parse: designation[opt] initializer
264
265    // If we know that this cannot be a designation, just parse the nested
266    // initializer directly.
267    OwningExprResult SubElt(Actions);
268    if (!MayBeDesignationStart(Tok.getKind(), PP))
269      SubElt = ParseInitializer();
270    else {
271      SubElt = ParseInitializerWithPotentialDesignator(InitExprDesignations,
272                                                       InitExprs.size());
273
274      // If we had an erroneous initializer, and we had a potentially valid
275      // designator, make sure to remove the designator from
276      // InitExprDesignations, otherwise we'll end up with a designator with no
277      // making initializer.
278      if (SubElt.isInvalid())
279        InitExprDesignations.EraseDesignation(InitExprs.size());
280    }
281
282    // If we couldn't parse the subelement, bail out.
283    if (!SubElt.isInvalid()) {
284      InitExprs.push_back(SubElt.release());
285    } else {
286      InitExprsOk = false;
287
288      // We have two ways to try to recover from this error: if the code looks
289      // gramatically ok (i.e. we have a comma coming up) try to continue
290      // parsing the rest of the initializer.  This allows us to emit
291      // diagnostics for later elements that we find.  If we don't see a comma,
292      // assume there is a parse error, and just skip to recover.
293      // FIXME: This comment doesn't sound right. If there is a r_brace
294      // immediately, it can't be an error, since there is no other way of
295      // leaving this loop except through this if.
296      if (Tok.isNot(tok::comma)) {
297        SkipUntil(tok::r_brace, false, true);
298        break;
299      }
300    }
301
302    // If we don't have a comma continued list, we're done.
303    if (Tok.isNot(tok::comma)) break;
304
305    // TODO: save comma locations if some client cares.
306    ConsumeToken();
307
308    // Handle trailing comma.
309    if (Tok.is(tok::r_brace)) break;
310  }
311  if (InitExprsOk && Tok.is(tok::r_brace))
312    return Actions.ActOnInitList(LBraceLoc, InitExprs.take(), InitExprs.size(),
313                                 InitExprDesignations, ConsumeBrace());
314
315  // Match the '}'.
316  MatchRHSPunctuation(tok::r_brace, LBraceLoc);
317  return ExprResult(true); // an error occurred.
318}
319
320