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