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