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