/src/llvm-project/clang/lib/Parse/ParseDecl.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements the Declaration portions of the Parser interfaces. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/AST/ASTContext.h" |
14 | | #include "clang/AST/DeclTemplate.h" |
15 | | #include "clang/AST/PrettyDeclStackTrace.h" |
16 | | #include "clang/Basic/AddressSpaces.h" |
17 | | #include "clang/Basic/AttributeCommonInfo.h" |
18 | | #include "clang/Basic/Attributes.h" |
19 | | #include "clang/Basic/CharInfo.h" |
20 | | #include "clang/Basic/TargetInfo.h" |
21 | | #include "clang/Basic/TokenKinds.h" |
22 | | #include "clang/Parse/ParseDiagnostic.h" |
23 | | #include "clang/Parse/Parser.h" |
24 | | #include "clang/Parse/RAIIObjectsForParser.h" |
25 | | #include "clang/Sema/EnterExpressionEvaluationContext.h" |
26 | | #include "clang/Sema/Lookup.h" |
27 | | #include "clang/Sema/ParsedTemplate.h" |
28 | | #include "clang/Sema/Scope.h" |
29 | | #include "clang/Sema/SemaDiagnostic.h" |
30 | | #include "llvm/ADT/SmallSet.h" |
31 | | #include "llvm/ADT/SmallString.h" |
32 | | #include "llvm/ADT/StringSwitch.h" |
33 | | #include <optional> |
34 | | |
35 | | using namespace clang; |
36 | | |
37 | | //===----------------------------------------------------------------------===// |
38 | | // C99 6.7: Declarations. |
39 | | //===----------------------------------------------------------------------===// |
40 | | |
41 | | /// ParseTypeName |
42 | | /// type-name: [C99 6.7.6] |
43 | | /// specifier-qualifier-list abstract-declarator[opt] |
44 | | /// |
45 | | /// Called type-id in C++. |
46 | | TypeResult Parser::ParseTypeName(SourceRange *Range, DeclaratorContext Context, |
47 | | AccessSpecifier AS, Decl **OwnedType, |
48 | 18 | ParsedAttributes *Attrs) { |
49 | 18 | DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context); |
50 | 18 | if (DSC == DeclSpecContext::DSC_normal) |
51 | 0 | DSC = DeclSpecContext::DSC_type_specifier; |
52 | | |
53 | | // Parse the common declaration-specifiers piece. |
54 | 18 | DeclSpec DS(AttrFactory); |
55 | 18 | if (Attrs) |
56 | 0 | DS.addAttributes(*Attrs); |
57 | 18 | ParseSpecifierQualifierList(DS, AS, DSC); |
58 | 18 | if (OwnedType) |
59 | 0 | *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; |
60 | | |
61 | | // Move declspec attributes to ParsedAttributes |
62 | 18 | if (Attrs) { |
63 | 0 | llvm::SmallVector<ParsedAttr *, 1> ToBeMoved; |
64 | 0 | for (ParsedAttr &AL : DS.getAttributes()) { |
65 | 0 | if (AL.isDeclspecAttribute()) |
66 | 0 | ToBeMoved.push_back(&AL); |
67 | 0 | } |
68 | |
|
69 | 0 | for (ParsedAttr *AL : ToBeMoved) |
70 | 0 | Attrs->takeOneFrom(DS.getAttributes(), AL); |
71 | 0 | } |
72 | | |
73 | | // Parse the abstract-declarator, if present. |
74 | 18 | Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context); |
75 | 18 | ParseDeclarator(DeclaratorInfo); |
76 | 18 | if (Range) |
77 | 0 | *Range = DeclaratorInfo.getSourceRange(); |
78 | | |
79 | 18 | if (DeclaratorInfo.isInvalidType()) |
80 | 18 | return true; |
81 | | |
82 | 0 | return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); |
83 | 18 | } |
84 | | |
85 | | /// Normalizes an attribute name by dropping prefixed and suffixed __. |
86 | 0 | static StringRef normalizeAttrName(StringRef Name) { |
87 | 0 | if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__")) |
88 | 0 | return Name.drop_front(2).drop_back(2); |
89 | 0 | return Name; |
90 | 0 | } |
91 | | |
92 | | /// isAttributeLateParsed - Return true if the attribute has arguments that |
93 | | /// require late parsing. |
94 | 0 | static bool isAttributeLateParsed(const IdentifierInfo &II) { |
95 | 0 | #define CLANG_ATTR_LATE_PARSED_LIST |
96 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
97 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
98 | 0 | .Default(false); |
99 | 0 | #undef CLANG_ATTR_LATE_PARSED_LIST |
100 | 0 | } |
101 | | |
102 | | /// Check if the a start and end source location expand to the same macro. |
103 | | static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, |
104 | 0 | SourceLocation EndLoc) { |
105 | 0 | if (!StartLoc.isMacroID() || !EndLoc.isMacroID()) |
106 | 0 | return false; |
107 | | |
108 | 0 | SourceManager &SM = PP.getSourceManager(); |
109 | 0 | if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc)) |
110 | 0 | return false; |
111 | | |
112 | 0 | bool AttrStartIsInMacro = |
113 | 0 | Lexer::isAtStartOfMacroExpansion(StartLoc, SM, PP.getLangOpts()); |
114 | 0 | bool AttrEndIsInMacro = |
115 | 0 | Lexer::isAtEndOfMacroExpansion(EndLoc, SM, PP.getLangOpts()); |
116 | 0 | return AttrStartIsInMacro && AttrEndIsInMacro; |
117 | 0 | } |
118 | | |
119 | | void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs, |
120 | 0 | LateParsedAttrList *LateAttrs) { |
121 | 0 | bool MoreToParse; |
122 | 0 | do { |
123 | | // Assume there's nothing left to parse, but if any attributes are in fact |
124 | | // parsed, loop to ensure all specified attribute combinations are parsed. |
125 | 0 | MoreToParse = false; |
126 | 0 | if (WhichAttrKinds & PAKM_CXX11) |
127 | 0 | MoreToParse |= MaybeParseCXX11Attributes(Attrs); |
128 | 0 | if (WhichAttrKinds & PAKM_GNU) |
129 | 0 | MoreToParse |= MaybeParseGNUAttributes(Attrs, LateAttrs); |
130 | 0 | if (WhichAttrKinds & PAKM_Declspec) |
131 | 0 | MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs); |
132 | 0 | } while (MoreToParse); |
133 | 0 | } |
134 | | |
135 | | /// ParseGNUAttributes - Parse a non-empty attributes list. |
136 | | /// |
137 | | /// [GNU] attributes: |
138 | | /// attribute |
139 | | /// attributes attribute |
140 | | /// |
141 | | /// [GNU] attribute: |
142 | | /// '__attribute__' '(' '(' attribute-list ')' ')' |
143 | | /// |
144 | | /// [GNU] attribute-list: |
145 | | /// attrib |
146 | | /// attribute_list ',' attrib |
147 | | /// |
148 | | /// [GNU] attrib: |
149 | | /// empty |
150 | | /// attrib-name |
151 | | /// attrib-name '(' identifier ')' |
152 | | /// attrib-name '(' identifier ',' nonempty-expr-list ')' |
153 | | /// attrib-name '(' argument-expression-list [C99 6.5.2] ')' |
154 | | /// |
155 | | /// [GNU] attrib-name: |
156 | | /// identifier |
157 | | /// typespec |
158 | | /// typequal |
159 | | /// storageclass |
160 | | /// |
161 | | /// Whether an attribute takes an 'identifier' is determined by the |
162 | | /// attrib-name. GCC's behavior here is not worth imitating: |
163 | | /// |
164 | | /// * In C mode, if the attribute argument list starts with an identifier |
165 | | /// followed by a ',' or an ')', and the identifier doesn't resolve to |
166 | | /// a type, it is parsed as an identifier. If the attribute actually |
167 | | /// wanted an expression, it's out of luck (but it turns out that no |
168 | | /// attributes work that way, because C constant expressions are very |
169 | | /// limited). |
170 | | /// * In C++ mode, if the attribute argument list starts with an identifier, |
171 | | /// and the attribute *wants* an identifier, it is parsed as an identifier. |
172 | | /// At block scope, any additional tokens between the identifier and the |
173 | | /// ',' or ')' are ignored, otherwise they produce a parse error. |
174 | | /// |
175 | | /// We follow the C++ model, but don't allow junk after the identifier. |
176 | | void Parser::ParseGNUAttributes(ParsedAttributes &Attrs, |
177 | 0 | LateParsedAttrList *LateAttrs, Declarator *D) { |
178 | 0 | assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); |
179 | | |
180 | 0 | SourceLocation StartLoc = Tok.getLocation(); |
181 | 0 | SourceLocation EndLoc = StartLoc; |
182 | |
|
183 | 0 | while (Tok.is(tok::kw___attribute)) { |
184 | 0 | SourceLocation AttrTokLoc = ConsumeToken(); |
185 | 0 | unsigned OldNumAttrs = Attrs.size(); |
186 | 0 | unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0; |
187 | |
|
188 | 0 | if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, |
189 | 0 | "attribute")) { |
190 | 0 | SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ; |
191 | 0 | return; |
192 | 0 | } |
193 | 0 | if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) { |
194 | 0 | SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ; |
195 | 0 | return; |
196 | 0 | } |
197 | | // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") )) |
198 | 0 | do { |
199 | | // Eat preceeding commas to allow __attribute__((,,,foo)) |
200 | 0 | while (TryConsumeToken(tok::comma)) |
201 | 0 | ; |
202 | | |
203 | | // Expect an identifier or declaration specifier (const, int, etc.) |
204 | 0 | if (Tok.isAnnotation()) |
205 | 0 | break; |
206 | 0 | if (Tok.is(tok::code_completion)) { |
207 | 0 | cutOffParsing(); |
208 | 0 | Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU); |
209 | 0 | break; |
210 | 0 | } |
211 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
212 | 0 | if (!AttrName) |
213 | 0 | break; |
214 | | |
215 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
216 | |
|
217 | 0 | if (Tok.isNot(tok::l_paren)) { |
218 | 0 | Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
219 | 0 | ParsedAttr::Form::GNU()); |
220 | 0 | continue; |
221 | 0 | } |
222 | | |
223 | | // Handle "parameterized" attributes |
224 | 0 | if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { |
225 | 0 | ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr, |
226 | 0 | SourceLocation(), ParsedAttr::Form::GNU(), D); |
227 | 0 | continue; |
228 | 0 | } |
229 | | |
230 | | // Handle attributes with arguments that require late parsing. |
231 | 0 | LateParsedAttribute *LA = |
232 | 0 | new LateParsedAttribute(this, *AttrName, AttrNameLoc); |
233 | 0 | LateAttrs->push_back(LA); |
234 | | |
235 | | // Attributes in a class are parsed at the end of the class, along |
236 | | // with other late-parsed declarations. |
237 | 0 | if (!ClassStack.empty() && !LateAttrs->parseSoon()) |
238 | 0 | getCurrentClass().LateParsedDeclarations.push_back(LA); |
239 | | |
240 | | // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it |
241 | | // recursively consumes balanced parens. |
242 | 0 | LA->Toks.push_back(Tok); |
243 | 0 | ConsumeParen(); |
244 | | // Consume everything up to and including the matching right parens. |
245 | 0 | ConsumeAndStoreUntil(tok::r_paren, LA->Toks, /*StopAtSemi=*/true); |
246 | |
|
247 | 0 | Token Eof; |
248 | 0 | Eof.startToken(); |
249 | 0 | Eof.setLocation(Tok.getLocation()); |
250 | 0 | LA->Toks.push_back(Eof); |
251 | 0 | } while (Tok.is(tok::comma)); |
252 | | |
253 | 0 | if (ExpectAndConsume(tok::r_paren)) |
254 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
255 | 0 | SourceLocation Loc = Tok.getLocation(); |
256 | 0 | if (ExpectAndConsume(tok::r_paren)) |
257 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
258 | 0 | EndLoc = Loc; |
259 | | |
260 | | // If this was declared in a macro, attach the macro IdentifierInfo to the |
261 | | // parsed attribute. |
262 | 0 | auto &SM = PP.getSourceManager(); |
263 | 0 | if (!SM.isWrittenInBuiltinFile(SM.getSpellingLoc(AttrTokLoc)) && |
264 | 0 | FindLocsWithCommonFileID(PP, AttrTokLoc, Loc)) { |
265 | 0 | CharSourceRange ExpansionRange = SM.getExpansionRange(AttrTokLoc); |
266 | 0 | StringRef FoundName = |
267 | 0 | Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts()); |
268 | 0 | IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName); |
269 | |
|
270 | 0 | for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i) |
271 | 0 | Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin()); |
272 | |
|
273 | 0 | if (LateAttrs) { |
274 | 0 | for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i) |
275 | 0 | (*LateAttrs)[i]->MacroII = MacroII; |
276 | 0 | } |
277 | 0 | } |
278 | 0 | } |
279 | | |
280 | 0 | Attrs.Range = SourceRange(StartLoc, EndLoc); |
281 | 0 | } |
282 | | |
283 | | /// Determine whether the given attribute has an identifier argument. |
284 | 0 | static bool attributeHasIdentifierArg(const IdentifierInfo &II) { |
285 | 0 | #define CLANG_ATTR_IDENTIFIER_ARG_LIST |
286 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
287 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
288 | 0 | .Default(false); |
289 | 0 | #undef CLANG_ATTR_IDENTIFIER_ARG_LIST |
290 | 0 | } |
291 | | |
292 | | /// Determine whether the given attribute has an identifier argument. |
293 | | static ParsedAttributeArgumentsProperties |
294 | 0 | attributeStringLiteralListArg(const IdentifierInfo &II) { |
295 | 0 | #define CLANG_ATTR_STRING_LITERAL_ARG_LIST |
296 | 0 | return llvm::StringSwitch<uint32_t>(normalizeAttrName(II.getName())) |
297 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
298 | 0 | .Default(0); |
299 | 0 | #undef CLANG_ATTR_STRING_LITERAL_ARG_LIST |
300 | 0 | } |
301 | | |
302 | | /// Determine whether the given attribute has a variadic identifier argument. |
303 | 0 | static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) { |
304 | 0 | #define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST |
305 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
306 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
307 | 0 | .Default(false); |
308 | 0 | #undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST |
309 | 0 | } |
310 | | |
311 | | /// Determine whether the given attribute treats kw_this as an identifier. |
312 | 0 | static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) { |
313 | 0 | #define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST |
314 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
315 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
316 | 0 | .Default(false); |
317 | 0 | #undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST |
318 | 0 | } |
319 | | |
320 | | /// Determine if an attribute accepts parameter packs. |
321 | 0 | static bool attributeAcceptsExprPack(const IdentifierInfo &II) { |
322 | 0 | #define CLANG_ATTR_ACCEPTS_EXPR_PACK |
323 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
324 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
325 | 0 | .Default(false); |
326 | 0 | #undef CLANG_ATTR_ACCEPTS_EXPR_PACK |
327 | 0 | } |
328 | | |
329 | | /// Determine whether the given attribute parses a type argument. |
330 | 0 | static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { |
331 | 0 | #define CLANG_ATTR_TYPE_ARG_LIST |
332 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
333 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
334 | 0 | .Default(false); |
335 | 0 | #undef CLANG_ATTR_TYPE_ARG_LIST |
336 | 0 | } |
337 | | |
338 | | /// Determine whether the given attribute requires parsing its arguments |
339 | | /// in an unevaluated context or not. |
340 | 0 | static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) { |
341 | 0 | #define CLANG_ATTR_ARG_CONTEXT_LIST |
342 | 0 | return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) |
343 | 0 | #include "clang/Parse/AttrParserStringSwitches.inc" |
344 | 0 | .Default(false); |
345 | 0 | #undef CLANG_ATTR_ARG_CONTEXT_LIST |
346 | 0 | } |
347 | | |
348 | 0 | IdentifierLoc *Parser::ParseIdentifierLoc() { |
349 | 0 | assert(Tok.is(tok::identifier) && "expected an identifier"); |
350 | 0 | IdentifierLoc *IL = IdentifierLoc::create(Actions.Context, |
351 | 0 | Tok.getLocation(), |
352 | 0 | Tok.getIdentifierInfo()); |
353 | 0 | ConsumeToken(); |
354 | 0 | return IL; |
355 | 0 | } |
356 | | |
357 | | void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, |
358 | | SourceLocation AttrNameLoc, |
359 | | ParsedAttributes &Attrs, |
360 | | IdentifierInfo *ScopeName, |
361 | | SourceLocation ScopeLoc, |
362 | 0 | ParsedAttr::Form Form) { |
363 | 0 | BalancedDelimiterTracker Parens(*this, tok::l_paren); |
364 | 0 | Parens.consumeOpen(); |
365 | |
|
366 | 0 | TypeResult T; |
367 | 0 | if (Tok.isNot(tok::r_paren)) |
368 | 0 | T = ParseTypeName(); |
369 | |
|
370 | 0 | if (Parens.consumeClose()) |
371 | 0 | return; |
372 | | |
373 | 0 | if (T.isInvalid()) |
374 | 0 | return; |
375 | | |
376 | 0 | if (T.isUsable()) |
377 | 0 | Attrs.addNewTypeAttr(&AttrName, |
378 | 0 | SourceRange(AttrNameLoc, Parens.getCloseLocation()), |
379 | 0 | ScopeName, ScopeLoc, T.get(), Form); |
380 | 0 | else |
381 | 0 | Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()), |
382 | 0 | ScopeName, ScopeLoc, nullptr, 0, Form); |
383 | 0 | } |
384 | | |
385 | | ExprResult |
386 | 0 | Parser::ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName) { |
387 | 0 | if (Tok.is(tok::l_paren)) { |
388 | 0 | BalancedDelimiterTracker Paren(*this, tok::l_paren); |
389 | 0 | Paren.consumeOpen(); |
390 | 0 | ExprResult Res = ParseUnevaluatedStringInAttribute(AttrName); |
391 | 0 | Paren.consumeClose(); |
392 | 0 | return Res; |
393 | 0 | } |
394 | 0 | if (!isTokenStringLiteral()) { |
395 | 0 | Diag(Tok.getLocation(), diag::err_expected_string_literal) |
396 | 0 | << /*in attribute...*/ 4 << AttrName.getName(); |
397 | 0 | return ExprError(); |
398 | 0 | } |
399 | 0 | return ParseUnevaluatedStringLiteralExpression(); |
400 | 0 | } |
401 | | |
402 | | bool Parser::ParseAttributeArgumentList( |
403 | | const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs, |
404 | 0 | ParsedAttributeArgumentsProperties ArgsProperties) { |
405 | 0 | bool SawError = false; |
406 | 0 | unsigned Arg = 0; |
407 | 0 | while (true) { |
408 | 0 | ExprResult Expr; |
409 | 0 | if (ArgsProperties.isStringLiteralArg(Arg)) { |
410 | 0 | Expr = ParseUnevaluatedStringInAttribute(AttrName); |
411 | 0 | } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { |
412 | 0 | Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); |
413 | 0 | Expr = ParseBraceInitializer(); |
414 | 0 | } else { |
415 | 0 | Expr = ParseAssignmentExpression(); |
416 | 0 | } |
417 | 0 | Expr = Actions.CorrectDelayedTyposInExpr(Expr); |
418 | |
|
419 | 0 | if (Tok.is(tok::ellipsis)) |
420 | 0 | Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken()); |
421 | 0 | else if (Tok.is(tok::code_completion)) { |
422 | | // There's nothing to suggest in here as we parsed a full expression. |
423 | | // Instead fail and propagate the error since caller might have something |
424 | | // the suggest, e.g. signature help in function call. Note that this is |
425 | | // performed before pushing the \p Expr, so that signature help can report |
426 | | // current argument correctly. |
427 | 0 | SawError = true; |
428 | 0 | cutOffParsing(); |
429 | 0 | break; |
430 | 0 | } |
431 | | |
432 | 0 | if (Expr.isInvalid()) { |
433 | 0 | SawError = true; |
434 | 0 | break; |
435 | 0 | } |
436 | | |
437 | 0 | Exprs.push_back(Expr.get()); |
438 | |
|
439 | 0 | if (Tok.isNot(tok::comma)) |
440 | 0 | break; |
441 | | // Move to the next argument, remember where the comma was. |
442 | 0 | Token Comma = Tok; |
443 | 0 | ConsumeToken(); |
444 | 0 | checkPotentialAngleBracketDelimiter(Comma); |
445 | 0 | Arg++; |
446 | 0 | } |
447 | |
|
448 | 0 | if (SawError) { |
449 | | // Ensure typos get diagnosed when errors were encountered while parsing the |
450 | | // expression list. |
451 | 0 | for (auto &E : Exprs) { |
452 | 0 | ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E); |
453 | 0 | if (Expr.isUsable()) |
454 | 0 | E = Expr.get(); |
455 | 0 | } |
456 | 0 | } |
457 | 0 | return SawError; |
458 | 0 | } |
459 | | |
460 | | unsigned Parser::ParseAttributeArgsCommon( |
461 | | IdentifierInfo *AttrName, SourceLocation AttrNameLoc, |
462 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
463 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
464 | | // Ignore the left paren location for now. |
465 | 0 | ConsumeParen(); |
466 | |
|
467 | 0 | bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName); |
468 | 0 | bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName); |
469 | 0 | bool AttributeHasVariadicIdentifierArg = |
470 | 0 | attributeHasVariadicIdentifierArg(*AttrName); |
471 | | |
472 | | // Interpret "kw_this" as an identifier if the attributed requests it. |
473 | 0 | if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) |
474 | 0 | Tok.setKind(tok::identifier); |
475 | |
|
476 | 0 | ArgsVector ArgExprs; |
477 | 0 | if (Tok.is(tok::identifier)) { |
478 | | // If this attribute wants an 'identifier' argument, make it so. |
479 | 0 | bool IsIdentifierArg = AttributeHasVariadicIdentifierArg || |
480 | 0 | attributeHasIdentifierArg(*AttrName); |
481 | 0 | ParsedAttr::Kind AttrKind = |
482 | 0 | ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax()); |
483 | | |
484 | | // If we don't know how to parse this attribute, but this is the only |
485 | | // token in this argument, assume it's meant to be an identifier. |
486 | 0 | if (AttrKind == ParsedAttr::UnknownAttribute || |
487 | 0 | AttrKind == ParsedAttr::IgnoredAttribute) { |
488 | 0 | const Token &Next = NextToken(); |
489 | 0 | IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma); |
490 | 0 | } |
491 | |
|
492 | 0 | if (IsIdentifierArg) |
493 | 0 | ArgExprs.push_back(ParseIdentifierLoc()); |
494 | 0 | } |
495 | |
|
496 | 0 | ParsedType TheParsedType; |
497 | 0 | if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) { |
498 | | // Eat the comma. |
499 | 0 | if (!ArgExprs.empty()) |
500 | 0 | ConsumeToken(); |
501 | |
|
502 | 0 | if (AttributeIsTypeArgAttr) { |
503 | | // FIXME: Multiple type arguments are not implemented. |
504 | 0 | TypeResult T = ParseTypeName(); |
505 | 0 | if (T.isInvalid()) { |
506 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
507 | 0 | return 0; |
508 | 0 | } |
509 | 0 | if (T.isUsable()) |
510 | 0 | TheParsedType = T.get(); |
511 | 0 | } else if (AttributeHasVariadicIdentifierArg) { |
512 | | // Parse variadic identifier arg. This can either consume identifiers or |
513 | | // expressions. Variadic identifier args do not support parameter packs |
514 | | // because those are typically used for attributes with enumeration |
515 | | // arguments, and those enumerations are not something the user could |
516 | | // express via a pack. |
517 | 0 | do { |
518 | | // Interpret "kw_this" as an identifier if the attributed requests it. |
519 | 0 | if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) |
520 | 0 | Tok.setKind(tok::identifier); |
521 | |
|
522 | 0 | ExprResult ArgExpr; |
523 | 0 | if (Tok.is(tok::identifier)) { |
524 | 0 | ArgExprs.push_back(ParseIdentifierLoc()); |
525 | 0 | } else { |
526 | 0 | bool Uneval = attributeParsedArgsUnevaluated(*AttrName); |
527 | 0 | EnterExpressionEvaluationContext Unevaluated( |
528 | 0 | Actions, |
529 | 0 | Uneval ? Sema::ExpressionEvaluationContext::Unevaluated |
530 | 0 | : Sema::ExpressionEvaluationContext::ConstantEvaluated); |
531 | |
|
532 | 0 | ExprResult ArgExpr( |
533 | 0 | Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); |
534 | |
|
535 | 0 | if (ArgExpr.isInvalid()) { |
536 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
537 | 0 | return 0; |
538 | 0 | } |
539 | 0 | ArgExprs.push_back(ArgExpr.get()); |
540 | 0 | } |
541 | | // Eat the comma, move to the next argument |
542 | 0 | } while (TryConsumeToken(tok::comma)); |
543 | 0 | } else { |
544 | | // General case. Parse all available expressions. |
545 | 0 | bool Uneval = attributeParsedArgsUnevaluated(*AttrName); |
546 | 0 | EnterExpressionEvaluationContext Unevaluated( |
547 | 0 | Actions, Uneval |
548 | 0 | ? Sema::ExpressionEvaluationContext::Unevaluated |
549 | 0 | : Sema::ExpressionEvaluationContext::ConstantEvaluated); |
550 | |
|
551 | 0 | ExprVector ParsedExprs; |
552 | 0 | ParsedAttributeArgumentsProperties ArgProperties = |
553 | 0 | attributeStringLiteralListArg(*AttrName); |
554 | 0 | if (ParseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties)) { |
555 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
556 | 0 | return 0; |
557 | 0 | } |
558 | | |
559 | | // Pack expansion must currently be explicitly supported by an attribute. |
560 | 0 | for (size_t I = 0; I < ParsedExprs.size(); ++I) { |
561 | 0 | if (!isa<PackExpansionExpr>(ParsedExprs[I])) |
562 | 0 | continue; |
563 | | |
564 | 0 | if (!attributeAcceptsExprPack(*AttrName)) { |
565 | 0 | Diag(Tok.getLocation(), |
566 | 0 | diag::err_attribute_argument_parm_pack_not_supported) |
567 | 0 | << AttrName; |
568 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
569 | 0 | return 0; |
570 | 0 | } |
571 | 0 | } |
572 | | |
573 | 0 | ArgExprs.insert(ArgExprs.end(), ParsedExprs.begin(), ParsedExprs.end()); |
574 | 0 | } |
575 | 0 | } |
576 | | |
577 | 0 | SourceLocation RParen = Tok.getLocation(); |
578 | 0 | if (!ExpectAndConsume(tok::r_paren)) { |
579 | 0 | SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; |
580 | |
|
581 | 0 | if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) { |
582 | 0 | Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen), |
583 | 0 | ScopeName, ScopeLoc, TheParsedType, Form); |
584 | 0 | } else { |
585 | 0 | Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, |
586 | 0 | ArgExprs.data(), ArgExprs.size(), Form); |
587 | 0 | } |
588 | 0 | } |
589 | |
|
590 | 0 | if (EndLoc) |
591 | 0 | *EndLoc = RParen; |
592 | |
|
593 | 0 | return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull()); |
594 | 0 | } |
595 | | |
596 | | /// Parse the arguments to a parameterized GNU attribute or |
597 | | /// a C++11 attribute in "gnu" namespace. |
598 | | void Parser::ParseGNUAttributeArgs( |
599 | | IdentifierInfo *AttrName, SourceLocation AttrNameLoc, |
600 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
601 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form, Declarator *D) { |
602 | |
|
603 | 0 | assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); |
604 | | |
605 | 0 | ParsedAttr::Kind AttrKind = |
606 | 0 | ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax()); |
607 | |
|
608 | 0 | if (AttrKind == ParsedAttr::AT_Availability) { |
609 | 0 | ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, |
610 | 0 | ScopeLoc, Form); |
611 | 0 | return; |
612 | 0 | } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) { |
613 | 0 | ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, |
614 | 0 | ScopeName, ScopeLoc, Form); |
615 | 0 | return; |
616 | 0 | } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) { |
617 | 0 | ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, |
618 | 0 | ScopeName, ScopeLoc, Form); |
619 | 0 | return; |
620 | 0 | } else if (AttrKind == ParsedAttr::AT_SwiftNewType) { |
621 | 0 | ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, |
622 | 0 | ScopeLoc, Form); |
623 | 0 | return; |
624 | 0 | } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) { |
625 | 0 | ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, |
626 | 0 | ScopeName, ScopeLoc, Form); |
627 | 0 | return; |
628 | 0 | } else if (attributeIsTypeArgAttr(*AttrName)) { |
629 | 0 | ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, ScopeName, |
630 | 0 | ScopeLoc, Form); |
631 | 0 | return; |
632 | 0 | } |
633 | | |
634 | | // These may refer to the function arguments, but need to be parsed early to |
635 | | // participate in determining whether it's a redeclaration. |
636 | 0 | std::optional<ParseScope> PrototypeScope; |
637 | 0 | if (normalizeAttrName(AttrName->getName()) == "enable_if" && |
638 | 0 | D && D->isFunctionDeclarator()) { |
639 | 0 | DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo(); |
640 | 0 | PrototypeScope.emplace(this, Scope::FunctionPrototypeScope | |
641 | 0 | Scope::FunctionDeclarationScope | |
642 | 0 | Scope::DeclScope); |
643 | 0 | for (unsigned i = 0; i != FTI.NumParams; ++i) { |
644 | 0 | ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param); |
645 | 0 | Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param); |
646 | 0 | } |
647 | 0 | } |
648 | |
|
649 | 0 | ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, |
650 | 0 | ScopeLoc, Form); |
651 | 0 | } |
652 | | |
653 | | unsigned Parser::ParseClangAttributeArgs( |
654 | | IdentifierInfo *AttrName, SourceLocation AttrNameLoc, |
655 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
656 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
657 | 0 | assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); |
658 | | |
659 | 0 | ParsedAttr::Kind AttrKind = |
660 | 0 | ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax()); |
661 | |
|
662 | 0 | switch (AttrKind) { |
663 | 0 | default: |
664 | 0 | return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, |
665 | 0 | ScopeName, ScopeLoc, Form); |
666 | 0 | case ParsedAttr::AT_ExternalSourceSymbol: |
667 | 0 | ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, |
668 | 0 | ScopeName, ScopeLoc, Form); |
669 | 0 | break; |
670 | 0 | case ParsedAttr::AT_Availability: |
671 | 0 | ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, |
672 | 0 | ScopeLoc, Form); |
673 | 0 | break; |
674 | 0 | case ParsedAttr::AT_ObjCBridgeRelated: |
675 | 0 | ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, |
676 | 0 | ScopeName, ScopeLoc, Form); |
677 | 0 | break; |
678 | 0 | case ParsedAttr::AT_SwiftNewType: |
679 | 0 | ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, |
680 | 0 | ScopeLoc, Form); |
681 | 0 | break; |
682 | 0 | case ParsedAttr::AT_TypeTagForDatatype: |
683 | 0 | ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, |
684 | 0 | ScopeName, ScopeLoc, Form); |
685 | 0 | break; |
686 | 0 | } |
687 | 0 | return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0; |
688 | 0 | } |
689 | | |
690 | | bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, |
691 | | SourceLocation AttrNameLoc, |
692 | 0 | ParsedAttributes &Attrs) { |
693 | 0 | unsigned ExistingAttrs = Attrs.size(); |
694 | | |
695 | | // If the attribute isn't known, we will not attempt to parse any |
696 | | // arguments. |
697 | 0 | if (!hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, AttrName, |
698 | 0 | getTargetInfo(), getLangOpts())) { |
699 | | // Eat the left paren, then skip to the ending right paren. |
700 | 0 | ConsumeParen(); |
701 | 0 | SkipUntil(tok::r_paren); |
702 | 0 | return false; |
703 | 0 | } |
704 | | |
705 | 0 | SourceLocation OpenParenLoc = Tok.getLocation(); |
706 | |
|
707 | 0 | if (AttrName->getName() == "property") { |
708 | | // The property declspec is more complex in that it can take one or two |
709 | | // assignment expressions as a parameter, but the lhs of the assignment |
710 | | // must be named get or put. |
711 | |
|
712 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
713 | 0 | T.expectAndConsume(diag::err_expected_lparen_after, |
714 | 0 | AttrName->getNameStart(), tok::r_paren); |
715 | |
|
716 | 0 | enum AccessorKind { |
717 | 0 | AK_Invalid = -1, |
718 | 0 | AK_Put = 0, |
719 | 0 | AK_Get = 1 // indices into AccessorNames |
720 | 0 | }; |
721 | 0 | IdentifierInfo *AccessorNames[] = {nullptr, nullptr}; |
722 | 0 | bool HasInvalidAccessor = false; |
723 | | |
724 | | // Parse the accessor specifications. |
725 | 0 | while (true) { |
726 | | // Stop if this doesn't look like an accessor spec. |
727 | 0 | if (!Tok.is(tok::identifier)) { |
728 | | // If the user wrote a completely empty list, use a special diagnostic. |
729 | 0 | if (Tok.is(tok::r_paren) && !HasInvalidAccessor && |
730 | 0 | AccessorNames[AK_Put] == nullptr && |
731 | 0 | AccessorNames[AK_Get] == nullptr) { |
732 | 0 | Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter); |
733 | 0 | break; |
734 | 0 | } |
735 | | |
736 | 0 | Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor); |
737 | 0 | break; |
738 | 0 | } |
739 | | |
740 | 0 | AccessorKind Kind; |
741 | 0 | SourceLocation KindLoc = Tok.getLocation(); |
742 | 0 | StringRef KindStr = Tok.getIdentifierInfo()->getName(); |
743 | 0 | if (KindStr == "get") { |
744 | 0 | Kind = AK_Get; |
745 | 0 | } else if (KindStr == "put") { |
746 | 0 | Kind = AK_Put; |
747 | | |
748 | | // Recover from the common mistake of using 'set' instead of 'put'. |
749 | 0 | } else if (KindStr == "set") { |
750 | 0 | Diag(KindLoc, diag::err_ms_property_has_set_accessor) |
751 | 0 | << FixItHint::CreateReplacement(KindLoc, "put"); |
752 | 0 | Kind = AK_Put; |
753 | | |
754 | | // Handle the mistake of forgetting the accessor kind by skipping |
755 | | // this accessor. |
756 | 0 | } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) { |
757 | 0 | Diag(KindLoc, diag::err_ms_property_missing_accessor_kind); |
758 | 0 | ConsumeToken(); |
759 | 0 | HasInvalidAccessor = true; |
760 | 0 | goto next_property_accessor; |
761 | | |
762 | | // Otherwise, complain about the unknown accessor kind. |
763 | 0 | } else { |
764 | 0 | Diag(KindLoc, diag::err_ms_property_unknown_accessor); |
765 | 0 | HasInvalidAccessor = true; |
766 | 0 | Kind = AK_Invalid; |
767 | | |
768 | | // Try to keep parsing unless it doesn't look like an accessor spec. |
769 | 0 | if (!NextToken().is(tok::equal)) |
770 | 0 | break; |
771 | 0 | } |
772 | | |
773 | | // Consume the identifier. |
774 | 0 | ConsumeToken(); |
775 | | |
776 | | // Consume the '='. |
777 | 0 | if (!TryConsumeToken(tok::equal)) { |
778 | 0 | Diag(Tok.getLocation(), diag::err_ms_property_expected_equal) |
779 | 0 | << KindStr; |
780 | 0 | break; |
781 | 0 | } |
782 | | |
783 | | // Expect the method name. |
784 | 0 | if (!Tok.is(tok::identifier)) { |
785 | 0 | Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name); |
786 | 0 | break; |
787 | 0 | } |
788 | | |
789 | 0 | if (Kind == AK_Invalid) { |
790 | | // Just drop invalid accessors. |
791 | 0 | } else if (AccessorNames[Kind] != nullptr) { |
792 | | // Complain about the repeated accessor, ignore it, and keep parsing. |
793 | 0 | Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr; |
794 | 0 | } else { |
795 | 0 | AccessorNames[Kind] = Tok.getIdentifierInfo(); |
796 | 0 | } |
797 | 0 | ConsumeToken(); |
798 | |
|
799 | 0 | next_property_accessor: |
800 | | // Keep processing accessors until we run out. |
801 | 0 | if (TryConsumeToken(tok::comma)) |
802 | 0 | continue; |
803 | | |
804 | | // If we run into the ')', stop without consuming it. |
805 | 0 | if (Tok.is(tok::r_paren)) |
806 | 0 | break; |
807 | | |
808 | 0 | Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen); |
809 | 0 | break; |
810 | 0 | } |
811 | | |
812 | | // Only add the property attribute if it was well-formed. |
813 | 0 | if (!HasInvalidAccessor) |
814 | 0 | Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(), |
815 | 0 | AccessorNames[AK_Get], AccessorNames[AK_Put], |
816 | 0 | ParsedAttr::Form::Declspec()); |
817 | 0 | T.skipToEnd(); |
818 | 0 | return !HasInvalidAccessor; |
819 | 0 | } |
820 | | |
821 | 0 | unsigned NumArgs = |
822 | 0 | ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, |
823 | 0 | SourceLocation(), ParsedAttr::Form::Declspec()); |
824 | | |
825 | | // If this attribute's args were parsed, and it was expected to have |
826 | | // arguments but none were provided, emit a diagnostic. |
827 | 0 | if (ExistingAttrs < Attrs.size() && Attrs.back().getMaxArgs() && !NumArgs) { |
828 | 0 | Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; |
829 | 0 | return false; |
830 | 0 | } |
831 | 0 | return true; |
832 | 0 | } |
833 | | |
834 | | /// [MS] decl-specifier: |
835 | | /// __declspec ( extended-decl-modifier-seq ) |
836 | | /// |
837 | | /// [MS] extended-decl-modifier-seq: |
838 | | /// extended-decl-modifier[opt] |
839 | | /// extended-decl-modifier extended-decl-modifier-seq |
840 | 0 | void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) { |
841 | 0 | assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled"); |
842 | 0 | assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); |
843 | | |
844 | 0 | SourceLocation StartLoc = Tok.getLocation(); |
845 | 0 | SourceLocation EndLoc = StartLoc; |
846 | |
|
847 | 0 | while (Tok.is(tok::kw___declspec)) { |
848 | 0 | ConsumeToken(); |
849 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
850 | 0 | if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", |
851 | 0 | tok::r_paren)) |
852 | 0 | return; |
853 | | |
854 | | // An empty declspec is perfectly legal and should not warn. Additionally, |
855 | | // you can specify multiple attributes per declspec. |
856 | 0 | while (Tok.isNot(tok::r_paren)) { |
857 | | // Attribute not present. |
858 | 0 | if (TryConsumeToken(tok::comma)) |
859 | 0 | continue; |
860 | | |
861 | 0 | if (Tok.is(tok::code_completion)) { |
862 | 0 | cutOffParsing(); |
863 | 0 | Actions.CodeCompleteAttribute(AttributeCommonInfo::AS_Declspec); |
864 | 0 | return; |
865 | 0 | } |
866 | | |
867 | | // We expect either a well-known identifier or a generic string. Anything |
868 | | // else is a malformed declspec. |
869 | 0 | bool IsString = Tok.getKind() == tok::string_literal; |
870 | 0 | if (!IsString && Tok.getKind() != tok::identifier && |
871 | 0 | Tok.getKind() != tok::kw_restrict) { |
872 | 0 | Diag(Tok, diag::err_ms_declspec_type); |
873 | 0 | T.skipToEnd(); |
874 | 0 | return; |
875 | 0 | } |
876 | | |
877 | 0 | IdentifierInfo *AttrName; |
878 | 0 | SourceLocation AttrNameLoc; |
879 | 0 | if (IsString) { |
880 | 0 | SmallString<8> StrBuffer; |
881 | 0 | bool Invalid = false; |
882 | 0 | StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid); |
883 | 0 | if (Invalid) { |
884 | 0 | T.skipToEnd(); |
885 | 0 | return; |
886 | 0 | } |
887 | 0 | AttrName = PP.getIdentifierInfo(Str); |
888 | 0 | AttrNameLoc = ConsumeStringToken(); |
889 | 0 | } else { |
890 | 0 | AttrName = Tok.getIdentifierInfo(); |
891 | 0 | AttrNameLoc = ConsumeToken(); |
892 | 0 | } |
893 | | |
894 | 0 | bool AttrHandled = false; |
895 | | |
896 | | // Parse attribute arguments. |
897 | 0 | if (Tok.is(tok::l_paren)) |
898 | 0 | AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); |
899 | 0 | else if (AttrName->getName() == "property") |
900 | | // The property attribute must have an argument list. |
901 | 0 | Diag(Tok.getLocation(), diag::err_expected_lparen_after) |
902 | 0 | << AttrName->getName(); |
903 | |
|
904 | 0 | if (!AttrHandled) |
905 | 0 | Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
906 | 0 | ParsedAttr::Form::Declspec()); |
907 | 0 | } |
908 | 0 | T.consumeClose(); |
909 | 0 | EndLoc = T.getCloseLocation(); |
910 | 0 | } |
911 | | |
912 | 0 | Attrs.Range = SourceRange(StartLoc, EndLoc); |
913 | 0 | } |
914 | | |
915 | 165 | void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { |
916 | | // Treat these like attributes |
917 | 165 | while (true) { |
918 | 165 | auto Kind = Tok.getKind(); |
919 | 165 | switch (Kind) { |
920 | 0 | case tok::kw___fastcall: |
921 | 0 | case tok::kw___stdcall: |
922 | 0 | case tok::kw___thiscall: |
923 | 0 | case tok::kw___regcall: |
924 | 0 | case tok::kw___cdecl: |
925 | 0 | case tok::kw___vectorcall: |
926 | 0 | case tok::kw___ptr64: |
927 | 0 | case tok::kw___w64: |
928 | 0 | case tok::kw___ptr32: |
929 | 0 | case tok::kw___sptr: |
930 | 0 | case tok::kw___uptr: { |
931 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
932 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
933 | 0 | attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
934 | 0 | Kind); |
935 | 0 | break; |
936 | 0 | } |
937 | 165 | default: |
938 | 165 | return; |
939 | 165 | } |
940 | 165 | } |
941 | 165 | } |
942 | | |
943 | 0 | void Parser::ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes &attrs) { |
944 | 0 | assert(Tok.is(tok::kw___funcref)); |
945 | 0 | SourceLocation StartLoc = Tok.getLocation(); |
946 | 0 | if (!getTargetInfo().getTriple().isWasm()) { |
947 | 0 | ConsumeToken(); |
948 | 0 | Diag(StartLoc, diag::err_wasm_funcref_not_wasm); |
949 | 0 | return; |
950 | 0 | } |
951 | | |
952 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
953 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
954 | 0 | attrs.addNew(AttrName, AttrNameLoc, /*ScopeName=*/nullptr, |
955 | 0 | /*ScopeLoc=*/SourceLocation{}, /*Args=*/nullptr, /*numArgs=*/0, |
956 | 0 | tok::kw___funcref); |
957 | 0 | } |
958 | | |
959 | 0 | void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() { |
960 | 0 | SourceLocation StartLoc = Tok.getLocation(); |
961 | 0 | SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes(); |
962 | |
|
963 | 0 | if (EndLoc.isValid()) { |
964 | 0 | SourceRange Range(StartLoc, EndLoc); |
965 | 0 | Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range; |
966 | 0 | } |
967 | 0 | } |
968 | | |
969 | 0 | SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() { |
970 | 0 | SourceLocation EndLoc; |
971 | |
|
972 | 0 | while (true) { |
973 | 0 | switch (Tok.getKind()) { |
974 | 0 | case tok::kw_const: |
975 | 0 | case tok::kw_volatile: |
976 | 0 | case tok::kw___fastcall: |
977 | 0 | case tok::kw___stdcall: |
978 | 0 | case tok::kw___thiscall: |
979 | 0 | case tok::kw___cdecl: |
980 | 0 | case tok::kw___vectorcall: |
981 | 0 | case tok::kw___ptr32: |
982 | 0 | case tok::kw___ptr64: |
983 | 0 | case tok::kw___w64: |
984 | 0 | case tok::kw___unaligned: |
985 | 0 | case tok::kw___sptr: |
986 | 0 | case tok::kw___uptr: |
987 | 0 | EndLoc = ConsumeToken(); |
988 | 0 | break; |
989 | 0 | default: |
990 | 0 | return EndLoc; |
991 | 0 | } |
992 | 0 | } |
993 | 0 | } |
994 | | |
995 | 0 | void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { |
996 | | // Treat these like attributes |
997 | 0 | while (Tok.is(tok::kw___pascal)) { |
998 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
999 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
1000 | 0 | attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
1001 | 0 | tok::kw___pascal); |
1002 | 0 | } |
1003 | 0 | } |
1004 | | |
1005 | 0 | void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) { |
1006 | | // Treat these like attributes |
1007 | 0 | while (Tok.is(tok::kw___kernel)) { |
1008 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
1009 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
1010 | 0 | attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
1011 | 0 | tok::kw___kernel); |
1012 | 0 | } |
1013 | 0 | } |
1014 | | |
1015 | 0 | void Parser::ParseCUDAFunctionAttributes(ParsedAttributes &attrs) { |
1016 | 0 | while (Tok.is(tok::kw___noinline__)) { |
1017 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
1018 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
1019 | 0 | attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
1020 | 0 | tok::kw___noinline__); |
1021 | 0 | } |
1022 | 0 | } |
1023 | | |
1024 | 0 | void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { |
1025 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
1026 | 0 | SourceLocation AttrNameLoc = Tok.getLocation(); |
1027 | 0 | Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
1028 | 0 | Tok.getKind()); |
1029 | 0 | } |
1030 | | |
1031 | 0 | bool Parser::isHLSLQualifier(const Token &Tok) const { |
1032 | 0 | return Tok.is(tok::kw_groupshared); |
1033 | 0 | } |
1034 | | |
1035 | 0 | void Parser::ParseHLSLQualifiers(ParsedAttributes &Attrs) { |
1036 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
1037 | 0 | auto Kind = Tok.getKind(); |
1038 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
1039 | 0 | Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); |
1040 | 0 | } |
1041 | | |
1042 | 0 | void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { |
1043 | | // Treat these like attributes, even though they're type specifiers. |
1044 | 0 | while (true) { |
1045 | 0 | auto Kind = Tok.getKind(); |
1046 | 0 | switch (Kind) { |
1047 | 0 | case tok::kw__Nonnull: |
1048 | 0 | case tok::kw__Nullable: |
1049 | 0 | case tok::kw__Nullable_result: |
1050 | 0 | case tok::kw__Null_unspecified: { |
1051 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
1052 | 0 | SourceLocation AttrNameLoc = ConsumeToken(); |
1053 | 0 | if (!getLangOpts().ObjC) |
1054 | 0 | Diag(AttrNameLoc, diag::ext_nullability) |
1055 | 0 | << AttrName; |
1056 | 0 | attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, |
1057 | 0 | Kind); |
1058 | 0 | break; |
1059 | 0 | } |
1060 | 0 | default: |
1061 | 0 | return; |
1062 | 0 | } |
1063 | 0 | } |
1064 | 0 | } |
1065 | | |
1066 | 0 | static bool VersionNumberSeparator(const char Separator) { |
1067 | 0 | return (Separator == '.' || Separator == '_'); |
1068 | 0 | } |
1069 | | |
1070 | | /// Parse a version number. |
1071 | | /// |
1072 | | /// version: |
1073 | | /// simple-integer |
1074 | | /// simple-integer '.' simple-integer |
1075 | | /// simple-integer '_' simple-integer |
1076 | | /// simple-integer '.' simple-integer '.' simple-integer |
1077 | | /// simple-integer '_' simple-integer '_' simple-integer |
1078 | 0 | VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { |
1079 | 0 | Range = SourceRange(Tok.getLocation(), Tok.getEndLoc()); |
1080 | |
|
1081 | 0 | if (!Tok.is(tok::numeric_constant)) { |
1082 | 0 | Diag(Tok, diag::err_expected_version); |
1083 | 0 | SkipUntil(tok::comma, tok::r_paren, |
1084 | 0 | StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); |
1085 | 0 | return VersionTuple(); |
1086 | 0 | } |
1087 | | |
1088 | | // Parse the major (and possibly minor and subminor) versions, which |
1089 | | // are stored in the numeric constant. We utilize a quirk of the |
1090 | | // lexer, which is that it handles something like 1.2.3 as a single |
1091 | | // numeric constant, rather than two separate tokens. |
1092 | 0 | SmallString<512> Buffer; |
1093 | 0 | Buffer.resize(Tok.getLength()+1); |
1094 | 0 | const char *ThisTokBegin = &Buffer[0]; |
1095 | | |
1096 | | // Get the spelling of the token, which eliminates trigraphs, etc. |
1097 | 0 | bool Invalid = false; |
1098 | 0 | unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid); |
1099 | 0 | if (Invalid) |
1100 | 0 | return VersionTuple(); |
1101 | | |
1102 | | // Parse the major version. |
1103 | 0 | unsigned AfterMajor = 0; |
1104 | 0 | unsigned Major = 0; |
1105 | 0 | while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) { |
1106 | 0 | Major = Major * 10 + ThisTokBegin[AfterMajor] - '0'; |
1107 | 0 | ++AfterMajor; |
1108 | 0 | } |
1109 | |
|
1110 | 0 | if (AfterMajor == 0) { |
1111 | 0 | Diag(Tok, diag::err_expected_version); |
1112 | 0 | SkipUntil(tok::comma, tok::r_paren, |
1113 | 0 | StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); |
1114 | 0 | return VersionTuple(); |
1115 | 0 | } |
1116 | | |
1117 | 0 | if (AfterMajor == ActualLength) { |
1118 | 0 | ConsumeToken(); |
1119 | | |
1120 | | // We only had a single version component. |
1121 | 0 | if (Major == 0) { |
1122 | 0 | Diag(Tok, diag::err_zero_version); |
1123 | 0 | return VersionTuple(); |
1124 | 0 | } |
1125 | | |
1126 | 0 | return VersionTuple(Major); |
1127 | 0 | } |
1128 | | |
1129 | 0 | const char AfterMajorSeparator = ThisTokBegin[AfterMajor]; |
1130 | 0 | if (!VersionNumberSeparator(AfterMajorSeparator) |
1131 | 0 | || (AfterMajor + 1 == ActualLength)) { |
1132 | 0 | Diag(Tok, diag::err_expected_version); |
1133 | 0 | SkipUntil(tok::comma, tok::r_paren, |
1134 | 0 | StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); |
1135 | 0 | return VersionTuple(); |
1136 | 0 | } |
1137 | | |
1138 | | // Parse the minor version. |
1139 | 0 | unsigned AfterMinor = AfterMajor + 1; |
1140 | 0 | unsigned Minor = 0; |
1141 | 0 | while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) { |
1142 | 0 | Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0'; |
1143 | 0 | ++AfterMinor; |
1144 | 0 | } |
1145 | |
|
1146 | 0 | if (AfterMinor == ActualLength) { |
1147 | 0 | ConsumeToken(); |
1148 | | |
1149 | | // We had major.minor. |
1150 | 0 | if (Major == 0 && Minor == 0) { |
1151 | 0 | Diag(Tok, diag::err_zero_version); |
1152 | 0 | return VersionTuple(); |
1153 | 0 | } |
1154 | | |
1155 | 0 | return VersionTuple(Major, Minor); |
1156 | 0 | } |
1157 | | |
1158 | 0 | const char AfterMinorSeparator = ThisTokBegin[AfterMinor]; |
1159 | | // If what follows is not a '.' or '_', we have a problem. |
1160 | 0 | if (!VersionNumberSeparator(AfterMinorSeparator)) { |
1161 | 0 | Diag(Tok, diag::err_expected_version); |
1162 | 0 | SkipUntil(tok::comma, tok::r_paren, |
1163 | 0 | StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); |
1164 | 0 | return VersionTuple(); |
1165 | 0 | } |
1166 | | |
1167 | | // Warn if separators, be it '.' or '_', do not match. |
1168 | 0 | if (AfterMajorSeparator != AfterMinorSeparator) |
1169 | 0 | Diag(Tok, diag::warn_expected_consistent_version_separator); |
1170 | | |
1171 | | // Parse the subminor version. |
1172 | 0 | unsigned AfterSubminor = AfterMinor + 1; |
1173 | 0 | unsigned Subminor = 0; |
1174 | 0 | while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) { |
1175 | 0 | Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0'; |
1176 | 0 | ++AfterSubminor; |
1177 | 0 | } |
1178 | |
|
1179 | 0 | if (AfterSubminor != ActualLength) { |
1180 | 0 | Diag(Tok, diag::err_expected_version); |
1181 | 0 | SkipUntil(tok::comma, tok::r_paren, |
1182 | 0 | StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); |
1183 | 0 | return VersionTuple(); |
1184 | 0 | } |
1185 | 0 | ConsumeToken(); |
1186 | 0 | return VersionTuple(Major, Minor, Subminor); |
1187 | 0 | } |
1188 | | |
1189 | | /// Parse the contents of the "availability" attribute. |
1190 | | /// |
1191 | | /// availability-attribute: |
1192 | | /// 'availability' '(' platform ',' opt-strict version-arg-list, |
1193 | | /// opt-replacement, opt-message')' |
1194 | | /// |
1195 | | /// platform: |
1196 | | /// identifier |
1197 | | /// |
1198 | | /// opt-strict: |
1199 | | /// 'strict' ',' |
1200 | | /// |
1201 | | /// version-arg-list: |
1202 | | /// version-arg |
1203 | | /// version-arg ',' version-arg-list |
1204 | | /// |
1205 | | /// version-arg: |
1206 | | /// 'introduced' '=' version |
1207 | | /// 'deprecated' '=' version |
1208 | | /// 'obsoleted' = version |
1209 | | /// 'unavailable' |
1210 | | /// opt-replacement: |
1211 | | /// 'replacement' '=' <string> |
1212 | | /// opt-message: |
1213 | | /// 'message' '=' <string> |
1214 | | void Parser::ParseAvailabilityAttribute( |
1215 | | IdentifierInfo &Availability, SourceLocation AvailabilityLoc, |
1216 | | ParsedAttributes &attrs, SourceLocation *endLoc, IdentifierInfo *ScopeName, |
1217 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
1218 | 0 | enum { Introduced, Deprecated, Obsoleted, Unknown }; |
1219 | 0 | AvailabilityChange Changes[Unknown]; |
1220 | 0 | ExprResult MessageExpr, ReplacementExpr; |
1221 | | |
1222 | | // Opening '('. |
1223 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
1224 | 0 | if (T.consumeOpen()) { |
1225 | 0 | Diag(Tok, diag::err_expected) << tok::l_paren; |
1226 | 0 | return; |
1227 | 0 | } |
1228 | | |
1229 | | // Parse the platform name. |
1230 | 0 | if (Tok.isNot(tok::identifier)) { |
1231 | 0 | Diag(Tok, diag::err_availability_expected_platform); |
1232 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1233 | 0 | return; |
1234 | 0 | } |
1235 | 0 | IdentifierLoc *Platform = ParseIdentifierLoc(); |
1236 | 0 | if (const IdentifierInfo *const Ident = Platform->Ident) { |
1237 | | // Canonicalize platform name from "macosx" to "macos". |
1238 | 0 | if (Ident->getName() == "macosx") |
1239 | 0 | Platform->Ident = PP.getIdentifierInfo("macos"); |
1240 | | // Canonicalize platform name from "macosx_app_extension" to |
1241 | | // "macos_app_extension". |
1242 | 0 | else if (Ident->getName() == "macosx_app_extension") |
1243 | 0 | Platform->Ident = PP.getIdentifierInfo("macos_app_extension"); |
1244 | 0 | else |
1245 | 0 | Platform->Ident = PP.getIdentifierInfo( |
1246 | 0 | AvailabilityAttr::canonicalizePlatformName(Ident->getName())); |
1247 | 0 | } |
1248 | | |
1249 | | // Parse the ',' following the platform name. |
1250 | 0 | if (ExpectAndConsume(tok::comma)) { |
1251 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1252 | 0 | return; |
1253 | 0 | } |
1254 | | |
1255 | | // If we haven't grabbed the pointers for the identifiers |
1256 | | // "introduced", "deprecated", and "obsoleted", do so now. |
1257 | 0 | if (!Ident_introduced) { |
1258 | 0 | Ident_introduced = PP.getIdentifierInfo("introduced"); |
1259 | 0 | Ident_deprecated = PP.getIdentifierInfo("deprecated"); |
1260 | 0 | Ident_obsoleted = PP.getIdentifierInfo("obsoleted"); |
1261 | 0 | Ident_unavailable = PP.getIdentifierInfo("unavailable"); |
1262 | 0 | Ident_message = PP.getIdentifierInfo("message"); |
1263 | 0 | Ident_strict = PP.getIdentifierInfo("strict"); |
1264 | 0 | Ident_replacement = PP.getIdentifierInfo("replacement"); |
1265 | 0 | } |
1266 | | |
1267 | | // Parse the optional "strict", the optional "replacement" and the set of |
1268 | | // introductions/deprecations/removals. |
1269 | 0 | SourceLocation UnavailableLoc, StrictLoc; |
1270 | 0 | do { |
1271 | 0 | if (Tok.isNot(tok::identifier)) { |
1272 | 0 | Diag(Tok, diag::err_availability_expected_change); |
1273 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1274 | 0 | return; |
1275 | 0 | } |
1276 | 0 | IdentifierInfo *Keyword = Tok.getIdentifierInfo(); |
1277 | 0 | SourceLocation KeywordLoc = ConsumeToken(); |
1278 | |
|
1279 | 0 | if (Keyword == Ident_strict) { |
1280 | 0 | if (StrictLoc.isValid()) { |
1281 | 0 | Diag(KeywordLoc, diag::err_availability_redundant) |
1282 | 0 | << Keyword << SourceRange(StrictLoc); |
1283 | 0 | } |
1284 | 0 | StrictLoc = KeywordLoc; |
1285 | 0 | continue; |
1286 | 0 | } |
1287 | | |
1288 | 0 | if (Keyword == Ident_unavailable) { |
1289 | 0 | if (UnavailableLoc.isValid()) { |
1290 | 0 | Diag(KeywordLoc, diag::err_availability_redundant) |
1291 | 0 | << Keyword << SourceRange(UnavailableLoc); |
1292 | 0 | } |
1293 | 0 | UnavailableLoc = KeywordLoc; |
1294 | 0 | continue; |
1295 | 0 | } |
1296 | | |
1297 | 0 | if (Keyword == Ident_deprecated && Platform->Ident && |
1298 | 0 | Platform->Ident->isStr("swift")) { |
1299 | | // For swift, we deprecate for all versions. |
1300 | 0 | if (Changes[Deprecated].KeywordLoc.isValid()) { |
1301 | 0 | Diag(KeywordLoc, diag::err_availability_redundant) |
1302 | 0 | << Keyword |
1303 | 0 | << SourceRange(Changes[Deprecated].KeywordLoc); |
1304 | 0 | } |
1305 | |
|
1306 | 0 | Changes[Deprecated].KeywordLoc = KeywordLoc; |
1307 | | // Use a fake version here. |
1308 | 0 | Changes[Deprecated].Version = VersionTuple(1); |
1309 | 0 | continue; |
1310 | 0 | } |
1311 | | |
1312 | 0 | if (Tok.isNot(tok::equal)) { |
1313 | 0 | Diag(Tok, diag::err_expected_after) << Keyword << tok::equal; |
1314 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1315 | 0 | return; |
1316 | 0 | } |
1317 | 0 | ConsumeToken(); |
1318 | 0 | if (Keyword == Ident_message || Keyword == Ident_replacement) { |
1319 | 0 | if (!isTokenStringLiteral()) { |
1320 | 0 | Diag(Tok, diag::err_expected_string_literal) |
1321 | 0 | << /*Source='availability attribute'*/2; |
1322 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1323 | 0 | return; |
1324 | 0 | } |
1325 | 0 | if (Keyword == Ident_message) { |
1326 | 0 | MessageExpr = ParseUnevaluatedStringLiteralExpression(); |
1327 | 0 | break; |
1328 | 0 | } else { |
1329 | 0 | ReplacementExpr = ParseUnevaluatedStringLiteralExpression(); |
1330 | 0 | continue; |
1331 | 0 | } |
1332 | 0 | } |
1333 | | |
1334 | | // Special handling of 'NA' only when applied to introduced or |
1335 | | // deprecated. |
1336 | 0 | if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) && |
1337 | 0 | Tok.is(tok::identifier)) { |
1338 | 0 | IdentifierInfo *NA = Tok.getIdentifierInfo(); |
1339 | 0 | if (NA->getName() == "NA") { |
1340 | 0 | ConsumeToken(); |
1341 | 0 | if (Keyword == Ident_introduced) |
1342 | 0 | UnavailableLoc = KeywordLoc; |
1343 | 0 | continue; |
1344 | 0 | } |
1345 | 0 | } |
1346 | | |
1347 | 0 | SourceRange VersionRange; |
1348 | 0 | VersionTuple Version = ParseVersionTuple(VersionRange); |
1349 | |
|
1350 | 0 | if (Version.empty()) { |
1351 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1352 | 0 | return; |
1353 | 0 | } |
1354 | | |
1355 | 0 | unsigned Index; |
1356 | 0 | if (Keyword == Ident_introduced) |
1357 | 0 | Index = Introduced; |
1358 | 0 | else if (Keyword == Ident_deprecated) |
1359 | 0 | Index = Deprecated; |
1360 | 0 | else if (Keyword == Ident_obsoleted) |
1361 | 0 | Index = Obsoleted; |
1362 | 0 | else |
1363 | 0 | Index = Unknown; |
1364 | |
|
1365 | 0 | if (Index < Unknown) { |
1366 | 0 | if (!Changes[Index].KeywordLoc.isInvalid()) { |
1367 | 0 | Diag(KeywordLoc, diag::err_availability_redundant) |
1368 | 0 | << Keyword |
1369 | 0 | << SourceRange(Changes[Index].KeywordLoc, |
1370 | 0 | Changes[Index].VersionRange.getEnd()); |
1371 | 0 | } |
1372 | |
|
1373 | 0 | Changes[Index].KeywordLoc = KeywordLoc; |
1374 | 0 | Changes[Index].Version = Version; |
1375 | 0 | Changes[Index].VersionRange = VersionRange; |
1376 | 0 | } else { |
1377 | 0 | Diag(KeywordLoc, diag::err_availability_unknown_change) |
1378 | 0 | << Keyword << VersionRange; |
1379 | 0 | } |
1380 | |
|
1381 | 0 | } while (TryConsumeToken(tok::comma)); |
1382 | | |
1383 | | // Closing ')'. |
1384 | 0 | if (T.consumeClose()) |
1385 | 0 | return; |
1386 | | |
1387 | 0 | if (endLoc) |
1388 | 0 | *endLoc = T.getCloseLocation(); |
1389 | | |
1390 | | // The 'unavailable' availability cannot be combined with any other |
1391 | | // availability changes. Make sure that hasn't happened. |
1392 | 0 | if (UnavailableLoc.isValid()) { |
1393 | 0 | bool Complained = false; |
1394 | 0 | for (unsigned Index = Introduced; Index != Unknown; ++Index) { |
1395 | 0 | if (Changes[Index].KeywordLoc.isValid()) { |
1396 | 0 | if (!Complained) { |
1397 | 0 | Diag(UnavailableLoc, diag::warn_availability_and_unavailable) |
1398 | 0 | << SourceRange(Changes[Index].KeywordLoc, |
1399 | 0 | Changes[Index].VersionRange.getEnd()); |
1400 | 0 | Complained = true; |
1401 | 0 | } |
1402 | | |
1403 | | // Clear out the availability. |
1404 | 0 | Changes[Index] = AvailabilityChange(); |
1405 | 0 | } |
1406 | 0 | } |
1407 | 0 | } |
1408 | | |
1409 | | // Record this attribute |
1410 | 0 | attrs.addNew(&Availability, |
1411 | 0 | SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName, |
1412 | 0 | ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated], |
1413 | 0 | Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), Form, |
1414 | 0 | StrictLoc, ReplacementExpr.get()); |
1415 | 0 | } |
1416 | | |
1417 | | /// Parse the contents of the "external_source_symbol" attribute. |
1418 | | /// |
1419 | | /// external-source-symbol-attribute: |
1420 | | /// 'external_source_symbol' '(' keyword-arg-list ')' |
1421 | | /// |
1422 | | /// keyword-arg-list: |
1423 | | /// keyword-arg |
1424 | | /// keyword-arg ',' keyword-arg-list |
1425 | | /// |
1426 | | /// keyword-arg: |
1427 | | /// 'language' '=' <string> |
1428 | | /// 'defined_in' '=' <string> |
1429 | | /// 'USR' '=' <string> |
1430 | | /// 'generated_declaration' |
1431 | | void Parser::ParseExternalSourceSymbolAttribute( |
1432 | | IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc, |
1433 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
1434 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
1435 | | // Opening '('. |
1436 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
1437 | 0 | if (T.expectAndConsume()) |
1438 | 0 | return; |
1439 | | |
1440 | | // Initialize the pointers for the keyword identifiers when required. |
1441 | 0 | if (!Ident_language) { |
1442 | 0 | Ident_language = PP.getIdentifierInfo("language"); |
1443 | 0 | Ident_defined_in = PP.getIdentifierInfo("defined_in"); |
1444 | 0 | Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration"); |
1445 | 0 | Ident_USR = PP.getIdentifierInfo("USR"); |
1446 | 0 | } |
1447 | |
|
1448 | 0 | ExprResult Language; |
1449 | 0 | bool HasLanguage = false; |
1450 | 0 | ExprResult DefinedInExpr; |
1451 | 0 | bool HasDefinedIn = false; |
1452 | 0 | IdentifierLoc *GeneratedDeclaration = nullptr; |
1453 | 0 | ExprResult USR; |
1454 | 0 | bool HasUSR = false; |
1455 | | |
1456 | | // Parse the language/defined_in/generated_declaration keywords |
1457 | 0 | do { |
1458 | 0 | if (Tok.isNot(tok::identifier)) { |
1459 | 0 | Diag(Tok, diag::err_external_source_symbol_expected_keyword); |
1460 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1461 | 0 | return; |
1462 | 0 | } |
1463 | | |
1464 | 0 | SourceLocation KeywordLoc = Tok.getLocation(); |
1465 | 0 | IdentifierInfo *Keyword = Tok.getIdentifierInfo(); |
1466 | 0 | if (Keyword == Ident_generated_declaration) { |
1467 | 0 | if (GeneratedDeclaration) { |
1468 | 0 | Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword; |
1469 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1470 | 0 | return; |
1471 | 0 | } |
1472 | 0 | GeneratedDeclaration = ParseIdentifierLoc(); |
1473 | 0 | continue; |
1474 | 0 | } |
1475 | | |
1476 | 0 | if (Keyword != Ident_language && Keyword != Ident_defined_in && |
1477 | 0 | Keyword != Ident_USR) { |
1478 | 0 | Diag(Tok, diag::err_external_source_symbol_expected_keyword); |
1479 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1480 | 0 | return; |
1481 | 0 | } |
1482 | | |
1483 | 0 | ConsumeToken(); |
1484 | 0 | if (ExpectAndConsume(tok::equal, diag::err_expected_after, |
1485 | 0 | Keyword->getName())) { |
1486 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1487 | 0 | return; |
1488 | 0 | } |
1489 | | |
1490 | 0 | bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn, |
1491 | 0 | HadUSR = HasUSR; |
1492 | 0 | if (Keyword == Ident_language) |
1493 | 0 | HasLanguage = true; |
1494 | 0 | else if (Keyword == Ident_USR) |
1495 | 0 | HasUSR = true; |
1496 | 0 | else |
1497 | 0 | HasDefinedIn = true; |
1498 | |
|
1499 | 0 | if (!isTokenStringLiteral()) { |
1500 | 0 | Diag(Tok, diag::err_expected_string_literal) |
1501 | 0 | << /*Source='external_source_symbol attribute'*/ 3 |
1502 | 0 | << /*language | source container | USR*/ ( |
1503 | 0 | Keyword == Ident_language |
1504 | 0 | ? 0 |
1505 | 0 | : (Keyword == Ident_defined_in ? 1 : 2)); |
1506 | 0 | SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); |
1507 | 0 | continue; |
1508 | 0 | } |
1509 | 0 | if (Keyword == Ident_language) { |
1510 | 0 | if (HadLanguage) { |
1511 | 0 | Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) |
1512 | 0 | << Keyword; |
1513 | 0 | ParseUnevaluatedStringLiteralExpression(); |
1514 | 0 | continue; |
1515 | 0 | } |
1516 | 0 | Language = ParseUnevaluatedStringLiteralExpression(); |
1517 | 0 | } else if (Keyword == Ident_USR) { |
1518 | 0 | if (HadUSR) { |
1519 | 0 | Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) |
1520 | 0 | << Keyword; |
1521 | 0 | ParseUnevaluatedStringLiteralExpression(); |
1522 | 0 | continue; |
1523 | 0 | } |
1524 | 0 | USR = ParseUnevaluatedStringLiteralExpression(); |
1525 | 0 | } else { |
1526 | 0 | assert(Keyword == Ident_defined_in && "Invalid clause keyword!"); |
1527 | 0 | if (HadDefinedIn) { |
1528 | 0 | Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) |
1529 | 0 | << Keyword; |
1530 | 0 | ParseUnevaluatedStringLiteralExpression(); |
1531 | 0 | continue; |
1532 | 0 | } |
1533 | 0 | DefinedInExpr = ParseUnevaluatedStringLiteralExpression(); |
1534 | 0 | } |
1535 | 0 | } while (TryConsumeToken(tok::comma)); |
1536 | | |
1537 | | // Closing ')'. |
1538 | 0 | if (T.consumeClose()) |
1539 | 0 | return; |
1540 | 0 | if (EndLoc) |
1541 | 0 | *EndLoc = T.getCloseLocation(); |
1542 | |
|
1543 | 0 | ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), GeneratedDeclaration, |
1544 | 0 | USR.get()}; |
1545 | 0 | Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()), |
1546 | 0 | ScopeName, ScopeLoc, Args, std::size(Args), Form); |
1547 | 0 | } |
1548 | | |
1549 | | /// Parse the contents of the "objc_bridge_related" attribute. |
1550 | | /// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')' |
1551 | | /// related_class: |
1552 | | /// Identifier |
1553 | | /// |
1554 | | /// opt-class_method: |
1555 | | /// Identifier: | <empty> |
1556 | | /// |
1557 | | /// opt-instance_method: |
1558 | | /// Identifier | <empty> |
1559 | | /// |
1560 | | void Parser::ParseObjCBridgeRelatedAttribute( |
1561 | | IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc, |
1562 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
1563 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
1564 | | // Opening '('. |
1565 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
1566 | 0 | if (T.consumeOpen()) { |
1567 | 0 | Diag(Tok, diag::err_expected) << tok::l_paren; |
1568 | 0 | return; |
1569 | 0 | } |
1570 | | |
1571 | | // Parse the related class name. |
1572 | 0 | if (Tok.isNot(tok::identifier)) { |
1573 | 0 | Diag(Tok, diag::err_objcbridge_related_expected_related_class); |
1574 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1575 | 0 | return; |
1576 | 0 | } |
1577 | 0 | IdentifierLoc *RelatedClass = ParseIdentifierLoc(); |
1578 | 0 | if (ExpectAndConsume(tok::comma)) { |
1579 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1580 | 0 | return; |
1581 | 0 | } |
1582 | | |
1583 | | // Parse class method name. It's non-optional in the sense that a trailing |
1584 | | // comma is required, but it can be the empty string, and then we record a |
1585 | | // nullptr. |
1586 | 0 | IdentifierLoc *ClassMethod = nullptr; |
1587 | 0 | if (Tok.is(tok::identifier)) { |
1588 | 0 | ClassMethod = ParseIdentifierLoc(); |
1589 | 0 | if (!TryConsumeToken(tok::colon)) { |
1590 | 0 | Diag(Tok, diag::err_objcbridge_related_selector_name); |
1591 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1592 | 0 | return; |
1593 | 0 | } |
1594 | 0 | } |
1595 | 0 | if (!TryConsumeToken(tok::comma)) { |
1596 | 0 | if (Tok.is(tok::colon)) |
1597 | 0 | Diag(Tok, diag::err_objcbridge_related_selector_name); |
1598 | 0 | else |
1599 | 0 | Diag(Tok, diag::err_expected) << tok::comma; |
1600 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1601 | 0 | return; |
1602 | 0 | } |
1603 | | |
1604 | | // Parse instance method name. Also non-optional but empty string is |
1605 | | // permitted. |
1606 | 0 | IdentifierLoc *InstanceMethod = nullptr; |
1607 | 0 | if (Tok.is(tok::identifier)) |
1608 | 0 | InstanceMethod = ParseIdentifierLoc(); |
1609 | 0 | else if (Tok.isNot(tok::r_paren)) { |
1610 | 0 | Diag(Tok, diag::err_expected) << tok::r_paren; |
1611 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
1612 | 0 | return; |
1613 | 0 | } |
1614 | | |
1615 | | // Closing ')'. |
1616 | 0 | if (T.consumeClose()) |
1617 | 0 | return; |
1618 | | |
1619 | 0 | if (EndLoc) |
1620 | 0 | *EndLoc = T.getCloseLocation(); |
1621 | | |
1622 | | // Record this attribute |
1623 | 0 | Attrs.addNew(&ObjCBridgeRelated, |
1624 | 0 | SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()), |
1625 | 0 | ScopeName, ScopeLoc, RelatedClass, ClassMethod, InstanceMethod, |
1626 | 0 | Form); |
1627 | 0 | } |
1628 | | |
1629 | | void Parser::ParseSwiftNewTypeAttribute( |
1630 | | IdentifierInfo &AttrName, SourceLocation AttrNameLoc, |
1631 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
1632 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
1633 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
1634 | | |
1635 | | // Opening '(' |
1636 | 0 | if (T.consumeOpen()) { |
1637 | 0 | Diag(Tok, diag::err_expected) << tok::l_paren; |
1638 | 0 | return; |
1639 | 0 | } |
1640 | | |
1641 | 0 | if (Tok.is(tok::r_paren)) { |
1642 | 0 | Diag(Tok.getLocation(), diag::err_argument_required_after_attribute); |
1643 | 0 | T.consumeClose(); |
1644 | 0 | return; |
1645 | 0 | } |
1646 | 0 | if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) { |
1647 | 0 | Diag(Tok, diag::warn_attribute_type_not_supported) |
1648 | 0 | << &AttrName << Tok.getIdentifierInfo(); |
1649 | 0 | if (!isTokenSpecial()) |
1650 | 0 | ConsumeToken(); |
1651 | 0 | T.consumeClose(); |
1652 | 0 | return; |
1653 | 0 | } |
1654 | | |
1655 | 0 | auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(), |
1656 | 0 | Tok.getIdentifierInfo()); |
1657 | 0 | ConsumeToken(); |
1658 | | |
1659 | | // Closing ')' |
1660 | 0 | if (T.consumeClose()) |
1661 | 0 | return; |
1662 | 0 | if (EndLoc) |
1663 | 0 | *EndLoc = T.getCloseLocation(); |
1664 | |
|
1665 | 0 | ArgsUnion Args[] = {SwiftType}; |
1666 | 0 | Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()), |
1667 | 0 | ScopeName, ScopeLoc, Args, std::size(Args), Form); |
1668 | 0 | } |
1669 | | |
1670 | | void Parser::ParseTypeTagForDatatypeAttribute( |
1671 | | IdentifierInfo &AttrName, SourceLocation AttrNameLoc, |
1672 | | ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, |
1673 | 0 | SourceLocation ScopeLoc, ParsedAttr::Form Form) { |
1674 | 0 | assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); |
1675 | | |
1676 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
1677 | 0 | T.consumeOpen(); |
1678 | |
|
1679 | 0 | if (Tok.isNot(tok::identifier)) { |
1680 | 0 | Diag(Tok, diag::err_expected) << tok::identifier; |
1681 | 0 | T.skipToEnd(); |
1682 | 0 | return; |
1683 | 0 | } |
1684 | 0 | IdentifierLoc *ArgumentKind = ParseIdentifierLoc(); |
1685 | |
|
1686 | 0 | if (ExpectAndConsume(tok::comma)) { |
1687 | 0 | T.skipToEnd(); |
1688 | 0 | return; |
1689 | 0 | } |
1690 | | |
1691 | 0 | SourceRange MatchingCTypeRange; |
1692 | 0 | TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange); |
1693 | 0 | if (MatchingCType.isInvalid()) { |
1694 | 0 | T.skipToEnd(); |
1695 | 0 | return; |
1696 | 0 | } |
1697 | | |
1698 | 0 | bool LayoutCompatible = false; |
1699 | 0 | bool MustBeNull = false; |
1700 | 0 | while (TryConsumeToken(tok::comma)) { |
1701 | 0 | if (Tok.isNot(tok::identifier)) { |
1702 | 0 | Diag(Tok, diag::err_expected) << tok::identifier; |
1703 | 0 | T.skipToEnd(); |
1704 | 0 | return; |
1705 | 0 | } |
1706 | 0 | IdentifierInfo *Flag = Tok.getIdentifierInfo(); |
1707 | 0 | if (Flag->isStr("layout_compatible")) |
1708 | 0 | LayoutCompatible = true; |
1709 | 0 | else if (Flag->isStr("must_be_null")) |
1710 | 0 | MustBeNull = true; |
1711 | 0 | else { |
1712 | 0 | Diag(Tok, diag::err_type_safety_unknown_flag) << Flag; |
1713 | 0 | T.skipToEnd(); |
1714 | 0 | return; |
1715 | 0 | } |
1716 | 0 | ConsumeToken(); // consume flag |
1717 | 0 | } |
1718 | | |
1719 | 0 | if (!T.consumeClose()) { |
1720 | 0 | Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc, |
1721 | 0 | ArgumentKind, MatchingCType.get(), |
1722 | 0 | LayoutCompatible, MustBeNull, Form); |
1723 | 0 | } |
1724 | |
|
1725 | 0 | if (EndLoc) |
1726 | 0 | *EndLoc = T.getCloseLocation(); |
1727 | 0 | } |
1728 | | |
1729 | | /// DiagnoseProhibitedCXX11Attribute - We have found the opening square brackets |
1730 | | /// of a C++11 attribute-specifier in a location where an attribute is not |
1731 | | /// permitted. By C++11 [dcl.attr.grammar]p6, this is ill-formed. Diagnose this |
1732 | | /// situation. |
1733 | | /// |
1734 | | /// \return \c true if we skipped an attribute-like chunk of tokens, \c false if |
1735 | | /// this doesn't appear to actually be an attribute-specifier, and the caller |
1736 | | /// should try to parse it. |
1737 | 5 | bool Parser::DiagnoseProhibitedCXX11Attribute() { |
1738 | 5 | assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)); |
1739 | | |
1740 | 0 | switch (isCXX11AttributeSpecifier(/*Disambiguate*/true)) { |
1741 | 4 | case CAK_NotAttributeSpecifier: |
1742 | | // No diagnostic: we're in Obj-C++11 and this is not actually an attribute. |
1743 | 4 | return false; |
1744 | | |
1745 | 1 | case CAK_InvalidAttributeSpecifier: |
1746 | 1 | Diag(Tok.getLocation(), diag::err_l_square_l_square_not_attribute); |
1747 | 1 | return false; |
1748 | | |
1749 | 0 | case CAK_AttributeSpecifier: |
1750 | | // Parse and discard the attributes. |
1751 | 0 | SourceLocation BeginLoc = ConsumeBracket(); |
1752 | 0 | ConsumeBracket(); |
1753 | 0 | SkipUntil(tok::r_square); |
1754 | 0 | assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied"); |
1755 | 0 | SourceLocation EndLoc = ConsumeBracket(); |
1756 | 0 | Diag(BeginLoc, diag::err_attributes_not_allowed) |
1757 | 0 | << SourceRange(BeginLoc, EndLoc); |
1758 | 0 | return true; |
1759 | 5 | } |
1760 | 0 | llvm_unreachable("All cases handled above."); |
1761 | 0 | } |
1762 | | |
1763 | | /// We have found the opening square brackets of a C++11 |
1764 | | /// attribute-specifier in a location where an attribute is not permitted, but |
1765 | | /// we know where the attributes ought to be written. Parse them anyway, and |
1766 | | /// provide a fixit moving them to the right place. |
1767 | | void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs, |
1768 | 0 | SourceLocation CorrectLocation) { |
1769 | 0 | assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) || |
1770 | 0 | Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute()); |
1771 | | |
1772 | | // Consume the attributes. |
1773 | 0 | auto Keyword = |
1774 | 0 | Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr; |
1775 | 0 | SourceLocation Loc = Tok.getLocation(); |
1776 | 0 | ParseCXX11Attributes(Attrs); |
1777 | 0 | CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true); |
1778 | | // FIXME: use err_attributes_misplaced |
1779 | 0 | (Keyword ? Diag(Loc, diag::err_keyword_not_allowed) << Keyword |
1780 | 0 | : Diag(Loc, diag::err_attributes_not_allowed)) |
1781 | 0 | << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) |
1782 | 0 | << FixItHint::CreateRemoval(AttrRange); |
1783 | 0 | } |
1784 | | |
1785 | | void Parser::DiagnoseProhibitedAttributes( |
1786 | 0 | const ParsedAttributesView &Attrs, const SourceLocation CorrectLocation) { |
1787 | 0 | auto *FirstAttr = Attrs.empty() ? nullptr : &Attrs.front(); |
1788 | 0 | if (CorrectLocation.isValid()) { |
1789 | 0 | CharSourceRange AttrRange(Attrs.Range, true); |
1790 | 0 | (FirstAttr && FirstAttr->isRegularKeywordAttribute() |
1791 | 0 | ? Diag(CorrectLocation, diag::err_keyword_misplaced) << FirstAttr |
1792 | 0 | : Diag(CorrectLocation, diag::err_attributes_misplaced)) |
1793 | 0 | << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) |
1794 | 0 | << FixItHint::CreateRemoval(AttrRange); |
1795 | 0 | } else { |
1796 | 0 | const SourceRange &Range = Attrs.Range; |
1797 | 0 | (FirstAttr && FirstAttr->isRegularKeywordAttribute() |
1798 | 0 | ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr |
1799 | 0 | : Diag(Range.getBegin(), diag::err_attributes_not_allowed)) |
1800 | 0 | << Range; |
1801 | 0 | } |
1802 | 0 | } |
1803 | | |
1804 | | void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs, |
1805 | | unsigned AttrDiagID, |
1806 | | unsigned KeywordDiagID, |
1807 | | bool DiagnoseEmptyAttrs, |
1808 | 0 | bool WarnOnUnknownAttrs) { |
1809 | |
|
1810 | 0 | if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) { |
1811 | | // An attribute list has been parsed, but it was empty. |
1812 | | // This is the case for [[]]. |
1813 | 0 | const auto &LangOpts = getLangOpts(); |
1814 | 0 | auto &SM = PP.getSourceManager(); |
1815 | 0 | Token FirstLSquare; |
1816 | 0 | Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts); |
1817 | |
|
1818 | 0 | if (FirstLSquare.is(tok::l_square)) { |
1819 | 0 | std::optional<Token> SecondLSquare = |
1820 | 0 | Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts); |
1821 | |
|
1822 | 0 | if (SecondLSquare && SecondLSquare->is(tok::l_square)) { |
1823 | | // The attribute range starts with [[, but is empty. So this must |
1824 | | // be [[]], which we are supposed to diagnose because |
1825 | | // DiagnoseEmptyAttrs is true. |
1826 | 0 | Diag(Attrs.Range.getBegin(), AttrDiagID) << Attrs.Range; |
1827 | 0 | return; |
1828 | 0 | } |
1829 | 0 | } |
1830 | 0 | } |
1831 | | |
1832 | 0 | for (const ParsedAttr &AL : Attrs) { |
1833 | 0 | if (AL.isRegularKeywordAttribute()) { |
1834 | 0 | Diag(AL.getLoc(), KeywordDiagID) << AL; |
1835 | 0 | AL.setInvalid(); |
1836 | 0 | continue; |
1837 | 0 | } |
1838 | 0 | if (!AL.isStandardAttributeSyntax()) |
1839 | 0 | continue; |
1840 | 0 | if (AL.getKind() == ParsedAttr::UnknownAttribute) { |
1841 | 0 | if (WarnOnUnknownAttrs) |
1842 | 0 | Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) |
1843 | 0 | << AL << AL.getRange(); |
1844 | 0 | } else { |
1845 | 0 | Diag(AL.getLoc(), AttrDiagID) << AL; |
1846 | 0 | AL.setInvalid(); |
1847 | 0 | } |
1848 | 0 | } |
1849 | 0 | } |
1850 | | |
1851 | 0 | void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) { |
1852 | 0 | for (const ParsedAttr &PA : Attrs) { |
1853 | 0 | if (PA.isStandardAttributeSyntax() || PA.isRegularKeywordAttribute()) |
1854 | 0 | Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) |
1855 | 0 | << PA << PA.isRegularKeywordAttribute() << PA.getRange(); |
1856 | 0 | } |
1857 | 0 | } |
1858 | | |
1859 | | // Usually, `__attribute__((attrib)) class Foo {} var` means that attribute |
1860 | | // applies to var, not the type Foo. |
1861 | | // As an exception to the rule, __declspec(align(...)) before the |
1862 | | // class-key affects the type instead of the variable. |
1863 | | // Also, Microsoft-style [attributes] seem to affect the type instead of the |
1864 | | // variable. |
1865 | | // This function moves attributes that should apply to the type off DS to Attrs. |
1866 | | void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs, |
1867 | | DeclSpec &DS, |
1868 | 0 | Sema::TagUseKind TUK) { |
1869 | 0 | if (TUK == Sema::TUK_Reference) |
1870 | 0 | return; |
1871 | | |
1872 | 0 | llvm::SmallVector<ParsedAttr *, 1> ToBeMoved; |
1873 | |
|
1874 | 0 | for (ParsedAttr &AL : DS.getAttributes()) { |
1875 | 0 | if ((AL.getKind() == ParsedAttr::AT_Aligned && |
1876 | 0 | AL.isDeclspecAttribute()) || |
1877 | 0 | AL.isMicrosoftAttribute()) |
1878 | 0 | ToBeMoved.push_back(&AL); |
1879 | 0 | } |
1880 | |
|
1881 | 0 | for (ParsedAttr *AL : ToBeMoved) { |
1882 | 0 | DS.getAttributes().remove(AL); |
1883 | 0 | Attrs.addAtEnd(AL); |
1884 | 0 | } |
1885 | 0 | } |
1886 | | |
1887 | | /// ParseDeclaration - Parse a full 'declaration', which consists of |
1888 | | /// declaration-specifiers, some number of declarators, and a semicolon. |
1889 | | /// 'Context' should be a DeclaratorContext value. This returns the |
1890 | | /// location of the semicolon in DeclEnd. |
1891 | | /// |
1892 | | /// declaration: [C99 6.7] |
1893 | | /// block-declaration -> |
1894 | | /// simple-declaration |
1895 | | /// others [FIXME] |
1896 | | /// [C++] template-declaration |
1897 | | /// [C++] namespace-definition |
1898 | | /// [C++] using-directive |
1899 | | /// [C++] using-declaration |
1900 | | /// [C++11/C11] static_assert-declaration |
1901 | | /// others... [FIXME] |
1902 | | /// |
1903 | | Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, |
1904 | | SourceLocation &DeclEnd, |
1905 | | ParsedAttributes &DeclAttrs, |
1906 | | ParsedAttributes &DeclSpecAttrs, |
1907 | 0 | SourceLocation *DeclSpecStart) { |
1908 | 0 | ParenBraceBracketBalancer BalancerRAIIObj(*this); |
1909 | | // Must temporarily exit the objective-c container scope for |
1910 | | // parsing c none objective-c decls. |
1911 | 0 | ObjCDeclContextSwitch ObjCDC(*this); |
1912 | |
|
1913 | 0 | Decl *SingleDecl = nullptr; |
1914 | 0 | switch (Tok.getKind()) { |
1915 | 0 | case tok::kw_template: |
1916 | 0 | case tok::kw_export: |
1917 | 0 | ProhibitAttributes(DeclAttrs); |
1918 | 0 | ProhibitAttributes(DeclSpecAttrs); |
1919 | 0 | SingleDecl = |
1920 | 0 | ParseDeclarationStartingWithTemplate(Context, DeclEnd, DeclAttrs); |
1921 | 0 | break; |
1922 | 0 | case tok::kw_inline: |
1923 | | // Could be the start of an inline namespace. Allowed as an ext in C++03. |
1924 | 0 | if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) { |
1925 | 0 | ProhibitAttributes(DeclAttrs); |
1926 | 0 | ProhibitAttributes(DeclSpecAttrs); |
1927 | 0 | SourceLocation InlineLoc = ConsumeToken(); |
1928 | 0 | return ParseNamespace(Context, DeclEnd, InlineLoc); |
1929 | 0 | } |
1930 | 0 | return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs, |
1931 | 0 | true, nullptr, DeclSpecStart); |
1932 | | |
1933 | 0 | case tok::kw_cbuffer: |
1934 | 0 | case tok::kw_tbuffer: |
1935 | 0 | SingleDecl = ParseHLSLBuffer(DeclEnd); |
1936 | 0 | break; |
1937 | 0 | case tok::kw_namespace: |
1938 | 0 | ProhibitAttributes(DeclAttrs); |
1939 | 0 | ProhibitAttributes(DeclSpecAttrs); |
1940 | 0 | return ParseNamespace(Context, DeclEnd); |
1941 | 0 | case tok::kw_using: { |
1942 | 0 | ParsedAttributes Attrs(AttrFactory); |
1943 | 0 | takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs); |
1944 | 0 | return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), |
1945 | 0 | DeclEnd, Attrs); |
1946 | 0 | } |
1947 | 0 | case tok::kw_static_assert: |
1948 | 0 | case tok::kw__Static_assert: |
1949 | 0 | ProhibitAttributes(DeclAttrs); |
1950 | 0 | ProhibitAttributes(DeclSpecAttrs); |
1951 | 0 | SingleDecl = ParseStaticAssertDeclaration(DeclEnd); |
1952 | 0 | break; |
1953 | 0 | default: |
1954 | 0 | return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs, |
1955 | 0 | true, nullptr, DeclSpecStart); |
1956 | 0 | } |
1957 | | |
1958 | | // This routine returns a DeclGroup, if the thing we parsed only contains a |
1959 | | // single decl, convert it now. |
1960 | 0 | return Actions.ConvertDeclToDeclGroup(SingleDecl); |
1961 | 0 | } |
1962 | | |
1963 | | /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] |
1964 | | /// declaration-specifiers init-declarator-list[opt] ';' |
1965 | | /// [C++11] attribute-specifier-seq decl-specifier-seq[opt] |
1966 | | /// init-declarator-list ';' |
1967 | | ///[C90/C++]init-declarator-list ';' [TODO] |
1968 | | /// [OMP] threadprivate-directive |
1969 | | /// [OMP] allocate-directive [TODO] |
1970 | | /// |
1971 | | /// for-range-declaration: [C++11 6.5p1: stmt.ranged] |
1972 | | /// attribute-specifier-seq[opt] type-specifier-seq declarator |
1973 | | /// |
1974 | | /// If RequireSemi is false, this does not check for a ';' at the end of the |
1975 | | /// declaration. If it is true, it checks for and eats it. |
1976 | | /// |
1977 | | /// If FRI is non-null, we might be parsing a for-range-declaration instead |
1978 | | /// of a simple-declaration. If we find that we are, we also parse the |
1979 | | /// for-range-initializer, and place it here. |
1980 | | /// |
1981 | | /// DeclSpecStart is used when decl-specifiers are parsed before parsing |
1982 | | /// the Declaration. The SourceLocation for this Decl is set to |
1983 | | /// DeclSpecStart if DeclSpecStart is non-null. |
1984 | | Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( |
1985 | | DeclaratorContext Context, SourceLocation &DeclEnd, |
1986 | | ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs, |
1987 | 0 | bool RequireSemi, ForRangeInit *FRI, SourceLocation *DeclSpecStart) { |
1988 | | // Need to retain these for diagnostics before we add them to the DeclSepc. |
1989 | 0 | ParsedAttributesView OriginalDeclSpecAttrs; |
1990 | 0 | OriginalDeclSpecAttrs.addAll(DeclSpecAttrs.begin(), DeclSpecAttrs.end()); |
1991 | 0 | OriginalDeclSpecAttrs.Range = DeclSpecAttrs.Range; |
1992 | | |
1993 | | // Parse the common declaration-specifiers piece. |
1994 | 0 | ParsingDeclSpec DS(*this); |
1995 | 0 | DS.takeAttributesFrom(DeclSpecAttrs); |
1996 | |
|
1997 | 0 | DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context); |
1998 | 0 | ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext); |
1999 | | |
2000 | | // If we had a free-standing type definition with a missing semicolon, we |
2001 | | // may get this far before the problem becomes obvious. |
2002 | 0 | if (DS.hasTagDefinition() && |
2003 | 0 | DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext)) |
2004 | 0 | return nullptr; |
2005 | | |
2006 | | // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" |
2007 | | // declaration-specifiers init-declarator-list[opt] ';' |
2008 | 0 | if (Tok.is(tok::semi)) { |
2009 | 0 | ProhibitAttributes(DeclAttrs); |
2010 | 0 | DeclEnd = Tok.getLocation(); |
2011 | 0 | if (RequireSemi) ConsumeToken(); |
2012 | 0 | RecordDecl *AnonRecord = nullptr; |
2013 | 0 | Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( |
2014 | 0 | getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord); |
2015 | 0 | Actions.ActOnDefinedDeclarationSpecifier(TheDecl); |
2016 | 0 | DS.complete(TheDecl); |
2017 | 0 | if (AnonRecord) { |
2018 | 0 | Decl* decls[] = {AnonRecord, TheDecl}; |
2019 | 0 | return Actions.BuildDeclaratorGroup(decls); |
2020 | 0 | } |
2021 | 0 | return Actions.ConvertDeclToDeclGroup(TheDecl); |
2022 | 0 | } |
2023 | | |
2024 | 0 | if (DS.hasTagDefinition()) |
2025 | 0 | Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl()); |
2026 | |
|
2027 | 0 | if (DeclSpecStart) |
2028 | 0 | DS.SetRangeStart(*DeclSpecStart); |
2029 | |
|
2030 | 0 | return ParseDeclGroup(DS, Context, DeclAttrs, &DeclEnd, FRI); |
2031 | 0 | } |
2032 | | |
2033 | | /// Returns true if this might be the start of a declarator, or a common typo |
2034 | | /// for a declarator. |
2035 | 7 | bool Parser::MightBeDeclarator(DeclaratorContext Context) { |
2036 | 7 | switch (Tok.getKind()) { |
2037 | 0 | case tok::annot_cxxscope: |
2038 | 0 | case tok::annot_template_id: |
2039 | 0 | case tok::caret: |
2040 | 0 | case tok::code_completion: |
2041 | 0 | case tok::coloncolon: |
2042 | 0 | case tok::ellipsis: |
2043 | 0 | case tok::kw___attribute: |
2044 | 0 | case tok::kw_operator: |
2045 | 0 | case tok::l_paren: |
2046 | 0 | case tok::star: |
2047 | 0 | return true; |
2048 | | |
2049 | 0 | case tok::amp: |
2050 | 0 | case tok::ampamp: |
2051 | 0 | return getLangOpts().CPlusPlus; |
2052 | | |
2053 | 0 | case tok::l_square: // Might be an attribute on an unnamed bit-field. |
2054 | 0 | return Context == DeclaratorContext::Member && getLangOpts().CPlusPlus11 && |
2055 | 0 | NextToken().is(tok::l_square); |
2056 | | |
2057 | 0 | case tok::colon: // Might be a typo for '::' or an unnamed bit-field. |
2058 | 0 | return Context == DeclaratorContext::Member || getLangOpts().CPlusPlus; |
2059 | | |
2060 | 3 | case tok::identifier: |
2061 | 3 | switch (NextToken().getKind()) { |
2062 | 0 | case tok::code_completion: |
2063 | 0 | case tok::coloncolon: |
2064 | 0 | case tok::comma: |
2065 | 0 | case tok::equal: |
2066 | 0 | case tok::equalequal: // Might be a typo for '='. |
2067 | 0 | case tok::kw_alignas: |
2068 | 0 | case tok::kw_asm: |
2069 | 0 | case tok::kw___attribute: |
2070 | 0 | case tok::l_brace: |
2071 | 0 | case tok::l_paren: |
2072 | 0 | case tok::l_square: |
2073 | 0 | case tok::less: |
2074 | 0 | case tok::r_brace: |
2075 | 0 | case tok::r_paren: |
2076 | 0 | case tok::r_square: |
2077 | 0 | case tok::semi: |
2078 | 0 | return true; |
2079 | | |
2080 | 0 | case tok::colon: |
2081 | | // At namespace scope, 'identifier:' is probably a typo for 'identifier::' |
2082 | | // and in block scope it's probably a label. Inside a class definition, |
2083 | | // this is a bit-field. |
2084 | 0 | return Context == DeclaratorContext::Member || |
2085 | 0 | (getLangOpts().CPlusPlus && Context == DeclaratorContext::File); |
2086 | | |
2087 | 3 | case tok::identifier: // Possible virt-specifier. |
2088 | 3 | return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken()); |
2089 | | |
2090 | 0 | default: |
2091 | 0 | return Tok.isRegularKeywordAttribute(); |
2092 | 3 | } |
2093 | | |
2094 | 4 | default: |
2095 | 4 | return Tok.isRegularKeywordAttribute(); |
2096 | 7 | } |
2097 | 7 | } |
2098 | | |
2099 | | /// Skip until we reach something which seems like a sensible place to pick |
2100 | | /// up parsing after a malformed declaration. This will sometimes stop sooner |
2101 | | /// than SkipUntil(tok::r_brace) would, but will never stop later. |
2102 | 23.1k | void Parser::SkipMalformedDecl() { |
2103 | 1.89M | while (true) { |
2104 | 1.89M | switch (Tok.getKind()) { |
2105 | 6.83k | case tok::l_brace: |
2106 | | // Skip until matching }, then stop. We've probably skipped over |
2107 | | // a malformed class or function definition or similar. |
2108 | 6.83k | ConsumeBrace(); |
2109 | 6.83k | SkipUntil(tok::r_brace); |
2110 | 6.83k | if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) { |
2111 | | // This declaration isn't over yet. Keep skipping. |
2112 | 61 | continue; |
2113 | 61 | } |
2114 | 6.77k | TryConsumeToken(tok::semi); |
2115 | 6.77k | return; |
2116 | | |
2117 | 7.17k | case tok::l_square: |
2118 | 7.17k | ConsumeBracket(); |
2119 | 7.17k | SkipUntil(tok::r_square); |
2120 | 7.17k | continue; |
2121 | | |
2122 | 6.76k | case tok::l_paren: |
2123 | 6.76k | ConsumeParen(); |
2124 | 6.76k | SkipUntil(tok::r_paren); |
2125 | 6.76k | continue; |
2126 | | |
2127 | 9.26k | case tok::r_brace: |
2128 | 9.26k | return; |
2129 | | |
2130 | 7.06k | case tok::semi: |
2131 | 7.06k | ConsumeToken(); |
2132 | 7.06k | return; |
2133 | | |
2134 | 1 | case tok::kw_inline: |
2135 | | // 'inline namespace' at the start of a line is almost certainly |
2136 | | // a good place to pick back up parsing, except in an Objective-C |
2137 | | // @interface context. |
2138 | 1 | if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) && |
2139 | 1 | (!ParsingInObjCContainer || CurParsedObjCImpl)) |
2140 | 0 | return; |
2141 | 1 | break; |
2142 | | |
2143 | 1 | case tok::kw_namespace: |
2144 | | // 'namespace' at the start of a line is almost certainly a good |
2145 | | // place to pick back up parsing, except in an Objective-C |
2146 | | // @interface context. |
2147 | 0 | if (Tok.isAtStartOfLine() && |
2148 | 0 | (!ParsingInObjCContainer || CurParsedObjCImpl)) |
2149 | 0 | return; |
2150 | 0 | break; |
2151 | | |
2152 | 3.69k | case tok::at: |
2153 | | // @end is very much like } in Objective-C contexts. |
2154 | 3.69k | if (NextToken().isObjCAtKeyword(tok::objc_end) && |
2155 | 3.69k | ParsingInObjCContainer) |
2156 | 0 | return; |
2157 | 3.69k | break; |
2158 | | |
2159 | 14.0k | case tok::minus: |
2160 | 20.6k | case tok::plus: |
2161 | | // - and + probably start new method declarations in Objective-C contexts. |
2162 | 20.6k | if (Tok.isAtStartOfLine() && ParsingInObjCContainer) |
2163 | 0 | return; |
2164 | 20.6k | break; |
2165 | | |
2166 | 20.6k | case tok::eof: |
2167 | 32 | case tok::annot_module_begin: |
2168 | 32 | case tok::annot_module_end: |
2169 | 32 | case tok::annot_module_include: |
2170 | 32 | case tok::annot_repl_input_end: |
2171 | 32 | return; |
2172 | | |
2173 | 1.83M | default: |
2174 | 1.83M | break; |
2175 | 1.89M | } |
2176 | | |
2177 | 1.85M | ConsumeAnyToken(); |
2178 | 1.85M | } |
2179 | 23.1k | } |
2180 | | |
2181 | | /// ParseDeclGroup - Having concluded that this is either a function |
2182 | | /// definition or a group of object declarations, actually parse the |
2183 | | /// result. |
2184 | | Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, |
2185 | | DeclaratorContext Context, |
2186 | | ParsedAttributes &Attrs, |
2187 | | SourceLocation *DeclEnd, |
2188 | 23.7k | ForRangeInit *FRI) { |
2189 | | // Parse the first declarator. |
2190 | | // Consume all of the attributes from `Attrs` by moving them to our own local |
2191 | | // list. This ensures that we will not attempt to interpret them as statement |
2192 | | // attributes higher up the callchain. |
2193 | 23.7k | ParsedAttributes LocalAttrs(AttrFactory); |
2194 | 23.7k | LocalAttrs.takeAllFrom(Attrs); |
2195 | 23.7k | ParsingDeclarator D(*this, DS, LocalAttrs, Context); |
2196 | 23.7k | ParseDeclarator(D); |
2197 | | |
2198 | | // Bail out if the first declarator didn't seem well-formed. |
2199 | 23.7k | if (!D.hasName() && !D.mayOmitIdentifier()) { |
2200 | 18.5k | SkipMalformedDecl(); |
2201 | 18.5k | return nullptr; |
2202 | 18.5k | } |
2203 | | |
2204 | 5.12k | if (getLangOpts().HLSL) |
2205 | 0 | MaybeParseHLSLSemantics(D); |
2206 | | |
2207 | 5.12k | if (Tok.is(tok::kw_requires)) |
2208 | 0 | ParseTrailingRequiresClause(D); |
2209 | | |
2210 | | // Save late-parsed attributes for now; they need to be parsed in the |
2211 | | // appropriate function scope after the function Decl has been constructed. |
2212 | | // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList. |
2213 | 5.12k | LateParsedAttrList LateParsedAttrs(true); |
2214 | 5.12k | if (D.isFunctionDeclarator()) { |
2215 | 77 | MaybeParseGNUAttributes(D, &LateParsedAttrs); |
2216 | | |
2217 | | // The _Noreturn keyword can't appear here, unlike the GNU noreturn |
2218 | | // attribute. If we find the keyword here, tell the user to put it |
2219 | | // at the start instead. |
2220 | 77 | if (Tok.is(tok::kw__Noreturn)) { |
2221 | 0 | SourceLocation Loc = ConsumeToken(); |
2222 | 0 | const char *PrevSpec; |
2223 | 0 | unsigned DiagID; |
2224 | | |
2225 | | // We can offer a fixit if it's valid to mark this function as _Noreturn |
2226 | | // and we don't have any other declarators in this declaration. |
2227 | 0 | bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); |
2228 | 0 | MaybeParseGNUAttributes(D, &LateParsedAttrs); |
2229 | 0 | Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try); |
2230 | |
|
2231 | 0 | Diag(Loc, diag::err_c11_noreturn_misplaced) |
2232 | 0 | << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint()) |
2233 | 0 | << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ") |
2234 | 0 | : FixItHint()); |
2235 | 0 | } |
2236 | | |
2237 | | // Check to see if we have a function *definition* which must have a body. |
2238 | 77 | if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) { |
2239 | 0 | cutOffParsing(); |
2240 | 0 | Actions.CodeCompleteAfterFunctionEquals(D); |
2241 | 0 | return nullptr; |
2242 | 0 | } |
2243 | | // We're at the point where the parsing of function declarator is finished. |
2244 | | // |
2245 | | // A common error is that users accidently add a virtual specifier |
2246 | | // (e.g. override) in an out-line method definition. |
2247 | | // We attempt to recover by stripping all these specifiers coming after |
2248 | | // the declarator. |
2249 | 77 | while (auto Specifier = isCXX11VirtSpecifier()) { |
2250 | 0 | Diag(Tok, diag::err_virt_specifier_outside_class) |
2251 | 0 | << VirtSpecifiers::getSpecifierName(Specifier) |
2252 | 0 | << FixItHint::CreateRemoval(Tok.getLocation()); |
2253 | 0 | ConsumeToken(); |
2254 | 0 | } |
2255 | | // Look at the next token to make sure that this isn't a function |
2256 | | // declaration. We have to check this because __attribute__ might be the |
2257 | | // start of a function definition in GCC-extended K&R C. |
2258 | 77 | if (!isDeclarationAfterDeclarator()) { |
2259 | | |
2260 | | // Function definitions are only allowed at file scope and in C++ classes. |
2261 | | // The C++ inline method definition case is handled elsewhere, so we only |
2262 | | // need to handle the file scope definition case. |
2263 | 59 | if (Context == DeclaratorContext::File) { |
2264 | 59 | if (isStartOfFunctionDefinition(D)) { |
2265 | 0 | if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { |
2266 | 0 | Diag(Tok, diag::err_function_declared_typedef); |
2267 | | |
2268 | | // Recover by treating the 'typedef' as spurious. |
2269 | 0 | DS.ClearStorageClassSpecs(); |
2270 | 0 | } |
2271 | |
|
2272 | 0 | Decl *TheDecl = ParseFunctionDefinition(D, ParsedTemplateInfo(), |
2273 | 0 | &LateParsedAttrs); |
2274 | 0 | return Actions.ConvertDeclToDeclGroup(TheDecl); |
2275 | 0 | } |
2276 | | |
2277 | 59 | if (isDeclarationSpecifier(ImplicitTypenameContext::No) || |
2278 | 59 | Tok.is(tok::kw_namespace)) { |
2279 | | // If there is an invalid declaration specifier or a namespace |
2280 | | // definition right after the function prototype, then we must be in a |
2281 | | // missing semicolon case where this isn't actually a body. Just fall |
2282 | | // through into the code that handles it as a prototype, and let the |
2283 | | // top-level code handle the erroneous declspec where it would |
2284 | | // otherwise expect a comma or semicolon. Note that |
2285 | | // isDeclarationSpecifier already covers 'inline namespace', since |
2286 | | // 'inline' can be a declaration specifier. |
2287 | 59 | } else { |
2288 | 59 | Diag(Tok, diag::err_expected_fn_body); |
2289 | 59 | SkipUntil(tok::semi); |
2290 | 59 | return nullptr; |
2291 | 59 | } |
2292 | 59 | } else { |
2293 | 0 | if (Tok.is(tok::l_brace)) { |
2294 | 0 | Diag(Tok, diag::err_function_definition_not_allowed); |
2295 | 0 | SkipMalformedDecl(); |
2296 | 0 | return nullptr; |
2297 | 0 | } |
2298 | 0 | } |
2299 | 59 | } |
2300 | 77 | } |
2301 | | |
2302 | 5.06k | if (ParseAsmAttributesAfterDeclarator(D)) |
2303 | 0 | return nullptr; |
2304 | | |
2305 | | // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we |
2306 | | // must parse and analyze the for-range-initializer before the declaration is |
2307 | | // analyzed. |
2308 | | // |
2309 | | // Handle the Objective-C for-in loop variable similarly, although we |
2310 | | // don't need to parse the container in advance. |
2311 | 5.06k | if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) { |
2312 | 0 | bool IsForRangeLoop = false; |
2313 | 0 | if (TryConsumeToken(tok::colon, FRI->ColonLoc)) { |
2314 | 0 | IsForRangeLoop = true; |
2315 | 0 | if (getLangOpts().OpenMP) |
2316 | 0 | Actions.startOpenMPCXXRangeFor(); |
2317 | 0 | if (Tok.is(tok::l_brace)) |
2318 | 0 | FRI->RangeExpr = ParseBraceInitializer(); |
2319 | 0 | else |
2320 | 0 | FRI->RangeExpr = ParseExpression(); |
2321 | 0 | } |
2322 | |
|
2323 | 0 | Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); |
2324 | 0 | if (IsForRangeLoop) { |
2325 | 0 | Actions.ActOnCXXForRangeDecl(ThisDecl); |
2326 | 0 | } else { |
2327 | | // Obj-C for loop |
2328 | 0 | if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl)) |
2329 | 0 | VD->setObjCForDecl(true); |
2330 | 0 | } |
2331 | 0 | Actions.FinalizeDeclaration(ThisDecl); |
2332 | 0 | D.complete(ThisDecl); |
2333 | 0 | return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl); |
2334 | 0 | } |
2335 | | |
2336 | 5.06k | SmallVector<Decl *, 8> DeclsInGroup; |
2337 | 5.06k | Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes( |
2338 | 5.06k | D, ParsedTemplateInfo(), FRI); |
2339 | 5.06k | if (LateParsedAttrs.size() > 0) |
2340 | 0 | ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); |
2341 | 5.06k | D.complete(FirstDecl); |
2342 | 5.06k | if (FirstDecl) |
2343 | 5.06k | DeclsInGroup.push_back(FirstDecl); |
2344 | | |
2345 | 5.06k | bool ExpectSemi = Context != DeclaratorContext::ForInit; |
2346 | | |
2347 | | // If we don't have a comma, it is either the end of the list (a ';') or an |
2348 | | // error, bail out. |
2349 | 5.06k | SourceLocation CommaLoc; |
2350 | 5.23k | while (TryConsumeToken(tok::comma, CommaLoc)) { |
2351 | 179 | if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) { |
2352 | | // This comma was followed by a line-break and something which can't be |
2353 | | // the start of a declarator. The comma was probably a typo for a |
2354 | | // semicolon. |
2355 | 7 | Diag(CommaLoc, diag::err_expected_semi_declaration) |
2356 | 7 | << FixItHint::CreateReplacement(CommaLoc, ";"); |
2357 | 7 | ExpectSemi = false; |
2358 | 7 | break; |
2359 | 7 | } |
2360 | | |
2361 | | // Parse the next declarator. |
2362 | 172 | D.clear(); |
2363 | 172 | D.setCommaLoc(CommaLoc); |
2364 | | |
2365 | | // Accept attributes in an init-declarator. In the first declarator in a |
2366 | | // declaration, these would be part of the declspec. In subsequent |
2367 | | // declarators, they become part of the declarator itself, so that they |
2368 | | // don't apply to declarators after *this* one. Examples: |
2369 | | // short __attribute__((common)) var; -> declspec |
2370 | | // short var __attribute__((common)); -> declarator |
2371 | | // short x, __attribute__((common)) var; -> declarator |
2372 | 172 | MaybeParseGNUAttributes(D); |
2373 | | |
2374 | | // MSVC parses but ignores qualifiers after the comma as an extension. |
2375 | 172 | if (getLangOpts().MicrosoftExt) |
2376 | 0 | DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); |
2377 | | |
2378 | 172 | ParseDeclarator(D); |
2379 | | |
2380 | 172 | if (getLangOpts().HLSL) |
2381 | 0 | MaybeParseHLSLSemantics(D); |
2382 | | |
2383 | 172 | if (!D.isInvalidType()) { |
2384 | | // C++2a [dcl.decl]p1 |
2385 | | // init-declarator: |
2386 | | // declarator initializer[opt] |
2387 | | // declarator requires-clause |
2388 | 27 | if (Tok.is(tok::kw_requires)) |
2389 | 0 | ParseTrailingRequiresClause(D); |
2390 | 27 | Decl *ThisDecl = ParseDeclarationAfterDeclarator(D); |
2391 | 27 | D.complete(ThisDecl); |
2392 | 27 | if (ThisDecl) |
2393 | 27 | DeclsInGroup.push_back(ThisDecl); |
2394 | 27 | } |
2395 | 172 | } |
2396 | | |
2397 | 5.06k | if (DeclEnd) |
2398 | 0 | *DeclEnd = Tok.getLocation(); |
2399 | | |
2400 | 5.06k | if (ExpectSemi && ExpectAndConsumeSemi( |
2401 | 5.05k | Context == DeclaratorContext::File |
2402 | 5.05k | ? diag::err_invalid_token_after_toplevel_declarator |
2403 | 5.05k | : diag::err_expected_semi_declaration)) { |
2404 | | // Okay, there was no semicolon and one was expected. If we see a |
2405 | | // declaration specifier, just assume it was missing and continue parsing. |
2406 | | // Otherwise things are very confused and we skip to recover. |
2407 | 4.56k | if (!isDeclarationSpecifier(ImplicitTypenameContext::No)) |
2408 | 4.54k | SkipMalformedDecl(); |
2409 | 4.56k | } |
2410 | | |
2411 | 5.06k | return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); |
2412 | 5.06k | } |
2413 | | |
2414 | | /// Parse an optional simple-asm-expr and attributes, and attach them to a |
2415 | | /// declarator. Returns true on an error. |
2416 | 5.08k | bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) { |
2417 | | // If a simple-asm-expr is present, parse it. |
2418 | 5.08k | if (Tok.is(tok::kw_asm)) { |
2419 | 0 | SourceLocation Loc; |
2420 | 0 | ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc)); |
2421 | 0 | if (AsmLabel.isInvalid()) { |
2422 | 0 | SkipUntil(tok::semi, StopBeforeMatch); |
2423 | 0 | return true; |
2424 | 0 | } |
2425 | | |
2426 | 0 | D.setAsmLabel(AsmLabel.get()); |
2427 | 0 | D.SetRangeEnd(Loc); |
2428 | 0 | } |
2429 | | |
2430 | 5.08k | MaybeParseGNUAttributes(D); |
2431 | 5.08k | return false; |
2432 | 5.08k | } |
2433 | | |
2434 | | /// Parse 'declaration' after parsing 'declaration-specifiers |
2435 | | /// declarator'. This method parses the remainder of the declaration |
2436 | | /// (including any attributes or initializer, among other things) and |
2437 | | /// finalizes the declaration. |
2438 | | /// |
2439 | | /// init-declarator: [C99 6.7] |
2440 | | /// declarator |
2441 | | /// declarator '=' initializer |
2442 | | /// [GNU] declarator simple-asm-expr[opt] attributes[opt] |
2443 | | /// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer |
2444 | | /// [C++] declarator initializer[opt] |
2445 | | /// |
2446 | | /// [C++] initializer: |
2447 | | /// [C++] '=' initializer-clause |
2448 | | /// [C++] '(' expression-list ')' |
2449 | | /// [C++0x] '=' 'default' [TODO] |
2450 | | /// [C++0x] '=' 'delete' |
2451 | | /// [C++0x] braced-init-list |
2452 | | /// |
2453 | | /// According to the standard grammar, =default and =delete are function |
2454 | | /// definitions, but that definitely doesn't fit with the parser here. |
2455 | | /// |
2456 | | Decl *Parser::ParseDeclarationAfterDeclarator( |
2457 | 27 | Declarator &D, const ParsedTemplateInfo &TemplateInfo) { |
2458 | 27 | if (ParseAsmAttributesAfterDeclarator(D)) |
2459 | 0 | return nullptr; |
2460 | | |
2461 | 27 | return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); |
2462 | 27 | } |
2463 | | |
2464 | | Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( |
2465 | 5.08k | Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) { |
2466 | | // RAII type used to track whether we're inside an initializer. |
2467 | 5.08k | struct InitializerScopeRAII { |
2468 | 5.08k | Parser &P; |
2469 | 5.08k | Declarator &D; |
2470 | 5.08k | Decl *ThisDecl; |
2471 | | |
2472 | 5.08k | InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl) |
2473 | 5.08k | : P(P), D(D), ThisDecl(ThisDecl) { |
2474 | 382 | if (ThisDecl && P.getLangOpts().CPlusPlus) { |
2475 | 304 | Scope *S = nullptr; |
2476 | 304 | if (D.getCXXScopeSpec().isSet()) { |
2477 | 0 | P.EnterScope(0); |
2478 | 0 | S = P.getCurScope(); |
2479 | 0 | } |
2480 | 304 | P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl); |
2481 | 304 | } |
2482 | 382 | } |
2483 | 5.08k | ~InitializerScopeRAII() { pop(); } |
2484 | 5.08k | void pop() { |
2485 | 764 | if (ThisDecl && P.getLangOpts().CPlusPlus) { |
2486 | 304 | Scope *S = nullptr; |
2487 | 304 | if (D.getCXXScopeSpec().isSet()) |
2488 | 0 | S = P.getCurScope(); |
2489 | 304 | P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl); |
2490 | 304 | if (S) |
2491 | 0 | P.ExitScope(); |
2492 | 304 | } |
2493 | 764 | ThisDecl = nullptr; |
2494 | 764 | } |
2495 | 5.08k | }; |
2496 | | |
2497 | 5.08k | enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced }; |
2498 | 5.08k | InitKind TheInitKind; |
2499 | | // If a '==' or '+=' is found, suggest a fixit to '='. |
2500 | 5.08k | if (isTokenEqualOrEqualTypo()) |
2501 | 209 | TheInitKind = InitKind::Equal; |
2502 | 4.88k | else if (Tok.is(tok::l_paren)) |
2503 | 55 | TheInitKind = InitKind::CXXDirect; |
2504 | 4.82k | else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) && |
2505 | 4.82k | (!CurParsedObjCImpl || !D.isFunctionDeclarator())) |
2506 | 118 | TheInitKind = InitKind::CXXBraced; |
2507 | 4.70k | else |
2508 | 4.70k | TheInitKind = InitKind::Uninitialized; |
2509 | 5.08k | if (TheInitKind != InitKind::Uninitialized) |
2510 | 382 | D.setHasInitializer(); |
2511 | | |
2512 | | // Inform Sema that we just parsed this declarator. |
2513 | 5.08k | Decl *ThisDecl = nullptr; |
2514 | 5.08k | Decl *OuterDecl = nullptr; |
2515 | 5.08k | switch (TemplateInfo.Kind) { |
2516 | 5.08k | case ParsedTemplateInfo::NonTemplate: |
2517 | 5.08k | ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); |
2518 | 5.08k | break; |
2519 | | |
2520 | 0 | case ParsedTemplateInfo::Template: |
2521 | 0 | case ParsedTemplateInfo::ExplicitSpecialization: { |
2522 | 0 | ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(), |
2523 | 0 | *TemplateInfo.TemplateParams, |
2524 | 0 | D); |
2525 | 0 | if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl)) { |
2526 | | // Re-direct this decl to refer to the templated decl so that we can |
2527 | | // initialize it. |
2528 | 0 | ThisDecl = VT->getTemplatedDecl(); |
2529 | 0 | OuterDecl = VT; |
2530 | 0 | } |
2531 | 0 | break; |
2532 | 0 | } |
2533 | 0 | case ParsedTemplateInfo::ExplicitInstantiation: { |
2534 | 0 | if (Tok.is(tok::semi)) { |
2535 | 0 | DeclResult ThisRes = Actions.ActOnExplicitInstantiation( |
2536 | 0 | getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D); |
2537 | 0 | if (ThisRes.isInvalid()) { |
2538 | 0 | SkipUntil(tok::semi, StopBeforeMatch); |
2539 | 0 | return nullptr; |
2540 | 0 | } |
2541 | 0 | ThisDecl = ThisRes.get(); |
2542 | 0 | } else { |
2543 | | // FIXME: This check should be for a variable template instantiation only. |
2544 | | |
2545 | | // Check that this is a valid instantiation |
2546 | 0 | if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { |
2547 | | // If the declarator-id is not a template-id, issue a diagnostic and |
2548 | | // recover by ignoring the 'template' keyword. |
2549 | 0 | Diag(Tok, diag::err_template_defn_explicit_instantiation) |
2550 | 0 | << 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); |
2551 | 0 | ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); |
2552 | 0 | } else { |
2553 | 0 | SourceLocation LAngleLoc = |
2554 | 0 | PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); |
2555 | 0 | Diag(D.getIdentifierLoc(), |
2556 | 0 | diag::err_explicit_instantiation_with_definition) |
2557 | 0 | << SourceRange(TemplateInfo.TemplateLoc) |
2558 | 0 | << FixItHint::CreateInsertion(LAngleLoc, "<>"); |
2559 | | |
2560 | | // Recover as if it were an explicit specialization. |
2561 | 0 | TemplateParameterLists FakedParamLists; |
2562 | 0 | FakedParamLists.push_back(Actions.ActOnTemplateParameterList( |
2563 | 0 | 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, |
2564 | 0 | std::nullopt, LAngleLoc, nullptr)); |
2565 | |
|
2566 | 0 | ThisDecl = |
2567 | 0 | Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D); |
2568 | 0 | } |
2569 | 0 | } |
2570 | 0 | break; |
2571 | 0 | } |
2572 | 5.08k | } |
2573 | | |
2574 | 5.08k | Sema::CUDATargetContextRAII X(Actions, Sema::CTCK_InitGlobalVar, ThisDecl); |
2575 | 5.08k | switch (TheInitKind) { |
2576 | | // Parse declarator '=' initializer. |
2577 | 209 | case InitKind::Equal: { |
2578 | 209 | SourceLocation EqualLoc = ConsumeToken(); |
2579 | | |
2580 | 209 | if (Tok.is(tok::kw_delete)) { |
2581 | 0 | if (D.isFunctionDeclarator()) |
2582 | 0 | Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) |
2583 | 0 | << 1 /* delete */; |
2584 | 0 | else |
2585 | 0 | Diag(ConsumeToken(), diag::err_deleted_non_function); |
2586 | 209 | } else if (Tok.is(tok::kw_default)) { |
2587 | 0 | if (D.isFunctionDeclarator()) |
2588 | 0 | Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) |
2589 | 0 | << 0 /* default */; |
2590 | 0 | else |
2591 | 0 | Diag(ConsumeToken(), diag::err_default_special_members) |
2592 | 0 | << getLangOpts().CPlusPlus20; |
2593 | 209 | } else { |
2594 | 209 | InitializerScopeRAII InitScope(*this, D, ThisDecl); |
2595 | | |
2596 | 209 | if (Tok.is(tok::code_completion)) { |
2597 | 0 | cutOffParsing(); |
2598 | 0 | Actions.CodeCompleteInitializer(getCurScope(), ThisDecl); |
2599 | 0 | Actions.FinalizeDeclaration(ThisDecl); |
2600 | 0 | return nullptr; |
2601 | 0 | } |
2602 | | |
2603 | 209 | PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl); |
2604 | 209 | ExprResult Init = ParseInitializer(); |
2605 | | |
2606 | | // If this is the only decl in (possibly) range based for statement, |
2607 | | // our best guess is that the user meant ':' instead of '='. |
2608 | 209 | if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) { |
2609 | 0 | Diag(EqualLoc, diag::err_single_decl_assign_in_for_range) |
2610 | 0 | << FixItHint::CreateReplacement(EqualLoc, ":"); |
2611 | | // We are trying to stop parser from looking for ';' in this for |
2612 | | // statement, therefore preventing spurious errors to be issued. |
2613 | 0 | FRI->ColonLoc = EqualLoc; |
2614 | 0 | Init = ExprError(); |
2615 | 0 | FRI->RangeExpr = Init; |
2616 | 0 | } |
2617 | | |
2618 | 209 | InitScope.pop(); |
2619 | | |
2620 | 209 | if (Init.isInvalid()) { |
2621 | 135 | SmallVector<tok::TokenKind, 2> StopTokens; |
2622 | 135 | StopTokens.push_back(tok::comma); |
2623 | 135 | if (D.getContext() == DeclaratorContext::ForInit || |
2624 | 135 | D.getContext() == DeclaratorContext::SelectionInit) |
2625 | 0 | StopTokens.push_back(tok::r_paren); |
2626 | 135 | SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch); |
2627 | 135 | Actions.ActOnInitializerError(ThisDecl); |
2628 | 135 | } else |
2629 | 74 | Actions.AddInitializerToDecl(ThisDecl, Init.get(), |
2630 | 74 | /*DirectInit=*/false); |
2631 | 209 | } |
2632 | 209 | break; |
2633 | 209 | } |
2634 | 209 | case InitKind::CXXDirect: { |
2635 | | // Parse C++ direct initializer: '(' expression-list ')' |
2636 | 55 | BalancedDelimiterTracker T(*this, tok::l_paren); |
2637 | 55 | T.consumeOpen(); |
2638 | | |
2639 | 55 | ExprVector Exprs; |
2640 | | |
2641 | 55 | InitializerScopeRAII InitScope(*this, D, ThisDecl); |
2642 | | |
2643 | 55 | auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl); |
2644 | 55 | auto RunSignatureHelp = [&]() { |
2645 | 0 | QualType PreferredType = Actions.ProduceConstructorSignatureHelp( |
2646 | 0 | ThisVarDecl->getType()->getCanonicalTypeInternal(), |
2647 | 0 | ThisDecl->getLocation(), Exprs, T.getOpenLocation(), |
2648 | 0 | /*Braced=*/false); |
2649 | 0 | CalledSignatureHelp = true; |
2650 | 0 | return PreferredType; |
2651 | 0 | }; |
2652 | 69 | auto SetPreferredType = [&] { |
2653 | 69 | PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); |
2654 | 69 | }; |
2655 | | |
2656 | 55 | llvm::function_ref<void()> ExpressionStarts; |
2657 | 55 | if (ThisVarDecl) { |
2658 | | // ParseExpressionList can sometimes succeed even when ThisDecl is not |
2659 | | // VarDecl. This is an error and it is reported in a call to |
2660 | | // Actions.ActOnInitializerError(). However, we call |
2661 | | // ProduceConstructorSignatureHelp only on VarDecls. |
2662 | 55 | ExpressionStarts = SetPreferredType; |
2663 | 55 | } |
2664 | | |
2665 | 55 | bool SawError = ParseExpressionList(Exprs, ExpressionStarts); |
2666 | | |
2667 | 55 | InitScope.pop(); |
2668 | | |
2669 | 55 | if (SawError) { |
2670 | 44 | if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) { |
2671 | 0 | Actions.ProduceConstructorSignatureHelp( |
2672 | 0 | ThisVarDecl->getType()->getCanonicalTypeInternal(), |
2673 | 0 | ThisDecl->getLocation(), Exprs, T.getOpenLocation(), |
2674 | 0 | /*Braced=*/false); |
2675 | 0 | CalledSignatureHelp = true; |
2676 | 0 | } |
2677 | 44 | Actions.ActOnInitializerError(ThisDecl); |
2678 | 44 | SkipUntil(tok::r_paren, StopAtSemi); |
2679 | 44 | } else { |
2680 | | // Match the ')'. |
2681 | 11 | T.consumeClose(); |
2682 | | |
2683 | 11 | ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(), |
2684 | 11 | T.getCloseLocation(), |
2685 | 11 | Exprs); |
2686 | 11 | Actions.AddInitializerToDecl(ThisDecl, Initializer.get(), |
2687 | 11 | /*DirectInit=*/true); |
2688 | 11 | } |
2689 | 55 | break; |
2690 | 209 | } |
2691 | 118 | case InitKind::CXXBraced: { |
2692 | | // Parse C++0x braced-init-list. |
2693 | 118 | Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); |
2694 | | |
2695 | 118 | InitializerScopeRAII InitScope(*this, D, ThisDecl); |
2696 | | |
2697 | 118 | PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl); |
2698 | 118 | ExprResult Init(ParseBraceInitializer()); |
2699 | | |
2700 | 118 | InitScope.pop(); |
2701 | | |
2702 | 118 | if (Init.isInvalid()) { |
2703 | 115 | Actions.ActOnInitializerError(ThisDecl); |
2704 | 115 | } else |
2705 | 3 | Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true); |
2706 | 118 | break; |
2707 | 209 | } |
2708 | 4.70k | case InitKind::Uninitialized: { |
2709 | 4.70k | Actions.ActOnUninitializedDecl(ThisDecl); |
2710 | 4.70k | break; |
2711 | 209 | } |
2712 | 5.08k | } |
2713 | | |
2714 | 5.08k | Actions.FinalizeDeclaration(ThisDecl); |
2715 | 5.08k | return OuterDecl ? OuterDecl : ThisDecl; |
2716 | 5.08k | } |
2717 | | |
2718 | | /// ParseSpecifierQualifierList |
2719 | | /// specifier-qualifier-list: |
2720 | | /// type-specifier specifier-qualifier-list[opt] |
2721 | | /// type-qualifier specifier-qualifier-list[opt] |
2722 | | /// [GNU] attributes specifier-qualifier-list[opt] |
2723 | | /// |
2724 | | void Parser::ParseSpecifierQualifierList( |
2725 | | DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename, |
2726 | 23 | AccessSpecifier AS, DeclSpecContext DSC) { |
2727 | | /// specifier-qualifier-list is a subset of declaration-specifiers. Just |
2728 | | /// parse declaration-specifiers and complain about extra stuff. |
2729 | | /// TODO: diagnose attribute-specifiers and alignment-specifiers. |
2730 | 23 | ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC, nullptr, |
2731 | 23 | AllowImplicitTypename); |
2732 | | |
2733 | | // Validate declspec for type-name. |
2734 | 23 | unsigned Specs = DS.getParsedSpecifiers(); |
2735 | 23 | if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) { |
2736 | 0 | Diag(Tok, diag::err_expected_type); |
2737 | 0 | DS.SetTypeSpecError(); |
2738 | 23 | } else if (Specs == DeclSpec::PQ_None && !DS.hasAttributes()) { |
2739 | 3 | Diag(Tok, diag::err_typename_requires_specqual); |
2740 | 3 | if (!DS.hasTypeSpecifier()) |
2741 | 3 | DS.SetTypeSpecError(); |
2742 | 3 | } |
2743 | | |
2744 | | // Issue diagnostic and remove storage class if present. |
2745 | 23 | if (Specs & DeclSpec::PQ_StorageClassSpecifier) { |
2746 | 0 | if (DS.getStorageClassSpecLoc().isValid()) |
2747 | 0 | Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass); |
2748 | 0 | else |
2749 | 0 | Diag(DS.getThreadStorageClassSpecLoc(), |
2750 | 0 | diag::err_typename_invalid_storageclass); |
2751 | 0 | DS.ClearStorageClassSpecs(); |
2752 | 0 | } |
2753 | | |
2754 | | // Issue diagnostic and remove function specifier if present. |
2755 | 23 | if (Specs & DeclSpec::PQ_FunctionSpecifier) { |
2756 | 0 | if (DS.isInlineSpecified()) |
2757 | 0 | Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec); |
2758 | 0 | if (DS.isVirtualSpecified()) |
2759 | 0 | Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec); |
2760 | 0 | if (DS.hasExplicitSpecifier()) |
2761 | 0 | Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec); |
2762 | 0 | if (DS.isNoreturnSpecified()) |
2763 | 0 | Diag(DS.getNoreturnSpecLoc(), diag::err_typename_invalid_functionspec); |
2764 | 0 | DS.ClearFunctionSpecs(); |
2765 | 0 | } |
2766 | | |
2767 | | // Issue diagnostic and remove constexpr specifier if present. |
2768 | 23 | if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) { |
2769 | 0 | Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr) |
2770 | 0 | << static_cast<int>(DS.getConstexprSpecifier()); |
2771 | 0 | DS.ClearConstexprSpec(); |
2772 | 0 | } |
2773 | 23 | } |
2774 | | |
2775 | | /// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the |
2776 | | /// specified token is valid after the identifier in a declarator which |
2777 | | /// immediately follows the declspec. For example, these things are valid: |
2778 | | /// |
2779 | | /// int x [ 4]; // direct-declarator |
2780 | | /// int x ( int y); // direct-declarator |
2781 | | /// int(int x ) // direct-declarator |
2782 | | /// int x ; // simple-declaration |
2783 | | /// int x = 17; // init-declarator-list |
2784 | | /// int x , y; // init-declarator-list |
2785 | | /// int x __asm__ ("foo"); // init-declarator-list |
2786 | | /// int x : 4; // struct-declarator |
2787 | | /// int x { 5}; // C++'0x unified initializers |
2788 | | /// |
2789 | | /// This is not, because 'x' does not immediately follow the declspec (though |
2790 | | /// ')' happens to be valid anyway). |
2791 | | /// int (x) |
2792 | | /// |
2793 | 5.71k | static bool isValidAfterIdentifierInDeclarator(const Token &T) { |
2794 | 5.71k | return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi, |
2795 | 5.71k | tok::comma, tok::equal, tok::kw_asm, tok::l_brace, |
2796 | 5.71k | tok::colon); |
2797 | 5.71k | } |
2798 | | |
2799 | | /// ParseImplicitInt - This method is called when we have an non-typename |
2800 | | /// identifier in a declspec (which normally terminates the decl spec) when |
2801 | | /// the declspec has no type specifier. In this case, the declspec is either |
2802 | | /// malformed or is "implicit int" (in K&R and C89). |
2803 | | /// |
2804 | | /// This method handles diagnosing this prettily and returns false if the |
2805 | | /// declspec is done being processed. If it recovers and thinks there may be |
2806 | | /// other pieces of declspec after it, it returns true. |
2807 | | /// |
2808 | | bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, |
2809 | | const ParsedTemplateInfo &TemplateInfo, |
2810 | | AccessSpecifier AS, DeclSpecContext DSC, |
2811 | 11.0k | ParsedAttributes &Attrs) { |
2812 | 11.0k | assert(Tok.is(tok::identifier) && "should have identifier"); |
2813 | | |
2814 | 0 | SourceLocation Loc = Tok.getLocation(); |
2815 | | // If we see an identifier that is not a type name, we normally would |
2816 | | // parse it as the identifier being declared. However, when a typename |
2817 | | // is typo'd or the definition is not included, this will incorrectly |
2818 | | // parse the typename as the identifier name and fall over misparsing |
2819 | | // later parts of the diagnostic. |
2820 | | // |
2821 | | // As such, we try to do some look-ahead in cases where this would |
2822 | | // otherwise be an "implicit-int" case to see if this is invalid. For |
2823 | | // example: "static foo_t x = 4;" In this case, if we parsed foo_t as |
2824 | | // an identifier with implicit int, we'd get a parse error because the |
2825 | | // next token is obviously invalid for a type. Parse these as a case |
2826 | | // with an invalid type specifier. |
2827 | 11.0k | assert(!DS.hasTypeSpecifier() && "Type specifier checked above"); |
2828 | | |
2829 | | // Since we know that this either implicit int (which is rare) or an |
2830 | | // error, do lookahead to try to do better recovery. This never applies |
2831 | | // within a type specifier. Outside of C++, we allow this even if the |
2832 | | // language doesn't "officially" support implicit int -- we support |
2833 | | // implicit int as an extension in some language modes. |
2834 | 11.0k | if (!isTypeSpecifier(DSC) && getLangOpts().isImplicitIntAllowed() && |
2835 | 11.0k | isValidAfterIdentifierInDeclarator(NextToken())) { |
2836 | | // If this token is valid for implicit int, e.g. "static x = 4", then |
2837 | | // we just avoid eating the identifier, so it will be parsed as the |
2838 | | // identifier in the declarator. |
2839 | 415 | return false; |
2840 | 415 | } |
2841 | | |
2842 | | // Early exit as Sema has a dedicated missing_actual_pipe_type diagnostic |
2843 | | // for incomplete declarations such as `pipe p`. |
2844 | 10.6k | if (getLangOpts().OpenCLCPlusPlus && DS.isTypeSpecPipe()) |
2845 | 0 | return false; |
2846 | | |
2847 | 10.6k | if (getLangOpts().CPlusPlus && |
2848 | 10.6k | DS.getStorageClassSpec() == DeclSpec::SCS_auto) { |
2849 | | // Don't require a type specifier if we have the 'auto' storage class |
2850 | | // specifier in C++98 -- we'll promote it to a type specifier. |
2851 | 0 | if (SS) |
2852 | 0 | AnnotateScopeToken(*SS, /*IsNewAnnotation*/false); |
2853 | 0 | return false; |
2854 | 0 | } |
2855 | | |
2856 | 10.6k | if (getLangOpts().CPlusPlus && (!SS || SS->isEmpty()) && |
2857 | 10.6k | getLangOpts().MSVCCompat) { |
2858 | | // Lookup of an unqualified type name has failed in MSVC compatibility mode. |
2859 | | // Give Sema a chance to recover if we are in a template with dependent base |
2860 | | // classes. |
2861 | 0 | if (ParsedType T = Actions.ActOnMSVCUnknownTypeName( |
2862 | 0 | *Tok.getIdentifierInfo(), Tok.getLocation(), |
2863 | 0 | DSC == DeclSpecContext::DSC_template_type_arg)) { |
2864 | 0 | const char *PrevSpec; |
2865 | 0 | unsigned DiagID; |
2866 | 0 | DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, |
2867 | 0 | Actions.getASTContext().getPrintingPolicy()); |
2868 | 0 | DS.SetRangeEnd(Tok.getLocation()); |
2869 | 0 | ConsumeToken(); |
2870 | 0 | return false; |
2871 | 0 | } |
2872 | 0 | } |
2873 | | |
2874 | | // Otherwise, if we don't consume this token, we are going to emit an |
2875 | | // error anyway. Try to recover from various common problems. Check |
2876 | | // to see if this was a reference to a tag name without a tag specified. |
2877 | | // This is a common problem in C (saying 'foo' instead of 'struct foo'). |
2878 | | // |
2879 | | // C++ doesn't need this, and isTagName doesn't take SS. |
2880 | 10.6k | if (SS == nullptr) { |
2881 | 10.6k | const char *TagName = nullptr, *FixitTagName = nullptr; |
2882 | 10.6k | tok::TokenKind TagKind = tok::unknown; |
2883 | | |
2884 | 10.6k | switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) { |
2885 | 10.6k | default: break; |
2886 | 10.6k | case DeclSpec::TST_enum: |
2887 | 0 | TagName="enum" ; FixitTagName = "enum " ; TagKind=tok::kw_enum ;break; |
2888 | 0 | case DeclSpec::TST_union: |
2889 | 0 | TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break; |
2890 | 0 | case DeclSpec::TST_struct: |
2891 | 0 | TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break; |
2892 | 0 | case DeclSpec::TST_interface: |
2893 | 0 | TagName="__interface"; FixitTagName = "__interface "; |
2894 | 0 | TagKind=tok::kw___interface;break; |
2895 | 0 | case DeclSpec::TST_class: |
2896 | 0 | TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break; |
2897 | 10.6k | } |
2898 | | |
2899 | 10.6k | if (TagName) { |
2900 | 0 | IdentifierInfo *TokenName = Tok.getIdentifierInfo(); |
2901 | 0 | LookupResult R(Actions, TokenName, SourceLocation(), |
2902 | 0 | Sema::LookupOrdinaryName); |
2903 | |
|
2904 | 0 | Diag(Loc, diag::err_use_of_tag_name_without_tag) |
2905 | 0 | << TokenName << TagName << getLangOpts().CPlusPlus |
2906 | 0 | << FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName); |
2907 | |
|
2908 | 0 | if (Actions.LookupParsedName(R, getCurScope(), SS)) { |
2909 | 0 | for (LookupResult::iterator I = R.begin(), IEnd = R.end(); |
2910 | 0 | I != IEnd; ++I) |
2911 | 0 | Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) |
2912 | 0 | << TokenName << TagName; |
2913 | 0 | } |
2914 | | |
2915 | | // Parse this as a tag as if the missing tag were present. |
2916 | 0 | if (TagKind == tok::kw_enum) |
2917 | 0 | ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, |
2918 | 0 | DeclSpecContext::DSC_normal); |
2919 | 0 | else |
2920 | 0 | ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS, |
2921 | 0 | /*EnteringContext*/ false, |
2922 | 0 | DeclSpecContext::DSC_normal, Attrs); |
2923 | 0 | return true; |
2924 | 0 | } |
2925 | 10.6k | } |
2926 | | |
2927 | | // Determine whether this identifier could plausibly be the name of something |
2928 | | // being declared (with a missing type). |
2929 | 10.6k | if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level || |
2930 | 10.6k | DSC == DeclSpecContext::DSC_class)) { |
2931 | | // Look ahead to the next token to try to figure out what this declaration |
2932 | | // was supposed to be. |
2933 | 10.6k | switch (NextToken().getKind()) { |
2934 | 43 | case tok::l_paren: { |
2935 | | // static x(4); // 'x' is not a type |
2936 | | // x(int n); // 'x' is not a type |
2937 | | // x (*p)[]; // 'x' is a type |
2938 | | // |
2939 | | // Since we're in an error case, we can afford to perform a tentative |
2940 | | // parse to determine which case we're in. |
2941 | 43 | TentativeParsingAction PA(*this); |
2942 | 43 | ConsumeToken(); |
2943 | 43 | TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false); |
2944 | 43 | PA.Revert(); |
2945 | | |
2946 | 43 | if (TPR != TPResult::False) { |
2947 | | // The identifier is followed by a parenthesized declarator. |
2948 | | // It's supposed to be a type. |
2949 | 1 | break; |
2950 | 1 | } |
2951 | | |
2952 | | // If we're in a context where we could be declaring a constructor, |
2953 | | // check whether this is a constructor declaration with a bogus name. |
2954 | 42 | if (DSC == DeclSpecContext::DSC_class || |
2955 | 42 | (DSC == DeclSpecContext::DSC_top_level && SS)) { |
2956 | 0 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
2957 | 0 | if (Actions.isCurrentClassNameTypo(II, SS)) { |
2958 | 0 | Diag(Loc, diag::err_constructor_bad_name) |
2959 | 0 | << Tok.getIdentifierInfo() << II |
2960 | 0 | << FixItHint::CreateReplacement(Tok.getLocation(), II->getName()); |
2961 | 0 | Tok.setIdentifierInfo(II); |
2962 | 0 | } |
2963 | 0 | } |
2964 | | // Fall through. |
2965 | 42 | [[fallthrough]]; |
2966 | 42 | } |
2967 | 99 | case tok::comma: |
2968 | 196 | case tok::equal: |
2969 | 196 | case tok::kw_asm: |
2970 | 278 | case tok::l_brace: |
2971 | 329 | case tok::l_square: |
2972 | 420 | case tok::semi: |
2973 | | // This looks like a variable or function declaration. The type is |
2974 | | // probably missing. We're done parsing decl-specifiers. |
2975 | | // But only if we are not in a function prototype scope. |
2976 | 420 | if (getCurScope()->isFunctionPrototypeScope()) |
2977 | 0 | break; |
2978 | 420 | if (SS) |
2979 | 0 | AnnotateScopeToken(*SS, /*IsNewAnnotation*/false); |
2980 | 420 | return false; |
2981 | | |
2982 | 10.2k | default: |
2983 | | // This is probably supposed to be a type. This includes cases like: |
2984 | | // int f(itn); |
2985 | | // struct S { unsigned : 4; }; |
2986 | 10.2k | break; |
2987 | 10.6k | } |
2988 | 10.6k | } |
2989 | | |
2990 | | // This is almost certainly an invalid type name. Let Sema emit a diagnostic |
2991 | | // and attempt to recover. |
2992 | 10.2k | ParsedType T; |
2993 | 10.2k | IdentifierInfo *II = Tok.getIdentifierInfo(); |
2994 | 10.2k | bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less); |
2995 | 10.2k | Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T, |
2996 | 10.2k | IsTemplateName); |
2997 | 10.2k | if (T) { |
2998 | | // The action has suggested that the type T could be used. Set that as |
2999 | | // the type in the declaration specifiers, consume the would-be type |
3000 | | // name token, and we're done. |
3001 | 0 | const char *PrevSpec; |
3002 | 0 | unsigned DiagID; |
3003 | 0 | DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, |
3004 | 0 | Actions.getASTContext().getPrintingPolicy()); |
3005 | 0 | DS.SetRangeEnd(Tok.getLocation()); |
3006 | 0 | ConsumeToken(); |
3007 | | // There may be other declaration specifiers after this. |
3008 | 0 | return true; |
3009 | 10.2k | } else if (II != Tok.getIdentifierInfo()) { |
3010 | | // If no type was suggested, the correction is to a keyword |
3011 | 0 | Tok.setKind(II->getTokenID()); |
3012 | | // There may be other declaration specifiers after this. |
3013 | 0 | return true; |
3014 | 0 | } |
3015 | | |
3016 | | // Otherwise, the action had no suggestion for us. Mark this as an error. |
3017 | 10.2k | DS.SetTypeSpecError(); |
3018 | 10.2k | DS.SetRangeEnd(Tok.getLocation()); |
3019 | 10.2k | ConsumeToken(); |
3020 | | |
3021 | | // Eat any following template arguments. |
3022 | 10.2k | if (IsTemplateName) { |
3023 | 83 | SourceLocation LAngle, RAngle; |
3024 | 83 | TemplateArgList Args; |
3025 | 83 | ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle); |
3026 | 83 | } |
3027 | | |
3028 | | // TODO: Could inject an invalid typedef decl in an enclosing scope to |
3029 | | // avoid rippling error messages on subsequent uses of the same type, |
3030 | | // could be useful if #include was forgotten. |
3031 | 10.2k | return true; |
3032 | 10.2k | } |
3033 | | |
3034 | | /// Determine the declaration specifier context from the declarator |
3035 | | /// context. |
3036 | | /// |
3037 | | /// \param Context the declarator context, which is one of the |
3038 | | /// DeclaratorContext enumerator values. |
3039 | | Parser::DeclSpecContext |
3040 | 18 | Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) { |
3041 | 18 | switch (Context) { |
3042 | 0 | case DeclaratorContext::Member: |
3043 | 0 | return DeclSpecContext::DSC_class; |
3044 | 0 | case DeclaratorContext::File: |
3045 | 0 | return DeclSpecContext::DSC_top_level; |
3046 | 0 | case DeclaratorContext::TemplateParam: |
3047 | 0 | return DeclSpecContext::DSC_template_param; |
3048 | 18 | case DeclaratorContext::TemplateArg: |
3049 | 18 | return DeclSpecContext::DSC_template_arg; |
3050 | 0 | case DeclaratorContext::TemplateTypeArg: |
3051 | 0 | return DeclSpecContext::DSC_template_type_arg; |
3052 | 0 | case DeclaratorContext::TrailingReturn: |
3053 | 0 | case DeclaratorContext::TrailingReturnVar: |
3054 | 0 | return DeclSpecContext::DSC_trailing; |
3055 | 0 | case DeclaratorContext::AliasDecl: |
3056 | 0 | case DeclaratorContext::AliasTemplate: |
3057 | 0 | return DeclSpecContext::DSC_alias_declaration; |
3058 | 0 | case DeclaratorContext::Association: |
3059 | 0 | return DeclSpecContext::DSC_association; |
3060 | 0 | case DeclaratorContext::TypeName: |
3061 | 0 | return DeclSpecContext::DSC_type_specifier; |
3062 | 0 | case DeclaratorContext::Condition: |
3063 | 0 | return DeclSpecContext::DSC_condition; |
3064 | 0 | case DeclaratorContext::ConversionId: |
3065 | 0 | return DeclSpecContext::DSC_conv_operator; |
3066 | 0 | case DeclaratorContext::CXXNew: |
3067 | 0 | return DeclSpecContext::DSC_new; |
3068 | 0 | case DeclaratorContext::Prototype: |
3069 | 0 | case DeclaratorContext::ObjCResult: |
3070 | 0 | case DeclaratorContext::ObjCParameter: |
3071 | 0 | case DeclaratorContext::KNRTypeList: |
3072 | 0 | case DeclaratorContext::FunctionalCast: |
3073 | 0 | case DeclaratorContext::Block: |
3074 | 0 | case DeclaratorContext::ForInit: |
3075 | 0 | case DeclaratorContext::SelectionInit: |
3076 | 0 | case DeclaratorContext::CXXCatch: |
3077 | 0 | case DeclaratorContext::ObjCCatch: |
3078 | 0 | case DeclaratorContext::BlockLiteral: |
3079 | 0 | case DeclaratorContext::LambdaExpr: |
3080 | 0 | case DeclaratorContext::LambdaExprParameter: |
3081 | 0 | case DeclaratorContext::RequiresExpr: |
3082 | 0 | return DeclSpecContext::DSC_normal; |
3083 | 18 | } |
3084 | | |
3085 | 0 | llvm_unreachable("Missing DeclaratorContext case"); |
3086 | 0 | } |
3087 | | |
3088 | | /// ParseAlignArgument - Parse the argument to an alignment-specifier. |
3089 | | /// |
3090 | | /// [C11] type-id |
3091 | | /// [C11] constant-expression |
3092 | | /// [C++0x] type-id ...[opt] |
3093 | | /// [C++0x] assignment-expression ...[opt] |
3094 | | ExprResult Parser::ParseAlignArgument(StringRef KWName, SourceLocation Start, |
3095 | | SourceLocation &EllipsisLoc, bool &IsType, |
3096 | 0 | ParsedType &TypeResult) { |
3097 | 0 | ExprResult ER; |
3098 | 0 | if (isTypeIdInParens()) { |
3099 | 0 | SourceLocation TypeLoc = Tok.getLocation(); |
3100 | 0 | ParsedType Ty = ParseTypeName().get(); |
3101 | 0 | SourceRange TypeRange(Start, Tok.getLocation()); |
3102 | 0 | if (Actions.ActOnAlignasTypeArgument(KWName, Ty, TypeLoc, TypeRange)) |
3103 | 0 | return ExprError(); |
3104 | 0 | TypeResult = Ty; |
3105 | 0 | IsType = true; |
3106 | 0 | } else { |
3107 | 0 | ER = ParseConstantExpression(); |
3108 | 0 | IsType = false; |
3109 | 0 | } |
3110 | | |
3111 | 0 | if (getLangOpts().CPlusPlus11) |
3112 | 0 | TryConsumeToken(tok::ellipsis, EllipsisLoc); |
3113 | |
|
3114 | 0 | return ER; |
3115 | 0 | } |
3116 | | |
3117 | | /// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the |
3118 | | /// attribute to Attrs. |
3119 | | /// |
3120 | | /// alignment-specifier: |
3121 | | /// [C11] '_Alignas' '(' type-id ')' |
3122 | | /// [C11] '_Alignas' '(' constant-expression ')' |
3123 | | /// [C++11] 'alignas' '(' type-id ...[opt] ')' |
3124 | | /// [C++11] 'alignas' '(' assignment-expression ...[opt] ')' |
3125 | | void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, |
3126 | 0 | SourceLocation *EndLoc) { |
3127 | 0 | assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) && |
3128 | 0 | "Not an alignment-specifier!"); |
3129 | 0 | Token KWTok = Tok; |
3130 | 0 | IdentifierInfo *KWName = KWTok.getIdentifierInfo(); |
3131 | 0 | auto Kind = KWTok.getKind(); |
3132 | 0 | SourceLocation KWLoc = ConsumeToken(); |
3133 | |
|
3134 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
3135 | 0 | if (T.expectAndConsume()) |
3136 | 0 | return; |
3137 | | |
3138 | 0 | bool IsType; |
3139 | 0 | ParsedType TypeResult; |
3140 | 0 | SourceLocation EllipsisLoc; |
3141 | 0 | ExprResult ArgExpr = |
3142 | 0 | ParseAlignArgument(PP.getSpelling(KWTok), T.getOpenLocation(), |
3143 | 0 | EllipsisLoc, IsType, TypeResult); |
3144 | 0 | if (ArgExpr.isInvalid()) { |
3145 | 0 | T.skipToEnd(); |
3146 | 0 | return; |
3147 | 0 | } |
3148 | | |
3149 | 0 | T.consumeClose(); |
3150 | 0 | if (EndLoc) |
3151 | 0 | *EndLoc = T.getCloseLocation(); |
3152 | |
|
3153 | 0 | if (IsType) { |
3154 | 0 | Attrs.addNewTypeAttr(KWName, KWLoc, nullptr, KWLoc, TypeResult, Kind, |
3155 | 0 | EllipsisLoc); |
3156 | 0 | } else { |
3157 | 0 | ArgsVector ArgExprs; |
3158 | 0 | ArgExprs.push_back(ArgExpr.get()); |
3159 | 0 | Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1, Kind, |
3160 | 0 | EllipsisLoc); |
3161 | 0 | } |
3162 | 0 | } |
3163 | | |
3164 | 0 | ExprResult Parser::ParseExtIntegerArgument() { |
3165 | 0 | assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) && |
3166 | 0 | "Not an extended int type"); |
3167 | 0 | ConsumeToken(); |
3168 | |
|
3169 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
3170 | 0 | if (T.expectAndConsume()) |
3171 | 0 | return ExprError(); |
3172 | | |
3173 | 0 | ExprResult ER = ParseConstantExpression(); |
3174 | 0 | if (ER.isInvalid()) { |
3175 | 0 | T.skipToEnd(); |
3176 | 0 | return ExprError(); |
3177 | 0 | } |
3178 | | |
3179 | 0 | if(T.consumeClose()) |
3180 | 0 | return ExprError(); |
3181 | 0 | return ER; |
3182 | 0 | } |
3183 | | |
3184 | | /// Determine whether we're looking at something that might be a declarator |
3185 | | /// in a simple-declaration. If it can't possibly be a declarator, maybe |
3186 | | /// diagnose a missing semicolon after a prior tag definition in the decl |
3187 | | /// specifier. |
3188 | | /// |
3189 | | /// \return \c true if an error occurred and this can't be any kind of |
3190 | | /// declaration. |
3191 | | bool |
3192 | | Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, |
3193 | | DeclSpecContext DSContext, |
3194 | 0 | LateParsedAttrList *LateAttrs) { |
3195 | 0 | assert(DS.hasTagDefinition() && "shouldn't call this"); |
3196 | | |
3197 | 0 | bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || |
3198 | 0 | DSContext == DeclSpecContext::DSC_top_level); |
3199 | |
|
3200 | 0 | if (getLangOpts().CPlusPlus && |
3201 | 0 | Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype, |
3202 | 0 | tok::annot_template_id) && |
3203 | 0 | TryAnnotateCXXScopeToken(EnteringContext)) { |
3204 | 0 | SkipMalformedDecl(); |
3205 | 0 | return true; |
3206 | 0 | } |
3207 | | |
3208 | 0 | bool HasScope = Tok.is(tok::annot_cxxscope); |
3209 | | // Make a copy in case GetLookAheadToken invalidates the result of NextToken. |
3210 | 0 | Token AfterScope = HasScope ? NextToken() : Tok; |
3211 | | |
3212 | | // Determine whether the following tokens could possibly be a |
3213 | | // declarator. |
3214 | 0 | bool MightBeDeclarator = true; |
3215 | 0 | if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) { |
3216 | | // A declarator-id can't start with 'typename'. |
3217 | 0 | MightBeDeclarator = false; |
3218 | 0 | } else if (AfterScope.is(tok::annot_template_id)) { |
3219 | | // If we have a type expressed as a template-id, this cannot be a |
3220 | | // declarator-id (such a type cannot be redeclared in a simple-declaration). |
3221 | 0 | TemplateIdAnnotation *Annot = |
3222 | 0 | static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue()); |
3223 | 0 | if (Annot->Kind == TNK_Type_template) |
3224 | 0 | MightBeDeclarator = false; |
3225 | 0 | } else if (AfterScope.is(tok::identifier)) { |
3226 | 0 | const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken(); |
3227 | | |
3228 | | // These tokens cannot come after the declarator-id in a |
3229 | | // simple-declaration, and are likely to come after a type-specifier. |
3230 | 0 | if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier, |
3231 | 0 | tok::annot_cxxscope, tok::coloncolon)) { |
3232 | | // Missing a semicolon. |
3233 | 0 | MightBeDeclarator = false; |
3234 | 0 | } else if (HasScope) { |
3235 | | // If the declarator-id has a scope specifier, it must redeclare a |
3236 | | // previously-declared entity. If that's a type (and this is not a |
3237 | | // typedef), that's an error. |
3238 | 0 | CXXScopeSpec SS; |
3239 | 0 | Actions.RestoreNestedNameSpecifierAnnotation( |
3240 | 0 | Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); |
3241 | 0 | IdentifierInfo *Name = AfterScope.getIdentifierInfo(); |
3242 | 0 | Sema::NameClassification Classification = Actions.ClassifyName( |
3243 | 0 | getCurScope(), SS, Name, AfterScope.getLocation(), Next, |
3244 | 0 | /*CCC=*/nullptr); |
3245 | 0 | switch (Classification.getKind()) { |
3246 | 0 | case Sema::NC_Error: |
3247 | 0 | SkipMalformedDecl(); |
3248 | 0 | return true; |
3249 | | |
3250 | 0 | case Sema::NC_Keyword: |
3251 | 0 | llvm_unreachable("typo correction is not possible here"); |
3252 | |
|
3253 | 0 | case Sema::NC_Type: |
3254 | 0 | case Sema::NC_TypeTemplate: |
3255 | 0 | case Sema::NC_UndeclaredNonType: |
3256 | 0 | case Sema::NC_UndeclaredTemplate: |
3257 | | // Not a previously-declared non-type entity. |
3258 | 0 | MightBeDeclarator = false; |
3259 | 0 | break; |
3260 | | |
3261 | 0 | case Sema::NC_Unknown: |
3262 | 0 | case Sema::NC_NonType: |
3263 | 0 | case Sema::NC_DependentNonType: |
3264 | 0 | case Sema::NC_OverloadSet: |
3265 | 0 | case Sema::NC_VarTemplate: |
3266 | 0 | case Sema::NC_FunctionTemplate: |
3267 | 0 | case Sema::NC_Concept: |
3268 | | // Might be a redeclaration of a prior entity. |
3269 | 0 | break; |
3270 | 0 | } |
3271 | 0 | } |
3272 | 0 | } |
3273 | | |
3274 | 0 | if (MightBeDeclarator) |
3275 | 0 | return false; |
3276 | | |
3277 | 0 | const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); |
3278 | 0 | Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()), |
3279 | 0 | diag::err_expected_after) |
3280 | 0 | << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi; |
3281 | | |
3282 | | // Try to recover from the typo, by dropping the tag definition and parsing |
3283 | | // the problematic tokens as a type. |
3284 | | // |
3285 | | // FIXME: Split the DeclSpec into pieces for the standalone |
3286 | | // declaration and pieces for the following declaration, instead |
3287 | | // of assuming that all the other pieces attach to new declaration, |
3288 | | // and call ParsedFreeStandingDeclSpec as appropriate. |
3289 | 0 | DS.ClearTypeSpecType(); |
3290 | 0 | ParsedTemplateInfo NotATemplate; |
3291 | 0 | ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs); |
3292 | 0 | return false; |
3293 | 0 | } |
3294 | | |
3295 | | /// ParseDeclarationSpecifiers |
3296 | | /// declaration-specifiers: [C99 6.7] |
3297 | | /// storage-class-specifier declaration-specifiers[opt] |
3298 | | /// type-specifier declaration-specifiers[opt] |
3299 | | /// [C99] function-specifier declaration-specifiers[opt] |
3300 | | /// [C11] alignment-specifier declaration-specifiers[opt] |
3301 | | /// [GNU] attributes declaration-specifiers[opt] |
3302 | | /// [Clang] '__module_private__' declaration-specifiers[opt] |
3303 | | /// [ObjC1] '__kindof' declaration-specifiers[opt] |
3304 | | /// |
3305 | | /// storage-class-specifier: [C99 6.7.1] |
3306 | | /// 'typedef' |
3307 | | /// 'extern' |
3308 | | /// 'static' |
3309 | | /// 'auto' |
3310 | | /// 'register' |
3311 | | /// [C++] 'mutable' |
3312 | | /// [C++11] 'thread_local' |
3313 | | /// [C11] '_Thread_local' |
3314 | | /// [GNU] '__thread' |
3315 | | /// function-specifier: [C99 6.7.4] |
3316 | | /// [C99] 'inline' |
3317 | | /// [C++] 'virtual' |
3318 | | /// [C++] 'explicit' |
3319 | | /// [OpenCL] '__kernel' |
3320 | | /// 'friend': [C++ dcl.friend] |
3321 | | /// 'constexpr': [C++0x dcl.constexpr] |
3322 | | void Parser::ParseDeclarationSpecifiers( |
3323 | | DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, |
3324 | | DeclSpecContext DSContext, LateParsedAttrList *LateAttrs, |
3325 | 23.9k | ImplicitTypenameContext AllowImplicitTypename) { |
3326 | 23.9k | if (DS.getSourceRange().isInvalid()) { |
3327 | | // Start the range at the current token but make the end of the range |
3328 | | // invalid. This will make the entire range invalid unless we successfully |
3329 | | // consume a token. |
3330 | 23.9k | DS.SetRangeStart(Tok.getLocation()); |
3331 | 23.9k | DS.SetRangeEnd(SourceLocation()); |
3332 | 23.9k | } |
3333 | | |
3334 | | // If we are in a operator context, convert it back into a type specifier |
3335 | | // context for better error handling later on. |
3336 | 23.9k | if (DSContext == DeclSpecContext::DSC_conv_operator) { |
3337 | | // No implicit typename here. |
3338 | 0 | AllowImplicitTypename = ImplicitTypenameContext::No; |
3339 | 0 | DSContext = DeclSpecContext::DSC_type_specifier; |
3340 | 0 | } |
3341 | | |
3342 | 23.9k | bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || |
3343 | 23.9k | DSContext == DeclSpecContext::DSC_top_level); |
3344 | 23.9k | bool AttrsLastTime = false; |
3345 | 23.9k | ParsedAttributes attrs(AttrFactory); |
3346 | | // We use Sema's policy to get bool macros right. |
3347 | 23.9k | PrintingPolicy Policy = Actions.getPrintingPolicy(); |
3348 | 34.3k | while (true) { |
3349 | 34.3k | bool isInvalid = false; |
3350 | 34.3k | bool isStorageClass = false; |
3351 | 34.3k | const char *PrevSpec = nullptr; |
3352 | 34.3k | unsigned DiagID = 0; |
3353 | | |
3354 | | // This value needs to be set to the location of the last token if the last |
3355 | | // token of the specifier is already consumed. |
3356 | 34.3k | SourceLocation ConsumedEnd; |
3357 | | |
3358 | | // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL |
3359 | | // implementation for VS2013 uses _Atomic as an identifier for one of the |
3360 | | // classes in <atomic>. |
3361 | | // |
3362 | | // A typedef declaration containing _Atomic<...> is among the places where |
3363 | | // the class is used. If we are currently parsing such a declaration, treat |
3364 | | // the token as an identifier. |
3365 | 34.3k | if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) && |
3366 | 34.3k | DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef && |
3367 | 34.3k | !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less)) |
3368 | 0 | Tok.setKind(tok::identifier); |
3369 | | |
3370 | 34.3k | SourceLocation Loc = Tok.getLocation(); |
3371 | | |
3372 | | // Helper for image types in OpenCL. |
3373 | 34.3k | auto handleOpenCLImageKW = [&] (StringRef Ext, TypeSpecifierType ImageTypeSpec) { |
3374 | | // Check if the image type is supported and otherwise turn the keyword into an identifier |
3375 | | // because image types from extensions are not reserved identifiers. |
3376 | 0 | if (!StringRef(Ext).empty() && !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) { |
3377 | 0 | Tok.getIdentifierInfo()->revertTokenIDToIdentifier(); |
3378 | 0 | Tok.setKind(tok::identifier); |
3379 | 0 | return false; |
3380 | 0 | } |
3381 | 0 | isInvalid = DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy); |
3382 | 0 | return true; |
3383 | 0 | }; |
3384 | | |
3385 | | // Turn off usual access checking for template specializations and |
3386 | | // instantiations. |
3387 | 34.3k | bool IsTemplateSpecOrInst = |
3388 | 34.3k | (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || |
3389 | 34.3k | TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); |
3390 | | |
3391 | 34.3k | switch (Tok.getKind()) { |
3392 | 18.9k | default: |
3393 | 18.9k | if (Tok.isRegularKeywordAttribute()) |
3394 | 0 | goto Attribute; |
3395 | | |
3396 | 23.9k | DoneWithDeclSpec: |
3397 | 23.9k | if (!AttrsLastTime) |
3398 | 23.9k | ProhibitAttributes(attrs); |
3399 | 0 | else { |
3400 | | // Reject C++11 / C23 attributes that aren't type attributes. |
3401 | 0 | for (const ParsedAttr &PA : attrs) { |
3402 | 0 | if (!PA.isCXX11Attribute() && !PA.isC23Attribute() && |
3403 | 0 | !PA.isRegularKeywordAttribute()) |
3404 | 0 | continue; |
3405 | 0 | if (PA.getKind() == ParsedAttr::UnknownAttribute) |
3406 | | // We will warn about the unknown attribute elsewhere (in |
3407 | | // SemaDeclAttr.cpp) |
3408 | 0 | continue; |
3409 | | // GCC ignores this attribute when placed on the DeclSpec in [[]] |
3410 | | // syntax, so we do the same. |
3411 | 0 | if (PA.getKind() == ParsedAttr::AT_VectorSize) { |
3412 | 0 | Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA; |
3413 | 0 | PA.setInvalid(); |
3414 | 0 | continue; |
3415 | 0 | } |
3416 | | // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they |
3417 | | // are type attributes, because we historically haven't allowed these |
3418 | | // to be used as type attributes in C++11 / C23 syntax. |
3419 | 0 | if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound && |
3420 | 0 | PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck) |
3421 | 0 | continue; |
3422 | 0 | Diag(PA.getLoc(), diag::err_attribute_not_type_attr) |
3423 | 0 | << PA << PA.isRegularKeywordAttribute(); |
3424 | 0 | PA.setInvalid(); |
3425 | 0 | } |
3426 | |
|
3427 | 0 | DS.takeAttributesFrom(attrs); |
3428 | 0 | } |
3429 | | |
3430 | | // If this is not a declaration specifier token, we're done reading decl |
3431 | | // specifiers. First verify that DeclSpec's are consistent. |
3432 | 23.9k | DS.Finish(Actions, Policy); |
3433 | 23.9k | return; |
3434 | | |
3435 | 177 | case tok::l_square: |
3436 | 177 | case tok::kw_alignas: |
3437 | 177 | if (!isAllowedCXX11AttributeSpecifier()) |
3438 | 177 | goto DoneWithDeclSpec; |
3439 | | |
3440 | 0 | Attribute: |
3441 | 0 | ProhibitAttributes(attrs); |
3442 | | // FIXME: It would be good to recover by accepting the attributes, |
3443 | | // but attempting to do that now would cause serious |
3444 | | // madness in terms of diagnostics. |
3445 | 0 | attrs.clear(); |
3446 | 0 | attrs.Range = SourceRange(); |
3447 | |
|
3448 | 0 | ParseCXX11Attributes(attrs); |
3449 | 0 | AttrsLastTime = true; |
3450 | 0 | continue; |
3451 | | |
3452 | 0 | case tok::code_completion: { |
3453 | 0 | Sema::ParserCompletionContext CCC = Sema::PCC_Namespace; |
3454 | 0 | if (DS.hasTypeSpecifier()) { |
3455 | 0 | bool AllowNonIdentifiers |
3456 | 0 | = (getCurScope()->getFlags() & (Scope::ControlScope | |
3457 | 0 | Scope::BlockScope | |
3458 | 0 | Scope::TemplateParamScope | |
3459 | 0 | Scope::FunctionPrototypeScope | |
3460 | 0 | Scope::AtCatchScope)) == 0; |
3461 | 0 | bool AllowNestedNameSpecifiers |
3462 | 0 | = DSContext == DeclSpecContext::DSC_top_level || |
3463 | 0 | (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified()); |
3464 | |
|
3465 | 0 | cutOffParsing(); |
3466 | 0 | Actions.CodeCompleteDeclSpec(getCurScope(), DS, |
3467 | 0 | AllowNonIdentifiers, |
3468 | 0 | AllowNestedNameSpecifiers); |
3469 | 0 | return; |
3470 | 0 | } |
3471 | | |
3472 | | // Class context can appear inside a function/block, so prioritise that. |
3473 | 0 | if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) |
3474 | 0 | CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate |
3475 | 0 | : Sema::PCC_Template; |
3476 | 0 | else if (DSContext == DeclSpecContext::DSC_class) |
3477 | 0 | CCC = Sema::PCC_Class; |
3478 | 0 | else if (getCurScope()->getFnParent() || getCurScope()->getBlockParent()) |
3479 | 0 | CCC = Sema::PCC_LocalDeclarationSpecifiers; |
3480 | 0 | else if (CurParsedObjCImpl) |
3481 | 0 | CCC = Sema::PCC_ObjCImplementation; |
3482 | |
|
3483 | 0 | cutOffParsing(); |
3484 | 0 | Actions.CodeCompleteOrdinaryName(getCurScope(), CCC); |
3485 | 0 | return; |
3486 | 0 | } |
3487 | | |
3488 | 0 | case tok::coloncolon: // ::foo::bar |
3489 | | // C++ scope specifier. Annotate and loop, or bail out on error. |
3490 | 0 | if (getLangOpts().CPlusPlus && |
3491 | 0 | TryAnnotateCXXScopeToken(EnteringContext)) { |
3492 | 0 | if (!DS.hasTypeSpecifier()) |
3493 | 0 | DS.SetTypeSpecError(); |
3494 | 0 | goto DoneWithDeclSpec; |
3495 | 0 | } |
3496 | 0 | if (Tok.is(tok::coloncolon)) // ::new or ::delete |
3497 | 0 | goto DoneWithDeclSpec; |
3498 | 0 | continue; |
3499 | | |
3500 | 0 | case tok::annot_cxxscope: { |
3501 | 0 | if (DS.hasTypeSpecifier() || DS.isTypeAltiVecVector()) |
3502 | 0 | goto DoneWithDeclSpec; |
3503 | | |
3504 | 0 | CXXScopeSpec SS; |
3505 | 0 | if (TemplateInfo.TemplateParams) |
3506 | 0 | SS.setTemplateParamLists(*TemplateInfo.TemplateParams); |
3507 | 0 | Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), |
3508 | 0 | Tok.getAnnotationRange(), |
3509 | 0 | SS); |
3510 | | |
3511 | | // We are looking for a qualified typename. |
3512 | 0 | Token Next = NextToken(); |
3513 | |
|
3514 | 0 | TemplateIdAnnotation *TemplateId = Next.is(tok::annot_template_id) |
3515 | 0 | ? takeTemplateIdAnnotation(Next) |
3516 | 0 | : nullptr; |
3517 | 0 | if (TemplateId && TemplateId->hasInvalidName()) { |
3518 | | // We found something like 'T::U<Args> x', but U is not a template. |
3519 | | // Assume it was supposed to be a type. |
3520 | 0 | DS.SetTypeSpecError(); |
3521 | 0 | ConsumeAnnotationToken(); |
3522 | 0 | break; |
3523 | 0 | } |
3524 | | |
3525 | 0 | if (TemplateId && TemplateId->Kind == TNK_Type_template) { |
3526 | | // We have a qualified template-id, e.g., N::A<int> |
3527 | | |
3528 | | // If this would be a valid constructor declaration with template |
3529 | | // arguments, we will reject the attempt to form an invalid type-id |
3530 | | // referring to the injected-class-name when we annotate the token, |
3531 | | // per C++ [class.qual]p2. |
3532 | | // |
3533 | | // To improve diagnostics for this case, parse the declaration as a |
3534 | | // constructor (and reject the extra template arguments later). |
3535 | 0 | if ((DSContext == DeclSpecContext::DSC_top_level || |
3536 | 0 | DSContext == DeclSpecContext::DSC_class) && |
3537 | 0 | TemplateId->Name && |
3538 | 0 | Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) && |
3539 | 0 | isConstructorDeclarator(/*Unqualified=*/false, |
3540 | 0 | /*DeductionGuide=*/false, |
3541 | 0 | DS.isFriendSpecified())) { |
3542 | | // The user meant this to be an out-of-line constructor |
3543 | | // definition, but template arguments are not allowed |
3544 | | // there. Just allow this as a constructor; we'll |
3545 | | // complain about it later. |
3546 | 0 | goto DoneWithDeclSpec; |
3547 | 0 | } |
3548 | | |
3549 | 0 | DS.getTypeSpecScope() = SS; |
3550 | 0 | ConsumeAnnotationToken(); // The C++ scope. |
3551 | 0 | assert(Tok.is(tok::annot_template_id) && |
3552 | 0 | "ParseOptionalCXXScopeSpecifier not working"); |
3553 | 0 | AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename); |
3554 | 0 | continue; |
3555 | 0 | } |
3556 | | |
3557 | 0 | if (TemplateId && TemplateId->Kind == TNK_Concept_template) { |
3558 | 0 | DS.getTypeSpecScope() = SS; |
3559 | | // This is probably a qualified placeholder-specifier, e.g., ::C<int> |
3560 | | // auto ... Consume the scope annotation and continue to consume the |
3561 | | // template-id as a placeholder-specifier. Let the next iteration |
3562 | | // diagnose a missing auto. |
3563 | 0 | ConsumeAnnotationToken(); |
3564 | 0 | continue; |
3565 | 0 | } |
3566 | | |
3567 | 0 | if (Next.is(tok::annot_typename)) { |
3568 | 0 | DS.getTypeSpecScope() = SS; |
3569 | 0 | ConsumeAnnotationToken(); // The C++ scope. |
3570 | 0 | TypeResult T = getTypeAnnotation(Tok); |
3571 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, |
3572 | 0 | Tok.getAnnotationEndLoc(), |
3573 | 0 | PrevSpec, DiagID, T, Policy); |
3574 | 0 | if (isInvalid) |
3575 | 0 | break; |
3576 | 0 | DS.SetRangeEnd(Tok.getAnnotationEndLoc()); |
3577 | 0 | ConsumeAnnotationToken(); // The typename |
3578 | 0 | } |
3579 | | |
3580 | 0 | if (AllowImplicitTypename == ImplicitTypenameContext::Yes && |
3581 | 0 | Next.is(tok::annot_template_id) && |
3582 | 0 | static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue()) |
3583 | 0 | ->Kind == TNK_Dependent_template_name) { |
3584 | 0 | DS.getTypeSpecScope() = SS; |
3585 | 0 | ConsumeAnnotationToken(); // The C++ scope. |
3586 | 0 | AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename); |
3587 | 0 | continue; |
3588 | 0 | } |
3589 | | |
3590 | 0 | if (Next.isNot(tok::identifier)) |
3591 | 0 | goto DoneWithDeclSpec; |
3592 | | |
3593 | | // Check whether this is a constructor declaration. If we're in a |
3594 | | // context where the identifier could be a class name, and it has the |
3595 | | // shape of a constructor declaration, process it as one. |
3596 | 0 | if ((DSContext == DeclSpecContext::DSC_top_level || |
3597 | 0 | DSContext == DeclSpecContext::DSC_class) && |
3598 | 0 | Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), |
3599 | 0 | &SS) && |
3600 | 0 | isConstructorDeclarator(/*Unqualified=*/false, |
3601 | 0 | /*DeductionGuide=*/false, |
3602 | 0 | DS.isFriendSpecified(), |
3603 | 0 | &TemplateInfo)) |
3604 | 0 | goto DoneWithDeclSpec; |
3605 | | |
3606 | | // C++20 [temp.spec] 13.9/6. |
3607 | | // This disables the access checking rules for function template explicit |
3608 | | // instantiation and explicit specialization: |
3609 | | // - `return type`. |
3610 | 0 | SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst); |
3611 | |
|
3612 | 0 | ParsedType TypeRep = Actions.getTypeName( |
3613 | 0 | *Next.getIdentifierInfo(), Next.getLocation(), getCurScope(), &SS, |
3614 | 0 | false, false, nullptr, |
3615 | 0 | /*IsCtorOrDtorName=*/false, |
3616 | 0 | /*WantNontrivialTypeSourceInfo=*/true, |
3617 | 0 | isClassTemplateDeductionContext(DSContext), AllowImplicitTypename); |
3618 | |
|
3619 | 0 | if (IsTemplateSpecOrInst) |
3620 | 0 | SAC.done(); |
3621 | | |
3622 | | // If the referenced identifier is not a type, then this declspec is |
3623 | | // erroneous: We already checked about that it has no type specifier, and |
3624 | | // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the |
3625 | | // typename. |
3626 | 0 | if (!TypeRep) { |
3627 | 0 | if (TryAnnotateTypeConstraint()) |
3628 | 0 | goto DoneWithDeclSpec; |
3629 | 0 | if (Tok.isNot(tok::annot_cxxscope) || |
3630 | 0 | NextToken().isNot(tok::identifier)) |
3631 | 0 | continue; |
3632 | | // Eat the scope spec so the identifier is current. |
3633 | 0 | ConsumeAnnotationToken(); |
3634 | 0 | ParsedAttributes Attrs(AttrFactory); |
3635 | 0 | if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) { |
3636 | 0 | if (!Attrs.empty()) { |
3637 | 0 | AttrsLastTime = true; |
3638 | 0 | attrs.takeAllFrom(Attrs); |
3639 | 0 | } |
3640 | 0 | continue; |
3641 | 0 | } |
3642 | 0 | goto DoneWithDeclSpec; |
3643 | 0 | } |
3644 | | |
3645 | 0 | DS.getTypeSpecScope() = SS; |
3646 | 0 | ConsumeAnnotationToken(); // The C++ scope. |
3647 | |
|
3648 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, |
3649 | 0 | DiagID, TypeRep, Policy); |
3650 | 0 | if (isInvalid) |
3651 | 0 | break; |
3652 | | |
3653 | 0 | DS.SetRangeEnd(Tok.getLocation()); |
3654 | 0 | ConsumeToken(); // The typename. |
3655 | |
|
3656 | 0 | continue; |
3657 | 0 | } |
3658 | | |
3659 | 14 | case tok::annot_typename: { |
3660 | | // If we've previously seen a tag definition, we were almost surely |
3661 | | // missing a semicolon after it. |
3662 | 14 | if (DS.hasTypeSpecifier() && DS.hasTagDefinition()) |
3663 | 0 | goto DoneWithDeclSpec; |
3664 | | |
3665 | 14 | TypeResult T = getTypeAnnotation(Tok); |
3666 | 14 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, |
3667 | 14 | DiagID, T, Policy); |
3668 | 14 | if (isInvalid) |
3669 | 0 | break; |
3670 | | |
3671 | 14 | DS.SetRangeEnd(Tok.getAnnotationEndLoc()); |
3672 | 14 | ConsumeAnnotationToken(); // The typename |
3673 | | |
3674 | 14 | continue; |
3675 | 14 | } |
3676 | | |
3677 | 0 | case tok::kw___is_signed: |
3678 | | // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang |
3679 | | // typically treats it as a trait. If we see __is_signed as it appears |
3680 | | // in libstdc++, e.g., |
3681 | | // |
3682 | | // static const bool __is_signed; |
3683 | | // |
3684 | | // then treat __is_signed as an identifier rather than as a keyword. |
3685 | 0 | if (DS.getTypeSpecType() == TST_bool && |
3686 | 0 | DS.getTypeQualifiers() == DeclSpec::TQ_const && |
3687 | 0 | DS.getStorageClassSpec() == DeclSpec::SCS_static) |
3688 | 0 | TryKeywordIdentFallback(true); |
3689 | | |
3690 | | // We're done with the declaration-specifiers. |
3691 | 0 | goto DoneWithDeclSpec; |
3692 | | |
3693 | | // typedef-name |
3694 | 0 | case tok::kw___super: |
3695 | 0 | case tok::kw_decltype: |
3696 | 14.9k | case tok::identifier: |
3697 | 14.9k | ParseIdentifier: { |
3698 | | // This identifier can only be a typedef name if we haven't already seen |
3699 | | // a type-specifier. Without this check we misparse: |
3700 | | // typedef int X; struct Y { short X; }; as 'short int'. |
3701 | 14.9k | if (DS.hasTypeSpecifier()) |
3702 | 3.87k | goto DoneWithDeclSpec; |
3703 | | |
3704 | | // If the token is an identifier named "__declspec" and Microsoft |
3705 | | // extensions are not enabled, it is likely that there will be cascading |
3706 | | // parse errors if this really is a __declspec attribute. Attempt to |
3707 | | // recognize that scenario and recover gracefully. |
3708 | 11.1k | if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) && |
3709 | 11.1k | Tok.getIdentifierInfo()->getName().equals("__declspec")) { |
3710 | 0 | Diag(Loc, diag::err_ms_attributes_not_enabled); |
3711 | | |
3712 | | // The next token should be an open paren. If it is, eat the entire |
3713 | | // attribute declaration and continue. |
3714 | 0 | if (NextToken().is(tok::l_paren)) { |
3715 | | // Consume the __declspec identifier. |
3716 | 0 | ConsumeToken(); |
3717 | | |
3718 | | // Eat the parens and everything between them. |
3719 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
3720 | 0 | if (T.consumeOpen()) { |
3721 | 0 | assert(false && "Not a left paren?"); |
3722 | 0 | return; |
3723 | 0 | } |
3724 | 0 | T.skipToEnd(); |
3725 | 0 | continue; |
3726 | 0 | } |
3727 | 0 | } |
3728 | | |
3729 | | // In C++, check to see if this is a scope specifier like foo::bar::, if |
3730 | | // so handle it as such. This is important for ctor parsing. |
3731 | 11.1k | if (getLangOpts().CPlusPlus) { |
3732 | | // C++20 [temp.spec] 13.9/6. |
3733 | | // This disables the access checking rules for function template |
3734 | | // explicit instantiation and explicit specialization: |
3735 | | // - `return type`. |
3736 | 5.40k | SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst); |
3737 | | |
3738 | 5.40k | const bool Success = TryAnnotateCXXScopeToken(EnteringContext); |
3739 | | |
3740 | 5.40k | if (IsTemplateSpecOrInst) |
3741 | 0 | SAC.done(); |
3742 | | |
3743 | 5.40k | if (Success) { |
3744 | 6 | if (IsTemplateSpecOrInst) |
3745 | 0 | SAC.redelay(); |
3746 | 6 | DS.SetTypeSpecError(); |
3747 | 6 | goto DoneWithDeclSpec; |
3748 | 6 | } |
3749 | | |
3750 | 5.39k | if (!Tok.is(tok::identifier)) |
3751 | 14 | continue; |
3752 | 5.39k | } |
3753 | | |
3754 | | // Check for need to substitute AltiVec keyword tokens. |
3755 | 11.0k | if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid)) |
3756 | 0 | break; |
3757 | | |
3758 | | // [AltiVec] 2.2: [If the 'vector' specifier is used] The syntax does not |
3759 | | // allow the use of a typedef name as a type specifier. |
3760 | 11.0k | if (DS.isTypeAltiVecVector()) |
3761 | 0 | goto DoneWithDeclSpec; |
3762 | | |
3763 | 11.0k | if (DSContext == DeclSpecContext::DSC_objc_method_result && |
3764 | 11.0k | isObjCInstancetype()) { |
3765 | 0 | ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc); |
3766 | 0 | assert(TypeRep); |
3767 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, |
3768 | 0 | DiagID, TypeRep, Policy); |
3769 | 0 | if (isInvalid) |
3770 | 0 | break; |
3771 | | |
3772 | 0 | DS.SetRangeEnd(Loc); |
3773 | 0 | ConsumeToken(); |
3774 | 0 | continue; |
3775 | 0 | } |
3776 | | |
3777 | | // If we're in a context where the identifier could be a class name, |
3778 | | // check whether this is a constructor declaration. |
3779 | 11.0k | if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && |
3780 | 11.0k | Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && |
3781 | 11.0k | isConstructorDeclarator(/*Unqualified=*/true, |
3782 | 0 | /*DeductionGuide=*/false, |
3783 | 0 | DS.isFriendSpecified())) |
3784 | 0 | goto DoneWithDeclSpec; |
3785 | | |
3786 | 11.0k | ParsedType TypeRep = Actions.getTypeName( |
3787 | 11.0k | *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr, |
3788 | 11.0k | false, false, nullptr, false, false, |
3789 | 11.0k | isClassTemplateDeductionContext(DSContext)); |
3790 | | |
3791 | | // If this is not a typedef name, don't parse it as part of the declspec, |
3792 | | // it must be an implicit int or an error. |
3793 | 11.0k | if (!TypeRep) { |
3794 | 11.0k | if (TryAnnotateTypeConstraint()) |
3795 | 0 | goto DoneWithDeclSpec; |
3796 | 11.0k | if (Tok.isNot(tok::identifier)) |
3797 | 0 | continue; |
3798 | 11.0k | ParsedAttributes Attrs(AttrFactory); |
3799 | 11.0k | if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) { |
3800 | 10.2k | if (!Attrs.empty()) { |
3801 | 0 | AttrsLastTime = true; |
3802 | 0 | attrs.takeAllFrom(Attrs); |
3803 | 0 | } |
3804 | 10.2k | continue; |
3805 | 10.2k | } |
3806 | 835 | goto DoneWithDeclSpec; |
3807 | 11.0k | } |
3808 | | |
3809 | | // Likewise, if this is a context where the identifier could be a template |
3810 | | // name, check whether this is a deduction guide declaration. |
3811 | 0 | CXXScopeSpec SS; |
3812 | 0 | if (getLangOpts().CPlusPlus17 && |
3813 | 0 | (DSContext == DeclSpecContext::DSC_class || |
3814 | 0 | DSContext == DeclSpecContext::DSC_top_level) && |
3815 | 0 | Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(), |
3816 | 0 | Tok.getLocation(), SS) && |
3817 | 0 | isConstructorDeclarator(/*Unqualified*/ true, |
3818 | 0 | /*DeductionGuide*/ true)) |
3819 | 0 | goto DoneWithDeclSpec; |
3820 | | |
3821 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, |
3822 | 0 | DiagID, TypeRep, Policy); |
3823 | 0 | if (isInvalid) |
3824 | 0 | break; |
3825 | | |
3826 | 0 | DS.SetRangeEnd(Tok.getLocation()); |
3827 | 0 | ConsumeToken(); // The identifier |
3828 | | |
3829 | | // Objective-C supports type arguments and protocol references |
3830 | | // following an Objective-C object or object pointer |
3831 | | // type. Handle either one of them. |
3832 | 0 | if (Tok.is(tok::less) && getLangOpts().ObjC) { |
3833 | 0 | SourceLocation NewEndLoc; |
3834 | 0 | TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers( |
3835 | 0 | Loc, TypeRep, /*consumeLastToken=*/true, |
3836 | 0 | NewEndLoc); |
3837 | 0 | if (NewTypeRep.isUsable()) { |
3838 | 0 | DS.UpdateTypeRep(NewTypeRep.get()); |
3839 | 0 | DS.SetRangeEnd(NewEndLoc); |
3840 | 0 | } |
3841 | 0 | } |
3842 | | |
3843 | | // Need to support trailing type qualifiers (e.g. "id<p> const"). |
3844 | | // If a type specifier follows, it will be diagnosed elsewhere. |
3845 | 0 | continue; |
3846 | 0 | } |
3847 | | |
3848 | | // type-name or placeholder-specifier |
3849 | 14 | case tok::annot_template_id: { |
3850 | 14 | TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); |
3851 | | |
3852 | 14 | if (TemplateId->hasInvalidName()) { |
3853 | 0 | DS.SetTypeSpecError(); |
3854 | 0 | break; |
3855 | 0 | } |
3856 | | |
3857 | 14 | if (TemplateId->Kind == TNK_Concept_template) { |
3858 | | // If we've already diagnosed that this type-constraint has invalid |
3859 | | // arguments, drop it and just form 'auto' or 'decltype(auto)'. |
3860 | 0 | if (TemplateId->hasInvalidArgs()) |
3861 | 0 | TemplateId = nullptr; |
3862 | | |
3863 | | // Any of the following tokens are likely the start of the user |
3864 | | // forgetting 'auto' or 'decltype(auto)', so diagnose. |
3865 | | // Note: if updating this list, please make sure we update |
3866 | | // isCXXDeclarationSpecifier's check for IsPlaceholderSpecifier to have |
3867 | | // a matching list. |
3868 | 0 | if (NextToken().isOneOf(tok::identifier, tok::kw_const, |
3869 | 0 | tok::kw_volatile, tok::kw_restrict, tok::amp, |
3870 | 0 | tok::ampamp)) { |
3871 | 0 | Diag(Loc, diag::err_placeholder_expected_auto_or_decltype_auto) |
3872 | 0 | << FixItHint::CreateInsertion(NextToken().getLocation(), "auto"); |
3873 | | // Attempt to continue as if 'auto' was placed here. |
3874 | 0 | isInvalid = DS.SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID, |
3875 | 0 | TemplateId, Policy); |
3876 | 0 | break; |
3877 | 0 | } |
3878 | 0 | if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype)) |
3879 | 0 | goto DoneWithDeclSpec; |
3880 | | |
3881 | 0 | if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId)) |
3882 | 0 | TemplateId = nullptr; |
3883 | |
|
3884 | 0 | ConsumeAnnotationToken(); |
3885 | 0 | SourceLocation AutoLoc = Tok.getLocation(); |
3886 | 0 | if (TryConsumeToken(tok::kw_decltype)) { |
3887 | 0 | BalancedDelimiterTracker Tracker(*this, tok::l_paren); |
3888 | 0 | if (Tracker.consumeOpen()) { |
3889 | | // Something like `void foo(Iterator decltype i)` |
3890 | 0 | Diag(Tok, diag::err_expected) << tok::l_paren; |
3891 | 0 | } else { |
3892 | 0 | if (!TryConsumeToken(tok::kw_auto)) { |
3893 | | // Something like `void foo(Iterator decltype(int) i)` |
3894 | 0 | Tracker.skipToEnd(); |
3895 | 0 | Diag(Tok, diag::err_placeholder_expected_auto_or_decltype_auto) |
3896 | 0 | << FixItHint::CreateReplacement(SourceRange(AutoLoc, |
3897 | 0 | Tok.getLocation()), |
3898 | 0 | "auto"); |
3899 | 0 | } else { |
3900 | 0 | Tracker.consumeClose(); |
3901 | 0 | } |
3902 | 0 | } |
3903 | 0 | ConsumedEnd = Tok.getLocation(); |
3904 | 0 | DS.setTypeArgumentRange(Tracker.getRange()); |
3905 | | // Even if something went wrong above, continue as if we've seen |
3906 | | // `decltype(auto)`. |
3907 | 0 | isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec, |
3908 | 0 | DiagID, TemplateId, Policy); |
3909 | 0 | } else { |
3910 | 0 | isInvalid = DS.SetTypeSpecType(TST_auto, AutoLoc, PrevSpec, DiagID, |
3911 | 0 | TemplateId, Policy); |
3912 | 0 | } |
3913 | 0 | break; |
3914 | 0 | } |
3915 | | |
3916 | 14 | if (TemplateId->Kind != TNK_Type_template && |
3917 | 14 | TemplateId->Kind != TNK_Undeclared_template) { |
3918 | | // This template-id does not refer to a type name, so we're |
3919 | | // done with the type-specifiers. |
3920 | 0 | goto DoneWithDeclSpec; |
3921 | 0 | } |
3922 | | |
3923 | | // If we're in a context where the template-id could be a |
3924 | | // constructor name or specialization, check whether this is a |
3925 | | // constructor declaration. |
3926 | 14 | if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && |
3927 | 14 | Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) && |
3928 | 14 | isConstructorDeclarator(/*Unqualified=*/true, |
3929 | 0 | /*DeductionGuide=*/false, |
3930 | 0 | DS.isFriendSpecified())) |
3931 | 0 | goto DoneWithDeclSpec; |
3932 | | |
3933 | | // Turn the template-id annotation token into a type annotation |
3934 | | // token, then try again to parse it as a type-specifier. |
3935 | 14 | CXXScopeSpec SS; |
3936 | 14 | AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename); |
3937 | 14 | continue; |
3938 | 14 | } |
3939 | | |
3940 | | // Attributes support. |
3941 | 0 | case tok::kw___attribute: |
3942 | 0 | case tok::kw___declspec: |
3943 | 0 | ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), LateAttrs); |
3944 | 0 | continue; |
3945 | | |
3946 | | // Microsoft single token adornments. |
3947 | 0 | case tok::kw___forceinline: { |
3948 | 0 | isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID); |
3949 | 0 | IdentifierInfo *AttrName = Tok.getIdentifierInfo(); |
3950 | 0 | SourceLocation AttrNameLoc = Tok.getLocation(); |
3951 | 0 | DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, |
3952 | 0 | nullptr, 0, tok::kw___forceinline); |
3953 | 0 | break; |
3954 | 0 | } |
3955 | | |
3956 | 0 | case tok::kw___unaligned: |
3957 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID, |
3958 | 0 | getLangOpts()); |
3959 | 0 | break; |
3960 | | |
3961 | 0 | case tok::kw___sptr: |
3962 | 0 | case tok::kw___uptr: |
3963 | 0 | case tok::kw___ptr64: |
3964 | 0 | case tok::kw___ptr32: |
3965 | 0 | case tok::kw___w64: |
3966 | 0 | case tok::kw___cdecl: |
3967 | 0 | case tok::kw___stdcall: |
3968 | 0 | case tok::kw___fastcall: |
3969 | 0 | case tok::kw___thiscall: |
3970 | 0 | case tok::kw___regcall: |
3971 | 0 | case tok::kw___vectorcall: |
3972 | 0 | ParseMicrosoftTypeAttributes(DS.getAttributes()); |
3973 | 0 | continue; |
3974 | | |
3975 | 0 | case tok::kw___funcref: |
3976 | 0 | ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes()); |
3977 | 0 | continue; |
3978 | | |
3979 | | // Borland single token adornments. |
3980 | 0 | case tok::kw___pascal: |
3981 | 0 | ParseBorlandTypeAttributes(DS.getAttributes()); |
3982 | 0 | continue; |
3983 | | |
3984 | | // OpenCL single token adornments. |
3985 | 0 | case tok::kw___kernel: |
3986 | 0 | ParseOpenCLKernelAttributes(DS.getAttributes()); |
3987 | 0 | continue; |
3988 | | |
3989 | | // CUDA/HIP single token adornments. |
3990 | 0 | case tok::kw___noinline__: |
3991 | 0 | ParseCUDAFunctionAttributes(DS.getAttributes()); |
3992 | 0 | continue; |
3993 | | |
3994 | | // Nullability type specifiers. |
3995 | 0 | case tok::kw__Nonnull: |
3996 | 0 | case tok::kw__Nullable: |
3997 | 0 | case tok::kw__Nullable_result: |
3998 | 0 | case tok::kw__Null_unspecified: |
3999 | 0 | ParseNullabilityTypeSpecifiers(DS.getAttributes()); |
4000 | 0 | continue; |
4001 | | |
4002 | | // Objective-C 'kindof' types. |
4003 | 0 | case tok::kw___kindof: |
4004 | 0 | DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc, |
4005 | 0 | nullptr, 0, tok::kw___kindof); |
4006 | 0 | (void)ConsumeToken(); |
4007 | 0 | continue; |
4008 | | |
4009 | | // storage-class-specifier |
4010 | 0 | case tok::kw_typedef: |
4011 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc, |
4012 | 0 | PrevSpec, DiagID, Policy); |
4013 | 0 | isStorageClass = true; |
4014 | 0 | break; |
4015 | 0 | case tok::kw_extern: |
4016 | 0 | if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread) |
4017 | 0 | Diag(Tok, diag::ext_thread_before) << "extern"; |
4018 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc, |
4019 | 0 | PrevSpec, DiagID, Policy); |
4020 | 0 | isStorageClass = true; |
4021 | 0 | break; |
4022 | 0 | case tok::kw___private_extern__: |
4023 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern, |
4024 | 0 | Loc, PrevSpec, DiagID, Policy); |
4025 | 0 | isStorageClass = true; |
4026 | 0 | break; |
4027 | 0 | case tok::kw_static: |
4028 | 0 | if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread) |
4029 | 0 | Diag(Tok, diag::ext_thread_before) << "static"; |
4030 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc, |
4031 | 0 | PrevSpec, DiagID, Policy); |
4032 | 0 | isStorageClass = true; |
4033 | 0 | break; |
4034 | 0 | case tok::kw_auto: |
4035 | 0 | if (getLangOpts().CPlusPlus11 || getLangOpts().C23) { |
4036 | 0 | if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { |
4037 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, |
4038 | 0 | PrevSpec, DiagID, Policy); |
4039 | 0 | if (!isInvalid && !getLangOpts().C23) |
4040 | 0 | Diag(Tok, diag::ext_auto_storage_class) |
4041 | 0 | << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); |
4042 | 0 | } else |
4043 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, |
4044 | 0 | DiagID, Policy); |
4045 | 0 | } else |
4046 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, |
4047 | 0 | PrevSpec, DiagID, Policy); |
4048 | 0 | isStorageClass = true; |
4049 | 0 | break; |
4050 | 0 | case tok::kw___auto_type: |
4051 | 0 | Diag(Tok, diag::ext_auto_type); |
4052 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec, |
4053 | 0 | DiagID, Policy); |
4054 | 0 | break; |
4055 | 0 | case tok::kw_register: |
4056 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc, |
4057 | 0 | PrevSpec, DiagID, Policy); |
4058 | 0 | isStorageClass = true; |
4059 | 0 | break; |
4060 | 0 | case tok::kw_mutable: |
4061 | 0 | isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc, |
4062 | 0 | PrevSpec, DiagID, Policy); |
4063 | 0 | isStorageClass = true; |
4064 | 0 | break; |
4065 | 0 | case tok::kw___thread: |
4066 | 0 | isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc, |
4067 | 0 | PrevSpec, DiagID); |
4068 | 0 | isStorageClass = true; |
4069 | 0 | break; |
4070 | 0 | case tok::kw_thread_local: |
4071 | 0 | if (getLangOpts().C23) |
4072 | 0 | Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName(); |
4073 | | // We map thread_local to _Thread_local in C23 mode so it retains the C |
4074 | | // semantics rather than getting the C++ semantics. |
4075 | | // FIXME: diagnostics will show _Thread_local when the user wrote |
4076 | | // thread_local in source in C23 mode; we need some general way to |
4077 | | // identify which way the user spelled the keyword in source. |
4078 | 0 | isInvalid = DS.SetStorageClassSpecThread( |
4079 | 0 | getLangOpts().C23 ? DeclSpec::TSCS__Thread_local |
4080 | 0 | : DeclSpec::TSCS_thread_local, |
4081 | 0 | Loc, PrevSpec, DiagID); |
4082 | 0 | isStorageClass = true; |
4083 | 0 | break; |
4084 | 0 | case tok::kw__Thread_local: |
4085 | 0 | if (!getLangOpts().C11) |
4086 | 0 | Diag(Tok, diag::ext_c11_feature) << Tok.getName(); |
4087 | 0 | isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, |
4088 | 0 | Loc, PrevSpec, DiagID); |
4089 | 0 | isStorageClass = true; |
4090 | 0 | break; |
4091 | | |
4092 | | // function-specifier |
4093 | 0 | case tok::kw_inline: |
4094 | 0 | isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID); |
4095 | 0 | break; |
4096 | 0 | case tok::kw_virtual: |
4097 | | // C++ for OpenCL does not allow virtual function qualifier, to avoid |
4098 | | // function pointers restricted in OpenCL v2.0 s6.9.a. |
4099 | 0 | if (getLangOpts().OpenCLCPlusPlus && |
4100 | 0 | !getActions().getOpenCLOptions().isAvailableOption( |
4101 | 0 | "__cl_clang_function_pointers", getLangOpts())) { |
4102 | 0 | DiagID = diag::err_openclcxx_virtual_function; |
4103 | 0 | PrevSpec = Tok.getIdentifierInfo()->getNameStart(); |
4104 | 0 | isInvalid = true; |
4105 | 0 | } else { |
4106 | 0 | isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID); |
4107 | 0 | } |
4108 | 0 | break; |
4109 | 0 | case tok::kw_explicit: { |
4110 | 0 | SourceLocation ExplicitLoc = Loc; |
4111 | 0 | SourceLocation CloseParenLoc; |
4112 | 0 | ExplicitSpecifier ExplicitSpec(nullptr, ExplicitSpecKind::ResolvedTrue); |
4113 | 0 | ConsumedEnd = ExplicitLoc; |
4114 | 0 | ConsumeToken(); // kw_explicit |
4115 | 0 | if (Tok.is(tok::l_paren)) { |
4116 | 0 | if (getLangOpts().CPlusPlus20 || isExplicitBool() == TPResult::True) { |
4117 | 0 | Diag(Tok.getLocation(), getLangOpts().CPlusPlus20 |
4118 | 0 | ? diag::warn_cxx17_compat_explicit_bool |
4119 | 0 | : diag::ext_explicit_bool); |
4120 | |
|
4121 | 0 | ExprResult ExplicitExpr(static_cast<Expr *>(nullptr)); |
4122 | 0 | BalancedDelimiterTracker Tracker(*this, tok::l_paren); |
4123 | 0 | Tracker.consumeOpen(); |
4124 | |
|
4125 | 0 | EnterExpressionEvaluationContext ConstantEvaluated( |
4126 | 0 | Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); |
4127 | |
|
4128 | 0 | ExplicitExpr = ParseConstantExpressionInExprEvalContext(); |
4129 | 0 | ConsumedEnd = Tok.getLocation(); |
4130 | 0 | if (ExplicitExpr.isUsable()) { |
4131 | 0 | CloseParenLoc = Tok.getLocation(); |
4132 | 0 | Tracker.consumeClose(); |
4133 | 0 | ExplicitSpec = |
4134 | 0 | Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get()); |
4135 | 0 | } else |
4136 | 0 | Tracker.skipToEnd(); |
4137 | 0 | } else { |
4138 | 0 | Diag(Tok.getLocation(), diag::warn_cxx20_compat_explicit_bool); |
4139 | 0 | } |
4140 | 0 | } |
4141 | 0 | isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID, |
4142 | 0 | ExplicitSpec, CloseParenLoc); |
4143 | 0 | break; |
4144 | 0 | } |
4145 | 0 | case tok::kw__Noreturn: |
4146 | 0 | if (!getLangOpts().C11) |
4147 | 0 | Diag(Tok, diag::ext_c11_feature) << Tok.getName(); |
4148 | 0 | isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); |
4149 | 0 | break; |
4150 | | |
4151 | | // alignment-specifier |
4152 | 0 | case tok::kw__Alignas: |
4153 | 0 | if (!getLangOpts().C11) |
4154 | 0 | Diag(Tok, diag::ext_c11_feature) << Tok.getName(); |
4155 | 0 | ParseAlignmentSpecifier(DS.getAttributes()); |
4156 | 0 | continue; |
4157 | | |
4158 | | // friend |
4159 | 0 | case tok::kw_friend: |
4160 | 0 | if (DSContext == DeclSpecContext::DSC_class) |
4161 | 0 | isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); |
4162 | 0 | else { |
4163 | 0 | PrevSpec = ""; // not actually used by the diagnostic |
4164 | 0 | DiagID = diag::err_friend_invalid_in_context; |
4165 | 0 | isInvalid = true; |
4166 | 0 | } |
4167 | 0 | break; |
4168 | | |
4169 | | // Modules |
4170 | 0 | case tok::kw___module_private__: |
4171 | 0 | isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID); |
4172 | 0 | break; |
4173 | | |
4174 | | // constexpr, consteval, constinit specifiers |
4175 | 0 | case tok::kw_constexpr: |
4176 | 0 | isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc, |
4177 | 0 | PrevSpec, DiagID); |
4178 | 0 | break; |
4179 | 0 | case tok::kw_consteval: |
4180 | 0 | isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Consteval, Loc, |
4181 | 0 | PrevSpec, DiagID); |
4182 | 0 | break; |
4183 | 0 | case tok::kw_constinit: |
4184 | 0 | isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constinit, Loc, |
4185 | 0 | PrevSpec, DiagID); |
4186 | 0 | break; |
4187 | | |
4188 | | // type-specifier |
4189 | 0 | case tok::kw_short: |
4190 | 0 | isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Short, Loc, PrevSpec, |
4191 | 0 | DiagID, Policy); |
4192 | 0 | break; |
4193 | 0 | case tok::kw_long: |
4194 | 0 | if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Long) |
4195 | 0 | isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Long, Loc, PrevSpec, |
4196 | 0 | DiagID, Policy); |
4197 | 0 | else |
4198 | 0 | isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc, |
4199 | 0 | PrevSpec, DiagID, Policy); |
4200 | 0 | break; |
4201 | 0 | case tok::kw___int64: |
4202 | 0 | isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc, |
4203 | 0 | PrevSpec, DiagID, Policy); |
4204 | 0 | break; |
4205 | 0 | case tok::kw_signed: |
4206 | 0 | isInvalid = |
4207 | 0 | DS.SetTypeSpecSign(TypeSpecifierSign::Signed, Loc, PrevSpec, DiagID); |
4208 | 0 | break; |
4209 | 0 | case tok::kw_unsigned: |
4210 | 0 | isInvalid = DS.SetTypeSpecSign(TypeSpecifierSign::Unsigned, Loc, PrevSpec, |
4211 | 0 | DiagID); |
4212 | 0 | break; |
4213 | 0 | case tok::kw__Complex: |
4214 | 0 | if (!getLangOpts().C99) |
4215 | 0 | Diag(Tok, diag::ext_c99_feature) << Tok.getName(); |
4216 | 0 | isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec, |
4217 | 0 | DiagID); |
4218 | 0 | break; |
4219 | 0 | case tok::kw__Imaginary: |
4220 | 0 | if (!getLangOpts().C99) |
4221 | 0 | Diag(Tok, diag::ext_c99_feature) << Tok.getName(); |
4222 | 0 | isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec, |
4223 | 0 | DiagID); |
4224 | 0 | break; |
4225 | 0 | case tok::kw_void: |
4226 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, |
4227 | 0 | DiagID, Policy); |
4228 | 0 | break; |
4229 | 0 | case tok::kw_char: |
4230 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, |
4231 | 0 | DiagID, Policy); |
4232 | 0 | break; |
4233 | 0 | case tok::kw_int: |
4234 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, |
4235 | 0 | DiagID, Policy); |
4236 | 0 | break; |
4237 | 0 | case tok::kw__ExtInt: |
4238 | 0 | case tok::kw__BitInt: { |
4239 | 0 | DiagnoseBitIntUse(Tok); |
4240 | 0 | ExprResult ER = ParseExtIntegerArgument(); |
4241 | 0 | if (ER.isInvalid()) |
4242 | 0 | continue; |
4243 | 0 | isInvalid = DS.SetBitIntType(Loc, ER.get(), PrevSpec, DiagID, Policy); |
4244 | 0 | ConsumedEnd = PrevTokLocation; |
4245 | 0 | break; |
4246 | 0 | } |
4247 | 0 | case tok::kw___int128: |
4248 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, |
4249 | 0 | DiagID, Policy); |
4250 | 0 | break; |
4251 | 0 | case tok::kw_half: |
4252 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, |
4253 | 0 | DiagID, Policy); |
4254 | 0 | break; |
4255 | 0 | case tok::kw___bf16: |
4256 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec, |
4257 | 0 | DiagID, Policy); |
4258 | 0 | break; |
4259 | 0 | case tok::kw_float: |
4260 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, |
4261 | 0 | DiagID, Policy); |
4262 | 0 | break; |
4263 | 0 | case tok::kw_double: |
4264 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, |
4265 | 0 | DiagID, Policy); |
4266 | 0 | break; |
4267 | 0 | case tok::kw__Float16: |
4268 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, |
4269 | 0 | DiagID, Policy); |
4270 | 0 | break; |
4271 | 0 | case tok::kw__Accum: |
4272 | 0 | assert(getLangOpts().FixedPoint && |
4273 | 0 | "This keyword is only used when fixed point types are enabled " |
4274 | 0 | "with `-ffixed-point`"); |
4275 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, DiagID, |
4276 | 0 | Policy); |
4277 | 0 | break; |
4278 | 0 | case tok::kw__Fract: |
4279 | 0 | assert(getLangOpts().FixedPoint && |
4280 | 0 | "This keyword is only used when fixed point types are enabled " |
4281 | 0 | "with `-ffixed-point`"); |
4282 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, DiagID, |
4283 | 0 | Policy); |
4284 | 0 | break; |
4285 | 0 | case tok::kw__Sat: |
4286 | 0 | assert(getLangOpts().FixedPoint && |
4287 | 0 | "This keyword is only used when fixed point types are enabled " |
4288 | 0 | "with `-ffixed-point`"); |
4289 | 0 | isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID); |
4290 | 0 | break; |
4291 | 0 | case tok::kw___float128: |
4292 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, |
4293 | 0 | DiagID, Policy); |
4294 | 0 | break; |
4295 | 0 | case tok::kw___ibm128: |
4296 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec, |
4297 | 0 | DiagID, Policy); |
4298 | 0 | break; |
4299 | 0 | case tok::kw_wchar_t: |
4300 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, |
4301 | 0 | DiagID, Policy); |
4302 | 0 | break; |
4303 | 0 | case tok::kw_char8_t: |
4304 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec, |
4305 | 0 | DiagID, Policy); |
4306 | 0 | break; |
4307 | 0 | case tok::kw_char16_t: |
4308 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, |
4309 | 0 | DiagID, Policy); |
4310 | 0 | break; |
4311 | 0 | case tok::kw_char32_t: |
4312 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, |
4313 | 0 | DiagID, Policy); |
4314 | 0 | break; |
4315 | 0 | case tok::kw_bool: |
4316 | 0 | if (getLangOpts().C23) |
4317 | 0 | Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName(); |
4318 | 0 | [[fallthrough]]; |
4319 | 0 | case tok::kw__Bool: |
4320 | 0 | if (Tok.is(tok::kw__Bool) && !getLangOpts().C99) |
4321 | 0 | Diag(Tok, diag::ext_c99_feature) << Tok.getName(); |
4322 | |
|
4323 | 0 | if (Tok.is(tok::kw_bool) && |
4324 | 0 | DS.getTypeSpecType() != DeclSpec::TST_unspecified && |
4325 | 0 | DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { |
4326 | 0 | PrevSpec = ""; // Not used by the diagnostic. |
4327 | 0 | DiagID = diag::err_bool_redeclaration; |
4328 | | // For better error recovery. |
4329 | 0 | Tok.setKind(tok::identifier); |
4330 | 0 | isInvalid = true; |
4331 | 0 | } else { |
4332 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, |
4333 | 0 | DiagID, Policy); |
4334 | 0 | } |
4335 | 0 | break; |
4336 | 0 | case tok::kw__Decimal32: |
4337 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, |
4338 | 0 | DiagID, Policy); |
4339 | 0 | break; |
4340 | 0 | case tok::kw__Decimal64: |
4341 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec, |
4342 | 0 | DiagID, Policy); |
4343 | 0 | break; |
4344 | 0 | case tok::kw__Decimal128: |
4345 | 0 | isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, |
4346 | 0 | DiagID, Policy); |
4347 | 0 | break; |
4348 | 0 | case tok::kw___vector: |
4349 | 0 | isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); |
4350 | 0 | break; |
4351 | 0 | case tok::kw___pixel: |
4352 | 0 | isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy); |
4353 | 0 | break; |
4354 | 0 | case tok::kw___bool: |
4355 | 0 | isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy); |
4356 | 0 | break; |
4357 | 0 | case tok::kw_pipe: |
4358 | 0 | if (!getLangOpts().OpenCL || |
4359 | 0 | getLangOpts().getOpenCLCompatibleVersion() < 200) { |
4360 | | // OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier |
4361 | | // should support the "pipe" word as identifier. |
4362 | 0 | Tok.getIdentifierInfo()->revertTokenIDToIdentifier(); |
4363 | 0 | Tok.setKind(tok::identifier); |
4364 | 0 | goto DoneWithDeclSpec; |
4365 | 0 | } else if (!getLangOpts().OpenCLPipes) { |
4366 | 0 | DiagID = diag::err_opencl_unknown_type_specifier; |
4367 | 0 | PrevSpec = Tok.getIdentifierInfo()->getNameStart(); |
4368 | 0 | isInvalid = true; |
4369 | 0 | } else |
4370 | 0 | isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy); |
4371 | 0 | break; |
4372 | | // We only need to enumerate each image type once. |
4373 | 0 | #define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) |
4374 | 0 | #define IMAGE_WRITE_TYPE(Type, Id, Ext) |
4375 | 0 | #define IMAGE_READ_TYPE(ImgType, Id, Ext) \ |
4376 | 0 | case tok::kw_##ImgType##_t: \ |
4377 | 0 | if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \ |
4378 | 0 | goto DoneWithDeclSpec; \ |
4379 | 0 | break; |
4380 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
4381 | 0 | case tok::kw___unknown_anytype: |
4382 | 0 | isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc, |
4383 | 0 | PrevSpec, DiagID, Policy); |
4384 | 0 | break; |
4385 | | |
4386 | | // class-specifier: |
4387 | 0 | case tok::kw_class: |
4388 | 0 | case tok::kw_struct: |
4389 | 0 | case tok::kw___interface: |
4390 | 0 | case tok::kw_union: { |
4391 | 0 | tok::TokenKind Kind = Tok.getKind(); |
4392 | 0 | ConsumeToken(); |
4393 | | |
4394 | | // These are attributes following class specifiers. |
4395 | | // To produce better diagnostic, we parse them when |
4396 | | // parsing class specifier. |
4397 | 0 | ParsedAttributes Attributes(AttrFactory); |
4398 | 0 | ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS, |
4399 | 0 | EnteringContext, DSContext, Attributes); |
4400 | | |
4401 | | // If there are attributes following class specifier, |
4402 | | // take them over and handle them here. |
4403 | 0 | if (!Attributes.empty()) { |
4404 | 0 | AttrsLastTime = true; |
4405 | 0 | attrs.takeAllFrom(Attributes); |
4406 | 0 | } |
4407 | 0 | continue; |
4408 | 0 | } |
4409 | | |
4410 | | // enum-specifier: |
4411 | 0 | case tok::kw_enum: |
4412 | 0 | ConsumeToken(); |
4413 | 0 | ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext); |
4414 | 0 | continue; |
4415 | | |
4416 | | // cv-qualifier: |
4417 | 0 | case tok::kw_const: |
4418 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID, |
4419 | 0 | getLangOpts()); |
4420 | 0 | break; |
4421 | 0 | case tok::kw_volatile: |
4422 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, |
4423 | 0 | getLangOpts()); |
4424 | 0 | break; |
4425 | 0 | case tok::kw_restrict: |
4426 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, |
4427 | 0 | getLangOpts()); |
4428 | 0 | break; |
4429 | | |
4430 | | // C++ typename-specifier: |
4431 | 0 | case tok::kw_typename: |
4432 | 0 | if (TryAnnotateTypeOrScopeToken()) { |
4433 | 0 | DS.SetTypeSpecError(); |
4434 | 0 | goto DoneWithDeclSpec; |
4435 | 0 | } |
4436 | 0 | if (!Tok.is(tok::kw_typename)) |
4437 | 0 | continue; |
4438 | 0 | break; |
4439 | | |
4440 | | // C23/GNU typeof support. |
4441 | 0 | case tok::kw_typeof: |
4442 | 0 | case tok::kw_typeof_unqual: |
4443 | 0 | ParseTypeofSpecifier(DS); |
4444 | 0 | continue; |
4445 | | |
4446 | 0 | case tok::annot_decltype: |
4447 | 0 | ParseDecltypeSpecifier(DS); |
4448 | 0 | continue; |
4449 | | |
4450 | 0 | case tok::annot_pragma_pack: |
4451 | 0 | HandlePragmaPack(); |
4452 | 0 | continue; |
4453 | | |
4454 | 0 | case tok::annot_pragma_ms_pragma: |
4455 | 0 | HandlePragmaMSPragma(); |
4456 | 0 | continue; |
4457 | | |
4458 | 0 | case tok::annot_pragma_ms_vtordisp: |
4459 | 0 | HandlePragmaMSVtorDisp(); |
4460 | 0 | continue; |
4461 | | |
4462 | 0 | case tok::annot_pragma_ms_pointers_to_members: |
4463 | 0 | HandlePragmaMSPointersToMembers(); |
4464 | 0 | continue; |
4465 | | |
4466 | 0 | #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: |
4467 | 0 | #include "clang/Basic/TransformTypeTraits.def" |
4468 | | // HACK: libstdc++ already uses '__remove_cv' as an alias template so we |
4469 | | // work around this by expecting all transform type traits to be suffixed |
4470 | | // with '('. They're an identifier otherwise. |
4471 | 0 | if (!MaybeParseTypeTransformTypeSpecifier(DS)) |
4472 | 0 | goto ParseIdentifier; |
4473 | 0 | continue; |
4474 | | |
4475 | 0 | case tok::kw__Atomic: |
4476 | | // C11 6.7.2.4/4: |
4477 | | // If the _Atomic keyword is immediately followed by a left parenthesis, |
4478 | | // it is interpreted as a type specifier (with a type name), not as a |
4479 | | // type qualifier. |
4480 | 0 | if (!getLangOpts().C11) |
4481 | 0 | Diag(Tok, diag::ext_c11_feature) << Tok.getName(); |
4482 | |
|
4483 | 0 | if (NextToken().is(tok::l_paren)) { |
4484 | 0 | ParseAtomicSpecifier(DS); |
4485 | 0 | continue; |
4486 | 0 | } |
4487 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID, |
4488 | 0 | getLangOpts()); |
4489 | 0 | break; |
4490 | | |
4491 | | // OpenCL address space qualifiers: |
4492 | 0 | case tok::kw___generic: |
4493 | | // generic address space is introduced only in OpenCL v2.0 |
4494 | | // see OpenCL C Spec v2.0 s6.5.5 |
4495 | | // OpenCL v3.0 introduces __opencl_c_generic_address_space |
4496 | | // feature macro to indicate if generic address space is supported |
4497 | 0 | if (!Actions.getLangOpts().OpenCLGenericAddressSpace) { |
4498 | 0 | DiagID = diag::err_opencl_unknown_type_specifier; |
4499 | 0 | PrevSpec = Tok.getIdentifierInfo()->getNameStart(); |
4500 | 0 | isInvalid = true; |
4501 | 0 | break; |
4502 | 0 | } |
4503 | 0 | [[fallthrough]]; |
4504 | 0 | case tok::kw_private: |
4505 | | // It's fine (but redundant) to check this for __generic on the |
4506 | | // fallthrough path; we only form the __generic token in OpenCL mode. |
4507 | 0 | if (!getLangOpts().OpenCL) |
4508 | 0 | goto DoneWithDeclSpec; |
4509 | 0 | [[fallthrough]]; |
4510 | 0 | case tok::kw___private: |
4511 | 0 | case tok::kw___global: |
4512 | 0 | case tok::kw___local: |
4513 | 0 | case tok::kw___constant: |
4514 | | // OpenCL access qualifiers: |
4515 | 0 | case tok::kw___read_only: |
4516 | 0 | case tok::kw___write_only: |
4517 | 0 | case tok::kw___read_write: |
4518 | 0 | ParseOpenCLQualifiers(DS.getAttributes()); |
4519 | 0 | break; |
4520 | | |
4521 | 0 | case tok::kw_groupshared: |
4522 | 0 | case tok::kw_in: |
4523 | 0 | case tok::kw_inout: |
4524 | 0 | case tok::kw_out: |
4525 | | // NOTE: ParseHLSLQualifiers will consume the qualifier token. |
4526 | 0 | ParseHLSLQualifiers(DS.getAttributes()); |
4527 | 0 | continue; |
4528 | | |
4529 | 236 | case tok::less: |
4530 | | // GCC ObjC supports types like "<SomeProtocol>" as a synonym for |
4531 | | // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous, |
4532 | | // but we support it. |
4533 | 236 | if (DS.hasTypeSpecifier() || !getLangOpts().ObjC) |
4534 | 156 | goto DoneWithDeclSpec; |
4535 | | |
4536 | 80 | SourceLocation StartLoc = Tok.getLocation(); |
4537 | 80 | SourceLocation EndLoc; |
4538 | 80 | TypeResult Type = parseObjCProtocolQualifierType(EndLoc); |
4539 | 80 | if (Type.isUsable()) { |
4540 | 80 | if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, StartLoc, |
4541 | 80 | PrevSpec, DiagID, Type.get(), |
4542 | 80 | Actions.getASTContext().getPrintingPolicy())) |
4543 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
4544 | | |
4545 | 80 | DS.SetRangeEnd(EndLoc); |
4546 | 80 | } else { |
4547 | 0 | DS.SetTypeSpecError(); |
4548 | 0 | } |
4549 | | |
4550 | | // Need to support trailing type qualifiers (e.g. "id<p> const"). |
4551 | | // If a type specifier follows, it will be diagnosed elsewhere. |
4552 | 80 | continue; |
4553 | 34.3k | } |
4554 | | |
4555 | 0 | DS.SetRangeEnd(ConsumedEnd.isValid() ? ConsumedEnd : Tok.getLocation()); |
4556 | | |
4557 | | // If the specifier wasn't legal, issue a diagnostic. |
4558 | 0 | if (isInvalid) { |
4559 | 0 | assert(PrevSpec && "Method did not return previous specifier!"); |
4560 | 0 | assert(DiagID); |
4561 | | |
4562 | 0 | if (DiagID == diag::ext_duplicate_declspec || |
4563 | 0 | DiagID == diag::ext_warn_duplicate_declspec || |
4564 | 0 | DiagID == diag::err_duplicate_declspec) |
4565 | 0 | Diag(Loc, DiagID) << PrevSpec |
4566 | 0 | << FixItHint::CreateRemoval( |
4567 | 0 | SourceRange(Loc, DS.getEndLoc())); |
4568 | 0 | else if (DiagID == diag::err_opencl_unknown_type_specifier) { |
4569 | 0 | Diag(Loc, DiagID) << getLangOpts().getOpenCLVersionString() << PrevSpec |
4570 | 0 | << isStorageClass; |
4571 | 0 | } else |
4572 | 0 | Diag(Loc, DiagID) << PrevSpec; |
4573 | 0 | } |
4574 | | |
4575 | 0 | if (DiagID != diag::err_bool_redeclaration && ConsumedEnd.isInvalid()) |
4576 | | // After an error the next token can be an annotation token. |
4577 | 0 | ConsumeAnyToken(); |
4578 | |
|
4579 | 0 | AttrsLastTime = false; |
4580 | 0 | } |
4581 | 23.9k | } |
4582 | | |
4583 | | /// ParseStructDeclaration - Parse a struct declaration without the terminating |
4584 | | /// semicolon. |
4585 | | /// |
4586 | | /// Note that a struct declaration refers to a declaration in a struct, |
4587 | | /// not to the declaration of a struct. |
4588 | | /// |
4589 | | /// struct-declaration: |
4590 | | /// [C23] attributes-specifier-seq[opt] |
4591 | | /// specifier-qualifier-list struct-declarator-list |
4592 | | /// [GNU] __extension__ struct-declaration |
4593 | | /// [GNU] specifier-qualifier-list |
4594 | | /// struct-declarator-list: |
4595 | | /// struct-declarator |
4596 | | /// struct-declarator-list ',' struct-declarator |
4597 | | /// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator |
4598 | | /// struct-declarator: |
4599 | | /// declarator |
4600 | | /// [GNU] declarator attributes[opt] |
4601 | | /// declarator[opt] ':' constant-expression |
4602 | | /// [GNU] declarator[opt] ':' constant-expression attributes[opt] |
4603 | | /// |
4604 | | void Parser::ParseStructDeclaration( |
4605 | | ParsingDeclSpec &DS, |
4606 | 0 | llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback) { |
4607 | |
|
4608 | 0 | if (Tok.is(tok::kw___extension__)) { |
4609 | | // __extension__ silences extension warnings in the subexpression. |
4610 | 0 | ExtensionRAIIObject O(Diags); // Use RAII to do this. |
4611 | 0 | ConsumeToken(); |
4612 | 0 | return ParseStructDeclaration(DS, FieldsCallback); |
4613 | 0 | } |
4614 | | |
4615 | | // Parse leading attributes. |
4616 | 0 | ParsedAttributes Attrs(AttrFactory); |
4617 | 0 | MaybeParseCXX11Attributes(Attrs); |
4618 | | |
4619 | | // Parse the common specifier-qualifiers-list piece. |
4620 | 0 | ParseSpecifierQualifierList(DS); |
4621 | | |
4622 | | // If there are no declarators, this is a free-standing declaration |
4623 | | // specifier. Let the actions module cope with it. |
4624 | 0 | if (Tok.is(tok::semi)) { |
4625 | | // C23 6.7.2.1p9 : "The optional attribute specifier sequence in a |
4626 | | // member declaration appertains to each of the members declared by the |
4627 | | // member declarator list; it shall not appear if the optional member |
4628 | | // declarator list is omitted." |
4629 | 0 | ProhibitAttributes(Attrs); |
4630 | 0 | RecordDecl *AnonRecord = nullptr; |
4631 | 0 | Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( |
4632 | 0 | getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord); |
4633 | 0 | assert(!AnonRecord && "Did not expect anonymous struct or union here"); |
4634 | 0 | DS.complete(TheDecl); |
4635 | 0 | return; |
4636 | 0 | } |
4637 | | |
4638 | | // Read struct-declarators until we find the semicolon. |
4639 | 0 | bool FirstDeclarator = true; |
4640 | 0 | SourceLocation CommaLoc; |
4641 | 0 | while (true) { |
4642 | 0 | ParsingFieldDeclarator DeclaratorInfo(*this, DS, Attrs); |
4643 | 0 | DeclaratorInfo.D.setCommaLoc(CommaLoc); |
4644 | | |
4645 | | // Attributes are only allowed here on successive declarators. |
4646 | 0 | if (!FirstDeclarator) { |
4647 | | // However, this does not apply for [[]] attributes (which could show up |
4648 | | // before or after the __attribute__ attributes). |
4649 | 0 | DiagnoseAndSkipCXX11Attributes(); |
4650 | 0 | MaybeParseGNUAttributes(DeclaratorInfo.D); |
4651 | 0 | DiagnoseAndSkipCXX11Attributes(); |
4652 | 0 | } |
4653 | | |
4654 | | /// struct-declarator: declarator |
4655 | | /// struct-declarator: declarator[opt] ':' constant-expression |
4656 | 0 | if (Tok.isNot(tok::colon)) { |
4657 | | // Don't parse FOO:BAR as if it were a typo for FOO::BAR. |
4658 | 0 | ColonProtectionRAIIObject X(*this); |
4659 | 0 | ParseDeclarator(DeclaratorInfo.D); |
4660 | 0 | } else |
4661 | 0 | DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation()); |
4662 | |
|
4663 | 0 | if (TryConsumeToken(tok::colon)) { |
4664 | 0 | ExprResult Res(ParseConstantExpression()); |
4665 | 0 | if (Res.isInvalid()) |
4666 | 0 | SkipUntil(tok::semi, StopBeforeMatch); |
4667 | 0 | else |
4668 | 0 | DeclaratorInfo.BitfieldSize = Res.get(); |
4669 | 0 | } |
4670 | | |
4671 | | // If attributes exist after the declarator, parse them. |
4672 | 0 | MaybeParseGNUAttributes(DeclaratorInfo.D); |
4673 | | |
4674 | | // We're done with this declarator; invoke the callback. |
4675 | 0 | FieldsCallback(DeclaratorInfo); |
4676 | | |
4677 | | // If we don't have a comma, it is either the end of the list (a ';') |
4678 | | // or an error, bail out. |
4679 | 0 | if (!TryConsumeToken(tok::comma, CommaLoc)) |
4680 | 0 | return; |
4681 | | |
4682 | 0 | FirstDeclarator = false; |
4683 | 0 | } |
4684 | 0 | } |
4685 | | |
4686 | | /// ParseStructUnionBody |
4687 | | /// struct-contents: |
4688 | | /// struct-declaration-list |
4689 | | /// [EXT] empty |
4690 | | /// [GNU] "struct-declaration-list" without terminating ';' |
4691 | | /// struct-declaration-list: |
4692 | | /// struct-declaration |
4693 | | /// struct-declaration-list struct-declaration |
4694 | | /// [OBC] '@' 'defs' '(' class-name ')' |
4695 | | /// |
4696 | | void Parser::ParseStructUnionBody(SourceLocation RecordLoc, |
4697 | 0 | DeclSpec::TST TagType, RecordDecl *TagDecl) { |
4698 | 0 | PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, |
4699 | 0 | "parsing struct/union body"); |
4700 | 0 | assert(!getLangOpts().CPlusPlus && "C++ declarations not supported"); |
4701 | | |
4702 | 0 | BalancedDelimiterTracker T(*this, tok::l_brace); |
4703 | 0 | if (T.consumeOpen()) |
4704 | 0 | return; |
4705 | | |
4706 | 0 | ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); |
4707 | 0 | Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); |
4708 | | |
4709 | | // While we still have something to read, read the declarations in the struct. |
4710 | 0 | while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && |
4711 | 0 | Tok.isNot(tok::eof)) { |
4712 | | // Each iteration of this loop reads one struct-declaration. |
4713 | | |
4714 | | // Check for extraneous top-level semicolon. |
4715 | 0 | if (Tok.is(tok::semi)) { |
4716 | 0 | ConsumeExtraSemi(InsideStruct, TagType); |
4717 | 0 | continue; |
4718 | 0 | } |
4719 | | |
4720 | | // Parse _Static_assert declaration. |
4721 | 0 | if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) { |
4722 | 0 | SourceLocation DeclEnd; |
4723 | 0 | ParseStaticAssertDeclaration(DeclEnd); |
4724 | 0 | continue; |
4725 | 0 | } |
4726 | | |
4727 | 0 | if (Tok.is(tok::annot_pragma_pack)) { |
4728 | 0 | HandlePragmaPack(); |
4729 | 0 | continue; |
4730 | 0 | } |
4731 | | |
4732 | 0 | if (Tok.is(tok::annot_pragma_align)) { |
4733 | 0 | HandlePragmaAlign(); |
4734 | 0 | continue; |
4735 | 0 | } |
4736 | | |
4737 | 0 | if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { |
4738 | | // Result can be ignored, because it must be always empty. |
4739 | 0 | AccessSpecifier AS = AS_none; |
4740 | 0 | ParsedAttributes Attrs(AttrFactory); |
4741 | 0 | (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs); |
4742 | 0 | continue; |
4743 | 0 | } |
4744 | | |
4745 | 0 | if (Tok.is(tok::annot_pragma_openacc)) { |
4746 | 0 | ParseOpenACCDirectiveDecl(); |
4747 | 0 | continue; |
4748 | 0 | } |
4749 | | |
4750 | 0 | if (tok::isPragmaAnnotation(Tok.getKind())) { |
4751 | 0 | Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) |
4752 | 0 | << DeclSpec::getSpecifierName( |
4753 | 0 | TagType, Actions.getASTContext().getPrintingPolicy()); |
4754 | 0 | ConsumeAnnotationToken(); |
4755 | 0 | continue; |
4756 | 0 | } |
4757 | | |
4758 | 0 | if (!Tok.is(tok::at)) { |
4759 | 0 | auto CFieldCallback = [&](ParsingFieldDeclarator &FD) { |
4760 | | // Install the declarator into the current TagDecl. |
4761 | 0 | Decl *Field = |
4762 | 0 | Actions.ActOnField(getCurScope(), TagDecl, |
4763 | 0 | FD.D.getDeclSpec().getSourceRange().getBegin(), |
4764 | 0 | FD.D, FD.BitfieldSize); |
4765 | 0 | FD.complete(Field); |
4766 | 0 | }; |
4767 | | |
4768 | | // Parse all the comma separated declarators. |
4769 | 0 | ParsingDeclSpec DS(*this); |
4770 | 0 | ParseStructDeclaration(DS, CFieldCallback); |
4771 | 0 | } else { // Handle @defs |
4772 | 0 | ConsumeToken(); |
4773 | 0 | if (!Tok.isObjCAtKeyword(tok::objc_defs)) { |
4774 | 0 | Diag(Tok, diag::err_unexpected_at); |
4775 | 0 | SkipUntil(tok::semi); |
4776 | 0 | continue; |
4777 | 0 | } |
4778 | 0 | ConsumeToken(); |
4779 | 0 | ExpectAndConsume(tok::l_paren); |
4780 | 0 | if (!Tok.is(tok::identifier)) { |
4781 | 0 | Diag(Tok, diag::err_expected) << tok::identifier; |
4782 | 0 | SkipUntil(tok::semi); |
4783 | 0 | continue; |
4784 | 0 | } |
4785 | 0 | SmallVector<Decl *, 16> Fields; |
4786 | 0 | Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(), |
4787 | 0 | Tok.getIdentifierInfo(), Fields); |
4788 | 0 | ConsumeToken(); |
4789 | 0 | ExpectAndConsume(tok::r_paren); |
4790 | 0 | } |
4791 | | |
4792 | 0 | if (TryConsumeToken(tok::semi)) |
4793 | 0 | continue; |
4794 | | |
4795 | 0 | if (Tok.is(tok::r_brace)) { |
4796 | 0 | ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list); |
4797 | 0 | break; |
4798 | 0 | } |
4799 | | |
4800 | 0 | ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); |
4801 | | // Skip to end of block or statement to avoid ext-warning on extra ';'. |
4802 | 0 | SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); |
4803 | | // If we stopped at a ';', eat it. |
4804 | 0 | TryConsumeToken(tok::semi); |
4805 | 0 | } |
4806 | |
|
4807 | 0 | T.consumeClose(); |
4808 | |
|
4809 | 0 | ParsedAttributes attrs(AttrFactory); |
4810 | | // If attributes exist after struct contents, parse them. |
4811 | 0 | MaybeParseGNUAttributes(attrs); |
4812 | |
|
4813 | 0 | SmallVector<Decl *, 32> FieldDecls(TagDecl->fields()); |
4814 | |
|
4815 | 0 | Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, |
4816 | 0 | T.getOpenLocation(), T.getCloseLocation(), attrs); |
4817 | 0 | StructScope.Exit(); |
4818 | 0 | Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); |
4819 | 0 | } |
4820 | | |
4821 | | /// ParseEnumSpecifier |
4822 | | /// enum-specifier: [C99 6.7.2.2] |
4823 | | /// 'enum' identifier[opt] '{' enumerator-list '}' |
4824 | | ///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}' |
4825 | | /// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt] |
4826 | | /// '}' attributes[opt] |
4827 | | /// [MS] 'enum' __declspec[opt] identifier[opt] '{' enumerator-list ',' [opt] |
4828 | | /// '}' |
4829 | | /// 'enum' identifier |
4830 | | /// [GNU] 'enum' attributes[opt] identifier |
4831 | | /// |
4832 | | /// [C++11] enum-head '{' enumerator-list[opt] '}' |
4833 | | /// [C++11] enum-head '{' enumerator-list ',' '}' |
4834 | | /// |
4835 | | /// enum-head: [C++11] |
4836 | | /// enum-key attribute-specifier-seq[opt] identifier[opt] enum-base[opt] |
4837 | | /// enum-key attribute-specifier-seq[opt] nested-name-specifier |
4838 | | /// identifier enum-base[opt] |
4839 | | /// |
4840 | | /// enum-key: [C++11] |
4841 | | /// 'enum' |
4842 | | /// 'enum' 'class' |
4843 | | /// 'enum' 'struct' |
4844 | | /// |
4845 | | /// enum-base: [C++11] |
4846 | | /// ':' type-specifier-seq |
4847 | | /// |
4848 | | /// [C++] elaborated-type-specifier: |
4849 | | /// [C++] 'enum' nested-name-specifier[opt] identifier |
4850 | | /// |
4851 | | void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, |
4852 | | const ParsedTemplateInfo &TemplateInfo, |
4853 | 0 | AccessSpecifier AS, DeclSpecContext DSC) { |
4854 | | // Parse the tag portion of this. |
4855 | 0 | if (Tok.is(tok::code_completion)) { |
4856 | | // Code completion for an enum name. |
4857 | 0 | cutOffParsing(); |
4858 | 0 | Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum); |
4859 | 0 | DS.SetTypeSpecError(); // Needed by ActOnUsingDeclaration. |
4860 | 0 | return; |
4861 | 0 | } |
4862 | | |
4863 | | // If attributes exist after tag, parse them. |
4864 | 0 | ParsedAttributes attrs(AttrFactory); |
4865 | 0 | MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs); |
4866 | |
|
4867 | 0 | SourceLocation ScopedEnumKWLoc; |
4868 | 0 | bool IsScopedUsingClassTag = false; |
4869 | | |
4870 | | // In C++11, recognize 'enum class' and 'enum struct'. |
4871 | 0 | if (Tok.isOneOf(tok::kw_class, tok::kw_struct) && getLangOpts().CPlusPlus) { |
4872 | 0 | Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum |
4873 | 0 | : diag::ext_scoped_enum); |
4874 | 0 | IsScopedUsingClassTag = Tok.is(tok::kw_class); |
4875 | 0 | ScopedEnumKWLoc = ConsumeToken(); |
4876 | | |
4877 | | // Attributes are not allowed between these keywords. Diagnose, |
4878 | | // but then just treat them like they appeared in the right place. |
4879 | 0 | ProhibitAttributes(attrs); |
4880 | | |
4881 | | // They are allowed afterwards, though. |
4882 | 0 | MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs); |
4883 | 0 | } |
4884 | | |
4885 | | // C++11 [temp.explicit]p12: |
4886 | | // The usual access controls do not apply to names used to specify |
4887 | | // explicit instantiations. |
4888 | | // We extend this to also cover explicit specializations. Note that |
4889 | | // we don't suppress if this turns out to be an elaborated type |
4890 | | // specifier. |
4891 | 0 | bool shouldDelayDiagsInTag = |
4892 | 0 | (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || |
4893 | 0 | TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); |
4894 | 0 | SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); |
4895 | | |
4896 | | // Determine whether this declaration is permitted to have an enum-base. |
4897 | 0 | AllowDefiningTypeSpec AllowEnumSpecifier = |
4898 | 0 | isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus); |
4899 | 0 | bool CanBeOpaqueEnumDeclaration = |
4900 | 0 | DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC); |
4901 | 0 | bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC || |
4902 | 0 | getLangOpts().MicrosoftExt) && |
4903 | 0 | (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes || |
4904 | 0 | CanBeOpaqueEnumDeclaration); |
4905 | |
|
4906 | 0 | CXXScopeSpec &SS = DS.getTypeSpecScope(); |
4907 | 0 | if (getLangOpts().CPlusPlus) { |
4908 | | // "enum foo : bar;" is not a potential typo for "enum foo::bar;". |
4909 | 0 | ColonProtectionRAIIObject X(*this); |
4910 | |
|
4911 | 0 | CXXScopeSpec Spec; |
4912 | 0 | if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr, |
4913 | 0 | /*ObjectHasErrors=*/false, |
4914 | 0 | /*EnteringContext=*/true)) |
4915 | 0 | return; |
4916 | | |
4917 | 0 | if (Spec.isSet() && Tok.isNot(tok::identifier)) { |
4918 | 0 | Diag(Tok, diag::err_expected) << tok::identifier; |
4919 | 0 | DS.SetTypeSpecError(); |
4920 | 0 | if (Tok.isNot(tok::l_brace)) { |
4921 | | // Has no name and is not a definition. |
4922 | | // Skip the rest of this declarator, up until the comma or semicolon. |
4923 | 0 | SkipUntil(tok::comma, StopAtSemi); |
4924 | 0 | return; |
4925 | 0 | } |
4926 | 0 | } |
4927 | | |
4928 | 0 | SS = Spec; |
4929 | 0 | } |
4930 | | |
4931 | | // Must have either 'enum name' or 'enum {...}' or (rarely) 'enum : T { ... }'. |
4932 | 0 | if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) && |
4933 | 0 | Tok.isNot(tok::colon)) { |
4934 | 0 | Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; |
4935 | |
|
4936 | 0 | DS.SetTypeSpecError(); |
4937 | | // Skip the rest of this declarator, up until the comma or semicolon. |
4938 | 0 | SkipUntil(tok::comma, StopAtSemi); |
4939 | 0 | return; |
4940 | 0 | } |
4941 | | |
4942 | | // If an identifier is present, consume and remember it. |
4943 | 0 | IdentifierInfo *Name = nullptr; |
4944 | 0 | SourceLocation NameLoc; |
4945 | 0 | if (Tok.is(tok::identifier)) { |
4946 | 0 | Name = Tok.getIdentifierInfo(); |
4947 | 0 | NameLoc = ConsumeToken(); |
4948 | 0 | } |
4949 | |
|
4950 | 0 | if (!Name && ScopedEnumKWLoc.isValid()) { |
4951 | | // C++0x 7.2p2: The optional identifier shall not be omitted in the |
4952 | | // declaration of a scoped enumeration. |
4953 | 0 | Diag(Tok, diag::err_scoped_enum_missing_identifier); |
4954 | 0 | ScopedEnumKWLoc = SourceLocation(); |
4955 | 0 | IsScopedUsingClassTag = false; |
4956 | 0 | } |
4957 | | |
4958 | | // Okay, end the suppression area. We'll decide whether to emit the |
4959 | | // diagnostics in a second. |
4960 | 0 | if (shouldDelayDiagsInTag) |
4961 | 0 | diagsFromTag.done(); |
4962 | |
|
4963 | 0 | TypeResult BaseType; |
4964 | 0 | SourceRange BaseRange; |
4965 | |
|
4966 | 0 | bool CanBeBitfield = |
4967 | 0 | getCurScope()->isClassScope() && ScopedEnumKWLoc.isInvalid() && Name; |
4968 | | |
4969 | | // Parse the fixed underlying type. |
4970 | 0 | if (Tok.is(tok::colon)) { |
4971 | | // This might be an enum-base or part of some unrelated enclosing context. |
4972 | | // |
4973 | | // 'enum E : base' is permitted in two circumstances: |
4974 | | // |
4975 | | // 1) As a defining-type-specifier, when followed by '{'. |
4976 | | // 2) As the sole constituent of a complete declaration -- when DS is empty |
4977 | | // and the next token is ';'. |
4978 | | // |
4979 | | // The restriction to defining-type-specifiers is important to allow parsing |
4980 | | // a ? new enum E : int{} |
4981 | | // _Generic(a, enum E : int{}) |
4982 | | // properly. |
4983 | | // |
4984 | | // One additional consideration applies: |
4985 | | // |
4986 | | // C++ [dcl.enum]p1: |
4987 | | // A ':' following "enum nested-name-specifier[opt] identifier" within |
4988 | | // the decl-specifier-seq of a member-declaration is parsed as part of |
4989 | | // an enum-base. |
4990 | | // |
4991 | | // Other language modes supporting enumerations with fixed underlying types |
4992 | | // do not have clear rules on this, so we disambiguate to determine whether |
4993 | | // the tokens form a bit-field width or an enum-base. |
4994 | |
|
4995 | 0 | if (CanBeBitfield && !isEnumBase(CanBeOpaqueEnumDeclaration)) { |
4996 | | // Outside C++11, do not interpret the tokens as an enum-base if they do |
4997 | | // not make sense as one. In C++11, it's an error if this happens. |
4998 | 0 | if (getLangOpts().CPlusPlus11) |
4999 | 0 | Diag(Tok.getLocation(), diag::err_anonymous_enum_bitfield); |
5000 | 0 | } else if (CanHaveEnumBase || !ColonIsSacred) { |
5001 | 0 | SourceLocation ColonLoc = ConsumeToken(); |
5002 | | |
5003 | | // Parse a type-specifier-seq as a type. We can't just ParseTypeName here, |
5004 | | // because under -fms-extensions, |
5005 | | // enum E : int *p; |
5006 | | // declares 'enum E : int; E *p;' not 'enum E : int*; E p;'. |
5007 | 0 | DeclSpec DS(AttrFactory); |
5008 | | // enum-base is not assumed to be a type and therefore requires the |
5009 | | // typename keyword [p0634r3]. |
5010 | 0 | ParseSpecifierQualifierList(DS, ImplicitTypenameContext::No, AS, |
5011 | 0 | DeclSpecContext::DSC_type_specifier); |
5012 | 0 | Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), |
5013 | 0 | DeclaratorContext::TypeName); |
5014 | 0 | BaseType = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); |
5015 | |
|
5016 | 0 | BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd()); |
5017 | |
|
5018 | 0 | if (!getLangOpts().ObjC && !getLangOpts().C23) { |
5019 | 0 | if (getLangOpts().CPlusPlus11) |
5020 | 0 | Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type) |
5021 | 0 | << BaseRange; |
5022 | 0 | else if (getLangOpts().CPlusPlus) |
5023 | 0 | Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type) |
5024 | 0 | << BaseRange; |
5025 | 0 | else if (getLangOpts().MicrosoftExt) |
5026 | 0 | Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type) |
5027 | 0 | << BaseRange; |
5028 | 0 | else |
5029 | 0 | Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type) |
5030 | 0 | << BaseRange; |
5031 | 0 | } |
5032 | 0 | } |
5033 | 0 | } |
5034 | | |
5035 | | // There are four options here. If we have 'friend enum foo;' then this is a |
5036 | | // friend declaration, and cannot have an accompanying definition. If we have |
5037 | | // 'enum foo;', then this is a forward declaration. If we have |
5038 | | // 'enum foo {...' then this is a definition. Otherwise we have something |
5039 | | // like 'enum foo xyz', a reference. |
5040 | | // |
5041 | | // This is needed to handle stuff like this right (C99 6.7.2.3p11): |
5042 | | // enum foo {..}; void bar() { enum foo; } <- new foo in bar. |
5043 | | // enum foo {..}; void bar() { enum foo x; } <- use of old foo. |
5044 | | // |
5045 | 0 | Sema::TagUseKind TUK; |
5046 | 0 | if (AllowEnumSpecifier == AllowDefiningTypeSpec::No) |
5047 | 0 | TUK = Sema::TUK_Reference; |
5048 | 0 | else if (Tok.is(tok::l_brace)) { |
5049 | 0 | if (DS.isFriendSpecified()) { |
5050 | 0 | Diag(Tok.getLocation(), diag::err_friend_decl_defines_type) |
5051 | 0 | << SourceRange(DS.getFriendSpecLoc()); |
5052 | 0 | ConsumeBrace(); |
5053 | 0 | SkipUntil(tok::r_brace, StopAtSemi); |
5054 | | // Discard any other definition-only pieces. |
5055 | 0 | attrs.clear(); |
5056 | 0 | ScopedEnumKWLoc = SourceLocation(); |
5057 | 0 | IsScopedUsingClassTag = false; |
5058 | 0 | BaseType = TypeResult(); |
5059 | 0 | TUK = Sema::TUK_Friend; |
5060 | 0 | } else { |
5061 | 0 | TUK = Sema::TUK_Definition; |
5062 | 0 | } |
5063 | 0 | } else if (!isTypeSpecifier(DSC) && |
5064 | 0 | (Tok.is(tok::semi) || |
5065 | 0 | (Tok.isAtStartOfLine() && |
5066 | 0 | !isValidAfterTypeSpecifier(CanBeBitfield)))) { |
5067 | | // An opaque-enum-declaration is required to be standalone (no preceding or |
5068 | | // following tokens in the declaration). Sema enforces this separately by |
5069 | | // diagnosing anything else in the DeclSpec. |
5070 | 0 | TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; |
5071 | 0 | if (Tok.isNot(tok::semi)) { |
5072 | | // A semicolon was missing after this declaration. Diagnose and recover. |
5073 | 0 | ExpectAndConsume(tok::semi, diag::err_expected_after, "enum"); |
5074 | 0 | PP.EnterToken(Tok, /*IsReinject=*/true); |
5075 | 0 | Tok.setKind(tok::semi); |
5076 | 0 | } |
5077 | 0 | } else { |
5078 | 0 | TUK = Sema::TUK_Reference; |
5079 | 0 | } |
5080 | |
|
5081 | 0 | bool IsElaboratedTypeSpecifier = |
5082 | 0 | TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend; |
5083 | | |
5084 | | // If this is an elaborated type specifier nested in a larger declaration, |
5085 | | // and we delayed diagnostics before, just merge them into the current pool. |
5086 | 0 | if (TUK == Sema::TUK_Reference && shouldDelayDiagsInTag) { |
5087 | 0 | diagsFromTag.redelay(); |
5088 | 0 | } |
5089 | |
|
5090 | 0 | MultiTemplateParamsArg TParams; |
5091 | 0 | if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && |
5092 | 0 | TUK != Sema::TUK_Reference) { |
5093 | 0 | if (!getLangOpts().CPlusPlus11 || !SS.isSet()) { |
5094 | | // Skip the rest of this declarator, up until the comma or semicolon. |
5095 | 0 | Diag(Tok, diag::err_enum_template); |
5096 | 0 | SkipUntil(tok::comma, StopAtSemi); |
5097 | 0 | return; |
5098 | 0 | } |
5099 | | |
5100 | 0 | if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { |
5101 | | // Enumerations can't be explicitly instantiated. |
5102 | 0 | DS.SetTypeSpecError(); |
5103 | 0 | Diag(StartLoc, diag::err_explicit_instantiation_enum); |
5104 | 0 | return; |
5105 | 0 | } |
5106 | | |
5107 | 0 | assert(TemplateInfo.TemplateParams && "no template parameters"); |
5108 | 0 | TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(), |
5109 | 0 | TemplateInfo.TemplateParams->size()); |
5110 | 0 | SS.setTemplateParamLists(TParams); |
5111 | 0 | } |
5112 | | |
5113 | 0 | if (!Name && TUK != Sema::TUK_Definition) { |
5114 | 0 | Diag(Tok, diag::err_enumerator_unnamed_no_def); |
5115 | |
|
5116 | 0 | DS.SetTypeSpecError(); |
5117 | | // Skip the rest of this declarator, up until the comma or semicolon. |
5118 | 0 | SkipUntil(tok::comma, StopAtSemi); |
5119 | 0 | return; |
5120 | 0 | } |
5121 | | |
5122 | | // An elaborated-type-specifier has a much more constrained grammar: |
5123 | | // |
5124 | | // 'enum' nested-name-specifier[opt] identifier |
5125 | | // |
5126 | | // If we parsed any other bits, reject them now. |
5127 | | // |
5128 | | // MSVC and (for now at least) Objective-C permit a full enum-specifier |
5129 | | // or opaque-enum-declaration anywhere. |
5130 | 0 | if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt && |
5131 | 0 | !getLangOpts().ObjC) { |
5132 | 0 | ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, |
5133 | 0 | diag::err_keyword_not_allowed, |
5134 | 0 | /*DiagnoseEmptyAttrs=*/true); |
5135 | 0 | if (BaseType.isUsable()) |
5136 | 0 | Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier) |
5137 | 0 | << (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange; |
5138 | 0 | else if (ScopedEnumKWLoc.isValid()) |
5139 | 0 | Diag(ScopedEnumKWLoc, diag::ext_elaborated_enum_class) |
5140 | 0 | << FixItHint::CreateRemoval(ScopedEnumKWLoc) << IsScopedUsingClassTag; |
5141 | 0 | } |
5142 | |
|
5143 | 0 | stripTypeAttributesOffDeclSpec(attrs, DS, TUK); |
5144 | |
|
5145 | 0 | Sema::SkipBodyInfo SkipBody; |
5146 | 0 | if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) && |
5147 | 0 | NextToken().is(tok::identifier)) |
5148 | 0 | SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(), |
5149 | 0 | NextToken().getIdentifierInfo(), |
5150 | 0 | NextToken().getLocation()); |
5151 | |
|
5152 | 0 | bool Owned = false; |
5153 | 0 | bool IsDependent = false; |
5154 | 0 | const char *PrevSpec = nullptr; |
5155 | 0 | unsigned DiagID; |
5156 | 0 | Decl *TagDecl = |
5157 | 0 | Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, |
5158 | 0 | Name, NameLoc, attrs, AS, DS.getModulePrivateSpecLoc(), |
5159 | 0 | TParams, Owned, IsDependent, ScopedEnumKWLoc, |
5160 | 0 | IsScopedUsingClassTag, |
5161 | 0 | BaseType, DSC == DeclSpecContext::DSC_type_specifier, |
5162 | 0 | DSC == DeclSpecContext::DSC_template_param || |
5163 | 0 | DSC == DeclSpecContext::DSC_template_type_arg, |
5164 | 0 | OffsetOfState, &SkipBody).get(); |
5165 | |
|
5166 | 0 | if (SkipBody.ShouldSkip) { |
5167 | 0 | assert(TUK == Sema::TUK_Definition && "can only skip a definition"); |
5168 | | |
5169 | 0 | BalancedDelimiterTracker T(*this, tok::l_brace); |
5170 | 0 | T.consumeOpen(); |
5171 | 0 | T.skipToEnd(); |
5172 | |
|
5173 | 0 | if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, |
5174 | 0 | NameLoc.isValid() ? NameLoc : StartLoc, |
5175 | 0 | PrevSpec, DiagID, TagDecl, Owned, |
5176 | 0 | Actions.getASTContext().getPrintingPolicy())) |
5177 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
5178 | 0 | return; |
5179 | 0 | } |
5180 | | |
5181 | 0 | if (IsDependent) { |
5182 | | // This enum has a dependent nested-name-specifier. Handle it as a |
5183 | | // dependent tag. |
5184 | 0 | if (!Name) { |
5185 | 0 | DS.SetTypeSpecError(); |
5186 | 0 | Diag(Tok, diag::err_expected_type_name_after_typename); |
5187 | 0 | return; |
5188 | 0 | } |
5189 | | |
5190 | 0 | TypeResult Type = Actions.ActOnDependentTag( |
5191 | 0 | getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc); |
5192 | 0 | if (Type.isInvalid()) { |
5193 | 0 | DS.SetTypeSpecError(); |
5194 | 0 | return; |
5195 | 0 | } |
5196 | | |
5197 | 0 | if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, |
5198 | 0 | NameLoc.isValid() ? NameLoc : StartLoc, |
5199 | 0 | PrevSpec, DiagID, Type.get(), |
5200 | 0 | Actions.getASTContext().getPrintingPolicy())) |
5201 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
5202 | |
|
5203 | 0 | return; |
5204 | 0 | } |
5205 | | |
5206 | 0 | if (!TagDecl) { |
5207 | | // The action failed to produce an enumeration tag. If this is a |
5208 | | // definition, consume the entire definition. |
5209 | 0 | if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) { |
5210 | 0 | ConsumeBrace(); |
5211 | 0 | SkipUntil(tok::r_brace, StopAtSemi); |
5212 | 0 | } |
5213 | |
|
5214 | 0 | DS.SetTypeSpecError(); |
5215 | 0 | return; |
5216 | 0 | } |
5217 | | |
5218 | 0 | if (Tok.is(tok::l_brace) && TUK == Sema::TUK_Definition) { |
5219 | 0 | Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl; |
5220 | 0 | ParseEnumBody(StartLoc, D); |
5221 | 0 | if (SkipBody.CheckSameAsPrevious && |
5222 | 0 | !Actions.ActOnDuplicateDefinition(TagDecl, SkipBody)) { |
5223 | 0 | DS.SetTypeSpecError(); |
5224 | 0 | return; |
5225 | 0 | } |
5226 | 0 | } |
5227 | | |
5228 | 0 | if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, |
5229 | 0 | NameLoc.isValid() ? NameLoc : StartLoc, |
5230 | 0 | PrevSpec, DiagID, TagDecl, Owned, |
5231 | 0 | Actions.getASTContext().getPrintingPolicy())) |
5232 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
5233 | 0 | } |
5234 | | |
5235 | | /// ParseEnumBody - Parse a {} enclosed enumerator-list. |
5236 | | /// enumerator-list: |
5237 | | /// enumerator |
5238 | | /// enumerator-list ',' enumerator |
5239 | | /// enumerator: |
5240 | | /// enumeration-constant attributes[opt] |
5241 | | /// enumeration-constant attributes[opt] '=' constant-expression |
5242 | | /// enumeration-constant: |
5243 | | /// identifier |
5244 | | /// |
5245 | 0 | void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { |
5246 | | // Enter the scope of the enum body and start the definition. |
5247 | 0 | ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope); |
5248 | 0 | Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl); |
5249 | |
|
5250 | 0 | BalancedDelimiterTracker T(*this, tok::l_brace); |
5251 | 0 | T.consumeOpen(); |
5252 | | |
5253 | | // C does not allow an empty enumerator-list, C++ does [dcl.enum]. |
5254 | 0 | if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) |
5255 | 0 | Diag(Tok, diag::err_empty_enum); |
5256 | |
|
5257 | 0 | SmallVector<Decl *, 32> EnumConstantDecls; |
5258 | 0 | SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags; |
5259 | |
|
5260 | 0 | Decl *LastEnumConstDecl = nullptr; |
5261 | | |
5262 | | // Parse the enumerator-list. |
5263 | 0 | while (Tok.isNot(tok::r_brace)) { |
5264 | | // Parse enumerator. If failed, try skipping till the start of the next |
5265 | | // enumerator definition. |
5266 | 0 | if (Tok.isNot(tok::identifier)) { |
5267 | 0 | Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; |
5268 | 0 | if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) && |
5269 | 0 | TryConsumeToken(tok::comma)) |
5270 | 0 | continue; |
5271 | 0 | break; |
5272 | 0 | } |
5273 | 0 | IdentifierInfo *Ident = Tok.getIdentifierInfo(); |
5274 | 0 | SourceLocation IdentLoc = ConsumeToken(); |
5275 | | |
5276 | | // If attributes exist after the enumerator, parse them. |
5277 | 0 | ParsedAttributes attrs(AttrFactory); |
5278 | 0 | MaybeParseGNUAttributes(attrs); |
5279 | 0 | if (isAllowedCXX11AttributeSpecifier()) { |
5280 | 0 | if (getLangOpts().CPlusPlus) |
5281 | 0 | Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 |
5282 | 0 | ? diag::warn_cxx14_compat_ns_enum_attribute |
5283 | 0 | : diag::ext_ns_enum_attribute) |
5284 | 0 | << 1 /*enumerator*/; |
5285 | 0 | ParseCXX11Attributes(attrs); |
5286 | 0 | } |
5287 | |
|
5288 | 0 | SourceLocation EqualLoc; |
5289 | 0 | ExprResult AssignedVal; |
5290 | 0 | EnumAvailabilityDiags.emplace_back(*this); |
5291 | |
|
5292 | 0 | EnterExpressionEvaluationContext ConstantEvaluated( |
5293 | 0 | Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); |
5294 | 0 | if (TryConsumeToken(tok::equal, EqualLoc)) { |
5295 | 0 | AssignedVal = ParseConstantExpressionInExprEvalContext(); |
5296 | 0 | if (AssignedVal.isInvalid()) |
5297 | 0 | SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch); |
5298 | 0 | } |
5299 | | |
5300 | | // Install the enumerator constant into EnumDecl. |
5301 | 0 | Decl *EnumConstDecl = Actions.ActOnEnumConstant( |
5302 | 0 | getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs, |
5303 | 0 | EqualLoc, AssignedVal.get()); |
5304 | 0 | EnumAvailabilityDiags.back().done(); |
5305 | |
|
5306 | 0 | EnumConstantDecls.push_back(EnumConstDecl); |
5307 | 0 | LastEnumConstDecl = EnumConstDecl; |
5308 | |
|
5309 | 0 | if (Tok.is(tok::identifier)) { |
5310 | | // We're missing a comma between enumerators. |
5311 | 0 | SourceLocation Loc = getEndOfPreviousToken(); |
5312 | 0 | Diag(Loc, diag::err_enumerator_list_missing_comma) |
5313 | 0 | << FixItHint::CreateInsertion(Loc, ", "); |
5314 | 0 | continue; |
5315 | 0 | } |
5316 | | |
5317 | | // Emumerator definition must be finished, only comma or r_brace are |
5318 | | // allowed here. |
5319 | 0 | SourceLocation CommaLoc; |
5320 | 0 | if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) { |
5321 | 0 | if (EqualLoc.isValid()) |
5322 | 0 | Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace |
5323 | 0 | << tok::comma; |
5324 | 0 | else |
5325 | 0 | Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator); |
5326 | 0 | if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) { |
5327 | 0 | if (TryConsumeToken(tok::comma, CommaLoc)) |
5328 | 0 | continue; |
5329 | 0 | } else { |
5330 | 0 | break; |
5331 | 0 | } |
5332 | 0 | } |
5333 | | |
5334 | | // If comma is followed by r_brace, emit appropriate warning. |
5335 | 0 | if (Tok.is(tok::r_brace) && CommaLoc.isValid()) { |
5336 | 0 | if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) |
5337 | 0 | Diag(CommaLoc, getLangOpts().CPlusPlus ? |
5338 | 0 | diag::ext_enumerator_list_comma_cxx : |
5339 | 0 | diag::ext_enumerator_list_comma_c) |
5340 | 0 | << FixItHint::CreateRemoval(CommaLoc); |
5341 | 0 | else if (getLangOpts().CPlusPlus11) |
5342 | 0 | Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma) |
5343 | 0 | << FixItHint::CreateRemoval(CommaLoc); |
5344 | 0 | break; |
5345 | 0 | } |
5346 | 0 | } |
5347 | | |
5348 | | // Eat the }. |
5349 | 0 | T.consumeClose(); |
5350 | | |
5351 | | // If attributes exist after the identifier list, parse them. |
5352 | 0 | ParsedAttributes attrs(AttrFactory); |
5353 | 0 | MaybeParseGNUAttributes(attrs); |
5354 | |
|
5355 | 0 | Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls, |
5356 | 0 | getCurScope(), attrs); |
5357 | | |
5358 | | // Now handle enum constant availability diagnostics. |
5359 | 0 | assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); |
5360 | 0 | for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) { |
5361 | 0 | ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); |
5362 | 0 | EnumAvailabilityDiags[i].redelay(); |
5363 | 0 | PD.complete(EnumConstantDecls[i]); |
5364 | 0 | } |
5365 | |
|
5366 | 0 | EnumScope.Exit(); |
5367 | 0 | Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getRange()); |
5368 | | |
5369 | | // The next token must be valid after an enum definition. If not, a ';' |
5370 | | // was probably forgotten. |
5371 | 0 | bool CanBeBitfield = getCurScope()->isClassScope(); |
5372 | 0 | if (!isValidAfterTypeSpecifier(CanBeBitfield)) { |
5373 | 0 | ExpectAndConsume(tok::semi, diag::err_expected_after, "enum"); |
5374 | | // Push this token back into the preprocessor and change our current token |
5375 | | // to ';' so that the rest of the code recovers as though there were an |
5376 | | // ';' after the definition. |
5377 | 0 | PP.EnterToken(Tok, /*IsReinject=*/true); |
5378 | 0 | Tok.setKind(tok::semi); |
5379 | 0 | } |
5380 | 0 | } |
5381 | | |
5382 | | /// isKnownToBeTypeSpecifier - Return true if we know that the specified token |
5383 | | /// is definitely a type-specifier. Return false if it isn't part of a type |
5384 | | /// specifier or if we're not sure. |
5385 | 0 | bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { |
5386 | 0 | switch (Tok.getKind()) { |
5387 | 0 | default: return false; |
5388 | | // type-specifiers |
5389 | 0 | case tok::kw_short: |
5390 | 0 | case tok::kw_long: |
5391 | 0 | case tok::kw___int64: |
5392 | 0 | case tok::kw___int128: |
5393 | 0 | case tok::kw_signed: |
5394 | 0 | case tok::kw_unsigned: |
5395 | 0 | case tok::kw__Complex: |
5396 | 0 | case tok::kw__Imaginary: |
5397 | 0 | case tok::kw_void: |
5398 | 0 | case tok::kw_char: |
5399 | 0 | case tok::kw_wchar_t: |
5400 | 0 | case tok::kw_char8_t: |
5401 | 0 | case tok::kw_char16_t: |
5402 | 0 | case tok::kw_char32_t: |
5403 | 0 | case tok::kw_int: |
5404 | 0 | case tok::kw__ExtInt: |
5405 | 0 | case tok::kw__BitInt: |
5406 | 0 | case tok::kw___bf16: |
5407 | 0 | case tok::kw_half: |
5408 | 0 | case tok::kw_float: |
5409 | 0 | case tok::kw_double: |
5410 | 0 | case tok::kw__Accum: |
5411 | 0 | case tok::kw__Fract: |
5412 | 0 | case tok::kw__Float16: |
5413 | 0 | case tok::kw___float128: |
5414 | 0 | case tok::kw___ibm128: |
5415 | 0 | case tok::kw_bool: |
5416 | 0 | case tok::kw__Bool: |
5417 | 0 | case tok::kw__Decimal32: |
5418 | 0 | case tok::kw__Decimal64: |
5419 | 0 | case tok::kw__Decimal128: |
5420 | 0 | case tok::kw___vector: |
5421 | 0 | #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: |
5422 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
5423 | | |
5424 | | // struct-or-union-specifier (C99) or class-specifier (C++) |
5425 | 0 | case tok::kw_class: |
5426 | 0 | case tok::kw_struct: |
5427 | 0 | case tok::kw___interface: |
5428 | 0 | case tok::kw_union: |
5429 | | // enum-specifier |
5430 | 0 | case tok::kw_enum: |
5431 | | |
5432 | | // typedef-name |
5433 | 0 | case tok::annot_typename: |
5434 | 0 | return true; |
5435 | 0 | } |
5436 | 0 | } |
5437 | | |
5438 | | /// isTypeSpecifierQualifier - Return true if the current token could be the |
5439 | | /// start of a specifier-qualifier-list. |
5440 | 6 | bool Parser::isTypeSpecifierQualifier() { |
5441 | 6 | switch (Tok.getKind()) { |
5442 | 2 | default: return false; |
5443 | | |
5444 | 4 | case tok::identifier: // foo::bar |
5445 | 4 | if (TryAltiVecVectorToken()) |
5446 | 0 | return true; |
5447 | 4 | [[fallthrough]]; |
5448 | 4 | case tok::kw_typename: // typename T::type |
5449 | | // Annotate typenames and C++ scope specifiers. If we get one, just |
5450 | | // recurse to handle whatever we get. |
5451 | 4 | if (TryAnnotateTypeOrScopeToken()) |
5452 | 0 | return true; |
5453 | 4 | if (Tok.is(tok::identifier)) |
5454 | 4 | return false; |
5455 | 0 | return isTypeSpecifierQualifier(); |
5456 | | |
5457 | 0 | case tok::coloncolon: // ::foo::bar |
5458 | 0 | if (NextToken().is(tok::kw_new) || // ::new |
5459 | 0 | NextToken().is(tok::kw_delete)) // ::delete |
5460 | 0 | return false; |
5461 | | |
5462 | 0 | if (TryAnnotateTypeOrScopeToken()) |
5463 | 0 | return true; |
5464 | 0 | return isTypeSpecifierQualifier(); |
5465 | | |
5466 | | // GNU attributes support. |
5467 | 0 | case tok::kw___attribute: |
5468 | | // C23/GNU typeof support. |
5469 | 0 | case tok::kw_typeof: |
5470 | 0 | case tok::kw_typeof_unqual: |
5471 | | |
5472 | | // type-specifiers |
5473 | 0 | case tok::kw_short: |
5474 | 0 | case tok::kw_long: |
5475 | 0 | case tok::kw___int64: |
5476 | 0 | case tok::kw___int128: |
5477 | 0 | case tok::kw_signed: |
5478 | 0 | case tok::kw_unsigned: |
5479 | 0 | case tok::kw__Complex: |
5480 | 0 | case tok::kw__Imaginary: |
5481 | 0 | case tok::kw_void: |
5482 | 0 | case tok::kw_char: |
5483 | 0 | case tok::kw_wchar_t: |
5484 | 0 | case tok::kw_char8_t: |
5485 | 0 | case tok::kw_char16_t: |
5486 | 0 | case tok::kw_char32_t: |
5487 | 0 | case tok::kw_int: |
5488 | 0 | case tok::kw__ExtInt: |
5489 | 0 | case tok::kw__BitInt: |
5490 | 0 | case tok::kw_half: |
5491 | 0 | case tok::kw___bf16: |
5492 | 0 | case tok::kw_float: |
5493 | 0 | case tok::kw_double: |
5494 | 0 | case tok::kw__Accum: |
5495 | 0 | case tok::kw__Fract: |
5496 | 0 | case tok::kw__Float16: |
5497 | 0 | case tok::kw___float128: |
5498 | 0 | case tok::kw___ibm128: |
5499 | 0 | case tok::kw_bool: |
5500 | 0 | case tok::kw__Bool: |
5501 | 0 | case tok::kw__Decimal32: |
5502 | 0 | case tok::kw__Decimal64: |
5503 | 0 | case tok::kw__Decimal128: |
5504 | 0 | case tok::kw___vector: |
5505 | 0 | #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: |
5506 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
5507 | | |
5508 | | // struct-or-union-specifier (C99) or class-specifier (C++) |
5509 | 0 | case tok::kw_class: |
5510 | 0 | case tok::kw_struct: |
5511 | 0 | case tok::kw___interface: |
5512 | 0 | case tok::kw_union: |
5513 | | // enum-specifier |
5514 | 0 | case tok::kw_enum: |
5515 | | |
5516 | | // type-qualifier |
5517 | 0 | case tok::kw_const: |
5518 | 0 | case tok::kw_volatile: |
5519 | 0 | case tok::kw_restrict: |
5520 | 0 | case tok::kw__Sat: |
5521 | | |
5522 | | // Debugger support. |
5523 | 0 | case tok::kw___unknown_anytype: |
5524 | | |
5525 | | // typedef-name |
5526 | 0 | case tok::annot_typename: |
5527 | 0 | return true; |
5528 | | |
5529 | | // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. |
5530 | 0 | case tok::less: |
5531 | 0 | return getLangOpts().ObjC; |
5532 | | |
5533 | 0 | case tok::kw___cdecl: |
5534 | 0 | case tok::kw___stdcall: |
5535 | 0 | case tok::kw___fastcall: |
5536 | 0 | case tok::kw___thiscall: |
5537 | 0 | case tok::kw___regcall: |
5538 | 0 | case tok::kw___vectorcall: |
5539 | 0 | case tok::kw___w64: |
5540 | 0 | case tok::kw___ptr64: |
5541 | 0 | case tok::kw___ptr32: |
5542 | 0 | case tok::kw___pascal: |
5543 | 0 | case tok::kw___unaligned: |
5544 | |
|
5545 | 0 | case tok::kw__Nonnull: |
5546 | 0 | case tok::kw__Nullable: |
5547 | 0 | case tok::kw__Nullable_result: |
5548 | 0 | case tok::kw__Null_unspecified: |
5549 | |
|
5550 | 0 | case tok::kw___kindof: |
5551 | |
|
5552 | 0 | case tok::kw___private: |
5553 | 0 | case tok::kw___local: |
5554 | 0 | case tok::kw___global: |
5555 | 0 | case tok::kw___constant: |
5556 | 0 | case tok::kw___generic: |
5557 | 0 | case tok::kw___read_only: |
5558 | 0 | case tok::kw___read_write: |
5559 | 0 | case tok::kw___write_only: |
5560 | 0 | case tok::kw___funcref: |
5561 | 0 | return true; |
5562 | | |
5563 | 0 | case tok::kw_private: |
5564 | 0 | return getLangOpts().OpenCL; |
5565 | | |
5566 | | // C11 _Atomic |
5567 | 0 | case tok::kw__Atomic: |
5568 | 0 | return true; |
5569 | | |
5570 | | // HLSL type qualifiers |
5571 | 0 | case tok::kw_groupshared: |
5572 | 0 | case tok::kw_in: |
5573 | 0 | case tok::kw_inout: |
5574 | 0 | case tok::kw_out: |
5575 | 0 | return getLangOpts().HLSL; |
5576 | 6 | } |
5577 | 6 | } |
5578 | | |
5579 | 0 | Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() { |
5580 | 0 | assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode"); |
5581 | | |
5582 | | // Parse a top-level-stmt. |
5583 | 0 | Parser::StmtVector Stmts; |
5584 | 0 | ParsedStmtContext SubStmtCtx = ParsedStmtContext(); |
5585 | 0 | Actions.PushFunctionScope(); |
5586 | 0 | StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); |
5587 | 0 | Actions.PopFunctionScopeInfo(); |
5588 | 0 | if (!R.isUsable()) |
5589 | 0 | return nullptr; |
5590 | | |
5591 | 0 | SmallVector<Decl *, 2> DeclsInGroup; |
5592 | 0 | DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get())); |
5593 | |
|
5594 | 0 | if (Tok.is(tok::annot_repl_input_end) && |
5595 | 0 | Tok.getAnnotationValue() != nullptr) { |
5596 | 0 | ConsumeAnnotationToken(); |
5597 | 0 | cast<TopLevelStmtDecl>(DeclsInGroup.back())->setSemiMissing(); |
5598 | 0 | } |
5599 | | |
5600 | | // Currently happens for things like -fms-extensions and use `__if_exists`. |
5601 | 0 | for (Stmt *S : Stmts) |
5602 | 0 | DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S)); |
5603 | |
|
5604 | 0 | return Actions.BuildDeclaratorGroup(DeclsInGroup); |
5605 | 0 | } |
5606 | | |
5607 | | /// isDeclarationSpecifier() - Return true if the current token is part of a |
5608 | | /// declaration specifier. |
5609 | | /// |
5610 | | /// \param AllowImplicitTypename whether this is a context where T::type [T |
5611 | | /// dependent] can appear. |
5612 | | /// \param DisambiguatingWithExpression True to indicate that the purpose of |
5613 | | /// this check is to disambiguate between an expression and a declaration. |
5614 | | bool Parser::isDeclarationSpecifier( |
5615 | | ImplicitTypenameContext AllowImplicitTypename, |
5616 | 4.63k | bool DisambiguatingWithExpression) { |
5617 | 4.63k | switch (Tok.getKind()) { |
5618 | 2.77k | default: return false; |
5619 | | |
5620 | | // OpenCL 2.0 and later define this keyword. |
5621 | 0 | case tok::kw_pipe: |
5622 | 0 | return getLangOpts().OpenCL && |
5623 | 0 | getLangOpts().getOpenCLCompatibleVersion() >= 200; |
5624 | | |
5625 | 1.80k | case tok::identifier: // foo::bar |
5626 | | // Unfortunate hack to support "Class.factoryMethod" notation. |
5627 | 1.80k | if (getLangOpts().ObjC && NextToken().is(tok::period)) |
5628 | 8 | return false; |
5629 | 1.79k | if (TryAltiVecVectorToken()) |
5630 | 0 | return true; |
5631 | 1.79k | [[fallthrough]]; |
5632 | 1.79k | case tok::kw_decltype: // decltype(T())::type |
5633 | 1.79k | case tok::kw_typename: // typename T::type |
5634 | | // Annotate typenames and C++ scope specifiers. If we get one, just |
5635 | | // recurse to handle whatever we get. |
5636 | 1.79k | if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename)) |
5637 | 0 | return true; |
5638 | 1.79k | if (TryAnnotateTypeConstraint()) |
5639 | 0 | return true; |
5640 | 1.79k | if (Tok.is(tok::identifier)) |
5641 | 1.79k | return false; |
5642 | | |
5643 | | // If we're in Objective-C and we have an Objective-C class type followed |
5644 | | // by an identifier and then either ':' or ']', in a place where an |
5645 | | // expression is permitted, then this is probably a class message send |
5646 | | // missing the initial '['. In this case, we won't consider this to be |
5647 | | // the start of a declaration. |
5648 | 2 | if (DisambiguatingWithExpression && |
5649 | 2 | isStartOfObjCClassMessageMissingOpenBracket()) |
5650 | 0 | return false; |
5651 | | |
5652 | 2 | return isDeclarationSpecifier(AllowImplicitTypename); |
5653 | | |
5654 | 0 | case tok::coloncolon: // ::foo::bar |
5655 | 0 | if (!getLangOpts().CPlusPlus) |
5656 | 0 | return false; |
5657 | 0 | if (NextToken().is(tok::kw_new) || // ::new |
5658 | 0 | NextToken().is(tok::kw_delete)) // ::delete |
5659 | 0 | return false; |
5660 | | |
5661 | | // Annotate typenames and C++ scope specifiers. If we get one, just |
5662 | | // recurse to handle whatever we get. |
5663 | 0 | if (TryAnnotateTypeOrScopeToken()) |
5664 | 0 | return true; |
5665 | 0 | return isDeclarationSpecifier(ImplicitTypenameContext::No); |
5666 | | |
5667 | | // storage-class-specifier |
5668 | 0 | case tok::kw_typedef: |
5669 | 0 | case tok::kw_extern: |
5670 | 0 | case tok::kw___private_extern__: |
5671 | 0 | case tok::kw_static: |
5672 | 0 | case tok::kw_auto: |
5673 | 0 | case tok::kw___auto_type: |
5674 | 0 | case tok::kw_register: |
5675 | 0 | case tok::kw___thread: |
5676 | 0 | case tok::kw_thread_local: |
5677 | 0 | case tok::kw__Thread_local: |
5678 | | |
5679 | | // Modules |
5680 | 0 | case tok::kw___module_private__: |
5681 | | |
5682 | | // Debugger support |
5683 | 0 | case tok::kw___unknown_anytype: |
5684 | | |
5685 | | // type-specifiers |
5686 | 0 | case tok::kw_short: |
5687 | 0 | case tok::kw_long: |
5688 | 0 | case tok::kw___int64: |
5689 | 0 | case tok::kw___int128: |
5690 | 0 | case tok::kw_signed: |
5691 | 0 | case tok::kw_unsigned: |
5692 | 0 | case tok::kw__Complex: |
5693 | 0 | case tok::kw__Imaginary: |
5694 | 0 | case tok::kw_void: |
5695 | 0 | case tok::kw_char: |
5696 | 0 | case tok::kw_wchar_t: |
5697 | 0 | case tok::kw_char8_t: |
5698 | 0 | case tok::kw_char16_t: |
5699 | 0 | case tok::kw_char32_t: |
5700 | |
|
5701 | 0 | case tok::kw_int: |
5702 | 0 | case tok::kw__ExtInt: |
5703 | 0 | case tok::kw__BitInt: |
5704 | 0 | case tok::kw_half: |
5705 | 0 | case tok::kw___bf16: |
5706 | 0 | case tok::kw_float: |
5707 | 0 | case tok::kw_double: |
5708 | 0 | case tok::kw__Accum: |
5709 | 0 | case tok::kw__Fract: |
5710 | 0 | case tok::kw__Float16: |
5711 | 0 | case tok::kw___float128: |
5712 | 0 | case tok::kw___ibm128: |
5713 | 0 | case tok::kw_bool: |
5714 | 0 | case tok::kw__Bool: |
5715 | 0 | case tok::kw__Decimal32: |
5716 | 0 | case tok::kw__Decimal64: |
5717 | 0 | case tok::kw__Decimal128: |
5718 | 0 | case tok::kw___vector: |
5719 | | |
5720 | | // struct-or-union-specifier (C99) or class-specifier (C++) |
5721 | 0 | case tok::kw_class: |
5722 | 0 | case tok::kw_struct: |
5723 | 0 | case tok::kw_union: |
5724 | 0 | case tok::kw___interface: |
5725 | | // enum-specifier |
5726 | 0 | case tok::kw_enum: |
5727 | | |
5728 | | // type-qualifier |
5729 | 0 | case tok::kw_const: |
5730 | 0 | case tok::kw_volatile: |
5731 | 0 | case tok::kw_restrict: |
5732 | 0 | case tok::kw__Sat: |
5733 | | |
5734 | | // function-specifier |
5735 | 0 | case tok::kw_inline: |
5736 | 0 | case tok::kw_virtual: |
5737 | 0 | case tok::kw_explicit: |
5738 | 0 | case tok::kw__Noreturn: |
5739 | | |
5740 | | // alignment-specifier |
5741 | 0 | case tok::kw__Alignas: |
5742 | | |
5743 | | // friend keyword. |
5744 | 0 | case tok::kw_friend: |
5745 | | |
5746 | | // static_assert-declaration |
5747 | 0 | case tok::kw_static_assert: |
5748 | 0 | case tok::kw__Static_assert: |
5749 | | |
5750 | | // C23/GNU typeof support. |
5751 | 0 | case tok::kw_typeof: |
5752 | 0 | case tok::kw_typeof_unqual: |
5753 | | |
5754 | | // GNU attributes. |
5755 | 0 | case tok::kw___attribute: |
5756 | | |
5757 | | // C++11 decltype and constexpr. |
5758 | 0 | case tok::annot_decltype: |
5759 | 0 | case tok::kw_constexpr: |
5760 | | |
5761 | | // C++20 consteval and constinit. |
5762 | 0 | case tok::kw_consteval: |
5763 | 0 | case tok::kw_constinit: |
5764 | | |
5765 | | // C11 _Atomic |
5766 | 0 | case tok::kw__Atomic: |
5767 | 0 | return true; |
5768 | | |
5769 | | // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. |
5770 | 54 | case tok::less: |
5771 | 54 | return getLangOpts().ObjC; |
5772 | | |
5773 | | // typedef-name |
5774 | 0 | case tok::annot_typename: |
5775 | 0 | return !DisambiguatingWithExpression || |
5776 | 0 | !isStartOfObjCClassMessageMissingOpenBracket(); |
5777 | | |
5778 | | // placeholder-type-specifier |
5779 | 2 | case tok::annot_template_id: { |
5780 | 2 | TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); |
5781 | 2 | if (TemplateId->hasInvalidName()) |
5782 | 0 | return true; |
5783 | | // FIXME: What about type templates that have only been annotated as |
5784 | | // annot_template_id, not as annot_typename? |
5785 | 2 | return isTypeConstraintAnnotation() && |
5786 | 2 | (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype)); |
5787 | 2 | } |
5788 | | |
5789 | 0 | case tok::annot_cxxscope: { |
5790 | 0 | TemplateIdAnnotation *TemplateId = |
5791 | 0 | NextToken().is(tok::annot_template_id) |
5792 | 0 | ? takeTemplateIdAnnotation(NextToken()) |
5793 | 0 | : nullptr; |
5794 | 0 | if (TemplateId && TemplateId->hasInvalidName()) |
5795 | 0 | return true; |
5796 | | // FIXME: What about type templates that have only been annotated as |
5797 | | // annot_template_id, not as annot_typename? |
5798 | 0 | if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint()) |
5799 | 0 | return true; |
5800 | 0 | return isTypeConstraintAnnotation() && |
5801 | 0 | GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype); |
5802 | 0 | } |
5803 | | |
5804 | 0 | case tok::kw___declspec: |
5805 | 0 | case tok::kw___cdecl: |
5806 | 0 | case tok::kw___stdcall: |
5807 | 0 | case tok::kw___fastcall: |
5808 | 0 | case tok::kw___thiscall: |
5809 | 0 | case tok::kw___regcall: |
5810 | 0 | case tok::kw___vectorcall: |
5811 | 0 | case tok::kw___w64: |
5812 | 0 | case tok::kw___sptr: |
5813 | 0 | case tok::kw___uptr: |
5814 | 0 | case tok::kw___ptr64: |
5815 | 0 | case tok::kw___ptr32: |
5816 | 0 | case tok::kw___forceinline: |
5817 | 0 | case tok::kw___pascal: |
5818 | 0 | case tok::kw___unaligned: |
5819 | |
|
5820 | 0 | case tok::kw__Nonnull: |
5821 | 0 | case tok::kw__Nullable: |
5822 | 0 | case tok::kw__Nullable_result: |
5823 | 0 | case tok::kw__Null_unspecified: |
5824 | |
|
5825 | 0 | case tok::kw___kindof: |
5826 | |
|
5827 | 0 | case tok::kw___private: |
5828 | 0 | case tok::kw___local: |
5829 | 0 | case tok::kw___global: |
5830 | 0 | case tok::kw___constant: |
5831 | 0 | case tok::kw___generic: |
5832 | 0 | case tok::kw___read_only: |
5833 | 0 | case tok::kw___read_write: |
5834 | 0 | case tok::kw___write_only: |
5835 | 0 | #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: |
5836 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
5837 | |
|
5838 | 0 | case tok::kw___funcref: |
5839 | 0 | case tok::kw_groupshared: |
5840 | 0 | return true; |
5841 | | |
5842 | 0 | case tok::kw_private: |
5843 | 0 | return getLangOpts().OpenCL; |
5844 | 4.63k | } |
5845 | 4.63k | } |
5846 | | |
5847 | | bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, |
5848 | | DeclSpec::FriendSpecified IsFriend, |
5849 | 0 | const ParsedTemplateInfo *TemplateInfo) { |
5850 | 0 | RevertingTentativeParsingAction TPA(*this); |
5851 | | // Parse the C++ scope specifier. |
5852 | 0 | CXXScopeSpec SS; |
5853 | 0 | if (TemplateInfo && TemplateInfo->TemplateParams) |
5854 | 0 | SS.setTemplateParamLists(*TemplateInfo->TemplateParams); |
5855 | |
|
5856 | 0 | if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, |
5857 | 0 | /*ObjectHasErrors=*/false, |
5858 | 0 | /*EnteringContext=*/true)) { |
5859 | 0 | return false; |
5860 | 0 | } |
5861 | | |
5862 | | // Parse the constructor name. |
5863 | 0 | if (Tok.is(tok::identifier)) { |
5864 | | // We already know that we have a constructor name; just consume |
5865 | | // the token. |
5866 | 0 | ConsumeToken(); |
5867 | 0 | } else if (Tok.is(tok::annot_template_id)) { |
5868 | 0 | ConsumeAnnotationToken(); |
5869 | 0 | } else { |
5870 | 0 | return false; |
5871 | 0 | } |
5872 | | |
5873 | | // There may be attributes here, appertaining to the constructor name or type |
5874 | | // we just stepped past. |
5875 | 0 | SkipCXX11Attributes(); |
5876 | | |
5877 | | // Current class name must be followed by a left parenthesis. |
5878 | 0 | if (Tok.isNot(tok::l_paren)) { |
5879 | 0 | return false; |
5880 | 0 | } |
5881 | 0 | ConsumeParen(); |
5882 | | |
5883 | | // A right parenthesis, or ellipsis followed by a right parenthesis signals |
5884 | | // that we have a constructor. |
5885 | 0 | if (Tok.is(tok::r_paren) || |
5886 | 0 | (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) { |
5887 | 0 | return true; |
5888 | 0 | } |
5889 | | |
5890 | | // A C++11 attribute here signals that we have a constructor, and is an |
5891 | | // attribute on the first constructor parameter. |
5892 | 0 | if (getLangOpts().CPlusPlus11 && |
5893 | 0 | isCXX11AttributeSpecifier(/*Disambiguate*/ false, |
5894 | 0 | /*OuterMightBeMessageSend*/ true)) { |
5895 | 0 | return true; |
5896 | 0 | } |
5897 | | |
5898 | | // If we need to, enter the specified scope. |
5899 | 0 | DeclaratorScopeObj DeclScopeObj(*this, SS); |
5900 | 0 | if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS)) |
5901 | 0 | DeclScopeObj.EnterDeclaratorScope(); |
5902 | | |
5903 | | // Optionally skip Microsoft attributes. |
5904 | 0 | ParsedAttributes Attrs(AttrFactory); |
5905 | 0 | MaybeParseMicrosoftAttributes(Attrs); |
5906 | | |
5907 | | // Check whether the next token(s) are part of a declaration |
5908 | | // specifier, in which case we have the start of a parameter and, |
5909 | | // therefore, we know that this is a constructor. |
5910 | | // Due to an ambiguity with implicit typename, the above is not enough. |
5911 | | // Additionally, check to see if we are a friend. |
5912 | | // If we parsed a scope specifier as well as friend, |
5913 | | // we might be parsing a friend constructor. |
5914 | 0 | bool IsConstructor = false; |
5915 | 0 | ImplicitTypenameContext ITC = IsFriend && !SS.isSet() |
5916 | 0 | ? ImplicitTypenameContext::No |
5917 | 0 | : ImplicitTypenameContext::Yes; |
5918 | | // Constructors cannot have this parameters, but we support that scenario here |
5919 | | // to improve diagnostic. |
5920 | 0 | if (Tok.is(tok::kw_this)) { |
5921 | 0 | ConsumeToken(); |
5922 | 0 | return isDeclarationSpecifier(ITC); |
5923 | 0 | } |
5924 | | |
5925 | 0 | if (isDeclarationSpecifier(ITC)) |
5926 | 0 | IsConstructor = true; |
5927 | 0 | else if (Tok.is(tok::identifier) || |
5928 | 0 | (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) { |
5929 | | // We've seen "C ( X" or "C ( X::Y", but "X" / "X::Y" is not a type. |
5930 | | // This might be a parenthesized member name, but is more likely to |
5931 | | // be a constructor declaration with an invalid argument type. Keep |
5932 | | // looking. |
5933 | 0 | if (Tok.is(tok::annot_cxxscope)) |
5934 | 0 | ConsumeAnnotationToken(); |
5935 | 0 | ConsumeToken(); |
5936 | | |
5937 | | // If this is not a constructor, we must be parsing a declarator, |
5938 | | // which must have one of the following syntactic forms (see the |
5939 | | // grammar extract at the start of ParseDirectDeclarator): |
5940 | 0 | switch (Tok.getKind()) { |
5941 | 0 | case tok::l_paren: |
5942 | | // C(X ( int)); |
5943 | 0 | case tok::l_square: |
5944 | | // C(X [ 5]); |
5945 | | // C(X [ [attribute]]); |
5946 | 0 | case tok::coloncolon: |
5947 | | // C(X :: Y); |
5948 | | // C(X :: *p); |
5949 | | // Assume this isn't a constructor, rather than assuming it's a |
5950 | | // constructor with an unnamed parameter of an ill-formed type. |
5951 | 0 | break; |
5952 | | |
5953 | 0 | case tok::r_paren: |
5954 | | // C(X ) |
5955 | | |
5956 | | // Skip past the right-paren and any following attributes to get to |
5957 | | // the function body or trailing-return-type. |
5958 | 0 | ConsumeParen(); |
5959 | 0 | SkipCXX11Attributes(); |
5960 | |
|
5961 | 0 | if (DeductionGuide) { |
5962 | | // C(X) -> ... is a deduction guide. |
5963 | 0 | IsConstructor = Tok.is(tok::arrow); |
5964 | 0 | break; |
5965 | 0 | } |
5966 | 0 | if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) { |
5967 | | // Assume these were meant to be constructors: |
5968 | | // C(X) : (the name of a bit-field cannot be parenthesized). |
5969 | | // C(X) try (this is otherwise ill-formed). |
5970 | 0 | IsConstructor = true; |
5971 | 0 | } |
5972 | 0 | if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) { |
5973 | | // If we have a constructor name within the class definition, |
5974 | | // assume these were meant to be constructors: |
5975 | | // C(X) { |
5976 | | // C(X) ; |
5977 | | // ... because otherwise we would be declaring a non-static data |
5978 | | // member that is ill-formed because it's of the same type as its |
5979 | | // surrounding class. |
5980 | | // |
5981 | | // FIXME: We can actually do this whether or not the name is qualified, |
5982 | | // because if it is qualified in this context it must be being used as |
5983 | | // a constructor name. |
5984 | | // currently, so we're somewhat conservative here. |
5985 | 0 | IsConstructor = IsUnqualified; |
5986 | 0 | } |
5987 | 0 | break; |
5988 | | |
5989 | 0 | default: |
5990 | 0 | IsConstructor = true; |
5991 | 0 | break; |
5992 | 0 | } |
5993 | 0 | } |
5994 | 0 | return IsConstructor; |
5995 | 0 | } |
5996 | | |
5997 | | /// ParseTypeQualifierListOpt |
5998 | | /// type-qualifier-list: [C99 6.7.5] |
5999 | | /// type-qualifier |
6000 | | /// [vendor] attributes |
6001 | | /// [ only if AttrReqs & AR_VendorAttributesParsed ] |
6002 | | /// type-qualifier-list type-qualifier |
6003 | | /// [vendor] type-qualifier-list attributes |
6004 | | /// [ only if AttrReqs & AR_VendorAttributesParsed ] |
6005 | | /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq |
6006 | | /// [ only if AttReqs & AR_CXX11AttributesParsed ] |
6007 | | /// Note: vendor can be GNU, MS, etc and can be explicitly controlled via |
6008 | | /// AttrRequirements bitmask values. |
6009 | | void Parser::ParseTypeQualifierListOpt( |
6010 | | DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed, |
6011 | | bool IdentifierRequired, |
6012 | 1.13k | std::optional<llvm::function_ref<void()>> CodeCompletionHandler) { |
6013 | 1.13k | if ((AttrReqs & AR_CXX11AttributesParsed) && |
6014 | 1.13k | isAllowedCXX11AttributeSpecifier()) { |
6015 | 0 | ParsedAttributes Attrs(AttrFactory); |
6016 | 0 | ParseCXX11Attributes(Attrs); |
6017 | 0 | DS.takeAttributesFrom(Attrs); |
6018 | 0 | } |
6019 | | |
6020 | 1.13k | SourceLocation EndLoc; |
6021 | | |
6022 | 1.13k | while (true) { |
6023 | 1.13k | bool isInvalid = false; |
6024 | 1.13k | const char *PrevSpec = nullptr; |
6025 | 1.13k | unsigned DiagID = 0; |
6026 | 1.13k | SourceLocation Loc = Tok.getLocation(); |
6027 | | |
6028 | 1.13k | switch (Tok.getKind()) { |
6029 | 0 | case tok::code_completion: |
6030 | 0 | cutOffParsing(); |
6031 | 0 | if (CodeCompletionHandler) |
6032 | 0 | (*CodeCompletionHandler)(); |
6033 | 0 | else |
6034 | 0 | Actions.CodeCompleteTypeQualifiers(DS); |
6035 | 0 | return; |
6036 | | |
6037 | 0 | case tok::kw_const: |
6038 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID, |
6039 | 0 | getLangOpts()); |
6040 | 0 | break; |
6041 | 0 | case tok::kw_volatile: |
6042 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, |
6043 | 0 | getLangOpts()); |
6044 | 0 | break; |
6045 | 0 | case tok::kw_restrict: |
6046 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, |
6047 | 0 | getLangOpts()); |
6048 | 0 | break; |
6049 | 0 | case tok::kw__Atomic: |
6050 | 0 | if (!AtomicAllowed) |
6051 | 0 | goto DoneWithTypeQuals; |
6052 | 0 | if (!getLangOpts().C11) |
6053 | 0 | Diag(Tok, diag::ext_c11_feature) << Tok.getName(); |
6054 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID, |
6055 | 0 | getLangOpts()); |
6056 | 0 | break; |
6057 | | |
6058 | | // OpenCL qualifiers: |
6059 | 0 | case tok::kw_private: |
6060 | 0 | if (!getLangOpts().OpenCL) |
6061 | 0 | goto DoneWithTypeQuals; |
6062 | 0 | [[fallthrough]]; |
6063 | 0 | case tok::kw___private: |
6064 | 0 | case tok::kw___global: |
6065 | 0 | case tok::kw___local: |
6066 | 0 | case tok::kw___constant: |
6067 | 0 | case tok::kw___generic: |
6068 | 0 | case tok::kw___read_only: |
6069 | 0 | case tok::kw___write_only: |
6070 | 0 | case tok::kw___read_write: |
6071 | 0 | ParseOpenCLQualifiers(DS.getAttributes()); |
6072 | 0 | break; |
6073 | | |
6074 | 0 | case tok::kw_groupshared: |
6075 | 0 | case tok::kw_in: |
6076 | 0 | case tok::kw_inout: |
6077 | 0 | case tok::kw_out: |
6078 | | // NOTE: ParseHLSLQualifiers will consume the qualifier token. |
6079 | 0 | ParseHLSLQualifiers(DS.getAttributes()); |
6080 | 0 | continue; |
6081 | | |
6082 | 0 | case tok::kw___unaligned: |
6083 | 0 | isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID, |
6084 | 0 | getLangOpts()); |
6085 | 0 | break; |
6086 | 0 | case tok::kw___uptr: |
6087 | | // GNU libc headers in C mode use '__uptr' as an identifier which conflicts |
6088 | | // with the MS modifier keyword. |
6089 | 0 | if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus && |
6090 | 0 | IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) { |
6091 | 0 | if (TryKeywordIdentFallback(false)) |
6092 | 0 | continue; |
6093 | 0 | } |
6094 | 0 | [[fallthrough]]; |
6095 | 0 | case tok::kw___sptr: |
6096 | 0 | case tok::kw___w64: |
6097 | 0 | case tok::kw___ptr64: |
6098 | 0 | case tok::kw___ptr32: |
6099 | 0 | case tok::kw___cdecl: |
6100 | 0 | case tok::kw___stdcall: |
6101 | 0 | case tok::kw___fastcall: |
6102 | 0 | case tok::kw___thiscall: |
6103 | 0 | case tok::kw___regcall: |
6104 | 0 | case tok::kw___vectorcall: |
6105 | 0 | if (AttrReqs & AR_DeclspecAttributesParsed) { |
6106 | 0 | ParseMicrosoftTypeAttributes(DS.getAttributes()); |
6107 | 0 | continue; |
6108 | 0 | } |
6109 | 0 | goto DoneWithTypeQuals; |
6110 | | |
6111 | 0 | case tok::kw___funcref: |
6112 | 0 | ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes()); |
6113 | 0 | continue; |
6114 | 0 | goto DoneWithTypeQuals; |
6115 | | |
6116 | 0 | case tok::kw___pascal: |
6117 | 0 | if (AttrReqs & AR_VendorAttributesParsed) { |
6118 | 0 | ParseBorlandTypeAttributes(DS.getAttributes()); |
6119 | 0 | continue; |
6120 | 0 | } |
6121 | 0 | goto DoneWithTypeQuals; |
6122 | | |
6123 | | // Nullability type specifiers. |
6124 | 0 | case tok::kw__Nonnull: |
6125 | 0 | case tok::kw__Nullable: |
6126 | 0 | case tok::kw__Nullable_result: |
6127 | 0 | case tok::kw__Null_unspecified: |
6128 | 0 | ParseNullabilityTypeSpecifiers(DS.getAttributes()); |
6129 | 0 | continue; |
6130 | | |
6131 | | // Objective-C 'kindof' types. |
6132 | 0 | case tok::kw___kindof: |
6133 | 0 | DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc, |
6134 | 0 | nullptr, 0, tok::kw___kindof); |
6135 | 0 | (void)ConsumeToken(); |
6136 | 0 | continue; |
6137 | | |
6138 | 0 | case tok::kw___attribute: |
6139 | 0 | if (AttrReqs & AR_GNUAttributesParsedAndRejected) |
6140 | | // When GNU attributes are expressly forbidden, diagnose their usage. |
6141 | 0 | Diag(Tok, diag::err_attributes_not_allowed); |
6142 | | |
6143 | | // Parse the attributes even if they are rejected to ensure that error |
6144 | | // recovery is graceful. |
6145 | 0 | if (AttrReqs & AR_GNUAttributesParsed || |
6146 | 0 | AttrReqs & AR_GNUAttributesParsedAndRejected) { |
6147 | 0 | ParseGNUAttributes(DS.getAttributes()); |
6148 | 0 | continue; // do *not* consume the next token! |
6149 | 0 | } |
6150 | | // otherwise, FALL THROUGH! |
6151 | 0 | [[fallthrough]]; |
6152 | 1.13k | default: |
6153 | 1.13k | DoneWithTypeQuals: |
6154 | | // If this is not a type-qualifier token, we're done reading type |
6155 | | // qualifiers. First verify that DeclSpec's are consistent. |
6156 | 1.13k | DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy()); |
6157 | 1.13k | if (EndLoc.isValid()) |
6158 | 0 | DS.SetRangeEnd(EndLoc); |
6159 | 1.13k | return; |
6160 | 1.13k | } |
6161 | | |
6162 | | // If the specifier combination wasn't legal, issue a diagnostic. |
6163 | 0 | if (isInvalid) { |
6164 | 0 | assert(PrevSpec && "Method did not return previous specifier!"); |
6165 | 0 | Diag(Tok, DiagID) << PrevSpec; |
6166 | 0 | } |
6167 | 0 | EndLoc = ConsumeToken(); |
6168 | 0 | } |
6169 | 1.13k | } |
6170 | | |
6171 | | /// ParseDeclarator - Parse and verify a newly-initialized declarator. |
6172 | 23.9k | void Parser::ParseDeclarator(Declarator &D) { |
6173 | | /// This implements the 'declarator' production in the C grammar, then checks |
6174 | | /// for well-formedness and issues diagnostics. |
6175 | 23.9k | Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { |
6176 | 23.9k | ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); |
6177 | 23.9k | }); |
6178 | 23.9k | } |
6179 | | |
6180 | | static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, |
6181 | 25.1k | DeclaratorContext TheContext) { |
6182 | 25.1k | if (Kind == tok::star || Kind == tok::caret) |
6183 | 680 | return true; |
6184 | | |
6185 | | // OpenCL 2.0 and later define this keyword. |
6186 | 24.4k | if (Kind == tok::kw_pipe && Lang.OpenCL && |
6187 | 24.4k | Lang.getOpenCLCompatibleVersion() >= 200) |
6188 | 0 | return true; |
6189 | | |
6190 | 24.4k | if (!Lang.CPlusPlus) |
6191 | 12.1k | return false; |
6192 | | |
6193 | 12.2k | if (Kind == tok::amp) |
6194 | 110 | return true; |
6195 | | |
6196 | | // We parse rvalue refs in C++03, because otherwise the errors are scary. |
6197 | | // But we must not parse them in conversion-type-ids and new-type-ids, since |
6198 | | // those can be legitimately followed by a && operator. |
6199 | | // (The same thing can in theory happen after a trailing-return-type, but |
6200 | | // since those are a C++11 feature, there is no rejects-valid issue there.) |
6201 | 12.1k | if (Kind == tok::ampamp) |
6202 | 0 | return Lang.CPlusPlus11 || (TheContext != DeclaratorContext::ConversionId && |
6203 | 0 | TheContext != DeclaratorContext::CXXNew); |
6204 | | |
6205 | 12.1k | return false; |
6206 | 12.1k | } |
6207 | | |
6208 | | // Indicates whether the given declarator is a pipe declarator. |
6209 | 0 | static bool isPipeDeclarator(const Declarator &D) { |
6210 | 0 | const unsigned NumTypes = D.getNumTypeObjects(); |
6211 | |
|
6212 | 0 | for (unsigned Idx = 0; Idx != NumTypes; ++Idx) |
6213 | 0 | if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind) |
6214 | 0 | return true; |
6215 | | |
6216 | 0 | return false; |
6217 | 0 | } |
6218 | | |
6219 | | /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator |
6220 | | /// is parsed by the function passed to it. Pass null, and the direct-declarator |
6221 | | /// isn't parsed at all, making this function effectively parse the C++ |
6222 | | /// ptr-operator production. |
6223 | | /// |
6224 | | /// If the grammar of this construct is extended, matching changes must also be |
6225 | | /// made to TryParseDeclarator and MightBeDeclarator, and possibly to |
6226 | | /// isConstructorDeclarator. |
6227 | | /// |
6228 | | /// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl] |
6229 | | /// [C] pointer[opt] direct-declarator |
6230 | | /// [C++] direct-declarator |
6231 | | /// [C++] ptr-operator declarator |
6232 | | /// |
6233 | | /// pointer: [C99 6.7.5] |
6234 | | /// '*' type-qualifier-list[opt] |
6235 | | /// '*' type-qualifier-list[opt] pointer |
6236 | | /// |
6237 | | /// ptr-operator: |
6238 | | /// '*' cv-qualifier-seq[opt] |
6239 | | /// '&' |
6240 | | /// [C++0x] '&&' |
6241 | | /// [GNU] '&' restrict[opt] attributes[opt] |
6242 | | /// [GNU?] '&&' restrict[opt] attributes[opt] |
6243 | | /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] |
6244 | | void Parser::ParseDeclaratorInternal(Declarator &D, |
6245 | 25.1k | DirectDeclParseFunction DirectDeclParser) { |
6246 | 25.1k | if (Diags.hasAllExtensionsSilenced()) |
6247 | 0 | D.setExtension(); |
6248 | | |
6249 | | // C++ member pointers start with a '::' or a nested-name. |
6250 | | // Member pointers get special handling, since there's no place for the |
6251 | | // scope spec in the generic path below. |
6252 | 25.1k | if (getLangOpts().CPlusPlus && |
6253 | 25.1k | (Tok.is(tok::coloncolon) || Tok.is(tok::kw_decltype) || |
6254 | 12.5k | (Tok.is(tok::identifier) && |
6255 | 12.5k | (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) || |
6256 | 12.5k | Tok.is(tok::annot_cxxscope))) { |
6257 | 40 | bool EnteringContext = D.getContext() == DeclaratorContext::File || |
6258 | 40 | D.getContext() == DeclaratorContext::Member; |
6259 | 40 | CXXScopeSpec SS; |
6260 | 40 | SS.setTemplateParamLists(D.getTemplateParameterLists()); |
6261 | 40 | ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, |
6262 | 40 | /*ObjectHasErrors=*/false, EnteringContext); |
6263 | | |
6264 | 40 | if (SS.isNotEmpty()) { |
6265 | 1 | if (Tok.isNot(tok::star)) { |
6266 | | // The scope spec really belongs to the direct-declarator. |
6267 | 1 | if (D.mayHaveIdentifier()) |
6268 | 1 | D.getCXXScopeSpec() = SS; |
6269 | 0 | else |
6270 | 0 | AnnotateScopeToken(SS, true); |
6271 | | |
6272 | 1 | if (DirectDeclParser) |
6273 | 1 | (this->*DirectDeclParser)(D); |
6274 | 1 | return; |
6275 | 1 | } |
6276 | | |
6277 | 0 | if (SS.isValid()) { |
6278 | 0 | checkCompoundToken(SS.getEndLoc(), tok::coloncolon, |
6279 | 0 | CompoundToken::MemberPtr); |
6280 | 0 | } |
6281 | |
|
6282 | 0 | SourceLocation StarLoc = ConsumeToken(); |
6283 | 0 | D.SetRangeEnd(StarLoc); |
6284 | 0 | DeclSpec DS(AttrFactory); |
6285 | 0 | ParseTypeQualifierListOpt(DS); |
6286 | 0 | D.ExtendWithDeclSpec(DS); |
6287 | | |
6288 | | // Recurse to parse whatever is left. |
6289 | 0 | Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { |
6290 | 0 | ParseDeclaratorInternal(D, DirectDeclParser); |
6291 | 0 | }); |
6292 | | |
6293 | | // Sema will have to catch (syntactically invalid) pointers into global |
6294 | | // scope. It has to catch pointers into namespace scope anyway. |
6295 | 0 | D.AddTypeInfo(DeclaratorChunk::getMemberPointer( |
6296 | 0 | SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()), |
6297 | 0 | std::move(DS.getAttributes()), |
6298 | 0 | /* Don't replace range end. */ SourceLocation()); |
6299 | 0 | return; |
6300 | 1 | } |
6301 | 40 | } |
6302 | | |
6303 | 25.1k | tok::TokenKind Kind = Tok.getKind(); |
6304 | | |
6305 | 25.1k | if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclarator(D)) { |
6306 | 0 | DeclSpec DS(AttrFactory); |
6307 | 0 | ParseTypeQualifierListOpt(DS); |
6308 | |
|
6309 | 0 | D.AddTypeInfo( |
6310 | 0 | DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), |
6311 | 0 | std::move(DS.getAttributes()), SourceLocation()); |
6312 | 0 | } |
6313 | | |
6314 | | // Not a pointer, C++ reference, or block. |
6315 | 25.1k | if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) { |
6316 | 24.3k | if (DirectDeclParser) |
6317 | 24.3k | (this->*DirectDeclParser)(D); |
6318 | 24.3k | return; |
6319 | 24.3k | } |
6320 | | |
6321 | | // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference, |
6322 | | // '&&' -> rvalue reference |
6323 | 790 | SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&. |
6324 | 790 | D.SetRangeEnd(Loc); |
6325 | | |
6326 | 790 | if (Kind == tok::star || Kind == tok::caret) { |
6327 | | // Is a pointer. |
6328 | 680 | DeclSpec DS(AttrFactory); |
6329 | | |
6330 | | // GNU attributes are not allowed here in a new-type-id, but Declspec and |
6331 | | // C++11 attributes are allowed. |
6332 | 680 | unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed | |
6333 | 680 | ((D.getContext() != DeclaratorContext::CXXNew) |
6334 | 680 | ? AR_GNUAttributesParsed |
6335 | 680 | : AR_GNUAttributesParsedAndRejected); |
6336 | 680 | ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier()); |
6337 | 680 | D.ExtendWithDeclSpec(DS); |
6338 | | |
6339 | | // Recursively parse the declarator. |
6340 | 680 | Actions.runWithSufficientStackSpace( |
6341 | 680 | D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); |
6342 | 680 | if (Kind == tok::star) |
6343 | | // Remember that we parsed a pointer type, and remember the type-quals. |
6344 | 282 | D.AddTypeInfo(DeclaratorChunk::getPointer( |
6345 | 282 | DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), |
6346 | 282 | DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(), |
6347 | 282 | DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), |
6348 | 282 | std::move(DS.getAttributes()), SourceLocation()); |
6349 | 398 | else |
6350 | | // Remember that we parsed a Block type, and remember the type-quals. |
6351 | 398 | D.AddTypeInfo( |
6352 | 398 | DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc), |
6353 | 398 | std::move(DS.getAttributes()), SourceLocation()); |
6354 | 680 | } else { |
6355 | | // Is a reference |
6356 | 110 | DeclSpec DS(AttrFactory); |
6357 | | |
6358 | | // Complain about rvalue references in C++03, but then go on and build |
6359 | | // the declarator. |
6360 | 110 | if (Kind == tok::ampamp) |
6361 | 0 | Diag(Loc, getLangOpts().CPlusPlus11 ? |
6362 | 0 | diag::warn_cxx98_compat_rvalue_reference : |
6363 | 0 | diag::ext_rvalue_reference); |
6364 | | |
6365 | | // GNU-style and C++11 attributes are allowed here, as is restrict. |
6366 | 110 | ParseTypeQualifierListOpt(DS); |
6367 | 110 | D.ExtendWithDeclSpec(DS); |
6368 | | |
6369 | | // C++ 8.3.2p1: cv-qualified references are ill-formed except when the |
6370 | | // cv-qualifiers are introduced through the use of a typedef or of a |
6371 | | // template type argument, in which case the cv-qualifiers are ignored. |
6372 | 110 | if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) { |
6373 | 0 | if (DS.getTypeQualifiers() & DeclSpec::TQ_const) |
6374 | 0 | Diag(DS.getConstSpecLoc(), |
6375 | 0 | diag::err_invalid_reference_qualifier_application) << "const"; |
6376 | 0 | if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) |
6377 | 0 | Diag(DS.getVolatileSpecLoc(), |
6378 | 0 | diag::err_invalid_reference_qualifier_application) << "volatile"; |
6379 | | // 'restrict' is permitted as an extension. |
6380 | 0 | if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) |
6381 | 0 | Diag(DS.getAtomicSpecLoc(), |
6382 | 0 | diag::err_invalid_reference_qualifier_application) << "_Atomic"; |
6383 | 0 | } |
6384 | | |
6385 | | // Recursively parse the declarator. |
6386 | 110 | Actions.runWithSufficientStackSpace( |
6387 | 110 | D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); |
6388 | | |
6389 | 110 | if (D.getNumTypeObjects() > 0) { |
6390 | | // C++ [dcl.ref]p4: There shall be no references to references. |
6391 | 6 | DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1); |
6392 | 6 | if (InnerChunk.Kind == DeclaratorChunk::Reference) { |
6393 | 0 | if (const IdentifierInfo *II = D.getIdentifier()) |
6394 | 0 | Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference) |
6395 | 0 | << II; |
6396 | 0 | else |
6397 | 0 | Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference) |
6398 | 0 | << "type name"; |
6399 | | |
6400 | | // Once we've complained about the reference-to-reference, we |
6401 | | // can go ahead and build the (technically ill-formed) |
6402 | | // declarator: reference collapsing will take care of it. |
6403 | 0 | } |
6404 | 6 | } |
6405 | | |
6406 | | // Remember that we parsed a reference type. |
6407 | 110 | D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, |
6408 | 110 | Kind == tok::amp), |
6409 | 110 | std::move(DS.getAttributes()), SourceLocation()); |
6410 | 110 | } |
6411 | 790 | } |
6412 | | |
6413 | | // When correcting from misplaced brackets before the identifier, the location |
6414 | | // is saved inside the declarator so that other diagnostic messages can use |
6415 | | // them. This extracts and returns that location, or returns the provided |
6416 | | // location if a stored location does not exist. |
6417 | | static SourceLocation getMissingDeclaratorIdLoc(Declarator &D, |
6418 | 18.3k | SourceLocation Loc) { |
6419 | 18.3k | if (D.getName().StartLocation.isInvalid() && |
6420 | 18.3k | D.getName().EndLocation.isValid()) |
6421 | 68 | return D.getName().EndLocation; |
6422 | | |
6423 | 18.2k | return Loc; |
6424 | 18.3k | } |
6425 | | |
6426 | | /// ParseDirectDeclarator |
6427 | | /// direct-declarator: [C99 6.7.5] |
6428 | | /// [C99] identifier |
6429 | | /// '(' declarator ')' |
6430 | | /// [GNU] '(' attributes declarator ')' |
6431 | | /// [C90] direct-declarator '[' constant-expression[opt] ']' |
6432 | | /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']' |
6433 | | /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']' |
6434 | | /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']' |
6435 | | /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']' |
6436 | | /// [C++11] direct-declarator '[' constant-expression[opt] ']' |
6437 | | /// attribute-specifier-seq[opt] |
6438 | | /// direct-declarator '(' parameter-type-list ')' |
6439 | | /// direct-declarator '(' identifier-list[opt] ')' |
6440 | | /// [GNU] direct-declarator '(' parameter-forward-declarations |
6441 | | /// parameter-type-list[opt] ')' |
6442 | | /// [C++] direct-declarator '(' parameter-declaration-clause ')' |
6443 | | /// cv-qualifier-seq[opt] exception-specification[opt] |
6444 | | /// [C++11] direct-declarator '(' parameter-declaration-clause ')' |
6445 | | /// attribute-specifier-seq[opt] cv-qualifier-seq[opt] |
6446 | | /// ref-qualifier[opt] exception-specification[opt] |
6447 | | /// [C++] declarator-id |
6448 | | /// [C++11] declarator-id attribute-specifier-seq[opt] |
6449 | | /// |
6450 | | /// declarator-id: [C++ 8] |
6451 | | /// '...'[opt] id-expression |
6452 | | /// '::'[opt] nested-name-specifier[opt] type-name |
6453 | | /// |
6454 | | /// id-expression: [C++ 5.1] |
6455 | | /// unqualified-id |
6456 | | /// qualified-id |
6457 | | /// |
6458 | | /// unqualified-id: [C++ 5.1] |
6459 | | /// identifier |
6460 | | /// operator-function-id |
6461 | | /// conversion-function-id |
6462 | | /// '~' class-name |
6463 | | /// template-id |
6464 | | /// |
6465 | | /// C++17 adds the following, which we also handle here: |
6466 | | /// |
6467 | | /// simple-declaration: |
6468 | | /// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';' |
6469 | | /// |
6470 | | /// Note, any additional constructs added here may need corresponding changes |
6471 | | /// in isConstructorDeclarator. |
6472 | 24.3k | void Parser::ParseDirectDeclarator(Declarator &D) { |
6473 | 24.3k | DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec()); |
6474 | | |
6475 | 24.3k | if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) { |
6476 | | // This might be a C++17 structured binding. |
6477 | 12.1k | if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() && |
6478 | 12.1k | D.getCXXScopeSpec().isEmpty()) |
6479 | 100 | return ParseDecompositionDeclarator(D); |
6480 | | |
6481 | | // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in |
6482 | | // this context it is a bitfield. Also in range-based for statement colon |
6483 | | // may delimit for-range-declaration. |
6484 | 12.0k | ColonProtectionRAIIObject X( |
6485 | 12.0k | *this, D.getContext() == DeclaratorContext::Member || |
6486 | 12.0k | (D.getContext() == DeclaratorContext::ForInit && |
6487 | 12.0k | getLangOpts().CPlusPlus11)); |
6488 | | |
6489 | | // ParseDeclaratorInternal might already have parsed the scope. |
6490 | 12.0k | if (D.getCXXScopeSpec().isEmpty()) { |
6491 | 12.0k | bool EnteringContext = D.getContext() == DeclaratorContext::File || |
6492 | 12.0k | D.getContext() == DeclaratorContext::Member; |
6493 | 12.0k | ParseOptionalCXXScopeSpecifier( |
6494 | 12.0k | D.getCXXScopeSpec(), /*ObjectType=*/nullptr, |
6495 | 12.0k | /*ObjectHasErrors=*/false, EnteringContext); |
6496 | 12.0k | } |
6497 | | |
6498 | 12.0k | if (D.getCXXScopeSpec().isValid()) { |
6499 | 0 | if (Actions.ShouldEnterDeclaratorScope(getCurScope(), |
6500 | 0 | D.getCXXScopeSpec())) |
6501 | | // Change the declaration context for name lookup, until this function |
6502 | | // is exited (and the declarator has been parsed). |
6503 | 0 | DeclScopeObj.EnterDeclaratorScope(); |
6504 | 0 | else if (getObjCDeclContext()) { |
6505 | | // Ensure that we don't interpret the next token as an identifier when |
6506 | | // dealing with declarations in an Objective-C container. |
6507 | 0 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6508 | 0 | D.setInvalidType(true); |
6509 | 0 | ConsumeToken(); |
6510 | 0 | goto PastIdentifier; |
6511 | 0 | } |
6512 | 0 | } |
6513 | | |
6514 | | // C++0x [dcl.fct]p14: |
6515 | | // There is a syntactic ambiguity when an ellipsis occurs at the end of a |
6516 | | // parameter-declaration-clause without a preceding comma. In this case, |
6517 | | // the ellipsis is parsed as part of the abstract-declarator if the type |
6518 | | // of the parameter either names a template parameter pack that has not |
6519 | | // been expanded or contains auto; otherwise, it is parsed as part of the |
6520 | | // parameter-declaration-clause. |
6521 | 12.0k | if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() && |
6522 | 12.0k | !((D.getContext() == DeclaratorContext::Prototype || |
6523 | 0 | D.getContext() == DeclaratorContext::LambdaExprParameter || |
6524 | 0 | D.getContext() == DeclaratorContext::BlockLiteral) && |
6525 | 0 | NextToken().is(tok::r_paren) && !D.hasGroupingParens() && |
6526 | 0 | !Actions.containsUnexpandedParameterPacks(D) && |
6527 | 0 | D.getDeclSpec().getTypeSpecType() != TST_auto)) { |
6528 | 0 | SourceLocation EllipsisLoc = ConsumeToken(); |
6529 | 0 | if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) { |
6530 | | // The ellipsis was put in the wrong place. Recover, and explain to |
6531 | | // the user what they should have done. |
6532 | 0 | ParseDeclarator(D); |
6533 | 0 | if (EllipsisLoc.isValid()) |
6534 | 0 | DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D); |
6535 | 0 | return; |
6536 | 0 | } else |
6537 | 0 | D.setEllipsisLoc(EllipsisLoc); |
6538 | | |
6539 | | // The ellipsis can't be followed by a parenthesized declarator. We |
6540 | | // check for that in ParseParenDeclarator, after we have disambiguated |
6541 | | // the l_paren token. |
6542 | 0 | } |
6543 | | |
6544 | 12.0k | if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id, |
6545 | 12.0k | tok::tilde)) { |
6546 | | // We found something that indicates the start of an unqualified-id. |
6547 | | // Parse that unqualified-id. |
6548 | 2.83k | bool AllowConstructorName; |
6549 | 2.83k | bool AllowDeductionGuide; |
6550 | 2.83k | if (D.getDeclSpec().hasTypeSpecifier()) { |
6551 | 2.10k | AllowConstructorName = false; |
6552 | 2.10k | AllowDeductionGuide = false; |
6553 | 2.10k | } else if (D.getCXXScopeSpec().isSet()) { |
6554 | 0 | AllowConstructorName = (D.getContext() == DeclaratorContext::File || |
6555 | 0 | D.getContext() == DeclaratorContext::Member); |
6556 | 0 | AllowDeductionGuide = false; |
6557 | 730 | } else { |
6558 | 730 | AllowConstructorName = (D.getContext() == DeclaratorContext::Member); |
6559 | 730 | AllowDeductionGuide = (D.getContext() == DeclaratorContext::File || |
6560 | 730 | D.getContext() == DeclaratorContext::Member); |
6561 | 730 | } |
6562 | | |
6563 | 2.83k | bool HadScope = D.getCXXScopeSpec().isValid(); |
6564 | 2.83k | if (ParseUnqualifiedId(D.getCXXScopeSpec(), |
6565 | 2.83k | /*ObjectType=*/nullptr, |
6566 | 2.83k | /*ObjectHadErrors=*/false, |
6567 | 2.83k | /*EnteringContext=*/true, |
6568 | 2.83k | /*AllowDestructorName=*/true, AllowConstructorName, |
6569 | 2.83k | AllowDeductionGuide, nullptr, D.getName()) || |
6570 | | // Once we're past the identifier, if the scope was bad, mark the |
6571 | | // whole declarator bad. |
6572 | 2.83k | D.getCXXScopeSpec().isInvalid()) { |
6573 | 188 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6574 | 188 | D.setInvalidType(true); |
6575 | 2.64k | } else { |
6576 | | // ParseUnqualifiedId might have parsed a scope specifier during error |
6577 | | // recovery. If it did so, enter that scope. |
6578 | 2.64k | if (!HadScope && D.getCXXScopeSpec().isValid() && |
6579 | 2.64k | Actions.ShouldEnterDeclaratorScope(getCurScope(), |
6580 | 0 | D.getCXXScopeSpec())) |
6581 | 0 | DeclScopeObj.EnterDeclaratorScope(); |
6582 | | |
6583 | | // Parsed the unqualified-id; update range information and move along. |
6584 | 2.64k | if (D.getSourceRange().getBegin().isInvalid()) |
6585 | 0 | D.SetRangeBegin(D.getName().getSourceRange().getBegin()); |
6586 | 2.64k | D.SetRangeEnd(D.getName().getSourceRange().getEnd()); |
6587 | 2.64k | } |
6588 | 2.83k | goto PastIdentifier; |
6589 | 2.83k | } |
6590 | | |
6591 | 9.18k | if (D.getCXXScopeSpec().isNotEmpty()) { |
6592 | | // We have a scope specifier but no following unqualified-id. |
6593 | 1 | Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()), |
6594 | 1 | diag::err_expected_unqualified_id) |
6595 | 1 | << /*C++*/1; |
6596 | 1 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6597 | 1 | goto PastIdentifier; |
6598 | 1 | } |
6599 | 12.2k | } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { |
6600 | 2.58k | assert(!getLangOpts().CPlusPlus && |
6601 | 2.58k | "There's a C++-specific check for tok::identifier above"); |
6602 | 0 | assert(Tok.getIdentifierInfo() && "Not an identifier?"); |
6603 | 0 | D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); |
6604 | 2.58k | D.SetRangeEnd(Tok.getLocation()); |
6605 | 2.58k | ConsumeToken(); |
6606 | 2.58k | goto PastIdentifier; |
6607 | 9.62k | } else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) { |
6608 | | // We're not allowed an identifier here, but we got one. Try to figure out |
6609 | | // if the user was trying to attach a name to the type, or whether the name |
6610 | | // is some unrelated trailing syntax. |
6611 | 19 | bool DiagnoseIdentifier = false; |
6612 | 19 | if (D.hasGroupingParens()) |
6613 | | // An identifier within parens is unlikely to be intended to be anything |
6614 | | // other than a name being "declared". |
6615 | 0 | DiagnoseIdentifier = true; |
6616 | 19 | else if (D.getContext() == DeclaratorContext::TemplateArg) |
6617 | | // T<int N> is an accidental identifier; T<int N indicates a missing '>'. |
6618 | 18 | DiagnoseIdentifier = |
6619 | 18 | NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater); |
6620 | 1 | else if (D.getContext() == DeclaratorContext::AliasDecl || |
6621 | 1 | D.getContext() == DeclaratorContext::AliasTemplate) |
6622 | | // The most likely error is that the ';' was forgotten. |
6623 | 0 | DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi); |
6624 | 1 | else if ((D.getContext() == DeclaratorContext::TrailingReturn || |
6625 | 1 | D.getContext() == DeclaratorContext::TrailingReturnVar) && |
6626 | 1 | !isCXX11VirtSpecifier(Tok)) |
6627 | 0 | DiagnoseIdentifier = NextToken().isOneOf( |
6628 | 0 | tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try); |
6629 | 19 | if (DiagnoseIdentifier) { |
6630 | 1 | Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id) |
6631 | 1 | << FixItHint::CreateRemoval(Tok.getLocation()); |
6632 | 1 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6633 | 1 | ConsumeToken(); |
6634 | 1 | goto PastIdentifier; |
6635 | 1 | } |
6636 | 19 | } |
6637 | | |
6638 | 18.8k | if (Tok.is(tok::l_paren)) { |
6639 | | // If this might be an abstract-declarator followed by a direct-initializer, |
6640 | | // check whether this is a valid declarator chunk. If it can't be, assume |
6641 | | // that it's an initializer instead. |
6642 | 165 | if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) { |
6643 | 0 | RevertingTentativeParsingAction PA(*this); |
6644 | 0 | if (TryParseDeclarator(true, D.mayHaveIdentifier(), true, |
6645 | 0 | D.getDeclSpec().getTypeSpecType() == TST_auto) == |
6646 | 0 | TPResult::False) { |
6647 | 0 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6648 | 0 | goto PastIdentifier; |
6649 | 0 | } |
6650 | 0 | } |
6651 | | |
6652 | | // direct-declarator: '(' declarator ')' |
6653 | | // direct-declarator: '(' attributes declarator ')' |
6654 | | // Example: 'char (*X)' or 'int (*XX)(void)' |
6655 | 165 | ParseParenDeclarator(D); |
6656 | | |
6657 | | // If the declarator was parenthesized, we entered the declarator |
6658 | | // scope when parsing the parenthesized declarator, then exited |
6659 | | // the scope already. Re-enter the scope, if we need to. |
6660 | 165 | if (D.getCXXScopeSpec().isSet()) { |
6661 | | // If there was an error parsing parenthesized declarator, declarator |
6662 | | // scope may have been entered before. Don't do it again. |
6663 | 0 | if (!D.isInvalidType() && |
6664 | 0 | Actions.ShouldEnterDeclaratorScope(getCurScope(), |
6665 | 0 | D.getCXXScopeSpec())) |
6666 | | // Change the declaration context for name lookup, until this function |
6667 | | // is exited (and the declarator has been parsed). |
6668 | 0 | DeclScopeObj.EnterDeclaratorScope(); |
6669 | 0 | } |
6670 | 18.6k | } else if (D.mayOmitIdentifier()) { |
6671 | | // This could be something simple like "int" (in which case the declarator |
6672 | | // portion is empty), if an abstract-declarator is allowed. |
6673 | 75 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6674 | | |
6675 | | // The grammar for abstract-pack-declarator does not allow grouping parens. |
6676 | | // FIXME: Revisit this once core issue 1488 is resolved. |
6677 | 75 | if (D.hasEllipsis() && D.hasGroupingParens()) |
6678 | 0 | Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()), |
6679 | 0 | diag::ext_abstract_pack_declarator_parens); |
6680 | 18.5k | } else { |
6681 | 18.5k | if (Tok.getKind() == tok::annot_pragma_parser_crash) |
6682 | 0 | LLVM_BUILTIN_TRAP; |
6683 | 18.5k | if (Tok.is(tok::l_square)) |
6684 | 81 | return ParseMisplacedBracketDeclarator(D); |
6685 | 18.4k | if (D.getContext() == DeclaratorContext::Member) { |
6686 | | // Objective-C++: Detect C++ keywords and try to prevent further errors by |
6687 | | // treating these keyword as valid member names. |
6688 | 0 | if (getLangOpts().ObjC && getLangOpts().CPlusPlus && |
6689 | 0 | !Tok.isAnnotation() && Tok.getIdentifierInfo() && |
6690 | 0 | Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) { |
6691 | 0 | Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), |
6692 | 0 | diag::err_expected_member_name_or_semi_objcxx_keyword) |
6693 | 0 | << Tok.getIdentifierInfo() |
6694 | 0 | << (D.getDeclSpec().isEmpty() ? SourceRange() |
6695 | 0 | : D.getDeclSpec().getSourceRange()); |
6696 | 0 | D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); |
6697 | 0 | D.SetRangeEnd(Tok.getLocation()); |
6698 | 0 | ConsumeToken(); |
6699 | 0 | goto PastIdentifier; |
6700 | 0 | } |
6701 | 0 | Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), |
6702 | 0 | diag::err_expected_member_name_or_semi) |
6703 | 0 | << (D.getDeclSpec().isEmpty() ? SourceRange() |
6704 | 0 | : D.getDeclSpec().getSourceRange()); |
6705 | 18.4k | } else { |
6706 | 18.4k | if (Tok.getKind() == tok::TokenKind::kw_while) { |
6707 | 0 | Diag(Tok, diag::err_while_loop_outside_of_a_function); |
6708 | 18.4k | } else if (getLangOpts().CPlusPlus) { |
6709 | 9.09k | if (Tok.isOneOf(tok::period, tok::arrow)) |
6710 | 135 | Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); |
6711 | 8.96k | else { |
6712 | 8.96k | SourceLocation Loc = D.getCXXScopeSpec().getEndLoc(); |
6713 | 8.96k | if (Tok.isAtStartOfLine() && Loc.isValid()) |
6714 | 0 | Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id) |
6715 | 0 | << getLangOpts().CPlusPlus; |
6716 | 8.96k | else |
6717 | 8.96k | Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), |
6718 | 8.96k | diag::err_expected_unqualified_id) |
6719 | 8.96k | << getLangOpts().CPlusPlus; |
6720 | 8.96k | } |
6721 | 9.39k | } else { |
6722 | 9.39k | Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), |
6723 | 9.39k | diag::err_expected_either) |
6724 | 9.39k | << tok::identifier << tok::l_paren; |
6725 | 9.39k | } |
6726 | 18.4k | } |
6727 | 18.4k | D.SetIdentifier(nullptr, Tok.getLocation()); |
6728 | 18.4k | D.setInvalidType(true); |
6729 | 18.4k | } |
6730 | | |
6731 | 24.1k | PastIdentifier: |
6732 | 24.1k | assert(D.isPastIdentifier() && |
6733 | 24.1k | "Haven't past the location of the identifier yet?"); |
6734 | | |
6735 | | // Don't parse attributes unless we have parsed an unparenthesized name. |
6736 | 24.1k | if (D.hasName() && !D.getNumTypeObjects()) |
6737 | 5.22k | MaybeParseCXX11Attributes(D); |
6738 | | |
6739 | 24.3k | while (true) { |
6740 | 24.3k | if (Tok.is(tok::l_paren)) { |
6741 | 139 | bool IsFunctionDeclaration = D.isFunctionDeclaratorAFunctionDeclaration(); |
6742 | | // Enter function-declaration scope, limiting any declarators to the |
6743 | | // function prototype scope, including parameter declarators. |
6744 | 139 | ParseScope PrototypeScope(this, |
6745 | 139 | Scope::FunctionPrototypeScope|Scope::DeclScope| |
6746 | 139 | (IsFunctionDeclaration |
6747 | 139 | ? Scope::FunctionDeclarationScope : 0)); |
6748 | | |
6749 | | // The paren may be part of a C++ direct initializer, eg. "int x(1);". |
6750 | | // In such a case, check if we actually have a function declarator; if it |
6751 | | // is not, the declarator has been fully parsed. |
6752 | 139 | bool IsAmbiguous = false; |
6753 | 139 | if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) { |
6754 | | // C++2a [temp.res]p5 |
6755 | | // A qualified-id is assumed to name a type if |
6756 | | // - [...] |
6757 | | // - it is a decl-specifier of the decl-specifier-seq of a |
6758 | | // - [...] |
6759 | | // - parameter-declaration in a member-declaration [...] |
6760 | | // - parameter-declaration in a declarator of a function or function |
6761 | | // template declaration whose declarator-id is qualified [...] |
6762 | 69 | auto AllowImplicitTypename = ImplicitTypenameContext::No; |
6763 | 69 | if (D.getCXXScopeSpec().isSet()) |
6764 | 0 | AllowImplicitTypename = |
6765 | 0 | (ImplicitTypenameContext)Actions.isDeclaratorFunctionLike(D); |
6766 | 69 | else if (D.getContext() == DeclaratorContext::Member) { |
6767 | 0 | AllowImplicitTypename = ImplicitTypenameContext::Yes; |
6768 | 0 | } |
6769 | | |
6770 | | // The name of the declarator, if any, is tentatively declared within |
6771 | | // a possible direct initializer. |
6772 | 69 | TentativelyDeclaredIdentifiers.push_back(D.getIdentifier()); |
6773 | 69 | bool IsFunctionDecl = |
6774 | 69 | isCXXFunctionDeclarator(&IsAmbiguous, AllowImplicitTypename); |
6775 | 69 | TentativelyDeclaredIdentifiers.pop_back(); |
6776 | 69 | if (!IsFunctionDecl) |
6777 | 60 | break; |
6778 | 69 | } |
6779 | 79 | ParsedAttributes attrs(AttrFactory); |
6780 | 79 | BalancedDelimiterTracker T(*this, tok::l_paren); |
6781 | 79 | T.consumeOpen(); |
6782 | 79 | if (IsFunctionDeclaration) |
6783 | 79 | Actions.ActOnStartFunctionDeclarationDeclarator(D, |
6784 | 79 | TemplateParameterDepth); |
6785 | 79 | ParseFunctionDeclarator(D, attrs, T, IsAmbiguous); |
6786 | 79 | if (IsFunctionDeclaration) |
6787 | 79 | Actions.ActOnFinishFunctionDeclarationDeclarator(D); |
6788 | 79 | PrototypeScope.Exit(); |
6789 | 24.2k | } else if (Tok.is(tok::l_square)) { |
6790 | 154 | ParseBracketDeclarator(D); |
6791 | 24.0k | } else if (Tok.isRegularKeywordAttribute()) { |
6792 | | // For consistency with attribute parsing. |
6793 | 0 | Diag(Tok, diag::err_keyword_not_allowed) << Tok.getIdentifierInfo(); |
6794 | 0 | bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind()); |
6795 | 0 | ConsumeToken(); |
6796 | 0 | if (TakesArgs) { |
6797 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
6798 | 0 | if (!T.consumeOpen()) |
6799 | 0 | T.skipToEnd(); |
6800 | 0 | } |
6801 | 24.0k | } else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) { |
6802 | | // This declarator is declaring a function, but the requires clause is |
6803 | | // in the wrong place: |
6804 | | // void (f() requires true); |
6805 | | // instead of |
6806 | | // void f() requires true; |
6807 | | // or |
6808 | | // void (f()) requires true; |
6809 | 0 | Diag(Tok, diag::err_requires_clause_inside_parens); |
6810 | 0 | ConsumeToken(); |
6811 | 0 | ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr( |
6812 | 0 | ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true)); |
6813 | 0 | if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() && |
6814 | 0 | !D.hasTrailingRequiresClause()) |
6815 | | // We're already ill-formed if we got here but we'll accept it anyway. |
6816 | 0 | D.setTrailingRequiresClause(TrailingRequiresClause.get()); |
6817 | 24.0k | } else { |
6818 | 24.0k | break; |
6819 | 24.0k | } |
6820 | 24.3k | } |
6821 | 24.1k | } |
6822 | | |
6823 | 100 | void Parser::ParseDecompositionDeclarator(Declarator &D) { |
6824 | 100 | assert(Tok.is(tok::l_square)); |
6825 | | |
6826 | | // If this doesn't look like a structured binding, maybe it's a misplaced |
6827 | | // array declarator. |
6828 | | // FIXME: Consume the l_square first so we don't need extra lookahead for |
6829 | | // this. |
6830 | 100 | if (!(NextToken().is(tok::identifier) && |
6831 | 100 | GetLookAheadToken(2).isOneOf(tok::comma, tok::r_square)) && |
6832 | 100 | !(NextToken().is(tok::r_square) && |
6833 | 100 | GetLookAheadToken(2).isOneOf(tok::equal, tok::l_brace))) |
6834 | 100 | return ParseMisplacedBracketDeclarator(D); |
6835 | | |
6836 | 0 | BalancedDelimiterTracker T(*this, tok::l_square); |
6837 | 0 | T.consumeOpen(); |
6838 | |
|
6839 | 0 | SmallVector<DecompositionDeclarator::Binding, 32> Bindings; |
6840 | 0 | while (Tok.isNot(tok::r_square)) { |
6841 | 0 | if (!Bindings.empty()) { |
6842 | 0 | if (Tok.is(tok::comma)) |
6843 | 0 | ConsumeToken(); |
6844 | 0 | else { |
6845 | 0 | if (Tok.is(tok::identifier)) { |
6846 | 0 | SourceLocation EndLoc = getEndOfPreviousToken(); |
6847 | 0 | Diag(EndLoc, diag::err_expected) |
6848 | 0 | << tok::comma << FixItHint::CreateInsertion(EndLoc, ","); |
6849 | 0 | } else { |
6850 | 0 | Diag(Tok, diag::err_expected_comma_or_rsquare); |
6851 | 0 | } |
6852 | |
|
6853 | 0 | SkipUntil(tok::r_square, tok::comma, tok::identifier, |
6854 | 0 | StopAtSemi | StopBeforeMatch); |
6855 | 0 | if (Tok.is(tok::comma)) |
6856 | 0 | ConsumeToken(); |
6857 | 0 | else if (Tok.isNot(tok::identifier)) |
6858 | 0 | break; |
6859 | 0 | } |
6860 | 0 | } |
6861 | | |
6862 | 0 | if (Tok.isNot(tok::identifier)) { |
6863 | 0 | Diag(Tok, diag::err_expected) << tok::identifier; |
6864 | 0 | break; |
6865 | 0 | } |
6866 | | |
6867 | 0 | Bindings.push_back({Tok.getIdentifierInfo(), Tok.getLocation()}); |
6868 | 0 | ConsumeToken(); |
6869 | 0 | } |
6870 | |
|
6871 | 0 | if (Tok.isNot(tok::r_square)) |
6872 | | // We've already diagnosed a problem here. |
6873 | 0 | T.skipToEnd(); |
6874 | 0 | else { |
6875 | | // C++17 does not allow the identifier-list in a structured binding |
6876 | | // to be empty. |
6877 | 0 | if (Bindings.empty()) |
6878 | 0 | Diag(Tok.getLocation(), diag::ext_decomp_decl_empty); |
6879 | |
|
6880 | 0 | T.consumeClose(); |
6881 | 0 | } |
6882 | |
|
6883 | 0 | return D.setDecompositionBindings(T.getOpenLocation(), Bindings, |
6884 | 0 | T.getCloseLocation()); |
6885 | 100 | } |
6886 | | |
6887 | | /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is |
6888 | | /// only called before the identifier, so these are most likely just grouping |
6889 | | /// parens for precedence. If we find that these are actually function |
6890 | | /// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator. |
6891 | | /// |
6892 | | /// direct-declarator: |
6893 | | /// '(' declarator ')' |
6894 | | /// [GNU] '(' attributes declarator ')' |
6895 | | /// direct-declarator '(' parameter-type-list ')' |
6896 | | /// direct-declarator '(' identifier-list[opt] ')' |
6897 | | /// [GNU] direct-declarator '(' parameter-forward-declarations |
6898 | | /// parameter-type-list[opt] ')' |
6899 | | /// |
6900 | 165 | void Parser::ParseParenDeclarator(Declarator &D) { |
6901 | 165 | BalancedDelimiterTracker T(*this, tok::l_paren); |
6902 | 165 | T.consumeOpen(); |
6903 | | |
6904 | 165 | assert(!D.isPastIdentifier() && "Should be called before passing identifier"); |
6905 | | |
6906 | | // Eat any attributes before we look at whether this is a grouping or function |
6907 | | // declarator paren. If this is a grouping paren, the attribute applies to |
6908 | | // the type being built up, for example: |
6909 | | // int (__attribute__(()) *x)(long y) |
6910 | | // If this ends up not being a grouping paren, the attribute applies to the |
6911 | | // first argument, for example: |
6912 | | // int (__attribute__(()) int x) |
6913 | | // In either case, we need to eat any attributes to be able to determine what |
6914 | | // sort of paren this is. |
6915 | | // |
6916 | 0 | ParsedAttributes attrs(AttrFactory); |
6917 | 165 | bool RequiresArg = false; |
6918 | 165 | if (Tok.is(tok::kw___attribute)) { |
6919 | 0 | ParseGNUAttributes(attrs); |
6920 | | |
6921 | | // We require that the argument list (if this is a non-grouping paren) be |
6922 | | // present even if the attribute list was empty. |
6923 | 0 | RequiresArg = true; |
6924 | 0 | } |
6925 | | |
6926 | | // Eat any Microsoft extensions. |
6927 | 165 | ParseMicrosoftTypeAttributes(attrs); |
6928 | | |
6929 | | // Eat any Borland extensions. |
6930 | 165 | if (Tok.is(tok::kw___pascal)) |
6931 | 0 | ParseBorlandTypeAttributes(attrs); |
6932 | | |
6933 | | // If we haven't past the identifier yet (or where the identifier would be |
6934 | | // stored, if this is an abstract declarator), then this is probably just |
6935 | | // grouping parens. However, if this could be an abstract-declarator, then |
6936 | | // this could also be the start of function arguments (consider 'void()'). |
6937 | 165 | bool isGrouping; |
6938 | | |
6939 | 165 | if (!D.mayOmitIdentifier()) { |
6940 | | // If this can't be an abstract-declarator, this *must* be a grouping |
6941 | | // paren, because we haven't seen the identifier yet. |
6942 | 163 | isGrouping = true; |
6943 | 163 | } else if (Tok.is(tok::r_paren) || // 'int()' is a function. |
6944 | 2 | (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) && |
6945 | 2 | NextToken().is(tok::r_paren)) || // C++ int(...) |
6946 | 2 | isDeclarationSpecifier( |
6947 | 2 | ImplicitTypenameContext::No) || // 'int(int)' is a function. |
6948 | 2 | isCXX11AttributeSpecifier()) { // 'int([[]]int)' is a function. |
6949 | | // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is |
6950 | | // considered to be a type, not a K&R identifier-list. |
6951 | 0 | isGrouping = false; |
6952 | 2 | } else { |
6953 | | // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'. |
6954 | 2 | isGrouping = true; |
6955 | 2 | } |
6956 | | |
6957 | | // If this is a grouping paren, handle: |
6958 | | // direct-declarator: '(' declarator ')' |
6959 | | // direct-declarator: '(' attributes declarator ')' |
6960 | 165 | if (isGrouping) { |
6961 | 165 | SourceLocation EllipsisLoc = D.getEllipsisLoc(); |
6962 | 165 | D.setEllipsisLoc(SourceLocation()); |
6963 | | |
6964 | 165 | bool hadGroupingParens = D.hasGroupingParens(); |
6965 | 165 | D.setGroupingParens(true); |
6966 | 165 | ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); |
6967 | | // Match the ')'. |
6968 | 165 | T.consumeClose(); |
6969 | 165 | D.AddTypeInfo( |
6970 | 165 | DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()), |
6971 | 165 | std::move(attrs), T.getCloseLocation()); |
6972 | | |
6973 | 165 | D.setGroupingParens(hadGroupingParens); |
6974 | | |
6975 | | // An ellipsis cannot be placed outside parentheses. |
6976 | 165 | if (EllipsisLoc.isValid()) |
6977 | 0 | DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D); |
6978 | | |
6979 | 165 | return; |
6980 | 165 | } |
6981 | | |
6982 | | // Okay, if this wasn't a grouping paren, it must be the start of a function |
6983 | | // argument list. Recognize that this declarator will never have an |
6984 | | // identifier (and remember where it would have been), then call into |
6985 | | // ParseFunctionDeclarator to handle of argument list. |
6986 | 0 | D.SetIdentifier(nullptr, Tok.getLocation()); |
6987 | | |
6988 | | // Enter function-declaration scope, limiting any declarators to the |
6989 | | // function prototype scope, including parameter declarators. |
6990 | 0 | ParseScope PrototypeScope(this, |
6991 | 0 | Scope::FunctionPrototypeScope | Scope::DeclScope | |
6992 | 0 | (D.isFunctionDeclaratorAFunctionDeclaration() |
6993 | 0 | ? Scope::FunctionDeclarationScope : 0)); |
6994 | 0 | ParseFunctionDeclarator(D, attrs, T, false, RequiresArg); |
6995 | 0 | PrototypeScope.Exit(); |
6996 | 0 | } |
6997 | | |
6998 | | void Parser::InitCXXThisScopeForDeclaratorIfRelevant( |
6999 | | const Declarator &D, const DeclSpec &DS, |
7000 | 10 | std::optional<Sema::CXXThisScopeRAII> &ThisScope) { |
7001 | | // C++11 [expr.prim.general]p3: |
7002 | | // If a declaration declares a member function or member function |
7003 | | // template of a class X, the expression this is a prvalue of type |
7004 | | // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq |
7005 | | // and the end of the function-definition, member-declarator, or |
7006 | | // declarator. |
7007 | | // FIXME: currently, "static" case isn't handled correctly. |
7008 | 10 | bool IsCXX11MemberFunction = |
7009 | 10 | getLangOpts().CPlusPlus11 && |
7010 | 10 | D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && |
7011 | 10 | (D.getContext() == DeclaratorContext::Member |
7012 | 10 | ? !D.getDeclSpec().isFriendSpecified() |
7013 | 10 | : D.getContext() == DeclaratorContext::File && |
7014 | 10 | D.getCXXScopeSpec().isValid() && |
7015 | 10 | Actions.CurContext->isRecord()); |
7016 | 10 | if (!IsCXX11MemberFunction) |
7017 | 10 | return; |
7018 | | |
7019 | 0 | Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers()); |
7020 | 0 | if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14) |
7021 | 0 | Q.addConst(); |
7022 | | // FIXME: Collect C++ address spaces. |
7023 | | // If there are multiple different address spaces, the source is invalid. |
7024 | | // Carry on using the first addr space for the qualifiers of 'this'. |
7025 | | // The diagnostic will be given later while creating the function |
7026 | | // prototype for the method. |
7027 | 0 | if (getLangOpts().OpenCLCPlusPlus) { |
7028 | 0 | for (ParsedAttr &attr : DS.getAttributes()) { |
7029 | 0 | LangAS ASIdx = attr.asOpenCLLangAS(); |
7030 | 0 | if (ASIdx != LangAS::Default) { |
7031 | 0 | Q.addAddressSpace(ASIdx); |
7032 | 0 | break; |
7033 | 0 | } |
7034 | 0 | } |
7035 | 0 | } |
7036 | 0 | ThisScope.emplace(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q, |
7037 | 0 | IsCXX11MemberFunction); |
7038 | 0 | } |
7039 | | |
7040 | | /// ParseFunctionDeclarator - We are after the identifier and have parsed the |
7041 | | /// declarator D up to a paren, which indicates that we are parsing function |
7042 | | /// arguments. |
7043 | | /// |
7044 | | /// If FirstArgAttrs is non-null, then the caller parsed those attributes |
7045 | | /// immediately after the open paren - they will be applied to the DeclSpec |
7046 | | /// of the first parameter. |
7047 | | /// |
7048 | | /// If RequiresArg is true, then the first argument of the function is required |
7049 | | /// to be present and required to not be an identifier list. |
7050 | | /// |
7051 | | /// For C++, after the parameter-list, it also parses the cv-qualifier-seq[opt], |
7052 | | /// (C++11) ref-qualifier[opt], exception-specification[opt], |
7053 | | /// (C++11) attribute-specifier-seq[opt], (C++11) trailing-return-type[opt] and |
7054 | | /// (C++2a) the trailing requires-clause. |
7055 | | /// |
7056 | | /// [C++11] exception-specification: |
7057 | | /// dynamic-exception-specification |
7058 | | /// noexcept-specification |
7059 | | /// |
7060 | | void Parser::ParseFunctionDeclarator(Declarator &D, |
7061 | | ParsedAttributes &FirstArgAttrs, |
7062 | | BalancedDelimiterTracker &Tracker, |
7063 | | bool IsAmbiguous, |
7064 | 79 | bool RequiresArg) { |
7065 | 79 | assert(getCurScope()->isFunctionPrototypeScope() && |
7066 | 79 | "Should call from a Function scope"); |
7067 | | // lparen is already consumed! |
7068 | 0 | assert(D.isPastIdentifier() && "Should not call before identifier!"); |
7069 | | |
7070 | | // This should be true when the function has typed arguments. |
7071 | | // Otherwise, it is treated as a K&R-style function. |
7072 | 0 | bool HasProto = false; |
7073 | | // Build up an array of information about the parsed arguments. |
7074 | 79 | SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; |
7075 | | // Remember where we see an ellipsis, if any. |
7076 | 79 | SourceLocation EllipsisLoc; |
7077 | | |
7078 | 79 | DeclSpec DS(AttrFactory); |
7079 | 79 | bool RefQualifierIsLValueRef = true; |
7080 | 79 | SourceLocation RefQualifierLoc; |
7081 | 79 | ExceptionSpecificationType ESpecType = EST_None; |
7082 | 79 | SourceRange ESpecRange; |
7083 | 79 | SmallVector<ParsedType, 2> DynamicExceptions; |
7084 | 79 | SmallVector<SourceRange, 2> DynamicExceptionRanges; |
7085 | 79 | ExprResult NoexceptExpr; |
7086 | 79 | CachedTokens *ExceptionSpecTokens = nullptr; |
7087 | 79 | ParsedAttributes FnAttrs(AttrFactory); |
7088 | 79 | TypeResult TrailingReturnType; |
7089 | 79 | SourceLocation TrailingReturnTypeLoc; |
7090 | | |
7091 | | /* LocalEndLoc is the end location for the local FunctionTypeLoc. |
7092 | | EndLoc is the end location for the function declarator. |
7093 | | They differ for trailing return types. */ |
7094 | 79 | SourceLocation StartLoc, LocalEndLoc, EndLoc; |
7095 | 79 | SourceLocation LParenLoc, RParenLoc; |
7096 | 79 | LParenLoc = Tracker.getOpenLocation(); |
7097 | 79 | StartLoc = LParenLoc; |
7098 | | |
7099 | 79 | if (isFunctionDeclaratorIdentifierList()) { |
7100 | 0 | if (RequiresArg) |
7101 | 0 | Diag(Tok, diag::err_argument_required_after_attribute); |
7102 | |
|
7103 | 0 | ParseFunctionDeclaratorIdentifierList(D, ParamInfo); |
7104 | |
|
7105 | 0 | Tracker.consumeClose(); |
7106 | 0 | RParenLoc = Tracker.getCloseLocation(); |
7107 | 0 | LocalEndLoc = RParenLoc; |
7108 | 0 | EndLoc = RParenLoc; |
7109 | | |
7110 | | // If there are attributes following the identifier list, parse them and |
7111 | | // prohibit them. |
7112 | 0 | MaybeParseCXX11Attributes(FnAttrs); |
7113 | 0 | ProhibitAttributes(FnAttrs); |
7114 | 79 | } else { |
7115 | 79 | if (Tok.isNot(tok::r_paren)) |
7116 | 73 | ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc); |
7117 | 6 | else if (RequiresArg) |
7118 | 0 | Diag(Tok, diag::err_argument_required_after_attribute); |
7119 | | |
7120 | | // OpenCL disallows functions without a prototype, but it doesn't enforce |
7121 | | // strict prototypes as in C23 because it allows a function definition to |
7122 | | // have an identifier list. See OpenCL 3.0 6.11/g for more details. |
7123 | 79 | HasProto = ParamInfo.size() || getLangOpts().requiresStrictPrototypes() || |
7124 | 79 | getLangOpts().OpenCL; |
7125 | | |
7126 | | // If we have the closing ')', eat it. |
7127 | 79 | Tracker.consumeClose(); |
7128 | 79 | RParenLoc = Tracker.getCloseLocation(); |
7129 | 79 | LocalEndLoc = RParenLoc; |
7130 | 79 | EndLoc = RParenLoc; |
7131 | | |
7132 | 79 | if (getLangOpts().CPlusPlus) { |
7133 | | // FIXME: Accept these components in any order, and produce fixits to |
7134 | | // correct the order if the user gets it wrong. Ideally we should deal |
7135 | | // with the pure-specifier in the same way. |
7136 | | |
7137 | | // Parse cv-qualifier-seq[opt]. |
7138 | 10 | ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, |
7139 | 10 | /*AtomicAllowed*/ false, |
7140 | 10 | /*IdentifierRequired=*/false, |
7141 | 10 | llvm::function_ref<void()>([&]() { |
7142 | 0 | Actions.CodeCompleteFunctionQualifiers(DS, D); |
7143 | 0 | })); |
7144 | 10 | if (!DS.getSourceRange().getEnd().isInvalid()) { |
7145 | 0 | EndLoc = DS.getSourceRange().getEnd(); |
7146 | 0 | } |
7147 | | |
7148 | | // Parse ref-qualifier[opt]. |
7149 | 10 | if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) |
7150 | 0 | EndLoc = RefQualifierLoc; |
7151 | | |
7152 | 10 | std::optional<Sema::CXXThisScopeRAII> ThisScope; |
7153 | 10 | InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope); |
7154 | | |
7155 | | // Parse exception-specification[opt]. |
7156 | | // FIXME: Per [class.mem]p6, all exception-specifications at class scope |
7157 | | // should be delayed, including those for non-members (eg, friend |
7158 | | // declarations). But only applying this to member declarations is |
7159 | | // consistent with what other implementations do. |
7160 | 10 | bool Delayed = D.isFirstDeclarationOfMember() && |
7161 | 10 | D.isFunctionDeclaratorAFunctionDeclaration(); |
7162 | 10 | if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) && |
7163 | 10 | GetLookAheadToken(0).is(tok::kw_noexcept) && |
7164 | 10 | GetLookAheadToken(1).is(tok::l_paren) && |
7165 | 10 | GetLookAheadToken(2).is(tok::kw_noexcept) && |
7166 | 10 | GetLookAheadToken(3).is(tok::l_paren) && |
7167 | 10 | GetLookAheadToken(4).is(tok::identifier) && |
7168 | 10 | GetLookAheadToken(4).getIdentifierInfo()->isStr("swap")) { |
7169 | | // HACK: We've got an exception-specification |
7170 | | // noexcept(noexcept(swap(...))) |
7171 | | // or |
7172 | | // noexcept(noexcept(swap(...)) && noexcept(swap(...))) |
7173 | | // on a 'swap' member function. This is a libstdc++ bug; the lookup |
7174 | | // for 'swap' will only find the function we're currently declaring, |
7175 | | // whereas it expects to find a non-member swap through ADL. Turn off |
7176 | | // delayed parsing to give it a chance to find what it expects. |
7177 | 0 | Delayed = false; |
7178 | 0 | } |
7179 | 10 | ESpecType = tryParseExceptionSpecification(Delayed, |
7180 | 10 | ESpecRange, |
7181 | 10 | DynamicExceptions, |
7182 | 10 | DynamicExceptionRanges, |
7183 | 10 | NoexceptExpr, |
7184 | 10 | ExceptionSpecTokens); |
7185 | 10 | if (ESpecType != EST_None) |
7186 | 0 | EndLoc = ESpecRange.getEnd(); |
7187 | | |
7188 | | // Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes |
7189 | | // after the exception-specification. |
7190 | 10 | MaybeParseCXX11Attributes(FnAttrs); |
7191 | | |
7192 | | // Parse trailing-return-type[opt]. |
7193 | 10 | LocalEndLoc = EndLoc; |
7194 | 10 | if (getLangOpts().CPlusPlus11 && Tok.is(tok::arrow)) { |
7195 | 0 | Diag(Tok, diag::warn_cxx98_compat_trailing_return_type); |
7196 | 0 | if (D.getDeclSpec().getTypeSpecType() == TST_auto) |
7197 | 0 | StartLoc = D.getDeclSpec().getTypeSpecTypeLoc(); |
7198 | 0 | LocalEndLoc = Tok.getLocation(); |
7199 | 0 | SourceRange Range; |
7200 | 0 | TrailingReturnType = |
7201 | 0 | ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit()); |
7202 | 0 | TrailingReturnTypeLoc = Range.getBegin(); |
7203 | 0 | EndLoc = Range.getEnd(); |
7204 | 0 | } |
7205 | 69 | } else { |
7206 | 69 | MaybeParseCXX11Attributes(FnAttrs); |
7207 | 69 | } |
7208 | 79 | } |
7209 | | |
7210 | | // Collect non-parameter declarations from the prototype if this is a function |
7211 | | // declaration. They will be moved into the scope of the function. Only do |
7212 | | // this in C and not C++, where the decls will continue to live in the |
7213 | | // surrounding context. |
7214 | 79 | SmallVector<NamedDecl *, 0> DeclsInPrototype; |
7215 | 79 | if (getCurScope()->isFunctionDeclarationScope() && !getLangOpts().CPlusPlus) { |
7216 | 69 | for (Decl *D : getCurScope()->decls()) { |
7217 | 34 | NamedDecl *ND = dyn_cast<NamedDecl>(D); |
7218 | 34 | if (!ND || isa<ParmVarDecl>(ND)) |
7219 | 34 | continue; |
7220 | 0 | DeclsInPrototype.push_back(ND); |
7221 | 0 | } |
7222 | | // Sort DeclsInPrototype based on raw encoding of the source location. |
7223 | | // Scope::decls() is iterating over a SmallPtrSet so sort the Decls before |
7224 | | // moving to DeclContext. This provides a stable ordering for traversing |
7225 | | // Decls in DeclContext, which is important for tasks like ASTWriter for |
7226 | | // deterministic output. |
7227 | 69 | llvm::sort(DeclsInPrototype, [](Decl *D1, Decl *D2) { |
7228 | 0 | return D1->getLocation().getRawEncoding() < |
7229 | 0 | D2->getLocation().getRawEncoding(); |
7230 | 0 | }); |
7231 | 69 | } |
7232 | | |
7233 | | // Remember that we parsed a function type, and remember the attributes. |
7234 | 79 | D.AddTypeInfo(DeclaratorChunk::getFunction( |
7235 | 79 | HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(), |
7236 | 79 | ParamInfo.size(), EllipsisLoc, RParenLoc, |
7237 | 79 | RefQualifierIsLValueRef, RefQualifierLoc, |
7238 | 79 | /*MutableLoc=*/SourceLocation(), |
7239 | 79 | ESpecType, ESpecRange, DynamicExceptions.data(), |
7240 | 79 | DynamicExceptionRanges.data(), DynamicExceptions.size(), |
7241 | 79 | NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, |
7242 | 79 | ExceptionSpecTokens, DeclsInPrototype, StartLoc, |
7243 | 79 | LocalEndLoc, D, TrailingReturnType, TrailingReturnTypeLoc, |
7244 | 79 | &DS), |
7245 | 79 | std::move(FnAttrs), EndLoc); |
7246 | 79 | } |
7247 | | |
7248 | | /// ParseRefQualifier - Parses a member function ref-qualifier. Returns |
7249 | | /// true if a ref-qualifier is found. |
7250 | | bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef, |
7251 | 10 | SourceLocation &RefQualifierLoc) { |
7252 | 10 | if (Tok.isOneOf(tok::amp, tok::ampamp)) { |
7253 | 0 | Diag(Tok, getLangOpts().CPlusPlus11 ? |
7254 | 0 | diag::warn_cxx98_compat_ref_qualifier : |
7255 | 0 | diag::ext_ref_qualifier); |
7256 | |
|
7257 | 0 | RefQualifierIsLValueRef = Tok.is(tok::amp); |
7258 | 0 | RefQualifierLoc = ConsumeToken(); |
7259 | 0 | return true; |
7260 | 0 | } |
7261 | 10 | return false; |
7262 | 10 | } |
7263 | | |
7264 | | /// isFunctionDeclaratorIdentifierList - This parameter list may have an |
7265 | | /// identifier list form for a K&R-style function: void foo(a,b,c) |
7266 | | /// |
7267 | | /// Note that identifier-lists are only allowed for normal declarators, not for |
7268 | | /// abstract-declarators. |
7269 | 79 | bool Parser::isFunctionDeclaratorIdentifierList() { |
7270 | 79 | return !getLangOpts().requiresStrictPrototypes() |
7271 | 79 | && Tok.is(tok::identifier) |
7272 | 79 | && !TryAltiVecVectorToken() |
7273 | | // K&R identifier lists can't have typedefs as identifiers, per C99 |
7274 | | // 6.7.5.3p11. |
7275 | 79 | && (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) |
7276 | | // Identifier lists follow a really simple grammar: the identifiers can |
7277 | | // be followed *only* by a ", identifier" or ")". However, K&R |
7278 | | // identifier lists are really rare in the brave new modern world, and |
7279 | | // it is very common for someone to typo a type in a non-K&R style |
7280 | | // list. If we are presented with something like: "void foo(intptr x, |
7281 | | // float y)", we don't want to start parsing the function declarator as |
7282 | | // though it is a K&R style declarator just because intptr is an |
7283 | | // invalid type. |
7284 | | // |
7285 | | // To handle this, we check to see if the token after the first |
7286 | | // identifier is a "," or ")". Only then do we parse it as an |
7287 | | // identifier list. |
7288 | 79 | && (!Tok.is(tok::eof) && |
7289 | 30 | (NextToken().is(tok::comma) || NextToken().is(tok::r_paren))); |
7290 | 79 | } |
7291 | | |
7292 | | /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator |
7293 | | /// we found a K&R-style identifier list instead of a typed parameter list. |
7294 | | /// |
7295 | | /// After returning, ParamInfo will hold the parsed parameters. |
7296 | | /// |
7297 | | /// identifier-list: [C99 6.7.5] |
7298 | | /// identifier |
7299 | | /// identifier-list ',' identifier |
7300 | | /// |
7301 | | void Parser::ParseFunctionDeclaratorIdentifierList( |
7302 | | Declarator &D, |
7303 | 0 | SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) { |
7304 | | // We should never reach this point in C23 or C++. |
7305 | 0 | assert(!getLangOpts().requiresStrictPrototypes() && |
7306 | 0 | "Cannot parse an identifier list in C23 or C++"); |
7307 | | |
7308 | | // If there was no identifier specified for the declarator, either we are in |
7309 | | // an abstract-declarator, or we are in a parameter declarator which was found |
7310 | | // to be abstract. In abstract-declarators, identifier lists are not valid: |
7311 | | // diagnose this. |
7312 | 0 | if (!D.getIdentifier()) |
7313 | 0 | Diag(Tok, diag::ext_ident_list_in_param); |
7314 | | |
7315 | | // Maintain an efficient lookup of params we have seen so far. |
7316 | 0 | llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar; |
7317 | |
|
7318 | 0 | do { |
7319 | | // If this isn't an identifier, report the error and skip until ')'. |
7320 | 0 | if (Tok.isNot(tok::identifier)) { |
7321 | 0 | Diag(Tok, diag::err_expected) << tok::identifier; |
7322 | 0 | SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); |
7323 | | // Forget we parsed anything. |
7324 | 0 | ParamInfo.clear(); |
7325 | 0 | return; |
7326 | 0 | } |
7327 | | |
7328 | 0 | IdentifierInfo *ParmII = Tok.getIdentifierInfo(); |
7329 | | |
7330 | | // Reject 'typedef int y; int test(x, y)', but continue parsing. |
7331 | 0 | if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope())) |
7332 | 0 | Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII; |
7333 | | |
7334 | | // Verify that the argument identifier has not already been mentioned. |
7335 | 0 | if (!ParamsSoFar.insert(ParmII).second) { |
7336 | 0 | Diag(Tok, diag::err_param_redefinition) << ParmII; |
7337 | 0 | } else { |
7338 | | // Remember this identifier in ParamInfo. |
7339 | 0 | ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, |
7340 | 0 | Tok.getLocation(), |
7341 | 0 | nullptr)); |
7342 | 0 | } |
7343 | | |
7344 | | // Eat the identifier. |
7345 | 0 | ConsumeToken(); |
7346 | | // The list continues if we see a comma. |
7347 | 0 | } while (TryConsumeToken(tok::comma)); |
7348 | 0 | } |
7349 | | |
7350 | | /// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list |
7351 | | /// after the opening parenthesis. This function will not parse a K&R-style |
7352 | | /// identifier list. |
7353 | | /// |
7354 | | /// DeclContext is the context of the declarator being parsed. If FirstArgAttrs |
7355 | | /// is non-null, then the caller parsed those attributes immediately after the |
7356 | | /// open paren - they will be applied to the DeclSpec of the first parameter. |
7357 | | /// |
7358 | | /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will |
7359 | | /// be the location of the ellipsis, if any was parsed. |
7360 | | /// |
7361 | | /// parameter-type-list: [C99 6.7.5] |
7362 | | /// parameter-list |
7363 | | /// parameter-list ',' '...' |
7364 | | /// [C++] parameter-list '...' |
7365 | | /// |
7366 | | /// parameter-list: [C99 6.7.5] |
7367 | | /// parameter-declaration |
7368 | | /// parameter-list ',' parameter-declaration |
7369 | | /// |
7370 | | /// parameter-declaration: [C99 6.7.5] |
7371 | | /// declaration-specifiers declarator |
7372 | | /// [C++] declaration-specifiers declarator '=' assignment-expression |
7373 | | /// [C++11] initializer-clause |
7374 | | /// [GNU] declaration-specifiers declarator attributes |
7375 | | /// declaration-specifiers abstract-declarator[opt] |
7376 | | /// [C++] declaration-specifiers abstract-declarator[opt] |
7377 | | /// '=' assignment-expression |
7378 | | /// [GNU] declaration-specifiers abstract-declarator[opt] attributes |
7379 | | /// [C++11] attribute-specifier-seq parameter-declaration |
7380 | | /// [C++2b] attribute-specifier-seq 'this' parameter-declaration |
7381 | | /// |
7382 | | void Parser::ParseParameterDeclarationClause( |
7383 | | DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, |
7384 | | SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, |
7385 | 73 | SourceLocation &EllipsisLoc, bool IsACXXFunctionDeclaration) { |
7386 | | |
7387 | | // Avoid exceeding the maximum function scope depth. |
7388 | | // See https://bugs.llvm.org/show_bug.cgi?id=19607 |
7389 | | // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with |
7390 | | // getFunctionPrototypeDepth() - 1. |
7391 | 73 | if (getCurScope()->getFunctionPrototypeDepth() - 1 > |
7392 | 73 | ParmVarDecl::getMaxFunctionScopeDepth()) { |
7393 | 0 | Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded) |
7394 | 0 | << ParmVarDecl::getMaxFunctionScopeDepth(); |
7395 | 0 | cutOffParsing(); |
7396 | 0 | return; |
7397 | 0 | } |
7398 | | |
7399 | | // C++2a [temp.res]p5 |
7400 | | // A qualified-id is assumed to name a type if |
7401 | | // - [...] |
7402 | | // - it is a decl-specifier of the decl-specifier-seq of a |
7403 | | // - [...] |
7404 | | // - parameter-declaration in a member-declaration [...] |
7405 | | // - parameter-declaration in a declarator of a function or function |
7406 | | // template declaration whose declarator-id is qualified [...] |
7407 | | // - parameter-declaration in a lambda-declarator [...] |
7408 | 73 | auto AllowImplicitTypename = ImplicitTypenameContext::No; |
7409 | 73 | if (DeclaratorCtx == DeclaratorContext::Member || |
7410 | 73 | DeclaratorCtx == DeclaratorContext::LambdaExpr || |
7411 | 73 | DeclaratorCtx == DeclaratorContext::RequiresExpr || |
7412 | 73 | IsACXXFunctionDeclaration) { |
7413 | 0 | AllowImplicitTypename = ImplicitTypenameContext::Yes; |
7414 | 0 | } |
7415 | | |
7416 | 74 | do { |
7417 | | // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq |
7418 | | // before deciding this was a parameter-declaration-clause. |
7419 | 74 | if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) |
7420 | 0 | break; |
7421 | | |
7422 | | // Parse the declaration-specifiers. |
7423 | | // Just use the ParsingDeclaration "scope" of the declarator. |
7424 | 74 | DeclSpec DS(AttrFactory); |
7425 | | |
7426 | 74 | ParsedAttributes ArgDeclAttrs(AttrFactory); |
7427 | 74 | ParsedAttributes ArgDeclSpecAttrs(AttrFactory); |
7428 | | |
7429 | 74 | if (FirstArgAttrs.Range.isValid()) { |
7430 | | // If the caller parsed attributes for the first argument, add them now. |
7431 | | // Take them so that we only apply the attributes to the first parameter. |
7432 | | // We have already started parsing the decl-specifier sequence, so don't |
7433 | | // parse any parameter-declaration pieces that precede it. |
7434 | 0 | ArgDeclSpecAttrs.takeAllFrom(FirstArgAttrs); |
7435 | 74 | } else { |
7436 | | // Parse any C++11 attributes. |
7437 | 74 | MaybeParseCXX11Attributes(ArgDeclAttrs); |
7438 | | |
7439 | | // Skip any Microsoft attributes before a param. |
7440 | 74 | MaybeParseMicrosoftAttributes(ArgDeclSpecAttrs); |
7441 | 74 | } |
7442 | | |
7443 | 74 | SourceLocation DSStart = Tok.getLocation(); |
7444 | | |
7445 | | // Parse a C++23 Explicit Object Parameter |
7446 | | // We do that in all language modes to produce a better diagnostic. |
7447 | 74 | SourceLocation ThisLoc; |
7448 | 74 | if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) |
7449 | 0 | ThisLoc = ConsumeToken(); |
7450 | | |
7451 | 74 | ParseDeclarationSpecifiers(DS, /*TemplateInfo=*/ParsedTemplateInfo(), |
7452 | 74 | AS_none, DeclSpecContext::DSC_normal, |
7453 | 74 | /*LateAttrs=*/nullptr, AllowImplicitTypename); |
7454 | | |
7455 | 74 | DS.takeAttributesFrom(ArgDeclSpecAttrs); |
7456 | | |
7457 | | // Parse the declarator. This is "PrototypeContext" or |
7458 | | // "LambdaExprParameterContext", because we must accept either |
7459 | | // 'declarator' or 'abstract-declarator' here. |
7460 | 74 | Declarator ParmDeclarator(DS, ArgDeclAttrs, |
7461 | 74 | DeclaratorCtx == DeclaratorContext::RequiresExpr |
7462 | 74 | ? DeclaratorContext::RequiresExpr |
7463 | 74 | : DeclaratorCtx == DeclaratorContext::LambdaExpr |
7464 | 74 | ? DeclaratorContext::LambdaExprParameter |
7465 | 74 | : DeclaratorContext::Prototype); |
7466 | 74 | ParseDeclarator(ParmDeclarator); |
7467 | | |
7468 | 74 | if (ThisLoc.isValid()) |
7469 | 0 | ParmDeclarator.SetRangeBegin(ThisLoc); |
7470 | | |
7471 | | // Parse GNU attributes, if present. |
7472 | 74 | MaybeParseGNUAttributes(ParmDeclarator); |
7473 | 74 | if (getLangOpts().HLSL) |
7474 | 0 | MaybeParseHLSLSemantics(DS.getAttributes()); |
7475 | | |
7476 | 74 | if (Tok.is(tok::kw_requires)) { |
7477 | | // User tried to define a requires clause in a parameter declaration, |
7478 | | // which is surely not a function declaration. |
7479 | | // void f(int (*g)(int, int) requires true); |
7480 | 0 | Diag(Tok, |
7481 | 0 | diag::err_requires_clause_on_declarator_not_declaring_a_function); |
7482 | 0 | ConsumeToken(); |
7483 | 0 | Actions.CorrectDelayedTyposInExpr( |
7484 | 0 | ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true)); |
7485 | 0 | } |
7486 | | |
7487 | | // Remember this parsed parameter in ParamInfo. |
7488 | 74 | IdentifierInfo *ParmII = ParmDeclarator.getIdentifier(); |
7489 | | |
7490 | | // DefArgToks is used when the parsing of default arguments needs |
7491 | | // to be delayed. |
7492 | 74 | std::unique_ptr<CachedTokens> DefArgToks; |
7493 | | |
7494 | | // If no parameter was specified, verify that *something* was specified, |
7495 | | // otherwise we have a missing type and identifier. |
7496 | 74 | if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr && |
7497 | 74 | ParmDeclarator.getNumTypeObjects() == 0) { |
7498 | | // Completely missing, emit error. |
7499 | 34 | Diag(DSStart, diag::err_missing_param); |
7500 | 40 | } else { |
7501 | | // Otherwise, we have something. Add it and let semantic analysis try |
7502 | | // to grok it and add the result to the ParamInfo we are building. |
7503 | | |
7504 | | // Last chance to recover from a misplaced ellipsis in an attempted |
7505 | | // parameter pack declaration. |
7506 | 40 | if (Tok.is(tok::ellipsis) && |
7507 | 40 | (NextToken().isNot(tok::r_paren) || |
7508 | 0 | (!ParmDeclarator.getEllipsisLoc().isValid() && |
7509 | 0 | !Actions.isUnexpandedParameterPackPermitted())) && |
7510 | 40 | Actions.containsUnexpandedParameterPacks(ParmDeclarator)) |
7511 | 0 | DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator); |
7512 | | |
7513 | | // Now we are at the point where declarator parsing is finished. |
7514 | | // |
7515 | | // Try to catch keywords in place of the identifier in a declarator, and |
7516 | | // in particular the common case where: |
7517 | | // 1 identifier comes at the end of the declarator |
7518 | | // 2 if the identifier is dropped, the declarator is valid but anonymous |
7519 | | // (no identifier) |
7520 | | // 3 declarator parsing succeeds, and then we have a trailing keyword, |
7521 | | // which is never valid in a param list (e.g. missing a ',') |
7522 | | // And we can't handle this in ParseDeclarator because in general keywords |
7523 | | // may be allowed to follow the declarator. (And in some cases there'd be |
7524 | | // better recovery like inserting punctuation). ParseDeclarator is just |
7525 | | // treating this as an anonymous parameter, and fortunately at this point |
7526 | | // we've already almost done that. |
7527 | | // |
7528 | | // We care about case 1) where the declarator type should be known, and |
7529 | | // the identifier should be null. |
7530 | 40 | if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName() && |
7531 | 40 | Tok.isNot(tok::raw_identifier) && !Tok.isAnnotation() && |
7532 | 40 | Tok.getIdentifierInfo() && |
7533 | 40 | Tok.getIdentifierInfo()->isKeyword(getLangOpts())) { |
7534 | 0 | Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok); |
7535 | | // Consume the keyword. |
7536 | 0 | ConsumeToken(); |
7537 | 0 | } |
7538 | | // Inform the actions module about the parameter declarator, so it gets |
7539 | | // added to the current scope. |
7540 | 40 | Decl *Param = |
7541 | 40 | Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ThisLoc); |
7542 | | // Parse the default argument, if any. We parse the default |
7543 | | // arguments in all dialects; the semantic analysis in |
7544 | | // ActOnParamDefaultArgument will reject the default argument in |
7545 | | // C. |
7546 | 40 | if (Tok.is(tok::equal)) { |
7547 | 1 | SourceLocation EqualLoc = Tok.getLocation(); |
7548 | | |
7549 | | // Parse the default argument |
7550 | 1 | if (DeclaratorCtx == DeclaratorContext::Member) { |
7551 | | // If we're inside a class definition, cache the tokens |
7552 | | // corresponding to the default argument. We'll actually parse |
7553 | | // them when we see the end of the class definition. |
7554 | 0 | DefArgToks.reset(new CachedTokens); |
7555 | |
|
7556 | 0 | SourceLocation ArgStartLoc = NextToken().getLocation(); |
7557 | 0 | ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument); |
7558 | 0 | Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc, |
7559 | 0 | ArgStartLoc); |
7560 | 1 | } else { |
7561 | | // Consume the '='. |
7562 | 1 | ConsumeToken(); |
7563 | | |
7564 | | // The argument isn't actually potentially evaluated unless it is |
7565 | | // used. |
7566 | 1 | EnterExpressionEvaluationContext Eval( |
7567 | 1 | Actions, |
7568 | 1 | Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, |
7569 | 1 | Param); |
7570 | | |
7571 | 1 | ExprResult DefArgResult; |
7572 | 1 | if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { |
7573 | 0 | Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); |
7574 | 0 | DefArgResult = ParseBraceInitializer(); |
7575 | 1 | } else { |
7576 | 1 | if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) { |
7577 | 0 | Diag(Tok, diag::err_stmt_expr_in_default_arg) << 0; |
7578 | 0 | Actions.ActOnParamDefaultArgumentError(Param, EqualLoc, |
7579 | 0 | /*DefaultArg=*/nullptr); |
7580 | | // Skip the statement expression and continue parsing |
7581 | 0 | SkipUntil(tok::comma, StopBeforeMatch); |
7582 | 0 | continue; |
7583 | 0 | } |
7584 | 1 | DefArgResult = ParseAssignmentExpression(); |
7585 | 1 | } |
7586 | 1 | DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult); |
7587 | 1 | if (DefArgResult.isInvalid()) { |
7588 | 1 | Actions.ActOnParamDefaultArgumentError(Param, EqualLoc, |
7589 | 1 | /*DefaultArg=*/nullptr); |
7590 | 1 | SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); |
7591 | 1 | } else { |
7592 | | // Inform the actions module about the default argument |
7593 | 0 | Actions.ActOnParamDefaultArgument(Param, EqualLoc, |
7594 | 0 | DefArgResult.get()); |
7595 | 0 | } |
7596 | 1 | } |
7597 | 1 | } |
7598 | | |
7599 | 40 | ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, |
7600 | 40 | ParmDeclarator.getIdentifierLoc(), |
7601 | 40 | Param, std::move(DefArgToks))); |
7602 | 40 | } |
7603 | | |
7604 | 74 | if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { |
7605 | 0 | if (!getLangOpts().CPlusPlus) { |
7606 | | // We have ellipsis without a preceding ',', which is ill-formed |
7607 | | // in C. Complain and provide the fix. |
7608 | 0 | Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis) |
7609 | 0 | << FixItHint::CreateInsertion(EllipsisLoc, ", "); |
7610 | 0 | } else if (ParmDeclarator.getEllipsisLoc().isValid() || |
7611 | 0 | Actions.containsUnexpandedParameterPacks(ParmDeclarator)) { |
7612 | | // It looks like this was supposed to be a parameter pack. Warn and |
7613 | | // point out where the ellipsis should have gone. |
7614 | 0 | SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc(); |
7615 | 0 | Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg) |
7616 | 0 | << ParmEllipsis.isValid() << ParmEllipsis; |
7617 | 0 | if (ParmEllipsis.isValid()) { |
7618 | 0 | Diag(ParmEllipsis, |
7619 | 0 | diag::note_misplaced_ellipsis_vararg_existing_ellipsis); |
7620 | 0 | } else { |
7621 | 0 | Diag(ParmDeclarator.getIdentifierLoc(), |
7622 | 0 | diag::note_misplaced_ellipsis_vararg_add_ellipsis) |
7623 | 0 | << FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(), |
7624 | 0 | "...") |
7625 | 0 | << !ParmDeclarator.hasName(); |
7626 | 0 | } |
7627 | 0 | Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma) |
7628 | 0 | << FixItHint::CreateInsertion(EllipsisLoc, ", "); |
7629 | 0 | } |
7630 | | |
7631 | | // We can't have any more parameters after an ellipsis. |
7632 | 0 | break; |
7633 | 0 | } |
7634 | | |
7635 | | // If the next token is a comma, consume it and keep reading arguments. |
7636 | 74 | } while (TryConsumeToken(tok::comma)); |
7637 | 73 | } |
7638 | | |
7639 | | /// [C90] direct-declarator '[' constant-expression[opt] ']' |
7640 | | /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']' |
7641 | | /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']' |
7642 | | /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']' |
7643 | | /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']' |
7644 | | /// [C++11] direct-declarator '[' constant-expression[opt] ']' |
7645 | | /// attribute-specifier-seq[opt] |
7646 | 335 | void Parser::ParseBracketDeclarator(Declarator &D) { |
7647 | 335 | if (CheckProhibitedCXX11Attribute()) |
7648 | 0 | return; |
7649 | | |
7650 | 335 | BalancedDelimiterTracker T(*this, tok::l_square); |
7651 | 335 | T.consumeOpen(); |
7652 | | |
7653 | | // C array syntax has many features, but by-far the most common is [] and [4]. |
7654 | | // This code does a fast path to handle some of the most obvious cases. |
7655 | 335 | if (Tok.getKind() == tok::r_square) { |
7656 | 0 | T.consumeClose(); |
7657 | 0 | ParsedAttributes attrs(AttrFactory); |
7658 | 0 | MaybeParseCXX11Attributes(attrs); |
7659 | | |
7660 | | // Remember that we parsed the empty array type. |
7661 | 0 | D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr, |
7662 | 0 | T.getOpenLocation(), |
7663 | 0 | T.getCloseLocation()), |
7664 | 0 | std::move(attrs), T.getCloseLocation()); |
7665 | 0 | return; |
7666 | 335 | } else if (Tok.getKind() == tok::numeric_constant && |
7667 | 335 | GetLookAheadToken(1).is(tok::r_square)) { |
7668 | | // [4] is very common. Parse the numeric constant expression. |
7669 | 1 | ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope())); |
7670 | 1 | ConsumeToken(); |
7671 | | |
7672 | 1 | T.consumeClose(); |
7673 | 1 | ParsedAttributes attrs(AttrFactory); |
7674 | 1 | MaybeParseCXX11Attributes(attrs); |
7675 | | |
7676 | | // Remember that we parsed a array type, and remember its features. |
7677 | 1 | D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(), |
7678 | 1 | T.getOpenLocation(), |
7679 | 1 | T.getCloseLocation()), |
7680 | 1 | std::move(attrs), T.getCloseLocation()); |
7681 | 1 | return; |
7682 | 334 | } else if (Tok.getKind() == tok::code_completion) { |
7683 | 0 | cutOffParsing(); |
7684 | 0 | Actions.CodeCompleteBracketDeclarator(getCurScope()); |
7685 | 0 | return; |
7686 | 0 | } |
7687 | | |
7688 | | // If valid, this location is the position where we read the 'static' keyword. |
7689 | 334 | SourceLocation StaticLoc; |
7690 | 334 | TryConsumeToken(tok::kw_static, StaticLoc); |
7691 | | |
7692 | | // If there is a type-qualifier-list, read it now. |
7693 | | // Type qualifiers in an array subscript are a C99 feature. |
7694 | 334 | DeclSpec DS(AttrFactory); |
7695 | 334 | ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed); |
7696 | | |
7697 | | // If we haven't already read 'static', check to see if there is one after the |
7698 | | // type-qualifier-list. |
7699 | 334 | if (!StaticLoc.isValid()) |
7700 | 334 | TryConsumeToken(tok::kw_static, StaticLoc); |
7701 | | |
7702 | | // Handle "direct-declarator [ type-qual-list[opt] * ]". |
7703 | 334 | bool isStar = false; |
7704 | 334 | ExprResult NumElements; |
7705 | | |
7706 | | // Handle the case where we have '[*]' as the array size. However, a leading |
7707 | | // star could be the start of an expression, for example 'X[*p + 4]'. Verify |
7708 | | // the token after the star is a ']'. Since stars in arrays are |
7709 | | // infrequent, use of lookahead is not costly here. |
7710 | 334 | if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) { |
7711 | 0 | ConsumeToken(); // Eat the '*'. |
7712 | |
|
7713 | 0 | if (StaticLoc.isValid()) { |
7714 | 0 | Diag(StaticLoc, diag::err_unspecified_vla_size_with_static); |
7715 | 0 | StaticLoc = SourceLocation(); // Drop the static. |
7716 | 0 | } |
7717 | 0 | isStar = true; |
7718 | 334 | } else if (Tok.isNot(tok::r_square)) { |
7719 | | // Note, in C89, this production uses the constant-expr production instead |
7720 | | // of assignment-expr. The only difference is that assignment-expr allows |
7721 | | // things like '=' and '*='. Sema rejects these in C89 mode because they |
7722 | | // are not i-c-e's, so we don't need to distinguish between the two here. |
7723 | | |
7724 | | // Parse the constant-expression or assignment-expression now (depending |
7725 | | // on dialect). |
7726 | 334 | if (getLangOpts().CPlusPlus) { |
7727 | 173 | NumElements = ParseArrayBoundExpression(); |
7728 | 173 | } else { |
7729 | 161 | EnterExpressionEvaluationContext Unevaluated( |
7730 | 161 | Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); |
7731 | 161 | NumElements = |
7732 | 161 | Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); |
7733 | 161 | } |
7734 | 334 | } else { |
7735 | 0 | if (StaticLoc.isValid()) { |
7736 | 0 | Diag(StaticLoc, diag::err_unspecified_size_with_static); |
7737 | 0 | StaticLoc = SourceLocation(); // Drop the static. |
7738 | 0 | } |
7739 | 0 | } |
7740 | | |
7741 | | // If there was an error parsing the assignment-expression, recover. |
7742 | 334 | if (NumElements.isInvalid()) { |
7743 | 255 | D.setInvalidType(true); |
7744 | | // If the expression was invalid, skip it. |
7745 | 255 | SkipUntil(tok::r_square, StopAtSemi); |
7746 | 255 | return; |
7747 | 255 | } |
7748 | | |
7749 | 79 | T.consumeClose(); |
7750 | | |
7751 | 79 | MaybeParseCXX11Attributes(DS.getAttributes()); |
7752 | | |
7753 | | // Remember that we parsed a array type, and remember its features. |
7754 | 79 | D.AddTypeInfo( |
7755 | 79 | DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), |
7756 | 79 | isStar, NumElements.get(), T.getOpenLocation(), |
7757 | 79 | T.getCloseLocation()), |
7758 | 79 | std::move(DS.getAttributes()), T.getCloseLocation()); |
7759 | 79 | } |
7760 | | |
7761 | | /// Diagnose brackets before an identifier. |
7762 | 181 | void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { |
7763 | 181 | assert(Tok.is(tok::l_square) && "Missing opening bracket"); |
7764 | 0 | assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier"); |
7765 | | |
7766 | 0 | SourceLocation StartBracketLoc = Tok.getLocation(); |
7767 | 181 | Declarator TempDeclarator(D.getDeclSpec(), ParsedAttributesView::none(), |
7768 | 181 | D.getContext()); |
7769 | | |
7770 | 362 | while (Tok.is(tok::l_square)) { |
7771 | 181 | ParseBracketDeclarator(TempDeclarator); |
7772 | 181 | } |
7773 | | |
7774 | | // Stuff the location of the start of the brackets into the Declarator. |
7775 | | // The diagnostics from ParseDirectDeclarator will make more sense if |
7776 | | // they use this location instead. |
7777 | 181 | if (Tok.is(tok::semi)) |
7778 | 68 | D.getName().EndLocation = StartBracketLoc; |
7779 | | |
7780 | 181 | SourceLocation SuggestParenLoc = Tok.getLocation(); |
7781 | | |
7782 | | // Now that the brackets are removed, try parsing the declarator again. |
7783 | 181 | ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); |
7784 | | |
7785 | | // Something went wrong parsing the brackets, in which case, |
7786 | | // ParseBracketDeclarator has emitted an error, and we don't need to emit |
7787 | | // one here. |
7788 | 181 | if (TempDeclarator.getNumTypeObjects() == 0) |
7789 | 142 | return; |
7790 | | |
7791 | | // Determine if parens will need to be suggested in the diagnostic. |
7792 | 39 | bool NeedParens = false; |
7793 | 39 | if (D.getNumTypeObjects() != 0) { |
7794 | 0 | switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) { |
7795 | 0 | case DeclaratorChunk::Pointer: |
7796 | 0 | case DeclaratorChunk::Reference: |
7797 | 0 | case DeclaratorChunk::BlockPointer: |
7798 | 0 | case DeclaratorChunk::MemberPointer: |
7799 | 0 | case DeclaratorChunk::Pipe: |
7800 | 0 | NeedParens = true; |
7801 | 0 | break; |
7802 | 0 | case DeclaratorChunk::Array: |
7803 | 0 | case DeclaratorChunk::Function: |
7804 | 0 | case DeclaratorChunk::Paren: |
7805 | 0 | break; |
7806 | 0 | } |
7807 | 0 | } |
7808 | | |
7809 | 39 | if (NeedParens) { |
7810 | | // Create a DeclaratorChunk for the inserted parens. |
7811 | 0 | SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc()); |
7812 | 0 | D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), |
7813 | 0 | SourceLocation()); |
7814 | 0 | } |
7815 | | |
7816 | | // Adding back the bracket info to the end of the Declarator. |
7817 | 78 | for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) { |
7818 | 39 | const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i); |
7819 | 39 | D.AddTypeInfo(Chunk, SourceLocation()); |
7820 | 39 | } |
7821 | | |
7822 | | // The missing identifier would have been diagnosed in ParseDirectDeclarator. |
7823 | | // If parentheses are required, always suggest them. |
7824 | 39 | if (!D.getIdentifier() && !NeedParens) |
7825 | 32 | return; |
7826 | | |
7827 | 7 | SourceLocation EndBracketLoc = TempDeclarator.getEndLoc(); |
7828 | | |
7829 | | // Generate the move bracket error message. |
7830 | 7 | SourceRange BracketRange(StartBracketLoc, EndBracketLoc); |
7831 | 7 | SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc()); |
7832 | | |
7833 | 7 | if (NeedParens) { |
7834 | 0 | Diag(EndLoc, diag::err_brackets_go_after_unqualified_id) |
7835 | 0 | << getLangOpts().CPlusPlus |
7836 | 0 | << FixItHint::CreateInsertion(SuggestParenLoc, "(") |
7837 | 0 | << FixItHint::CreateInsertion(EndLoc, ")") |
7838 | 0 | << FixItHint::CreateInsertionFromRange( |
7839 | 0 | EndLoc, CharSourceRange(BracketRange, true)) |
7840 | 0 | << FixItHint::CreateRemoval(BracketRange); |
7841 | 7 | } else { |
7842 | 7 | Diag(EndLoc, diag::err_brackets_go_after_unqualified_id) |
7843 | 7 | << getLangOpts().CPlusPlus |
7844 | 7 | << FixItHint::CreateInsertionFromRange( |
7845 | 7 | EndLoc, CharSourceRange(BracketRange, true)) |
7846 | 7 | << FixItHint::CreateRemoval(BracketRange); |
7847 | 7 | } |
7848 | 7 | } |
7849 | | |
7850 | | /// [GNU] typeof-specifier: |
7851 | | /// typeof ( expressions ) |
7852 | | /// typeof ( type-name ) |
7853 | | /// [GNU/C++] typeof unary-expression |
7854 | | /// [C23] typeof-specifier: |
7855 | | /// typeof '(' typeof-specifier-argument ')' |
7856 | | /// typeof_unqual '(' typeof-specifier-argument ')' |
7857 | | /// |
7858 | | /// typeof-specifier-argument: |
7859 | | /// expression |
7860 | | /// type-name |
7861 | | /// |
7862 | 0 | void Parser::ParseTypeofSpecifier(DeclSpec &DS) { |
7863 | 0 | assert(Tok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) && |
7864 | 0 | "Not a typeof specifier"); |
7865 | | |
7866 | 0 | bool IsUnqual = Tok.is(tok::kw_typeof_unqual); |
7867 | 0 | const IdentifierInfo *II = Tok.getIdentifierInfo(); |
7868 | 0 | if (getLangOpts().C23 && !II->getName().starts_with("__")) |
7869 | 0 | Diag(Tok.getLocation(), diag::warn_c23_compat_keyword) << Tok.getName(); |
7870 | |
|
7871 | 0 | Token OpTok = Tok; |
7872 | 0 | SourceLocation StartLoc = ConsumeToken(); |
7873 | 0 | bool HasParens = Tok.is(tok::l_paren); |
7874 | |
|
7875 | 0 | EnterExpressionEvaluationContext Unevaluated( |
7876 | 0 | Actions, Sema::ExpressionEvaluationContext::Unevaluated, |
7877 | 0 | Sema::ReuseLambdaContextDecl); |
7878 | |
|
7879 | 0 | bool isCastExpr; |
7880 | 0 | ParsedType CastTy; |
7881 | 0 | SourceRange CastRange; |
7882 | 0 | ExprResult Operand = Actions.CorrectDelayedTyposInExpr( |
7883 | 0 | ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange)); |
7884 | 0 | if (HasParens) |
7885 | 0 | DS.setTypeArgumentRange(CastRange); |
7886 | |
|
7887 | 0 | if (CastRange.getEnd().isInvalid()) |
7888 | | // FIXME: Not accurate, the range gets one token more than it should. |
7889 | 0 | DS.SetRangeEnd(Tok.getLocation()); |
7890 | 0 | else |
7891 | 0 | DS.SetRangeEnd(CastRange.getEnd()); |
7892 | |
|
7893 | 0 | if (isCastExpr) { |
7894 | 0 | if (!CastTy) { |
7895 | 0 | DS.SetTypeSpecError(); |
7896 | 0 | return; |
7897 | 0 | } |
7898 | | |
7899 | 0 | const char *PrevSpec = nullptr; |
7900 | 0 | unsigned DiagID; |
7901 | | // Check for duplicate type specifiers (e.g. "int typeof(int)"). |
7902 | 0 | if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualType |
7903 | 0 | : DeclSpec::TST_typeofType, |
7904 | 0 | StartLoc, PrevSpec, |
7905 | 0 | DiagID, CastTy, |
7906 | 0 | Actions.getASTContext().getPrintingPolicy())) |
7907 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
7908 | 0 | return; |
7909 | 0 | } |
7910 | | |
7911 | | // If we get here, the operand to the typeof was an expression. |
7912 | 0 | if (Operand.isInvalid()) { |
7913 | 0 | DS.SetTypeSpecError(); |
7914 | 0 | return; |
7915 | 0 | } |
7916 | | |
7917 | | // We might need to transform the operand if it is potentially evaluated. |
7918 | 0 | Operand = Actions.HandleExprEvaluationContextForTypeof(Operand.get()); |
7919 | 0 | if (Operand.isInvalid()) { |
7920 | 0 | DS.SetTypeSpecError(); |
7921 | 0 | return; |
7922 | 0 | } |
7923 | | |
7924 | 0 | const char *PrevSpec = nullptr; |
7925 | 0 | unsigned DiagID; |
7926 | | // Check for duplicate type specifiers (e.g. "int typeof(int)"). |
7927 | 0 | if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualExpr |
7928 | 0 | : DeclSpec::TST_typeofExpr, |
7929 | 0 | StartLoc, PrevSpec, |
7930 | 0 | DiagID, Operand.get(), |
7931 | 0 | Actions.getASTContext().getPrintingPolicy())) |
7932 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
7933 | 0 | } |
7934 | | |
7935 | | /// [C11] atomic-specifier: |
7936 | | /// _Atomic ( type-name ) |
7937 | | /// |
7938 | 0 | void Parser::ParseAtomicSpecifier(DeclSpec &DS) { |
7939 | 0 | assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) && |
7940 | 0 | "Not an atomic specifier"); |
7941 | | |
7942 | 0 | SourceLocation StartLoc = ConsumeToken(); |
7943 | 0 | BalancedDelimiterTracker T(*this, tok::l_paren); |
7944 | 0 | if (T.consumeOpen()) |
7945 | 0 | return; |
7946 | | |
7947 | 0 | TypeResult Result = ParseTypeName(); |
7948 | 0 | if (Result.isInvalid()) { |
7949 | 0 | SkipUntil(tok::r_paren, StopAtSemi); |
7950 | 0 | return; |
7951 | 0 | } |
7952 | | |
7953 | | // Match the ')' |
7954 | 0 | T.consumeClose(); |
7955 | |
|
7956 | 0 | if (T.getCloseLocation().isInvalid()) |
7957 | 0 | return; |
7958 | | |
7959 | 0 | DS.setTypeArgumentRange(T.getRange()); |
7960 | 0 | DS.SetRangeEnd(T.getCloseLocation()); |
7961 | |
|
7962 | 0 | const char *PrevSpec = nullptr; |
7963 | 0 | unsigned DiagID; |
7964 | 0 | if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec, |
7965 | 0 | DiagID, Result.get(), |
7966 | 0 | Actions.getASTContext().getPrintingPolicy())) |
7967 | 0 | Diag(StartLoc, DiagID) << PrevSpec; |
7968 | 0 | } |
7969 | | |
7970 | | /// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called |
7971 | | /// from TryAltiVecVectorToken. |
7972 | 0 | bool Parser::TryAltiVecVectorTokenOutOfLine() { |
7973 | 0 | Token Next = NextToken(); |
7974 | 0 | switch (Next.getKind()) { |
7975 | 0 | default: return false; |
7976 | 0 | case tok::kw_short: |
7977 | 0 | case tok::kw_long: |
7978 | 0 | case tok::kw_signed: |
7979 | 0 | case tok::kw_unsigned: |
7980 | 0 | case tok::kw_void: |
7981 | 0 | case tok::kw_char: |
7982 | 0 | case tok::kw_int: |
7983 | 0 | case tok::kw_float: |
7984 | 0 | case tok::kw_double: |
7985 | 0 | case tok::kw_bool: |
7986 | 0 | case tok::kw__Bool: |
7987 | 0 | case tok::kw___bool: |
7988 | 0 | case tok::kw___pixel: |
7989 | 0 | Tok.setKind(tok::kw___vector); |
7990 | 0 | return true; |
7991 | 0 | case tok::identifier: |
7992 | 0 | if (Next.getIdentifierInfo() == Ident_pixel) { |
7993 | 0 | Tok.setKind(tok::kw___vector); |
7994 | 0 | return true; |
7995 | 0 | } |
7996 | 0 | if (Next.getIdentifierInfo() == Ident_bool || |
7997 | 0 | Next.getIdentifierInfo() == Ident_Bool) { |
7998 | 0 | Tok.setKind(tok::kw___vector); |
7999 | 0 | return true; |
8000 | 0 | } |
8001 | 0 | return false; |
8002 | 0 | } |
8003 | 0 | } |
8004 | | |
8005 | | bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, |
8006 | | const char *&PrevSpec, unsigned &DiagID, |
8007 | 0 | bool &isInvalid) { |
8008 | 0 | const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); |
8009 | 0 | if (Tok.getIdentifierInfo() == Ident_vector) { |
8010 | 0 | Token Next = NextToken(); |
8011 | 0 | switch (Next.getKind()) { |
8012 | 0 | case tok::kw_short: |
8013 | 0 | case tok::kw_long: |
8014 | 0 | case tok::kw_signed: |
8015 | 0 | case tok::kw_unsigned: |
8016 | 0 | case tok::kw_void: |
8017 | 0 | case tok::kw_char: |
8018 | 0 | case tok::kw_int: |
8019 | 0 | case tok::kw_float: |
8020 | 0 | case tok::kw_double: |
8021 | 0 | case tok::kw_bool: |
8022 | 0 | case tok::kw__Bool: |
8023 | 0 | case tok::kw___bool: |
8024 | 0 | case tok::kw___pixel: |
8025 | 0 | isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); |
8026 | 0 | return true; |
8027 | 0 | case tok::identifier: |
8028 | 0 | if (Next.getIdentifierInfo() == Ident_pixel) { |
8029 | 0 | isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy); |
8030 | 0 | return true; |
8031 | 0 | } |
8032 | 0 | if (Next.getIdentifierInfo() == Ident_bool || |
8033 | 0 | Next.getIdentifierInfo() == Ident_Bool) { |
8034 | 0 | isInvalid = |
8035 | 0 | DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); |
8036 | 0 | return true; |
8037 | 0 | } |
8038 | 0 | break; |
8039 | 0 | default: |
8040 | 0 | break; |
8041 | 0 | } |
8042 | 0 | } else if ((Tok.getIdentifierInfo() == Ident_pixel) && |
8043 | 0 | DS.isTypeAltiVecVector()) { |
8044 | 0 | isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy); |
8045 | 0 | return true; |
8046 | 0 | } else if ((Tok.getIdentifierInfo() == Ident_bool) && |
8047 | 0 | DS.isTypeAltiVecVector()) { |
8048 | 0 | isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy); |
8049 | 0 | return true; |
8050 | 0 | } |
8051 | 0 | return false; |
8052 | 0 | } |
8053 | | |
8054 | 0 | void Parser::DiagnoseBitIntUse(const Token &Tok) { |
8055 | | // If the token is for _ExtInt, diagnose it as being deprecated. Otherwise, |
8056 | | // the token is about _BitInt and gets (potentially) diagnosed as use of an |
8057 | | // extension. |
8058 | 0 | assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) && |
8059 | 0 | "expected either an _ExtInt or _BitInt token!"); |
8060 | | |
8061 | 0 | SourceLocation Loc = Tok.getLocation(); |
8062 | 0 | if (Tok.is(tok::kw__ExtInt)) { |
8063 | 0 | Diag(Loc, diag::warn_ext_int_deprecated) |
8064 | 0 | << FixItHint::CreateReplacement(Loc, "_BitInt"); |
8065 | 0 | } else { |
8066 | | // In C23 mode, diagnose that the use is not compatible with pre-C23 modes. |
8067 | | // Otherwise, diagnose that the use is a Clang extension. |
8068 | 0 | if (getLangOpts().C23) |
8069 | 0 | Diag(Loc, diag::warn_c23_compat_keyword) << Tok.getName(); |
8070 | 0 | else |
8071 | 0 | Diag(Loc, diag::ext_bit_int) << getLangOpts().CPlusPlus; |
8072 | 0 | } |
8073 | 0 | } |