ParseInit.cpp revision 198398
1193326Sed//===--- ParseInit.cpp - Initializer Parsing ------------------------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements initializer parsing as specified by C99 6.7.8. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#include "clang/Parse/Designator.h" 15193326Sed#include "clang/Parse/Parser.h" 16193326Sed#include "clang/Parse/ParseDiagnostic.h" 17193326Sed#include "llvm/ADT/SmallString.h" 18198398Srdivacky#include "llvm/Support/raw_ostream.h" 19193326Sedusing namespace clang; 20193326Sed 21193326Sed 22193326Sed/// MayBeDesignationStart - Return true if this token might be the start of a 23193326Sed/// designator. If we can tell it is impossible that it is a designator, return 24198092Srdivacky/// false. 25193326Sedstatic bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) { 26193326Sed switch (K) { 27193326Sed default: return false; 28193326Sed case tok::period: // designator: '.' identifier 29193326Sed case tok::l_square: // designator: array-designator 30193326Sed return true; 31193326Sed case tok::identifier: // designation: identifier ':' 32193326Sed return PP.LookAhead(0).is(tok::colon); 33193326Sed } 34193326Sed} 35193326Sed 36193326Sed/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production 37193326Sed/// checking to see if the token stream starts with a designator. 38193326Sed/// 39193326Sed/// designation: 40193326Sed/// designator-list '=' 41193326Sed/// [GNU] array-designator 42193326Sed/// [GNU] identifier ':' 43193326Sed/// 44193326Sed/// designator-list: 45193326Sed/// designator 46193326Sed/// designator-list designator 47193326Sed/// 48193326Sed/// designator: 49193326Sed/// array-designator 50193326Sed/// '.' identifier 51193326Sed/// 52193326Sed/// array-designator: 53193326Sed/// '[' constant-expression ']' 54193326Sed/// [GNU] '[' constant-expression '...' constant-expression ']' 55193326Sed/// 56193326Sed/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an 57193326Sed/// initializer (because it is an expression). We need to consider this case 58193326Sed/// when parsing array designators. 59193326Sed/// 60193326SedParser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() { 61193326Sed 62193326Sed // If this is the old-style GNU extension: 63193326Sed // designation ::= identifier ':' 64193326Sed // Handle it as a field designator. Otherwise, this must be the start of a 65193326Sed // normal expression. 66193326Sed if (Tok.is(tok::identifier)) { 67193326Sed const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); 68193326Sed 69198398Srdivacky llvm::SmallString<256> NewSyntax; 70198398Srdivacky llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName() 71198398Srdivacky << " = "; 72193326Sed 73193326Sed SourceLocation NameLoc = ConsumeToken(); // Eat the identifier. 74198092Srdivacky 75193326Sed assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); 76193326Sed SourceLocation ColonLoc = ConsumeToken(); 77193326Sed 78193326Sed Diag(Tok, diag::ext_gnu_old_style_field_designator) 79198092Srdivacky << CodeModificationHint::CreateReplacement(SourceRange(NameLoc, 80193326Sed ColonLoc), 81198398Srdivacky NewSyntax.str()); 82193326Sed 83193326Sed Designation D; 84193326Sed D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); 85198092Srdivacky return Actions.ActOnDesignatedInitializer(D, ColonLoc, true, 86193326Sed ParseInitializer()); 87193326Sed } 88198092Srdivacky 89193326Sed // Desig - This is initialized when we see our first designator. We may have 90193326Sed // an objc message send with no designator, so we don't want to create this 91193326Sed // eagerly. 92193326Sed Designation Desig; 93198092Srdivacky 94193326Sed // Parse each designator in the designator list until we find an initializer. 95193326Sed while (Tok.is(tok::period) || Tok.is(tok::l_square)) { 96193326Sed if (Tok.is(tok::period)) { 97193326Sed // designator: '.' identifier 98193326Sed SourceLocation DotLoc = ConsumeToken(); 99198092Srdivacky 100193326Sed if (Tok.isNot(tok::identifier)) { 101193326Sed Diag(Tok.getLocation(), diag::err_expected_field_designator); 102193326Sed return ExprError(); 103193326Sed } 104198092Srdivacky 105193326Sed Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc, 106193326Sed Tok.getLocation())); 107193326Sed ConsumeToken(); // Eat the identifier. 108193326Sed continue; 109193326Sed } 110198092Srdivacky 111193326Sed // We must have either an array designator now or an objc message send. 112193326Sed assert(Tok.is(tok::l_square) && "Unexpected token!"); 113198092Srdivacky 114193326Sed // Handle the two forms of array designator: 115193326Sed // array-designator: '[' constant-expression ']' 116193326Sed // array-designator: '[' constant-expression '...' constant-expression ']' 117193326Sed // 118193326Sed // Also, we have to handle the case where the expression after the 119193326Sed // designator an an objc message send: '[' objc-message-expr ']'. 120193326Sed // Interesting cases are: 121193326Sed // [foo bar] -> objc message send 122193326Sed // [foo] -> array designator 123193326Sed // [foo ... bar] -> array designator 124193326Sed // [4][foo bar] -> obsolete GNU designation with objc message send. 125193326Sed // 126193326Sed SourceLocation StartLoc = ConsumeBracket(); 127198092Srdivacky 128193326Sed // If Objective-C is enabled and this is a typename or other identifier 129193326Sed // receiver, parse this as a message send expression. 130193326Sed if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) { 131193326Sed // If we have exactly one array designator, this used the GNU 132193326Sed // 'designation: array-designator' extension, otherwise there should be no 133193326Sed // designators at all! 134198092Srdivacky if (Desig.getNumDesignators() == 1 && 135193326Sed (Desig.getDesignator(0).isArrayDesignator() || 136193326Sed Desig.getDesignator(0).isArrayRangeDesignator())) 137193326Sed Diag(StartLoc, diag::ext_gnu_missing_equal_designator); 138193326Sed else if (Desig.getNumDesignators() > 0) 139193326Sed Diag(Tok, diag::err_expected_equal_designator); 140193326Sed 141193326Sed IdentifierInfo *Name = Tok.getIdentifierInfo(); 142193326Sed SourceLocation NameLoc = ConsumeToken(); 143193326Sed return ParseAssignmentExprWithObjCMessageExprStart( 144193326Sed StartLoc, NameLoc, Name, ExprArg(Actions)); 145193326Sed } 146193326Sed 147193326Sed // Note that we parse this as an assignment expression, not a constant 148193326Sed // expression (allowing *=, =, etc) to handle the objc case. Sema needs 149193326Sed // to validate that the expression is a constant. 150193326Sed OwningExprResult Idx(ParseAssignmentExpression()); 151193326Sed if (Idx.isInvalid()) { 152193326Sed SkipUntil(tok::r_square); 153193326Sed return move(Idx); 154193326Sed } 155198092Srdivacky 156193326Sed // Given an expression, we could either have a designator (if the next 157193326Sed // tokens are '...' or ']' or an objc message send. If this is an objc 158198092Srdivacky // message send, handle it now. An objc-message send is the start of 159193326Sed // an assignment-expression production. 160198092Srdivacky if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) && 161193326Sed Tok.isNot(tok::r_square)) { 162198092Srdivacky 163193326Sed // If we have exactly one array designator, this used the GNU 164193326Sed // 'designation: array-designator' extension, otherwise there should be no 165193326Sed // designators at all! 166198092Srdivacky if (Desig.getNumDesignators() == 1 && 167193326Sed (Desig.getDesignator(0).isArrayDesignator() || 168193326Sed Desig.getDesignator(0).isArrayRangeDesignator())) 169193326Sed Diag(StartLoc, diag::ext_gnu_missing_equal_designator); 170193326Sed else if (Desig.getNumDesignators() > 0) 171193326Sed Diag(Tok, diag::err_expected_equal_designator); 172193326Sed 173193326Sed return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 174193326Sed SourceLocation(), 175193326Sed 0, move(Idx)); 176193326Sed } 177193326Sed 178193326Sed // If this is a normal array designator, remember it. 179193326Sed if (Tok.isNot(tok::ellipsis)) { 180193326Sed Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc)); 181193326Sed } else { 182193326Sed // Handle the gnu array range extension. 183193326Sed Diag(Tok, diag::ext_gnu_array_range); 184193326Sed SourceLocation EllipsisLoc = ConsumeToken(); 185193326Sed 186193326Sed OwningExprResult RHS(ParseConstantExpression()); 187193326Sed if (RHS.isInvalid()) { 188193326Sed SkipUntil(tok::r_square); 189193326Sed return move(RHS); 190193326Sed } 191193326Sed Desig.AddDesignator(Designator::getArrayRange(Idx.release(), 192193326Sed RHS.release(), 193193326Sed StartLoc, EllipsisLoc)); 194193326Sed } 195193326Sed 196193326Sed SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); 197193326Sed Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(EndLoc); 198193326Sed } 199193326Sed 200193326Sed // Okay, we're done with the designator sequence. We know that there must be 201193326Sed // at least one designator, because the only case we can get into this method 202193326Sed // without a designator is when we have an objc message send. That case is 203193326Sed // handled and returned from above. 204193326Sed assert(!Desig.empty() && "Designator is empty?"); 205193326Sed 206193326Sed // Handle a normal designator sequence end, which is an equal. 207193326Sed if (Tok.is(tok::equal)) { 208193326Sed SourceLocation EqualLoc = ConsumeToken(); 209193326Sed return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false, 210193326Sed ParseInitializer()); 211193326Sed } 212193326Sed 213193326Sed // We read some number of designators and found something that isn't an = or 214193326Sed // an initializer. If we have exactly one array designator, this 215193326Sed // is the GNU 'designation: array-designator' extension. Otherwise, it is a 216193326Sed // parse error. 217198092Srdivacky if (Desig.getNumDesignators() == 1 && 218193326Sed (Desig.getDesignator(0).isArrayDesignator() || 219193326Sed Desig.getDesignator(0).isArrayRangeDesignator())) { 220193326Sed Diag(Tok, diag::ext_gnu_missing_equal_designator) 221193326Sed << CodeModificationHint::CreateInsertion(Tok.getLocation(), "= "); 222193326Sed return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(), 223193326Sed true, ParseInitializer()); 224193326Sed } 225193326Sed 226193326Sed Diag(Tok, diag::err_expected_equal_designator); 227193326Sed return ExprError(); 228193326Sed} 229193326Sed 230193326Sed 231193326Sed/// ParseBraceInitializer - Called when parsing an initializer that has a 232193326Sed/// leading open brace. 233193326Sed/// 234193326Sed/// initializer: [C99 6.7.8] 235193326Sed/// '{' initializer-list '}' 236193326Sed/// '{' initializer-list ',' '}' 237193326Sed/// [GNU] '{' '}' 238193326Sed/// 239193326Sed/// initializer-list: 240193326Sed/// designation[opt] initializer 241193326Sed/// initializer-list ',' designation[opt] initializer 242193326Sed/// 243193326SedParser::OwningExprResult Parser::ParseBraceInitializer() { 244193326Sed SourceLocation LBraceLoc = ConsumeBrace(); 245193326Sed 246193326Sed /// InitExprs - This is the actual list of expressions contained in the 247193326Sed /// initializer. 248193326Sed ExprVector InitExprs(Actions); 249193326Sed 250193326Sed if (Tok.is(tok::r_brace)) { 251193326Sed // Empty initializers are a C++ feature and a GNU extension to C. 252193326Sed if (!getLang().CPlusPlus) 253193326Sed Diag(LBraceLoc, diag::ext_gnu_empty_initializer); 254193326Sed // Match the '}'. 255193326Sed return Actions.ActOnInitList(LBraceLoc, Action::MultiExprArg(Actions), 256193326Sed ConsumeBrace()); 257193326Sed } 258193326Sed 259193326Sed bool InitExprsOk = true; 260193326Sed 261193326Sed while (1) { 262193326Sed // Parse: designation[opt] initializer 263193326Sed 264193326Sed // If we know that this cannot be a designation, just parse the nested 265193326Sed // initializer directly. 266193326Sed OwningExprResult SubElt(Actions); 267193326Sed if (MayBeDesignationStart(Tok.getKind(), PP)) 268193326Sed SubElt = ParseInitializerWithPotentialDesignator(); 269193326Sed else 270193326Sed SubElt = ParseInitializer(); 271198092Srdivacky 272193326Sed // If we couldn't parse the subelement, bail out. 273193326Sed if (!SubElt.isInvalid()) { 274193326Sed InitExprs.push_back(SubElt.release()); 275193326Sed } else { 276193326Sed InitExprsOk = false; 277198092Srdivacky 278193326Sed // We have two ways to try to recover from this error: if the code looks 279193326Sed // gramatically ok (i.e. we have a comma coming up) try to continue 280193326Sed // parsing the rest of the initializer. This allows us to emit 281193326Sed // diagnostics for later elements that we find. If we don't see a comma, 282193326Sed // assume there is a parse error, and just skip to recover. 283193326Sed // FIXME: This comment doesn't sound right. If there is a r_brace 284193326Sed // immediately, it can't be an error, since there is no other way of 285193326Sed // leaving this loop except through this if. 286193326Sed if (Tok.isNot(tok::comma)) { 287193326Sed SkipUntil(tok::r_brace, false, true); 288193326Sed break; 289193326Sed } 290193326Sed } 291193326Sed 292193326Sed // If we don't have a comma continued list, we're done. 293193326Sed if (Tok.isNot(tok::comma)) break; 294193326Sed 295193326Sed // TODO: save comma locations if some client cares. 296193326Sed ConsumeToken(); 297193326Sed 298193326Sed // Handle trailing comma. 299193326Sed if (Tok.is(tok::r_brace)) break; 300193326Sed } 301193326Sed if (InitExprsOk && Tok.is(tok::r_brace)) 302193326Sed return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs), 303193326Sed ConsumeBrace()); 304193326Sed 305193326Sed // Match the '}'. 306193326Sed MatchRHSPunctuation(tok::r_brace, LBraceLoc); 307193326Sed return ExprError(); // an error occurred. 308193326Sed} 309193326Sed 310