1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/Parse/ParseDiagnostic.h" |
14 | #include "clang/Parse/Parser.h" |
15 | #include "clang/Parse/RAIIObjectsForParser.h" |
16 | #include "clang/Sema/Designator.h" |
17 | #include "clang/Sema/Scope.h" |
18 | #include "llvm/ADT/SmallString.h" |
19 | using namespace clang; |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | bool Parser::MayBeDesignationStart() { |
26 | switch (Tok.getKind()) { |
27 | default: |
28 | return false; |
29 | |
30 | case tok::period: |
31 | return true; |
32 | |
33 | case tok::l_square: { |
34 | if (!PP.getLangOpts().CPlusPlus11) |
35 | return true; |
36 | |
37 | |
38 | |
39 | |
40 | switch (PP.LookAhead(0).getKind()) { |
41 | case tok::equal: |
42 | case tok::r_square: |
43 | |
44 | return false; |
45 | |
46 | case tok::amp: |
47 | case tok::kw_this: |
48 | case tok::identifier: |
49 | |
50 | |
51 | break; |
52 | |
53 | default: |
54 | |
55 | |
56 | return true; |
57 | } |
58 | |
59 | |
60 | break; |
61 | } |
62 | case tok::identifier: |
63 | return PP.LookAhead(0).is(tok::colon); |
64 | } |
65 | |
66 | |
67 | |
68 | TentativeParsingAction Tentative(*this); |
69 | |
70 | LambdaIntroducer Intro; |
71 | bool SkippedInits = false; |
72 | Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits)); |
73 | |
74 | if (DiagID) { |
75 | |
76 | Tentative.Revert(); |
77 | return true; |
78 | } |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | tok::TokenKind Kind = Tok.getKind(); |
86 | |
87 | |
88 | Tentative.Revert(); |
89 | return Kind == tok::equal; |
90 | } |
91 | |
92 | static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, |
93 | Designation &Desig) { |
94 | |
95 | |
96 | |
97 | if (Desig.getNumDesignators() == 1 && |
98 | (Desig.getDesignator(0).isArrayDesignator() || |
99 | Desig.getDesignator(0).isArrayRangeDesignator())) |
100 | P.Diag(Loc, diag::ext_gnu_missing_equal_designator); |
101 | else if (Desig.getNumDesignators() > 0) |
102 | P.Diag(Loc, diag::err_expected_equal_designator); |
103 | } |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | ExprResult Parser::ParseInitializerWithPotentialDesignator() { |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | if (Tok.is(tok::identifier)) { |
136 | const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); |
137 | |
138 | SmallString<256> NewSyntax; |
139 | llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName() |
140 | << " = "; |
141 | |
142 | SourceLocation NameLoc = ConsumeToken(); |
143 | |
144 | (0) . __assert_fail ("Tok.is(tok..colon) && \"MayBeDesignationStart not working properly!\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseInit.cpp", 144, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); |
145 | SourceLocation ColonLoc = ConsumeToken(); |
146 | |
147 | Diag(NameLoc, diag::ext_gnu_old_style_field_designator) |
148 | << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc), |
149 | NewSyntax); |
150 | |
151 | Designation D; |
152 | D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); |
153 | return Actions.ActOnDesignatedInitializer(D, ColonLoc, true, |
154 | ParseInitializer()); |
155 | } |
156 | |
157 | |
158 | |
159 | |
160 | Designation Desig; |
161 | |
162 | |
163 | while (Tok.is(tok::period) || Tok.is(tok::l_square)) { |
164 | if (Tok.is(tok::period)) { |
165 | |
166 | SourceLocation DotLoc = ConsumeToken(); |
167 | |
168 | if (Tok.isNot(tok::identifier)) { |
169 | Diag(Tok.getLocation(), diag::err_expected_field_designator); |
170 | return ExprError(); |
171 | } |
172 | |
173 | Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc, |
174 | Tok.getLocation())); |
175 | ConsumeToken(); |
176 | continue; |
177 | } |
178 | |
179 | |
180 | (0) . __assert_fail ("Tok.is(tok..l_square) && \"Unexpected token!\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseInit.cpp", 180, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Tok.is(tok::l_square) && "Unexpected token!"); |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | InMessageExpressionRAIIObject InMessage(*this, true); |
200 | |
201 | BalancedDelimiterTracker T(*this, tok::l_square); |
202 | T.consumeOpen(); |
203 | SourceLocation StartLoc = T.getOpenLocation(); |
204 | |
205 | ExprResult Idx; |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | if (getLangOpts().ObjC && getLangOpts().CPlusPlus) { |
212 | |
213 | if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && |
214 | NextToken().isNot(tok::period) && |
215 | getCurScope()->isInObjcMethodScope()) { |
216 | CheckArrayDesignatorSyntax(*this, StartLoc, Desig); |
217 | return ParseAssignmentExprWithObjCMessageExprStart( |
218 | StartLoc, ConsumeToken(), nullptr, nullptr); |
219 | } |
220 | |
221 | |
222 | bool IsExpr; |
223 | void *TypeOrExpr; |
224 | if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { |
225 | SkipUntil(tok::r_square, StopAtSemi); |
226 | return ExprError(); |
227 | } |
228 | |
229 | |
230 | |
231 | if (!IsExpr) { |
232 | CheckArrayDesignatorSyntax(*this, StartLoc, Desig); |
233 | return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, |
234 | SourceLocation(), |
235 | ParsedType::getFromOpaquePtr(TypeOrExpr), |
236 | nullptr); |
237 | } |
238 | |
239 | |
240 | |
241 | |
242 | |
243 | Idx = ExprResult(static_cast<Expr*>(TypeOrExpr)); |
244 | } else if (getLangOpts().ObjC && Tok.is(tok::identifier)) { |
245 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
246 | SourceLocation IILoc = Tok.getLocation(); |
247 | ParsedType ReceiverType; |
248 | |
249 | |
250 | |
251 | switch (Actions.getObjCMessageKind( |
252 | getCurScope(), II, IILoc, II == Ident_super, |
253 | NextToken().is(tok::period), ReceiverType)) { |
254 | case Sema::ObjCSuperMessage: |
255 | CheckArrayDesignatorSyntax(*this, StartLoc, Desig); |
256 | return ParseAssignmentExprWithObjCMessageExprStart( |
257 | StartLoc, ConsumeToken(), nullptr, nullptr); |
258 | |
259 | case Sema::ObjCClassMessage: |
260 | CheckArrayDesignatorSyntax(*this, StartLoc, Desig); |
261 | ConsumeToken(); |
262 | if (!ReceiverType) { |
263 | SkipUntil(tok::r_square, StopAtSemi); |
264 | return ExprError(); |
265 | } |
266 | |
267 | |
268 | if (Tok.is(tok::less)) { |
269 | SourceLocation NewEndLoc; |
270 | TypeResult NewReceiverType |
271 | = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType, |
272 | , |
273 | NewEndLoc); |
274 | if (!NewReceiverType.isUsable()) { |
275 | SkipUntil(tok::r_square, StopAtSemi); |
276 | return ExprError(); |
277 | } |
278 | |
279 | ReceiverType = NewReceiverType.get(); |
280 | } |
281 | |
282 | return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, |
283 | SourceLocation(), |
284 | ReceiverType, |
285 | nullptr); |
286 | |
287 | case Sema::ObjCInstanceMessage: |
288 | |
289 | |
290 | |
291 | break; |
292 | } |
293 | } |
294 | |
295 | |
296 | |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | if (!Idx.get()) { |
303 | Idx = ParseAssignmentExpression(); |
304 | if (Idx.isInvalid()) { |
305 | SkipUntil(tok::r_square, StopAtSemi); |
306 | return Idx; |
307 | } |
308 | } |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | if (getLangOpts().ObjC && Tok.isNot(tok::ellipsis) && |
315 | Tok.isNot(tok::r_square)) { |
316 | CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig); |
317 | return ParseAssignmentExprWithObjCMessageExprStart( |
318 | StartLoc, SourceLocation(), nullptr, Idx.get()); |
319 | } |
320 | |
321 | |
322 | if (Tok.isNot(tok::ellipsis)) { |
323 | Desig.AddDesignator(Designator::getArray(Idx.get(), StartLoc)); |
324 | } else { |
325 | |
326 | Diag(Tok, diag::ext_gnu_array_range); |
327 | SourceLocation EllipsisLoc = ConsumeToken(); |
328 | |
329 | ExprResult RHS(ParseConstantExpression()); |
330 | if (RHS.isInvalid()) { |
331 | SkipUntil(tok::r_square, StopAtSemi); |
332 | return RHS; |
333 | } |
334 | Desig.AddDesignator(Designator::getArrayRange(Idx.get(), |
335 | RHS.get(), |
336 | StartLoc, EllipsisLoc)); |
337 | } |
338 | |
339 | T.consumeClose(); |
340 | Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc( |
341 | T.getCloseLocation()); |
342 | } |
343 | |
344 | |
345 | |
346 | |
347 | |
348 | (0) . __assert_fail ("!Desig.empty() && \"Designator is empty?\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseInit.cpp", 348, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Desig.empty() && "Designator is empty?"); |
349 | |
350 | |
351 | if (Tok.is(tok::equal)) { |
352 | SourceLocation EqualLoc = ConsumeToken(); |
353 | return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false, |
354 | ParseInitializer()); |
355 | } |
356 | |
357 | |
358 | |
359 | |
360 | |
361 | if (Desig.getNumDesignators() == 1 && |
362 | (Desig.getDesignator(0).isArrayDesignator() || |
363 | Desig.getDesignator(0).isArrayRangeDesignator())) { |
364 | Diag(Tok, diag::ext_gnu_missing_equal_designator) |
365 | << FixItHint::CreateInsertion(Tok.getLocation(), "= "); |
366 | return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(), |
367 | true, ParseInitializer()); |
368 | } |
369 | |
370 | Diag(Tok, diag::err_expected_equal_designator); |
371 | return ExprError(); |
372 | } |
373 | |
374 | |
375 | |
376 | |
377 | |
378 | |
379 | |
380 | |
381 | |
382 | |
383 | |
384 | |
385 | |
386 | |
387 | ExprResult Parser::ParseBraceInitializer() { |
388 | InMessageExpressionRAIIObject InMessage(*this, false); |
389 | |
390 | BalancedDelimiterTracker T(*this, tok::l_brace); |
391 | T.consumeOpen(); |
392 | SourceLocation LBraceLoc = T.getOpenLocation(); |
393 | |
394 | |
395 | |
396 | ExprVector InitExprs; |
397 | |
398 | if (Tok.is(tok::r_brace)) { |
399 | |
400 | if (!getLangOpts().CPlusPlus) |
401 | Diag(LBraceLoc, diag::ext_gnu_empty_initializer); |
402 | |
403 | return Actions.ActOnInitList(LBraceLoc, None, ConsumeBrace()); |
404 | } |
405 | |
406 | |
407 | EnterExpressionEvaluationContext EnterContext( |
408 | Actions, EnterExpressionEvaluationContext::InitList); |
409 | |
410 | bool InitExprsOk = true; |
411 | |
412 | while (1) { |
413 | |
414 | if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || |
415 | Tok.is(tok::kw___if_not_exists))) { |
416 | if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) { |
417 | if (Tok.isNot(tok::comma)) break; |
418 | ConsumeToken(); |
419 | } |
420 | if (Tok.is(tok::r_brace)) break; |
421 | continue; |
422 | } |
423 | |
424 | |
425 | |
426 | |
427 | |
428 | ExprResult SubElt; |
429 | if (MayBeDesignationStart()) |
430 | SubElt = ParseInitializerWithPotentialDesignator(); |
431 | else |
432 | SubElt = ParseInitializer(); |
433 | |
434 | if (Tok.is(tok::ellipsis)) |
435 | SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken()); |
436 | |
437 | SubElt = Actions.CorrectDelayedTyposInExpr(SubElt.get()); |
438 | |
439 | |
440 | if (SubElt.isUsable()) { |
441 | InitExprs.push_back(SubElt.get()); |
442 | } else { |
443 | InitExprsOk = false; |
444 | |
445 | |
446 | |
447 | |
448 | |
449 | |
450 | |
451 | |
452 | |
453 | if (Tok.isNot(tok::comma)) { |
454 | SkipUntil(tok::r_brace, StopBeforeMatch); |
455 | break; |
456 | } |
457 | } |
458 | |
459 | |
460 | if (Tok.isNot(tok::comma)) break; |
461 | |
462 | |
463 | ConsumeToken(); |
464 | |
465 | |
466 | if (Tok.is(tok::r_brace)) break; |
467 | } |
468 | |
469 | bool closed = !T.consumeClose(); |
470 | |
471 | if (InitExprsOk && closed) |
472 | return Actions.ActOnInitList(LBraceLoc, InitExprs, |
473 | T.getCloseLocation()); |
474 | |
475 | return ExprError(); |
476 | } |
477 | |
478 | |
479 | |
480 | |
481 | bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, |
482 | bool &InitExprsOk) { |
483 | bool trailingComma = false; |
484 | IfExistsCondition Result; |
485 | if (ParseMicrosoftIfExistsCondition(Result)) |
486 | return false; |
487 | |
488 | BalancedDelimiterTracker Braces(*this, tok::l_brace); |
489 | if (Braces.consumeOpen()) { |
490 | Diag(Tok, diag::err_expected) << tok::l_brace; |
491 | return false; |
492 | } |
493 | |
494 | switch (Result.Behavior) { |
495 | case IEB_Parse: |
496 | |
497 | break; |
498 | |
499 | case IEB_Dependent: |
500 | Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) |
501 | << Result.IsIfExists; |
502 | |
503 | LLVM_FALLTHROUGH; |
504 | |
505 | case IEB_Skip: |
506 | Braces.skipToEnd(); |
507 | return false; |
508 | } |
509 | |
510 | while (!isEofOrEom()) { |
511 | trailingComma = false; |
512 | |
513 | |
514 | ExprResult SubElt; |
515 | if (MayBeDesignationStart()) |
516 | SubElt = ParseInitializerWithPotentialDesignator(); |
517 | else |
518 | SubElt = ParseInitializer(); |
519 | |
520 | if (Tok.is(tok::ellipsis)) |
521 | SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken()); |
522 | |
523 | |
524 | if (!SubElt.isInvalid()) |
525 | InitExprs.push_back(SubElt.get()); |
526 | else |
527 | InitExprsOk = false; |
528 | |
529 | if (Tok.is(tok::comma)) { |
530 | ConsumeToken(); |
531 | trailingComma = true; |
532 | } |
533 | |
534 | if (Tok.is(tok::r_brace)) |
535 | break; |
536 | } |
537 | |
538 | Braces.consumeClose(); |
539 | |
540 | return !trailingComma; |
541 | } |
542 | |