1e5dd7070Spatrick //===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the Declaration portions of the Parser interfaces.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "clang/AST/ASTContext.h"
14e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
15e5dd7070Spatrick #include "clang/AST/PrettyDeclStackTrace.h"
16e5dd7070Spatrick #include "clang/Basic/AddressSpaces.h"
17*12c85518Srobert #include "clang/Basic/AttributeCommonInfo.h"
18e5dd7070Spatrick #include "clang/Basic/Attributes.h"
19e5dd7070Spatrick #include "clang/Basic/CharInfo.h"
20e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
21e5dd7070Spatrick #include "clang/Parse/ParseDiagnostic.h"
22*12c85518Srobert #include "clang/Parse/Parser.h"
23*12c85518Srobert #include "clang/Parse/RAIIObjectsForParser.h"
24e5dd7070Spatrick #include "clang/Sema/Lookup.h"
25e5dd7070Spatrick #include "clang/Sema/ParsedTemplate.h"
26e5dd7070Spatrick #include "clang/Sema/Scope.h"
27a9ac8606Spatrick #include "clang/Sema/SemaDiagnostic.h"
28e5dd7070Spatrick #include "llvm/ADT/SmallSet.h"
29e5dd7070Spatrick #include "llvm/ADT/SmallString.h"
30e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
31*12c85518Srobert #include <optional>
32e5dd7070Spatrick
33e5dd7070Spatrick using namespace clang;
34e5dd7070Spatrick
35e5dd7070Spatrick //===----------------------------------------------------------------------===//
36e5dd7070Spatrick // C99 6.7: Declarations.
37e5dd7070Spatrick //===----------------------------------------------------------------------===//
38e5dd7070Spatrick
39e5dd7070Spatrick /// ParseTypeName
40e5dd7070Spatrick /// type-name: [C99 6.7.6]
41e5dd7070Spatrick /// specifier-qualifier-list abstract-declarator[opt]
42e5dd7070Spatrick ///
43e5dd7070Spatrick /// Called type-id in C++.
ParseTypeName(SourceRange * Range,DeclaratorContext Context,AccessSpecifier AS,Decl ** OwnedType,ParsedAttributes * Attrs)44*12c85518Srobert TypeResult Parser::ParseTypeName(SourceRange *Range, DeclaratorContext Context,
45*12c85518Srobert AccessSpecifier AS, Decl **OwnedType,
46e5dd7070Spatrick ParsedAttributes *Attrs) {
47e5dd7070Spatrick DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
48e5dd7070Spatrick if (DSC == DeclSpecContext::DSC_normal)
49e5dd7070Spatrick DSC = DeclSpecContext::DSC_type_specifier;
50e5dd7070Spatrick
51e5dd7070Spatrick // Parse the common declaration-specifiers piece.
52e5dd7070Spatrick DeclSpec DS(AttrFactory);
53e5dd7070Spatrick if (Attrs)
54e5dd7070Spatrick DS.addAttributes(*Attrs);
55e5dd7070Spatrick ParseSpecifierQualifierList(DS, AS, DSC);
56e5dd7070Spatrick if (OwnedType)
57e5dd7070Spatrick *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;
58e5dd7070Spatrick
59e5dd7070Spatrick // Parse the abstract-declarator, if present.
60*12c85518Srobert Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
61e5dd7070Spatrick ParseDeclarator(DeclaratorInfo);
62e5dd7070Spatrick if (Range)
63e5dd7070Spatrick *Range = DeclaratorInfo.getSourceRange();
64e5dd7070Spatrick
65e5dd7070Spatrick if (DeclaratorInfo.isInvalidType())
66e5dd7070Spatrick return true;
67e5dd7070Spatrick
68e5dd7070Spatrick return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
69e5dd7070Spatrick }
70e5dd7070Spatrick
71e5dd7070Spatrick /// Normalizes an attribute name by dropping prefixed and suffixed __.
normalizeAttrName(StringRef Name)72e5dd7070Spatrick static StringRef normalizeAttrName(StringRef Name) {
73e5dd7070Spatrick if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
74e5dd7070Spatrick return Name.drop_front(2).drop_back(2);
75e5dd7070Spatrick return Name;
76e5dd7070Spatrick }
77e5dd7070Spatrick
78e5dd7070Spatrick /// isAttributeLateParsed - Return true if the attribute has arguments that
79e5dd7070Spatrick /// require late parsing.
isAttributeLateParsed(const IdentifierInfo & II)80e5dd7070Spatrick static bool isAttributeLateParsed(const IdentifierInfo &II) {
81e5dd7070Spatrick #define CLANG_ATTR_LATE_PARSED_LIST
82e5dd7070Spatrick return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
83e5dd7070Spatrick #include "clang/Parse/AttrParserStringSwitches.inc"
84e5dd7070Spatrick .Default(false);
85e5dd7070Spatrick #undef CLANG_ATTR_LATE_PARSED_LIST
86e5dd7070Spatrick }
87e5dd7070Spatrick
88e5dd7070Spatrick /// Check if the a start and end source location expand to the same macro.
FindLocsWithCommonFileID(Preprocessor & PP,SourceLocation StartLoc,SourceLocation EndLoc)89e5dd7070Spatrick static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc,
90e5dd7070Spatrick SourceLocation EndLoc) {
91e5dd7070Spatrick if (!StartLoc.isMacroID() || !EndLoc.isMacroID())
92e5dd7070Spatrick return false;
93e5dd7070Spatrick
94e5dd7070Spatrick SourceManager &SM = PP.getSourceManager();
95e5dd7070Spatrick if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc))
96e5dd7070Spatrick return false;
97e5dd7070Spatrick
98e5dd7070Spatrick bool AttrStartIsInMacro =
99e5dd7070Spatrick Lexer::isAtStartOfMacroExpansion(StartLoc, SM, PP.getLangOpts());
100e5dd7070Spatrick bool AttrEndIsInMacro =
101e5dd7070Spatrick Lexer::isAtEndOfMacroExpansion(EndLoc, SM, PP.getLangOpts());
102e5dd7070Spatrick return AttrStartIsInMacro && AttrEndIsInMacro;
103e5dd7070Spatrick }
104e5dd7070Spatrick
ParseAttributes(unsigned WhichAttrKinds,ParsedAttributes & Attrs,LateParsedAttrList * LateAttrs)105*12c85518Srobert void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
106a9ac8606Spatrick LateParsedAttrList *LateAttrs) {
107a9ac8606Spatrick bool MoreToParse;
108a9ac8606Spatrick do {
109a9ac8606Spatrick // Assume there's nothing left to parse, but if any attributes are in fact
110a9ac8606Spatrick // parsed, loop to ensure all specified attribute combinations are parsed.
111a9ac8606Spatrick MoreToParse = false;
112a9ac8606Spatrick if (WhichAttrKinds & PAKM_CXX11)
113*12c85518Srobert MoreToParse |= MaybeParseCXX11Attributes(Attrs);
114a9ac8606Spatrick if (WhichAttrKinds & PAKM_GNU)
115*12c85518Srobert MoreToParse |= MaybeParseGNUAttributes(Attrs, LateAttrs);
116a9ac8606Spatrick if (WhichAttrKinds & PAKM_Declspec)
117*12c85518Srobert MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs);
118a9ac8606Spatrick } while (MoreToParse);
119a9ac8606Spatrick }
120a9ac8606Spatrick
121e5dd7070Spatrick /// ParseGNUAttributes - Parse a non-empty attributes list.
122e5dd7070Spatrick ///
123e5dd7070Spatrick /// [GNU] attributes:
124e5dd7070Spatrick /// attribute
125e5dd7070Spatrick /// attributes attribute
126e5dd7070Spatrick ///
127e5dd7070Spatrick /// [GNU] attribute:
128e5dd7070Spatrick /// '__attribute__' '(' '(' attribute-list ')' ')'
129e5dd7070Spatrick ///
130e5dd7070Spatrick /// [GNU] attribute-list:
131e5dd7070Spatrick /// attrib
132e5dd7070Spatrick /// attribute_list ',' attrib
133e5dd7070Spatrick ///
134e5dd7070Spatrick /// [GNU] attrib:
135e5dd7070Spatrick /// empty
136e5dd7070Spatrick /// attrib-name
137e5dd7070Spatrick /// attrib-name '(' identifier ')'
138e5dd7070Spatrick /// attrib-name '(' identifier ',' nonempty-expr-list ')'
139e5dd7070Spatrick /// attrib-name '(' argument-expression-list [C99 6.5.2] ')'
140e5dd7070Spatrick ///
141e5dd7070Spatrick /// [GNU] attrib-name:
142e5dd7070Spatrick /// identifier
143e5dd7070Spatrick /// typespec
144e5dd7070Spatrick /// typequal
145e5dd7070Spatrick /// storageclass
146e5dd7070Spatrick ///
147e5dd7070Spatrick /// Whether an attribute takes an 'identifier' is determined by the
148e5dd7070Spatrick /// attrib-name. GCC's behavior here is not worth imitating:
149e5dd7070Spatrick ///
150e5dd7070Spatrick /// * In C mode, if the attribute argument list starts with an identifier
151e5dd7070Spatrick /// followed by a ',' or an ')', and the identifier doesn't resolve to
152e5dd7070Spatrick /// a type, it is parsed as an identifier. If the attribute actually
153e5dd7070Spatrick /// wanted an expression, it's out of luck (but it turns out that no
154e5dd7070Spatrick /// attributes work that way, because C constant expressions are very
155e5dd7070Spatrick /// limited).
156e5dd7070Spatrick /// * In C++ mode, if the attribute argument list starts with an identifier,
157e5dd7070Spatrick /// and the attribute *wants* an identifier, it is parsed as an identifier.
158e5dd7070Spatrick /// At block scope, any additional tokens between the identifier and the
159e5dd7070Spatrick /// ',' or ')' are ignored, otherwise they produce a parse error.
160e5dd7070Spatrick ///
161e5dd7070Spatrick /// We follow the C++ model, but don't allow junk after the identifier.
ParseGNUAttributes(ParsedAttributes & Attrs,LateParsedAttrList * LateAttrs,Declarator * D)162*12c85518Srobert void Parser::ParseGNUAttributes(ParsedAttributes &Attrs,
163a9ac8606Spatrick LateParsedAttrList *LateAttrs, Declarator *D) {
164e5dd7070Spatrick assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
165e5dd7070Spatrick
166*12c85518Srobert SourceLocation StartLoc = Tok.getLocation();
167*12c85518Srobert SourceLocation EndLoc = StartLoc;
168a9ac8606Spatrick
169e5dd7070Spatrick while (Tok.is(tok::kw___attribute)) {
170e5dd7070Spatrick SourceLocation AttrTokLoc = ConsumeToken();
171a9ac8606Spatrick unsigned OldNumAttrs = Attrs.size();
172e5dd7070Spatrick unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0;
173e5dd7070Spatrick
174e5dd7070Spatrick if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
175e5dd7070Spatrick "attribute")) {
176e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
177e5dd7070Spatrick return;
178e5dd7070Spatrick }
179e5dd7070Spatrick if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
180e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
181e5dd7070Spatrick return;
182e5dd7070Spatrick }
183e5dd7070Spatrick // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
184e5dd7070Spatrick do {
185e5dd7070Spatrick // Eat preceeding commas to allow __attribute__((,,,foo))
186e5dd7070Spatrick while (TryConsumeToken(tok::comma))
187e5dd7070Spatrick ;
188e5dd7070Spatrick
189e5dd7070Spatrick // Expect an identifier or declaration specifier (const, int, etc.)
190e5dd7070Spatrick if (Tok.isAnnotation())
191e5dd7070Spatrick break;
192*12c85518Srobert if (Tok.is(tok::code_completion)) {
193*12c85518Srobert cutOffParsing();
194*12c85518Srobert Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
195*12c85518Srobert break;
196*12c85518Srobert }
197e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
198e5dd7070Spatrick if (!AttrName)
199e5dd7070Spatrick break;
200e5dd7070Spatrick
201e5dd7070Spatrick SourceLocation AttrNameLoc = ConsumeToken();
202e5dd7070Spatrick
203e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
204a9ac8606Spatrick Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
205e5dd7070Spatrick ParsedAttr::AS_GNU);
206e5dd7070Spatrick continue;
207e5dd7070Spatrick }
208e5dd7070Spatrick
209e5dd7070Spatrick // Handle "parameterized" attributes
210e5dd7070Spatrick if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
211*12c85518Srobert ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr,
212e5dd7070Spatrick SourceLocation(), ParsedAttr::AS_GNU, D);
213e5dd7070Spatrick continue;
214e5dd7070Spatrick }
215e5dd7070Spatrick
216e5dd7070Spatrick // Handle attributes with arguments that require late parsing.
217e5dd7070Spatrick LateParsedAttribute *LA =
218e5dd7070Spatrick new LateParsedAttribute(this, *AttrName, AttrNameLoc);
219e5dd7070Spatrick LateAttrs->push_back(LA);
220e5dd7070Spatrick
221e5dd7070Spatrick // Attributes in a class are parsed at the end of the class, along
222e5dd7070Spatrick // with other late-parsed declarations.
223e5dd7070Spatrick if (!ClassStack.empty() && !LateAttrs->parseSoon())
224e5dd7070Spatrick getCurrentClass().LateParsedDeclarations.push_back(LA);
225e5dd7070Spatrick
226e5dd7070Spatrick // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it
227e5dd7070Spatrick // recursively consumes balanced parens.
228e5dd7070Spatrick LA->Toks.push_back(Tok);
229e5dd7070Spatrick ConsumeParen();
230e5dd7070Spatrick // Consume everything up to and including the matching right parens.
231e5dd7070Spatrick ConsumeAndStoreUntil(tok::r_paren, LA->Toks, /*StopAtSemi=*/true);
232e5dd7070Spatrick
233e5dd7070Spatrick Token Eof;
234e5dd7070Spatrick Eof.startToken();
235e5dd7070Spatrick Eof.setLocation(Tok.getLocation());
236e5dd7070Spatrick LA->Toks.push_back(Eof);
237e5dd7070Spatrick } while (Tok.is(tok::comma));
238e5dd7070Spatrick
239e5dd7070Spatrick if (ExpectAndConsume(tok::r_paren))
240e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
241e5dd7070Spatrick SourceLocation Loc = Tok.getLocation();
242e5dd7070Spatrick if (ExpectAndConsume(tok::r_paren))
243e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
244*12c85518Srobert EndLoc = Loc;
245e5dd7070Spatrick
246e5dd7070Spatrick // If this was declared in a macro, attach the macro IdentifierInfo to the
247e5dd7070Spatrick // parsed attribute.
248e5dd7070Spatrick auto &SM = PP.getSourceManager();
249e5dd7070Spatrick if (!SM.isWrittenInBuiltinFile(SM.getSpellingLoc(AttrTokLoc)) &&
250e5dd7070Spatrick FindLocsWithCommonFileID(PP, AttrTokLoc, Loc)) {
251e5dd7070Spatrick CharSourceRange ExpansionRange = SM.getExpansionRange(AttrTokLoc);
252e5dd7070Spatrick StringRef FoundName =
253e5dd7070Spatrick Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts());
254e5dd7070Spatrick IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName);
255e5dd7070Spatrick
256a9ac8606Spatrick for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i)
257a9ac8606Spatrick Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin());
258e5dd7070Spatrick
259e5dd7070Spatrick if (LateAttrs) {
260e5dd7070Spatrick for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i)
261e5dd7070Spatrick (*LateAttrs)[i]->MacroII = MacroII;
262e5dd7070Spatrick }
263e5dd7070Spatrick }
264e5dd7070Spatrick }
265a9ac8606Spatrick
266*12c85518Srobert Attrs.Range = SourceRange(StartLoc, EndLoc);
267e5dd7070Spatrick }
268e5dd7070Spatrick
269e5dd7070Spatrick /// Determine whether the given attribute has an identifier argument.
attributeHasIdentifierArg(const IdentifierInfo & II)270e5dd7070Spatrick static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
271e5dd7070Spatrick #define CLANG_ATTR_IDENTIFIER_ARG_LIST
272e5dd7070Spatrick return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
273e5dd7070Spatrick #include "clang/Parse/AttrParserStringSwitches.inc"
274e5dd7070Spatrick .Default(false);
275e5dd7070Spatrick #undef CLANG_ATTR_IDENTIFIER_ARG_LIST
276e5dd7070Spatrick }
277e5dd7070Spatrick
278e5dd7070Spatrick /// Determine whether the given attribute has a variadic identifier argument.
attributeHasVariadicIdentifierArg(const IdentifierInfo & II)279e5dd7070Spatrick static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) {
280e5dd7070Spatrick #define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
281e5dd7070Spatrick return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
282e5dd7070Spatrick #include "clang/Parse/AttrParserStringSwitches.inc"
283e5dd7070Spatrick .Default(false);
284e5dd7070Spatrick #undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
285e5dd7070Spatrick }
286e5dd7070Spatrick
287e5dd7070Spatrick /// Determine whether the given attribute treats kw_this as an identifier.
attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo & II)288e5dd7070Spatrick static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) {
289e5dd7070Spatrick #define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
290e5dd7070Spatrick return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
291e5dd7070Spatrick #include "clang/Parse/AttrParserStringSwitches.inc"
292e5dd7070Spatrick .Default(false);
293e5dd7070Spatrick #undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
294e5dd7070Spatrick }
295e5dd7070Spatrick
296*12c85518Srobert /// Determine if an attribute accepts parameter packs.
attributeAcceptsExprPack(const IdentifierInfo & II)297*12c85518Srobert static bool attributeAcceptsExprPack(const IdentifierInfo &II) {
298*12c85518Srobert #define CLANG_ATTR_ACCEPTS_EXPR_PACK
299*12c85518Srobert return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
300*12c85518Srobert #include "clang/Parse/AttrParserStringSwitches.inc"
301*12c85518Srobert .Default(false);
302*12c85518Srobert #undef CLANG_ATTR_ACCEPTS_EXPR_PACK
303*12c85518Srobert }
304*12c85518Srobert
305e5dd7070Spatrick /// Determine whether the given attribute parses a type argument.
attributeIsTypeArgAttr(const IdentifierInfo & II)306e5dd7070Spatrick static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
307e5dd7070Spatrick #define CLANG_ATTR_TYPE_ARG_LIST
308e5dd7070Spatrick return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
309e5dd7070Spatrick #include "clang/Parse/AttrParserStringSwitches.inc"
310e5dd7070Spatrick .Default(false);
311e5dd7070Spatrick #undef CLANG_ATTR_TYPE_ARG_LIST
312e5dd7070Spatrick }
313e5dd7070Spatrick
314e5dd7070Spatrick /// Determine whether the given attribute requires parsing its arguments
315e5dd7070Spatrick /// in an unevaluated context or not.
attributeParsedArgsUnevaluated(const IdentifierInfo & II)316e5dd7070Spatrick static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {
317e5dd7070Spatrick #define CLANG_ATTR_ARG_CONTEXT_LIST
318e5dd7070Spatrick return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
319e5dd7070Spatrick #include "clang/Parse/AttrParserStringSwitches.inc"
320e5dd7070Spatrick .Default(false);
321e5dd7070Spatrick #undef CLANG_ATTR_ARG_CONTEXT_LIST
322e5dd7070Spatrick }
323e5dd7070Spatrick
ParseIdentifierLoc()324e5dd7070Spatrick IdentifierLoc *Parser::ParseIdentifierLoc() {
325e5dd7070Spatrick assert(Tok.is(tok::identifier) && "expected an identifier");
326e5dd7070Spatrick IdentifierLoc *IL = IdentifierLoc::create(Actions.Context,
327e5dd7070Spatrick Tok.getLocation(),
328e5dd7070Spatrick Tok.getIdentifierInfo());
329e5dd7070Spatrick ConsumeToken();
330e5dd7070Spatrick return IL;
331e5dd7070Spatrick }
332e5dd7070Spatrick
ParseAttributeWithTypeArg(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)333e5dd7070Spatrick void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
334e5dd7070Spatrick SourceLocation AttrNameLoc,
335e5dd7070Spatrick ParsedAttributes &Attrs,
336e5dd7070Spatrick IdentifierInfo *ScopeName,
337e5dd7070Spatrick SourceLocation ScopeLoc,
338e5dd7070Spatrick ParsedAttr::Syntax Syntax) {
339e5dd7070Spatrick BalancedDelimiterTracker Parens(*this, tok::l_paren);
340e5dd7070Spatrick Parens.consumeOpen();
341e5dd7070Spatrick
342e5dd7070Spatrick TypeResult T;
343e5dd7070Spatrick if (Tok.isNot(tok::r_paren))
344e5dd7070Spatrick T = ParseTypeName();
345e5dd7070Spatrick
346e5dd7070Spatrick if (Parens.consumeClose())
347e5dd7070Spatrick return;
348e5dd7070Spatrick
349e5dd7070Spatrick if (T.isInvalid())
350e5dd7070Spatrick return;
351e5dd7070Spatrick
352e5dd7070Spatrick if (T.isUsable())
353e5dd7070Spatrick Attrs.addNewTypeAttr(&AttrName,
354e5dd7070Spatrick SourceRange(AttrNameLoc, Parens.getCloseLocation()),
355e5dd7070Spatrick ScopeName, ScopeLoc, T.get(), Syntax);
356e5dd7070Spatrick else
357e5dd7070Spatrick Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
358e5dd7070Spatrick ScopeName, ScopeLoc, nullptr, 0, Syntax);
359e5dd7070Spatrick }
360e5dd7070Spatrick
ParseAttributeArgsCommon(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)361e5dd7070Spatrick unsigned Parser::ParseAttributeArgsCommon(
362e5dd7070Spatrick IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
363e5dd7070Spatrick ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
364e5dd7070Spatrick SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
365e5dd7070Spatrick // Ignore the left paren location for now.
366e5dd7070Spatrick ConsumeParen();
367e5dd7070Spatrick
368e5dd7070Spatrick bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName);
369e5dd7070Spatrick bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName);
370*12c85518Srobert bool AttributeHasVariadicIdentifierArg =
371*12c85518Srobert attributeHasVariadicIdentifierArg(*AttrName);
372e5dd7070Spatrick
373e5dd7070Spatrick // Interpret "kw_this" as an identifier if the attributed requests it.
374e5dd7070Spatrick if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
375e5dd7070Spatrick Tok.setKind(tok::identifier);
376e5dd7070Spatrick
377e5dd7070Spatrick ArgsVector ArgExprs;
378e5dd7070Spatrick if (Tok.is(tok::identifier)) {
379e5dd7070Spatrick // If this attribute wants an 'identifier' argument, make it so.
380*12c85518Srobert bool IsIdentifierArg = AttributeHasVariadicIdentifierArg ||
381*12c85518Srobert attributeHasIdentifierArg(*AttrName);
382e5dd7070Spatrick ParsedAttr::Kind AttrKind =
383e5dd7070Spatrick ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
384e5dd7070Spatrick
385e5dd7070Spatrick // If we don't know how to parse this attribute, but this is the only
386e5dd7070Spatrick // token in this argument, assume it's meant to be an identifier.
387e5dd7070Spatrick if (AttrKind == ParsedAttr::UnknownAttribute ||
388e5dd7070Spatrick AttrKind == ParsedAttr::IgnoredAttribute) {
389e5dd7070Spatrick const Token &Next = NextToken();
390e5dd7070Spatrick IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);
391e5dd7070Spatrick }
392e5dd7070Spatrick
393e5dd7070Spatrick if (IsIdentifierArg)
394e5dd7070Spatrick ArgExprs.push_back(ParseIdentifierLoc());
395e5dd7070Spatrick }
396e5dd7070Spatrick
397e5dd7070Spatrick ParsedType TheParsedType;
398e5dd7070Spatrick if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
399e5dd7070Spatrick // Eat the comma.
400e5dd7070Spatrick if (!ArgExprs.empty())
401e5dd7070Spatrick ConsumeToken();
402e5dd7070Spatrick
403e5dd7070Spatrick if (AttributeIsTypeArgAttr) {
404*12c85518Srobert // FIXME: Multiple type arguments are not implemented.
405e5dd7070Spatrick TypeResult T = ParseTypeName();
406e5dd7070Spatrick if (T.isInvalid()) {
407e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
408e5dd7070Spatrick return 0;
409e5dd7070Spatrick }
410e5dd7070Spatrick if (T.isUsable())
411e5dd7070Spatrick TheParsedType = T.get();
412*12c85518Srobert } else if (AttributeHasVariadicIdentifierArg) {
413*12c85518Srobert // Parse variadic identifier arg. This can either consume identifiers or
414*12c85518Srobert // expressions. Variadic identifier args do not support parameter packs
415*12c85518Srobert // because those are typically used for attributes with enumeration
416*12c85518Srobert // arguments, and those enumerations are not something the user could
417*12c85518Srobert // express via a pack.
418*12c85518Srobert do {
419*12c85518Srobert // Interpret "kw_this" as an identifier if the attributed requests it.
420*12c85518Srobert if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
421*12c85518Srobert Tok.setKind(tok::identifier);
422*12c85518Srobert
423*12c85518Srobert ExprResult ArgExpr;
424*12c85518Srobert if (Tok.is(tok::identifier)) {
425e5dd7070Spatrick ArgExprs.push_back(ParseIdentifierLoc());
426e5dd7070Spatrick } else {
427e5dd7070Spatrick bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
428e5dd7070Spatrick EnterExpressionEvaluationContext Unevaluated(
429e5dd7070Spatrick Actions,
430e5dd7070Spatrick Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
431e5dd7070Spatrick : Sema::ExpressionEvaluationContext::ConstantEvaluated);
432e5dd7070Spatrick
433e5dd7070Spatrick ExprResult ArgExpr(
434e5dd7070Spatrick Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
435*12c85518Srobert
436e5dd7070Spatrick if (ArgExpr.isInvalid()) {
437e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
438e5dd7070Spatrick return 0;
439e5dd7070Spatrick }
440e5dd7070Spatrick ArgExprs.push_back(ArgExpr.get());
441e5dd7070Spatrick }
442e5dd7070Spatrick // Eat the comma, move to the next argument
443e5dd7070Spatrick } while (TryConsumeToken(tok::comma));
444*12c85518Srobert } else {
445*12c85518Srobert // General case. Parse all available expressions.
446*12c85518Srobert bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
447*12c85518Srobert EnterExpressionEvaluationContext Unevaluated(
448*12c85518Srobert Actions, Uneval
449*12c85518Srobert ? Sema::ExpressionEvaluationContext::Unevaluated
450*12c85518Srobert : Sema::ExpressionEvaluationContext::ConstantEvaluated);
451*12c85518Srobert
452*12c85518Srobert ExprVector ParsedExprs;
453*12c85518Srobert if (ParseExpressionList(ParsedExprs, llvm::function_ref<void()>(),
454*12c85518Srobert /*FailImmediatelyOnInvalidExpr=*/true,
455*12c85518Srobert /*EarlyTypoCorrection=*/true)) {
456*12c85518Srobert SkipUntil(tok::r_paren, StopAtSemi);
457*12c85518Srobert return 0;
458*12c85518Srobert }
459*12c85518Srobert
460*12c85518Srobert // Pack expansion must currently be explicitly supported by an attribute.
461*12c85518Srobert for (size_t I = 0; I < ParsedExprs.size(); ++I) {
462*12c85518Srobert if (!isa<PackExpansionExpr>(ParsedExprs[I]))
463*12c85518Srobert continue;
464*12c85518Srobert
465*12c85518Srobert if (!attributeAcceptsExprPack(*AttrName)) {
466*12c85518Srobert Diag(Tok.getLocation(),
467*12c85518Srobert diag::err_attribute_argument_parm_pack_not_supported)
468*12c85518Srobert << AttrName;
469*12c85518Srobert SkipUntil(tok::r_paren, StopAtSemi);
470*12c85518Srobert return 0;
471*12c85518Srobert }
472*12c85518Srobert }
473*12c85518Srobert
474*12c85518Srobert ArgExprs.insert(ArgExprs.end(), ParsedExprs.begin(), ParsedExprs.end());
475*12c85518Srobert }
476e5dd7070Spatrick }
477e5dd7070Spatrick
478e5dd7070Spatrick SourceLocation RParen = Tok.getLocation();
479e5dd7070Spatrick if (!ExpectAndConsume(tok::r_paren)) {
480e5dd7070Spatrick SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
481e5dd7070Spatrick
482e5dd7070Spatrick if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) {
483e5dd7070Spatrick Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen),
484e5dd7070Spatrick ScopeName, ScopeLoc, TheParsedType, Syntax);
485e5dd7070Spatrick } else {
486e5dd7070Spatrick Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
487e5dd7070Spatrick ArgExprs.data(), ArgExprs.size(), Syntax);
488e5dd7070Spatrick }
489e5dd7070Spatrick }
490e5dd7070Spatrick
491e5dd7070Spatrick if (EndLoc)
492e5dd7070Spatrick *EndLoc = RParen;
493e5dd7070Spatrick
494e5dd7070Spatrick return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull());
495e5dd7070Spatrick }
496e5dd7070Spatrick
497e5dd7070Spatrick /// Parse the arguments to a parameterized GNU attribute or
498e5dd7070Spatrick /// a C++11 attribute in "gnu" namespace.
ParseGNUAttributeArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax,Declarator * D)499*12c85518Srobert void Parser::ParseGNUAttributeArgs(
500*12c85518Srobert IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
501*12c85518Srobert ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
502*12c85518Srobert SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax, Declarator *D) {
503e5dd7070Spatrick
504e5dd7070Spatrick assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
505e5dd7070Spatrick
506e5dd7070Spatrick ParsedAttr::Kind AttrKind =
507e5dd7070Spatrick ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
508e5dd7070Spatrick
509e5dd7070Spatrick if (AttrKind == ParsedAttr::AT_Availability) {
510e5dd7070Spatrick ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
511e5dd7070Spatrick ScopeLoc, Syntax);
512e5dd7070Spatrick return;
513e5dd7070Spatrick } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) {
514e5dd7070Spatrick ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
515e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
516e5dd7070Spatrick return;
517e5dd7070Spatrick } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) {
518e5dd7070Spatrick ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
519e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
520e5dd7070Spatrick return;
521a9ac8606Spatrick } else if (AttrKind == ParsedAttr::AT_SwiftNewType) {
522a9ac8606Spatrick ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
523a9ac8606Spatrick ScopeLoc, Syntax);
524a9ac8606Spatrick return;
525e5dd7070Spatrick } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {
526e5dd7070Spatrick ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
527e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
528e5dd7070Spatrick return;
529e5dd7070Spatrick } else if (attributeIsTypeArgAttr(*AttrName)) {
530*12c85518Srobert ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, ScopeName,
531e5dd7070Spatrick ScopeLoc, Syntax);
532e5dd7070Spatrick return;
533e5dd7070Spatrick }
534e5dd7070Spatrick
535e5dd7070Spatrick // These may refer to the function arguments, but need to be parsed early to
536e5dd7070Spatrick // participate in determining whether it's a redeclaration.
537*12c85518Srobert std::optional<ParseScope> PrototypeScope;
538e5dd7070Spatrick if (normalizeAttrName(AttrName->getName()) == "enable_if" &&
539e5dd7070Spatrick D && D->isFunctionDeclarator()) {
540e5dd7070Spatrick DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
541e5dd7070Spatrick PrototypeScope.emplace(this, Scope::FunctionPrototypeScope |
542e5dd7070Spatrick Scope::FunctionDeclarationScope |
543e5dd7070Spatrick Scope::DeclScope);
544e5dd7070Spatrick for (unsigned i = 0; i != FTI.NumParams; ++i) {
545e5dd7070Spatrick ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
546e5dd7070Spatrick Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
547e5dd7070Spatrick }
548e5dd7070Spatrick }
549e5dd7070Spatrick
550e5dd7070Spatrick ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
551e5dd7070Spatrick ScopeLoc, Syntax);
552e5dd7070Spatrick }
553e5dd7070Spatrick
ParseClangAttributeArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)554e5dd7070Spatrick unsigned Parser::ParseClangAttributeArgs(
555e5dd7070Spatrick IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
556e5dd7070Spatrick ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
557e5dd7070Spatrick SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
558e5dd7070Spatrick assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
559e5dd7070Spatrick
560e5dd7070Spatrick ParsedAttr::Kind AttrKind =
561e5dd7070Spatrick ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
562e5dd7070Spatrick
563e5dd7070Spatrick switch (AttrKind) {
564e5dd7070Spatrick default:
565e5dd7070Spatrick return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
566e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
567e5dd7070Spatrick case ParsedAttr::AT_ExternalSourceSymbol:
568e5dd7070Spatrick ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
569e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
570e5dd7070Spatrick break;
571e5dd7070Spatrick case ParsedAttr::AT_Availability:
572e5dd7070Spatrick ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
573e5dd7070Spatrick ScopeLoc, Syntax);
574e5dd7070Spatrick break;
575e5dd7070Spatrick case ParsedAttr::AT_ObjCBridgeRelated:
576e5dd7070Spatrick ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
577e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
578e5dd7070Spatrick break;
579a9ac8606Spatrick case ParsedAttr::AT_SwiftNewType:
580a9ac8606Spatrick ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
581a9ac8606Spatrick ScopeLoc, Syntax);
582a9ac8606Spatrick break;
583e5dd7070Spatrick case ParsedAttr::AT_TypeTagForDatatype:
584e5dd7070Spatrick ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
585e5dd7070Spatrick ScopeName, ScopeLoc, Syntax);
586e5dd7070Spatrick break;
587e5dd7070Spatrick }
588e5dd7070Spatrick return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;
589e5dd7070Spatrick }
590e5dd7070Spatrick
ParseMicrosoftDeclSpecArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs)591e5dd7070Spatrick bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
592e5dd7070Spatrick SourceLocation AttrNameLoc,
593e5dd7070Spatrick ParsedAttributes &Attrs) {
594*12c85518Srobert unsigned ExistingAttrs = Attrs.size();
595*12c85518Srobert
596e5dd7070Spatrick // If the attribute isn't known, we will not attempt to parse any
597e5dd7070Spatrick // arguments.
598*12c85518Srobert if (!hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, AttrName,
599e5dd7070Spatrick getTargetInfo(), getLangOpts())) {
600e5dd7070Spatrick // Eat the left paren, then skip to the ending right paren.
601e5dd7070Spatrick ConsumeParen();
602e5dd7070Spatrick SkipUntil(tok::r_paren);
603e5dd7070Spatrick return false;
604e5dd7070Spatrick }
605e5dd7070Spatrick
606e5dd7070Spatrick SourceLocation OpenParenLoc = Tok.getLocation();
607e5dd7070Spatrick
608e5dd7070Spatrick if (AttrName->getName() == "property") {
609e5dd7070Spatrick // The property declspec is more complex in that it can take one or two
610e5dd7070Spatrick // assignment expressions as a parameter, but the lhs of the assignment
611e5dd7070Spatrick // must be named get or put.
612e5dd7070Spatrick
613e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
614e5dd7070Spatrick T.expectAndConsume(diag::err_expected_lparen_after,
615e5dd7070Spatrick AttrName->getNameStart(), tok::r_paren);
616e5dd7070Spatrick
617e5dd7070Spatrick enum AccessorKind {
618e5dd7070Spatrick AK_Invalid = -1,
619e5dd7070Spatrick AK_Put = 0,
620e5dd7070Spatrick AK_Get = 1 // indices into AccessorNames
621e5dd7070Spatrick };
622e5dd7070Spatrick IdentifierInfo *AccessorNames[] = {nullptr, nullptr};
623e5dd7070Spatrick bool HasInvalidAccessor = false;
624e5dd7070Spatrick
625e5dd7070Spatrick // Parse the accessor specifications.
626e5dd7070Spatrick while (true) {
627e5dd7070Spatrick // Stop if this doesn't look like an accessor spec.
628e5dd7070Spatrick if (!Tok.is(tok::identifier)) {
629e5dd7070Spatrick // If the user wrote a completely empty list, use a special diagnostic.
630e5dd7070Spatrick if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
631e5dd7070Spatrick AccessorNames[AK_Put] == nullptr &&
632e5dd7070Spatrick AccessorNames[AK_Get] == nullptr) {
633e5dd7070Spatrick Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);
634e5dd7070Spatrick break;
635e5dd7070Spatrick }
636e5dd7070Spatrick
637e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor);
638e5dd7070Spatrick break;
639e5dd7070Spatrick }
640e5dd7070Spatrick
641e5dd7070Spatrick AccessorKind Kind;
642e5dd7070Spatrick SourceLocation KindLoc = Tok.getLocation();
643e5dd7070Spatrick StringRef KindStr = Tok.getIdentifierInfo()->getName();
644e5dd7070Spatrick if (KindStr == "get") {
645e5dd7070Spatrick Kind = AK_Get;
646e5dd7070Spatrick } else if (KindStr == "put") {
647e5dd7070Spatrick Kind = AK_Put;
648e5dd7070Spatrick
649e5dd7070Spatrick // Recover from the common mistake of using 'set' instead of 'put'.
650e5dd7070Spatrick } else if (KindStr == "set") {
651e5dd7070Spatrick Diag(KindLoc, diag::err_ms_property_has_set_accessor)
652e5dd7070Spatrick << FixItHint::CreateReplacement(KindLoc, "put");
653e5dd7070Spatrick Kind = AK_Put;
654e5dd7070Spatrick
655e5dd7070Spatrick // Handle the mistake of forgetting the accessor kind by skipping
656e5dd7070Spatrick // this accessor.
657e5dd7070Spatrick } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
658e5dd7070Spatrick Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
659e5dd7070Spatrick ConsumeToken();
660e5dd7070Spatrick HasInvalidAccessor = true;
661e5dd7070Spatrick goto next_property_accessor;
662e5dd7070Spatrick
663e5dd7070Spatrick // Otherwise, complain about the unknown accessor kind.
664e5dd7070Spatrick } else {
665e5dd7070Spatrick Diag(KindLoc, diag::err_ms_property_unknown_accessor);
666e5dd7070Spatrick HasInvalidAccessor = true;
667e5dd7070Spatrick Kind = AK_Invalid;
668e5dd7070Spatrick
669e5dd7070Spatrick // Try to keep parsing unless it doesn't look like an accessor spec.
670e5dd7070Spatrick if (!NextToken().is(tok::equal))
671e5dd7070Spatrick break;
672e5dd7070Spatrick }
673e5dd7070Spatrick
674e5dd7070Spatrick // Consume the identifier.
675e5dd7070Spatrick ConsumeToken();
676e5dd7070Spatrick
677e5dd7070Spatrick // Consume the '='.
678e5dd7070Spatrick if (!TryConsumeToken(tok::equal)) {
679e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
680e5dd7070Spatrick << KindStr;
681e5dd7070Spatrick break;
682e5dd7070Spatrick }
683e5dd7070Spatrick
684e5dd7070Spatrick // Expect the method name.
685e5dd7070Spatrick if (!Tok.is(tok::identifier)) {
686e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name);
687e5dd7070Spatrick break;
688e5dd7070Spatrick }
689e5dd7070Spatrick
690e5dd7070Spatrick if (Kind == AK_Invalid) {
691e5dd7070Spatrick // Just drop invalid accessors.
692e5dd7070Spatrick } else if (AccessorNames[Kind] != nullptr) {
693e5dd7070Spatrick // Complain about the repeated accessor, ignore it, and keep parsing.
694e5dd7070Spatrick Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
695e5dd7070Spatrick } else {
696e5dd7070Spatrick AccessorNames[Kind] = Tok.getIdentifierInfo();
697e5dd7070Spatrick }
698e5dd7070Spatrick ConsumeToken();
699e5dd7070Spatrick
700e5dd7070Spatrick next_property_accessor:
701e5dd7070Spatrick // Keep processing accessors until we run out.
702e5dd7070Spatrick if (TryConsumeToken(tok::comma))
703e5dd7070Spatrick continue;
704e5dd7070Spatrick
705e5dd7070Spatrick // If we run into the ')', stop without consuming it.
706e5dd7070Spatrick if (Tok.is(tok::r_paren))
707e5dd7070Spatrick break;
708e5dd7070Spatrick
709e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
710e5dd7070Spatrick break;
711e5dd7070Spatrick }
712e5dd7070Spatrick
713e5dd7070Spatrick // Only add the property attribute if it was well-formed.
714e5dd7070Spatrick if (!HasInvalidAccessor)
715e5dd7070Spatrick Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),
716e5dd7070Spatrick AccessorNames[AK_Get], AccessorNames[AK_Put],
717e5dd7070Spatrick ParsedAttr::AS_Declspec);
718e5dd7070Spatrick T.skipToEnd();
719e5dd7070Spatrick return !HasInvalidAccessor;
720e5dd7070Spatrick }
721e5dd7070Spatrick
722e5dd7070Spatrick unsigned NumArgs =
723e5dd7070Spatrick ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
724e5dd7070Spatrick SourceLocation(), ParsedAttr::AS_Declspec);
725e5dd7070Spatrick
726e5dd7070Spatrick // If this attribute's args were parsed, and it was expected to have
727e5dd7070Spatrick // arguments but none were provided, emit a diagnostic.
728*12c85518Srobert if (ExistingAttrs < Attrs.size() && Attrs.back().getMaxArgs() && !NumArgs) {
729e5dd7070Spatrick Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;
730e5dd7070Spatrick return false;
731e5dd7070Spatrick }
732e5dd7070Spatrick return true;
733e5dd7070Spatrick }
734e5dd7070Spatrick
735e5dd7070Spatrick /// [MS] decl-specifier:
736e5dd7070Spatrick /// __declspec ( extended-decl-modifier-seq )
737e5dd7070Spatrick ///
738e5dd7070Spatrick /// [MS] extended-decl-modifier-seq:
739e5dd7070Spatrick /// extended-decl-modifier[opt]
740e5dd7070Spatrick /// extended-decl-modifier extended-decl-modifier-seq
ParseMicrosoftDeclSpecs(ParsedAttributes & Attrs)741*12c85518Srobert void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) {
742e5dd7070Spatrick assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled");
743e5dd7070Spatrick assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
744e5dd7070Spatrick
745*12c85518Srobert SourceLocation StartLoc = Tok.getLocation();
746*12c85518Srobert SourceLocation EndLoc = StartLoc;
747*12c85518Srobert
748e5dd7070Spatrick while (Tok.is(tok::kw___declspec)) {
749e5dd7070Spatrick ConsumeToken();
750e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
751e5dd7070Spatrick if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
752e5dd7070Spatrick tok::r_paren))
753e5dd7070Spatrick return;
754e5dd7070Spatrick
755e5dd7070Spatrick // An empty declspec is perfectly legal and should not warn. Additionally,
756e5dd7070Spatrick // you can specify multiple attributes per declspec.
757e5dd7070Spatrick while (Tok.isNot(tok::r_paren)) {
758e5dd7070Spatrick // Attribute not present.
759e5dd7070Spatrick if (TryConsumeToken(tok::comma))
760e5dd7070Spatrick continue;
761e5dd7070Spatrick
762*12c85518Srobert if (Tok.is(tok::code_completion)) {
763*12c85518Srobert cutOffParsing();
764*12c85518Srobert Actions.CodeCompleteAttribute(AttributeCommonInfo::AS_Declspec);
765*12c85518Srobert return;
766*12c85518Srobert }
767*12c85518Srobert
768e5dd7070Spatrick // We expect either a well-known identifier or a generic string. Anything
769e5dd7070Spatrick // else is a malformed declspec.
770e5dd7070Spatrick bool IsString = Tok.getKind() == tok::string_literal;
771e5dd7070Spatrick if (!IsString && Tok.getKind() != tok::identifier &&
772e5dd7070Spatrick Tok.getKind() != tok::kw_restrict) {
773e5dd7070Spatrick Diag(Tok, diag::err_ms_declspec_type);
774e5dd7070Spatrick T.skipToEnd();
775e5dd7070Spatrick return;
776e5dd7070Spatrick }
777e5dd7070Spatrick
778e5dd7070Spatrick IdentifierInfo *AttrName;
779e5dd7070Spatrick SourceLocation AttrNameLoc;
780e5dd7070Spatrick if (IsString) {
781e5dd7070Spatrick SmallString<8> StrBuffer;
782e5dd7070Spatrick bool Invalid = false;
783e5dd7070Spatrick StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
784e5dd7070Spatrick if (Invalid) {
785e5dd7070Spatrick T.skipToEnd();
786e5dd7070Spatrick return;
787e5dd7070Spatrick }
788e5dd7070Spatrick AttrName = PP.getIdentifierInfo(Str);
789e5dd7070Spatrick AttrNameLoc = ConsumeStringToken();
790e5dd7070Spatrick } else {
791e5dd7070Spatrick AttrName = Tok.getIdentifierInfo();
792e5dd7070Spatrick AttrNameLoc = ConsumeToken();
793e5dd7070Spatrick }
794e5dd7070Spatrick
795e5dd7070Spatrick bool AttrHandled = false;
796e5dd7070Spatrick
797e5dd7070Spatrick // Parse attribute arguments.
798e5dd7070Spatrick if (Tok.is(tok::l_paren))
799e5dd7070Spatrick AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
800e5dd7070Spatrick else if (AttrName->getName() == "property")
801e5dd7070Spatrick // The property attribute must have an argument list.
802e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_expected_lparen_after)
803e5dd7070Spatrick << AttrName->getName();
804e5dd7070Spatrick
805e5dd7070Spatrick if (!AttrHandled)
806e5dd7070Spatrick Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
807e5dd7070Spatrick ParsedAttr::AS_Declspec);
808e5dd7070Spatrick }
809e5dd7070Spatrick T.consumeClose();
810*12c85518Srobert EndLoc = T.getCloseLocation();
811e5dd7070Spatrick }
812*12c85518Srobert
813*12c85518Srobert Attrs.Range = SourceRange(StartLoc, EndLoc);
814e5dd7070Spatrick }
815e5dd7070Spatrick
ParseMicrosoftTypeAttributes(ParsedAttributes & attrs)816e5dd7070Spatrick void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
817e5dd7070Spatrick // Treat these like attributes
818e5dd7070Spatrick while (true) {
819e5dd7070Spatrick switch (Tok.getKind()) {
820e5dd7070Spatrick case tok::kw___fastcall:
821e5dd7070Spatrick case tok::kw___stdcall:
822e5dd7070Spatrick case tok::kw___thiscall:
823e5dd7070Spatrick case tok::kw___regcall:
824e5dd7070Spatrick case tok::kw___cdecl:
825e5dd7070Spatrick case tok::kw___vectorcall:
826e5dd7070Spatrick case tok::kw___ptr64:
827e5dd7070Spatrick case tok::kw___w64:
828e5dd7070Spatrick case tok::kw___ptr32:
829e5dd7070Spatrick case tok::kw___sptr:
830e5dd7070Spatrick case tok::kw___uptr: {
831e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
832e5dd7070Spatrick SourceLocation AttrNameLoc = ConsumeToken();
833e5dd7070Spatrick attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
834e5dd7070Spatrick ParsedAttr::AS_Keyword);
835e5dd7070Spatrick break;
836e5dd7070Spatrick }
837e5dd7070Spatrick default:
838e5dd7070Spatrick return;
839e5dd7070Spatrick }
840e5dd7070Spatrick }
841e5dd7070Spatrick }
842e5dd7070Spatrick
DiagnoseAndSkipExtendedMicrosoftTypeAttributes()843e5dd7070Spatrick void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() {
844e5dd7070Spatrick SourceLocation StartLoc = Tok.getLocation();
845e5dd7070Spatrick SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes();
846e5dd7070Spatrick
847e5dd7070Spatrick if (EndLoc.isValid()) {
848e5dd7070Spatrick SourceRange Range(StartLoc, EndLoc);
849e5dd7070Spatrick Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range;
850e5dd7070Spatrick }
851e5dd7070Spatrick }
852e5dd7070Spatrick
SkipExtendedMicrosoftTypeAttributes()853e5dd7070Spatrick SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() {
854e5dd7070Spatrick SourceLocation EndLoc;
855e5dd7070Spatrick
856e5dd7070Spatrick while (true) {
857e5dd7070Spatrick switch (Tok.getKind()) {
858e5dd7070Spatrick case tok::kw_const:
859e5dd7070Spatrick case tok::kw_volatile:
860e5dd7070Spatrick case tok::kw___fastcall:
861e5dd7070Spatrick case tok::kw___stdcall:
862e5dd7070Spatrick case tok::kw___thiscall:
863e5dd7070Spatrick case tok::kw___cdecl:
864e5dd7070Spatrick case tok::kw___vectorcall:
865e5dd7070Spatrick case tok::kw___ptr32:
866e5dd7070Spatrick case tok::kw___ptr64:
867e5dd7070Spatrick case tok::kw___w64:
868e5dd7070Spatrick case tok::kw___unaligned:
869e5dd7070Spatrick case tok::kw___sptr:
870e5dd7070Spatrick case tok::kw___uptr:
871e5dd7070Spatrick EndLoc = ConsumeToken();
872e5dd7070Spatrick break;
873e5dd7070Spatrick default:
874e5dd7070Spatrick return EndLoc;
875e5dd7070Spatrick }
876e5dd7070Spatrick }
877e5dd7070Spatrick }
878e5dd7070Spatrick
ParseBorlandTypeAttributes(ParsedAttributes & attrs)879e5dd7070Spatrick void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
880e5dd7070Spatrick // Treat these like attributes
881e5dd7070Spatrick while (Tok.is(tok::kw___pascal)) {
882e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
883e5dd7070Spatrick SourceLocation AttrNameLoc = ConsumeToken();
884e5dd7070Spatrick attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
885e5dd7070Spatrick ParsedAttr::AS_Keyword);
886e5dd7070Spatrick }
887e5dd7070Spatrick }
888e5dd7070Spatrick
ParseOpenCLKernelAttributes(ParsedAttributes & attrs)889e5dd7070Spatrick void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) {
890e5dd7070Spatrick // Treat these like attributes
891e5dd7070Spatrick while (Tok.is(tok::kw___kernel)) {
892e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
893e5dd7070Spatrick SourceLocation AttrNameLoc = ConsumeToken();
894e5dd7070Spatrick attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
895e5dd7070Spatrick ParsedAttr::AS_Keyword);
896e5dd7070Spatrick }
897e5dd7070Spatrick }
898e5dd7070Spatrick
ParseCUDAFunctionAttributes(ParsedAttributes & attrs)899*12c85518Srobert void Parser::ParseCUDAFunctionAttributes(ParsedAttributes &attrs) {
900*12c85518Srobert while (Tok.is(tok::kw___noinline__)) {
901*12c85518Srobert IdentifierInfo *AttrName = Tok.getIdentifierInfo();
902*12c85518Srobert SourceLocation AttrNameLoc = ConsumeToken();
903*12c85518Srobert attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
904*12c85518Srobert ParsedAttr::AS_Keyword);
905*12c85518Srobert }
906*12c85518Srobert }
907*12c85518Srobert
ParseOpenCLQualifiers(ParsedAttributes & Attrs)908e5dd7070Spatrick void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
909e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
910e5dd7070Spatrick SourceLocation AttrNameLoc = Tok.getLocation();
911e5dd7070Spatrick Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
912e5dd7070Spatrick ParsedAttr::AS_Keyword);
913e5dd7070Spatrick }
914e5dd7070Spatrick
isHLSLQualifier(const Token & Tok) const915*12c85518Srobert bool Parser::isHLSLQualifier(const Token &Tok) const {
916*12c85518Srobert return Tok.is(tok::kw_groupshared);
917*12c85518Srobert }
918*12c85518Srobert
ParseHLSLQualifiers(ParsedAttributes & Attrs)919*12c85518Srobert void Parser::ParseHLSLQualifiers(ParsedAttributes &Attrs) {
920*12c85518Srobert IdentifierInfo *AttrName = Tok.getIdentifierInfo();
921*12c85518Srobert SourceLocation AttrNameLoc = ConsumeToken();
922*12c85518Srobert Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
923*12c85518Srobert ParsedAttr::AS_Keyword);
924*12c85518Srobert }
925*12c85518Srobert
ParseNullabilityTypeSpecifiers(ParsedAttributes & attrs)926e5dd7070Spatrick void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
927e5dd7070Spatrick // Treat these like attributes, even though they're type specifiers.
928e5dd7070Spatrick while (true) {
929e5dd7070Spatrick switch (Tok.getKind()) {
930e5dd7070Spatrick case tok::kw__Nonnull:
931e5dd7070Spatrick case tok::kw__Nullable:
932a9ac8606Spatrick case tok::kw__Nullable_result:
933e5dd7070Spatrick case tok::kw__Null_unspecified: {
934e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
935e5dd7070Spatrick SourceLocation AttrNameLoc = ConsumeToken();
936e5dd7070Spatrick if (!getLangOpts().ObjC)
937e5dd7070Spatrick Diag(AttrNameLoc, diag::ext_nullability)
938e5dd7070Spatrick << AttrName;
939e5dd7070Spatrick attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
940e5dd7070Spatrick ParsedAttr::AS_Keyword);
941e5dd7070Spatrick break;
942e5dd7070Spatrick }
943e5dd7070Spatrick default:
944e5dd7070Spatrick return;
945e5dd7070Spatrick }
946e5dd7070Spatrick }
947e5dd7070Spatrick }
948e5dd7070Spatrick
VersionNumberSeparator(const char Separator)949e5dd7070Spatrick static bool VersionNumberSeparator(const char Separator) {
950e5dd7070Spatrick return (Separator == '.' || Separator == '_');
951e5dd7070Spatrick }
952e5dd7070Spatrick
953e5dd7070Spatrick /// Parse a version number.
954e5dd7070Spatrick ///
955e5dd7070Spatrick /// version:
956e5dd7070Spatrick /// simple-integer
957e5dd7070Spatrick /// simple-integer '.' simple-integer
958e5dd7070Spatrick /// simple-integer '_' simple-integer
959e5dd7070Spatrick /// simple-integer '.' simple-integer '.' simple-integer
960e5dd7070Spatrick /// simple-integer '_' simple-integer '_' simple-integer
ParseVersionTuple(SourceRange & Range)961e5dd7070Spatrick VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
962e5dd7070Spatrick Range = SourceRange(Tok.getLocation(), Tok.getEndLoc());
963e5dd7070Spatrick
964e5dd7070Spatrick if (!Tok.is(tok::numeric_constant)) {
965e5dd7070Spatrick Diag(Tok, diag::err_expected_version);
966e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren,
967e5dd7070Spatrick StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
968e5dd7070Spatrick return VersionTuple();
969e5dd7070Spatrick }
970e5dd7070Spatrick
971e5dd7070Spatrick // Parse the major (and possibly minor and subminor) versions, which
972e5dd7070Spatrick // are stored in the numeric constant. We utilize a quirk of the
973e5dd7070Spatrick // lexer, which is that it handles something like 1.2.3 as a single
974e5dd7070Spatrick // numeric constant, rather than two separate tokens.
975e5dd7070Spatrick SmallString<512> Buffer;
976e5dd7070Spatrick Buffer.resize(Tok.getLength()+1);
977e5dd7070Spatrick const char *ThisTokBegin = &Buffer[0];
978e5dd7070Spatrick
979e5dd7070Spatrick // Get the spelling of the token, which eliminates trigraphs, etc.
980e5dd7070Spatrick bool Invalid = false;
981e5dd7070Spatrick unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);
982e5dd7070Spatrick if (Invalid)
983e5dd7070Spatrick return VersionTuple();
984e5dd7070Spatrick
985e5dd7070Spatrick // Parse the major version.
986e5dd7070Spatrick unsigned AfterMajor = 0;
987e5dd7070Spatrick unsigned Major = 0;
988e5dd7070Spatrick while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) {
989e5dd7070Spatrick Major = Major * 10 + ThisTokBegin[AfterMajor] - '0';
990e5dd7070Spatrick ++AfterMajor;
991e5dd7070Spatrick }
992e5dd7070Spatrick
993e5dd7070Spatrick if (AfterMajor == 0) {
994e5dd7070Spatrick Diag(Tok, diag::err_expected_version);
995e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren,
996e5dd7070Spatrick StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
997e5dd7070Spatrick return VersionTuple();
998e5dd7070Spatrick }
999e5dd7070Spatrick
1000e5dd7070Spatrick if (AfterMajor == ActualLength) {
1001e5dd7070Spatrick ConsumeToken();
1002e5dd7070Spatrick
1003e5dd7070Spatrick // We only had a single version component.
1004e5dd7070Spatrick if (Major == 0) {
1005e5dd7070Spatrick Diag(Tok, diag::err_zero_version);
1006e5dd7070Spatrick return VersionTuple();
1007e5dd7070Spatrick }
1008e5dd7070Spatrick
1009e5dd7070Spatrick return VersionTuple(Major);
1010e5dd7070Spatrick }
1011e5dd7070Spatrick
1012e5dd7070Spatrick const char AfterMajorSeparator = ThisTokBegin[AfterMajor];
1013e5dd7070Spatrick if (!VersionNumberSeparator(AfterMajorSeparator)
1014e5dd7070Spatrick || (AfterMajor + 1 == ActualLength)) {
1015e5dd7070Spatrick Diag(Tok, diag::err_expected_version);
1016e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren,
1017e5dd7070Spatrick StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
1018e5dd7070Spatrick return VersionTuple();
1019e5dd7070Spatrick }
1020e5dd7070Spatrick
1021e5dd7070Spatrick // Parse the minor version.
1022e5dd7070Spatrick unsigned AfterMinor = AfterMajor + 1;
1023e5dd7070Spatrick unsigned Minor = 0;
1024e5dd7070Spatrick while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) {
1025e5dd7070Spatrick Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0';
1026e5dd7070Spatrick ++AfterMinor;
1027e5dd7070Spatrick }
1028e5dd7070Spatrick
1029e5dd7070Spatrick if (AfterMinor == ActualLength) {
1030e5dd7070Spatrick ConsumeToken();
1031e5dd7070Spatrick
1032e5dd7070Spatrick // We had major.minor.
1033e5dd7070Spatrick if (Major == 0 && Minor == 0) {
1034e5dd7070Spatrick Diag(Tok, diag::err_zero_version);
1035e5dd7070Spatrick return VersionTuple();
1036e5dd7070Spatrick }
1037e5dd7070Spatrick
1038e5dd7070Spatrick return VersionTuple(Major, Minor);
1039e5dd7070Spatrick }
1040e5dd7070Spatrick
1041e5dd7070Spatrick const char AfterMinorSeparator = ThisTokBegin[AfterMinor];
1042e5dd7070Spatrick // If what follows is not a '.' or '_', we have a problem.
1043e5dd7070Spatrick if (!VersionNumberSeparator(AfterMinorSeparator)) {
1044e5dd7070Spatrick Diag(Tok, diag::err_expected_version);
1045e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren,
1046e5dd7070Spatrick StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
1047e5dd7070Spatrick return VersionTuple();
1048e5dd7070Spatrick }
1049e5dd7070Spatrick
1050e5dd7070Spatrick // Warn if separators, be it '.' or '_', do not match.
1051e5dd7070Spatrick if (AfterMajorSeparator != AfterMinorSeparator)
1052e5dd7070Spatrick Diag(Tok, diag::warn_expected_consistent_version_separator);
1053e5dd7070Spatrick
1054e5dd7070Spatrick // Parse the subminor version.
1055e5dd7070Spatrick unsigned AfterSubminor = AfterMinor + 1;
1056e5dd7070Spatrick unsigned Subminor = 0;
1057e5dd7070Spatrick while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) {
1058e5dd7070Spatrick Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0';
1059e5dd7070Spatrick ++AfterSubminor;
1060e5dd7070Spatrick }
1061e5dd7070Spatrick
1062e5dd7070Spatrick if (AfterSubminor != ActualLength) {
1063e5dd7070Spatrick Diag(Tok, diag::err_expected_version);
1064e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren,
1065e5dd7070Spatrick StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
1066e5dd7070Spatrick return VersionTuple();
1067e5dd7070Spatrick }
1068e5dd7070Spatrick ConsumeToken();
1069e5dd7070Spatrick return VersionTuple(Major, Minor, Subminor);
1070e5dd7070Spatrick }
1071e5dd7070Spatrick
1072e5dd7070Spatrick /// Parse the contents of the "availability" attribute.
1073e5dd7070Spatrick ///
1074e5dd7070Spatrick /// availability-attribute:
1075e5dd7070Spatrick /// 'availability' '(' platform ',' opt-strict version-arg-list,
1076e5dd7070Spatrick /// opt-replacement, opt-message')'
1077e5dd7070Spatrick ///
1078e5dd7070Spatrick /// platform:
1079e5dd7070Spatrick /// identifier
1080e5dd7070Spatrick ///
1081e5dd7070Spatrick /// opt-strict:
1082e5dd7070Spatrick /// 'strict' ','
1083e5dd7070Spatrick ///
1084e5dd7070Spatrick /// version-arg-list:
1085e5dd7070Spatrick /// version-arg
1086e5dd7070Spatrick /// version-arg ',' version-arg-list
1087e5dd7070Spatrick ///
1088e5dd7070Spatrick /// version-arg:
1089e5dd7070Spatrick /// 'introduced' '=' version
1090e5dd7070Spatrick /// 'deprecated' '=' version
1091e5dd7070Spatrick /// 'obsoleted' = version
1092e5dd7070Spatrick /// 'unavailable'
1093e5dd7070Spatrick /// opt-replacement:
1094e5dd7070Spatrick /// 'replacement' '=' <string>
1095e5dd7070Spatrick /// opt-message:
1096e5dd7070Spatrick /// 'message' '=' <string>
ParseAvailabilityAttribute(IdentifierInfo & Availability,SourceLocation AvailabilityLoc,ParsedAttributes & attrs,SourceLocation * endLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)1097e5dd7070Spatrick void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
1098e5dd7070Spatrick SourceLocation AvailabilityLoc,
1099e5dd7070Spatrick ParsedAttributes &attrs,
1100e5dd7070Spatrick SourceLocation *endLoc,
1101e5dd7070Spatrick IdentifierInfo *ScopeName,
1102e5dd7070Spatrick SourceLocation ScopeLoc,
1103e5dd7070Spatrick ParsedAttr::Syntax Syntax) {
1104e5dd7070Spatrick enum { Introduced, Deprecated, Obsoleted, Unknown };
1105e5dd7070Spatrick AvailabilityChange Changes[Unknown];
1106e5dd7070Spatrick ExprResult MessageExpr, ReplacementExpr;
1107e5dd7070Spatrick
1108e5dd7070Spatrick // Opening '('.
1109e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
1110e5dd7070Spatrick if (T.consumeOpen()) {
1111e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::l_paren;
1112e5dd7070Spatrick return;
1113e5dd7070Spatrick }
1114e5dd7070Spatrick
1115e5dd7070Spatrick // Parse the platform name.
1116e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1117e5dd7070Spatrick Diag(Tok, diag::err_availability_expected_platform);
1118e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1119e5dd7070Spatrick return;
1120e5dd7070Spatrick }
1121e5dd7070Spatrick IdentifierLoc *Platform = ParseIdentifierLoc();
1122e5dd7070Spatrick if (const IdentifierInfo *const Ident = Platform->Ident) {
1123e5dd7070Spatrick // Canonicalize platform name from "macosx" to "macos".
1124e5dd7070Spatrick if (Ident->getName() == "macosx")
1125e5dd7070Spatrick Platform->Ident = PP.getIdentifierInfo("macos");
1126e5dd7070Spatrick // Canonicalize platform name from "macosx_app_extension" to
1127e5dd7070Spatrick // "macos_app_extension".
1128e5dd7070Spatrick else if (Ident->getName() == "macosx_app_extension")
1129e5dd7070Spatrick Platform->Ident = PP.getIdentifierInfo("macos_app_extension");
1130e5dd7070Spatrick else
1131e5dd7070Spatrick Platform->Ident = PP.getIdentifierInfo(
1132e5dd7070Spatrick AvailabilityAttr::canonicalizePlatformName(Ident->getName()));
1133e5dd7070Spatrick }
1134e5dd7070Spatrick
1135e5dd7070Spatrick // Parse the ',' following the platform name.
1136e5dd7070Spatrick if (ExpectAndConsume(tok::comma)) {
1137e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1138e5dd7070Spatrick return;
1139e5dd7070Spatrick }
1140e5dd7070Spatrick
1141e5dd7070Spatrick // If we haven't grabbed the pointers for the identifiers
1142e5dd7070Spatrick // "introduced", "deprecated", and "obsoleted", do so now.
1143e5dd7070Spatrick if (!Ident_introduced) {
1144e5dd7070Spatrick Ident_introduced = PP.getIdentifierInfo("introduced");
1145e5dd7070Spatrick Ident_deprecated = PP.getIdentifierInfo("deprecated");
1146e5dd7070Spatrick Ident_obsoleted = PP.getIdentifierInfo("obsoleted");
1147e5dd7070Spatrick Ident_unavailable = PP.getIdentifierInfo("unavailable");
1148e5dd7070Spatrick Ident_message = PP.getIdentifierInfo("message");
1149e5dd7070Spatrick Ident_strict = PP.getIdentifierInfo("strict");
1150e5dd7070Spatrick Ident_replacement = PP.getIdentifierInfo("replacement");
1151e5dd7070Spatrick }
1152e5dd7070Spatrick
1153e5dd7070Spatrick // Parse the optional "strict", the optional "replacement" and the set of
1154e5dd7070Spatrick // introductions/deprecations/removals.
1155e5dd7070Spatrick SourceLocation UnavailableLoc, StrictLoc;
1156e5dd7070Spatrick do {
1157e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1158e5dd7070Spatrick Diag(Tok, diag::err_availability_expected_change);
1159e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1160e5dd7070Spatrick return;
1161e5dd7070Spatrick }
1162e5dd7070Spatrick IdentifierInfo *Keyword = Tok.getIdentifierInfo();
1163e5dd7070Spatrick SourceLocation KeywordLoc = ConsumeToken();
1164e5dd7070Spatrick
1165e5dd7070Spatrick if (Keyword == Ident_strict) {
1166e5dd7070Spatrick if (StrictLoc.isValid()) {
1167e5dd7070Spatrick Diag(KeywordLoc, diag::err_availability_redundant)
1168e5dd7070Spatrick << Keyword << SourceRange(StrictLoc);
1169e5dd7070Spatrick }
1170e5dd7070Spatrick StrictLoc = KeywordLoc;
1171e5dd7070Spatrick continue;
1172e5dd7070Spatrick }
1173e5dd7070Spatrick
1174e5dd7070Spatrick if (Keyword == Ident_unavailable) {
1175e5dd7070Spatrick if (UnavailableLoc.isValid()) {
1176e5dd7070Spatrick Diag(KeywordLoc, diag::err_availability_redundant)
1177e5dd7070Spatrick << Keyword << SourceRange(UnavailableLoc);
1178e5dd7070Spatrick }
1179e5dd7070Spatrick UnavailableLoc = KeywordLoc;
1180e5dd7070Spatrick continue;
1181e5dd7070Spatrick }
1182e5dd7070Spatrick
1183e5dd7070Spatrick if (Keyword == Ident_deprecated && Platform->Ident &&
1184e5dd7070Spatrick Platform->Ident->isStr("swift")) {
1185e5dd7070Spatrick // For swift, we deprecate for all versions.
1186e5dd7070Spatrick if (Changes[Deprecated].KeywordLoc.isValid()) {
1187e5dd7070Spatrick Diag(KeywordLoc, diag::err_availability_redundant)
1188e5dd7070Spatrick << Keyword
1189e5dd7070Spatrick << SourceRange(Changes[Deprecated].KeywordLoc);
1190e5dd7070Spatrick }
1191e5dd7070Spatrick
1192e5dd7070Spatrick Changes[Deprecated].KeywordLoc = KeywordLoc;
1193e5dd7070Spatrick // Use a fake version here.
1194e5dd7070Spatrick Changes[Deprecated].Version = VersionTuple(1);
1195e5dd7070Spatrick continue;
1196e5dd7070Spatrick }
1197e5dd7070Spatrick
1198e5dd7070Spatrick if (Tok.isNot(tok::equal)) {
1199e5dd7070Spatrick Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
1200e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1201e5dd7070Spatrick return;
1202e5dd7070Spatrick }
1203e5dd7070Spatrick ConsumeToken();
1204e5dd7070Spatrick if (Keyword == Ident_message || Keyword == Ident_replacement) {
1205e5dd7070Spatrick if (Tok.isNot(tok::string_literal)) {
1206e5dd7070Spatrick Diag(Tok, diag::err_expected_string_literal)
1207e5dd7070Spatrick << /*Source='availability attribute'*/2;
1208e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1209e5dd7070Spatrick return;
1210e5dd7070Spatrick }
1211e5dd7070Spatrick if (Keyword == Ident_message)
1212e5dd7070Spatrick MessageExpr = ParseStringLiteralExpression();
1213e5dd7070Spatrick else
1214e5dd7070Spatrick ReplacementExpr = ParseStringLiteralExpression();
1215e5dd7070Spatrick // Also reject wide string literals.
1216e5dd7070Spatrick if (StringLiteral *MessageStringLiteral =
1217e5dd7070Spatrick cast_or_null<StringLiteral>(MessageExpr.get())) {
1218*12c85518Srobert if (!MessageStringLiteral->isOrdinary()) {
1219e5dd7070Spatrick Diag(MessageStringLiteral->getSourceRange().getBegin(),
1220e5dd7070Spatrick diag::err_expected_string_literal)
1221e5dd7070Spatrick << /*Source='availability attribute'*/ 2;
1222e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1223e5dd7070Spatrick return;
1224e5dd7070Spatrick }
1225e5dd7070Spatrick }
1226e5dd7070Spatrick if (Keyword == Ident_message)
1227e5dd7070Spatrick break;
1228e5dd7070Spatrick else
1229e5dd7070Spatrick continue;
1230e5dd7070Spatrick }
1231e5dd7070Spatrick
1232e5dd7070Spatrick // Special handling of 'NA' only when applied to introduced or
1233e5dd7070Spatrick // deprecated.
1234e5dd7070Spatrick if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) &&
1235e5dd7070Spatrick Tok.is(tok::identifier)) {
1236e5dd7070Spatrick IdentifierInfo *NA = Tok.getIdentifierInfo();
1237e5dd7070Spatrick if (NA->getName() == "NA") {
1238e5dd7070Spatrick ConsumeToken();
1239e5dd7070Spatrick if (Keyword == Ident_introduced)
1240e5dd7070Spatrick UnavailableLoc = KeywordLoc;
1241e5dd7070Spatrick continue;
1242e5dd7070Spatrick }
1243e5dd7070Spatrick }
1244e5dd7070Spatrick
1245e5dd7070Spatrick SourceRange VersionRange;
1246e5dd7070Spatrick VersionTuple Version = ParseVersionTuple(VersionRange);
1247e5dd7070Spatrick
1248e5dd7070Spatrick if (Version.empty()) {
1249e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1250e5dd7070Spatrick return;
1251e5dd7070Spatrick }
1252e5dd7070Spatrick
1253e5dd7070Spatrick unsigned Index;
1254e5dd7070Spatrick if (Keyword == Ident_introduced)
1255e5dd7070Spatrick Index = Introduced;
1256e5dd7070Spatrick else if (Keyword == Ident_deprecated)
1257e5dd7070Spatrick Index = Deprecated;
1258e5dd7070Spatrick else if (Keyword == Ident_obsoleted)
1259e5dd7070Spatrick Index = Obsoleted;
1260e5dd7070Spatrick else
1261e5dd7070Spatrick Index = Unknown;
1262e5dd7070Spatrick
1263e5dd7070Spatrick if (Index < Unknown) {
1264e5dd7070Spatrick if (!Changes[Index].KeywordLoc.isInvalid()) {
1265e5dd7070Spatrick Diag(KeywordLoc, diag::err_availability_redundant)
1266e5dd7070Spatrick << Keyword
1267e5dd7070Spatrick << SourceRange(Changes[Index].KeywordLoc,
1268e5dd7070Spatrick Changes[Index].VersionRange.getEnd());
1269e5dd7070Spatrick }
1270e5dd7070Spatrick
1271e5dd7070Spatrick Changes[Index].KeywordLoc = KeywordLoc;
1272e5dd7070Spatrick Changes[Index].Version = Version;
1273e5dd7070Spatrick Changes[Index].VersionRange = VersionRange;
1274e5dd7070Spatrick } else {
1275e5dd7070Spatrick Diag(KeywordLoc, diag::err_availability_unknown_change)
1276e5dd7070Spatrick << Keyword << VersionRange;
1277e5dd7070Spatrick }
1278e5dd7070Spatrick
1279e5dd7070Spatrick } while (TryConsumeToken(tok::comma));
1280e5dd7070Spatrick
1281e5dd7070Spatrick // Closing ')'.
1282e5dd7070Spatrick if (T.consumeClose())
1283e5dd7070Spatrick return;
1284e5dd7070Spatrick
1285e5dd7070Spatrick if (endLoc)
1286e5dd7070Spatrick *endLoc = T.getCloseLocation();
1287e5dd7070Spatrick
1288e5dd7070Spatrick // The 'unavailable' availability cannot be combined with any other
1289e5dd7070Spatrick // availability changes. Make sure that hasn't happened.
1290e5dd7070Spatrick if (UnavailableLoc.isValid()) {
1291e5dd7070Spatrick bool Complained = false;
1292e5dd7070Spatrick for (unsigned Index = Introduced; Index != Unknown; ++Index) {
1293e5dd7070Spatrick if (Changes[Index].KeywordLoc.isValid()) {
1294e5dd7070Spatrick if (!Complained) {
1295e5dd7070Spatrick Diag(UnavailableLoc, diag::warn_availability_and_unavailable)
1296e5dd7070Spatrick << SourceRange(Changes[Index].KeywordLoc,
1297e5dd7070Spatrick Changes[Index].VersionRange.getEnd());
1298e5dd7070Spatrick Complained = true;
1299e5dd7070Spatrick }
1300e5dd7070Spatrick
1301e5dd7070Spatrick // Clear out the availability.
1302e5dd7070Spatrick Changes[Index] = AvailabilityChange();
1303e5dd7070Spatrick }
1304e5dd7070Spatrick }
1305e5dd7070Spatrick }
1306e5dd7070Spatrick
1307e5dd7070Spatrick // Record this attribute
1308e5dd7070Spatrick attrs.addNew(&Availability,
1309e5dd7070Spatrick SourceRange(AvailabilityLoc, T.getCloseLocation()),
1310e5dd7070Spatrick ScopeName, ScopeLoc,
1311e5dd7070Spatrick Platform,
1312e5dd7070Spatrick Changes[Introduced],
1313e5dd7070Spatrick Changes[Deprecated],
1314e5dd7070Spatrick Changes[Obsoleted],
1315e5dd7070Spatrick UnavailableLoc, MessageExpr.get(),
1316e5dd7070Spatrick Syntax, StrictLoc, ReplacementExpr.get());
1317e5dd7070Spatrick }
1318e5dd7070Spatrick
1319e5dd7070Spatrick /// Parse the contents of the "external_source_symbol" attribute.
1320e5dd7070Spatrick ///
1321e5dd7070Spatrick /// external-source-symbol-attribute:
1322e5dd7070Spatrick /// 'external_source_symbol' '(' keyword-arg-list ')'
1323e5dd7070Spatrick ///
1324e5dd7070Spatrick /// keyword-arg-list:
1325e5dd7070Spatrick /// keyword-arg
1326e5dd7070Spatrick /// keyword-arg ',' keyword-arg-list
1327e5dd7070Spatrick ///
1328e5dd7070Spatrick /// keyword-arg:
1329e5dd7070Spatrick /// 'language' '=' <string>
1330e5dd7070Spatrick /// 'defined_in' '=' <string>
1331e5dd7070Spatrick /// 'generated_declaration'
ParseExternalSourceSymbolAttribute(IdentifierInfo & ExternalSourceSymbol,SourceLocation Loc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)1332e5dd7070Spatrick void Parser::ParseExternalSourceSymbolAttribute(
1333e5dd7070Spatrick IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,
1334e5dd7070Spatrick ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
1335e5dd7070Spatrick SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
1336e5dd7070Spatrick // Opening '('.
1337e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
1338e5dd7070Spatrick if (T.expectAndConsume())
1339e5dd7070Spatrick return;
1340e5dd7070Spatrick
1341e5dd7070Spatrick // Initialize the pointers for the keyword identifiers when required.
1342e5dd7070Spatrick if (!Ident_language) {
1343e5dd7070Spatrick Ident_language = PP.getIdentifierInfo("language");
1344e5dd7070Spatrick Ident_defined_in = PP.getIdentifierInfo("defined_in");
1345e5dd7070Spatrick Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration");
1346e5dd7070Spatrick }
1347e5dd7070Spatrick
1348e5dd7070Spatrick ExprResult Language;
1349e5dd7070Spatrick bool HasLanguage = false;
1350e5dd7070Spatrick ExprResult DefinedInExpr;
1351e5dd7070Spatrick bool HasDefinedIn = false;
1352e5dd7070Spatrick IdentifierLoc *GeneratedDeclaration = nullptr;
1353e5dd7070Spatrick
1354e5dd7070Spatrick // Parse the language/defined_in/generated_declaration keywords
1355e5dd7070Spatrick do {
1356e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1357e5dd7070Spatrick Diag(Tok, diag::err_external_source_symbol_expected_keyword);
1358e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1359e5dd7070Spatrick return;
1360e5dd7070Spatrick }
1361e5dd7070Spatrick
1362e5dd7070Spatrick SourceLocation KeywordLoc = Tok.getLocation();
1363e5dd7070Spatrick IdentifierInfo *Keyword = Tok.getIdentifierInfo();
1364e5dd7070Spatrick if (Keyword == Ident_generated_declaration) {
1365e5dd7070Spatrick if (GeneratedDeclaration) {
1366e5dd7070Spatrick Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword;
1367e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1368e5dd7070Spatrick return;
1369e5dd7070Spatrick }
1370e5dd7070Spatrick GeneratedDeclaration = ParseIdentifierLoc();
1371e5dd7070Spatrick continue;
1372e5dd7070Spatrick }
1373e5dd7070Spatrick
1374e5dd7070Spatrick if (Keyword != Ident_language && Keyword != Ident_defined_in) {
1375e5dd7070Spatrick Diag(Tok, diag::err_external_source_symbol_expected_keyword);
1376e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1377e5dd7070Spatrick return;
1378e5dd7070Spatrick }
1379e5dd7070Spatrick
1380e5dd7070Spatrick ConsumeToken();
1381e5dd7070Spatrick if (ExpectAndConsume(tok::equal, diag::err_expected_after,
1382e5dd7070Spatrick Keyword->getName())) {
1383e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1384e5dd7070Spatrick return;
1385e5dd7070Spatrick }
1386e5dd7070Spatrick
1387e5dd7070Spatrick bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn;
1388e5dd7070Spatrick if (Keyword == Ident_language)
1389e5dd7070Spatrick HasLanguage = true;
1390e5dd7070Spatrick else
1391e5dd7070Spatrick HasDefinedIn = true;
1392e5dd7070Spatrick
1393e5dd7070Spatrick if (Tok.isNot(tok::string_literal)) {
1394e5dd7070Spatrick Diag(Tok, diag::err_expected_string_literal)
1395e5dd7070Spatrick << /*Source='external_source_symbol attribute'*/ 3
1396e5dd7070Spatrick << /*language | source container*/ (Keyword != Ident_language);
1397e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
1398e5dd7070Spatrick continue;
1399e5dd7070Spatrick }
1400e5dd7070Spatrick if (Keyword == Ident_language) {
1401e5dd7070Spatrick if (HadLanguage) {
1402e5dd7070Spatrick Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
1403e5dd7070Spatrick << Keyword;
1404e5dd7070Spatrick ParseStringLiteralExpression();
1405e5dd7070Spatrick continue;
1406e5dd7070Spatrick }
1407e5dd7070Spatrick Language = ParseStringLiteralExpression();
1408e5dd7070Spatrick } else {
1409e5dd7070Spatrick assert(Keyword == Ident_defined_in && "Invalid clause keyword!");
1410e5dd7070Spatrick if (HadDefinedIn) {
1411e5dd7070Spatrick Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
1412e5dd7070Spatrick << Keyword;
1413e5dd7070Spatrick ParseStringLiteralExpression();
1414e5dd7070Spatrick continue;
1415e5dd7070Spatrick }
1416e5dd7070Spatrick DefinedInExpr = ParseStringLiteralExpression();
1417e5dd7070Spatrick }
1418e5dd7070Spatrick } while (TryConsumeToken(tok::comma));
1419e5dd7070Spatrick
1420e5dd7070Spatrick // Closing ')'.
1421e5dd7070Spatrick if (T.consumeClose())
1422e5dd7070Spatrick return;
1423e5dd7070Spatrick if (EndLoc)
1424e5dd7070Spatrick *EndLoc = T.getCloseLocation();
1425e5dd7070Spatrick
1426e5dd7070Spatrick ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(),
1427e5dd7070Spatrick GeneratedDeclaration};
1428e5dd7070Spatrick Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()),
1429*12c85518Srobert ScopeName, ScopeLoc, Args, std::size(Args), Syntax);
1430e5dd7070Spatrick }
1431e5dd7070Spatrick
1432e5dd7070Spatrick /// Parse the contents of the "objc_bridge_related" attribute.
1433e5dd7070Spatrick /// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
1434e5dd7070Spatrick /// related_class:
1435e5dd7070Spatrick /// Identifier
1436e5dd7070Spatrick ///
1437e5dd7070Spatrick /// opt-class_method:
1438e5dd7070Spatrick /// Identifier: | <empty>
1439e5dd7070Spatrick ///
1440e5dd7070Spatrick /// opt-instance_method:
1441e5dd7070Spatrick /// Identifier | <empty>
1442e5dd7070Spatrick ///
ParseObjCBridgeRelatedAttribute(IdentifierInfo & ObjCBridgeRelated,SourceLocation ObjCBridgeRelatedLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)1443*12c85518Srobert void Parser::ParseObjCBridgeRelatedAttribute(
1444*12c85518Srobert IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc,
1445*12c85518Srobert ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
1446*12c85518Srobert SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
1447e5dd7070Spatrick // Opening '('.
1448e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
1449e5dd7070Spatrick if (T.consumeOpen()) {
1450e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::l_paren;
1451e5dd7070Spatrick return;
1452e5dd7070Spatrick }
1453e5dd7070Spatrick
1454e5dd7070Spatrick // Parse the related class name.
1455e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1456e5dd7070Spatrick Diag(Tok, diag::err_objcbridge_related_expected_related_class);
1457e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1458e5dd7070Spatrick return;
1459e5dd7070Spatrick }
1460e5dd7070Spatrick IdentifierLoc *RelatedClass = ParseIdentifierLoc();
1461e5dd7070Spatrick if (ExpectAndConsume(tok::comma)) {
1462e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1463e5dd7070Spatrick return;
1464e5dd7070Spatrick }
1465e5dd7070Spatrick
1466e5dd7070Spatrick // Parse class method name. It's non-optional in the sense that a trailing
1467e5dd7070Spatrick // comma is required, but it can be the empty string, and then we record a
1468e5dd7070Spatrick // nullptr.
1469e5dd7070Spatrick IdentifierLoc *ClassMethod = nullptr;
1470e5dd7070Spatrick if (Tok.is(tok::identifier)) {
1471e5dd7070Spatrick ClassMethod = ParseIdentifierLoc();
1472e5dd7070Spatrick if (!TryConsumeToken(tok::colon)) {
1473e5dd7070Spatrick Diag(Tok, diag::err_objcbridge_related_selector_name);
1474e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1475e5dd7070Spatrick return;
1476e5dd7070Spatrick }
1477e5dd7070Spatrick }
1478e5dd7070Spatrick if (!TryConsumeToken(tok::comma)) {
1479e5dd7070Spatrick if (Tok.is(tok::colon))
1480e5dd7070Spatrick Diag(Tok, diag::err_objcbridge_related_selector_name);
1481e5dd7070Spatrick else
1482e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::comma;
1483e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1484e5dd7070Spatrick return;
1485e5dd7070Spatrick }
1486e5dd7070Spatrick
1487e5dd7070Spatrick // Parse instance method name. Also non-optional but empty string is
1488e5dd7070Spatrick // permitted.
1489e5dd7070Spatrick IdentifierLoc *InstanceMethod = nullptr;
1490e5dd7070Spatrick if (Tok.is(tok::identifier))
1491e5dd7070Spatrick InstanceMethod = ParseIdentifierLoc();
1492e5dd7070Spatrick else if (Tok.isNot(tok::r_paren)) {
1493e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::r_paren;
1494e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
1495e5dd7070Spatrick return;
1496e5dd7070Spatrick }
1497e5dd7070Spatrick
1498e5dd7070Spatrick // Closing ')'.
1499e5dd7070Spatrick if (T.consumeClose())
1500e5dd7070Spatrick return;
1501e5dd7070Spatrick
1502*12c85518Srobert if (EndLoc)
1503*12c85518Srobert *EndLoc = T.getCloseLocation();
1504e5dd7070Spatrick
1505e5dd7070Spatrick // Record this attribute
1506*12c85518Srobert Attrs.addNew(&ObjCBridgeRelated,
1507e5dd7070Spatrick SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
1508*12c85518Srobert ScopeName, ScopeLoc, RelatedClass, ClassMethod, InstanceMethod,
1509e5dd7070Spatrick Syntax);
1510e5dd7070Spatrick }
1511e5dd7070Spatrick
ParseSwiftNewTypeAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)1512a9ac8606Spatrick void Parser::ParseSwiftNewTypeAttribute(
1513a9ac8606Spatrick IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
1514a9ac8606Spatrick ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
1515a9ac8606Spatrick SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
1516a9ac8606Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
1517a9ac8606Spatrick
1518a9ac8606Spatrick // Opening '('
1519a9ac8606Spatrick if (T.consumeOpen()) {
1520a9ac8606Spatrick Diag(Tok, diag::err_expected) << tok::l_paren;
1521a9ac8606Spatrick return;
1522a9ac8606Spatrick }
1523a9ac8606Spatrick
1524a9ac8606Spatrick if (Tok.is(tok::r_paren)) {
1525a9ac8606Spatrick Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
1526a9ac8606Spatrick T.consumeClose();
1527a9ac8606Spatrick return;
1528a9ac8606Spatrick }
1529a9ac8606Spatrick if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
1530a9ac8606Spatrick Diag(Tok, diag::warn_attribute_type_not_supported)
1531a9ac8606Spatrick << &AttrName << Tok.getIdentifierInfo();
1532a9ac8606Spatrick if (!isTokenSpecial())
1533a9ac8606Spatrick ConsumeToken();
1534a9ac8606Spatrick T.consumeClose();
1535a9ac8606Spatrick return;
1536a9ac8606Spatrick }
1537a9ac8606Spatrick
1538a9ac8606Spatrick auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
1539a9ac8606Spatrick Tok.getIdentifierInfo());
1540a9ac8606Spatrick ConsumeToken();
1541a9ac8606Spatrick
1542a9ac8606Spatrick // Closing ')'
1543a9ac8606Spatrick if (T.consumeClose())
1544a9ac8606Spatrick return;
1545a9ac8606Spatrick if (EndLoc)
1546a9ac8606Spatrick *EndLoc = T.getCloseLocation();
1547a9ac8606Spatrick
1548a9ac8606Spatrick ArgsUnion Args[] = {SwiftType};
1549a9ac8606Spatrick Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()),
1550*12c85518Srobert ScopeName, ScopeLoc, Args, std::size(Args), Syntax);
1551a9ac8606Spatrick }
1552a9ac8606Spatrick
ParseTypeTagForDatatypeAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)1553e5dd7070Spatrick void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
1554e5dd7070Spatrick SourceLocation AttrNameLoc,
1555e5dd7070Spatrick ParsedAttributes &Attrs,
1556e5dd7070Spatrick SourceLocation *EndLoc,
1557e5dd7070Spatrick IdentifierInfo *ScopeName,
1558e5dd7070Spatrick SourceLocation ScopeLoc,
1559e5dd7070Spatrick ParsedAttr::Syntax Syntax) {
1560e5dd7070Spatrick assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
1561e5dd7070Spatrick
1562e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
1563e5dd7070Spatrick T.consumeOpen();
1564e5dd7070Spatrick
1565e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1566e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::identifier;
1567e5dd7070Spatrick T.skipToEnd();
1568e5dd7070Spatrick return;
1569e5dd7070Spatrick }
1570e5dd7070Spatrick IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
1571e5dd7070Spatrick
1572e5dd7070Spatrick if (ExpectAndConsume(tok::comma)) {
1573e5dd7070Spatrick T.skipToEnd();
1574e5dd7070Spatrick return;
1575e5dd7070Spatrick }
1576e5dd7070Spatrick
1577e5dd7070Spatrick SourceRange MatchingCTypeRange;
1578e5dd7070Spatrick TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange);
1579e5dd7070Spatrick if (MatchingCType.isInvalid()) {
1580e5dd7070Spatrick T.skipToEnd();
1581e5dd7070Spatrick return;
1582e5dd7070Spatrick }
1583e5dd7070Spatrick
1584e5dd7070Spatrick bool LayoutCompatible = false;
1585e5dd7070Spatrick bool MustBeNull = false;
1586e5dd7070Spatrick while (TryConsumeToken(tok::comma)) {
1587e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1588e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::identifier;
1589e5dd7070Spatrick T.skipToEnd();
1590e5dd7070Spatrick return;
1591e5dd7070Spatrick }
1592e5dd7070Spatrick IdentifierInfo *Flag = Tok.getIdentifierInfo();
1593e5dd7070Spatrick if (Flag->isStr("layout_compatible"))
1594e5dd7070Spatrick LayoutCompatible = true;
1595e5dd7070Spatrick else if (Flag->isStr("must_be_null"))
1596e5dd7070Spatrick MustBeNull = true;
1597e5dd7070Spatrick else {
1598e5dd7070Spatrick Diag(Tok, diag::err_type_safety_unknown_flag) << Flag;
1599e5dd7070Spatrick T.skipToEnd();
1600e5dd7070Spatrick return;
1601e5dd7070Spatrick }
1602e5dd7070Spatrick ConsumeToken(); // consume flag
1603e5dd7070Spatrick }
1604e5dd7070Spatrick
1605e5dd7070Spatrick if (!T.consumeClose()) {
1606e5dd7070Spatrick Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc,
1607e5dd7070Spatrick ArgumentKind, MatchingCType.get(),
1608e5dd7070Spatrick LayoutCompatible, MustBeNull, Syntax);
1609e5dd7070Spatrick }
1610e5dd7070Spatrick
1611e5dd7070Spatrick if (EndLoc)
1612e5dd7070Spatrick *EndLoc = T.getCloseLocation();
1613e5dd7070Spatrick }
1614e5dd7070Spatrick
1615e5dd7070Spatrick /// DiagnoseProhibitedCXX11Attribute - We have found the opening square brackets
1616e5dd7070Spatrick /// of a C++11 attribute-specifier in a location where an attribute is not
1617e5dd7070Spatrick /// permitted. By C++11 [dcl.attr.grammar]p6, this is ill-formed. Diagnose this
1618e5dd7070Spatrick /// situation.
1619e5dd7070Spatrick ///
1620e5dd7070Spatrick /// \return \c true if we skipped an attribute-like chunk of tokens, \c false if
1621e5dd7070Spatrick /// this doesn't appear to actually be an attribute-specifier, and the caller
1622e5dd7070Spatrick /// should try to parse it.
DiagnoseProhibitedCXX11Attribute()1623e5dd7070Spatrick bool Parser::DiagnoseProhibitedCXX11Attribute() {
1624e5dd7070Spatrick assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square));
1625e5dd7070Spatrick
1626e5dd7070Spatrick switch (isCXX11AttributeSpecifier(/*Disambiguate*/true)) {
1627e5dd7070Spatrick case CAK_NotAttributeSpecifier:
1628e5dd7070Spatrick // No diagnostic: we're in Obj-C++11 and this is not actually an attribute.
1629e5dd7070Spatrick return false;
1630e5dd7070Spatrick
1631e5dd7070Spatrick case CAK_InvalidAttributeSpecifier:
1632e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_l_square_l_square_not_attribute);
1633e5dd7070Spatrick return false;
1634e5dd7070Spatrick
1635e5dd7070Spatrick case CAK_AttributeSpecifier:
1636e5dd7070Spatrick // Parse and discard the attributes.
1637e5dd7070Spatrick SourceLocation BeginLoc = ConsumeBracket();
1638e5dd7070Spatrick ConsumeBracket();
1639e5dd7070Spatrick SkipUntil(tok::r_square);
1640e5dd7070Spatrick assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied");
1641e5dd7070Spatrick SourceLocation EndLoc = ConsumeBracket();
1642e5dd7070Spatrick Diag(BeginLoc, diag::err_attributes_not_allowed)
1643e5dd7070Spatrick << SourceRange(BeginLoc, EndLoc);
1644e5dd7070Spatrick return true;
1645e5dd7070Spatrick }
1646e5dd7070Spatrick llvm_unreachable("All cases handled above.");
1647e5dd7070Spatrick }
1648e5dd7070Spatrick
1649e5dd7070Spatrick /// We have found the opening square brackets of a C++11
1650e5dd7070Spatrick /// attribute-specifier in a location where an attribute is not permitted, but
1651e5dd7070Spatrick /// we know where the attributes ought to be written. Parse them anyway, and
1652e5dd7070Spatrick /// provide a fixit moving them to the right place.
DiagnoseMisplacedCXX11Attribute(ParsedAttributes & Attrs,SourceLocation CorrectLocation)1653*12c85518Srobert void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs,
1654e5dd7070Spatrick SourceLocation CorrectLocation) {
1655e5dd7070Spatrick assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
1656e5dd7070Spatrick Tok.is(tok::kw_alignas));
1657e5dd7070Spatrick
1658e5dd7070Spatrick // Consume the attributes.
1659e5dd7070Spatrick SourceLocation Loc = Tok.getLocation();
1660e5dd7070Spatrick ParseCXX11Attributes(Attrs);
1661e5dd7070Spatrick CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
1662e5dd7070Spatrick // FIXME: use err_attributes_misplaced
1663e5dd7070Spatrick Diag(Loc, diag::err_attributes_not_allowed)
1664e5dd7070Spatrick << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
1665e5dd7070Spatrick << FixItHint::CreateRemoval(AttrRange);
1666e5dd7070Spatrick }
1667e5dd7070Spatrick
DiagnoseProhibitedAttributes(const SourceRange & Range,const SourceLocation CorrectLocation)1668e5dd7070Spatrick void Parser::DiagnoseProhibitedAttributes(
1669e5dd7070Spatrick const SourceRange &Range, const SourceLocation CorrectLocation) {
1670e5dd7070Spatrick if (CorrectLocation.isValid()) {
1671e5dd7070Spatrick CharSourceRange AttrRange(Range, true);
1672e5dd7070Spatrick Diag(CorrectLocation, diag::err_attributes_misplaced)
1673e5dd7070Spatrick << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
1674e5dd7070Spatrick << FixItHint::CreateRemoval(AttrRange);
1675e5dd7070Spatrick } else
1676e5dd7070Spatrick Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range;
1677e5dd7070Spatrick }
1678e5dd7070Spatrick
ProhibitCXX11Attributes(ParsedAttributes & Attrs,unsigned DiagID,bool DiagnoseEmptyAttrs,bool WarnOnUnknownAttrs)1679*12c85518Srobert void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned DiagID,
1680*12c85518Srobert bool DiagnoseEmptyAttrs,
1681*12c85518Srobert bool WarnOnUnknownAttrs) {
1682a9ac8606Spatrick
1683a9ac8606Spatrick if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) {
1684a9ac8606Spatrick // An attribute list has been parsed, but it was empty.
1685a9ac8606Spatrick // This is the case for [[]].
1686a9ac8606Spatrick const auto &LangOpts = getLangOpts();
1687a9ac8606Spatrick auto &SM = PP.getSourceManager();
1688a9ac8606Spatrick Token FirstLSquare;
1689a9ac8606Spatrick Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts);
1690a9ac8606Spatrick
1691a9ac8606Spatrick if (FirstLSquare.is(tok::l_square)) {
1692*12c85518Srobert std::optional<Token> SecondLSquare =
1693a9ac8606Spatrick Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts);
1694a9ac8606Spatrick
1695a9ac8606Spatrick if (SecondLSquare && SecondLSquare->is(tok::l_square)) {
1696a9ac8606Spatrick // The attribute range starts with [[, but is empty. So this must
1697a9ac8606Spatrick // be [[]], which we are supposed to diagnose because
1698a9ac8606Spatrick // DiagnoseEmptyAttrs is true.
1699a9ac8606Spatrick Diag(Attrs.Range.getBegin(), DiagID) << Attrs.Range;
1700a9ac8606Spatrick return;
1701a9ac8606Spatrick }
1702a9ac8606Spatrick }
1703a9ac8606Spatrick }
1704a9ac8606Spatrick
1705e5dd7070Spatrick for (const ParsedAttr &AL : Attrs) {
1706e5dd7070Spatrick if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
1707e5dd7070Spatrick continue;
1708*12c85518Srobert if (AL.getKind() == ParsedAttr::UnknownAttribute) {
1709*12c85518Srobert if (WarnOnUnknownAttrs)
1710a9ac8606Spatrick Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
1711a9ac8606Spatrick << AL << AL.getRange();
1712*12c85518Srobert } else {
1713e5dd7070Spatrick Diag(AL.getLoc(), DiagID) << AL;
1714e5dd7070Spatrick AL.setInvalid();
1715e5dd7070Spatrick }
1716e5dd7070Spatrick }
1717e5dd7070Spatrick }
1718e5dd7070Spatrick
DiagnoseCXX11AttributeExtension(ParsedAttributes & Attrs)1719*12c85518Srobert void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) {
1720a9ac8606Spatrick for (const ParsedAttr &PA : Attrs) {
1721a9ac8606Spatrick if (PA.isCXX11Attribute() || PA.isC2xAttribute())
1722a9ac8606Spatrick Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) << PA << PA.getRange();
1723a9ac8606Spatrick }
1724a9ac8606Spatrick }
1725a9ac8606Spatrick
1726e5dd7070Spatrick // Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
1727e5dd7070Spatrick // applies to var, not the type Foo.
1728e5dd7070Spatrick // As an exception to the rule, __declspec(align(...)) before the
1729e5dd7070Spatrick // class-key affects the type instead of the variable.
1730e5dd7070Spatrick // Also, Microsoft-style [attributes] seem to affect the type instead of the
1731e5dd7070Spatrick // variable.
1732e5dd7070Spatrick // This function moves attributes that should apply to the type off DS to Attrs.
stripTypeAttributesOffDeclSpec(ParsedAttributes & Attrs,DeclSpec & DS,Sema::TagUseKind TUK)1733*12c85518Srobert void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs,
1734e5dd7070Spatrick DeclSpec &DS,
1735e5dd7070Spatrick Sema::TagUseKind TUK) {
1736e5dd7070Spatrick if (TUK == Sema::TUK_Reference)
1737e5dd7070Spatrick return;
1738e5dd7070Spatrick
1739e5dd7070Spatrick llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;
1740e5dd7070Spatrick
1741e5dd7070Spatrick for (ParsedAttr &AL : DS.getAttributes()) {
1742e5dd7070Spatrick if ((AL.getKind() == ParsedAttr::AT_Aligned &&
1743e5dd7070Spatrick AL.isDeclspecAttribute()) ||
1744e5dd7070Spatrick AL.isMicrosoftAttribute())
1745e5dd7070Spatrick ToBeMoved.push_back(&AL);
1746e5dd7070Spatrick }
1747e5dd7070Spatrick
1748e5dd7070Spatrick for (ParsedAttr *AL : ToBeMoved) {
1749e5dd7070Spatrick DS.getAttributes().remove(AL);
1750e5dd7070Spatrick Attrs.addAtEnd(AL);
1751e5dd7070Spatrick }
1752e5dd7070Spatrick }
1753e5dd7070Spatrick
1754e5dd7070Spatrick /// ParseDeclaration - Parse a full 'declaration', which consists of
1755e5dd7070Spatrick /// declaration-specifiers, some number of declarators, and a semicolon.
1756e5dd7070Spatrick /// 'Context' should be a DeclaratorContext value. This returns the
1757e5dd7070Spatrick /// location of the semicolon in DeclEnd.
1758e5dd7070Spatrick ///
1759e5dd7070Spatrick /// declaration: [C99 6.7]
1760e5dd7070Spatrick /// block-declaration ->
1761e5dd7070Spatrick /// simple-declaration
1762e5dd7070Spatrick /// others [FIXME]
1763e5dd7070Spatrick /// [C++] template-declaration
1764e5dd7070Spatrick /// [C++] namespace-definition
1765e5dd7070Spatrick /// [C++] using-directive
1766e5dd7070Spatrick /// [C++] using-declaration
1767e5dd7070Spatrick /// [C++11/C11] static_assert-declaration
1768e5dd7070Spatrick /// others... [FIXME]
1769e5dd7070Spatrick ///
ParseDeclaration(DeclaratorContext Context,SourceLocation & DeclEnd,ParsedAttributes & DeclAttrs,ParsedAttributes & DeclSpecAttrs,SourceLocation * DeclSpecStart)1770*12c85518Srobert Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
1771*12c85518Srobert SourceLocation &DeclEnd,
1772*12c85518Srobert ParsedAttributes &DeclAttrs,
1773*12c85518Srobert ParsedAttributes &DeclSpecAttrs,
1774e5dd7070Spatrick SourceLocation *DeclSpecStart) {
1775e5dd7070Spatrick ParenBraceBracketBalancer BalancerRAIIObj(*this);
1776e5dd7070Spatrick // Must temporarily exit the objective-c container scope for
1777e5dd7070Spatrick // parsing c none objective-c decls.
1778e5dd7070Spatrick ObjCDeclContextSwitch ObjCDC(*this);
1779e5dd7070Spatrick
1780e5dd7070Spatrick Decl *SingleDecl = nullptr;
1781e5dd7070Spatrick switch (Tok.getKind()) {
1782e5dd7070Spatrick case tok::kw_template:
1783e5dd7070Spatrick case tok::kw_export:
1784*12c85518Srobert ProhibitAttributes(DeclAttrs);
1785*12c85518Srobert ProhibitAttributes(DeclSpecAttrs);
1786*12c85518Srobert SingleDecl =
1787*12c85518Srobert ParseDeclarationStartingWithTemplate(Context, DeclEnd, DeclAttrs);
1788e5dd7070Spatrick break;
1789e5dd7070Spatrick case tok::kw_inline:
1790e5dd7070Spatrick // Could be the start of an inline namespace. Allowed as an ext in C++03.
1791e5dd7070Spatrick if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) {
1792*12c85518Srobert ProhibitAttributes(DeclAttrs);
1793*12c85518Srobert ProhibitAttributes(DeclSpecAttrs);
1794e5dd7070Spatrick SourceLocation InlineLoc = ConsumeToken();
1795e5dd7070Spatrick return ParseNamespace(Context, DeclEnd, InlineLoc);
1796e5dd7070Spatrick }
1797*12c85518Srobert return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,
1798*12c85518Srobert true, nullptr, DeclSpecStart);
1799*12c85518Srobert
1800*12c85518Srobert case tok::kw_cbuffer:
1801*12c85518Srobert case tok::kw_tbuffer:
1802*12c85518Srobert SingleDecl = ParseHLSLBuffer(DeclEnd);
1803*12c85518Srobert break;
1804e5dd7070Spatrick case tok::kw_namespace:
1805*12c85518Srobert ProhibitAttributes(DeclAttrs);
1806*12c85518Srobert ProhibitAttributes(DeclSpecAttrs);
1807e5dd7070Spatrick return ParseNamespace(Context, DeclEnd);
1808*12c85518Srobert case tok::kw_using: {
1809*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
1810*12c85518Srobert takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs);
1811e5dd7070Spatrick return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
1812*12c85518Srobert DeclEnd, Attrs);
1813*12c85518Srobert }
1814e5dd7070Spatrick case tok::kw_static_assert:
1815e5dd7070Spatrick case tok::kw__Static_assert:
1816*12c85518Srobert ProhibitAttributes(DeclAttrs);
1817*12c85518Srobert ProhibitAttributes(DeclSpecAttrs);
1818e5dd7070Spatrick SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
1819e5dd7070Spatrick break;
1820e5dd7070Spatrick default:
1821*12c85518Srobert return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,
1822*12c85518Srobert true, nullptr, DeclSpecStart);
1823e5dd7070Spatrick }
1824e5dd7070Spatrick
1825e5dd7070Spatrick // This routine returns a DeclGroup, if the thing we parsed only contains a
1826e5dd7070Spatrick // single decl, convert it now.
1827e5dd7070Spatrick return Actions.ConvertDeclToDeclGroup(SingleDecl);
1828e5dd7070Spatrick }
1829e5dd7070Spatrick
1830e5dd7070Spatrick /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
1831e5dd7070Spatrick /// declaration-specifiers init-declarator-list[opt] ';'
1832e5dd7070Spatrick /// [C++11] attribute-specifier-seq decl-specifier-seq[opt]
1833e5dd7070Spatrick /// init-declarator-list ';'
1834e5dd7070Spatrick ///[C90/C++]init-declarator-list ';' [TODO]
1835e5dd7070Spatrick /// [OMP] threadprivate-directive
1836e5dd7070Spatrick /// [OMP] allocate-directive [TODO]
1837e5dd7070Spatrick ///
1838e5dd7070Spatrick /// for-range-declaration: [C++11 6.5p1: stmt.ranged]
1839e5dd7070Spatrick /// attribute-specifier-seq[opt] type-specifier-seq declarator
1840e5dd7070Spatrick ///
1841e5dd7070Spatrick /// If RequireSemi is false, this does not check for a ';' at the end of the
1842e5dd7070Spatrick /// declaration. If it is true, it checks for and eats it.
1843e5dd7070Spatrick ///
1844e5dd7070Spatrick /// If FRI is non-null, we might be parsing a for-range-declaration instead
1845e5dd7070Spatrick /// of a simple-declaration. If we find that we are, we also parse the
1846e5dd7070Spatrick /// for-range-initializer, and place it here.
1847e5dd7070Spatrick ///
1848e5dd7070Spatrick /// DeclSpecStart is used when decl-specifiers are parsed before parsing
1849e5dd7070Spatrick /// the Declaration. The SourceLocation for this Decl is set to
1850e5dd7070Spatrick /// DeclSpecStart if DeclSpecStart is non-null.
ParseSimpleDeclaration(DeclaratorContext Context,SourceLocation & DeclEnd,ParsedAttributes & DeclAttrs,ParsedAttributes & DeclSpecAttrs,bool RequireSemi,ForRangeInit * FRI,SourceLocation * DeclSpecStart)1851e5dd7070Spatrick Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
1852e5dd7070Spatrick DeclaratorContext Context, SourceLocation &DeclEnd,
1853*12c85518Srobert ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs,
1854*12c85518Srobert bool RequireSemi, ForRangeInit *FRI, SourceLocation *DeclSpecStart) {
1855*12c85518Srobert // Need to retain these for diagnostics before we add them to the DeclSepc.
1856*12c85518Srobert ParsedAttributesView OriginalDeclSpecAttrs;
1857*12c85518Srobert OriginalDeclSpecAttrs.addAll(DeclSpecAttrs.begin(), DeclSpecAttrs.end());
1858*12c85518Srobert OriginalDeclSpecAttrs.Range = DeclSpecAttrs.Range;
1859*12c85518Srobert
1860e5dd7070Spatrick // Parse the common declaration-specifiers piece.
1861e5dd7070Spatrick ParsingDeclSpec DS(*this);
1862*12c85518Srobert DS.takeAttributesFrom(DeclSpecAttrs);
1863e5dd7070Spatrick
1864e5dd7070Spatrick DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);
1865e5dd7070Spatrick ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext);
1866e5dd7070Spatrick
1867e5dd7070Spatrick // If we had a free-standing type definition with a missing semicolon, we
1868e5dd7070Spatrick // may get this far before the problem becomes obvious.
1869e5dd7070Spatrick if (DS.hasTagDefinition() &&
1870e5dd7070Spatrick DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext))
1871e5dd7070Spatrick return nullptr;
1872e5dd7070Spatrick
1873e5dd7070Spatrick // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
1874e5dd7070Spatrick // declaration-specifiers init-declarator-list[opt] ';'
1875e5dd7070Spatrick if (Tok.is(tok::semi)) {
1876*12c85518Srobert ProhibitAttributes(DeclAttrs);
1877e5dd7070Spatrick DeclEnd = Tok.getLocation();
1878e5dd7070Spatrick if (RequireSemi) ConsumeToken();
1879e5dd7070Spatrick RecordDecl *AnonRecord = nullptr;
1880*12c85518Srobert Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
1881*12c85518Srobert getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
1882e5dd7070Spatrick DS.complete(TheDecl);
1883e5dd7070Spatrick if (AnonRecord) {
1884e5dd7070Spatrick Decl* decls[] = {AnonRecord, TheDecl};
1885e5dd7070Spatrick return Actions.BuildDeclaratorGroup(decls);
1886e5dd7070Spatrick }
1887e5dd7070Spatrick return Actions.ConvertDeclToDeclGroup(TheDecl);
1888e5dd7070Spatrick }
1889e5dd7070Spatrick
1890e5dd7070Spatrick if (DeclSpecStart)
1891e5dd7070Spatrick DS.SetRangeStart(*DeclSpecStart);
1892e5dd7070Spatrick
1893*12c85518Srobert return ParseDeclGroup(DS, Context, DeclAttrs, &DeclEnd, FRI);
1894e5dd7070Spatrick }
1895e5dd7070Spatrick
1896e5dd7070Spatrick /// Returns true if this might be the start of a declarator, or a common typo
1897e5dd7070Spatrick /// for a declarator.
MightBeDeclarator(DeclaratorContext Context)1898e5dd7070Spatrick bool Parser::MightBeDeclarator(DeclaratorContext Context) {
1899e5dd7070Spatrick switch (Tok.getKind()) {
1900e5dd7070Spatrick case tok::annot_cxxscope:
1901e5dd7070Spatrick case tok::annot_template_id:
1902e5dd7070Spatrick case tok::caret:
1903e5dd7070Spatrick case tok::code_completion:
1904e5dd7070Spatrick case tok::coloncolon:
1905e5dd7070Spatrick case tok::ellipsis:
1906e5dd7070Spatrick case tok::kw___attribute:
1907e5dd7070Spatrick case tok::kw_operator:
1908e5dd7070Spatrick case tok::l_paren:
1909e5dd7070Spatrick case tok::star:
1910e5dd7070Spatrick return true;
1911e5dd7070Spatrick
1912e5dd7070Spatrick case tok::amp:
1913e5dd7070Spatrick case tok::ampamp:
1914e5dd7070Spatrick return getLangOpts().CPlusPlus;
1915e5dd7070Spatrick
1916e5dd7070Spatrick case tok::l_square: // Might be an attribute on an unnamed bit-field.
1917a9ac8606Spatrick return Context == DeclaratorContext::Member && getLangOpts().CPlusPlus11 &&
1918a9ac8606Spatrick NextToken().is(tok::l_square);
1919e5dd7070Spatrick
1920e5dd7070Spatrick case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
1921a9ac8606Spatrick return Context == DeclaratorContext::Member || getLangOpts().CPlusPlus;
1922e5dd7070Spatrick
1923e5dd7070Spatrick case tok::identifier:
1924e5dd7070Spatrick switch (NextToken().getKind()) {
1925e5dd7070Spatrick case tok::code_completion:
1926e5dd7070Spatrick case tok::coloncolon:
1927e5dd7070Spatrick case tok::comma:
1928e5dd7070Spatrick case tok::equal:
1929e5dd7070Spatrick case tok::equalequal: // Might be a typo for '='.
1930e5dd7070Spatrick case tok::kw_alignas:
1931e5dd7070Spatrick case tok::kw_asm:
1932e5dd7070Spatrick case tok::kw___attribute:
1933e5dd7070Spatrick case tok::l_brace:
1934e5dd7070Spatrick case tok::l_paren:
1935e5dd7070Spatrick case tok::l_square:
1936e5dd7070Spatrick case tok::less:
1937e5dd7070Spatrick case tok::r_brace:
1938e5dd7070Spatrick case tok::r_paren:
1939e5dd7070Spatrick case tok::r_square:
1940e5dd7070Spatrick case tok::semi:
1941e5dd7070Spatrick return true;
1942e5dd7070Spatrick
1943e5dd7070Spatrick case tok::colon:
1944e5dd7070Spatrick // At namespace scope, 'identifier:' is probably a typo for 'identifier::'
1945e5dd7070Spatrick // and in block scope it's probably a label. Inside a class definition,
1946e5dd7070Spatrick // this is a bit-field.
1947a9ac8606Spatrick return Context == DeclaratorContext::Member ||
1948a9ac8606Spatrick (getLangOpts().CPlusPlus && Context == DeclaratorContext::File);
1949e5dd7070Spatrick
1950e5dd7070Spatrick case tok::identifier: // Possible virt-specifier.
1951e5dd7070Spatrick return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
1952e5dd7070Spatrick
1953e5dd7070Spatrick default:
1954e5dd7070Spatrick return false;
1955e5dd7070Spatrick }
1956e5dd7070Spatrick
1957e5dd7070Spatrick default:
1958e5dd7070Spatrick return false;
1959e5dd7070Spatrick }
1960e5dd7070Spatrick }
1961e5dd7070Spatrick
1962e5dd7070Spatrick /// Skip until we reach something which seems like a sensible place to pick
1963e5dd7070Spatrick /// up parsing after a malformed declaration. This will sometimes stop sooner
1964e5dd7070Spatrick /// than SkipUntil(tok::r_brace) would, but will never stop later.
SkipMalformedDecl()1965e5dd7070Spatrick void Parser::SkipMalformedDecl() {
1966e5dd7070Spatrick while (true) {
1967e5dd7070Spatrick switch (Tok.getKind()) {
1968e5dd7070Spatrick case tok::l_brace:
1969e5dd7070Spatrick // Skip until matching }, then stop. We've probably skipped over
1970e5dd7070Spatrick // a malformed class or function definition or similar.
1971e5dd7070Spatrick ConsumeBrace();
1972e5dd7070Spatrick SkipUntil(tok::r_brace);
1973e5dd7070Spatrick if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) {
1974e5dd7070Spatrick // This declaration isn't over yet. Keep skipping.
1975e5dd7070Spatrick continue;
1976e5dd7070Spatrick }
1977e5dd7070Spatrick TryConsumeToken(tok::semi);
1978e5dd7070Spatrick return;
1979e5dd7070Spatrick
1980e5dd7070Spatrick case tok::l_square:
1981e5dd7070Spatrick ConsumeBracket();
1982e5dd7070Spatrick SkipUntil(tok::r_square);
1983e5dd7070Spatrick continue;
1984e5dd7070Spatrick
1985e5dd7070Spatrick case tok::l_paren:
1986e5dd7070Spatrick ConsumeParen();
1987e5dd7070Spatrick SkipUntil(tok::r_paren);
1988e5dd7070Spatrick continue;
1989e5dd7070Spatrick
1990e5dd7070Spatrick case tok::r_brace:
1991e5dd7070Spatrick return;
1992e5dd7070Spatrick
1993e5dd7070Spatrick case tok::semi:
1994e5dd7070Spatrick ConsumeToken();
1995e5dd7070Spatrick return;
1996e5dd7070Spatrick
1997e5dd7070Spatrick case tok::kw_inline:
1998e5dd7070Spatrick // 'inline namespace' at the start of a line is almost certainly
1999e5dd7070Spatrick // a good place to pick back up parsing, except in an Objective-C
2000e5dd7070Spatrick // @interface context.
2001e5dd7070Spatrick if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) &&
2002e5dd7070Spatrick (!ParsingInObjCContainer || CurParsedObjCImpl))
2003e5dd7070Spatrick return;
2004e5dd7070Spatrick break;
2005e5dd7070Spatrick
2006e5dd7070Spatrick case tok::kw_namespace:
2007e5dd7070Spatrick // 'namespace' at the start of a line is almost certainly a good
2008e5dd7070Spatrick // place to pick back up parsing, except in an Objective-C
2009e5dd7070Spatrick // @interface context.
2010e5dd7070Spatrick if (Tok.isAtStartOfLine() &&
2011e5dd7070Spatrick (!ParsingInObjCContainer || CurParsedObjCImpl))
2012e5dd7070Spatrick return;
2013e5dd7070Spatrick break;
2014e5dd7070Spatrick
2015e5dd7070Spatrick case tok::at:
2016e5dd7070Spatrick // @end is very much like } in Objective-C contexts.
2017e5dd7070Spatrick if (NextToken().isObjCAtKeyword(tok::objc_end) &&
2018e5dd7070Spatrick ParsingInObjCContainer)
2019e5dd7070Spatrick return;
2020e5dd7070Spatrick break;
2021e5dd7070Spatrick
2022e5dd7070Spatrick case tok::minus:
2023e5dd7070Spatrick case tok::plus:
2024e5dd7070Spatrick // - and + probably start new method declarations in Objective-C contexts.
2025e5dd7070Spatrick if (Tok.isAtStartOfLine() && ParsingInObjCContainer)
2026e5dd7070Spatrick return;
2027e5dd7070Spatrick break;
2028e5dd7070Spatrick
2029e5dd7070Spatrick case tok::eof:
2030e5dd7070Spatrick case tok::annot_module_begin:
2031e5dd7070Spatrick case tok::annot_module_end:
2032e5dd7070Spatrick case tok::annot_module_include:
2033e5dd7070Spatrick return;
2034e5dd7070Spatrick
2035e5dd7070Spatrick default:
2036e5dd7070Spatrick break;
2037e5dd7070Spatrick }
2038e5dd7070Spatrick
2039e5dd7070Spatrick ConsumeAnyToken();
2040e5dd7070Spatrick }
2041e5dd7070Spatrick }
2042e5dd7070Spatrick
2043e5dd7070Spatrick /// ParseDeclGroup - Having concluded that this is either a function
2044e5dd7070Spatrick /// definition or a group of object declarations, actually parse the
2045e5dd7070Spatrick /// result.
ParseDeclGroup(ParsingDeclSpec & DS,DeclaratorContext Context,ParsedAttributes & Attrs,SourceLocation * DeclEnd,ForRangeInit * FRI)2046e5dd7070Spatrick Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
2047e5dd7070Spatrick DeclaratorContext Context,
2048*12c85518Srobert ParsedAttributes &Attrs,
2049e5dd7070Spatrick SourceLocation *DeclEnd,
2050e5dd7070Spatrick ForRangeInit *FRI) {
2051e5dd7070Spatrick // Parse the first declarator.
2052*12c85518Srobert // Consume all of the attributes from `Attrs` by moving them to our own local
2053*12c85518Srobert // list. This ensures that we will not attempt to interpret them as statement
2054*12c85518Srobert // attributes higher up the callchain.
2055*12c85518Srobert ParsedAttributes LocalAttrs(AttrFactory);
2056*12c85518Srobert LocalAttrs.takeAllFrom(Attrs);
2057*12c85518Srobert ParsingDeclarator D(*this, DS, LocalAttrs, Context);
2058e5dd7070Spatrick ParseDeclarator(D);
2059e5dd7070Spatrick
2060e5dd7070Spatrick // Bail out if the first declarator didn't seem well-formed.
2061e5dd7070Spatrick if (!D.hasName() && !D.mayOmitIdentifier()) {
2062e5dd7070Spatrick SkipMalformedDecl();
2063e5dd7070Spatrick return nullptr;
2064e5dd7070Spatrick }
2065e5dd7070Spatrick
2066*12c85518Srobert if (getLangOpts().HLSL)
2067*12c85518Srobert MaybeParseHLSLSemantics(D);
2068*12c85518Srobert
2069e5dd7070Spatrick if (Tok.is(tok::kw_requires))
2070e5dd7070Spatrick ParseTrailingRequiresClause(D);
2071e5dd7070Spatrick
2072e5dd7070Spatrick // Save late-parsed attributes for now; they need to be parsed in the
2073e5dd7070Spatrick // appropriate function scope after the function Decl has been constructed.
2074e5dd7070Spatrick // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList.
2075e5dd7070Spatrick LateParsedAttrList LateParsedAttrs(true);
2076e5dd7070Spatrick if (D.isFunctionDeclarator()) {
2077e5dd7070Spatrick MaybeParseGNUAttributes(D, &LateParsedAttrs);
2078e5dd7070Spatrick
2079e5dd7070Spatrick // The _Noreturn keyword can't appear here, unlike the GNU noreturn
2080e5dd7070Spatrick // attribute. If we find the keyword here, tell the user to put it
2081e5dd7070Spatrick // at the start instead.
2082e5dd7070Spatrick if (Tok.is(tok::kw__Noreturn)) {
2083e5dd7070Spatrick SourceLocation Loc = ConsumeToken();
2084e5dd7070Spatrick const char *PrevSpec;
2085e5dd7070Spatrick unsigned DiagID;
2086e5dd7070Spatrick
2087e5dd7070Spatrick // We can offer a fixit if it's valid to mark this function as _Noreturn
2088e5dd7070Spatrick // and we don't have any other declarators in this declaration.
2089e5dd7070Spatrick bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
2090e5dd7070Spatrick MaybeParseGNUAttributes(D, &LateParsedAttrs);
2091e5dd7070Spatrick Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try);
2092e5dd7070Spatrick
2093e5dd7070Spatrick Diag(Loc, diag::err_c11_noreturn_misplaced)
2094e5dd7070Spatrick << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())
2095e5dd7070Spatrick << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ")
2096e5dd7070Spatrick : FixItHint());
2097e5dd7070Spatrick }
2098e5dd7070Spatrick
2099e5dd7070Spatrick // Check to see if we have a function *definition* which must have a body.
2100ec727ea7Spatrick if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) {
2101ec727ea7Spatrick cutOffParsing();
2102a9ac8606Spatrick Actions.CodeCompleteAfterFunctionEquals(D);
2103ec727ea7Spatrick return nullptr;
2104ec727ea7Spatrick }
2105*12c85518Srobert // We're at the point where the parsing of function declarator is finished.
2106*12c85518Srobert //
2107*12c85518Srobert // A common error is that users accidently add a virtual specifier
2108*12c85518Srobert // (e.g. override) in an out-line method definition.
2109*12c85518Srobert // We attempt to recover by stripping all these specifiers coming after
2110*12c85518Srobert // the declarator.
2111*12c85518Srobert while (auto Specifier = isCXX11VirtSpecifier()) {
2112*12c85518Srobert Diag(Tok, diag::err_virt_specifier_outside_class)
2113*12c85518Srobert << VirtSpecifiers::getSpecifierName(Specifier)
2114*12c85518Srobert << FixItHint::CreateRemoval(Tok.getLocation());
2115*12c85518Srobert ConsumeToken();
2116*12c85518Srobert }
2117e5dd7070Spatrick // Look at the next token to make sure that this isn't a function
2118e5dd7070Spatrick // declaration. We have to check this because __attribute__ might be the
2119e5dd7070Spatrick // start of a function definition in GCC-extended K&R C.
2120ec727ea7Spatrick if (!isDeclarationAfterDeclarator()) {
2121e5dd7070Spatrick
2122e5dd7070Spatrick // Function definitions are only allowed at file scope and in C++ classes.
2123e5dd7070Spatrick // The C++ inline method definition case is handled elsewhere, so we only
2124e5dd7070Spatrick // need to handle the file scope definition case.
2125a9ac8606Spatrick if (Context == DeclaratorContext::File) {
2126e5dd7070Spatrick if (isStartOfFunctionDefinition(D)) {
2127e5dd7070Spatrick if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
2128e5dd7070Spatrick Diag(Tok, diag::err_function_declared_typedef);
2129e5dd7070Spatrick
2130e5dd7070Spatrick // Recover by treating the 'typedef' as spurious.
2131e5dd7070Spatrick DS.ClearStorageClassSpecs();
2132e5dd7070Spatrick }
2133e5dd7070Spatrick
2134ec727ea7Spatrick Decl *TheDecl = ParseFunctionDefinition(D, ParsedTemplateInfo(),
2135ec727ea7Spatrick &LateParsedAttrs);
2136e5dd7070Spatrick return Actions.ConvertDeclToDeclGroup(TheDecl);
2137e5dd7070Spatrick }
2138e5dd7070Spatrick
2139*12c85518Srobert if (isDeclarationSpecifier(ImplicitTypenameContext::No)) {
2140e5dd7070Spatrick // If there is an invalid declaration specifier right after the
2141e5dd7070Spatrick // function prototype, then we must be in a missing semicolon case
2142e5dd7070Spatrick // where this isn't actually a body. Just fall through into the code
2143e5dd7070Spatrick // that handles it as a prototype, and let the top-level code handle
2144e5dd7070Spatrick // the erroneous declspec where it would otherwise expect a comma or
2145e5dd7070Spatrick // semicolon.
2146e5dd7070Spatrick } else {
2147e5dd7070Spatrick Diag(Tok, diag::err_expected_fn_body);
2148e5dd7070Spatrick SkipUntil(tok::semi);
2149e5dd7070Spatrick return nullptr;
2150e5dd7070Spatrick }
2151e5dd7070Spatrick } else {
2152e5dd7070Spatrick if (Tok.is(tok::l_brace)) {
2153e5dd7070Spatrick Diag(Tok, diag::err_function_definition_not_allowed);
2154e5dd7070Spatrick SkipMalformedDecl();
2155e5dd7070Spatrick return nullptr;
2156e5dd7070Spatrick }
2157e5dd7070Spatrick }
2158e5dd7070Spatrick }
2159ec727ea7Spatrick }
2160e5dd7070Spatrick
2161e5dd7070Spatrick if (ParseAsmAttributesAfterDeclarator(D))
2162e5dd7070Spatrick return nullptr;
2163e5dd7070Spatrick
2164e5dd7070Spatrick // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we
2165e5dd7070Spatrick // must parse and analyze the for-range-initializer before the declaration is
2166e5dd7070Spatrick // analyzed.
2167e5dd7070Spatrick //
2168e5dd7070Spatrick // Handle the Objective-C for-in loop variable similarly, although we
2169e5dd7070Spatrick // don't need to parse the container in advance.
2170e5dd7070Spatrick if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {
2171e5dd7070Spatrick bool IsForRangeLoop = false;
2172e5dd7070Spatrick if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
2173e5dd7070Spatrick IsForRangeLoop = true;
2174e5dd7070Spatrick if (getLangOpts().OpenMP)
2175e5dd7070Spatrick Actions.startOpenMPCXXRangeFor();
2176e5dd7070Spatrick if (Tok.is(tok::l_brace))
2177e5dd7070Spatrick FRI->RangeExpr = ParseBraceInitializer();
2178e5dd7070Spatrick else
2179e5dd7070Spatrick FRI->RangeExpr = ParseExpression();
2180e5dd7070Spatrick }
2181e5dd7070Spatrick
2182e5dd7070Spatrick Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
2183e5dd7070Spatrick if (IsForRangeLoop) {
2184e5dd7070Spatrick Actions.ActOnCXXForRangeDecl(ThisDecl);
2185e5dd7070Spatrick } else {
2186e5dd7070Spatrick // Obj-C for loop
2187e5dd7070Spatrick if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl))
2188e5dd7070Spatrick VD->setObjCForDecl(true);
2189e5dd7070Spatrick }
2190e5dd7070Spatrick Actions.FinalizeDeclaration(ThisDecl);
2191e5dd7070Spatrick D.complete(ThisDecl);
2192e5dd7070Spatrick return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);
2193e5dd7070Spatrick }
2194e5dd7070Spatrick
2195e5dd7070Spatrick SmallVector<Decl *, 8> DeclsInGroup;
2196e5dd7070Spatrick Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(
2197e5dd7070Spatrick D, ParsedTemplateInfo(), FRI);
2198e5dd7070Spatrick if (LateParsedAttrs.size() > 0)
2199e5dd7070Spatrick ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);
2200e5dd7070Spatrick D.complete(FirstDecl);
2201e5dd7070Spatrick if (FirstDecl)
2202e5dd7070Spatrick DeclsInGroup.push_back(FirstDecl);
2203e5dd7070Spatrick
2204a9ac8606Spatrick bool ExpectSemi = Context != DeclaratorContext::ForInit;
2205e5dd7070Spatrick
2206e5dd7070Spatrick // If we don't have a comma, it is either the end of the list (a ';') or an
2207e5dd7070Spatrick // error, bail out.
2208e5dd7070Spatrick SourceLocation CommaLoc;
2209e5dd7070Spatrick while (TryConsumeToken(tok::comma, CommaLoc)) {
2210e5dd7070Spatrick if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) {
2211e5dd7070Spatrick // This comma was followed by a line-break and something which can't be
2212e5dd7070Spatrick // the start of a declarator. The comma was probably a typo for a
2213e5dd7070Spatrick // semicolon.
2214e5dd7070Spatrick Diag(CommaLoc, diag::err_expected_semi_declaration)
2215e5dd7070Spatrick << FixItHint::CreateReplacement(CommaLoc, ";");
2216e5dd7070Spatrick ExpectSemi = false;
2217e5dd7070Spatrick break;
2218e5dd7070Spatrick }
2219e5dd7070Spatrick
2220e5dd7070Spatrick // Parse the next declarator.
2221e5dd7070Spatrick D.clear();
2222e5dd7070Spatrick D.setCommaLoc(CommaLoc);
2223e5dd7070Spatrick
2224e5dd7070Spatrick // Accept attributes in an init-declarator. In the first declarator in a
2225e5dd7070Spatrick // declaration, these would be part of the declspec. In subsequent
2226e5dd7070Spatrick // declarators, they become part of the declarator itself, so that they
2227e5dd7070Spatrick // don't apply to declarators after *this* one. Examples:
2228e5dd7070Spatrick // short __attribute__((common)) var; -> declspec
2229e5dd7070Spatrick // short var __attribute__((common)); -> declarator
2230e5dd7070Spatrick // short x, __attribute__((common)) var; -> declarator
2231e5dd7070Spatrick MaybeParseGNUAttributes(D);
2232e5dd7070Spatrick
2233e5dd7070Spatrick // MSVC parses but ignores qualifiers after the comma as an extension.
2234e5dd7070Spatrick if (getLangOpts().MicrosoftExt)
2235e5dd7070Spatrick DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
2236e5dd7070Spatrick
2237e5dd7070Spatrick ParseDeclarator(D);
2238*12c85518Srobert
2239*12c85518Srobert if (getLangOpts().HLSL)
2240*12c85518Srobert MaybeParseHLSLSemantics(D);
2241*12c85518Srobert
2242e5dd7070Spatrick if (!D.isInvalidType()) {
2243e5dd7070Spatrick // C++2a [dcl.decl]p1
2244e5dd7070Spatrick // init-declarator:
2245e5dd7070Spatrick // declarator initializer[opt]
2246e5dd7070Spatrick // declarator requires-clause
2247e5dd7070Spatrick if (Tok.is(tok::kw_requires))
2248e5dd7070Spatrick ParseTrailingRequiresClause(D);
2249e5dd7070Spatrick Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
2250e5dd7070Spatrick D.complete(ThisDecl);
2251e5dd7070Spatrick if (ThisDecl)
2252e5dd7070Spatrick DeclsInGroup.push_back(ThisDecl);
2253e5dd7070Spatrick }
2254e5dd7070Spatrick }
2255e5dd7070Spatrick
2256e5dd7070Spatrick if (DeclEnd)
2257e5dd7070Spatrick *DeclEnd = Tok.getLocation();
2258e5dd7070Spatrick
2259a9ac8606Spatrick if (ExpectSemi && ExpectAndConsumeSemi(
2260a9ac8606Spatrick Context == DeclaratorContext::File
2261e5dd7070Spatrick ? diag::err_invalid_token_after_toplevel_declarator
2262e5dd7070Spatrick : diag::err_expected_semi_declaration)) {
2263e5dd7070Spatrick // Okay, there was no semicolon and one was expected. If we see a
2264e5dd7070Spatrick // declaration specifier, just assume it was missing and continue parsing.
2265e5dd7070Spatrick // Otherwise things are very confused and we skip to recover.
2266*12c85518Srobert if (!isDeclarationSpecifier(ImplicitTypenameContext::No)) {
2267e5dd7070Spatrick SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
2268e5dd7070Spatrick TryConsumeToken(tok::semi);
2269e5dd7070Spatrick }
2270e5dd7070Spatrick }
2271e5dd7070Spatrick
2272e5dd7070Spatrick return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
2273e5dd7070Spatrick }
2274e5dd7070Spatrick
2275e5dd7070Spatrick /// Parse an optional simple-asm-expr and attributes, and attach them to a
2276e5dd7070Spatrick /// declarator. Returns true on an error.
ParseAsmAttributesAfterDeclarator(Declarator & D)2277e5dd7070Spatrick bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
2278e5dd7070Spatrick // If a simple-asm-expr is present, parse it.
2279e5dd7070Spatrick if (Tok.is(tok::kw_asm)) {
2280e5dd7070Spatrick SourceLocation Loc;
2281e5dd7070Spatrick ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));
2282e5dd7070Spatrick if (AsmLabel.isInvalid()) {
2283e5dd7070Spatrick SkipUntil(tok::semi, StopBeforeMatch);
2284e5dd7070Spatrick return true;
2285e5dd7070Spatrick }
2286e5dd7070Spatrick
2287e5dd7070Spatrick D.setAsmLabel(AsmLabel.get());
2288e5dd7070Spatrick D.SetRangeEnd(Loc);
2289e5dd7070Spatrick }
2290e5dd7070Spatrick
2291e5dd7070Spatrick MaybeParseGNUAttributes(D);
2292e5dd7070Spatrick return false;
2293e5dd7070Spatrick }
2294e5dd7070Spatrick
2295e5dd7070Spatrick /// Parse 'declaration' after parsing 'declaration-specifiers
2296e5dd7070Spatrick /// declarator'. This method parses the remainder of the declaration
2297e5dd7070Spatrick /// (including any attributes or initializer, among other things) and
2298e5dd7070Spatrick /// finalizes the declaration.
2299e5dd7070Spatrick ///
2300e5dd7070Spatrick /// init-declarator: [C99 6.7]
2301e5dd7070Spatrick /// declarator
2302e5dd7070Spatrick /// declarator '=' initializer
2303e5dd7070Spatrick /// [GNU] declarator simple-asm-expr[opt] attributes[opt]
2304e5dd7070Spatrick /// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer
2305e5dd7070Spatrick /// [C++] declarator initializer[opt]
2306e5dd7070Spatrick ///
2307e5dd7070Spatrick /// [C++] initializer:
2308e5dd7070Spatrick /// [C++] '=' initializer-clause
2309e5dd7070Spatrick /// [C++] '(' expression-list ')'
2310e5dd7070Spatrick /// [C++0x] '=' 'default' [TODO]
2311e5dd7070Spatrick /// [C++0x] '=' 'delete'
2312e5dd7070Spatrick /// [C++0x] braced-init-list
2313e5dd7070Spatrick ///
2314e5dd7070Spatrick /// According to the standard grammar, =default and =delete are function
2315e5dd7070Spatrick /// definitions, but that definitely doesn't fit with the parser here.
2316e5dd7070Spatrick ///
ParseDeclarationAfterDeclarator(Declarator & D,const ParsedTemplateInfo & TemplateInfo)2317e5dd7070Spatrick Decl *Parser::ParseDeclarationAfterDeclarator(
2318e5dd7070Spatrick Declarator &D, const ParsedTemplateInfo &TemplateInfo) {
2319e5dd7070Spatrick if (ParseAsmAttributesAfterDeclarator(D))
2320e5dd7070Spatrick return nullptr;
2321e5dd7070Spatrick
2322e5dd7070Spatrick return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
2323e5dd7070Spatrick }
2324e5dd7070Spatrick
ParseDeclarationAfterDeclaratorAndAttributes(Declarator & D,const ParsedTemplateInfo & TemplateInfo,ForRangeInit * FRI)2325e5dd7070Spatrick Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
2326e5dd7070Spatrick Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
2327e5dd7070Spatrick // RAII type used to track whether we're inside an initializer.
2328e5dd7070Spatrick struct InitializerScopeRAII {
2329e5dd7070Spatrick Parser &P;
2330e5dd7070Spatrick Declarator &D;
2331e5dd7070Spatrick Decl *ThisDecl;
2332e5dd7070Spatrick
2333e5dd7070Spatrick InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
2334e5dd7070Spatrick : P(P), D(D), ThisDecl(ThisDecl) {
2335e5dd7070Spatrick if (ThisDecl && P.getLangOpts().CPlusPlus) {
2336e5dd7070Spatrick Scope *S = nullptr;
2337e5dd7070Spatrick if (D.getCXXScopeSpec().isSet()) {
2338e5dd7070Spatrick P.EnterScope(0);
2339e5dd7070Spatrick S = P.getCurScope();
2340e5dd7070Spatrick }
2341e5dd7070Spatrick P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
2342e5dd7070Spatrick }
2343e5dd7070Spatrick }
2344e5dd7070Spatrick ~InitializerScopeRAII() { pop(); }
2345e5dd7070Spatrick void pop() {
2346e5dd7070Spatrick if (ThisDecl && P.getLangOpts().CPlusPlus) {
2347e5dd7070Spatrick Scope *S = nullptr;
2348e5dd7070Spatrick if (D.getCXXScopeSpec().isSet())
2349e5dd7070Spatrick S = P.getCurScope();
2350e5dd7070Spatrick P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
2351e5dd7070Spatrick if (S)
2352e5dd7070Spatrick P.ExitScope();
2353e5dd7070Spatrick }
2354e5dd7070Spatrick ThisDecl = nullptr;
2355e5dd7070Spatrick }
2356e5dd7070Spatrick };
2357e5dd7070Spatrick
2358a9ac8606Spatrick enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced };
2359a9ac8606Spatrick InitKind TheInitKind;
2360a9ac8606Spatrick // If a '==' or '+=' is found, suggest a fixit to '='.
2361a9ac8606Spatrick if (isTokenEqualOrEqualTypo())
2362a9ac8606Spatrick TheInitKind = InitKind::Equal;
2363a9ac8606Spatrick else if (Tok.is(tok::l_paren))
2364a9ac8606Spatrick TheInitKind = InitKind::CXXDirect;
2365a9ac8606Spatrick else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
2366a9ac8606Spatrick (!CurParsedObjCImpl || !D.isFunctionDeclarator()))
2367a9ac8606Spatrick TheInitKind = InitKind::CXXBraced;
2368a9ac8606Spatrick else
2369a9ac8606Spatrick TheInitKind = InitKind::Uninitialized;
2370a9ac8606Spatrick if (TheInitKind != InitKind::Uninitialized)
2371a9ac8606Spatrick D.setHasInitializer();
2372a9ac8606Spatrick
2373a9ac8606Spatrick // Inform Sema that we just parsed this declarator.
2374e5dd7070Spatrick Decl *ThisDecl = nullptr;
2375a9ac8606Spatrick Decl *OuterDecl = nullptr;
2376e5dd7070Spatrick switch (TemplateInfo.Kind) {
2377e5dd7070Spatrick case ParsedTemplateInfo::NonTemplate:
2378e5dd7070Spatrick ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
2379e5dd7070Spatrick break;
2380e5dd7070Spatrick
2381e5dd7070Spatrick case ParsedTemplateInfo::Template:
2382e5dd7070Spatrick case ParsedTemplateInfo::ExplicitSpecialization: {
2383e5dd7070Spatrick ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
2384e5dd7070Spatrick *TemplateInfo.TemplateParams,
2385e5dd7070Spatrick D);
2386a9ac8606Spatrick if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl)) {
2387e5dd7070Spatrick // Re-direct this decl to refer to the templated decl so that we can
2388e5dd7070Spatrick // initialize it.
2389e5dd7070Spatrick ThisDecl = VT->getTemplatedDecl();
2390a9ac8606Spatrick OuterDecl = VT;
2391a9ac8606Spatrick }
2392e5dd7070Spatrick break;
2393e5dd7070Spatrick }
2394e5dd7070Spatrick case ParsedTemplateInfo::ExplicitInstantiation: {
2395e5dd7070Spatrick if (Tok.is(tok::semi)) {
2396e5dd7070Spatrick DeclResult ThisRes = Actions.ActOnExplicitInstantiation(
2397e5dd7070Spatrick getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
2398e5dd7070Spatrick if (ThisRes.isInvalid()) {
2399e5dd7070Spatrick SkipUntil(tok::semi, StopBeforeMatch);
2400e5dd7070Spatrick return nullptr;
2401e5dd7070Spatrick }
2402e5dd7070Spatrick ThisDecl = ThisRes.get();
2403e5dd7070Spatrick } else {
2404e5dd7070Spatrick // FIXME: This check should be for a variable template instantiation only.
2405e5dd7070Spatrick
2406e5dd7070Spatrick // Check that this is a valid instantiation
2407e5dd7070Spatrick if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
2408e5dd7070Spatrick // If the declarator-id is not a template-id, issue a diagnostic and
2409e5dd7070Spatrick // recover by ignoring the 'template' keyword.
2410e5dd7070Spatrick Diag(Tok, diag::err_template_defn_explicit_instantiation)
2411e5dd7070Spatrick << 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
2412e5dd7070Spatrick ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
2413e5dd7070Spatrick } else {
2414e5dd7070Spatrick SourceLocation LAngleLoc =
2415e5dd7070Spatrick PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
2416e5dd7070Spatrick Diag(D.getIdentifierLoc(),
2417e5dd7070Spatrick diag::err_explicit_instantiation_with_definition)
2418e5dd7070Spatrick << SourceRange(TemplateInfo.TemplateLoc)
2419e5dd7070Spatrick << FixItHint::CreateInsertion(LAngleLoc, "<>");
2420e5dd7070Spatrick
2421e5dd7070Spatrick // Recover as if it were an explicit specialization.
2422e5dd7070Spatrick TemplateParameterLists FakedParamLists;
2423e5dd7070Spatrick FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
2424*12c85518Srobert 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,
2425*12c85518Srobert std::nullopt, LAngleLoc, nullptr));
2426e5dd7070Spatrick
2427e5dd7070Spatrick ThisDecl =
2428e5dd7070Spatrick Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
2429e5dd7070Spatrick }
2430e5dd7070Spatrick }
2431e5dd7070Spatrick break;
2432e5dd7070Spatrick }
2433e5dd7070Spatrick }
2434e5dd7070Spatrick
2435a9ac8606Spatrick switch (TheInitKind) {
2436e5dd7070Spatrick // Parse declarator '=' initializer.
2437a9ac8606Spatrick case InitKind::Equal: {
2438e5dd7070Spatrick SourceLocation EqualLoc = ConsumeToken();
2439e5dd7070Spatrick
2440e5dd7070Spatrick if (Tok.is(tok::kw_delete)) {
2441e5dd7070Spatrick if (D.isFunctionDeclarator())
2442e5dd7070Spatrick Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
2443e5dd7070Spatrick << 1 /* delete */;
2444e5dd7070Spatrick else
2445e5dd7070Spatrick Diag(ConsumeToken(), diag::err_deleted_non_function);
2446e5dd7070Spatrick } else if (Tok.is(tok::kw_default)) {
2447e5dd7070Spatrick if (D.isFunctionDeclarator())
2448e5dd7070Spatrick Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
2449e5dd7070Spatrick << 0 /* default */;
2450e5dd7070Spatrick else
2451e5dd7070Spatrick Diag(ConsumeToken(), diag::err_default_special_members)
2452ec727ea7Spatrick << getLangOpts().CPlusPlus20;
2453e5dd7070Spatrick } else {
2454e5dd7070Spatrick InitializerScopeRAII InitScope(*this, D, ThisDecl);
2455e5dd7070Spatrick
2456e5dd7070Spatrick if (Tok.is(tok::code_completion)) {
2457a9ac8606Spatrick cutOffParsing();
2458e5dd7070Spatrick Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
2459e5dd7070Spatrick Actions.FinalizeDeclaration(ThisDecl);
2460e5dd7070Spatrick return nullptr;
2461e5dd7070Spatrick }
2462e5dd7070Spatrick
2463e5dd7070Spatrick PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
2464e5dd7070Spatrick ExprResult Init = ParseInitializer();
2465e5dd7070Spatrick
2466e5dd7070Spatrick // If this is the only decl in (possibly) range based for statement,
2467e5dd7070Spatrick // our best guess is that the user meant ':' instead of '='.
2468e5dd7070Spatrick if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) {
2469e5dd7070Spatrick Diag(EqualLoc, diag::err_single_decl_assign_in_for_range)
2470e5dd7070Spatrick << FixItHint::CreateReplacement(EqualLoc, ":");
2471e5dd7070Spatrick // We are trying to stop parser from looking for ';' in this for
2472e5dd7070Spatrick // statement, therefore preventing spurious errors to be issued.
2473e5dd7070Spatrick FRI->ColonLoc = EqualLoc;
2474e5dd7070Spatrick Init = ExprError();
2475e5dd7070Spatrick FRI->RangeExpr = Init;
2476e5dd7070Spatrick }
2477e5dd7070Spatrick
2478e5dd7070Spatrick InitScope.pop();
2479e5dd7070Spatrick
2480e5dd7070Spatrick if (Init.isInvalid()) {
2481e5dd7070Spatrick SmallVector<tok::TokenKind, 2> StopTokens;
2482e5dd7070Spatrick StopTokens.push_back(tok::comma);
2483a9ac8606Spatrick if (D.getContext() == DeclaratorContext::ForInit ||
2484a9ac8606Spatrick D.getContext() == DeclaratorContext::SelectionInit)
2485e5dd7070Spatrick StopTokens.push_back(tok::r_paren);
2486e5dd7070Spatrick SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
2487e5dd7070Spatrick Actions.ActOnInitializerError(ThisDecl);
2488e5dd7070Spatrick } else
2489e5dd7070Spatrick Actions.AddInitializerToDecl(ThisDecl, Init.get(),
2490e5dd7070Spatrick /*DirectInit=*/false);
2491e5dd7070Spatrick }
2492a9ac8606Spatrick break;
2493a9ac8606Spatrick }
2494a9ac8606Spatrick case InitKind::CXXDirect: {
2495e5dd7070Spatrick // Parse C++ direct initializer: '(' expression-list ')'
2496e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
2497e5dd7070Spatrick T.consumeOpen();
2498e5dd7070Spatrick
2499e5dd7070Spatrick ExprVector Exprs;
2500e5dd7070Spatrick
2501e5dd7070Spatrick InitializerScopeRAII InitScope(*this, D, ThisDecl);
2502e5dd7070Spatrick
2503e5dd7070Spatrick auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
2504e5dd7070Spatrick auto RunSignatureHelp = [&]() {
2505e5dd7070Spatrick QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
2506*12c85518Srobert ThisVarDecl->getType()->getCanonicalTypeInternal(),
2507*12c85518Srobert ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
2508*12c85518Srobert /*Braced=*/false);
2509e5dd7070Spatrick CalledSignatureHelp = true;
2510e5dd7070Spatrick return PreferredType;
2511e5dd7070Spatrick };
2512e5dd7070Spatrick auto SetPreferredType = [&] {
2513e5dd7070Spatrick PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
2514e5dd7070Spatrick };
2515e5dd7070Spatrick
2516e5dd7070Spatrick llvm::function_ref<void()> ExpressionStarts;
2517e5dd7070Spatrick if (ThisVarDecl) {
2518e5dd7070Spatrick // ParseExpressionList can sometimes succeed even when ThisDecl is not
2519e5dd7070Spatrick // VarDecl. This is an error and it is reported in a call to
2520e5dd7070Spatrick // Actions.ActOnInitializerError(). However, we call
2521e5dd7070Spatrick // ProduceConstructorSignatureHelp only on VarDecls.
2522e5dd7070Spatrick ExpressionStarts = SetPreferredType;
2523e5dd7070Spatrick }
2524*12c85518Srobert if (ParseExpressionList(Exprs, ExpressionStarts)) {
2525e5dd7070Spatrick if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
2526e5dd7070Spatrick Actions.ProduceConstructorSignatureHelp(
2527*12c85518Srobert ThisVarDecl->getType()->getCanonicalTypeInternal(),
2528*12c85518Srobert ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
2529*12c85518Srobert /*Braced=*/false);
2530e5dd7070Spatrick CalledSignatureHelp = true;
2531e5dd7070Spatrick }
2532e5dd7070Spatrick Actions.ActOnInitializerError(ThisDecl);
2533e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
2534e5dd7070Spatrick } else {
2535e5dd7070Spatrick // Match the ')'.
2536e5dd7070Spatrick T.consumeClose();
2537e5dd7070Spatrick InitScope.pop();
2538e5dd7070Spatrick
2539e5dd7070Spatrick ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
2540e5dd7070Spatrick T.getCloseLocation(),
2541e5dd7070Spatrick Exprs);
2542e5dd7070Spatrick Actions.AddInitializerToDecl(ThisDecl, Initializer.get(),
2543e5dd7070Spatrick /*DirectInit=*/true);
2544e5dd7070Spatrick }
2545a9ac8606Spatrick break;
2546a9ac8606Spatrick }
2547a9ac8606Spatrick case InitKind::CXXBraced: {
2548e5dd7070Spatrick // Parse C++0x braced-init-list.
2549e5dd7070Spatrick Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
2550e5dd7070Spatrick
2551e5dd7070Spatrick InitializerScopeRAII InitScope(*this, D, ThisDecl);
2552e5dd7070Spatrick
2553ec727ea7Spatrick PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
2554e5dd7070Spatrick ExprResult Init(ParseBraceInitializer());
2555e5dd7070Spatrick
2556e5dd7070Spatrick InitScope.pop();
2557e5dd7070Spatrick
2558e5dd7070Spatrick if (Init.isInvalid()) {
2559e5dd7070Spatrick Actions.ActOnInitializerError(ThisDecl);
2560e5dd7070Spatrick } else
2561e5dd7070Spatrick Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true);
2562a9ac8606Spatrick break;
2563a9ac8606Spatrick }
2564a9ac8606Spatrick case InitKind::Uninitialized: {
2565e5dd7070Spatrick Actions.ActOnUninitializedDecl(ThisDecl);
2566a9ac8606Spatrick break;
2567a9ac8606Spatrick }
2568e5dd7070Spatrick }
2569e5dd7070Spatrick
2570e5dd7070Spatrick Actions.FinalizeDeclaration(ThisDecl);
2571a9ac8606Spatrick return OuterDecl ? OuterDecl : ThisDecl;
2572e5dd7070Spatrick }
2573e5dd7070Spatrick
2574e5dd7070Spatrick /// ParseSpecifierQualifierList
2575e5dd7070Spatrick /// specifier-qualifier-list:
2576e5dd7070Spatrick /// type-specifier specifier-qualifier-list[opt]
2577e5dd7070Spatrick /// type-qualifier specifier-qualifier-list[opt]
2578e5dd7070Spatrick /// [GNU] attributes specifier-qualifier-list[opt]
2579e5dd7070Spatrick ///
ParseSpecifierQualifierList(DeclSpec & DS,ImplicitTypenameContext AllowImplicitTypename,AccessSpecifier AS,DeclSpecContext DSC)2580*12c85518Srobert void Parser::ParseSpecifierQualifierList(
2581*12c85518Srobert DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename,
2582*12c85518Srobert AccessSpecifier AS, DeclSpecContext DSC) {
2583e5dd7070Spatrick /// specifier-qualifier-list is a subset of declaration-specifiers. Just
2584e5dd7070Spatrick /// parse declaration-specifiers and complain about extra stuff.
2585e5dd7070Spatrick /// TODO: diagnose attribute-specifiers and alignment-specifiers.
2586*12c85518Srobert ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC, nullptr,
2587*12c85518Srobert AllowImplicitTypename);
2588e5dd7070Spatrick
2589e5dd7070Spatrick // Validate declspec for type-name.
2590e5dd7070Spatrick unsigned Specs = DS.getParsedSpecifiers();
2591e5dd7070Spatrick if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {
2592e5dd7070Spatrick Diag(Tok, diag::err_expected_type);
2593e5dd7070Spatrick DS.SetTypeSpecError();
2594e5dd7070Spatrick } else if (Specs == DeclSpec::PQ_None && !DS.hasAttributes()) {
2595e5dd7070Spatrick Diag(Tok, diag::err_typename_requires_specqual);
2596e5dd7070Spatrick if (!DS.hasTypeSpecifier())
2597e5dd7070Spatrick DS.SetTypeSpecError();
2598e5dd7070Spatrick }
2599e5dd7070Spatrick
2600e5dd7070Spatrick // Issue diagnostic and remove storage class if present.
2601e5dd7070Spatrick if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
2602e5dd7070Spatrick if (DS.getStorageClassSpecLoc().isValid())
2603e5dd7070Spatrick Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);
2604e5dd7070Spatrick else
2605e5dd7070Spatrick Diag(DS.getThreadStorageClassSpecLoc(),
2606e5dd7070Spatrick diag::err_typename_invalid_storageclass);
2607e5dd7070Spatrick DS.ClearStorageClassSpecs();
2608e5dd7070Spatrick }
2609e5dd7070Spatrick
2610e5dd7070Spatrick // Issue diagnostic and remove function specifier if present.
2611e5dd7070Spatrick if (Specs & DeclSpec::PQ_FunctionSpecifier) {
2612e5dd7070Spatrick if (DS.isInlineSpecified())
2613e5dd7070Spatrick Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
2614e5dd7070Spatrick if (DS.isVirtualSpecified())
2615e5dd7070Spatrick Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
2616e5dd7070Spatrick if (DS.hasExplicitSpecifier())
2617e5dd7070Spatrick Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
2618*12c85518Srobert if (DS.isNoreturnSpecified())
2619*12c85518Srobert Diag(DS.getNoreturnSpecLoc(), diag::err_typename_invalid_functionspec);
2620e5dd7070Spatrick DS.ClearFunctionSpecs();
2621e5dd7070Spatrick }
2622e5dd7070Spatrick
2623e5dd7070Spatrick // Issue diagnostic and remove constexpr specifier if present.
2624e5dd7070Spatrick if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) {
2625e5dd7070Spatrick Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr)
2626a9ac8606Spatrick << static_cast<int>(DS.getConstexprSpecifier());
2627e5dd7070Spatrick DS.ClearConstexprSpec();
2628e5dd7070Spatrick }
2629e5dd7070Spatrick }
2630e5dd7070Spatrick
2631e5dd7070Spatrick /// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the
2632e5dd7070Spatrick /// specified token is valid after the identifier in a declarator which
2633e5dd7070Spatrick /// immediately follows the declspec. For example, these things are valid:
2634e5dd7070Spatrick ///
2635e5dd7070Spatrick /// int x [ 4]; // direct-declarator
2636e5dd7070Spatrick /// int x ( int y); // direct-declarator
2637e5dd7070Spatrick /// int(int x ) // direct-declarator
2638e5dd7070Spatrick /// int x ; // simple-declaration
2639e5dd7070Spatrick /// int x = 17; // init-declarator-list
2640e5dd7070Spatrick /// int x , y; // init-declarator-list
2641e5dd7070Spatrick /// int x __asm__ ("foo"); // init-declarator-list
2642e5dd7070Spatrick /// int x : 4; // struct-declarator
2643e5dd7070Spatrick /// int x { 5}; // C++'0x unified initializers
2644e5dd7070Spatrick ///
2645e5dd7070Spatrick /// This is not, because 'x' does not immediately follow the declspec (though
2646e5dd7070Spatrick /// ')' happens to be valid anyway).
2647e5dd7070Spatrick /// int (x)
2648e5dd7070Spatrick ///
isValidAfterIdentifierInDeclarator(const Token & T)2649e5dd7070Spatrick static bool isValidAfterIdentifierInDeclarator(const Token &T) {
2650e5dd7070Spatrick return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi,
2651e5dd7070Spatrick tok::comma, tok::equal, tok::kw_asm, tok::l_brace,
2652e5dd7070Spatrick tok::colon);
2653e5dd7070Spatrick }
2654e5dd7070Spatrick
2655e5dd7070Spatrick /// ParseImplicitInt - This method is called when we have an non-typename
2656e5dd7070Spatrick /// identifier in a declspec (which normally terminates the decl spec) when
2657e5dd7070Spatrick /// the declspec has no type specifier. In this case, the declspec is either
2658e5dd7070Spatrick /// malformed or is "implicit int" (in K&R and C89).
2659e5dd7070Spatrick ///
2660e5dd7070Spatrick /// This method handles diagnosing this prettily and returns false if the
2661e5dd7070Spatrick /// declspec is done being processed. If it recovers and thinks there may be
2662e5dd7070Spatrick /// other pieces of declspec after it, it returns true.
2663e5dd7070Spatrick ///
ParseImplicitInt(DeclSpec & DS,CXXScopeSpec * SS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSC,ParsedAttributes & Attrs)2664e5dd7070Spatrick bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
2665e5dd7070Spatrick const ParsedTemplateInfo &TemplateInfo,
2666e5dd7070Spatrick AccessSpecifier AS, DeclSpecContext DSC,
2667*12c85518Srobert ParsedAttributes &Attrs) {
2668e5dd7070Spatrick assert(Tok.is(tok::identifier) && "should have identifier");
2669e5dd7070Spatrick
2670e5dd7070Spatrick SourceLocation Loc = Tok.getLocation();
2671e5dd7070Spatrick // If we see an identifier that is not a type name, we normally would
2672e5dd7070Spatrick // parse it as the identifier being declared. However, when a typename
2673e5dd7070Spatrick // is typo'd or the definition is not included, this will incorrectly
2674e5dd7070Spatrick // parse the typename as the identifier name and fall over misparsing
2675e5dd7070Spatrick // later parts of the diagnostic.
2676e5dd7070Spatrick //
2677e5dd7070Spatrick // As such, we try to do some look-ahead in cases where this would
2678e5dd7070Spatrick // otherwise be an "implicit-int" case to see if this is invalid. For
2679e5dd7070Spatrick // example: "static foo_t x = 4;" In this case, if we parsed foo_t as
2680e5dd7070Spatrick // an identifier with implicit int, we'd get a parse error because the
2681e5dd7070Spatrick // next token is obviously invalid for a type. Parse these as a case
2682e5dd7070Spatrick // with an invalid type specifier.
2683e5dd7070Spatrick assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
2684e5dd7070Spatrick
2685e5dd7070Spatrick // Since we know that this either implicit int (which is rare) or an
2686e5dd7070Spatrick // error, do lookahead to try to do better recovery. This never applies
2687e5dd7070Spatrick // within a type specifier. Outside of C++, we allow this even if the
2688e5dd7070Spatrick // language doesn't "officially" support implicit int -- we support
2689*12c85518Srobert // implicit int as an extension in some language modes.
2690*12c85518Srobert if (!isTypeSpecifier(DSC) && getLangOpts().isImplicitIntAllowed() &&
2691e5dd7070Spatrick isValidAfterIdentifierInDeclarator(NextToken())) {
2692e5dd7070Spatrick // If this token is valid for implicit int, e.g. "static x = 4", then
2693e5dd7070Spatrick // we just avoid eating the identifier, so it will be parsed as the
2694e5dd7070Spatrick // identifier in the declarator.
2695e5dd7070Spatrick return false;
2696e5dd7070Spatrick }
2697e5dd7070Spatrick
2698e5dd7070Spatrick // Early exit as Sema has a dedicated missing_actual_pipe_type diagnostic
2699e5dd7070Spatrick // for incomplete declarations such as `pipe p`.
2700e5dd7070Spatrick if (getLangOpts().OpenCLCPlusPlus && DS.isTypeSpecPipe())
2701e5dd7070Spatrick return false;
2702e5dd7070Spatrick
2703e5dd7070Spatrick if (getLangOpts().CPlusPlus &&
2704e5dd7070Spatrick DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
2705e5dd7070Spatrick // Don't require a type specifier if we have the 'auto' storage class
2706e5dd7070Spatrick // specifier in C++98 -- we'll promote it to a type specifier.
2707e5dd7070Spatrick if (SS)
2708e5dd7070Spatrick AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
2709e5dd7070Spatrick return false;
2710e5dd7070Spatrick }
2711e5dd7070Spatrick
2712e5dd7070Spatrick if (getLangOpts().CPlusPlus && (!SS || SS->isEmpty()) &&
2713e5dd7070Spatrick getLangOpts().MSVCCompat) {
2714e5dd7070Spatrick // Lookup of an unqualified type name has failed in MSVC compatibility mode.
2715e5dd7070Spatrick // Give Sema a chance to recover if we are in a template with dependent base
2716e5dd7070Spatrick // classes.
2717e5dd7070Spatrick if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(
2718e5dd7070Spatrick *Tok.getIdentifierInfo(), Tok.getLocation(),
2719e5dd7070Spatrick DSC == DeclSpecContext::DSC_template_type_arg)) {
2720e5dd7070Spatrick const char *PrevSpec;
2721e5dd7070Spatrick unsigned DiagID;
2722e5dd7070Spatrick DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
2723e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy());
2724e5dd7070Spatrick DS.SetRangeEnd(Tok.getLocation());
2725e5dd7070Spatrick ConsumeToken();
2726e5dd7070Spatrick return false;
2727e5dd7070Spatrick }
2728e5dd7070Spatrick }
2729e5dd7070Spatrick
2730e5dd7070Spatrick // Otherwise, if we don't consume this token, we are going to emit an
2731e5dd7070Spatrick // error anyway. Try to recover from various common problems. Check
2732e5dd7070Spatrick // to see if this was a reference to a tag name without a tag specified.
2733e5dd7070Spatrick // This is a common problem in C (saying 'foo' instead of 'struct foo').
2734e5dd7070Spatrick //
2735e5dd7070Spatrick // C++ doesn't need this, and isTagName doesn't take SS.
2736e5dd7070Spatrick if (SS == nullptr) {
2737e5dd7070Spatrick const char *TagName = nullptr, *FixitTagName = nullptr;
2738e5dd7070Spatrick tok::TokenKind TagKind = tok::unknown;
2739e5dd7070Spatrick
2740e5dd7070Spatrick switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {
2741e5dd7070Spatrick default: break;
2742e5dd7070Spatrick case DeclSpec::TST_enum:
2743e5dd7070Spatrick TagName="enum" ; FixitTagName = "enum " ; TagKind=tok::kw_enum ;break;
2744e5dd7070Spatrick case DeclSpec::TST_union:
2745e5dd7070Spatrick TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break;
2746e5dd7070Spatrick case DeclSpec::TST_struct:
2747e5dd7070Spatrick TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break;
2748e5dd7070Spatrick case DeclSpec::TST_interface:
2749e5dd7070Spatrick TagName="__interface"; FixitTagName = "__interface ";
2750e5dd7070Spatrick TagKind=tok::kw___interface;break;
2751e5dd7070Spatrick case DeclSpec::TST_class:
2752e5dd7070Spatrick TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break;
2753e5dd7070Spatrick }
2754e5dd7070Spatrick
2755e5dd7070Spatrick if (TagName) {
2756e5dd7070Spatrick IdentifierInfo *TokenName = Tok.getIdentifierInfo();
2757e5dd7070Spatrick LookupResult R(Actions, TokenName, SourceLocation(),
2758e5dd7070Spatrick Sema::LookupOrdinaryName);
2759e5dd7070Spatrick
2760e5dd7070Spatrick Diag(Loc, diag::err_use_of_tag_name_without_tag)
2761e5dd7070Spatrick << TokenName << TagName << getLangOpts().CPlusPlus
2762e5dd7070Spatrick << FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);
2763e5dd7070Spatrick
2764e5dd7070Spatrick if (Actions.LookupParsedName(R, getCurScope(), SS)) {
2765e5dd7070Spatrick for (LookupResult::iterator I = R.begin(), IEnd = R.end();
2766e5dd7070Spatrick I != IEnd; ++I)
2767e5dd7070Spatrick Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
2768e5dd7070Spatrick << TokenName << TagName;
2769e5dd7070Spatrick }
2770e5dd7070Spatrick
2771e5dd7070Spatrick // Parse this as a tag as if the missing tag were present.
2772e5dd7070Spatrick if (TagKind == tok::kw_enum)
2773e5dd7070Spatrick ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,
2774e5dd7070Spatrick DeclSpecContext::DSC_normal);
2775e5dd7070Spatrick else
2776e5dd7070Spatrick ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
2777e5dd7070Spatrick /*EnteringContext*/ false,
2778e5dd7070Spatrick DeclSpecContext::DSC_normal, Attrs);
2779e5dd7070Spatrick return true;
2780e5dd7070Spatrick }
2781e5dd7070Spatrick }
2782e5dd7070Spatrick
2783e5dd7070Spatrick // Determine whether this identifier could plausibly be the name of something
2784e5dd7070Spatrick // being declared (with a missing type).
2785e5dd7070Spatrick if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||
2786e5dd7070Spatrick DSC == DeclSpecContext::DSC_class)) {
2787e5dd7070Spatrick // Look ahead to the next token to try to figure out what this declaration
2788e5dd7070Spatrick // was supposed to be.
2789e5dd7070Spatrick switch (NextToken().getKind()) {
2790e5dd7070Spatrick case tok::l_paren: {
2791e5dd7070Spatrick // static x(4); // 'x' is not a type
2792e5dd7070Spatrick // x(int n); // 'x' is not a type
2793e5dd7070Spatrick // x (*p)[]; // 'x' is a type
2794e5dd7070Spatrick //
2795e5dd7070Spatrick // Since we're in an error case, we can afford to perform a tentative
2796e5dd7070Spatrick // parse to determine which case we're in.
2797e5dd7070Spatrick TentativeParsingAction PA(*this);
2798e5dd7070Spatrick ConsumeToken();
2799e5dd7070Spatrick TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
2800e5dd7070Spatrick PA.Revert();
2801e5dd7070Spatrick
2802e5dd7070Spatrick if (TPR != TPResult::False) {
2803e5dd7070Spatrick // The identifier is followed by a parenthesized declarator.
2804e5dd7070Spatrick // It's supposed to be a type.
2805e5dd7070Spatrick break;
2806e5dd7070Spatrick }
2807e5dd7070Spatrick
2808e5dd7070Spatrick // If we're in a context where we could be declaring a constructor,
2809e5dd7070Spatrick // check whether this is a constructor declaration with a bogus name.
2810e5dd7070Spatrick if (DSC == DeclSpecContext::DSC_class ||
2811e5dd7070Spatrick (DSC == DeclSpecContext::DSC_top_level && SS)) {
2812e5dd7070Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
2813e5dd7070Spatrick if (Actions.isCurrentClassNameTypo(II, SS)) {
2814e5dd7070Spatrick Diag(Loc, diag::err_constructor_bad_name)
2815e5dd7070Spatrick << Tok.getIdentifierInfo() << II
2816e5dd7070Spatrick << FixItHint::CreateReplacement(Tok.getLocation(), II->getName());
2817e5dd7070Spatrick Tok.setIdentifierInfo(II);
2818e5dd7070Spatrick }
2819e5dd7070Spatrick }
2820e5dd7070Spatrick // Fall through.
2821*12c85518Srobert [[fallthrough]];
2822e5dd7070Spatrick }
2823e5dd7070Spatrick case tok::comma:
2824e5dd7070Spatrick case tok::equal:
2825e5dd7070Spatrick case tok::kw_asm:
2826e5dd7070Spatrick case tok::l_brace:
2827e5dd7070Spatrick case tok::l_square:
2828e5dd7070Spatrick case tok::semi:
2829e5dd7070Spatrick // This looks like a variable or function declaration. The type is
2830e5dd7070Spatrick // probably missing. We're done parsing decl-specifiers.
2831e5dd7070Spatrick // But only if we are not in a function prototype scope.
2832e5dd7070Spatrick if (getCurScope()->isFunctionPrototypeScope())
2833e5dd7070Spatrick break;
2834e5dd7070Spatrick if (SS)
2835e5dd7070Spatrick AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
2836e5dd7070Spatrick return false;
2837e5dd7070Spatrick
2838e5dd7070Spatrick default:
2839e5dd7070Spatrick // This is probably supposed to be a type. This includes cases like:
2840e5dd7070Spatrick // int f(itn);
2841ec727ea7Spatrick // struct S { unsigned : 4; };
2842e5dd7070Spatrick break;
2843e5dd7070Spatrick }
2844e5dd7070Spatrick }
2845e5dd7070Spatrick
2846e5dd7070Spatrick // This is almost certainly an invalid type name. Let Sema emit a diagnostic
2847e5dd7070Spatrick // and attempt to recover.
2848e5dd7070Spatrick ParsedType T;
2849e5dd7070Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
2850e5dd7070Spatrick bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less);
2851e5dd7070Spatrick Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,
2852e5dd7070Spatrick IsTemplateName);
2853e5dd7070Spatrick if (T) {
2854e5dd7070Spatrick // The action has suggested that the type T could be used. Set that as
2855e5dd7070Spatrick // the type in the declaration specifiers, consume the would-be type
2856e5dd7070Spatrick // name token, and we're done.
2857e5dd7070Spatrick const char *PrevSpec;
2858e5dd7070Spatrick unsigned DiagID;
2859e5dd7070Spatrick DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
2860e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy());
2861e5dd7070Spatrick DS.SetRangeEnd(Tok.getLocation());
2862e5dd7070Spatrick ConsumeToken();
2863e5dd7070Spatrick // There may be other declaration specifiers after this.
2864e5dd7070Spatrick return true;
2865e5dd7070Spatrick } else if (II != Tok.getIdentifierInfo()) {
2866e5dd7070Spatrick // If no type was suggested, the correction is to a keyword
2867e5dd7070Spatrick Tok.setKind(II->getTokenID());
2868e5dd7070Spatrick // There may be other declaration specifiers after this.
2869e5dd7070Spatrick return true;
2870e5dd7070Spatrick }
2871e5dd7070Spatrick
2872e5dd7070Spatrick // Otherwise, the action had no suggestion for us. Mark this as an error.
2873e5dd7070Spatrick DS.SetTypeSpecError();
2874e5dd7070Spatrick DS.SetRangeEnd(Tok.getLocation());
2875e5dd7070Spatrick ConsumeToken();
2876e5dd7070Spatrick
2877e5dd7070Spatrick // Eat any following template arguments.
2878e5dd7070Spatrick if (IsTemplateName) {
2879e5dd7070Spatrick SourceLocation LAngle, RAngle;
2880e5dd7070Spatrick TemplateArgList Args;
2881e5dd7070Spatrick ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle);
2882e5dd7070Spatrick }
2883e5dd7070Spatrick
2884e5dd7070Spatrick // TODO: Could inject an invalid typedef decl in an enclosing scope to
2885e5dd7070Spatrick // avoid rippling error messages on subsequent uses of the same type,
2886e5dd7070Spatrick // could be useful if #include was forgotten.
2887e5dd7070Spatrick return true;
2888e5dd7070Spatrick }
2889e5dd7070Spatrick
2890e5dd7070Spatrick /// Determine the declaration specifier context from the declarator
2891e5dd7070Spatrick /// context.
2892e5dd7070Spatrick ///
2893e5dd7070Spatrick /// \param Context the declarator context, which is one of the
2894e5dd7070Spatrick /// DeclaratorContext enumerator values.
2895e5dd7070Spatrick Parser::DeclSpecContext
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context)2896e5dd7070Spatrick Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
2897*12c85518Srobert switch (Context) {
2898*12c85518Srobert case DeclaratorContext::Member:
2899e5dd7070Spatrick return DeclSpecContext::DSC_class;
2900*12c85518Srobert case DeclaratorContext::File:
2901e5dd7070Spatrick return DeclSpecContext::DSC_top_level;
2902*12c85518Srobert case DeclaratorContext::TemplateParam:
2903e5dd7070Spatrick return DeclSpecContext::DSC_template_param;
2904*12c85518Srobert case DeclaratorContext::TemplateArg:
2905*12c85518Srobert return DeclSpecContext::DSC_template_arg;
2906*12c85518Srobert case DeclaratorContext::TemplateTypeArg:
2907e5dd7070Spatrick return DeclSpecContext::DSC_template_type_arg;
2908*12c85518Srobert case DeclaratorContext::TrailingReturn:
2909*12c85518Srobert case DeclaratorContext::TrailingReturnVar:
2910e5dd7070Spatrick return DeclSpecContext::DSC_trailing;
2911*12c85518Srobert case DeclaratorContext::AliasDecl:
2912*12c85518Srobert case DeclaratorContext::AliasTemplate:
2913e5dd7070Spatrick return DeclSpecContext::DSC_alias_declaration;
2914*12c85518Srobert case DeclaratorContext::Association:
2915*12c85518Srobert return DeclSpecContext::DSC_association;
2916*12c85518Srobert case DeclaratorContext::TypeName:
2917*12c85518Srobert return DeclSpecContext::DSC_type_specifier;
2918*12c85518Srobert case DeclaratorContext::Condition:
2919*12c85518Srobert return DeclSpecContext::DSC_condition;
2920*12c85518Srobert case DeclaratorContext::ConversionId:
2921*12c85518Srobert return DeclSpecContext::DSC_conv_operator;
2922*12c85518Srobert case DeclaratorContext::Prototype:
2923*12c85518Srobert case DeclaratorContext::ObjCResult:
2924*12c85518Srobert case DeclaratorContext::ObjCParameter:
2925*12c85518Srobert case DeclaratorContext::KNRTypeList:
2926*12c85518Srobert case DeclaratorContext::FunctionalCast:
2927*12c85518Srobert case DeclaratorContext::Block:
2928*12c85518Srobert case DeclaratorContext::ForInit:
2929*12c85518Srobert case DeclaratorContext::SelectionInit:
2930*12c85518Srobert case DeclaratorContext::CXXNew:
2931*12c85518Srobert case DeclaratorContext::CXXCatch:
2932*12c85518Srobert case DeclaratorContext::ObjCCatch:
2933*12c85518Srobert case DeclaratorContext::BlockLiteral:
2934*12c85518Srobert case DeclaratorContext::LambdaExpr:
2935*12c85518Srobert case DeclaratorContext::LambdaExprParameter:
2936*12c85518Srobert case DeclaratorContext::RequiresExpr:
2937e5dd7070Spatrick return DeclSpecContext::DSC_normal;
2938e5dd7070Spatrick }
2939e5dd7070Spatrick
2940*12c85518Srobert llvm_unreachable("Missing DeclaratorContext case");
2941*12c85518Srobert }
2942*12c85518Srobert
2943e5dd7070Spatrick /// ParseAlignArgument - Parse the argument to an alignment-specifier.
2944e5dd7070Spatrick ///
2945e5dd7070Spatrick /// FIXME: Simply returns an alignof() expression if the argument is a
2946e5dd7070Spatrick /// type. Ideally, the type should be propagated directly into Sema.
2947e5dd7070Spatrick ///
2948e5dd7070Spatrick /// [C11] type-id
2949e5dd7070Spatrick /// [C11] constant-expression
2950e5dd7070Spatrick /// [C++0x] type-id ...[opt]
2951e5dd7070Spatrick /// [C++0x] assignment-expression ...[opt]
ParseAlignArgument(SourceLocation Start,SourceLocation & EllipsisLoc)2952e5dd7070Spatrick ExprResult Parser::ParseAlignArgument(SourceLocation Start,
2953e5dd7070Spatrick SourceLocation &EllipsisLoc) {
2954e5dd7070Spatrick ExprResult ER;
2955e5dd7070Spatrick if (isTypeIdInParens()) {
2956e5dd7070Spatrick SourceLocation TypeLoc = Tok.getLocation();
2957e5dd7070Spatrick ParsedType Ty = ParseTypeName().get();
2958e5dd7070Spatrick SourceRange TypeRange(Start, Tok.getLocation());
2959e5dd7070Spatrick ER = Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true,
2960e5dd7070Spatrick Ty.getAsOpaquePtr(), TypeRange);
2961e5dd7070Spatrick } else
2962e5dd7070Spatrick ER = ParseConstantExpression();
2963e5dd7070Spatrick
2964e5dd7070Spatrick if (getLangOpts().CPlusPlus11)
2965e5dd7070Spatrick TryConsumeToken(tok::ellipsis, EllipsisLoc);
2966e5dd7070Spatrick
2967e5dd7070Spatrick return ER;
2968e5dd7070Spatrick }
2969e5dd7070Spatrick
2970e5dd7070Spatrick /// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the
2971e5dd7070Spatrick /// attribute to Attrs.
2972e5dd7070Spatrick ///
2973e5dd7070Spatrick /// alignment-specifier:
2974e5dd7070Spatrick /// [C11] '_Alignas' '(' type-id ')'
2975e5dd7070Spatrick /// [C11] '_Alignas' '(' constant-expression ')'
2976e5dd7070Spatrick /// [C++11] 'alignas' '(' type-id ...[opt] ')'
2977e5dd7070Spatrick /// [C++11] 'alignas' '(' assignment-expression ...[opt] ')'
ParseAlignmentSpecifier(ParsedAttributes & Attrs,SourceLocation * EndLoc)2978e5dd7070Spatrick void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
2979e5dd7070Spatrick SourceLocation *EndLoc) {
2980e5dd7070Spatrick assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) &&
2981e5dd7070Spatrick "Not an alignment-specifier!");
2982e5dd7070Spatrick
2983e5dd7070Spatrick IdentifierInfo *KWName = Tok.getIdentifierInfo();
2984e5dd7070Spatrick SourceLocation KWLoc = ConsumeToken();
2985e5dd7070Spatrick
2986e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
2987e5dd7070Spatrick if (T.expectAndConsume())
2988e5dd7070Spatrick return;
2989e5dd7070Spatrick
2990e5dd7070Spatrick SourceLocation EllipsisLoc;
2991e5dd7070Spatrick ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation(), EllipsisLoc);
2992e5dd7070Spatrick if (ArgExpr.isInvalid()) {
2993e5dd7070Spatrick T.skipToEnd();
2994e5dd7070Spatrick return;
2995e5dd7070Spatrick }
2996e5dd7070Spatrick
2997e5dd7070Spatrick T.consumeClose();
2998e5dd7070Spatrick if (EndLoc)
2999e5dd7070Spatrick *EndLoc = T.getCloseLocation();
3000e5dd7070Spatrick
3001e5dd7070Spatrick ArgsVector ArgExprs;
3002e5dd7070Spatrick ArgExprs.push_back(ArgExpr.get());
3003e5dd7070Spatrick Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1,
3004e5dd7070Spatrick ParsedAttr::AS_Keyword, EllipsisLoc);
3005e5dd7070Spatrick }
3006e5dd7070Spatrick
ParseExtIntegerArgument()3007ec727ea7Spatrick ExprResult Parser::ParseExtIntegerArgument() {
3008*12c85518Srobert assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) &&
3009*12c85518Srobert "Not an extended int type");
3010ec727ea7Spatrick ConsumeToken();
3011ec727ea7Spatrick
3012ec727ea7Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
3013ec727ea7Spatrick if (T.expectAndConsume())
3014ec727ea7Spatrick return ExprError();
3015ec727ea7Spatrick
3016ec727ea7Spatrick ExprResult ER = ParseConstantExpression();
3017ec727ea7Spatrick if (ER.isInvalid()) {
3018ec727ea7Spatrick T.skipToEnd();
3019ec727ea7Spatrick return ExprError();
3020ec727ea7Spatrick }
3021ec727ea7Spatrick
3022ec727ea7Spatrick if(T.consumeClose())
3023ec727ea7Spatrick return ExprError();
3024ec727ea7Spatrick return ER;
3025ec727ea7Spatrick }
3026ec727ea7Spatrick
3027e5dd7070Spatrick /// Determine whether we're looking at something that might be a declarator
3028e5dd7070Spatrick /// in a simple-declaration. If it can't possibly be a declarator, maybe
3029e5dd7070Spatrick /// diagnose a missing semicolon after a prior tag definition in the decl
3030e5dd7070Spatrick /// specifier.
3031e5dd7070Spatrick ///
3032e5dd7070Spatrick /// \return \c true if an error occurred and this can't be any kind of
3033e5dd7070Spatrick /// declaration.
3034e5dd7070Spatrick bool
DiagnoseMissingSemiAfterTagDefinition(DeclSpec & DS,AccessSpecifier AS,DeclSpecContext DSContext,LateParsedAttrList * LateAttrs)3035e5dd7070Spatrick Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
3036e5dd7070Spatrick DeclSpecContext DSContext,
3037e5dd7070Spatrick LateParsedAttrList *LateAttrs) {
3038e5dd7070Spatrick assert(DS.hasTagDefinition() && "shouldn't call this");
3039e5dd7070Spatrick
3040e5dd7070Spatrick bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
3041e5dd7070Spatrick DSContext == DeclSpecContext::DSC_top_level);
3042e5dd7070Spatrick
3043e5dd7070Spatrick if (getLangOpts().CPlusPlus &&
3044e5dd7070Spatrick Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
3045e5dd7070Spatrick tok::annot_template_id) &&
3046e5dd7070Spatrick TryAnnotateCXXScopeToken(EnteringContext)) {
3047e5dd7070Spatrick SkipMalformedDecl();
3048e5dd7070Spatrick return true;
3049e5dd7070Spatrick }
3050e5dd7070Spatrick
3051e5dd7070Spatrick bool HasScope = Tok.is(tok::annot_cxxscope);
3052e5dd7070Spatrick // Make a copy in case GetLookAheadToken invalidates the result of NextToken.
3053e5dd7070Spatrick Token AfterScope = HasScope ? NextToken() : Tok;
3054e5dd7070Spatrick
3055e5dd7070Spatrick // Determine whether the following tokens could possibly be a
3056e5dd7070Spatrick // declarator.
3057e5dd7070Spatrick bool MightBeDeclarator = true;
3058e5dd7070Spatrick if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) {
3059e5dd7070Spatrick // A declarator-id can't start with 'typename'.
3060e5dd7070Spatrick MightBeDeclarator = false;
3061e5dd7070Spatrick } else if (AfterScope.is(tok::annot_template_id)) {
3062e5dd7070Spatrick // If we have a type expressed as a template-id, this cannot be a
3063e5dd7070Spatrick // declarator-id (such a type cannot be redeclared in a simple-declaration).
3064e5dd7070Spatrick TemplateIdAnnotation *Annot =
3065e5dd7070Spatrick static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());
3066e5dd7070Spatrick if (Annot->Kind == TNK_Type_template)
3067e5dd7070Spatrick MightBeDeclarator = false;
3068e5dd7070Spatrick } else if (AfterScope.is(tok::identifier)) {
3069e5dd7070Spatrick const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken();
3070e5dd7070Spatrick
3071e5dd7070Spatrick // These tokens cannot come after the declarator-id in a
3072e5dd7070Spatrick // simple-declaration, and are likely to come after a type-specifier.
3073e5dd7070Spatrick if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier,
3074e5dd7070Spatrick tok::annot_cxxscope, tok::coloncolon)) {
3075e5dd7070Spatrick // Missing a semicolon.
3076e5dd7070Spatrick MightBeDeclarator = false;
3077e5dd7070Spatrick } else if (HasScope) {
3078e5dd7070Spatrick // If the declarator-id has a scope specifier, it must redeclare a
3079e5dd7070Spatrick // previously-declared entity. If that's a type (and this is not a
3080e5dd7070Spatrick // typedef), that's an error.
3081e5dd7070Spatrick CXXScopeSpec SS;
3082e5dd7070Spatrick Actions.RestoreNestedNameSpecifierAnnotation(
3083e5dd7070Spatrick Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
3084e5dd7070Spatrick IdentifierInfo *Name = AfterScope.getIdentifierInfo();
3085e5dd7070Spatrick Sema::NameClassification Classification = Actions.ClassifyName(
3086e5dd7070Spatrick getCurScope(), SS, Name, AfterScope.getLocation(), Next,
3087e5dd7070Spatrick /*CCC=*/nullptr);
3088e5dd7070Spatrick switch (Classification.getKind()) {
3089e5dd7070Spatrick case Sema::NC_Error:
3090e5dd7070Spatrick SkipMalformedDecl();
3091e5dd7070Spatrick return true;
3092e5dd7070Spatrick
3093e5dd7070Spatrick case Sema::NC_Keyword:
3094e5dd7070Spatrick llvm_unreachable("typo correction is not possible here");
3095e5dd7070Spatrick
3096e5dd7070Spatrick case Sema::NC_Type:
3097e5dd7070Spatrick case Sema::NC_TypeTemplate:
3098e5dd7070Spatrick case Sema::NC_UndeclaredNonType:
3099e5dd7070Spatrick case Sema::NC_UndeclaredTemplate:
3100e5dd7070Spatrick // Not a previously-declared non-type entity.
3101e5dd7070Spatrick MightBeDeclarator = false;
3102e5dd7070Spatrick break;
3103e5dd7070Spatrick
3104e5dd7070Spatrick case Sema::NC_Unknown:
3105e5dd7070Spatrick case Sema::NC_NonType:
3106e5dd7070Spatrick case Sema::NC_DependentNonType:
3107a9ac8606Spatrick case Sema::NC_OverloadSet:
3108e5dd7070Spatrick case Sema::NC_VarTemplate:
3109e5dd7070Spatrick case Sema::NC_FunctionTemplate:
3110e5dd7070Spatrick case Sema::NC_Concept:
3111e5dd7070Spatrick // Might be a redeclaration of a prior entity.
3112e5dd7070Spatrick break;
3113e5dd7070Spatrick }
3114e5dd7070Spatrick }
3115e5dd7070Spatrick }
3116e5dd7070Spatrick
3117e5dd7070Spatrick if (MightBeDeclarator)
3118e5dd7070Spatrick return false;
3119e5dd7070Spatrick
3120e5dd7070Spatrick const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
3121e5dd7070Spatrick Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()),
3122e5dd7070Spatrick diag::err_expected_after)
3123e5dd7070Spatrick << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;
3124e5dd7070Spatrick
3125e5dd7070Spatrick // Try to recover from the typo, by dropping the tag definition and parsing
3126e5dd7070Spatrick // the problematic tokens as a type.
3127e5dd7070Spatrick //
3128e5dd7070Spatrick // FIXME: Split the DeclSpec into pieces for the standalone
3129e5dd7070Spatrick // declaration and pieces for the following declaration, instead
3130e5dd7070Spatrick // of assuming that all the other pieces attach to new declaration,
3131e5dd7070Spatrick // and call ParsedFreeStandingDeclSpec as appropriate.
3132e5dd7070Spatrick DS.ClearTypeSpecType();
3133e5dd7070Spatrick ParsedTemplateInfo NotATemplate;
3134e5dd7070Spatrick ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);
3135e5dd7070Spatrick return false;
3136e5dd7070Spatrick }
3137e5dd7070Spatrick
3138e5dd7070Spatrick // Choose the apprpriate diagnostic error for why fixed point types are
3139e5dd7070Spatrick // disabled, set the previous specifier, and mark as invalid.
SetupFixedPointError(const LangOptions & LangOpts,const char * & PrevSpec,unsigned & DiagID,bool & isInvalid)3140e5dd7070Spatrick static void SetupFixedPointError(const LangOptions &LangOpts,
3141e5dd7070Spatrick const char *&PrevSpec, unsigned &DiagID,
3142e5dd7070Spatrick bool &isInvalid) {
3143e5dd7070Spatrick assert(!LangOpts.FixedPoint);
3144e5dd7070Spatrick DiagID = diag::err_fixed_point_not_enabled;
3145e5dd7070Spatrick PrevSpec = ""; // Not used by diagnostic
3146e5dd7070Spatrick isInvalid = true;
3147e5dd7070Spatrick }
3148e5dd7070Spatrick
3149e5dd7070Spatrick /// ParseDeclarationSpecifiers
3150e5dd7070Spatrick /// declaration-specifiers: [C99 6.7]
3151e5dd7070Spatrick /// storage-class-specifier declaration-specifiers[opt]
3152e5dd7070Spatrick /// type-specifier declaration-specifiers[opt]
3153e5dd7070Spatrick /// [C99] function-specifier declaration-specifiers[opt]
3154e5dd7070Spatrick /// [C11] alignment-specifier declaration-specifiers[opt]
3155e5dd7070Spatrick /// [GNU] attributes declaration-specifiers[opt]
3156e5dd7070Spatrick /// [Clang] '__module_private__' declaration-specifiers[opt]
3157e5dd7070Spatrick /// [ObjC1] '__kindof' declaration-specifiers[opt]
3158e5dd7070Spatrick ///
3159e5dd7070Spatrick /// storage-class-specifier: [C99 6.7.1]
3160e5dd7070Spatrick /// 'typedef'
3161e5dd7070Spatrick /// 'extern'
3162e5dd7070Spatrick /// 'static'
3163e5dd7070Spatrick /// 'auto'
3164e5dd7070Spatrick /// 'register'
3165e5dd7070Spatrick /// [C++] 'mutable'
3166e5dd7070Spatrick /// [C++11] 'thread_local'
3167e5dd7070Spatrick /// [C11] '_Thread_local'
3168e5dd7070Spatrick /// [GNU] '__thread'
3169e5dd7070Spatrick /// function-specifier: [C99 6.7.4]
3170e5dd7070Spatrick /// [C99] 'inline'
3171e5dd7070Spatrick /// [C++] 'virtual'
3172e5dd7070Spatrick /// [C++] 'explicit'
3173e5dd7070Spatrick /// [OpenCL] '__kernel'
3174e5dd7070Spatrick /// 'friend': [C++ dcl.friend]
3175e5dd7070Spatrick /// 'constexpr': [C++0x dcl.constexpr]
ParseDeclarationSpecifiers(DeclSpec & DS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSContext,LateParsedAttrList * LateAttrs,ImplicitTypenameContext AllowImplicitTypename)3176*12c85518Srobert void Parser::ParseDeclarationSpecifiers(
3177*12c85518Srobert DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS,
3178*12c85518Srobert DeclSpecContext DSContext, LateParsedAttrList *LateAttrs,
3179*12c85518Srobert ImplicitTypenameContext AllowImplicitTypename) {
3180e5dd7070Spatrick if (DS.getSourceRange().isInvalid()) {
3181e5dd7070Spatrick // Start the range at the current token but make the end of the range
3182e5dd7070Spatrick // invalid. This will make the entire range invalid unless we successfully
3183e5dd7070Spatrick // consume a token.
3184e5dd7070Spatrick DS.SetRangeStart(Tok.getLocation());
3185e5dd7070Spatrick DS.SetRangeEnd(SourceLocation());
3186e5dd7070Spatrick }
3187e5dd7070Spatrick
3188*12c85518Srobert // If we are in a operator context, convert it back into a type specifier
3189*12c85518Srobert // context for better error handling later on.
3190*12c85518Srobert if (DSContext == DeclSpecContext::DSC_conv_operator) {
3191*12c85518Srobert // No implicit typename here.
3192*12c85518Srobert AllowImplicitTypename = ImplicitTypenameContext::No;
3193*12c85518Srobert DSContext = DeclSpecContext::DSC_type_specifier;
3194*12c85518Srobert }
3195*12c85518Srobert
3196e5dd7070Spatrick bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
3197e5dd7070Spatrick DSContext == DeclSpecContext::DSC_top_level);
3198e5dd7070Spatrick bool AttrsLastTime = false;
3199*12c85518Srobert ParsedAttributes attrs(AttrFactory);
3200e5dd7070Spatrick // We use Sema's policy to get bool macros right.
3201e5dd7070Spatrick PrintingPolicy Policy = Actions.getPrintingPolicy();
3202*12c85518Srobert while (true) {
3203e5dd7070Spatrick bool isInvalid = false;
3204e5dd7070Spatrick bool isStorageClass = false;
3205e5dd7070Spatrick const char *PrevSpec = nullptr;
3206e5dd7070Spatrick unsigned DiagID = 0;
3207e5dd7070Spatrick
3208e5dd7070Spatrick // This value needs to be set to the location of the last token if the last
3209e5dd7070Spatrick // token of the specifier is already consumed.
3210e5dd7070Spatrick SourceLocation ConsumedEnd;
3211e5dd7070Spatrick
3212e5dd7070Spatrick // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
3213e5dd7070Spatrick // implementation for VS2013 uses _Atomic as an identifier for one of the
3214e5dd7070Spatrick // classes in <atomic>.
3215e5dd7070Spatrick //
3216e5dd7070Spatrick // A typedef declaration containing _Atomic<...> is among the places where
3217e5dd7070Spatrick // the class is used. If we are currently parsing such a declaration, treat
3218e5dd7070Spatrick // the token as an identifier.
3219e5dd7070Spatrick if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
3220e5dd7070Spatrick DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef &&
3221e5dd7070Spatrick !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less))
3222e5dd7070Spatrick Tok.setKind(tok::identifier);
3223e5dd7070Spatrick
3224e5dd7070Spatrick SourceLocation Loc = Tok.getLocation();
3225e5dd7070Spatrick
3226a9ac8606Spatrick // Helper for image types in OpenCL.
3227a9ac8606Spatrick auto handleOpenCLImageKW = [&] (StringRef Ext, TypeSpecifierType ImageTypeSpec) {
3228a9ac8606Spatrick // Check if the image type is supported and otherwise turn the keyword into an identifier
3229a9ac8606Spatrick // because image types from extensions are not reserved identifiers.
3230a9ac8606Spatrick if (!StringRef(Ext).empty() && !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) {
3231a9ac8606Spatrick Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
3232a9ac8606Spatrick Tok.setKind(tok::identifier);
3233a9ac8606Spatrick return false;
3234a9ac8606Spatrick }
3235a9ac8606Spatrick isInvalid = DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy);
3236a9ac8606Spatrick return true;
3237a9ac8606Spatrick };
3238a9ac8606Spatrick
3239*12c85518Srobert // Turn off usual access checking for template specializations and
3240*12c85518Srobert // instantiations.
3241*12c85518Srobert bool IsTemplateSpecOrInst =
3242*12c85518Srobert (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
3243*12c85518Srobert TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
3244*12c85518Srobert
3245e5dd7070Spatrick switch (Tok.getKind()) {
3246e5dd7070Spatrick default:
3247e5dd7070Spatrick DoneWithDeclSpec:
3248e5dd7070Spatrick if (!AttrsLastTime)
3249e5dd7070Spatrick ProhibitAttributes(attrs);
3250e5dd7070Spatrick else {
3251*12c85518Srobert // Reject C++11 / C2x attributes that aren't type attributes.
3252*12c85518Srobert for (const ParsedAttr &PA : attrs) {
3253*12c85518Srobert if (!PA.isCXX11Attribute() && !PA.isC2xAttribute())
3254*12c85518Srobert continue;
3255*12c85518Srobert if (PA.getKind() == ParsedAttr::UnknownAttribute)
3256*12c85518Srobert // We will warn about the unknown attribute elsewhere (in
3257*12c85518Srobert // SemaDeclAttr.cpp)
3258*12c85518Srobert continue;
3259*12c85518Srobert // GCC ignores this attribute when placed on the DeclSpec in [[]]
3260*12c85518Srobert // syntax, so we do the same.
3261*12c85518Srobert if (PA.getKind() == ParsedAttr::AT_VectorSize) {
3262*12c85518Srobert Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA;
3263*12c85518Srobert PA.setInvalid();
3264*12c85518Srobert continue;
3265*12c85518Srobert }
3266*12c85518Srobert // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they
3267*12c85518Srobert // are type attributes, because we historically haven't allowed these
3268*12c85518Srobert // to be used as type attributes in C++11 / C2x syntax.
3269*12c85518Srobert if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound &&
3270*12c85518Srobert PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
3271*12c85518Srobert continue;
3272*12c85518Srobert Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA;
3273*12c85518Srobert PA.setInvalid();
3274*12c85518Srobert }
3275e5dd7070Spatrick
3276e5dd7070Spatrick DS.takeAttributesFrom(attrs);
3277e5dd7070Spatrick }
3278e5dd7070Spatrick
3279e5dd7070Spatrick // If this is not a declaration specifier token, we're done reading decl
3280e5dd7070Spatrick // specifiers. First verify that DeclSpec's are consistent.
3281e5dd7070Spatrick DS.Finish(Actions, Policy);
3282e5dd7070Spatrick return;
3283e5dd7070Spatrick
3284e5dd7070Spatrick case tok::l_square:
3285e5dd7070Spatrick case tok::kw_alignas:
3286e5dd7070Spatrick if (!standardAttributesAllowed() || !isCXX11AttributeSpecifier())
3287e5dd7070Spatrick goto DoneWithDeclSpec;
3288e5dd7070Spatrick
3289e5dd7070Spatrick ProhibitAttributes(attrs);
3290e5dd7070Spatrick // FIXME: It would be good to recover by accepting the attributes,
3291e5dd7070Spatrick // but attempting to do that now would cause serious
3292e5dd7070Spatrick // madness in terms of diagnostics.
3293e5dd7070Spatrick attrs.clear();
3294e5dd7070Spatrick attrs.Range = SourceRange();
3295e5dd7070Spatrick
3296e5dd7070Spatrick ParseCXX11Attributes(attrs);
3297e5dd7070Spatrick AttrsLastTime = true;
3298e5dd7070Spatrick continue;
3299e5dd7070Spatrick
3300e5dd7070Spatrick case tok::code_completion: {
3301e5dd7070Spatrick Sema::ParserCompletionContext CCC = Sema::PCC_Namespace;
3302e5dd7070Spatrick if (DS.hasTypeSpecifier()) {
3303e5dd7070Spatrick bool AllowNonIdentifiers
3304e5dd7070Spatrick = (getCurScope()->getFlags() & (Scope::ControlScope |
3305e5dd7070Spatrick Scope::BlockScope |
3306e5dd7070Spatrick Scope::TemplateParamScope |
3307e5dd7070Spatrick Scope::FunctionPrototypeScope |
3308e5dd7070Spatrick Scope::AtCatchScope)) == 0;
3309e5dd7070Spatrick bool AllowNestedNameSpecifiers
3310e5dd7070Spatrick = DSContext == DeclSpecContext::DSC_top_level ||
3311e5dd7070Spatrick (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
3312e5dd7070Spatrick
3313a9ac8606Spatrick cutOffParsing();
3314e5dd7070Spatrick Actions.CodeCompleteDeclSpec(getCurScope(), DS,
3315e5dd7070Spatrick AllowNonIdentifiers,
3316e5dd7070Spatrick AllowNestedNameSpecifiers);
3317a9ac8606Spatrick return;
3318e5dd7070Spatrick }
3319e5dd7070Spatrick
3320*12c85518Srobert // Class context can appear inside a function/block, so prioritise that.
3321*12c85518Srobert if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
3322e5dd7070Spatrick CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate
3323e5dd7070Spatrick : Sema::PCC_Template;
3324e5dd7070Spatrick else if (DSContext == DeclSpecContext::DSC_class)
3325e5dd7070Spatrick CCC = Sema::PCC_Class;
3326*12c85518Srobert else if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
3327*12c85518Srobert CCC = Sema::PCC_LocalDeclarationSpecifiers;
3328e5dd7070Spatrick else if (CurParsedObjCImpl)
3329e5dd7070Spatrick CCC = Sema::PCC_ObjCImplementation;
3330e5dd7070Spatrick
3331a9ac8606Spatrick cutOffParsing();
3332e5dd7070Spatrick Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
3333a9ac8606Spatrick return;
3334e5dd7070Spatrick }
3335e5dd7070Spatrick
3336e5dd7070Spatrick case tok::coloncolon: // ::foo::bar
3337e5dd7070Spatrick // C++ scope specifier. Annotate and loop, or bail out on error.
3338e5dd7070Spatrick if (TryAnnotateCXXScopeToken(EnteringContext)) {
3339e5dd7070Spatrick if (!DS.hasTypeSpecifier())
3340e5dd7070Spatrick DS.SetTypeSpecError();
3341e5dd7070Spatrick goto DoneWithDeclSpec;
3342e5dd7070Spatrick }
3343e5dd7070Spatrick if (Tok.is(tok::coloncolon)) // ::new or ::delete
3344e5dd7070Spatrick goto DoneWithDeclSpec;
3345e5dd7070Spatrick continue;
3346e5dd7070Spatrick
3347e5dd7070Spatrick case tok::annot_cxxscope: {
3348e5dd7070Spatrick if (DS.hasTypeSpecifier() || DS.isTypeAltiVecVector())
3349e5dd7070Spatrick goto DoneWithDeclSpec;
3350e5dd7070Spatrick
3351e5dd7070Spatrick CXXScopeSpec SS;
3352e5dd7070Spatrick Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
3353e5dd7070Spatrick Tok.getAnnotationRange(),
3354e5dd7070Spatrick SS);
3355e5dd7070Spatrick
3356e5dd7070Spatrick // We are looking for a qualified typename.
3357e5dd7070Spatrick Token Next = NextToken();
3358ec727ea7Spatrick
3359ec727ea7Spatrick TemplateIdAnnotation *TemplateId = Next.is(tok::annot_template_id)
3360ec727ea7Spatrick ? takeTemplateIdAnnotation(Next)
3361ec727ea7Spatrick : nullptr;
3362ec727ea7Spatrick if (TemplateId && TemplateId->hasInvalidName()) {
3363ec727ea7Spatrick // We found something like 'T::U<Args> x', but U is not a template.
3364ec727ea7Spatrick // Assume it was supposed to be a type.
3365ec727ea7Spatrick DS.SetTypeSpecError();
3366ec727ea7Spatrick ConsumeAnnotationToken();
3367ec727ea7Spatrick break;
3368ec727ea7Spatrick }
3369ec727ea7Spatrick
3370ec727ea7Spatrick if (TemplateId && TemplateId->Kind == TNK_Type_template) {
3371e5dd7070Spatrick // We have a qualified template-id, e.g., N::A<int>
3372e5dd7070Spatrick
3373e5dd7070Spatrick // If this would be a valid constructor declaration with template
3374e5dd7070Spatrick // arguments, we will reject the attempt to form an invalid type-id
3375e5dd7070Spatrick // referring to the injected-class-name when we annotate the token,
3376e5dd7070Spatrick // per C++ [class.qual]p2.
3377e5dd7070Spatrick //
3378e5dd7070Spatrick // To improve diagnostics for this case, parse the declaration as a
3379e5dd7070Spatrick // constructor (and reject the extra template arguments later).
3380e5dd7070Spatrick if ((DSContext == DeclSpecContext::DSC_top_level ||
3381e5dd7070Spatrick DSContext == DeclSpecContext::DSC_class) &&
3382e5dd7070Spatrick TemplateId->Name &&
3383e5dd7070Spatrick Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
3384*12c85518Srobert isConstructorDeclarator(/*Unqualified=*/false,
3385*12c85518Srobert /*DeductionGuide=*/false,
3386*12c85518Srobert DS.isFriendSpecified())) {
3387e5dd7070Spatrick // The user meant this to be an out-of-line constructor
3388e5dd7070Spatrick // definition, but template arguments are not allowed
3389e5dd7070Spatrick // there. Just allow this as a constructor; we'll
3390e5dd7070Spatrick // complain about it later.
3391e5dd7070Spatrick goto DoneWithDeclSpec;
3392e5dd7070Spatrick }
3393e5dd7070Spatrick
3394e5dd7070Spatrick DS.getTypeSpecScope() = SS;
3395e5dd7070Spatrick ConsumeAnnotationToken(); // The C++ scope.
3396e5dd7070Spatrick assert(Tok.is(tok::annot_template_id) &&
3397e5dd7070Spatrick "ParseOptionalCXXScopeSpecifier not working");
3398*12c85518Srobert AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
3399e5dd7070Spatrick continue;
3400e5dd7070Spatrick }
3401e5dd7070Spatrick
3402ec727ea7Spatrick if (TemplateId && TemplateId->Kind == TNK_Concept_template &&
3403e5dd7070Spatrick GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype)) {
3404e5dd7070Spatrick DS.getTypeSpecScope() = SS;
3405e5dd7070Spatrick // This is a qualified placeholder-specifier, e.g., ::C<int> auto ...
3406e5dd7070Spatrick // Consume the scope annotation and continue to consume the template-id
3407e5dd7070Spatrick // as a placeholder-specifier.
3408e5dd7070Spatrick ConsumeAnnotationToken();
3409e5dd7070Spatrick continue;
3410e5dd7070Spatrick }
3411e5dd7070Spatrick
3412e5dd7070Spatrick if (Next.is(tok::annot_typename)) {
3413e5dd7070Spatrick DS.getTypeSpecScope() = SS;
3414e5dd7070Spatrick ConsumeAnnotationToken(); // The C++ scope.
3415ec727ea7Spatrick TypeResult T = getTypeAnnotation(Tok);
3416e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
3417e5dd7070Spatrick Tok.getAnnotationEndLoc(),
3418e5dd7070Spatrick PrevSpec, DiagID, T, Policy);
3419e5dd7070Spatrick if (isInvalid)
3420e5dd7070Spatrick break;
3421e5dd7070Spatrick DS.SetRangeEnd(Tok.getAnnotationEndLoc());
3422e5dd7070Spatrick ConsumeAnnotationToken(); // The typename
3423e5dd7070Spatrick }
3424e5dd7070Spatrick
3425*12c85518Srobert if (AllowImplicitTypename == ImplicitTypenameContext::Yes &&
3426*12c85518Srobert Next.is(tok::annot_template_id) &&
3427*12c85518Srobert static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
3428*12c85518Srobert ->Kind == TNK_Dependent_template_name) {
3429*12c85518Srobert DS.getTypeSpecScope() = SS;
3430*12c85518Srobert ConsumeAnnotationToken(); // The C++ scope.
3431*12c85518Srobert AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
3432*12c85518Srobert continue;
3433*12c85518Srobert }
3434*12c85518Srobert
3435e5dd7070Spatrick if (Next.isNot(tok::identifier))
3436e5dd7070Spatrick goto DoneWithDeclSpec;
3437e5dd7070Spatrick
3438e5dd7070Spatrick // Check whether this is a constructor declaration. If we're in a
3439e5dd7070Spatrick // context where the identifier could be a class name, and it has the
3440e5dd7070Spatrick // shape of a constructor declaration, process it as one.
3441e5dd7070Spatrick if ((DSContext == DeclSpecContext::DSC_top_level ||
3442e5dd7070Spatrick DSContext == DeclSpecContext::DSC_class) &&
3443e5dd7070Spatrick Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
3444e5dd7070Spatrick &SS) &&
3445*12c85518Srobert isConstructorDeclarator(/*Unqualified=*/false,
3446*12c85518Srobert /*DeductionGuide=*/false,
3447*12c85518Srobert DS.isFriendSpecified()))
3448e5dd7070Spatrick goto DoneWithDeclSpec;
3449e5dd7070Spatrick
3450*12c85518Srobert // C++20 [temp.spec] 13.9/6.
3451*12c85518Srobert // This disables the access checking rules for function template explicit
3452*12c85518Srobert // instantiation and explicit specialization:
3453*12c85518Srobert // - `return type`.
3454*12c85518Srobert SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
3455*12c85518Srobert
3456*12c85518Srobert ParsedType TypeRep = Actions.getTypeName(
3457*12c85518Srobert *Next.getIdentifierInfo(), Next.getLocation(), getCurScope(), &SS,
3458*12c85518Srobert false, false, nullptr,
3459e5dd7070Spatrick /*IsCtorOrDtorName=*/false,
3460e5dd7070Spatrick /*WantNontrivialTypeSourceInfo=*/true,
3461*12c85518Srobert isClassTemplateDeductionContext(DSContext), AllowImplicitTypename);
3462*12c85518Srobert
3463*12c85518Srobert if (IsTemplateSpecOrInst)
3464*12c85518Srobert SAC.done();
3465e5dd7070Spatrick
3466e5dd7070Spatrick // If the referenced identifier is not a type, then this declspec is
3467e5dd7070Spatrick // erroneous: We already checked about that it has no type specifier, and
3468e5dd7070Spatrick // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
3469e5dd7070Spatrick // typename.
3470e5dd7070Spatrick if (!TypeRep) {
3471e5dd7070Spatrick if (TryAnnotateTypeConstraint())
3472e5dd7070Spatrick goto DoneWithDeclSpec;
3473ec727ea7Spatrick if (Tok.isNot(tok::annot_cxxscope) ||
3474ec727ea7Spatrick NextToken().isNot(tok::identifier))
3475e5dd7070Spatrick continue;
3476e5dd7070Spatrick // Eat the scope spec so the identifier is current.
3477e5dd7070Spatrick ConsumeAnnotationToken();
3478*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
3479e5dd7070Spatrick if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {
3480e5dd7070Spatrick if (!Attrs.empty()) {
3481e5dd7070Spatrick AttrsLastTime = true;
3482e5dd7070Spatrick attrs.takeAllFrom(Attrs);
3483e5dd7070Spatrick }
3484e5dd7070Spatrick continue;
3485e5dd7070Spatrick }
3486e5dd7070Spatrick goto DoneWithDeclSpec;
3487e5dd7070Spatrick }
3488e5dd7070Spatrick
3489e5dd7070Spatrick DS.getTypeSpecScope() = SS;
3490e5dd7070Spatrick ConsumeAnnotationToken(); // The C++ scope.
3491e5dd7070Spatrick
3492e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
3493e5dd7070Spatrick DiagID, TypeRep, Policy);
3494e5dd7070Spatrick if (isInvalid)
3495e5dd7070Spatrick break;
3496e5dd7070Spatrick
3497e5dd7070Spatrick DS.SetRangeEnd(Tok.getLocation());
3498e5dd7070Spatrick ConsumeToken(); // The typename.
3499e5dd7070Spatrick
3500e5dd7070Spatrick continue;
3501e5dd7070Spatrick }
3502e5dd7070Spatrick
3503e5dd7070Spatrick case tok::annot_typename: {
3504e5dd7070Spatrick // If we've previously seen a tag definition, we were almost surely
3505e5dd7070Spatrick // missing a semicolon after it.
3506e5dd7070Spatrick if (DS.hasTypeSpecifier() && DS.hasTagDefinition())
3507e5dd7070Spatrick goto DoneWithDeclSpec;
3508e5dd7070Spatrick
3509ec727ea7Spatrick TypeResult T = getTypeAnnotation(Tok);
3510e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
3511e5dd7070Spatrick DiagID, T, Policy);
3512e5dd7070Spatrick if (isInvalid)
3513e5dd7070Spatrick break;
3514e5dd7070Spatrick
3515e5dd7070Spatrick DS.SetRangeEnd(Tok.getAnnotationEndLoc());
3516e5dd7070Spatrick ConsumeAnnotationToken(); // The typename
3517e5dd7070Spatrick
3518e5dd7070Spatrick continue;
3519e5dd7070Spatrick }
3520e5dd7070Spatrick
3521e5dd7070Spatrick case tok::kw___is_signed:
3522e5dd7070Spatrick // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang
3523e5dd7070Spatrick // typically treats it as a trait. If we see __is_signed as it appears
3524e5dd7070Spatrick // in libstdc++, e.g.,
3525e5dd7070Spatrick //
3526e5dd7070Spatrick // static const bool __is_signed;
3527e5dd7070Spatrick //
3528e5dd7070Spatrick // then treat __is_signed as an identifier rather than as a keyword.
3529e5dd7070Spatrick if (DS.getTypeSpecType() == TST_bool &&
3530e5dd7070Spatrick DS.getTypeQualifiers() == DeclSpec::TQ_const &&
3531e5dd7070Spatrick DS.getStorageClassSpec() == DeclSpec::SCS_static)
3532e5dd7070Spatrick TryKeywordIdentFallback(true);
3533e5dd7070Spatrick
3534e5dd7070Spatrick // We're done with the declaration-specifiers.
3535e5dd7070Spatrick goto DoneWithDeclSpec;
3536e5dd7070Spatrick
3537e5dd7070Spatrick // typedef-name
3538e5dd7070Spatrick case tok::kw___super:
3539e5dd7070Spatrick case tok::kw_decltype:
3540*12c85518Srobert case tok::identifier:
3541*12c85518Srobert ParseIdentifier: {
3542e5dd7070Spatrick // This identifier can only be a typedef name if we haven't already seen
3543e5dd7070Spatrick // a type-specifier. Without this check we misparse:
3544e5dd7070Spatrick // typedef int X; struct Y { short X; }; as 'short int'.
3545e5dd7070Spatrick if (DS.hasTypeSpecifier())
3546e5dd7070Spatrick goto DoneWithDeclSpec;
3547e5dd7070Spatrick
3548e5dd7070Spatrick // If the token is an identifier named "__declspec" and Microsoft
3549e5dd7070Spatrick // extensions are not enabled, it is likely that there will be cascading
3550e5dd7070Spatrick // parse errors if this really is a __declspec attribute. Attempt to
3551e5dd7070Spatrick // recognize that scenario and recover gracefully.
3552e5dd7070Spatrick if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) &&
3553e5dd7070Spatrick Tok.getIdentifierInfo()->getName().equals("__declspec")) {
3554e5dd7070Spatrick Diag(Loc, diag::err_ms_attributes_not_enabled);
3555e5dd7070Spatrick
3556e5dd7070Spatrick // The next token should be an open paren. If it is, eat the entire
3557e5dd7070Spatrick // attribute declaration and continue.
3558e5dd7070Spatrick if (NextToken().is(tok::l_paren)) {
3559e5dd7070Spatrick // Consume the __declspec identifier.
3560e5dd7070Spatrick ConsumeToken();
3561e5dd7070Spatrick
3562e5dd7070Spatrick // Eat the parens and everything between them.
3563e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
3564e5dd7070Spatrick if (T.consumeOpen()) {
3565e5dd7070Spatrick assert(false && "Not a left paren?");
3566e5dd7070Spatrick return;
3567e5dd7070Spatrick }
3568e5dd7070Spatrick T.skipToEnd();
3569e5dd7070Spatrick continue;
3570e5dd7070Spatrick }
3571e5dd7070Spatrick }
3572e5dd7070Spatrick
3573e5dd7070Spatrick // In C++, check to see if this is a scope specifier like foo::bar::, if
3574e5dd7070Spatrick // so handle it as such. This is important for ctor parsing.
3575e5dd7070Spatrick if (getLangOpts().CPlusPlus) {
3576*12c85518Srobert // C++20 [temp.spec] 13.9/6.
3577*12c85518Srobert // This disables the access checking rules for function template
3578*12c85518Srobert // explicit instantiation and explicit specialization:
3579*12c85518Srobert // - `return type`.
3580*12c85518Srobert SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
3581*12c85518Srobert
3582*12c85518Srobert const bool Success = TryAnnotateCXXScopeToken(EnteringContext);
3583*12c85518Srobert
3584*12c85518Srobert if (IsTemplateSpecOrInst)
3585*12c85518Srobert SAC.done();
3586*12c85518Srobert
3587*12c85518Srobert if (Success) {
3588*12c85518Srobert if (IsTemplateSpecOrInst)
3589*12c85518Srobert SAC.redelay();
3590e5dd7070Spatrick DS.SetTypeSpecError();
3591e5dd7070Spatrick goto DoneWithDeclSpec;
3592e5dd7070Spatrick }
3593*12c85518Srobert
3594e5dd7070Spatrick if (!Tok.is(tok::identifier))
3595e5dd7070Spatrick continue;
3596e5dd7070Spatrick }
3597e5dd7070Spatrick
3598e5dd7070Spatrick // Check for need to substitute AltiVec keyword tokens.
3599e5dd7070Spatrick if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
3600e5dd7070Spatrick break;
3601e5dd7070Spatrick
3602e5dd7070Spatrick // [AltiVec] 2.2: [If the 'vector' specifier is used] The syntax does not
3603e5dd7070Spatrick // allow the use of a typedef name as a type specifier.
3604e5dd7070Spatrick if (DS.isTypeAltiVecVector())
3605e5dd7070Spatrick goto DoneWithDeclSpec;
3606e5dd7070Spatrick
3607e5dd7070Spatrick if (DSContext == DeclSpecContext::DSC_objc_method_result &&
3608e5dd7070Spatrick isObjCInstancetype()) {
3609e5dd7070Spatrick ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
3610e5dd7070Spatrick assert(TypeRep);
3611e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
3612e5dd7070Spatrick DiagID, TypeRep, Policy);
3613e5dd7070Spatrick if (isInvalid)
3614e5dd7070Spatrick break;
3615e5dd7070Spatrick
3616e5dd7070Spatrick DS.SetRangeEnd(Loc);
3617e5dd7070Spatrick ConsumeToken();
3618e5dd7070Spatrick continue;
3619e5dd7070Spatrick }
3620e5dd7070Spatrick
3621e5dd7070Spatrick // If we're in a context where the identifier could be a class name,
3622e5dd7070Spatrick // check whether this is a constructor declaration.
3623e5dd7070Spatrick if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
3624e5dd7070Spatrick Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
3625*12c85518Srobert isConstructorDeclarator(/*Unqualified=*/true,
3626*12c85518Srobert /*DeductionGuide=*/false,
3627*12c85518Srobert DS.isFriendSpecified()))
3628e5dd7070Spatrick goto DoneWithDeclSpec;
3629e5dd7070Spatrick
3630e5dd7070Spatrick ParsedType TypeRep = Actions.getTypeName(
3631e5dd7070Spatrick *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,
3632e5dd7070Spatrick false, false, nullptr, false, false,
3633e5dd7070Spatrick isClassTemplateDeductionContext(DSContext));
3634e5dd7070Spatrick
3635e5dd7070Spatrick // If this is not a typedef name, don't parse it as part of the declspec,
3636e5dd7070Spatrick // it must be an implicit int or an error.
3637e5dd7070Spatrick if (!TypeRep) {
3638e5dd7070Spatrick if (TryAnnotateTypeConstraint())
3639e5dd7070Spatrick goto DoneWithDeclSpec;
3640ec727ea7Spatrick if (Tok.isNot(tok::identifier))
3641e5dd7070Spatrick continue;
3642*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
3643e5dd7070Spatrick if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) {
3644e5dd7070Spatrick if (!Attrs.empty()) {
3645e5dd7070Spatrick AttrsLastTime = true;
3646e5dd7070Spatrick attrs.takeAllFrom(Attrs);
3647e5dd7070Spatrick }
3648e5dd7070Spatrick continue;
3649e5dd7070Spatrick }
3650e5dd7070Spatrick goto DoneWithDeclSpec;
3651e5dd7070Spatrick }
3652e5dd7070Spatrick
3653e5dd7070Spatrick // Likewise, if this is a context where the identifier could be a template
3654e5dd7070Spatrick // name, check whether this is a deduction guide declaration.
3655e5dd7070Spatrick if (getLangOpts().CPlusPlus17 &&
3656e5dd7070Spatrick (DSContext == DeclSpecContext::DSC_class ||
3657e5dd7070Spatrick DSContext == DeclSpecContext::DSC_top_level) &&
3658e5dd7070Spatrick Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
3659e5dd7070Spatrick Tok.getLocation()) &&
3660e5dd7070Spatrick isConstructorDeclarator(/*Unqualified*/ true,
3661e5dd7070Spatrick /*DeductionGuide*/ true))
3662e5dd7070Spatrick goto DoneWithDeclSpec;
3663e5dd7070Spatrick
3664e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
3665e5dd7070Spatrick DiagID, TypeRep, Policy);
3666e5dd7070Spatrick if (isInvalid)
3667e5dd7070Spatrick break;
3668e5dd7070Spatrick
3669e5dd7070Spatrick DS.SetRangeEnd(Tok.getLocation());
3670e5dd7070Spatrick ConsumeToken(); // The identifier
3671e5dd7070Spatrick
3672e5dd7070Spatrick // Objective-C supports type arguments and protocol references
3673e5dd7070Spatrick // following an Objective-C object or object pointer
3674e5dd7070Spatrick // type. Handle either one of them.
3675e5dd7070Spatrick if (Tok.is(tok::less) && getLangOpts().ObjC) {
3676e5dd7070Spatrick SourceLocation NewEndLoc;
3677e5dd7070Spatrick TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers(
3678e5dd7070Spatrick Loc, TypeRep, /*consumeLastToken=*/true,
3679e5dd7070Spatrick NewEndLoc);
3680e5dd7070Spatrick if (NewTypeRep.isUsable()) {
3681e5dd7070Spatrick DS.UpdateTypeRep(NewTypeRep.get());
3682e5dd7070Spatrick DS.SetRangeEnd(NewEndLoc);
3683e5dd7070Spatrick }
3684e5dd7070Spatrick }
3685e5dd7070Spatrick
3686e5dd7070Spatrick // Need to support trailing type qualifiers (e.g. "id<p> const").
3687e5dd7070Spatrick // If a type specifier follows, it will be diagnosed elsewhere.
3688e5dd7070Spatrick continue;
3689e5dd7070Spatrick }
3690e5dd7070Spatrick
3691e5dd7070Spatrick // type-name or placeholder-specifier
3692e5dd7070Spatrick case tok::annot_template_id: {
3693e5dd7070Spatrick TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
3694ec727ea7Spatrick
3695ec727ea7Spatrick if (TemplateId->hasInvalidName()) {
3696ec727ea7Spatrick DS.SetTypeSpecError();
3697ec727ea7Spatrick break;
3698ec727ea7Spatrick }
3699ec727ea7Spatrick
3700e5dd7070Spatrick if (TemplateId->Kind == TNK_Concept_template) {
3701ec727ea7Spatrick // If we've already diagnosed that this type-constraint has invalid
3702*12c85518Srobert // arguments, drop it and just form 'auto' or 'decltype(auto)'.
3703ec727ea7Spatrick if (TemplateId->hasInvalidArgs())
3704ec727ea7Spatrick TemplateId = nullptr;
3705ec727ea7Spatrick
3706*12c85518Srobert // Any of the following tokens are likely the start of the user
3707*12c85518Srobert // forgetting 'auto' or 'decltype(auto)', so diagnose.
3708*12c85518Srobert // Note: if updating this list, please make sure we update
3709*12c85518Srobert // isCXXDeclarationSpecifier's check for IsPlaceholderSpecifier to have
3710*12c85518Srobert // a matching list.
3711*12c85518Srobert if (NextToken().isOneOf(tok::identifier, tok::kw_const,
3712*12c85518Srobert tok::kw_volatile, tok::kw_restrict, tok::amp,
3713*12c85518Srobert tok::ampamp)) {
3714e5dd7070Spatrick Diag(Loc, diag::err_placeholder_expected_auto_or_decltype_auto)
3715e5dd7070Spatrick << FixItHint::CreateInsertion(NextToken().getLocation(), "auto");
3716e5dd7070Spatrick // Attempt to continue as if 'auto' was placed here.
3717e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID,
3718e5dd7070Spatrick TemplateId, Policy);
3719e5dd7070Spatrick break;
3720e5dd7070Spatrick }
3721e5dd7070Spatrick if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
3722e5dd7070Spatrick goto DoneWithDeclSpec;
3723e5dd7070Spatrick ConsumeAnnotationToken();
3724e5dd7070Spatrick SourceLocation AutoLoc = Tok.getLocation();
3725e5dd7070Spatrick if (TryConsumeToken(tok::kw_decltype)) {
3726e5dd7070Spatrick BalancedDelimiterTracker Tracker(*this, tok::l_paren);
3727e5dd7070Spatrick if (Tracker.consumeOpen()) {
3728e5dd7070Spatrick // Something like `void foo(Iterator decltype i)`
3729e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::l_paren;
3730e5dd7070Spatrick } else {
3731e5dd7070Spatrick if (!TryConsumeToken(tok::kw_auto)) {
3732e5dd7070Spatrick // Something like `void foo(Iterator decltype(int) i)`
3733e5dd7070Spatrick Tracker.skipToEnd();
3734e5dd7070Spatrick Diag(Tok, diag::err_placeholder_expected_auto_or_decltype_auto)
3735e5dd7070Spatrick << FixItHint::CreateReplacement(SourceRange(AutoLoc,
3736e5dd7070Spatrick Tok.getLocation()),
3737e5dd7070Spatrick "auto");
3738e5dd7070Spatrick } else {
3739e5dd7070Spatrick Tracker.consumeClose();
3740e5dd7070Spatrick }
3741e5dd7070Spatrick }
3742e5dd7070Spatrick ConsumedEnd = Tok.getLocation();
3743*12c85518Srobert DS.setTypeArgumentRange(Tracker.getRange());
3744e5dd7070Spatrick // Even if something went wrong above, continue as if we've seen
3745e5dd7070Spatrick // `decltype(auto)`.
3746e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec,
3747e5dd7070Spatrick DiagID, TemplateId, Policy);
3748e5dd7070Spatrick } else {
3749*12c85518Srobert isInvalid = DS.SetTypeSpecType(TST_auto, AutoLoc, PrevSpec, DiagID,
3750e5dd7070Spatrick TemplateId, Policy);
3751e5dd7070Spatrick }
3752e5dd7070Spatrick break;
3753e5dd7070Spatrick }
3754e5dd7070Spatrick
3755e5dd7070Spatrick if (TemplateId->Kind != TNK_Type_template &&
3756e5dd7070Spatrick TemplateId->Kind != TNK_Undeclared_template) {
3757e5dd7070Spatrick // This template-id does not refer to a type name, so we're
3758e5dd7070Spatrick // done with the type-specifiers.
3759e5dd7070Spatrick goto DoneWithDeclSpec;
3760e5dd7070Spatrick }
3761e5dd7070Spatrick
3762e5dd7070Spatrick // If we're in a context where the template-id could be a
3763e5dd7070Spatrick // constructor name or specialization, check whether this is a
3764e5dd7070Spatrick // constructor declaration.
3765e5dd7070Spatrick if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
3766e5dd7070Spatrick Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
3767*12c85518Srobert isConstructorDeclarator(/*Unqualified=*/true,
3768*12c85518Srobert /*DeductionGuide=*/false,
3769*12c85518Srobert DS.isFriendSpecified()))
3770e5dd7070Spatrick goto DoneWithDeclSpec;
3771e5dd7070Spatrick
3772e5dd7070Spatrick // Turn the template-id annotation token into a type annotation
3773e5dd7070Spatrick // token, then try again to parse it as a type-specifier.
3774e5dd7070Spatrick CXXScopeSpec SS;
3775*12c85518Srobert AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
3776e5dd7070Spatrick continue;
3777e5dd7070Spatrick }
3778e5dd7070Spatrick
3779a9ac8606Spatrick // Attributes support.
3780e5dd7070Spatrick case tok::kw___attribute:
3781e5dd7070Spatrick case tok::kw___declspec:
3782*12c85518Srobert ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), LateAttrs);
3783e5dd7070Spatrick continue;
3784e5dd7070Spatrick
3785e5dd7070Spatrick // Microsoft single token adornments.
3786e5dd7070Spatrick case tok::kw___forceinline: {
3787e5dd7070Spatrick isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);
3788e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
3789e5dd7070Spatrick SourceLocation AttrNameLoc = Tok.getLocation();
3790e5dd7070Spatrick DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,
3791e5dd7070Spatrick nullptr, 0, ParsedAttr::AS_Keyword);
3792e5dd7070Spatrick break;
3793e5dd7070Spatrick }
3794e5dd7070Spatrick
3795e5dd7070Spatrick case tok::kw___unaligned:
3796e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,
3797e5dd7070Spatrick getLangOpts());
3798e5dd7070Spatrick break;
3799e5dd7070Spatrick
3800e5dd7070Spatrick case tok::kw___sptr:
3801e5dd7070Spatrick case tok::kw___uptr:
3802e5dd7070Spatrick case tok::kw___ptr64:
3803e5dd7070Spatrick case tok::kw___ptr32:
3804e5dd7070Spatrick case tok::kw___w64:
3805e5dd7070Spatrick case tok::kw___cdecl:
3806e5dd7070Spatrick case tok::kw___stdcall:
3807e5dd7070Spatrick case tok::kw___fastcall:
3808e5dd7070Spatrick case tok::kw___thiscall:
3809e5dd7070Spatrick case tok::kw___regcall:
3810e5dd7070Spatrick case tok::kw___vectorcall:
3811e5dd7070Spatrick ParseMicrosoftTypeAttributes(DS.getAttributes());
3812e5dd7070Spatrick continue;
3813e5dd7070Spatrick
3814e5dd7070Spatrick // Borland single token adornments.
3815e5dd7070Spatrick case tok::kw___pascal:
3816e5dd7070Spatrick ParseBorlandTypeAttributes(DS.getAttributes());
3817e5dd7070Spatrick continue;
3818e5dd7070Spatrick
3819e5dd7070Spatrick // OpenCL single token adornments.
3820e5dd7070Spatrick case tok::kw___kernel:
3821e5dd7070Spatrick ParseOpenCLKernelAttributes(DS.getAttributes());
3822e5dd7070Spatrick continue;
3823e5dd7070Spatrick
3824*12c85518Srobert // CUDA/HIP single token adornments.
3825*12c85518Srobert case tok::kw___noinline__:
3826*12c85518Srobert ParseCUDAFunctionAttributes(DS.getAttributes());
3827*12c85518Srobert continue;
3828*12c85518Srobert
3829e5dd7070Spatrick // Nullability type specifiers.
3830e5dd7070Spatrick case tok::kw__Nonnull:
3831e5dd7070Spatrick case tok::kw__Nullable:
3832a9ac8606Spatrick case tok::kw__Nullable_result:
3833e5dd7070Spatrick case tok::kw__Null_unspecified:
3834e5dd7070Spatrick ParseNullabilityTypeSpecifiers(DS.getAttributes());
3835e5dd7070Spatrick continue;
3836e5dd7070Spatrick
3837e5dd7070Spatrick // Objective-C 'kindof' types.
3838e5dd7070Spatrick case tok::kw___kindof:
3839e5dd7070Spatrick DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
3840e5dd7070Spatrick nullptr, 0, ParsedAttr::AS_Keyword);
3841e5dd7070Spatrick (void)ConsumeToken();
3842e5dd7070Spatrick continue;
3843e5dd7070Spatrick
3844e5dd7070Spatrick // storage-class-specifier
3845e5dd7070Spatrick case tok::kw_typedef:
3846e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
3847e5dd7070Spatrick PrevSpec, DiagID, Policy);
3848e5dd7070Spatrick isStorageClass = true;
3849e5dd7070Spatrick break;
3850e5dd7070Spatrick case tok::kw_extern:
3851e5dd7070Spatrick if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
3852e5dd7070Spatrick Diag(Tok, diag::ext_thread_before) << "extern";
3853e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
3854e5dd7070Spatrick PrevSpec, DiagID, Policy);
3855e5dd7070Spatrick isStorageClass = true;
3856e5dd7070Spatrick break;
3857e5dd7070Spatrick case tok::kw___private_extern__:
3858e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
3859e5dd7070Spatrick Loc, PrevSpec, DiagID, Policy);
3860e5dd7070Spatrick isStorageClass = true;
3861e5dd7070Spatrick break;
3862e5dd7070Spatrick case tok::kw_static:
3863e5dd7070Spatrick if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
3864e5dd7070Spatrick Diag(Tok, diag::ext_thread_before) << "static";
3865e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
3866e5dd7070Spatrick PrevSpec, DiagID, Policy);
3867e5dd7070Spatrick isStorageClass = true;
3868e5dd7070Spatrick break;
3869e5dd7070Spatrick case tok::kw_auto:
3870e5dd7070Spatrick if (getLangOpts().CPlusPlus11) {
3871e5dd7070Spatrick if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
3872e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
3873e5dd7070Spatrick PrevSpec, DiagID, Policy);
3874e5dd7070Spatrick if (!isInvalid)
3875e5dd7070Spatrick Diag(Tok, diag::ext_auto_storage_class)
3876e5dd7070Spatrick << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
3877e5dd7070Spatrick } else
3878e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
3879e5dd7070Spatrick DiagID, Policy);
3880e5dd7070Spatrick } else
3881e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
3882e5dd7070Spatrick PrevSpec, DiagID, Policy);
3883e5dd7070Spatrick isStorageClass = true;
3884e5dd7070Spatrick break;
3885e5dd7070Spatrick case tok::kw___auto_type:
3886e5dd7070Spatrick Diag(Tok, diag::ext_auto_type);
3887e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
3888e5dd7070Spatrick DiagID, Policy);
3889e5dd7070Spatrick break;
3890e5dd7070Spatrick case tok::kw_register:
3891e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
3892e5dd7070Spatrick PrevSpec, DiagID, Policy);
3893e5dd7070Spatrick isStorageClass = true;
3894e5dd7070Spatrick break;
3895e5dd7070Spatrick case tok::kw_mutable:
3896e5dd7070Spatrick isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
3897e5dd7070Spatrick PrevSpec, DiagID, Policy);
3898e5dd7070Spatrick isStorageClass = true;
3899e5dd7070Spatrick break;
3900e5dd7070Spatrick case tok::kw___thread:
3901e5dd7070Spatrick isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
3902e5dd7070Spatrick PrevSpec, DiagID);
3903e5dd7070Spatrick isStorageClass = true;
3904e5dd7070Spatrick break;
3905e5dd7070Spatrick case tok::kw_thread_local:
3906e5dd7070Spatrick isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc,
3907e5dd7070Spatrick PrevSpec, DiagID);
3908e5dd7070Spatrick isStorageClass = true;
3909e5dd7070Spatrick break;
3910e5dd7070Spatrick case tok::kw__Thread_local:
3911e5dd7070Spatrick if (!getLangOpts().C11)
3912e5dd7070Spatrick Diag(Tok, diag::ext_c11_feature) << Tok.getName();
3913e5dd7070Spatrick isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
3914e5dd7070Spatrick Loc, PrevSpec, DiagID);
3915e5dd7070Spatrick isStorageClass = true;
3916e5dd7070Spatrick break;
3917e5dd7070Spatrick
3918e5dd7070Spatrick // function-specifier
3919e5dd7070Spatrick case tok::kw_inline:
3920e5dd7070Spatrick isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);
3921e5dd7070Spatrick break;
3922e5dd7070Spatrick case tok::kw_virtual:
3923e5dd7070Spatrick // C++ for OpenCL does not allow virtual function qualifier, to avoid
3924e5dd7070Spatrick // function pointers restricted in OpenCL v2.0 s6.9.a.
3925a9ac8606Spatrick if (getLangOpts().OpenCLCPlusPlus &&
3926a9ac8606Spatrick !getActions().getOpenCLOptions().isAvailableOption(
3927a9ac8606Spatrick "__cl_clang_function_pointers", getLangOpts())) {
3928e5dd7070Spatrick DiagID = diag::err_openclcxx_virtual_function;
3929e5dd7070Spatrick PrevSpec = Tok.getIdentifierInfo()->getNameStart();
3930e5dd7070Spatrick isInvalid = true;
3931a9ac8606Spatrick } else {
3932e5dd7070Spatrick isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
3933e5dd7070Spatrick }
3934e5dd7070Spatrick break;
3935e5dd7070Spatrick case tok::kw_explicit: {
3936e5dd7070Spatrick SourceLocation ExplicitLoc = Loc;
3937e5dd7070Spatrick SourceLocation CloseParenLoc;
3938e5dd7070Spatrick ExplicitSpecifier ExplicitSpec(nullptr, ExplicitSpecKind::ResolvedTrue);
3939e5dd7070Spatrick ConsumedEnd = ExplicitLoc;
3940e5dd7070Spatrick ConsumeToken(); // kw_explicit
3941e5dd7070Spatrick if (Tok.is(tok::l_paren)) {
3942ec727ea7Spatrick if (getLangOpts().CPlusPlus20 || isExplicitBool() == TPResult::True) {
3943ec727ea7Spatrick Diag(Tok.getLocation(), getLangOpts().CPlusPlus20
3944e5dd7070Spatrick ? diag::warn_cxx17_compat_explicit_bool
3945e5dd7070Spatrick : diag::ext_explicit_bool);
3946e5dd7070Spatrick
3947e5dd7070Spatrick ExprResult ExplicitExpr(static_cast<Expr *>(nullptr));
3948e5dd7070Spatrick BalancedDelimiterTracker Tracker(*this, tok::l_paren);
3949e5dd7070Spatrick Tracker.consumeOpen();
3950e5dd7070Spatrick ExplicitExpr = ParseConstantExpression();
3951e5dd7070Spatrick ConsumedEnd = Tok.getLocation();
3952e5dd7070Spatrick if (ExplicitExpr.isUsable()) {
3953e5dd7070Spatrick CloseParenLoc = Tok.getLocation();
3954e5dd7070Spatrick Tracker.consumeClose();
3955e5dd7070Spatrick ExplicitSpec =
3956e5dd7070Spatrick Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get());
3957e5dd7070Spatrick } else
3958e5dd7070Spatrick Tracker.skipToEnd();
3959e5dd7070Spatrick } else {
3960ec727ea7Spatrick Diag(Tok.getLocation(), diag::warn_cxx20_compat_explicit_bool);
3961e5dd7070Spatrick }
3962e5dd7070Spatrick }
3963e5dd7070Spatrick isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID,
3964e5dd7070Spatrick ExplicitSpec, CloseParenLoc);
3965e5dd7070Spatrick break;
3966e5dd7070Spatrick }
3967e5dd7070Spatrick case tok::kw__Noreturn:
3968e5dd7070Spatrick if (!getLangOpts().C11)
3969e5dd7070Spatrick Diag(Tok, diag::ext_c11_feature) << Tok.getName();
3970e5dd7070Spatrick isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
3971e5dd7070Spatrick break;
3972e5dd7070Spatrick
3973e5dd7070Spatrick // alignment-specifier
3974e5dd7070Spatrick case tok::kw__Alignas:
3975e5dd7070Spatrick if (!getLangOpts().C11)
3976e5dd7070Spatrick Diag(Tok, diag::ext_c11_feature) << Tok.getName();
3977e5dd7070Spatrick ParseAlignmentSpecifier(DS.getAttributes());
3978e5dd7070Spatrick continue;
3979e5dd7070Spatrick
3980e5dd7070Spatrick // friend
3981e5dd7070Spatrick case tok::kw_friend:
3982e5dd7070Spatrick if (DSContext == DeclSpecContext::DSC_class)
3983e5dd7070Spatrick isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
3984e5dd7070Spatrick else {
3985e5dd7070Spatrick PrevSpec = ""; // not actually used by the diagnostic
3986e5dd7070Spatrick DiagID = diag::err_friend_invalid_in_context;
3987e5dd7070Spatrick isInvalid = true;
3988e5dd7070Spatrick }
3989e5dd7070Spatrick break;
3990e5dd7070Spatrick
3991e5dd7070Spatrick // Modules
3992e5dd7070Spatrick case tok::kw___module_private__:
3993e5dd7070Spatrick isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);
3994e5dd7070Spatrick break;
3995e5dd7070Spatrick
3996e5dd7070Spatrick // constexpr, consteval, constinit specifiers
3997e5dd7070Spatrick case tok::kw_constexpr:
3998a9ac8606Spatrick isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
3999a9ac8606Spatrick PrevSpec, DiagID);
4000e5dd7070Spatrick break;
4001e5dd7070Spatrick case tok::kw_consteval:
4002a9ac8606Spatrick isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Consteval, Loc,
4003a9ac8606Spatrick PrevSpec, DiagID);
4004e5dd7070Spatrick break;
4005e5dd7070Spatrick case tok::kw_constinit:
4006a9ac8606Spatrick isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constinit, Loc,
4007a9ac8606Spatrick PrevSpec, DiagID);
4008e5dd7070Spatrick break;
4009e5dd7070Spatrick
4010e5dd7070Spatrick // type-specifier
4011e5dd7070Spatrick case tok::kw_short:
4012a9ac8606Spatrick isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Short, Loc, PrevSpec,
4013e5dd7070Spatrick DiagID, Policy);
4014e5dd7070Spatrick break;
4015e5dd7070Spatrick case tok::kw_long:
4016a9ac8606Spatrick if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Long)
4017a9ac8606Spatrick isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Long, Loc, PrevSpec,
4018e5dd7070Spatrick DiagID, Policy);
4019e5dd7070Spatrick else
4020a9ac8606Spatrick isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,
4021a9ac8606Spatrick PrevSpec, DiagID, Policy);
4022e5dd7070Spatrick break;
4023e5dd7070Spatrick case tok::kw___int64:
4024a9ac8606Spatrick isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,
4025a9ac8606Spatrick PrevSpec, DiagID, Policy);
4026e5dd7070Spatrick break;
4027e5dd7070Spatrick case tok::kw_signed:
4028a9ac8606Spatrick isInvalid =
4029a9ac8606Spatrick DS.SetTypeSpecSign(TypeSpecifierSign::Signed, Loc, PrevSpec, DiagID);
4030e5dd7070Spatrick break;
4031e5dd7070Spatrick case tok::kw_unsigned:
4032a9ac8606Spatrick isInvalid = DS.SetTypeSpecSign(TypeSpecifierSign::Unsigned, Loc, PrevSpec,
4033e5dd7070Spatrick DiagID);
4034e5dd7070Spatrick break;
4035e5dd7070Spatrick case tok::kw__Complex:
4036e5dd7070Spatrick if (!getLangOpts().C99)
4037e5dd7070Spatrick Diag(Tok, diag::ext_c99_feature) << Tok.getName();
4038e5dd7070Spatrick isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
4039e5dd7070Spatrick DiagID);
4040e5dd7070Spatrick break;
4041e5dd7070Spatrick case tok::kw__Imaginary:
4042e5dd7070Spatrick if (!getLangOpts().C99)
4043e5dd7070Spatrick Diag(Tok, diag::ext_c99_feature) << Tok.getName();
4044e5dd7070Spatrick isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
4045e5dd7070Spatrick DiagID);
4046e5dd7070Spatrick break;
4047e5dd7070Spatrick case tok::kw_void:
4048e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
4049e5dd7070Spatrick DiagID, Policy);
4050e5dd7070Spatrick break;
4051e5dd7070Spatrick case tok::kw_char:
4052e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
4053e5dd7070Spatrick DiagID, Policy);
4054e5dd7070Spatrick break;
4055e5dd7070Spatrick case tok::kw_int:
4056e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
4057e5dd7070Spatrick DiagID, Policy);
4058e5dd7070Spatrick break;
4059*12c85518Srobert case tok::kw__ExtInt:
4060*12c85518Srobert case tok::kw__BitInt: {
4061*12c85518Srobert DiagnoseBitIntUse(Tok);
4062ec727ea7Spatrick ExprResult ER = ParseExtIntegerArgument();
4063ec727ea7Spatrick if (ER.isInvalid())
4064ec727ea7Spatrick continue;
4065*12c85518Srobert isInvalid = DS.SetBitIntType(Loc, ER.get(), PrevSpec, DiagID, Policy);
4066ec727ea7Spatrick ConsumedEnd = PrevTokLocation;
4067ec727ea7Spatrick break;
4068ec727ea7Spatrick }
4069e5dd7070Spatrick case tok::kw___int128:
4070e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
4071e5dd7070Spatrick DiagID, Policy);
4072e5dd7070Spatrick break;
4073e5dd7070Spatrick case tok::kw_half:
4074e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
4075e5dd7070Spatrick DiagID, Policy);
4076e5dd7070Spatrick break;
4077ec727ea7Spatrick case tok::kw___bf16:
4078ec727ea7Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec,
4079ec727ea7Spatrick DiagID, Policy);
4080ec727ea7Spatrick break;
4081e5dd7070Spatrick case tok::kw_float:
4082e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
4083e5dd7070Spatrick DiagID, Policy);
4084e5dd7070Spatrick break;
4085e5dd7070Spatrick case tok::kw_double:
4086e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
4087e5dd7070Spatrick DiagID, Policy);
4088e5dd7070Spatrick break;
4089e5dd7070Spatrick case tok::kw__Float16:
4090e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,
4091e5dd7070Spatrick DiagID, Policy);
4092e5dd7070Spatrick break;
4093e5dd7070Spatrick case tok::kw__Accum:
4094e5dd7070Spatrick if (!getLangOpts().FixedPoint) {
4095e5dd7070Spatrick SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
4096e5dd7070Spatrick } else {
4097e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec,
4098e5dd7070Spatrick DiagID, Policy);
4099e5dd7070Spatrick }
4100e5dd7070Spatrick break;
4101e5dd7070Spatrick case tok::kw__Fract:
4102e5dd7070Spatrick if (!getLangOpts().FixedPoint) {
4103e5dd7070Spatrick SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
4104e5dd7070Spatrick } else {
4105e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec,
4106e5dd7070Spatrick DiagID, Policy);
4107e5dd7070Spatrick }
4108e5dd7070Spatrick break;
4109e5dd7070Spatrick case tok::kw__Sat:
4110e5dd7070Spatrick if (!getLangOpts().FixedPoint) {
4111e5dd7070Spatrick SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
4112e5dd7070Spatrick } else {
4113e5dd7070Spatrick isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID);
4114e5dd7070Spatrick }
4115e5dd7070Spatrick break;
4116e5dd7070Spatrick case tok::kw___float128:
4117e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
4118e5dd7070Spatrick DiagID, Policy);
4119e5dd7070Spatrick break;
4120*12c85518Srobert case tok::kw___ibm128:
4121*12c85518Srobert isInvalid = DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec,
4122*12c85518Srobert DiagID, Policy);
4123*12c85518Srobert break;
4124e5dd7070Spatrick case tok::kw_wchar_t:
4125e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
4126e5dd7070Spatrick DiagID, Policy);
4127e5dd7070Spatrick break;
4128e5dd7070Spatrick case tok::kw_char8_t:
4129e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec,
4130e5dd7070Spatrick DiagID, Policy);
4131e5dd7070Spatrick break;
4132e5dd7070Spatrick case tok::kw_char16_t:
4133e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
4134e5dd7070Spatrick DiagID, Policy);
4135e5dd7070Spatrick break;
4136e5dd7070Spatrick case tok::kw_char32_t:
4137e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
4138e5dd7070Spatrick DiagID, Policy);
4139e5dd7070Spatrick break;
4140e5dd7070Spatrick case tok::kw_bool:
4141e5dd7070Spatrick case tok::kw__Bool:
4142e5dd7070Spatrick if (Tok.is(tok::kw__Bool) && !getLangOpts().C99)
4143e5dd7070Spatrick Diag(Tok, diag::ext_c99_feature) << Tok.getName();
4144e5dd7070Spatrick
4145e5dd7070Spatrick if (Tok.is(tok::kw_bool) &&
4146e5dd7070Spatrick DS.getTypeSpecType() != DeclSpec::TST_unspecified &&
4147e5dd7070Spatrick DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
4148e5dd7070Spatrick PrevSpec = ""; // Not used by the diagnostic.
4149e5dd7070Spatrick DiagID = diag::err_bool_redeclaration;
4150e5dd7070Spatrick // For better error recovery.
4151e5dd7070Spatrick Tok.setKind(tok::identifier);
4152e5dd7070Spatrick isInvalid = true;
4153e5dd7070Spatrick } else {
4154e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
4155e5dd7070Spatrick DiagID, Policy);
4156e5dd7070Spatrick }
4157e5dd7070Spatrick break;
4158e5dd7070Spatrick case tok::kw__Decimal32:
4159e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
4160e5dd7070Spatrick DiagID, Policy);
4161e5dd7070Spatrick break;
4162e5dd7070Spatrick case tok::kw__Decimal64:
4163e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
4164e5dd7070Spatrick DiagID, Policy);
4165e5dd7070Spatrick break;
4166e5dd7070Spatrick case tok::kw__Decimal128:
4167e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
4168e5dd7070Spatrick DiagID, Policy);
4169e5dd7070Spatrick break;
4170e5dd7070Spatrick case tok::kw___vector:
4171e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
4172e5dd7070Spatrick break;
4173e5dd7070Spatrick case tok::kw___pixel:
4174e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
4175e5dd7070Spatrick break;
4176e5dd7070Spatrick case tok::kw___bool:
4177e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
4178e5dd7070Spatrick break;
4179e5dd7070Spatrick case tok::kw_pipe:
4180*12c85518Srobert if (!getLangOpts().OpenCL ||
4181*12c85518Srobert getLangOpts().getOpenCLCompatibleVersion() < 200) {
4182a9ac8606Spatrick // OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier
4183a9ac8606Spatrick // should support the "pipe" word as identifier.
4184e5dd7070Spatrick Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
4185a9ac8606Spatrick Tok.setKind(tok::identifier);
4186e5dd7070Spatrick goto DoneWithDeclSpec;
4187a9ac8606Spatrick } else if (!getLangOpts().OpenCLPipes) {
4188a9ac8606Spatrick DiagID = diag::err_opencl_unknown_type_specifier;
4189a9ac8606Spatrick PrevSpec = Tok.getIdentifierInfo()->getNameStart();
4190a9ac8606Spatrick isInvalid = true;
4191a9ac8606Spatrick } else
4192e5dd7070Spatrick isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
4193e5dd7070Spatrick break;
4194a9ac8606Spatrick // We only need to enumerate each image type once.
4195a9ac8606Spatrick #define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
4196a9ac8606Spatrick #define IMAGE_WRITE_TYPE(Type, Id, Ext)
4197a9ac8606Spatrick #define IMAGE_READ_TYPE(ImgType, Id, Ext) \
4198e5dd7070Spatrick case tok::kw_##ImgType##_t: \
4199a9ac8606Spatrick if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \
4200a9ac8606Spatrick goto DoneWithDeclSpec; \
4201e5dd7070Spatrick break;
4202e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
4203e5dd7070Spatrick case tok::kw___unknown_anytype:
4204e5dd7070Spatrick isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
4205e5dd7070Spatrick PrevSpec, DiagID, Policy);
4206e5dd7070Spatrick break;
4207e5dd7070Spatrick
4208e5dd7070Spatrick // class-specifier:
4209e5dd7070Spatrick case tok::kw_class:
4210e5dd7070Spatrick case tok::kw_struct:
4211e5dd7070Spatrick case tok::kw___interface:
4212e5dd7070Spatrick case tok::kw_union: {
4213e5dd7070Spatrick tok::TokenKind Kind = Tok.getKind();
4214e5dd7070Spatrick ConsumeToken();
4215e5dd7070Spatrick
4216e5dd7070Spatrick // These are attributes following class specifiers.
4217e5dd7070Spatrick // To produce better diagnostic, we parse them when
4218e5dd7070Spatrick // parsing class specifier.
4219*12c85518Srobert ParsedAttributes Attributes(AttrFactory);
4220e5dd7070Spatrick ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS,
4221e5dd7070Spatrick EnteringContext, DSContext, Attributes);
4222e5dd7070Spatrick
4223e5dd7070Spatrick // If there are attributes following class specifier,
4224e5dd7070Spatrick // take them over and handle them here.
4225e5dd7070Spatrick if (!Attributes.empty()) {
4226e5dd7070Spatrick AttrsLastTime = true;
4227e5dd7070Spatrick attrs.takeAllFrom(Attributes);
4228e5dd7070Spatrick }
4229e5dd7070Spatrick continue;
4230e5dd7070Spatrick }
4231e5dd7070Spatrick
4232e5dd7070Spatrick // enum-specifier:
4233e5dd7070Spatrick case tok::kw_enum:
4234e5dd7070Spatrick ConsumeToken();
4235e5dd7070Spatrick ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext);
4236e5dd7070Spatrick continue;
4237e5dd7070Spatrick
4238e5dd7070Spatrick // cv-qualifier:
4239e5dd7070Spatrick case tok::kw_const:
4240e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
4241e5dd7070Spatrick getLangOpts());
4242e5dd7070Spatrick break;
4243e5dd7070Spatrick case tok::kw_volatile:
4244e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
4245e5dd7070Spatrick getLangOpts());
4246e5dd7070Spatrick break;
4247e5dd7070Spatrick case tok::kw_restrict:
4248e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
4249e5dd7070Spatrick getLangOpts());
4250e5dd7070Spatrick break;
4251e5dd7070Spatrick
4252e5dd7070Spatrick // C++ typename-specifier:
4253e5dd7070Spatrick case tok::kw_typename:
4254e5dd7070Spatrick if (TryAnnotateTypeOrScopeToken()) {
4255e5dd7070Spatrick DS.SetTypeSpecError();
4256e5dd7070Spatrick goto DoneWithDeclSpec;
4257e5dd7070Spatrick }
4258e5dd7070Spatrick if (!Tok.is(tok::kw_typename))
4259e5dd7070Spatrick continue;
4260e5dd7070Spatrick break;
4261e5dd7070Spatrick
4262*12c85518Srobert // C2x/GNU typeof support.
4263e5dd7070Spatrick case tok::kw_typeof:
4264*12c85518Srobert case tok::kw_typeof_unqual:
4265e5dd7070Spatrick ParseTypeofSpecifier(DS);
4266e5dd7070Spatrick continue;
4267e5dd7070Spatrick
4268e5dd7070Spatrick case tok::annot_decltype:
4269e5dd7070Spatrick ParseDecltypeSpecifier(DS);
4270e5dd7070Spatrick continue;
4271e5dd7070Spatrick
4272e5dd7070Spatrick case tok::annot_pragma_pack:
4273e5dd7070Spatrick HandlePragmaPack();
4274e5dd7070Spatrick continue;
4275e5dd7070Spatrick
4276e5dd7070Spatrick case tok::annot_pragma_ms_pragma:
4277e5dd7070Spatrick HandlePragmaMSPragma();
4278e5dd7070Spatrick continue;
4279e5dd7070Spatrick
4280e5dd7070Spatrick case tok::annot_pragma_ms_vtordisp:
4281e5dd7070Spatrick HandlePragmaMSVtorDisp();
4282e5dd7070Spatrick continue;
4283e5dd7070Spatrick
4284e5dd7070Spatrick case tok::annot_pragma_ms_pointers_to_members:
4285e5dd7070Spatrick HandlePragmaMSPointersToMembers();
4286e5dd7070Spatrick continue;
4287e5dd7070Spatrick
4288*12c85518Srobert #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
4289*12c85518Srobert #include "clang/Basic/TransformTypeTraits.def"
4290*12c85518Srobert // HACK: libstdc++ already uses '__remove_cv' as an alias template so we
4291*12c85518Srobert // work around this by expecting all transform type traits to be suffixed
4292*12c85518Srobert // with '('. They're an identifier otherwise.
4293*12c85518Srobert if (!MaybeParseTypeTransformTypeSpecifier(DS))
4294*12c85518Srobert goto ParseIdentifier;
4295e5dd7070Spatrick continue;
4296e5dd7070Spatrick
4297e5dd7070Spatrick case tok::kw__Atomic:
4298e5dd7070Spatrick // C11 6.7.2.4/4:
4299e5dd7070Spatrick // If the _Atomic keyword is immediately followed by a left parenthesis,
4300e5dd7070Spatrick // it is interpreted as a type specifier (with a type name), not as a
4301e5dd7070Spatrick // type qualifier.
4302e5dd7070Spatrick if (!getLangOpts().C11)
4303e5dd7070Spatrick Diag(Tok, diag::ext_c11_feature) << Tok.getName();
4304e5dd7070Spatrick
4305e5dd7070Spatrick if (NextToken().is(tok::l_paren)) {
4306e5dd7070Spatrick ParseAtomicSpecifier(DS);
4307e5dd7070Spatrick continue;
4308e5dd7070Spatrick }
4309e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
4310e5dd7070Spatrick getLangOpts());
4311e5dd7070Spatrick break;
4312e5dd7070Spatrick
4313e5dd7070Spatrick // OpenCL address space qualifiers:
4314e5dd7070Spatrick case tok::kw___generic:
4315e5dd7070Spatrick // generic address space is introduced only in OpenCL v2.0
4316e5dd7070Spatrick // see OpenCL C Spec v2.0 s6.5.5
4317a9ac8606Spatrick // OpenCL v3.0 introduces __opencl_c_generic_address_space
4318a9ac8606Spatrick // feature macro to indicate if generic address space is supported
4319a9ac8606Spatrick if (!Actions.getLangOpts().OpenCLGenericAddressSpace) {
4320e5dd7070Spatrick DiagID = diag::err_opencl_unknown_type_specifier;
4321e5dd7070Spatrick PrevSpec = Tok.getIdentifierInfo()->getNameStart();
4322e5dd7070Spatrick isInvalid = true;
4323e5dd7070Spatrick break;
4324e5dd7070Spatrick }
4325*12c85518Srobert [[fallthrough]];
4326e5dd7070Spatrick case tok::kw_private:
4327e5dd7070Spatrick // It's fine (but redundant) to check this for __generic on the
4328e5dd7070Spatrick // fallthrough path; we only form the __generic token in OpenCL mode.
4329e5dd7070Spatrick if (!getLangOpts().OpenCL)
4330e5dd7070Spatrick goto DoneWithDeclSpec;
4331*12c85518Srobert [[fallthrough]];
4332e5dd7070Spatrick case tok::kw___private:
4333e5dd7070Spatrick case tok::kw___global:
4334e5dd7070Spatrick case tok::kw___local:
4335e5dd7070Spatrick case tok::kw___constant:
4336e5dd7070Spatrick // OpenCL access qualifiers:
4337e5dd7070Spatrick case tok::kw___read_only:
4338e5dd7070Spatrick case tok::kw___write_only:
4339e5dd7070Spatrick case tok::kw___read_write:
4340e5dd7070Spatrick ParseOpenCLQualifiers(DS.getAttributes());
4341e5dd7070Spatrick break;
4342e5dd7070Spatrick
4343*12c85518Srobert case tok::kw_groupshared:
4344*12c85518Srobert // NOTE: ParseHLSLQualifiers will consume the qualifier token.
4345*12c85518Srobert ParseHLSLQualifiers(DS.getAttributes());
4346*12c85518Srobert continue;
4347*12c85518Srobert
4348e5dd7070Spatrick case tok::less:
4349e5dd7070Spatrick // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
4350e5dd7070Spatrick // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
4351e5dd7070Spatrick // but we support it.
4352e5dd7070Spatrick if (DS.hasTypeSpecifier() || !getLangOpts().ObjC)
4353e5dd7070Spatrick goto DoneWithDeclSpec;
4354e5dd7070Spatrick
4355e5dd7070Spatrick SourceLocation StartLoc = Tok.getLocation();
4356e5dd7070Spatrick SourceLocation EndLoc;
4357e5dd7070Spatrick TypeResult Type = parseObjCProtocolQualifierType(EndLoc);
4358e5dd7070Spatrick if (Type.isUsable()) {
4359e5dd7070Spatrick if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, StartLoc,
4360e5dd7070Spatrick PrevSpec, DiagID, Type.get(),
4361e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
4362e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
4363e5dd7070Spatrick
4364e5dd7070Spatrick DS.SetRangeEnd(EndLoc);
4365e5dd7070Spatrick } else {
4366e5dd7070Spatrick DS.SetTypeSpecError();
4367e5dd7070Spatrick }
4368e5dd7070Spatrick
4369e5dd7070Spatrick // Need to support trailing type qualifiers (e.g. "id<p> const").
4370e5dd7070Spatrick // If a type specifier follows, it will be diagnosed elsewhere.
4371e5dd7070Spatrick continue;
4372e5dd7070Spatrick }
4373e5dd7070Spatrick
4374e5dd7070Spatrick DS.SetRangeEnd(ConsumedEnd.isValid() ? ConsumedEnd : Tok.getLocation());
4375e5dd7070Spatrick
4376e5dd7070Spatrick // If the specifier wasn't legal, issue a diagnostic.
4377e5dd7070Spatrick if (isInvalid) {
4378e5dd7070Spatrick assert(PrevSpec && "Method did not return previous specifier!");
4379e5dd7070Spatrick assert(DiagID);
4380e5dd7070Spatrick
4381e5dd7070Spatrick if (DiagID == diag::ext_duplicate_declspec ||
4382e5dd7070Spatrick DiagID == diag::ext_warn_duplicate_declspec ||
4383e5dd7070Spatrick DiagID == diag::err_duplicate_declspec)
4384e5dd7070Spatrick Diag(Loc, DiagID) << PrevSpec
4385e5dd7070Spatrick << FixItHint::CreateRemoval(
4386e5dd7070Spatrick SourceRange(Loc, DS.getEndLoc()));
4387e5dd7070Spatrick else if (DiagID == diag::err_opencl_unknown_type_specifier) {
4388*12c85518Srobert Diag(Loc, DiagID) << getLangOpts().getOpenCLVersionString() << PrevSpec
4389*12c85518Srobert << isStorageClass;
4390e5dd7070Spatrick } else
4391e5dd7070Spatrick Diag(Loc, DiagID) << PrevSpec;
4392e5dd7070Spatrick }
4393e5dd7070Spatrick
4394e5dd7070Spatrick if (DiagID != diag::err_bool_redeclaration && ConsumedEnd.isInvalid())
4395e5dd7070Spatrick // After an error the next token can be an annotation token.
4396e5dd7070Spatrick ConsumeAnyToken();
4397e5dd7070Spatrick
4398e5dd7070Spatrick AttrsLastTime = false;
4399e5dd7070Spatrick }
4400e5dd7070Spatrick }
4401e5dd7070Spatrick
4402e5dd7070Spatrick /// ParseStructDeclaration - Parse a struct declaration without the terminating
4403e5dd7070Spatrick /// semicolon.
4404e5dd7070Spatrick ///
4405e5dd7070Spatrick /// Note that a struct declaration refers to a declaration in a struct,
4406e5dd7070Spatrick /// not to the declaration of a struct.
4407e5dd7070Spatrick ///
4408e5dd7070Spatrick /// struct-declaration:
4409e5dd7070Spatrick /// [C2x] attributes-specifier-seq[opt]
4410e5dd7070Spatrick /// specifier-qualifier-list struct-declarator-list
4411e5dd7070Spatrick /// [GNU] __extension__ struct-declaration
4412e5dd7070Spatrick /// [GNU] specifier-qualifier-list
4413e5dd7070Spatrick /// struct-declarator-list:
4414e5dd7070Spatrick /// struct-declarator
4415e5dd7070Spatrick /// struct-declarator-list ',' struct-declarator
4416e5dd7070Spatrick /// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator
4417e5dd7070Spatrick /// struct-declarator:
4418e5dd7070Spatrick /// declarator
4419e5dd7070Spatrick /// [GNU] declarator attributes[opt]
4420e5dd7070Spatrick /// declarator[opt] ':' constant-expression
4421e5dd7070Spatrick /// [GNU] declarator[opt] ':' constant-expression attributes[opt]
4422e5dd7070Spatrick ///
ParseStructDeclaration(ParsingDeclSpec & DS,llvm::function_ref<void (ParsingFieldDeclarator &)> FieldsCallback)4423e5dd7070Spatrick void Parser::ParseStructDeclaration(
4424e5dd7070Spatrick ParsingDeclSpec &DS,
4425e5dd7070Spatrick llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback) {
4426e5dd7070Spatrick
4427e5dd7070Spatrick if (Tok.is(tok::kw___extension__)) {
4428e5dd7070Spatrick // __extension__ silences extension warnings in the subexpression.
4429e5dd7070Spatrick ExtensionRAIIObject O(Diags); // Use RAII to do this.
4430e5dd7070Spatrick ConsumeToken();
4431e5dd7070Spatrick return ParseStructDeclaration(DS, FieldsCallback);
4432e5dd7070Spatrick }
4433e5dd7070Spatrick
4434e5dd7070Spatrick // Parse leading attributes.
4435*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
4436e5dd7070Spatrick MaybeParseCXX11Attributes(Attrs);
4437e5dd7070Spatrick
4438e5dd7070Spatrick // Parse the common specifier-qualifiers-list piece.
4439e5dd7070Spatrick ParseSpecifierQualifierList(DS);
4440e5dd7070Spatrick
4441e5dd7070Spatrick // If there are no declarators, this is a free-standing declaration
4442e5dd7070Spatrick // specifier. Let the actions module cope with it.
4443e5dd7070Spatrick if (Tok.is(tok::semi)) {
4444*12c85518Srobert // C2x 6.7.2.1p9 : "The optional attribute specifier sequence in a
4445*12c85518Srobert // member declaration appertains to each of the members declared by the
4446*12c85518Srobert // member declarator list; it shall not appear if the optional member
4447*12c85518Srobert // declarator list is omitted."
4448*12c85518Srobert ProhibitAttributes(Attrs);
4449e5dd7070Spatrick RecordDecl *AnonRecord = nullptr;
4450*12c85518Srobert Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
4451*12c85518Srobert getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
4452e5dd7070Spatrick assert(!AnonRecord && "Did not expect anonymous struct or union here");
4453e5dd7070Spatrick DS.complete(TheDecl);
4454e5dd7070Spatrick return;
4455e5dd7070Spatrick }
4456e5dd7070Spatrick
4457e5dd7070Spatrick // Read struct-declarators until we find the semicolon.
4458e5dd7070Spatrick bool FirstDeclarator = true;
4459e5dd7070Spatrick SourceLocation CommaLoc;
4460*12c85518Srobert while (true) {
4461*12c85518Srobert ParsingFieldDeclarator DeclaratorInfo(*this, DS, Attrs);
4462e5dd7070Spatrick DeclaratorInfo.D.setCommaLoc(CommaLoc);
4463e5dd7070Spatrick
4464e5dd7070Spatrick // Attributes are only allowed here on successive declarators.
4465a9ac8606Spatrick if (!FirstDeclarator) {
4466a9ac8606Spatrick // However, this does not apply for [[]] attributes (which could show up
4467a9ac8606Spatrick // before or after the __attribute__ attributes).
4468a9ac8606Spatrick DiagnoseAndSkipCXX11Attributes();
4469e5dd7070Spatrick MaybeParseGNUAttributes(DeclaratorInfo.D);
4470a9ac8606Spatrick DiagnoseAndSkipCXX11Attributes();
4471a9ac8606Spatrick }
4472e5dd7070Spatrick
4473e5dd7070Spatrick /// struct-declarator: declarator
4474e5dd7070Spatrick /// struct-declarator: declarator[opt] ':' constant-expression
4475e5dd7070Spatrick if (Tok.isNot(tok::colon)) {
4476e5dd7070Spatrick // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
4477e5dd7070Spatrick ColonProtectionRAIIObject X(*this);
4478e5dd7070Spatrick ParseDeclarator(DeclaratorInfo.D);
4479e5dd7070Spatrick } else
4480e5dd7070Spatrick DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation());
4481e5dd7070Spatrick
4482e5dd7070Spatrick if (TryConsumeToken(tok::colon)) {
4483e5dd7070Spatrick ExprResult Res(ParseConstantExpression());
4484e5dd7070Spatrick if (Res.isInvalid())
4485e5dd7070Spatrick SkipUntil(tok::semi, StopBeforeMatch);
4486e5dd7070Spatrick else
4487e5dd7070Spatrick DeclaratorInfo.BitfieldSize = Res.get();
4488e5dd7070Spatrick }
4489e5dd7070Spatrick
4490e5dd7070Spatrick // If attributes exist after the declarator, parse them.
4491e5dd7070Spatrick MaybeParseGNUAttributes(DeclaratorInfo.D);
4492e5dd7070Spatrick
4493e5dd7070Spatrick // We're done with this declarator; invoke the callback.
4494e5dd7070Spatrick FieldsCallback(DeclaratorInfo);
4495e5dd7070Spatrick
4496e5dd7070Spatrick // If we don't have a comma, it is either the end of the list (a ';')
4497e5dd7070Spatrick // or an error, bail out.
4498e5dd7070Spatrick if (!TryConsumeToken(tok::comma, CommaLoc))
4499e5dd7070Spatrick return;
4500e5dd7070Spatrick
4501e5dd7070Spatrick FirstDeclarator = false;
4502e5dd7070Spatrick }
4503e5dd7070Spatrick }
4504e5dd7070Spatrick
4505e5dd7070Spatrick /// ParseStructUnionBody
4506e5dd7070Spatrick /// struct-contents:
4507e5dd7070Spatrick /// struct-declaration-list
4508e5dd7070Spatrick /// [EXT] empty
4509a9ac8606Spatrick /// [GNU] "struct-declaration-list" without terminating ';'
4510e5dd7070Spatrick /// struct-declaration-list:
4511e5dd7070Spatrick /// struct-declaration
4512e5dd7070Spatrick /// struct-declaration-list struct-declaration
4513e5dd7070Spatrick /// [OBC] '@' 'defs' '(' class-name ')'
4514e5dd7070Spatrick ///
ParseStructUnionBody(SourceLocation RecordLoc,DeclSpec::TST TagType,RecordDecl * TagDecl)4515e5dd7070Spatrick void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
4516ec727ea7Spatrick DeclSpec::TST TagType, RecordDecl *TagDecl) {
4517e5dd7070Spatrick PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
4518e5dd7070Spatrick "parsing struct/union body");
4519e5dd7070Spatrick assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
4520e5dd7070Spatrick
4521e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_brace);
4522e5dd7070Spatrick if (T.consumeOpen())
4523e5dd7070Spatrick return;
4524e5dd7070Spatrick
4525e5dd7070Spatrick ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
4526e5dd7070Spatrick Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
4527e5dd7070Spatrick
4528e5dd7070Spatrick // While we still have something to read, read the declarations in the struct.
4529e5dd7070Spatrick while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
4530e5dd7070Spatrick Tok.isNot(tok::eof)) {
4531e5dd7070Spatrick // Each iteration of this loop reads one struct-declaration.
4532e5dd7070Spatrick
4533e5dd7070Spatrick // Check for extraneous top-level semicolon.
4534e5dd7070Spatrick if (Tok.is(tok::semi)) {
4535e5dd7070Spatrick ConsumeExtraSemi(InsideStruct, TagType);
4536e5dd7070Spatrick continue;
4537e5dd7070Spatrick }
4538e5dd7070Spatrick
4539e5dd7070Spatrick // Parse _Static_assert declaration.
4540a9ac8606Spatrick if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) {
4541e5dd7070Spatrick SourceLocation DeclEnd;
4542e5dd7070Spatrick ParseStaticAssertDeclaration(DeclEnd);
4543e5dd7070Spatrick continue;
4544e5dd7070Spatrick }
4545e5dd7070Spatrick
4546e5dd7070Spatrick if (Tok.is(tok::annot_pragma_pack)) {
4547e5dd7070Spatrick HandlePragmaPack();
4548e5dd7070Spatrick continue;
4549e5dd7070Spatrick }
4550e5dd7070Spatrick
4551e5dd7070Spatrick if (Tok.is(tok::annot_pragma_align)) {
4552e5dd7070Spatrick HandlePragmaAlign();
4553e5dd7070Spatrick continue;
4554e5dd7070Spatrick }
4555e5dd7070Spatrick
4556a9ac8606Spatrick if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
4557e5dd7070Spatrick // Result can be ignored, because it must be always empty.
4558e5dd7070Spatrick AccessSpecifier AS = AS_none;
4559*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
4560e5dd7070Spatrick (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
4561e5dd7070Spatrick continue;
4562e5dd7070Spatrick }
4563e5dd7070Spatrick
4564e5dd7070Spatrick if (tok::isPragmaAnnotation(Tok.getKind())) {
4565e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)
4566e5dd7070Spatrick << DeclSpec::getSpecifierName(
4567e5dd7070Spatrick TagType, Actions.getASTContext().getPrintingPolicy());
4568e5dd7070Spatrick ConsumeAnnotationToken();
4569e5dd7070Spatrick continue;
4570e5dd7070Spatrick }
4571e5dd7070Spatrick
4572e5dd7070Spatrick if (!Tok.is(tok::at)) {
4573e5dd7070Spatrick auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
4574e5dd7070Spatrick // Install the declarator into the current TagDecl.
4575e5dd7070Spatrick Decl *Field =
4576e5dd7070Spatrick Actions.ActOnField(getCurScope(), TagDecl,
4577e5dd7070Spatrick FD.D.getDeclSpec().getSourceRange().getBegin(),
4578e5dd7070Spatrick FD.D, FD.BitfieldSize);
4579e5dd7070Spatrick FD.complete(Field);
4580e5dd7070Spatrick };
4581e5dd7070Spatrick
4582e5dd7070Spatrick // Parse all the comma separated declarators.
4583e5dd7070Spatrick ParsingDeclSpec DS(*this);
4584e5dd7070Spatrick ParseStructDeclaration(DS, CFieldCallback);
4585e5dd7070Spatrick } else { // Handle @defs
4586e5dd7070Spatrick ConsumeToken();
4587e5dd7070Spatrick if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
4588e5dd7070Spatrick Diag(Tok, diag::err_unexpected_at);
4589e5dd7070Spatrick SkipUntil(tok::semi);
4590e5dd7070Spatrick continue;
4591e5dd7070Spatrick }
4592e5dd7070Spatrick ConsumeToken();
4593e5dd7070Spatrick ExpectAndConsume(tok::l_paren);
4594e5dd7070Spatrick if (!Tok.is(tok::identifier)) {
4595e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::identifier;
4596e5dd7070Spatrick SkipUntil(tok::semi);
4597e5dd7070Spatrick continue;
4598e5dd7070Spatrick }
4599e5dd7070Spatrick SmallVector<Decl *, 16> Fields;
4600e5dd7070Spatrick Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),
4601e5dd7070Spatrick Tok.getIdentifierInfo(), Fields);
4602e5dd7070Spatrick ConsumeToken();
4603e5dd7070Spatrick ExpectAndConsume(tok::r_paren);
4604e5dd7070Spatrick }
4605e5dd7070Spatrick
4606e5dd7070Spatrick if (TryConsumeToken(tok::semi))
4607e5dd7070Spatrick continue;
4608e5dd7070Spatrick
4609e5dd7070Spatrick if (Tok.is(tok::r_brace)) {
4610e5dd7070Spatrick ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
4611e5dd7070Spatrick break;
4612e5dd7070Spatrick }
4613e5dd7070Spatrick
4614e5dd7070Spatrick ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
4615e5dd7070Spatrick // Skip to end of block or statement to avoid ext-warning on extra ';'.
4616e5dd7070Spatrick SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
4617e5dd7070Spatrick // If we stopped at a ';', eat it.
4618e5dd7070Spatrick TryConsumeToken(tok::semi);
4619e5dd7070Spatrick }
4620e5dd7070Spatrick
4621e5dd7070Spatrick T.consumeClose();
4622e5dd7070Spatrick
4623e5dd7070Spatrick ParsedAttributes attrs(AttrFactory);
4624e5dd7070Spatrick // If attributes exist after struct contents, parse them.
4625e5dd7070Spatrick MaybeParseGNUAttributes(attrs);
4626e5dd7070Spatrick
4627*12c85518Srobert SmallVector<Decl *, 32> FieldDecls(TagDecl->fields());
4628ec727ea7Spatrick
4629e5dd7070Spatrick Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls,
4630e5dd7070Spatrick T.getOpenLocation(), T.getCloseLocation(), attrs);
4631e5dd7070Spatrick StructScope.Exit();
4632e5dd7070Spatrick Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());
4633e5dd7070Spatrick }
4634e5dd7070Spatrick
4635e5dd7070Spatrick /// ParseEnumSpecifier
4636e5dd7070Spatrick /// enum-specifier: [C99 6.7.2.2]
4637e5dd7070Spatrick /// 'enum' identifier[opt] '{' enumerator-list '}'
4638e5dd7070Spatrick ///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'
4639e5dd7070Spatrick /// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
4640e5dd7070Spatrick /// '}' attributes[opt]
4641e5dd7070Spatrick /// [MS] 'enum' __declspec[opt] identifier[opt] '{' enumerator-list ',' [opt]
4642e5dd7070Spatrick /// '}'
4643e5dd7070Spatrick /// 'enum' identifier
4644e5dd7070Spatrick /// [GNU] 'enum' attributes[opt] identifier
4645e5dd7070Spatrick ///
4646e5dd7070Spatrick /// [C++11] enum-head '{' enumerator-list[opt] '}'
4647e5dd7070Spatrick /// [C++11] enum-head '{' enumerator-list ',' '}'
4648e5dd7070Spatrick ///
4649e5dd7070Spatrick /// enum-head: [C++11]
4650e5dd7070Spatrick /// enum-key attribute-specifier-seq[opt] identifier[opt] enum-base[opt]
4651e5dd7070Spatrick /// enum-key attribute-specifier-seq[opt] nested-name-specifier
4652e5dd7070Spatrick /// identifier enum-base[opt]
4653e5dd7070Spatrick ///
4654e5dd7070Spatrick /// enum-key: [C++11]
4655e5dd7070Spatrick /// 'enum'
4656e5dd7070Spatrick /// 'enum' 'class'
4657e5dd7070Spatrick /// 'enum' 'struct'
4658e5dd7070Spatrick ///
4659e5dd7070Spatrick /// enum-base: [C++11]
4660e5dd7070Spatrick /// ':' type-specifier-seq
4661e5dd7070Spatrick ///
4662e5dd7070Spatrick /// [C++] elaborated-type-specifier:
4663ec727ea7Spatrick /// [C++] 'enum' nested-name-specifier[opt] identifier
4664e5dd7070Spatrick ///
ParseEnumSpecifier(SourceLocation StartLoc,DeclSpec & DS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSC)4665e5dd7070Spatrick void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
4666e5dd7070Spatrick const ParsedTemplateInfo &TemplateInfo,
4667e5dd7070Spatrick AccessSpecifier AS, DeclSpecContext DSC) {
4668e5dd7070Spatrick // Parse the tag portion of this.
4669e5dd7070Spatrick if (Tok.is(tok::code_completion)) {
4670e5dd7070Spatrick // Code completion for an enum name.
4671a9ac8606Spatrick cutOffParsing();
4672e5dd7070Spatrick Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);
4673*12c85518Srobert DS.SetTypeSpecError(); // Needed by ActOnUsingDeclaration.
4674a9ac8606Spatrick return;
4675e5dd7070Spatrick }
4676e5dd7070Spatrick
4677e5dd7070Spatrick // If attributes exist after tag, parse them.
4678*12c85518Srobert ParsedAttributes attrs(AttrFactory);
4679a9ac8606Spatrick MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
4680e5dd7070Spatrick
4681e5dd7070Spatrick SourceLocation ScopedEnumKWLoc;
4682e5dd7070Spatrick bool IsScopedUsingClassTag = false;
4683e5dd7070Spatrick
4684e5dd7070Spatrick // In C++11, recognize 'enum class' and 'enum struct'.
4685*12c85518Srobert if (Tok.isOneOf(tok::kw_class, tok::kw_struct) && getLangOpts().CPlusPlus) {
4686e5dd7070Spatrick Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum
4687e5dd7070Spatrick : diag::ext_scoped_enum);
4688e5dd7070Spatrick IsScopedUsingClassTag = Tok.is(tok::kw_class);
4689e5dd7070Spatrick ScopedEnumKWLoc = ConsumeToken();
4690e5dd7070Spatrick
4691e5dd7070Spatrick // Attributes are not allowed between these keywords. Diagnose,
4692e5dd7070Spatrick // but then just treat them like they appeared in the right place.
4693e5dd7070Spatrick ProhibitAttributes(attrs);
4694e5dd7070Spatrick
4695e5dd7070Spatrick // They are allowed afterwards, though.
4696a9ac8606Spatrick MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
4697e5dd7070Spatrick }
4698e5dd7070Spatrick
4699e5dd7070Spatrick // C++11 [temp.explicit]p12:
4700e5dd7070Spatrick // The usual access controls do not apply to names used to specify
4701e5dd7070Spatrick // explicit instantiations.
4702e5dd7070Spatrick // We extend this to also cover explicit specializations. Note that
4703e5dd7070Spatrick // we don't suppress if this turns out to be an elaborated type
4704e5dd7070Spatrick // specifier.
4705e5dd7070Spatrick bool shouldDelayDiagsInTag =
4706e5dd7070Spatrick (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
4707e5dd7070Spatrick TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
4708e5dd7070Spatrick SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
4709e5dd7070Spatrick
4710ec727ea7Spatrick // Determine whether this declaration is permitted to have an enum-base.
4711ec727ea7Spatrick AllowDefiningTypeSpec AllowEnumSpecifier =
4712*12c85518Srobert isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus);
4713ec727ea7Spatrick bool CanBeOpaqueEnumDeclaration =
4714ec727ea7Spatrick DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC);
4715ec727ea7Spatrick bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC ||
4716ec727ea7Spatrick getLangOpts().MicrosoftExt) &&
4717ec727ea7Spatrick (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes ||
4718ec727ea7Spatrick CanBeOpaqueEnumDeclaration);
4719e5dd7070Spatrick
4720e5dd7070Spatrick CXXScopeSpec &SS = DS.getTypeSpecScope();
4721e5dd7070Spatrick if (getLangOpts().CPlusPlus) {
4722ec727ea7Spatrick // "enum foo : bar;" is not a potential typo for "enum foo::bar;".
4723ec727ea7Spatrick ColonProtectionRAIIObject X(*this);
4724e5dd7070Spatrick
4725e5dd7070Spatrick CXXScopeSpec Spec;
4726ec727ea7Spatrick if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,
4727*12c85518Srobert /*ObjectHasErrors=*/false,
4728e5dd7070Spatrick /*EnteringContext=*/true))
4729e5dd7070Spatrick return;
4730e5dd7070Spatrick
4731e5dd7070Spatrick if (Spec.isSet() && Tok.isNot(tok::identifier)) {
4732e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::identifier;
4733*12c85518Srobert DS.SetTypeSpecError();
4734e5dd7070Spatrick if (Tok.isNot(tok::l_brace)) {
4735e5dd7070Spatrick // Has no name and is not a definition.
4736e5dd7070Spatrick // Skip the rest of this declarator, up until the comma or semicolon.
4737e5dd7070Spatrick SkipUntil(tok::comma, StopAtSemi);
4738e5dd7070Spatrick return;
4739e5dd7070Spatrick }
4740e5dd7070Spatrick }
4741e5dd7070Spatrick
4742e5dd7070Spatrick SS = Spec;
4743e5dd7070Spatrick }
4744e5dd7070Spatrick
4745ec727ea7Spatrick // Must have either 'enum name' or 'enum {...}' or (rarely) 'enum : T { ... }'.
4746e5dd7070Spatrick if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
4747ec727ea7Spatrick Tok.isNot(tok::colon)) {
4748e5dd7070Spatrick Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
4749e5dd7070Spatrick
4750*12c85518Srobert DS.SetTypeSpecError();
4751e5dd7070Spatrick // Skip the rest of this declarator, up until the comma or semicolon.
4752e5dd7070Spatrick SkipUntil(tok::comma, StopAtSemi);
4753e5dd7070Spatrick return;
4754e5dd7070Spatrick }
4755e5dd7070Spatrick
4756e5dd7070Spatrick // If an identifier is present, consume and remember it.
4757e5dd7070Spatrick IdentifierInfo *Name = nullptr;
4758e5dd7070Spatrick SourceLocation NameLoc;
4759e5dd7070Spatrick if (Tok.is(tok::identifier)) {
4760e5dd7070Spatrick Name = Tok.getIdentifierInfo();
4761e5dd7070Spatrick NameLoc = ConsumeToken();
4762e5dd7070Spatrick }
4763e5dd7070Spatrick
4764e5dd7070Spatrick if (!Name && ScopedEnumKWLoc.isValid()) {
4765e5dd7070Spatrick // C++0x 7.2p2: The optional identifier shall not be omitted in the
4766e5dd7070Spatrick // declaration of a scoped enumeration.
4767e5dd7070Spatrick Diag(Tok, diag::err_scoped_enum_missing_identifier);
4768e5dd7070Spatrick ScopedEnumKWLoc = SourceLocation();
4769e5dd7070Spatrick IsScopedUsingClassTag = false;
4770e5dd7070Spatrick }
4771e5dd7070Spatrick
4772e5dd7070Spatrick // Okay, end the suppression area. We'll decide whether to emit the
4773e5dd7070Spatrick // diagnostics in a second.
4774e5dd7070Spatrick if (shouldDelayDiagsInTag)
4775e5dd7070Spatrick diagsFromTag.done();
4776e5dd7070Spatrick
4777e5dd7070Spatrick TypeResult BaseType;
4778ec727ea7Spatrick SourceRange BaseRange;
4779ec727ea7Spatrick
4780*12c85518Srobert bool CanBeBitfield =
4781*12c85518Srobert getCurScope()->isClassScope() && ScopedEnumKWLoc.isInvalid() && Name;
4782e5dd7070Spatrick
4783e5dd7070Spatrick // Parse the fixed underlying type.
4784ec727ea7Spatrick if (Tok.is(tok::colon)) {
4785ec727ea7Spatrick // This might be an enum-base or part of some unrelated enclosing context.
4786ec727ea7Spatrick //
4787ec727ea7Spatrick // 'enum E : base' is permitted in two circumstances:
4788ec727ea7Spatrick //
4789ec727ea7Spatrick // 1) As a defining-type-specifier, when followed by '{'.
4790ec727ea7Spatrick // 2) As the sole constituent of a complete declaration -- when DS is empty
4791ec727ea7Spatrick // and the next token is ';'.
4792ec727ea7Spatrick //
4793ec727ea7Spatrick // The restriction to defining-type-specifiers is important to allow parsing
4794ec727ea7Spatrick // a ? new enum E : int{}
4795ec727ea7Spatrick // _Generic(a, enum E : int{})
4796ec727ea7Spatrick // properly.
4797ec727ea7Spatrick //
4798ec727ea7Spatrick // One additional consideration applies:
4799ec727ea7Spatrick //
4800ec727ea7Spatrick // C++ [dcl.enum]p1:
4801ec727ea7Spatrick // A ':' following "enum nested-name-specifier[opt] identifier" within
4802ec727ea7Spatrick // the decl-specifier-seq of a member-declaration is parsed as part of
4803ec727ea7Spatrick // an enum-base.
4804ec727ea7Spatrick //
4805ec727ea7Spatrick // Other language modes supporting enumerations with fixed underlying types
4806ec727ea7Spatrick // do not have clear rules on this, so we disambiguate to determine whether
4807ec727ea7Spatrick // the tokens form a bit-field width or an enum-base.
4808e5dd7070Spatrick
4809ec727ea7Spatrick if (CanBeBitfield && !isEnumBase(CanBeOpaqueEnumDeclaration)) {
4810ec727ea7Spatrick // Outside C++11, do not interpret the tokens as an enum-base if they do
4811ec727ea7Spatrick // not make sense as one. In C++11, it's an error if this happens.
4812ec727ea7Spatrick if (getLangOpts().CPlusPlus11)
4813ec727ea7Spatrick Diag(Tok.getLocation(), diag::err_anonymous_enum_bitfield);
4814ec727ea7Spatrick } else if (CanHaveEnumBase || !ColonIsSacred) {
4815ec727ea7Spatrick SourceLocation ColonLoc = ConsumeToken();
4816e5dd7070Spatrick
4817ec727ea7Spatrick // Parse a type-specifier-seq as a type. We can't just ParseTypeName here,
4818ec727ea7Spatrick // because under -fms-extensions,
4819ec727ea7Spatrick // enum E : int *p;
4820ec727ea7Spatrick // declares 'enum E : int; E *p;' not 'enum E : int*; E p;'.
4821ec727ea7Spatrick DeclSpec DS(AttrFactory);
4822*12c85518Srobert // enum-base is not assumed to be a type and therefore requires the
4823*12c85518Srobert // typename keyword [p0634r3].
4824*12c85518Srobert ParseSpecifierQualifierList(DS, ImplicitTypenameContext::No, AS,
4825*12c85518Srobert DeclSpecContext::DSC_type_specifier);
4826*12c85518Srobert Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
4827*12c85518Srobert DeclaratorContext::TypeName);
4828ec727ea7Spatrick BaseType = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
4829e5dd7070Spatrick
4830ec727ea7Spatrick BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());
4831e5dd7070Spatrick
4832e5dd7070Spatrick if (!getLangOpts().ObjC) {
4833e5dd7070Spatrick if (getLangOpts().CPlusPlus11)
4834ec727ea7Spatrick Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
4835ec727ea7Spatrick << BaseRange;
4836e5dd7070Spatrick else if (getLangOpts().CPlusPlus)
4837ec727ea7Spatrick Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
4838ec727ea7Spatrick << BaseRange;
4839e5dd7070Spatrick else if (getLangOpts().MicrosoftExt)
4840ec727ea7Spatrick Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
4841ec727ea7Spatrick << BaseRange;
4842e5dd7070Spatrick else
4843ec727ea7Spatrick Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)
4844ec727ea7Spatrick << BaseRange;
4845e5dd7070Spatrick }
4846e5dd7070Spatrick }
4847e5dd7070Spatrick }
4848e5dd7070Spatrick
4849e5dd7070Spatrick // There are four options here. If we have 'friend enum foo;' then this is a
4850e5dd7070Spatrick // friend declaration, and cannot have an accompanying definition. If we have
4851e5dd7070Spatrick // 'enum foo;', then this is a forward declaration. If we have
4852e5dd7070Spatrick // 'enum foo {...' then this is a definition. Otherwise we have something
4853e5dd7070Spatrick // like 'enum foo xyz', a reference.
4854e5dd7070Spatrick //
4855e5dd7070Spatrick // This is needed to handle stuff like this right (C99 6.7.2.3p11):
4856e5dd7070Spatrick // enum foo {..}; void bar() { enum foo; } <- new foo in bar.
4857e5dd7070Spatrick // enum foo {..}; void bar() { enum foo x; } <- use of old foo.
4858e5dd7070Spatrick //
4859e5dd7070Spatrick Sema::TagUseKind TUK;
4860ec727ea7Spatrick if (AllowEnumSpecifier == AllowDefiningTypeSpec::No)
4861e5dd7070Spatrick TUK = Sema::TUK_Reference;
4862ec727ea7Spatrick else if (Tok.is(tok::l_brace)) {
4863e5dd7070Spatrick if (DS.isFriendSpecified()) {
4864e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
4865e5dd7070Spatrick << SourceRange(DS.getFriendSpecLoc());
4866e5dd7070Spatrick ConsumeBrace();
4867e5dd7070Spatrick SkipUntil(tok::r_brace, StopAtSemi);
4868ec727ea7Spatrick // Discard any other definition-only pieces.
4869ec727ea7Spatrick attrs.clear();
4870ec727ea7Spatrick ScopedEnumKWLoc = SourceLocation();
4871ec727ea7Spatrick IsScopedUsingClassTag = false;
4872ec727ea7Spatrick BaseType = TypeResult();
4873e5dd7070Spatrick TUK = Sema::TUK_Friend;
4874e5dd7070Spatrick } else {
4875e5dd7070Spatrick TUK = Sema::TUK_Definition;
4876e5dd7070Spatrick }
4877e5dd7070Spatrick } else if (!isTypeSpecifier(DSC) &&
4878e5dd7070Spatrick (Tok.is(tok::semi) ||
4879e5dd7070Spatrick (Tok.isAtStartOfLine() &&
4880e5dd7070Spatrick !isValidAfterTypeSpecifier(CanBeBitfield)))) {
4881ec727ea7Spatrick // An opaque-enum-declaration is required to be standalone (no preceding or
4882ec727ea7Spatrick // following tokens in the declaration). Sema enforces this separately by
4883ec727ea7Spatrick // diagnosing anything else in the DeclSpec.
4884e5dd7070Spatrick TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
4885e5dd7070Spatrick if (Tok.isNot(tok::semi)) {
4886e5dd7070Spatrick // A semicolon was missing after this declaration. Diagnose and recover.
4887e5dd7070Spatrick ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
4888e5dd7070Spatrick PP.EnterToken(Tok, /*IsReinject=*/true);
4889e5dd7070Spatrick Tok.setKind(tok::semi);
4890e5dd7070Spatrick }
4891e5dd7070Spatrick } else {
4892e5dd7070Spatrick TUK = Sema::TUK_Reference;
4893e5dd7070Spatrick }
4894e5dd7070Spatrick
4895ec727ea7Spatrick bool IsElaboratedTypeSpecifier =
4896ec727ea7Spatrick TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend;
4897ec727ea7Spatrick
4898ec727ea7Spatrick // If this is an elaborated type specifier nested in a larger declaration,
4899ec727ea7Spatrick // and we delayed diagnostics before, just merge them into the current pool.
4900e5dd7070Spatrick if (TUK == Sema::TUK_Reference && shouldDelayDiagsInTag) {
4901e5dd7070Spatrick diagsFromTag.redelay();
4902e5dd7070Spatrick }
4903e5dd7070Spatrick
4904e5dd7070Spatrick MultiTemplateParamsArg TParams;
4905e5dd7070Spatrick if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
4906e5dd7070Spatrick TUK != Sema::TUK_Reference) {
4907e5dd7070Spatrick if (!getLangOpts().CPlusPlus11 || !SS.isSet()) {
4908e5dd7070Spatrick // Skip the rest of this declarator, up until the comma or semicolon.
4909e5dd7070Spatrick Diag(Tok, diag::err_enum_template);
4910e5dd7070Spatrick SkipUntil(tok::comma, StopAtSemi);
4911e5dd7070Spatrick return;
4912e5dd7070Spatrick }
4913e5dd7070Spatrick
4914e5dd7070Spatrick if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
4915e5dd7070Spatrick // Enumerations can't be explicitly instantiated.
4916e5dd7070Spatrick DS.SetTypeSpecError();
4917e5dd7070Spatrick Diag(StartLoc, diag::err_explicit_instantiation_enum);
4918e5dd7070Spatrick return;
4919e5dd7070Spatrick }
4920e5dd7070Spatrick
4921e5dd7070Spatrick assert(TemplateInfo.TemplateParams && "no template parameters");
4922e5dd7070Spatrick TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(),
4923e5dd7070Spatrick TemplateInfo.TemplateParams->size());
4924e5dd7070Spatrick }
4925e5dd7070Spatrick
4926e5dd7070Spatrick if (!Name && TUK != Sema::TUK_Definition) {
4927e5dd7070Spatrick Diag(Tok, diag::err_enumerator_unnamed_no_def);
4928e5dd7070Spatrick
4929*12c85518Srobert DS.SetTypeSpecError();
4930e5dd7070Spatrick // Skip the rest of this declarator, up until the comma or semicolon.
4931e5dd7070Spatrick SkipUntil(tok::comma, StopAtSemi);
4932e5dd7070Spatrick return;
4933e5dd7070Spatrick }
4934e5dd7070Spatrick
4935ec727ea7Spatrick // An elaborated-type-specifier has a much more constrained grammar:
4936ec727ea7Spatrick //
4937ec727ea7Spatrick // 'enum' nested-name-specifier[opt] identifier
4938ec727ea7Spatrick //
4939ec727ea7Spatrick // If we parsed any other bits, reject them now.
4940ec727ea7Spatrick //
4941ec727ea7Spatrick // MSVC and (for now at least) Objective-C permit a full enum-specifier
4942ec727ea7Spatrick // or opaque-enum-declaration anywhere.
4943ec727ea7Spatrick if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt &&
4944ec727ea7Spatrick !getLangOpts().ObjC) {
4945a9ac8606Spatrick ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
4946a9ac8606Spatrick /*DiagnoseEmptyAttrs=*/true);
4947ec727ea7Spatrick if (BaseType.isUsable())
4948ec727ea7Spatrick Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier)
4949ec727ea7Spatrick << (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange;
4950ec727ea7Spatrick else if (ScopedEnumKWLoc.isValid())
4951ec727ea7Spatrick Diag(ScopedEnumKWLoc, diag::ext_elaborated_enum_class)
4952ec727ea7Spatrick << FixItHint::CreateRemoval(ScopedEnumKWLoc) << IsScopedUsingClassTag;
4953ec727ea7Spatrick }
4954ec727ea7Spatrick
4955e5dd7070Spatrick stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
4956e5dd7070Spatrick
4957e5dd7070Spatrick Sema::SkipBodyInfo SkipBody;
4958e5dd7070Spatrick if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) &&
4959e5dd7070Spatrick NextToken().is(tok::identifier))
4960e5dd7070Spatrick SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(),
4961e5dd7070Spatrick NextToken().getIdentifierInfo(),
4962e5dd7070Spatrick NextToken().getLocation());
4963e5dd7070Spatrick
4964e5dd7070Spatrick bool Owned = false;
4965e5dd7070Spatrick bool IsDependent = false;
4966e5dd7070Spatrick const char *PrevSpec = nullptr;
4967e5dd7070Spatrick unsigned DiagID;
4968*12c85518Srobert Decl *TagDecl =
4969*12c85518Srobert Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS,
4970*12c85518Srobert Name, NameLoc, attrs, AS, DS.getModulePrivateSpecLoc(),
4971*12c85518Srobert TParams, Owned, IsDependent, ScopedEnumKWLoc,
4972*12c85518Srobert IsScopedUsingClassTag,
4973*12c85518Srobert BaseType, DSC == DeclSpecContext::DSC_type_specifier,
4974e5dd7070Spatrick DSC == DeclSpecContext::DSC_template_param ||
4975e5dd7070Spatrick DSC == DeclSpecContext::DSC_template_type_arg,
4976*12c85518Srobert OffsetOfState, &SkipBody).get();
4977e5dd7070Spatrick
4978e5dd7070Spatrick if (SkipBody.ShouldSkip) {
4979e5dd7070Spatrick assert(TUK == Sema::TUK_Definition && "can only skip a definition");
4980e5dd7070Spatrick
4981e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_brace);
4982e5dd7070Spatrick T.consumeOpen();
4983e5dd7070Spatrick T.skipToEnd();
4984e5dd7070Spatrick
4985e5dd7070Spatrick if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
4986e5dd7070Spatrick NameLoc.isValid() ? NameLoc : StartLoc,
4987e5dd7070Spatrick PrevSpec, DiagID, TagDecl, Owned,
4988e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
4989e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
4990e5dd7070Spatrick return;
4991e5dd7070Spatrick }
4992e5dd7070Spatrick
4993e5dd7070Spatrick if (IsDependent) {
4994e5dd7070Spatrick // This enum has a dependent nested-name-specifier. Handle it as a
4995e5dd7070Spatrick // dependent tag.
4996e5dd7070Spatrick if (!Name) {
4997e5dd7070Spatrick DS.SetTypeSpecError();
4998e5dd7070Spatrick Diag(Tok, diag::err_expected_type_name_after_typename);
4999e5dd7070Spatrick return;
5000e5dd7070Spatrick }
5001e5dd7070Spatrick
5002e5dd7070Spatrick TypeResult Type = Actions.ActOnDependentTag(
5003e5dd7070Spatrick getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc);
5004e5dd7070Spatrick if (Type.isInvalid()) {
5005e5dd7070Spatrick DS.SetTypeSpecError();
5006e5dd7070Spatrick return;
5007e5dd7070Spatrick }
5008e5dd7070Spatrick
5009e5dd7070Spatrick if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
5010e5dd7070Spatrick NameLoc.isValid() ? NameLoc : StartLoc,
5011e5dd7070Spatrick PrevSpec, DiagID, Type.get(),
5012e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
5013e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
5014e5dd7070Spatrick
5015e5dd7070Spatrick return;
5016e5dd7070Spatrick }
5017e5dd7070Spatrick
5018e5dd7070Spatrick if (!TagDecl) {
5019e5dd7070Spatrick // The action failed to produce an enumeration tag. If this is a
5020e5dd7070Spatrick // definition, consume the entire definition.
5021e5dd7070Spatrick if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
5022e5dd7070Spatrick ConsumeBrace();
5023e5dd7070Spatrick SkipUntil(tok::r_brace, StopAtSemi);
5024e5dd7070Spatrick }
5025e5dd7070Spatrick
5026e5dd7070Spatrick DS.SetTypeSpecError();
5027e5dd7070Spatrick return;
5028e5dd7070Spatrick }
5029e5dd7070Spatrick
5030ec727ea7Spatrick if (Tok.is(tok::l_brace) && TUK == Sema::TUK_Definition) {
5031e5dd7070Spatrick Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl;
5032e5dd7070Spatrick ParseEnumBody(StartLoc, D);
5033e5dd7070Spatrick if (SkipBody.CheckSameAsPrevious &&
5034*12c85518Srobert !Actions.ActOnDuplicateDefinition(TagDecl, SkipBody)) {
5035e5dd7070Spatrick DS.SetTypeSpecError();
5036e5dd7070Spatrick return;
5037e5dd7070Spatrick }
5038e5dd7070Spatrick }
5039e5dd7070Spatrick
5040e5dd7070Spatrick if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
5041e5dd7070Spatrick NameLoc.isValid() ? NameLoc : StartLoc,
5042e5dd7070Spatrick PrevSpec, DiagID, TagDecl, Owned,
5043e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
5044e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
5045e5dd7070Spatrick }
5046e5dd7070Spatrick
5047e5dd7070Spatrick /// ParseEnumBody - Parse a {} enclosed enumerator-list.
5048e5dd7070Spatrick /// enumerator-list:
5049e5dd7070Spatrick /// enumerator
5050e5dd7070Spatrick /// enumerator-list ',' enumerator
5051e5dd7070Spatrick /// enumerator:
5052e5dd7070Spatrick /// enumeration-constant attributes[opt]
5053e5dd7070Spatrick /// enumeration-constant attributes[opt] '=' constant-expression
5054e5dd7070Spatrick /// enumeration-constant:
5055e5dd7070Spatrick /// identifier
5056e5dd7070Spatrick ///
ParseEnumBody(SourceLocation StartLoc,Decl * EnumDecl)5057e5dd7070Spatrick void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
5058e5dd7070Spatrick // Enter the scope of the enum body and start the definition.
5059e5dd7070Spatrick ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope);
5060e5dd7070Spatrick Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
5061e5dd7070Spatrick
5062e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_brace);
5063e5dd7070Spatrick T.consumeOpen();
5064e5dd7070Spatrick
5065e5dd7070Spatrick // C does not allow an empty enumerator-list, C++ does [dcl.enum].
5066e5dd7070Spatrick if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)
5067e5dd7070Spatrick Diag(Tok, diag::err_empty_enum);
5068e5dd7070Spatrick
5069e5dd7070Spatrick SmallVector<Decl *, 32> EnumConstantDecls;
5070e5dd7070Spatrick SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
5071e5dd7070Spatrick
5072e5dd7070Spatrick Decl *LastEnumConstDecl = nullptr;
5073e5dd7070Spatrick
5074e5dd7070Spatrick // Parse the enumerator-list.
5075e5dd7070Spatrick while (Tok.isNot(tok::r_brace)) {
5076e5dd7070Spatrick // Parse enumerator. If failed, try skipping till the start of the next
5077e5dd7070Spatrick // enumerator definition.
5078e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
5079e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
5080e5dd7070Spatrick if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&
5081e5dd7070Spatrick TryConsumeToken(tok::comma))
5082e5dd7070Spatrick continue;
5083e5dd7070Spatrick break;
5084e5dd7070Spatrick }
5085e5dd7070Spatrick IdentifierInfo *Ident = Tok.getIdentifierInfo();
5086e5dd7070Spatrick SourceLocation IdentLoc = ConsumeToken();
5087e5dd7070Spatrick
5088e5dd7070Spatrick // If attributes exist after the enumerator, parse them.
5089*12c85518Srobert ParsedAttributes attrs(AttrFactory);
5090e5dd7070Spatrick MaybeParseGNUAttributes(attrs);
5091e5dd7070Spatrick if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
5092e5dd7070Spatrick if (getLangOpts().CPlusPlus)
5093e5dd7070Spatrick Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
5094e5dd7070Spatrick ? diag::warn_cxx14_compat_ns_enum_attribute
5095e5dd7070Spatrick : diag::ext_ns_enum_attribute)
5096e5dd7070Spatrick << 1 /*enumerator*/;
5097e5dd7070Spatrick ParseCXX11Attributes(attrs);
5098e5dd7070Spatrick }
5099e5dd7070Spatrick
5100e5dd7070Spatrick SourceLocation EqualLoc;
5101e5dd7070Spatrick ExprResult AssignedVal;
5102e5dd7070Spatrick EnumAvailabilityDiags.emplace_back(*this);
5103e5dd7070Spatrick
5104e5dd7070Spatrick EnterExpressionEvaluationContext ConstantEvaluated(
5105e5dd7070Spatrick Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
5106e5dd7070Spatrick if (TryConsumeToken(tok::equal, EqualLoc)) {
5107e5dd7070Spatrick AssignedVal = ParseConstantExpressionInExprEvalContext();
5108e5dd7070Spatrick if (AssignedVal.isInvalid())
5109e5dd7070Spatrick SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
5110e5dd7070Spatrick }
5111e5dd7070Spatrick
5112e5dd7070Spatrick // Install the enumerator constant into EnumDecl.
5113e5dd7070Spatrick Decl *EnumConstDecl = Actions.ActOnEnumConstant(
5114e5dd7070Spatrick getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs,
5115e5dd7070Spatrick EqualLoc, AssignedVal.get());
5116e5dd7070Spatrick EnumAvailabilityDiags.back().done();
5117e5dd7070Spatrick
5118e5dd7070Spatrick EnumConstantDecls.push_back(EnumConstDecl);
5119e5dd7070Spatrick LastEnumConstDecl = EnumConstDecl;
5120e5dd7070Spatrick
5121e5dd7070Spatrick if (Tok.is(tok::identifier)) {
5122e5dd7070Spatrick // We're missing a comma between enumerators.
5123e5dd7070Spatrick SourceLocation Loc = getEndOfPreviousToken();
5124e5dd7070Spatrick Diag(Loc, diag::err_enumerator_list_missing_comma)
5125e5dd7070Spatrick << FixItHint::CreateInsertion(Loc, ", ");
5126e5dd7070Spatrick continue;
5127e5dd7070Spatrick }
5128e5dd7070Spatrick
5129e5dd7070Spatrick // Emumerator definition must be finished, only comma or r_brace are
5130e5dd7070Spatrick // allowed here.
5131e5dd7070Spatrick SourceLocation CommaLoc;
5132e5dd7070Spatrick if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {
5133e5dd7070Spatrick if (EqualLoc.isValid())
5134e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace
5135e5dd7070Spatrick << tok::comma;
5136e5dd7070Spatrick else
5137e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);
5138e5dd7070Spatrick if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {
5139e5dd7070Spatrick if (TryConsumeToken(tok::comma, CommaLoc))
5140e5dd7070Spatrick continue;
5141e5dd7070Spatrick } else {
5142e5dd7070Spatrick break;
5143e5dd7070Spatrick }
5144e5dd7070Spatrick }
5145e5dd7070Spatrick
5146e5dd7070Spatrick // If comma is followed by r_brace, emit appropriate warning.
5147e5dd7070Spatrick if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {
5148e5dd7070Spatrick if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
5149e5dd7070Spatrick Diag(CommaLoc, getLangOpts().CPlusPlus ?
5150e5dd7070Spatrick diag::ext_enumerator_list_comma_cxx :
5151e5dd7070Spatrick diag::ext_enumerator_list_comma_c)
5152e5dd7070Spatrick << FixItHint::CreateRemoval(CommaLoc);
5153e5dd7070Spatrick else if (getLangOpts().CPlusPlus11)
5154e5dd7070Spatrick Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
5155e5dd7070Spatrick << FixItHint::CreateRemoval(CommaLoc);
5156e5dd7070Spatrick break;
5157e5dd7070Spatrick }
5158e5dd7070Spatrick }
5159e5dd7070Spatrick
5160e5dd7070Spatrick // Eat the }.
5161e5dd7070Spatrick T.consumeClose();
5162e5dd7070Spatrick
5163e5dd7070Spatrick // If attributes exist after the identifier list, parse them.
5164e5dd7070Spatrick ParsedAttributes attrs(AttrFactory);
5165e5dd7070Spatrick MaybeParseGNUAttributes(attrs);
5166e5dd7070Spatrick
5167e5dd7070Spatrick Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls,
5168e5dd7070Spatrick getCurScope(), attrs);
5169e5dd7070Spatrick
5170e5dd7070Spatrick // Now handle enum constant availability diagnostics.
5171e5dd7070Spatrick assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());
5172e5dd7070Spatrick for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) {
5173e5dd7070Spatrick ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
5174e5dd7070Spatrick EnumAvailabilityDiags[i].redelay();
5175e5dd7070Spatrick PD.complete(EnumConstantDecls[i]);
5176e5dd7070Spatrick }
5177e5dd7070Spatrick
5178e5dd7070Spatrick EnumScope.Exit();
5179e5dd7070Spatrick Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getRange());
5180e5dd7070Spatrick
5181e5dd7070Spatrick // The next token must be valid after an enum definition. If not, a ';'
5182e5dd7070Spatrick // was probably forgotten.
5183*12c85518Srobert bool CanBeBitfield = getCurScope()->isClassScope();
5184e5dd7070Spatrick if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
5185e5dd7070Spatrick ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
5186e5dd7070Spatrick // Push this token back into the preprocessor and change our current token
5187e5dd7070Spatrick // to ';' so that the rest of the code recovers as though there were an
5188e5dd7070Spatrick // ';' after the definition.
5189e5dd7070Spatrick PP.EnterToken(Tok, /*IsReinject=*/true);
5190e5dd7070Spatrick Tok.setKind(tok::semi);
5191e5dd7070Spatrick }
5192e5dd7070Spatrick }
5193e5dd7070Spatrick
5194e5dd7070Spatrick /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
5195e5dd7070Spatrick /// is definitely a type-specifier. Return false if it isn't part of a type
5196e5dd7070Spatrick /// specifier or if we're not sure.
isKnownToBeTypeSpecifier(const Token & Tok) const5197e5dd7070Spatrick bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
5198e5dd7070Spatrick switch (Tok.getKind()) {
5199e5dd7070Spatrick default: return false;
5200e5dd7070Spatrick // type-specifiers
5201e5dd7070Spatrick case tok::kw_short:
5202e5dd7070Spatrick case tok::kw_long:
5203e5dd7070Spatrick case tok::kw___int64:
5204e5dd7070Spatrick case tok::kw___int128:
5205e5dd7070Spatrick case tok::kw_signed:
5206e5dd7070Spatrick case tok::kw_unsigned:
5207e5dd7070Spatrick case tok::kw__Complex:
5208e5dd7070Spatrick case tok::kw__Imaginary:
5209e5dd7070Spatrick case tok::kw_void:
5210e5dd7070Spatrick case tok::kw_char:
5211e5dd7070Spatrick case tok::kw_wchar_t:
5212e5dd7070Spatrick case tok::kw_char8_t:
5213e5dd7070Spatrick case tok::kw_char16_t:
5214e5dd7070Spatrick case tok::kw_char32_t:
5215e5dd7070Spatrick case tok::kw_int:
5216ec727ea7Spatrick case tok::kw__ExtInt:
5217*12c85518Srobert case tok::kw__BitInt:
5218ec727ea7Spatrick case tok::kw___bf16:
5219e5dd7070Spatrick case tok::kw_half:
5220e5dd7070Spatrick case tok::kw_float:
5221e5dd7070Spatrick case tok::kw_double:
5222e5dd7070Spatrick case tok::kw__Accum:
5223e5dd7070Spatrick case tok::kw__Fract:
5224e5dd7070Spatrick case tok::kw__Float16:
5225e5dd7070Spatrick case tok::kw___float128:
5226*12c85518Srobert case tok::kw___ibm128:
5227e5dd7070Spatrick case tok::kw_bool:
5228e5dd7070Spatrick case tok::kw__Bool:
5229e5dd7070Spatrick case tok::kw__Decimal32:
5230e5dd7070Spatrick case tok::kw__Decimal64:
5231e5dd7070Spatrick case tok::kw__Decimal128:
5232e5dd7070Spatrick case tok::kw___vector:
5233e5dd7070Spatrick #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
5234e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
5235e5dd7070Spatrick
5236e5dd7070Spatrick // struct-or-union-specifier (C99) or class-specifier (C++)
5237e5dd7070Spatrick case tok::kw_class:
5238e5dd7070Spatrick case tok::kw_struct:
5239e5dd7070Spatrick case tok::kw___interface:
5240e5dd7070Spatrick case tok::kw_union:
5241e5dd7070Spatrick // enum-specifier
5242e5dd7070Spatrick case tok::kw_enum:
5243e5dd7070Spatrick
5244e5dd7070Spatrick // typedef-name
5245e5dd7070Spatrick case tok::annot_typename:
5246e5dd7070Spatrick return true;
5247e5dd7070Spatrick }
5248e5dd7070Spatrick }
5249e5dd7070Spatrick
5250e5dd7070Spatrick /// isTypeSpecifierQualifier - Return true if the current token could be the
5251e5dd7070Spatrick /// start of a specifier-qualifier-list.
isTypeSpecifierQualifier()5252e5dd7070Spatrick bool Parser::isTypeSpecifierQualifier() {
5253e5dd7070Spatrick switch (Tok.getKind()) {
5254e5dd7070Spatrick default: return false;
5255e5dd7070Spatrick
5256e5dd7070Spatrick case tok::identifier: // foo::bar
5257e5dd7070Spatrick if (TryAltiVecVectorToken())
5258e5dd7070Spatrick return true;
5259*12c85518Srobert [[fallthrough]];
5260e5dd7070Spatrick case tok::kw_typename: // typename T::type
5261e5dd7070Spatrick // Annotate typenames and C++ scope specifiers. If we get one, just
5262e5dd7070Spatrick // recurse to handle whatever we get.
5263e5dd7070Spatrick if (TryAnnotateTypeOrScopeToken())
5264e5dd7070Spatrick return true;
5265e5dd7070Spatrick if (Tok.is(tok::identifier))
5266e5dd7070Spatrick return false;
5267e5dd7070Spatrick return isTypeSpecifierQualifier();
5268e5dd7070Spatrick
5269e5dd7070Spatrick case tok::coloncolon: // ::foo::bar
5270e5dd7070Spatrick if (NextToken().is(tok::kw_new) || // ::new
5271e5dd7070Spatrick NextToken().is(tok::kw_delete)) // ::delete
5272e5dd7070Spatrick return false;
5273e5dd7070Spatrick
5274e5dd7070Spatrick if (TryAnnotateTypeOrScopeToken())
5275e5dd7070Spatrick return true;
5276e5dd7070Spatrick return isTypeSpecifierQualifier();
5277e5dd7070Spatrick
5278e5dd7070Spatrick // GNU attributes support.
5279e5dd7070Spatrick case tok::kw___attribute:
5280*12c85518Srobert // C2x/GNU typeof support.
5281e5dd7070Spatrick case tok::kw_typeof:
5282*12c85518Srobert case tok::kw_typeof_unqual:
5283e5dd7070Spatrick
5284e5dd7070Spatrick // type-specifiers
5285e5dd7070Spatrick case tok::kw_short:
5286e5dd7070Spatrick case tok::kw_long:
5287e5dd7070Spatrick case tok::kw___int64:
5288e5dd7070Spatrick case tok::kw___int128:
5289e5dd7070Spatrick case tok::kw_signed:
5290e5dd7070Spatrick case tok::kw_unsigned:
5291e5dd7070Spatrick case tok::kw__Complex:
5292e5dd7070Spatrick case tok::kw__Imaginary:
5293e5dd7070Spatrick case tok::kw_void:
5294e5dd7070Spatrick case tok::kw_char:
5295e5dd7070Spatrick case tok::kw_wchar_t:
5296e5dd7070Spatrick case tok::kw_char8_t:
5297e5dd7070Spatrick case tok::kw_char16_t:
5298e5dd7070Spatrick case tok::kw_char32_t:
5299e5dd7070Spatrick case tok::kw_int:
5300ec727ea7Spatrick case tok::kw__ExtInt:
5301*12c85518Srobert case tok::kw__BitInt:
5302e5dd7070Spatrick case tok::kw_half:
5303ec727ea7Spatrick case tok::kw___bf16:
5304e5dd7070Spatrick case tok::kw_float:
5305e5dd7070Spatrick case tok::kw_double:
5306e5dd7070Spatrick case tok::kw__Accum:
5307e5dd7070Spatrick case tok::kw__Fract:
5308e5dd7070Spatrick case tok::kw__Float16:
5309e5dd7070Spatrick case tok::kw___float128:
5310*12c85518Srobert case tok::kw___ibm128:
5311e5dd7070Spatrick case tok::kw_bool:
5312e5dd7070Spatrick case tok::kw__Bool:
5313e5dd7070Spatrick case tok::kw__Decimal32:
5314e5dd7070Spatrick case tok::kw__Decimal64:
5315e5dd7070Spatrick case tok::kw__Decimal128:
5316e5dd7070Spatrick case tok::kw___vector:
5317e5dd7070Spatrick #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
5318e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
5319e5dd7070Spatrick
5320e5dd7070Spatrick // struct-or-union-specifier (C99) or class-specifier (C++)
5321e5dd7070Spatrick case tok::kw_class:
5322e5dd7070Spatrick case tok::kw_struct:
5323e5dd7070Spatrick case tok::kw___interface:
5324e5dd7070Spatrick case tok::kw_union:
5325e5dd7070Spatrick // enum-specifier
5326e5dd7070Spatrick case tok::kw_enum:
5327e5dd7070Spatrick
5328e5dd7070Spatrick // type-qualifier
5329e5dd7070Spatrick case tok::kw_const:
5330e5dd7070Spatrick case tok::kw_volatile:
5331e5dd7070Spatrick case tok::kw_restrict:
5332e5dd7070Spatrick case tok::kw__Sat:
5333e5dd7070Spatrick
5334e5dd7070Spatrick // Debugger support.
5335e5dd7070Spatrick case tok::kw___unknown_anytype:
5336e5dd7070Spatrick
5337e5dd7070Spatrick // typedef-name
5338e5dd7070Spatrick case tok::annot_typename:
5339e5dd7070Spatrick return true;
5340e5dd7070Spatrick
5341e5dd7070Spatrick // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
5342e5dd7070Spatrick case tok::less:
5343e5dd7070Spatrick return getLangOpts().ObjC;
5344e5dd7070Spatrick
5345e5dd7070Spatrick case tok::kw___cdecl:
5346e5dd7070Spatrick case tok::kw___stdcall:
5347e5dd7070Spatrick case tok::kw___fastcall:
5348e5dd7070Spatrick case tok::kw___thiscall:
5349e5dd7070Spatrick case tok::kw___regcall:
5350e5dd7070Spatrick case tok::kw___vectorcall:
5351e5dd7070Spatrick case tok::kw___w64:
5352e5dd7070Spatrick case tok::kw___ptr64:
5353e5dd7070Spatrick case tok::kw___ptr32:
5354e5dd7070Spatrick case tok::kw___pascal:
5355e5dd7070Spatrick case tok::kw___unaligned:
5356e5dd7070Spatrick
5357e5dd7070Spatrick case tok::kw__Nonnull:
5358e5dd7070Spatrick case tok::kw__Nullable:
5359a9ac8606Spatrick case tok::kw__Nullable_result:
5360e5dd7070Spatrick case tok::kw__Null_unspecified:
5361e5dd7070Spatrick
5362e5dd7070Spatrick case tok::kw___kindof:
5363e5dd7070Spatrick
5364e5dd7070Spatrick case tok::kw___private:
5365e5dd7070Spatrick case tok::kw___local:
5366e5dd7070Spatrick case tok::kw___global:
5367e5dd7070Spatrick case tok::kw___constant:
5368e5dd7070Spatrick case tok::kw___generic:
5369e5dd7070Spatrick case tok::kw___read_only:
5370e5dd7070Spatrick case tok::kw___read_write:
5371e5dd7070Spatrick case tok::kw___write_only:
5372*12c85518Srobert
5373*12c85518Srobert case tok::kw_groupshared:
5374e5dd7070Spatrick return true;
5375e5dd7070Spatrick
5376e5dd7070Spatrick case tok::kw_private:
5377e5dd7070Spatrick return getLangOpts().OpenCL;
5378e5dd7070Spatrick
5379e5dd7070Spatrick // C11 _Atomic
5380e5dd7070Spatrick case tok::kw__Atomic:
5381e5dd7070Spatrick return true;
5382e5dd7070Spatrick }
5383e5dd7070Spatrick }
5384e5dd7070Spatrick
ParseTopLevelStmtDecl()5385*12c85518Srobert Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
5386*12c85518Srobert assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode");
5387*12c85518Srobert
5388*12c85518Srobert // Parse a top-level-stmt.
5389*12c85518Srobert Parser::StmtVector Stmts;
5390*12c85518Srobert ParsedStmtContext SubStmtCtx = ParsedStmtContext();
5391*12c85518Srobert StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
5392*12c85518Srobert if (!R.isUsable())
5393*12c85518Srobert return nullptr;
5394*12c85518Srobert
5395*12c85518Srobert SmallVector<Decl *, 2> DeclsInGroup;
5396*12c85518Srobert DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
5397*12c85518Srobert // Currently happens for things like -fms-extensions and use `__if_exists`.
5398*12c85518Srobert for (Stmt *S : Stmts)
5399*12c85518Srobert DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
5400*12c85518Srobert
5401*12c85518Srobert return Actions.BuildDeclaratorGroup(DeclsInGroup);
5402*12c85518Srobert }
5403*12c85518Srobert
5404e5dd7070Spatrick /// isDeclarationSpecifier() - Return true if the current token is part of a
5405e5dd7070Spatrick /// declaration specifier.
5406e5dd7070Spatrick ///
5407*12c85518Srobert /// \param AllowImplicitTypename whether this is a context where T::type [T
5408*12c85518Srobert /// dependent] can appear.
5409e5dd7070Spatrick /// \param DisambiguatingWithExpression True to indicate that the purpose of
5410e5dd7070Spatrick /// this check is to disambiguate between an expression and a declaration.
isDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,bool DisambiguatingWithExpression)5411*12c85518Srobert bool Parser::isDeclarationSpecifier(
5412*12c85518Srobert ImplicitTypenameContext AllowImplicitTypename,
5413*12c85518Srobert bool DisambiguatingWithExpression) {
5414e5dd7070Spatrick switch (Tok.getKind()) {
5415e5dd7070Spatrick default: return false;
5416e5dd7070Spatrick
5417a9ac8606Spatrick // OpenCL 2.0 and later define this keyword.
5418e5dd7070Spatrick case tok::kw_pipe:
5419*12c85518Srobert return getLangOpts().OpenCL &&
5420*12c85518Srobert getLangOpts().getOpenCLCompatibleVersion() >= 200;
5421e5dd7070Spatrick
5422e5dd7070Spatrick case tok::identifier: // foo::bar
5423e5dd7070Spatrick // Unfortunate hack to support "Class.factoryMethod" notation.
5424e5dd7070Spatrick if (getLangOpts().ObjC && NextToken().is(tok::period))
5425e5dd7070Spatrick return false;
5426e5dd7070Spatrick if (TryAltiVecVectorToken())
5427e5dd7070Spatrick return true;
5428*12c85518Srobert [[fallthrough]];
5429e5dd7070Spatrick case tok::kw_decltype: // decltype(T())::type
5430e5dd7070Spatrick case tok::kw_typename: // typename T::type
5431e5dd7070Spatrick // Annotate typenames and C++ scope specifiers. If we get one, just
5432e5dd7070Spatrick // recurse to handle whatever we get.
5433*12c85518Srobert if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))
5434e5dd7070Spatrick return true;
5435e5dd7070Spatrick if (TryAnnotateTypeConstraint())
5436e5dd7070Spatrick return true;
5437e5dd7070Spatrick if (Tok.is(tok::identifier))
5438e5dd7070Spatrick return false;
5439e5dd7070Spatrick
5440e5dd7070Spatrick // If we're in Objective-C and we have an Objective-C class type followed
5441e5dd7070Spatrick // by an identifier and then either ':' or ']', in a place where an
5442e5dd7070Spatrick // expression is permitted, then this is probably a class message send
5443e5dd7070Spatrick // missing the initial '['. In this case, we won't consider this to be
5444e5dd7070Spatrick // the start of a declaration.
5445e5dd7070Spatrick if (DisambiguatingWithExpression &&
5446e5dd7070Spatrick isStartOfObjCClassMessageMissingOpenBracket())
5447e5dd7070Spatrick return false;
5448e5dd7070Spatrick
5449*12c85518Srobert return isDeclarationSpecifier(AllowImplicitTypename);
5450e5dd7070Spatrick
5451e5dd7070Spatrick case tok::coloncolon: // ::foo::bar
5452*12c85518Srobert if (!getLangOpts().CPlusPlus)
5453*12c85518Srobert return false;
5454e5dd7070Spatrick if (NextToken().is(tok::kw_new) || // ::new
5455e5dd7070Spatrick NextToken().is(tok::kw_delete)) // ::delete
5456e5dd7070Spatrick return false;
5457e5dd7070Spatrick
5458e5dd7070Spatrick // Annotate typenames and C++ scope specifiers. If we get one, just
5459e5dd7070Spatrick // recurse to handle whatever we get.
5460e5dd7070Spatrick if (TryAnnotateTypeOrScopeToken())
5461e5dd7070Spatrick return true;
5462*12c85518Srobert return isDeclarationSpecifier(ImplicitTypenameContext::No);
5463e5dd7070Spatrick
5464e5dd7070Spatrick // storage-class-specifier
5465e5dd7070Spatrick case tok::kw_typedef:
5466e5dd7070Spatrick case tok::kw_extern:
5467e5dd7070Spatrick case tok::kw___private_extern__:
5468e5dd7070Spatrick case tok::kw_static:
5469e5dd7070Spatrick case tok::kw_auto:
5470e5dd7070Spatrick case tok::kw___auto_type:
5471e5dd7070Spatrick case tok::kw_register:
5472e5dd7070Spatrick case tok::kw___thread:
5473e5dd7070Spatrick case tok::kw_thread_local:
5474e5dd7070Spatrick case tok::kw__Thread_local:
5475e5dd7070Spatrick
5476e5dd7070Spatrick // Modules
5477e5dd7070Spatrick case tok::kw___module_private__:
5478e5dd7070Spatrick
5479e5dd7070Spatrick // Debugger support
5480e5dd7070Spatrick case tok::kw___unknown_anytype:
5481e5dd7070Spatrick
5482e5dd7070Spatrick // type-specifiers
5483e5dd7070Spatrick case tok::kw_short:
5484e5dd7070Spatrick case tok::kw_long:
5485e5dd7070Spatrick case tok::kw___int64:
5486e5dd7070Spatrick case tok::kw___int128:
5487e5dd7070Spatrick case tok::kw_signed:
5488e5dd7070Spatrick case tok::kw_unsigned:
5489e5dd7070Spatrick case tok::kw__Complex:
5490e5dd7070Spatrick case tok::kw__Imaginary:
5491e5dd7070Spatrick case tok::kw_void:
5492e5dd7070Spatrick case tok::kw_char:
5493e5dd7070Spatrick case tok::kw_wchar_t:
5494e5dd7070Spatrick case tok::kw_char8_t:
5495e5dd7070Spatrick case tok::kw_char16_t:
5496e5dd7070Spatrick case tok::kw_char32_t:
5497e5dd7070Spatrick
5498e5dd7070Spatrick case tok::kw_int:
5499ec727ea7Spatrick case tok::kw__ExtInt:
5500*12c85518Srobert case tok::kw__BitInt:
5501e5dd7070Spatrick case tok::kw_half:
5502ec727ea7Spatrick case tok::kw___bf16:
5503e5dd7070Spatrick case tok::kw_float:
5504e5dd7070Spatrick case tok::kw_double:
5505e5dd7070Spatrick case tok::kw__Accum:
5506e5dd7070Spatrick case tok::kw__Fract:
5507e5dd7070Spatrick case tok::kw__Float16:
5508e5dd7070Spatrick case tok::kw___float128:
5509*12c85518Srobert case tok::kw___ibm128:
5510e5dd7070Spatrick case tok::kw_bool:
5511e5dd7070Spatrick case tok::kw__Bool:
5512e5dd7070Spatrick case tok::kw__Decimal32:
5513e5dd7070Spatrick case tok::kw__Decimal64:
5514e5dd7070Spatrick case tok::kw__Decimal128:
5515e5dd7070Spatrick case tok::kw___vector:
5516e5dd7070Spatrick
5517e5dd7070Spatrick // struct-or-union-specifier (C99) or class-specifier (C++)
5518e5dd7070Spatrick case tok::kw_class:
5519e5dd7070Spatrick case tok::kw_struct:
5520e5dd7070Spatrick case tok::kw_union:
5521e5dd7070Spatrick case tok::kw___interface:
5522e5dd7070Spatrick // enum-specifier
5523e5dd7070Spatrick case tok::kw_enum:
5524e5dd7070Spatrick
5525e5dd7070Spatrick // type-qualifier
5526e5dd7070Spatrick case tok::kw_const:
5527e5dd7070Spatrick case tok::kw_volatile:
5528e5dd7070Spatrick case tok::kw_restrict:
5529e5dd7070Spatrick case tok::kw__Sat:
5530e5dd7070Spatrick
5531e5dd7070Spatrick // function-specifier
5532e5dd7070Spatrick case tok::kw_inline:
5533e5dd7070Spatrick case tok::kw_virtual:
5534e5dd7070Spatrick case tok::kw_explicit:
5535e5dd7070Spatrick case tok::kw__Noreturn:
5536e5dd7070Spatrick
5537e5dd7070Spatrick // alignment-specifier
5538e5dd7070Spatrick case tok::kw__Alignas:
5539e5dd7070Spatrick
5540e5dd7070Spatrick // friend keyword.
5541e5dd7070Spatrick case tok::kw_friend:
5542e5dd7070Spatrick
5543e5dd7070Spatrick // static_assert-declaration
5544a9ac8606Spatrick case tok::kw_static_assert:
5545e5dd7070Spatrick case tok::kw__Static_assert:
5546e5dd7070Spatrick
5547*12c85518Srobert // C2x/GNU typeof support.
5548e5dd7070Spatrick case tok::kw_typeof:
5549*12c85518Srobert case tok::kw_typeof_unqual:
5550e5dd7070Spatrick
5551e5dd7070Spatrick // GNU attributes.
5552e5dd7070Spatrick case tok::kw___attribute:
5553e5dd7070Spatrick
5554e5dd7070Spatrick // C++11 decltype and constexpr.
5555e5dd7070Spatrick case tok::annot_decltype:
5556e5dd7070Spatrick case tok::kw_constexpr:
5557e5dd7070Spatrick
5558e5dd7070Spatrick // C++20 consteval and constinit.
5559e5dd7070Spatrick case tok::kw_consteval:
5560e5dd7070Spatrick case tok::kw_constinit:
5561e5dd7070Spatrick
5562e5dd7070Spatrick // C11 _Atomic
5563e5dd7070Spatrick case tok::kw__Atomic:
5564e5dd7070Spatrick return true;
5565e5dd7070Spatrick
5566e5dd7070Spatrick // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
5567e5dd7070Spatrick case tok::less:
5568e5dd7070Spatrick return getLangOpts().ObjC;
5569e5dd7070Spatrick
5570e5dd7070Spatrick // typedef-name
5571e5dd7070Spatrick case tok::annot_typename:
5572e5dd7070Spatrick return !DisambiguatingWithExpression ||
5573e5dd7070Spatrick !isStartOfObjCClassMessageMissingOpenBracket();
5574e5dd7070Spatrick
5575e5dd7070Spatrick // placeholder-type-specifier
5576e5dd7070Spatrick case tok::annot_template_id: {
5577ec727ea7Spatrick TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
5578ec727ea7Spatrick if (TemplateId->hasInvalidName())
5579ec727ea7Spatrick return true;
5580ec727ea7Spatrick // FIXME: What about type templates that have only been annotated as
5581ec727ea7Spatrick // annot_template_id, not as annot_typename?
5582e5dd7070Spatrick return isTypeConstraintAnnotation() &&
5583e5dd7070Spatrick (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));
5584e5dd7070Spatrick }
5585ec727ea7Spatrick
5586ec727ea7Spatrick case tok::annot_cxxscope: {
5587ec727ea7Spatrick TemplateIdAnnotation *TemplateId =
5588ec727ea7Spatrick NextToken().is(tok::annot_template_id)
5589ec727ea7Spatrick ? takeTemplateIdAnnotation(NextToken())
5590ec727ea7Spatrick : nullptr;
5591ec727ea7Spatrick if (TemplateId && TemplateId->hasInvalidName())
5592ec727ea7Spatrick return true;
5593ec727ea7Spatrick // FIXME: What about type templates that have only been annotated as
5594ec727ea7Spatrick // annot_template_id, not as annot_typename?
5595e5dd7070Spatrick if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())
5596e5dd7070Spatrick return true;
5597e5dd7070Spatrick return isTypeConstraintAnnotation() &&
5598e5dd7070Spatrick GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);
5599ec727ea7Spatrick }
5600ec727ea7Spatrick
5601e5dd7070Spatrick case tok::kw___declspec:
5602e5dd7070Spatrick case tok::kw___cdecl:
5603e5dd7070Spatrick case tok::kw___stdcall:
5604e5dd7070Spatrick case tok::kw___fastcall:
5605e5dd7070Spatrick case tok::kw___thiscall:
5606e5dd7070Spatrick case tok::kw___regcall:
5607e5dd7070Spatrick case tok::kw___vectorcall:
5608e5dd7070Spatrick case tok::kw___w64:
5609e5dd7070Spatrick case tok::kw___sptr:
5610e5dd7070Spatrick case tok::kw___uptr:
5611e5dd7070Spatrick case tok::kw___ptr64:
5612e5dd7070Spatrick case tok::kw___ptr32:
5613e5dd7070Spatrick case tok::kw___forceinline:
5614e5dd7070Spatrick case tok::kw___pascal:
5615e5dd7070Spatrick case tok::kw___unaligned:
5616e5dd7070Spatrick
5617e5dd7070Spatrick case tok::kw__Nonnull:
5618e5dd7070Spatrick case tok::kw__Nullable:
5619a9ac8606Spatrick case tok::kw__Nullable_result:
5620e5dd7070Spatrick case tok::kw__Null_unspecified:
5621e5dd7070Spatrick
5622e5dd7070Spatrick case tok::kw___kindof:
5623e5dd7070Spatrick
5624e5dd7070Spatrick case tok::kw___private:
5625e5dd7070Spatrick case tok::kw___local:
5626e5dd7070Spatrick case tok::kw___global:
5627e5dd7070Spatrick case tok::kw___constant:
5628e5dd7070Spatrick case tok::kw___generic:
5629e5dd7070Spatrick case tok::kw___read_only:
5630e5dd7070Spatrick case tok::kw___read_write:
5631e5dd7070Spatrick case tok::kw___write_only:
5632e5dd7070Spatrick #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
5633e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
5634e5dd7070Spatrick
5635*12c85518Srobert case tok::kw_groupshared:
5636e5dd7070Spatrick return true;
5637e5dd7070Spatrick
5638e5dd7070Spatrick case tok::kw_private:
5639e5dd7070Spatrick return getLangOpts().OpenCL;
5640e5dd7070Spatrick }
5641e5dd7070Spatrick }
5642e5dd7070Spatrick
isConstructorDeclarator(bool IsUnqualified,bool DeductionGuide,DeclSpec::FriendSpecified IsFriend)5643*12c85518Srobert bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide,
5644*12c85518Srobert DeclSpec::FriendSpecified IsFriend) {
5645e5dd7070Spatrick TentativeParsingAction TPA(*this);
5646e5dd7070Spatrick
5647e5dd7070Spatrick // Parse the C++ scope specifier.
5648e5dd7070Spatrick CXXScopeSpec SS;
5649ec727ea7Spatrick if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
5650*12c85518Srobert /*ObjectHasErrors=*/false,
5651e5dd7070Spatrick /*EnteringContext=*/true)) {
5652e5dd7070Spatrick TPA.Revert();
5653e5dd7070Spatrick return false;
5654e5dd7070Spatrick }
5655e5dd7070Spatrick
5656e5dd7070Spatrick // Parse the constructor name.
5657e5dd7070Spatrick if (Tok.is(tok::identifier)) {
5658e5dd7070Spatrick // We already know that we have a constructor name; just consume
5659e5dd7070Spatrick // the token.
5660e5dd7070Spatrick ConsumeToken();
5661e5dd7070Spatrick } else if (Tok.is(tok::annot_template_id)) {
5662e5dd7070Spatrick ConsumeAnnotationToken();
5663e5dd7070Spatrick } else {
5664e5dd7070Spatrick TPA.Revert();
5665e5dd7070Spatrick return false;
5666e5dd7070Spatrick }
5667e5dd7070Spatrick
5668e5dd7070Spatrick // There may be attributes here, appertaining to the constructor name or type
5669e5dd7070Spatrick // we just stepped past.
5670e5dd7070Spatrick SkipCXX11Attributes();
5671e5dd7070Spatrick
5672e5dd7070Spatrick // Current class name must be followed by a left parenthesis.
5673e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
5674e5dd7070Spatrick TPA.Revert();
5675e5dd7070Spatrick return false;
5676e5dd7070Spatrick }
5677e5dd7070Spatrick ConsumeParen();
5678e5dd7070Spatrick
5679e5dd7070Spatrick // A right parenthesis, or ellipsis followed by a right parenthesis signals
5680e5dd7070Spatrick // that we have a constructor.
5681e5dd7070Spatrick if (Tok.is(tok::r_paren) ||
5682e5dd7070Spatrick (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) {
5683e5dd7070Spatrick TPA.Revert();
5684e5dd7070Spatrick return true;
5685e5dd7070Spatrick }
5686e5dd7070Spatrick
5687e5dd7070Spatrick // A C++11 attribute here signals that we have a constructor, and is an
5688e5dd7070Spatrick // attribute on the first constructor parameter.
5689e5dd7070Spatrick if (getLangOpts().CPlusPlus11 &&
5690e5dd7070Spatrick isCXX11AttributeSpecifier(/*Disambiguate*/ false,
5691e5dd7070Spatrick /*OuterMightBeMessageSend*/ true)) {
5692e5dd7070Spatrick TPA.Revert();
5693e5dd7070Spatrick return true;
5694e5dd7070Spatrick }
5695e5dd7070Spatrick
5696e5dd7070Spatrick // If we need to, enter the specified scope.
5697e5dd7070Spatrick DeclaratorScopeObj DeclScopeObj(*this, SS);
5698e5dd7070Spatrick if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
5699e5dd7070Spatrick DeclScopeObj.EnterDeclaratorScope();
5700e5dd7070Spatrick
5701e5dd7070Spatrick // Optionally skip Microsoft attributes.
5702e5dd7070Spatrick ParsedAttributes Attrs(AttrFactory);
5703e5dd7070Spatrick MaybeParseMicrosoftAttributes(Attrs);
5704e5dd7070Spatrick
5705e5dd7070Spatrick // Check whether the next token(s) are part of a declaration
5706e5dd7070Spatrick // specifier, in which case we have the start of a parameter and,
5707e5dd7070Spatrick // therefore, we know that this is a constructor.
5708*12c85518Srobert // Due to an ambiguity with implicit typename, the above is not enough.
5709*12c85518Srobert // Additionally, check to see if we are a friend.
5710e5dd7070Spatrick bool IsConstructor = false;
5711*12c85518Srobert if (isDeclarationSpecifier(IsFriend ? ImplicitTypenameContext::No
5712*12c85518Srobert : ImplicitTypenameContext::Yes))
5713e5dd7070Spatrick IsConstructor = true;
5714e5dd7070Spatrick else if (Tok.is(tok::identifier) ||
5715e5dd7070Spatrick (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) {
5716e5dd7070Spatrick // We've seen "C ( X" or "C ( X::Y", but "X" / "X::Y" is not a type.
5717e5dd7070Spatrick // This might be a parenthesized member name, but is more likely to
5718e5dd7070Spatrick // be a constructor declaration with an invalid argument type. Keep
5719e5dd7070Spatrick // looking.
5720e5dd7070Spatrick if (Tok.is(tok::annot_cxxscope))
5721e5dd7070Spatrick ConsumeAnnotationToken();
5722e5dd7070Spatrick ConsumeToken();
5723e5dd7070Spatrick
5724e5dd7070Spatrick // If this is not a constructor, we must be parsing a declarator,
5725e5dd7070Spatrick // which must have one of the following syntactic forms (see the
5726e5dd7070Spatrick // grammar extract at the start of ParseDirectDeclarator):
5727e5dd7070Spatrick switch (Tok.getKind()) {
5728e5dd7070Spatrick case tok::l_paren:
5729e5dd7070Spatrick // C(X ( int));
5730e5dd7070Spatrick case tok::l_square:
5731e5dd7070Spatrick // C(X [ 5]);
5732e5dd7070Spatrick // C(X [ [attribute]]);
5733e5dd7070Spatrick case tok::coloncolon:
5734e5dd7070Spatrick // C(X :: Y);
5735e5dd7070Spatrick // C(X :: *p);
5736e5dd7070Spatrick // Assume this isn't a constructor, rather than assuming it's a
5737e5dd7070Spatrick // constructor with an unnamed parameter of an ill-formed type.
5738e5dd7070Spatrick break;
5739e5dd7070Spatrick
5740e5dd7070Spatrick case tok::r_paren:
5741e5dd7070Spatrick // C(X )
5742e5dd7070Spatrick
5743e5dd7070Spatrick // Skip past the right-paren and any following attributes to get to
5744e5dd7070Spatrick // the function body or trailing-return-type.
5745e5dd7070Spatrick ConsumeParen();
5746e5dd7070Spatrick SkipCXX11Attributes();
5747e5dd7070Spatrick
5748e5dd7070Spatrick if (DeductionGuide) {
5749e5dd7070Spatrick // C(X) -> ... is a deduction guide.
5750e5dd7070Spatrick IsConstructor = Tok.is(tok::arrow);
5751e5dd7070Spatrick break;
5752e5dd7070Spatrick }
5753e5dd7070Spatrick if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
5754e5dd7070Spatrick // Assume these were meant to be constructors:
5755e5dd7070Spatrick // C(X) : (the name of a bit-field cannot be parenthesized).
5756e5dd7070Spatrick // C(X) try (this is otherwise ill-formed).
5757e5dd7070Spatrick IsConstructor = true;
5758e5dd7070Spatrick }
5759e5dd7070Spatrick if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) {
5760e5dd7070Spatrick // If we have a constructor name within the class definition,
5761e5dd7070Spatrick // assume these were meant to be constructors:
5762e5dd7070Spatrick // C(X) {
5763e5dd7070Spatrick // C(X) ;
5764e5dd7070Spatrick // ... because otherwise we would be declaring a non-static data
5765e5dd7070Spatrick // member that is ill-formed because it's of the same type as its
5766e5dd7070Spatrick // surrounding class.
5767e5dd7070Spatrick //
5768e5dd7070Spatrick // FIXME: We can actually do this whether or not the name is qualified,
5769e5dd7070Spatrick // because if it is qualified in this context it must be being used as
5770e5dd7070Spatrick // a constructor name.
5771e5dd7070Spatrick // currently, so we're somewhat conservative here.
5772e5dd7070Spatrick IsConstructor = IsUnqualified;
5773e5dd7070Spatrick }
5774e5dd7070Spatrick break;
5775e5dd7070Spatrick
5776e5dd7070Spatrick default:
5777e5dd7070Spatrick IsConstructor = true;
5778e5dd7070Spatrick break;
5779e5dd7070Spatrick }
5780e5dd7070Spatrick }
5781e5dd7070Spatrick
5782e5dd7070Spatrick TPA.Revert();
5783e5dd7070Spatrick return IsConstructor;
5784e5dd7070Spatrick }
5785e5dd7070Spatrick
5786e5dd7070Spatrick /// ParseTypeQualifierListOpt
5787e5dd7070Spatrick /// type-qualifier-list: [C99 6.7.5]
5788e5dd7070Spatrick /// type-qualifier
5789e5dd7070Spatrick /// [vendor] attributes
5790e5dd7070Spatrick /// [ only if AttrReqs & AR_VendorAttributesParsed ]
5791e5dd7070Spatrick /// type-qualifier-list type-qualifier
5792e5dd7070Spatrick /// [vendor] type-qualifier-list attributes
5793e5dd7070Spatrick /// [ only if AttrReqs & AR_VendorAttributesParsed ]
5794e5dd7070Spatrick /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
5795e5dd7070Spatrick /// [ only if AttReqs & AR_CXX11AttributesParsed ]
5796e5dd7070Spatrick /// Note: vendor can be GNU, MS, etc and can be explicitly controlled via
5797e5dd7070Spatrick /// AttrRequirements bitmask values.
ParseTypeQualifierListOpt(DeclSpec & DS,unsigned AttrReqs,bool AtomicAllowed,bool IdentifierRequired,std::optional<llvm::function_ref<void ()>> CodeCompletionHandler)5798e5dd7070Spatrick void Parser::ParseTypeQualifierListOpt(
5799e5dd7070Spatrick DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
5800e5dd7070Spatrick bool IdentifierRequired,
5801*12c85518Srobert std::optional<llvm::function_ref<void()>> CodeCompletionHandler) {
5802e5dd7070Spatrick if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) &&
5803e5dd7070Spatrick isCXX11AttributeSpecifier()) {
5804*12c85518Srobert ParsedAttributes Attrs(AttrFactory);
5805*12c85518Srobert ParseCXX11Attributes(Attrs);
5806*12c85518Srobert DS.takeAttributesFrom(Attrs);
5807e5dd7070Spatrick }
5808e5dd7070Spatrick
5809e5dd7070Spatrick SourceLocation EndLoc;
5810e5dd7070Spatrick
5811*12c85518Srobert while (true) {
5812e5dd7070Spatrick bool isInvalid = false;
5813e5dd7070Spatrick const char *PrevSpec = nullptr;
5814e5dd7070Spatrick unsigned DiagID = 0;
5815e5dd7070Spatrick SourceLocation Loc = Tok.getLocation();
5816e5dd7070Spatrick
5817e5dd7070Spatrick switch (Tok.getKind()) {
5818e5dd7070Spatrick case tok::code_completion:
5819a9ac8606Spatrick cutOffParsing();
5820e5dd7070Spatrick if (CodeCompletionHandler)
5821e5dd7070Spatrick (*CodeCompletionHandler)();
5822e5dd7070Spatrick else
5823e5dd7070Spatrick Actions.CodeCompleteTypeQualifiers(DS);
5824a9ac8606Spatrick return;
5825e5dd7070Spatrick
5826e5dd7070Spatrick case tok::kw_const:
5827e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
5828e5dd7070Spatrick getLangOpts());
5829e5dd7070Spatrick break;
5830e5dd7070Spatrick case tok::kw_volatile:
5831e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
5832e5dd7070Spatrick getLangOpts());
5833e5dd7070Spatrick break;
5834e5dd7070Spatrick case tok::kw_restrict:
5835e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
5836e5dd7070Spatrick getLangOpts());
5837e5dd7070Spatrick break;
5838e5dd7070Spatrick case tok::kw__Atomic:
5839e5dd7070Spatrick if (!AtomicAllowed)
5840e5dd7070Spatrick goto DoneWithTypeQuals;
5841e5dd7070Spatrick if (!getLangOpts().C11)
5842e5dd7070Spatrick Diag(Tok, diag::ext_c11_feature) << Tok.getName();
5843e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
5844e5dd7070Spatrick getLangOpts());
5845e5dd7070Spatrick break;
5846e5dd7070Spatrick
5847e5dd7070Spatrick // OpenCL qualifiers:
5848e5dd7070Spatrick case tok::kw_private:
5849e5dd7070Spatrick if (!getLangOpts().OpenCL)
5850e5dd7070Spatrick goto DoneWithTypeQuals;
5851*12c85518Srobert [[fallthrough]];
5852e5dd7070Spatrick case tok::kw___private:
5853e5dd7070Spatrick case tok::kw___global:
5854e5dd7070Spatrick case tok::kw___local:
5855e5dd7070Spatrick case tok::kw___constant:
5856e5dd7070Spatrick case tok::kw___generic:
5857e5dd7070Spatrick case tok::kw___read_only:
5858e5dd7070Spatrick case tok::kw___write_only:
5859e5dd7070Spatrick case tok::kw___read_write:
5860e5dd7070Spatrick ParseOpenCLQualifiers(DS.getAttributes());
5861e5dd7070Spatrick break;
5862e5dd7070Spatrick
5863*12c85518Srobert case tok::kw_groupshared:
5864*12c85518Srobert // NOTE: ParseHLSLQualifiers will consume the qualifier token.
5865*12c85518Srobert ParseHLSLQualifiers(DS.getAttributes());
5866*12c85518Srobert continue;
5867*12c85518Srobert
5868e5dd7070Spatrick case tok::kw___unaligned:
5869e5dd7070Spatrick isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,
5870e5dd7070Spatrick getLangOpts());
5871e5dd7070Spatrick break;
5872e5dd7070Spatrick case tok::kw___uptr:
5873e5dd7070Spatrick // GNU libc headers in C mode use '__uptr' as an identifier which conflicts
5874e5dd7070Spatrick // with the MS modifier keyword.
5875e5dd7070Spatrick if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus &&
5876e5dd7070Spatrick IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) {
5877e5dd7070Spatrick if (TryKeywordIdentFallback(false))
5878e5dd7070Spatrick continue;
5879e5dd7070Spatrick }
5880*12c85518Srobert [[fallthrough]];
5881e5dd7070Spatrick case tok::kw___sptr:
5882e5dd7070Spatrick case tok::kw___w64:
5883e5dd7070Spatrick case tok::kw___ptr64:
5884e5dd7070Spatrick case tok::kw___ptr32:
5885e5dd7070Spatrick case tok::kw___cdecl:
5886e5dd7070Spatrick case tok::kw___stdcall:
5887e5dd7070Spatrick case tok::kw___fastcall:
5888e5dd7070Spatrick case tok::kw___thiscall:
5889e5dd7070Spatrick case tok::kw___regcall:
5890e5dd7070Spatrick case tok::kw___vectorcall:
5891e5dd7070Spatrick if (AttrReqs & AR_DeclspecAttributesParsed) {
5892e5dd7070Spatrick ParseMicrosoftTypeAttributes(DS.getAttributes());
5893e5dd7070Spatrick continue;
5894e5dd7070Spatrick }
5895e5dd7070Spatrick goto DoneWithTypeQuals;
5896e5dd7070Spatrick case tok::kw___pascal:
5897e5dd7070Spatrick if (AttrReqs & AR_VendorAttributesParsed) {
5898e5dd7070Spatrick ParseBorlandTypeAttributes(DS.getAttributes());
5899e5dd7070Spatrick continue;
5900e5dd7070Spatrick }
5901e5dd7070Spatrick goto DoneWithTypeQuals;
5902e5dd7070Spatrick
5903e5dd7070Spatrick // Nullability type specifiers.
5904e5dd7070Spatrick case tok::kw__Nonnull:
5905e5dd7070Spatrick case tok::kw__Nullable:
5906a9ac8606Spatrick case tok::kw__Nullable_result:
5907e5dd7070Spatrick case tok::kw__Null_unspecified:
5908e5dd7070Spatrick ParseNullabilityTypeSpecifiers(DS.getAttributes());
5909e5dd7070Spatrick continue;
5910e5dd7070Spatrick
5911e5dd7070Spatrick // Objective-C 'kindof' types.
5912e5dd7070Spatrick case tok::kw___kindof:
5913e5dd7070Spatrick DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
5914e5dd7070Spatrick nullptr, 0, ParsedAttr::AS_Keyword);
5915e5dd7070Spatrick (void)ConsumeToken();
5916e5dd7070Spatrick continue;
5917e5dd7070Spatrick
5918e5dd7070Spatrick case tok::kw___attribute:
5919e5dd7070Spatrick if (AttrReqs & AR_GNUAttributesParsedAndRejected)
5920e5dd7070Spatrick // When GNU attributes are expressly forbidden, diagnose their usage.
5921e5dd7070Spatrick Diag(Tok, diag::err_attributes_not_allowed);
5922e5dd7070Spatrick
5923e5dd7070Spatrick // Parse the attributes even if they are rejected to ensure that error
5924e5dd7070Spatrick // recovery is graceful.
5925e5dd7070Spatrick if (AttrReqs & AR_GNUAttributesParsed ||
5926e5dd7070Spatrick AttrReqs & AR_GNUAttributesParsedAndRejected) {
5927e5dd7070Spatrick ParseGNUAttributes(DS.getAttributes());
5928e5dd7070Spatrick continue; // do *not* consume the next token!
5929e5dd7070Spatrick }
5930e5dd7070Spatrick // otherwise, FALL THROUGH!
5931*12c85518Srobert [[fallthrough]];
5932e5dd7070Spatrick default:
5933e5dd7070Spatrick DoneWithTypeQuals:
5934e5dd7070Spatrick // If this is not a type-qualifier token, we're done reading type
5935e5dd7070Spatrick // qualifiers. First verify that DeclSpec's are consistent.
5936e5dd7070Spatrick DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
5937e5dd7070Spatrick if (EndLoc.isValid())
5938e5dd7070Spatrick DS.SetRangeEnd(EndLoc);
5939e5dd7070Spatrick return;
5940e5dd7070Spatrick }
5941e5dd7070Spatrick
5942e5dd7070Spatrick // If the specifier combination wasn't legal, issue a diagnostic.
5943e5dd7070Spatrick if (isInvalid) {
5944e5dd7070Spatrick assert(PrevSpec && "Method did not return previous specifier!");
5945e5dd7070Spatrick Diag(Tok, DiagID) << PrevSpec;
5946e5dd7070Spatrick }
5947e5dd7070Spatrick EndLoc = ConsumeToken();
5948e5dd7070Spatrick }
5949e5dd7070Spatrick }
5950e5dd7070Spatrick
5951e5dd7070Spatrick /// ParseDeclarator - Parse and verify a newly-initialized declarator.
ParseDeclarator(Declarator & D)5952e5dd7070Spatrick void Parser::ParseDeclarator(Declarator &D) {
5953e5dd7070Spatrick /// This implements the 'declarator' production in the C grammar, then checks
5954e5dd7070Spatrick /// for well-formedness and issues diagnostics.
5955*12c85518Srobert Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {
5956e5dd7070Spatrick ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
5957*12c85518Srobert });
5958e5dd7070Spatrick }
5959e5dd7070Spatrick
isPtrOperatorToken(tok::TokenKind Kind,const LangOptions & Lang,DeclaratorContext TheContext)5960e5dd7070Spatrick static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
5961e5dd7070Spatrick DeclaratorContext TheContext) {
5962e5dd7070Spatrick if (Kind == tok::star || Kind == tok::caret)
5963e5dd7070Spatrick return true;
5964e5dd7070Spatrick
5965a9ac8606Spatrick // OpenCL 2.0 and later define this keyword.
5966*12c85518Srobert if (Kind == tok::kw_pipe && Lang.OpenCL &&
5967*12c85518Srobert Lang.getOpenCLCompatibleVersion() >= 200)
5968e5dd7070Spatrick return true;
5969e5dd7070Spatrick
5970e5dd7070Spatrick if (!Lang.CPlusPlus)
5971e5dd7070Spatrick return false;
5972e5dd7070Spatrick
5973e5dd7070Spatrick if (Kind == tok::amp)
5974e5dd7070Spatrick return true;
5975e5dd7070Spatrick
5976e5dd7070Spatrick // We parse rvalue refs in C++03, because otherwise the errors are scary.
5977e5dd7070Spatrick // But we must not parse them in conversion-type-ids and new-type-ids, since
5978e5dd7070Spatrick // those can be legitimately followed by a && operator.
5979e5dd7070Spatrick // (The same thing can in theory happen after a trailing-return-type, but
5980e5dd7070Spatrick // since those are a C++11 feature, there is no rejects-valid issue there.)
5981e5dd7070Spatrick if (Kind == tok::ampamp)
5982a9ac8606Spatrick return Lang.CPlusPlus11 || (TheContext != DeclaratorContext::ConversionId &&
5983a9ac8606Spatrick TheContext != DeclaratorContext::CXXNew);
5984e5dd7070Spatrick
5985e5dd7070Spatrick return false;
5986e5dd7070Spatrick }
5987e5dd7070Spatrick
5988e5dd7070Spatrick // Indicates whether the given declarator is a pipe declarator.
isPipeDeclarator(const Declarator & D)5989*12c85518Srobert static bool isPipeDeclarator(const Declarator &D) {
5990e5dd7070Spatrick const unsigned NumTypes = D.getNumTypeObjects();
5991e5dd7070Spatrick
5992e5dd7070Spatrick for (unsigned Idx = 0; Idx != NumTypes; ++Idx)
5993e5dd7070Spatrick if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)
5994e5dd7070Spatrick return true;
5995e5dd7070Spatrick
5996e5dd7070Spatrick return false;
5997e5dd7070Spatrick }
5998e5dd7070Spatrick
5999e5dd7070Spatrick /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
6000e5dd7070Spatrick /// is parsed by the function passed to it. Pass null, and the direct-declarator
6001e5dd7070Spatrick /// isn't parsed at all, making this function effectively parse the C++
6002e5dd7070Spatrick /// ptr-operator production.
6003e5dd7070Spatrick ///
6004e5dd7070Spatrick /// If the grammar of this construct is extended, matching changes must also be
6005e5dd7070Spatrick /// made to TryParseDeclarator and MightBeDeclarator, and possibly to
6006e5dd7070Spatrick /// isConstructorDeclarator.
6007e5dd7070Spatrick ///
6008e5dd7070Spatrick /// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]
6009e5dd7070Spatrick /// [C] pointer[opt] direct-declarator
6010e5dd7070Spatrick /// [C++] direct-declarator
6011e5dd7070Spatrick /// [C++] ptr-operator declarator
6012e5dd7070Spatrick ///
6013e5dd7070Spatrick /// pointer: [C99 6.7.5]
6014e5dd7070Spatrick /// '*' type-qualifier-list[opt]
6015e5dd7070Spatrick /// '*' type-qualifier-list[opt] pointer
6016e5dd7070Spatrick ///
6017e5dd7070Spatrick /// ptr-operator:
6018e5dd7070Spatrick /// '*' cv-qualifier-seq[opt]
6019e5dd7070Spatrick /// '&'
6020e5dd7070Spatrick /// [C++0x] '&&'
6021e5dd7070Spatrick /// [GNU] '&' restrict[opt] attributes[opt]
6022e5dd7070Spatrick /// [GNU?] '&&' restrict[opt] attributes[opt]
6023e5dd7070Spatrick /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
ParseDeclaratorInternal(Declarator & D,DirectDeclParseFunction DirectDeclParser)6024e5dd7070Spatrick void Parser::ParseDeclaratorInternal(Declarator &D,
6025e5dd7070Spatrick DirectDeclParseFunction DirectDeclParser) {
6026e5dd7070Spatrick if (Diags.hasAllExtensionsSilenced())
6027e5dd7070Spatrick D.setExtension();
6028e5dd7070Spatrick
6029e5dd7070Spatrick // C++ member pointers start with a '::' or a nested-name.
6030e5dd7070Spatrick // Member pointers get special handling, since there's no place for the
6031e5dd7070Spatrick // scope spec in the generic path below.
6032e5dd7070Spatrick if (getLangOpts().CPlusPlus &&
6033e5dd7070Spatrick (Tok.is(tok::coloncolon) || Tok.is(tok::kw_decltype) ||
6034e5dd7070Spatrick (Tok.is(tok::identifier) &&
6035e5dd7070Spatrick (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
6036e5dd7070Spatrick Tok.is(tok::annot_cxxscope))) {
6037a9ac8606Spatrick bool EnteringContext = D.getContext() == DeclaratorContext::File ||
6038a9ac8606Spatrick D.getContext() == DeclaratorContext::Member;
6039e5dd7070Spatrick CXXScopeSpec SS;
6040ec727ea7Spatrick ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
6041*12c85518Srobert /*ObjectHasErrors=*/false, EnteringContext);
6042e5dd7070Spatrick
6043e5dd7070Spatrick if (SS.isNotEmpty()) {
6044e5dd7070Spatrick if (Tok.isNot(tok::star)) {
6045e5dd7070Spatrick // The scope spec really belongs to the direct-declarator.
6046e5dd7070Spatrick if (D.mayHaveIdentifier())
6047e5dd7070Spatrick D.getCXXScopeSpec() = SS;
6048e5dd7070Spatrick else
6049e5dd7070Spatrick AnnotateScopeToken(SS, true);
6050e5dd7070Spatrick
6051e5dd7070Spatrick if (DirectDeclParser)
6052e5dd7070Spatrick (this->*DirectDeclParser)(D);
6053e5dd7070Spatrick return;
6054e5dd7070Spatrick }
6055e5dd7070Spatrick
6056a9ac8606Spatrick if (SS.isValid()) {
6057a9ac8606Spatrick checkCompoundToken(SS.getEndLoc(), tok::coloncolon,
6058a9ac8606Spatrick CompoundToken::MemberPtr);
6059a9ac8606Spatrick }
6060a9ac8606Spatrick
6061ec727ea7Spatrick SourceLocation StarLoc = ConsumeToken();
6062ec727ea7Spatrick D.SetRangeEnd(StarLoc);
6063e5dd7070Spatrick DeclSpec DS(AttrFactory);
6064e5dd7070Spatrick ParseTypeQualifierListOpt(DS);
6065e5dd7070Spatrick D.ExtendWithDeclSpec(DS);
6066e5dd7070Spatrick
6067e5dd7070Spatrick // Recurse to parse whatever is left.
6068*12c85518Srobert Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {
6069e5dd7070Spatrick ParseDeclaratorInternal(D, DirectDeclParser);
6070*12c85518Srobert });
6071e5dd7070Spatrick
6072e5dd7070Spatrick // Sema will have to catch (syntactically invalid) pointers into global
6073e5dd7070Spatrick // scope. It has to catch pointers into namespace scope anyway.
6074e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
6075ec727ea7Spatrick SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()),
6076e5dd7070Spatrick std::move(DS.getAttributes()),
6077e5dd7070Spatrick /* Don't replace range end. */ SourceLocation());
6078e5dd7070Spatrick return;
6079e5dd7070Spatrick }
6080e5dd7070Spatrick }
6081e5dd7070Spatrick
6082e5dd7070Spatrick tok::TokenKind Kind = Tok.getKind();
6083e5dd7070Spatrick
6084*12c85518Srobert if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclarator(D)) {
6085e5dd7070Spatrick DeclSpec DS(AttrFactory);
6086e5dd7070Spatrick ParseTypeQualifierListOpt(DS);
6087e5dd7070Spatrick
6088e5dd7070Spatrick D.AddTypeInfo(
6089e5dd7070Spatrick DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
6090e5dd7070Spatrick std::move(DS.getAttributes()), SourceLocation());
6091e5dd7070Spatrick }
6092e5dd7070Spatrick
6093e5dd7070Spatrick // Not a pointer, C++ reference, or block.
6094e5dd7070Spatrick if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {
6095e5dd7070Spatrick if (DirectDeclParser)
6096e5dd7070Spatrick (this->*DirectDeclParser)(D);
6097e5dd7070Spatrick return;
6098e5dd7070Spatrick }
6099e5dd7070Spatrick
6100e5dd7070Spatrick // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,
6101e5dd7070Spatrick // '&&' -> rvalue reference
6102e5dd7070Spatrick SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&.
6103e5dd7070Spatrick D.SetRangeEnd(Loc);
6104e5dd7070Spatrick
6105e5dd7070Spatrick if (Kind == tok::star || Kind == tok::caret) {
6106e5dd7070Spatrick // Is a pointer.
6107e5dd7070Spatrick DeclSpec DS(AttrFactory);
6108e5dd7070Spatrick
6109e5dd7070Spatrick // GNU attributes are not allowed here in a new-type-id, but Declspec and
6110e5dd7070Spatrick // C++11 attributes are allowed.
6111e5dd7070Spatrick unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |
6112a9ac8606Spatrick ((D.getContext() != DeclaratorContext::CXXNew)
6113e5dd7070Spatrick ? AR_GNUAttributesParsed
6114e5dd7070Spatrick : AR_GNUAttributesParsedAndRejected);
6115e5dd7070Spatrick ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());
6116e5dd7070Spatrick D.ExtendWithDeclSpec(DS);
6117e5dd7070Spatrick
6118e5dd7070Spatrick // Recursively parse the declarator.
6119*12c85518Srobert Actions.runWithSufficientStackSpace(
6120*12c85518Srobert D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });
6121e5dd7070Spatrick if (Kind == tok::star)
6122e5dd7070Spatrick // Remember that we parsed a pointer type, and remember the type-quals.
6123e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getPointer(
6124e5dd7070Spatrick DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(),
6125e5dd7070Spatrick DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(),
6126e5dd7070Spatrick DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()),
6127e5dd7070Spatrick std::move(DS.getAttributes()), SourceLocation());
6128e5dd7070Spatrick else
6129e5dd7070Spatrick // Remember that we parsed a Block type, and remember the type-quals.
6130e5dd7070Spatrick D.AddTypeInfo(
6131e5dd7070Spatrick DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc),
6132e5dd7070Spatrick std::move(DS.getAttributes()), SourceLocation());
6133e5dd7070Spatrick } else {
6134e5dd7070Spatrick // Is a reference
6135e5dd7070Spatrick DeclSpec DS(AttrFactory);
6136e5dd7070Spatrick
6137e5dd7070Spatrick // Complain about rvalue references in C++03, but then go on and build
6138e5dd7070Spatrick // the declarator.
6139e5dd7070Spatrick if (Kind == tok::ampamp)
6140e5dd7070Spatrick Diag(Loc, getLangOpts().CPlusPlus11 ?
6141e5dd7070Spatrick diag::warn_cxx98_compat_rvalue_reference :
6142e5dd7070Spatrick diag::ext_rvalue_reference);
6143e5dd7070Spatrick
6144e5dd7070Spatrick // GNU-style and C++11 attributes are allowed here, as is restrict.
6145e5dd7070Spatrick ParseTypeQualifierListOpt(DS);
6146e5dd7070Spatrick D.ExtendWithDeclSpec(DS);
6147e5dd7070Spatrick
6148e5dd7070Spatrick // C++ 8.3.2p1: cv-qualified references are ill-formed except when the
6149e5dd7070Spatrick // cv-qualifiers are introduced through the use of a typedef or of a
6150e5dd7070Spatrick // template type argument, in which case the cv-qualifiers are ignored.
6151e5dd7070Spatrick if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
6152e5dd7070Spatrick if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
6153e5dd7070Spatrick Diag(DS.getConstSpecLoc(),
6154e5dd7070Spatrick diag::err_invalid_reference_qualifier_application) << "const";
6155e5dd7070Spatrick if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
6156e5dd7070Spatrick Diag(DS.getVolatileSpecLoc(),
6157e5dd7070Spatrick diag::err_invalid_reference_qualifier_application) << "volatile";
6158e5dd7070Spatrick // 'restrict' is permitted as an extension.
6159e5dd7070Spatrick if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
6160e5dd7070Spatrick Diag(DS.getAtomicSpecLoc(),
6161e5dd7070Spatrick diag::err_invalid_reference_qualifier_application) << "_Atomic";
6162e5dd7070Spatrick }
6163e5dd7070Spatrick
6164e5dd7070Spatrick // Recursively parse the declarator.
6165*12c85518Srobert Actions.runWithSufficientStackSpace(
6166*12c85518Srobert D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });
6167e5dd7070Spatrick
6168e5dd7070Spatrick if (D.getNumTypeObjects() > 0) {
6169e5dd7070Spatrick // C++ [dcl.ref]p4: There shall be no references to references.
6170e5dd7070Spatrick DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);
6171e5dd7070Spatrick if (InnerChunk.Kind == DeclaratorChunk::Reference) {
6172e5dd7070Spatrick if (const IdentifierInfo *II = D.getIdentifier())
6173e5dd7070Spatrick Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
6174e5dd7070Spatrick << II;
6175e5dd7070Spatrick else
6176e5dd7070Spatrick Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
6177e5dd7070Spatrick << "type name";
6178e5dd7070Spatrick
6179e5dd7070Spatrick // Once we've complained about the reference-to-reference, we
6180e5dd7070Spatrick // can go ahead and build the (technically ill-formed)
6181e5dd7070Spatrick // declarator: reference collapsing will take care of it.
6182e5dd7070Spatrick }
6183e5dd7070Spatrick }
6184e5dd7070Spatrick
6185e5dd7070Spatrick // Remember that we parsed a reference type.
6186e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
6187e5dd7070Spatrick Kind == tok::amp),
6188e5dd7070Spatrick std::move(DS.getAttributes()), SourceLocation());
6189e5dd7070Spatrick }
6190e5dd7070Spatrick }
6191e5dd7070Spatrick
6192e5dd7070Spatrick // When correcting from misplaced brackets before the identifier, the location
6193e5dd7070Spatrick // is saved inside the declarator so that other diagnostic messages can use
6194e5dd7070Spatrick // them. This extracts and returns that location, or returns the provided
6195e5dd7070Spatrick // location if a stored location does not exist.
getMissingDeclaratorIdLoc(Declarator & D,SourceLocation Loc)6196e5dd7070Spatrick static SourceLocation getMissingDeclaratorIdLoc(Declarator &D,
6197e5dd7070Spatrick SourceLocation Loc) {
6198e5dd7070Spatrick if (D.getName().StartLocation.isInvalid() &&
6199e5dd7070Spatrick D.getName().EndLocation.isValid())
6200e5dd7070Spatrick return D.getName().EndLocation;
6201e5dd7070Spatrick
6202e5dd7070Spatrick return Loc;
6203e5dd7070Spatrick }
6204e5dd7070Spatrick
6205e5dd7070Spatrick /// ParseDirectDeclarator
6206e5dd7070Spatrick /// direct-declarator: [C99 6.7.5]
6207e5dd7070Spatrick /// [C99] identifier
6208e5dd7070Spatrick /// '(' declarator ')'
6209e5dd7070Spatrick /// [GNU] '(' attributes declarator ')'
6210e5dd7070Spatrick /// [C90] direct-declarator '[' constant-expression[opt] ']'
6211e5dd7070Spatrick /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
6212e5dd7070Spatrick /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
6213e5dd7070Spatrick /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
6214e5dd7070Spatrick /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
6215e5dd7070Spatrick /// [C++11] direct-declarator '[' constant-expression[opt] ']'
6216e5dd7070Spatrick /// attribute-specifier-seq[opt]
6217e5dd7070Spatrick /// direct-declarator '(' parameter-type-list ')'
6218e5dd7070Spatrick /// direct-declarator '(' identifier-list[opt] ')'
6219e5dd7070Spatrick /// [GNU] direct-declarator '(' parameter-forward-declarations
6220e5dd7070Spatrick /// parameter-type-list[opt] ')'
6221e5dd7070Spatrick /// [C++] direct-declarator '(' parameter-declaration-clause ')'
6222e5dd7070Spatrick /// cv-qualifier-seq[opt] exception-specification[opt]
6223e5dd7070Spatrick /// [C++11] direct-declarator '(' parameter-declaration-clause ')'
6224e5dd7070Spatrick /// attribute-specifier-seq[opt] cv-qualifier-seq[opt]
6225e5dd7070Spatrick /// ref-qualifier[opt] exception-specification[opt]
6226e5dd7070Spatrick /// [C++] declarator-id
6227e5dd7070Spatrick /// [C++11] declarator-id attribute-specifier-seq[opt]
6228e5dd7070Spatrick ///
6229e5dd7070Spatrick /// declarator-id: [C++ 8]
6230e5dd7070Spatrick /// '...'[opt] id-expression
6231e5dd7070Spatrick /// '::'[opt] nested-name-specifier[opt] type-name
6232e5dd7070Spatrick ///
6233e5dd7070Spatrick /// id-expression: [C++ 5.1]
6234e5dd7070Spatrick /// unqualified-id
6235e5dd7070Spatrick /// qualified-id
6236e5dd7070Spatrick ///
6237e5dd7070Spatrick /// unqualified-id: [C++ 5.1]
6238e5dd7070Spatrick /// identifier
6239e5dd7070Spatrick /// operator-function-id
6240e5dd7070Spatrick /// conversion-function-id
6241e5dd7070Spatrick /// '~' class-name
6242e5dd7070Spatrick /// template-id
6243e5dd7070Spatrick ///
6244e5dd7070Spatrick /// C++17 adds the following, which we also handle here:
6245e5dd7070Spatrick ///
6246e5dd7070Spatrick /// simple-declaration:
6247e5dd7070Spatrick /// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';'
6248e5dd7070Spatrick ///
6249e5dd7070Spatrick /// Note, any additional constructs added here may need corresponding changes
6250e5dd7070Spatrick /// in isConstructorDeclarator.
ParseDirectDeclarator(Declarator & D)6251e5dd7070Spatrick void Parser::ParseDirectDeclarator(Declarator &D) {
6252e5dd7070Spatrick DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
6253e5dd7070Spatrick
6254e5dd7070Spatrick if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
6255e5dd7070Spatrick // This might be a C++17 structured binding.
6256e5dd7070Spatrick if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() &&
6257e5dd7070Spatrick D.getCXXScopeSpec().isEmpty())
6258e5dd7070Spatrick return ParseDecompositionDeclarator(D);
6259e5dd7070Spatrick
6260e5dd7070Spatrick // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
6261e5dd7070Spatrick // this context it is a bitfield. Also in range-based for statement colon
6262e5dd7070Spatrick // may delimit for-range-declaration.
6263e5dd7070Spatrick ColonProtectionRAIIObject X(
6264a9ac8606Spatrick *this, D.getContext() == DeclaratorContext::Member ||
6265a9ac8606Spatrick (D.getContext() == DeclaratorContext::ForInit &&
6266e5dd7070Spatrick getLangOpts().CPlusPlus11));
6267e5dd7070Spatrick
6268e5dd7070Spatrick // ParseDeclaratorInternal might already have parsed the scope.
6269e5dd7070Spatrick if (D.getCXXScopeSpec().isEmpty()) {
6270a9ac8606Spatrick bool EnteringContext = D.getContext() == DeclaratorContext::File ||
6271a9ac8606Spatrick D.getContext() == DeclaratorContext::Member;
6272ec727ea7Spatrick ParseOptionalCXXScopeSpecifier(
6273ec727ea7Spatrick D.getCXXScopeSpec(), /*ObjectType=*/nullptr,
6274*12c85518Srobert /*ObjectHasErrors=*/false, EnteringContext);
6275e5dd7070Spatrick }
6276e5dd7070Spatrick
6277e5dd7070Spatrick if (D.getCXXScopeSpec().isValid()) {
6278e5dd7070Spatrick if (Actions.ShouldEnterDeclaratorScope(getCurScope(),
6279e5dd7070Spatrick D.getCXXScopeSpec()))
6280e5dd7070Spatrick // Change the declaration context for name lookup, until this function
6281e5dd7070Spatrick // is exited (and the declarator has been parsed).
6282e5dd7070Spatrick DeclScopeObj.EnterDeclaratorScope();
6283e5dd7070Spatrick else if (getObjCDeclContext()) {
6284e5dd7070Spatrick // Ensure that we don't interpret the next token as an identifier when
6285e5dd7070Spatrick // dealing with declarations in an Objective-C container.
6286e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6287e5dd7070Spatrick D.setInvalidType(true);
6288e5dd7070Spatrick ConsumeToken();
6289e5dd7070Spatrick goto PastIdentifier;
6290e5dd7070Spatrick }
6291e5dd7070Spatrick }
6292e5dd7070Spatrick
6293e5dd7070Spatrick // C++0x [dcl.fct]p14:
6294e5dd7070Spatrick // There is a syntactic ambiguity when an ellipsis occurs at the end of a
6295e5dd7070Spatrick // parameter-declaration-clause without a preceding comma. In this case,
6296e5dd7070Spatrick // the ellipsis is parsed as part of the abstract-declarator if the type
6297e5dd7070Spatrick // of the parameter either names a template parameter pack that has not
6298e5dd7070Spatrick // been expanded or contains auto; otherwise, it is parsed as part of the
6299e5dd7070Spatrick // parameter-declaration-clause.
6300e5dd7070Spatrick if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
6301a9ac8606Spatrick !((D.getContext() == DeclaratorContext::Prototype ||
6302a9ac8606Spatrick D.getContext() == DeclaratorContext::LambdaExprParameter ||
6303a9ac8606Spatrick D.getContext() == DeclaratorContext::BlockLiteral) &&
6304a9ac8606Spatrick NextToken().is(tok::r_paren) && !D.hasGroupingParens() &&
6305e5dd7070Spatrick !Actions.containsUnexpandedParameterPacks(D) &&
6306e5dd7070Spatrick D.getDeclSpec().getTypeSpecType() != TST_auto)) {
6307e5dd7070Spatrick SourceLocation EllipsisLoc = ConsumeToken();
6308e5dd7070Spatrick if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) {
6309e5dd7070Spatrick // The ellipsis was put in the wrong place. Recover, and explain to
6310e5dd7070Spatrick // the user what they should have done.
6311e5dd7070Spatrick ParseDeclarator(D);
6312e5dd7070Spatrick if (EllipsisLoc.isValid())
6313e5dd7070Spatrick DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
6314e5dd7070Spatrick return;
6315e5dd7070Spatrick } else
6316e5dd7070Spatrick D.setEllipsisLoc(EllipsisLoc);
6317e5dd7070Spatrick
6318e5dd7070Spatrick // The ellipsis can't be followed by a parenthesized declarator. We
6319e5dd7070Spatrick // check for that in ParseParenDeclarator, after we have disambiguated
6320e5dd7070Spatrick // the l_paren token.
6321e5dd7070Spatrick }
6322e5dd7070Spatrick
6323e5dd7070Spatrick if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
6324e5dd7070Spatrick tok::tilde)) {
6325e5dd7070Spatrick // We found something that indicates the start of an unqualified-id.
6326e5dd7070Spatrick // Parse that unqualified-id.
6327e5dd7070Spatrick bool AllowConstructorName;
6328e5dd7070Spatrick bool AllowDeductionGuide;
6329e5dd7070Spatrick if (D.getDeclSpec().hasTypeSpecifier()) {
6330e5dd7070Spatrick AllowConstructorName = false;
6331e5dd7070Spatrick AllowDeductionGuide = false;
6332e5dd7070Spatrick } else if (D.getCXXScopeSpec().isSet()) {
6333a9ac8606Spatrick AllowConstructorName = (D.getContext() == DeclaratorContext::File ||
6334a9ac8606Spatrick D.getContext() == DeclaratorContext::Member);
6335e5dd7070Spatrick AllowDeductionGuide = false;
6336e5dd7070Spatrick } else {
6337a9ac8606Spatrick AllowConstructorName = (D.getContext() == DeclaratorContext::Member);
6338a9ac8606Spatrick AllowDeductionGuide = (D.getContext() == DeclaratorContext::File ||
6339a9ac8606Spatrick D.getContext() == DeclaratorContext::Member);
6340e5dd7070Spatrick }
6341e5dd7070Spatrick
6342e5dd7070Spatrick bool HadScope = D.getCXXScopeSpec().isValid();
6343e5dd7070Spatrick if (ParseUnqualifiedId(D.getCXXScopeSpec(),
6344ec727ea7Spatrick /*ObjectType=*/nullptr,
6345ec727ea7Spatrick /*ObjectHadErrors=*/false,
6346e5dd7070Spatrick /*EnteringContext=*/true,
6347e5dd7070Spatrick /*AllowDestructorName=*/true, AllowConstructorName,
6348ec727ea7Spatrick AllowDeductionGuide, nullptr, D.getName()) ||
6349e5dd7070Spatrick // Once we're past the identifier, if the scope was bad, mark the
6350e5dd7070Spatrick // whole declarator bad.
6351e5dd7070Spatrick D.getCXXScopeSpec().isInvalid()) {
6352e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6353e5dd7070Spatrick D.setInvalidType(true);
6354e5dd7070Spatrick } else {
6355e5dd7070Spatrick // ParseUnqualifiedId might have parsed a scope specifier during error
6356e5dd7070Spatrick // recovery. If it did so, enter that scope.
6357e5dd7070Spatrick if (!HadScope && D.getCXXScopeSpec().isValid() &&
6358e5dd7070Spatrick Actions.ShouldEnterDeclaratorScope(getCurScope(),
6359e5dd7070Spatrick D.getCXXScopeSpec()))
6360e5dd7070Spatrick DeclScopeObj.EnterDeclaratorScope();
6361e5dd7070Spatrick
6362e5dd7070Spatrick // Parsed the unqualified-id; update range information and move along.
6363e5dd7070Spatrick if (D.getSourceRange().getBegin().isInvalid())
6364e5dd7070Spatrick D.SetRangeBegin(D.getName().getSourceRange().getBegin());
6365e5dd7070Spatrick D.SetRangeEnd(D.getName().getSourceRange().getEnd());
6366e5dd7070Spatrick }
6367e5dd7070Spatrick goto PastIdentifier;
6368e5dd7070Spatrick }
6369e5dd7070Spatrick
6370e5dd7070Spatrick if (D.getCXXScopeSpec().isNotEmpty()) {
6371e5dd7070Spatrick // We have a scope specifier but no following unqualified-id.
6372e5dd7070Spatrick Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()),
6373e5dd7070Spatrick diag::err_expected_unqualified_id)
6374e5dd7070Spatrick << /*C++*/1;
6375e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6376e5dd7070Spatrick goto PastIdentifier;
6377e5dd7070Spatrick }
6378e5dd7070Spatrick } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
6379e5dd7070Spatrick assert(!getLangOpts().CPlusPlus &&
6380e5dd7070Spatrick "There's a C++-specific check for tok::identifier above");
6381e5dd7070Spatrick assert(Tok.getIdentifierInfo() && "Not an identifier?");
6382e5dd7070Spatrick D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
6383e5dd7070Spatrick D.SetRangeEnd(Tok.getLocation());
6384e5dd7070Spatrick ConsumeToken();
6385e5dd7070Spatrick goto PastIdentifier;
6386e5dd7070Spatrick } else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) {
6387e5dd7070Spatrick // We're not allowed an identifier here, but we got one. Try to figure out
6388e5dd7070Spatrick // if the user was trying to attach a name to the type, or whether the name
6389e5dd7070Spatrick // is some unrelated trailing syntax.
6390e5dd7070Spatrick bool DiagnoseIdentifier = false;
6391e5dd7070Spatrick if (D.hasGroupingParens())
6392e5dd7070Spatrick // An identifier within parens is unlikely to be intended to be anything
6393e5dd7070Spatrick // other than a name being "declared".
6394e5dd7070Spatrick DiagnoseIdentifier = true;
6395a9ac8606Spatrick else if (D.getContext() == DeclaratorContext::TemplateArg)
6396e5dd7070Spatrick // T<int N> is an accidental identifier; T<int N indicates a missing '>'.
6397e5dd7070Spatrick DiagnoseIdentifier =
6398e5dd7070Spatrick NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
6399a9ac8606Spatrick else if (D.getContext() == DeclaratorContext::AliasDecl ||
6400a9ac8606Spatrick D.getContext() == DeclaratorContext::AliasTemplate)
6401e5dd7070Spatrick // The most likely error is that the ';' was forgotten.
6402e5dd7070Spatrick DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
6403a9ac8606Spatrick else if ((D.getContext() == DeclaratorContext::TrailingReturn ||
6404a9ac8606Spatrick D.getContext() == DeclaratorContext::TrailingReturnVar) &&
6405e5dd7070Spatrick !isCXX11VirtSpecifier(Tok))
6406e5dd7070Spatrick DiagnoseIdentifier = NextToken().isOneOf(
6407e5dd7070Spatrick tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
6408e5dd7070Spatrick if (DiagnoseIdentifier) {
6409e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
6410e5dd7070Spatrick << FixItHint::CreateRemoval(Tok.getLocation());
6411e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6412e5dd7070Spatrick ConsumeToken();
6413e5dd7070Spatrick goto PastIdentifier;
6414e5dd7070Spatrick }
6415e5dd7070Spatrick }
6416e5dd7070Spatrick
6417e5dd7070Spatrick if (Tok.is(tok::l_paren)) {
6418e5dd7070Spatrick // If this might be an abstract-declarator followed by a direct-initializer,
6419e5dd7070Spatrick // check whether this is a valid declarator chunk. If it can't be, assume
6420e5dd7070Spatrick // that it's an initializer instead.
6421e5dd7070Spatrick if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
6422e5dd7070Spatrick RevertingTentativeParsingAction PA(*this);
6423e5dd7070Spatrick if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) ==
6424e5dd7070Spatrick TPResult::False) {
6425e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6426e5dd7070Spatrick goto PastIdentifier;
6427e5dd7070Spatrick }
6428e5dd7070Spatrick }
6429e5dd7070Spatrick
6430e5dd7070Spatrick // direct-declarator: '(' declarator ')'
6431e5dd7070Spatrick // direct-declarator: '(' attributes declarator ')'
6432e5dd7070Spatrick // Example: 'char (*X)' or 'int (*XX)(void)'
6433e5dd7070Spatrick ParseParenDeclarator(D);
6434e5dd7070Spatrick
6435e5dd7070Spatrick // If the declarator was parenthesized, we entered the declarator
6436e5dd7070Spatrick // scope when parsing the parenthesized declarator, then exited
6437e5dd7070Spatrick // the scope already. Re-enter the scope, if we need to.
6438e5dd7070Spatrick if (D.getCXXScopeSpec().isSet()) {
6439e5dd7070Spatrick // If there was an error parsing parenthesized declarator, declarator
6440e5dd7070Spatrick // scope may have been entered before. Don't do it again.
6441e5dd7070Spatrick if (!D.isInvalidType() &&
6442e5dd7070Spatrick Actions.ShouldEnterDeclaratorScope(getCurScope(),
6443e5dd7070Spatrick D.getCXXScopeSpec()))
6444e5dd7070Spatrick // Change the declaration context for name lookup, until this function
6445e5dd7070Spatrick // is exited (and the declarator has been parsed).
6446e5dd7070Spatrick DeclScopeObj.EnterDeclaratorScope();
6447e5dd7070Spatrick }
6448e5dd7070Spatrick } else if (D.mayOmitIdentifier()) {
6449e5dd7070Spatrick // This could be something simple like "int" (in which case the declarator
6450e5dd7070Spatrick // portion is empty), if an abstract-declarator is allowed.
6451e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6452e5dd7070Spatrick
6453e5dd7070Spatrick // The grammar for abstract-pack-declarator does not allow grouping parens.
6454e5dd7070Spatrick // FIXME: Revisit this once core issue 1488 is resolved.
6455e5dd7070Spatrick if (D.hasEllipsis() && D.hasGroupingParens())
6456e5dd7070Spatrick Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()),
6457e5dd7070Spatrick diag::ext_abstract_pack_declarator_parens);
6458e5dd7070Spatrick } else {
6459e5dd7070Spatrick if (Tok.getKind() == tok::annot_pragma_parser_crash)
6460e5dd7070Spatrick LLVM_BUILTIN_TRAP;
6461e5dd7070Spatrick if (Tok.is(tok::l_square))
6462e5dd7070Spatrick return ParseMisplacedBracketDeclarator(D);
6463a9ac8606Spatrick if (D.getContext() == DeclaratorContext::Member) {
6464e5dd7070Spatrick // Objective-C++: Detect C++ keywords and try to prevent further errors by
6465e5dd7070Spatrick // treating these keyword as valid member names.
6466e5dd7070Spatrick if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&
6467e5dd7070Spatrick Tok.getIdentifierInfo() &&
6468e5dd7070Spatrick Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) {
6469e5dd7070Spatrick Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
6470e5dd7070Spatrick diag::err_expected_member_name_or_semi_objcxx_keyword)
6471e5dd7070Spatrick << Tok.getIdentifierInfo()
6472e5dd7070Spatrick << (D.getDeclSpec().isEmpty() ? SourceRange()
6473e5dd7070Spatrick : D.getDeclSpec().getSourceRange());
6474e5dd7070Spatrick D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
6475e5dd7070Spatrick D.SetRangeEnd(Tok.getLocation());
6476e5dd7070Spatrick ConsumeToken();
6477e5dd7070Spatrick goto PastIdentifier;
6478e5dd7070Spatrick }
6479e5dd7070Spatrick Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
6480e5dd7070Spatrick diag::err_expected_member_name_or_semi)
6481e5dd7070Spatrick << (D.getDeclSpec().isEmpty() ? SourceRange()
6482e5dd7070Spatrick : D.getDeclSpec().getSourceRange());
6483*12c85518Srobert } else {
6484*12c85518Srobert if (Tok.getKind() == tok::TokenKind::kw_while) {
6485*12c85518Srobert Diag(Tok, diag::err_while_loop_outside_of_a_function);
6486e5dd7070Spatrick } else if (getLangOpts().CPlusPlus) {
6487e5dd7070Spatrick if (Tok.isOneOf(tok::period, tok::arrow))
6488e5dd7070Spatrick Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
6489e5dd7070Spatrick else {
6490e5dd7070Spatrick SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
6491e5dd7070Spatrick if (Tok.isAtStartOfLine() && Loc.isValid())
6492e5dd7070Spatrick Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
6493e5dd7070Spatrick << getLangOpts().CPlusPlus;
6494e5dd7070Spatrick else
6495e5dd7070Spatrick Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
6496e5dd7070Spatrick diag::err_expected_unqualified_id)
6497e5dd7070Spatrick << getLangOpts().CPlusPlus;
6498e5dd7070Spatrick }
6499e5dd7070Spatrick } else {
6500e5dd7070Spatrick Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
6501e5dd7070Spatrick diag::err_expected_either)
6502e5dd7070Spatrick << tok::identifier << tok::l_paren;
6503e5dd7070Spatrick }
6504*12c85518Srobert }
6505e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6506e5dd7070Spatrick D.setInvalidType(true);
6507e5dd7070Spatrick }
6508e5dd7070Spatrick
6509e5dd7070Spatrick PastIdentifier:
6510e5dd7070Spatrick assert(D.isPastIdentifier() &&
6511e5dd7070Spatrick "Haven't past the location of the identifier yet?");
6512e5dd7070Spatrick
6513e5dd7070Spatrick // Don't parse attributes unless we have parsed an unparenthesized name.
6514e5dd7070Spatrick if (D.hasName() && !D.getNumTypeObjects())
6515e5dd7070Spatrick MaybeParseCXX11Attributes(D);
6516e5dd7070Spatrick
6517*12c85518Srobert while (true) {
6518e5dd7070Spatrick if (Tok.is(tok::l_paren)) {
6519e5dd7070Spatrick bool IsFunctionDeclaration = D.isFunctionDeclaratorAFunctionDeclaration();
6520e5dd7070Spatrick // Enter function-declaration scope, limiting any declarators to the
6521e5dd7070Spatrick // function prototype scope, including parameter declarators.
6522e5dd7070Spatrick ParseScope PrototypeScope(this,
6523e5dd7070Spatrick Scope::FunctionPrototypeScope|Scope::DeclScope|
6524e5dd7070Spatrick (IsFunctionDeclaration
6525e5dd7070Spatrick ? Scope::FunctionDeclarationScope : 0));
6526e5dd7070Spatrick
6527e5dd7070Spatrick // The paren may be part of a C++ direct initializer, eg. "int x(1);".
6528e5dd7070Spatrick // In such a case, check if we actually have a function declarator; if it
6529e5dd7070Spatrick // is not, the declarator has been fully parsed.
6530e5dd7070Spatrick bool IsAmbiguous = false;
6531e5dd7070Spatrick if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
6532*12c85518Srobert // C++2a [temp.res]p5
6533*12c85518Srobert // A qualified-id is assumed to name a type if
6534*12c85518Srobert // - [...]
6535*12c85518Srobert // - it is a decl-specifier of the decl-specifier-seq of a
6536*12c85518Srobert // - [...]
6537*12c85518Srobert // - parameter-declaration in a member-declaration [...]
6538*12c85518Srobert // - parameter-declaration in a declarator of a function or function
6539*12c85518Srobert // template declaration whose declarator-id is qualified [...]
6540*12c85518Srobert auto AllowImplicitTypename = ImplicitTypenameContext::No;
6541*12c85518Srobert if (D.getCXXScopeSpec().isSet())
6542*12c85518Srobert AllowImplicitTypename =
6543*12c85518Srobert (ImplicitTypenameContext)Actions.isDeclaratorFunctionLike(D);
6544*12c85518Srobert else if (D.getContext() == DeclaratorContext::Member) {
6545*12c85518Srobert AllowImplicitTypename = ImplicitTypenameContext::Yes;
6546*12c85518Srobert }
6547*12c85518Srobert
6548e5dd7070Spatrick // The name of the declarator, if any, is tentatively declared within
6549e5dd7070Spatrick // a possible direct initializer.
6550e5dd7070Spatrick TentativelyDeclaredIdentifiers.push_back(D.getIdentifier());
6551*12c85518Srobert bool IsFunctionDecl =
6552*12c85518Srobert isCXXFunctionDeclarator(&IsAmbiguous, AllowImplicitTypename);
6553e5dd7070Spatrick TentativelyDeclaredIdentifiers.pop_back();
6554e5dd7070Spatrick if (!IsFunctionDecl)
6555e5dd7070Spatrick break;
6556e5dd7070Spatrick }
6557e5dd7070Spatrick ParsedAttributes attrs(AttrFactory);
6558e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
6559e5dd7070Spatrick T.consumeOpen();
6560e5dd7070Spatrick if (IsFunctionDeclaration)
6561e5dd7070Spatrick Actions.ActOnStartFunctionDeclarationDeclarator(D,
6562e5dd7070Spatrick TemplateParameterDepth);
6563e5dd7070Spatrick ParseFunctionDeclarator(D, attrs, T, IsAmbiguous);
6564e5dd7070Spatrick if (IsFunctionDeclaration)
6565e5dd7070Spatrick Actions.ActOnFinishFunctionDeclarationDeclarator(D);
6566e5dd7070Spatrick PrototypeScope.Exit();
6567e5dd7070Spatrick } else if (Tok.is(tok::l_square)) {
6568e5dd7070Spatrick ParseBracketDeclarator(D);
6569e5dd7070Spatrick } else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) {
6570e5dd7070Spatrick // This declarator is declaring a function, but the requires clause is
6571e5dd7070Spatrick // in the wrong place:
6572e5dd7070Spatrick // void (f() requires true);
6573e5dd7070Spatrick // instead of
6574e5dd7070Spatrick // void f() requires true;
6575e5dd7070Spatrick // or
6576e5dd7070Spatrick // void (f()) requires true;
6577e5dd7070Spatrick Diag(Tok, diag::err_requires_clause_inside_parens);
6578e5dd7070Spatrick ConsumeToken();
6579e5dd7070Spatrick ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr(
6580e5dd7070Spatrick ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
6581e5dd7070Spatrick if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() &&
6582e5dd7070Spatrick !D.hasTrailingRequiresClause())
6583e5dd7070Spatrick // We're already ill-formed if we got here but we'll accept it anyway.
6584e5dd7070Spatrick D.setTrailingRequiresClause(TrailingRequiresClause.get());
6585e5dd7070Spatrick } else {
6586e5dd7070Spatrick break;
6587e5dd7070Spatrick }
6588e5dd7070Spatrick }
6589e5dd7070Spatrick }
6590e5dd7070Spatrick
ParseDecompositionDeclarator(Declarator & D)6591e5dd7070Spatrick void Parser::ParseDecompositionDeclarator(Declarator &D) {
6592e5dd7070Spatrick assert(Tok.is(tok::l_square));
6593e5dd7070Spatrick
6594e5dd7070Spatrick // If this doesn't look like a structured binding, maybe it's a misplaced
6595e5dd7070Spatrick // array declarator.
6596e5dd7070Spatrick // FIXME: Consume the l_square first so we don't need extra lookahead for
6597e5dd7070Spatrick // this.
6598e5dd7070Spatrick if (!(NextToken().is(tok::identifier) &&
6599e5dd7070Spatrick GetLookAheadToken(2).isOneOf(tok::comma, tok::r_square)) &&
6600e5dd7070Spatrick !(NextToken().is(tok::r_square) &&
6601e5dd7070Spatrick GetLookAheadToken(2).isOneOf(tok::equal, tok::l_brace)))
6602e5dd7070Spatrick return ParseMisplacedBracketDeclarator(D);
6603e5dd7070Spatrick
6604e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_square);
6605e5dd7070Spatrick T.consumeOpen();
6606e5dd7070Spatrick
6607e5dd7070Spatrick SmallVector<DecompositionDeclarator::Binding, 32> Bindings;
6608e5dd7070Spatrick while (Tok.isNot(tok::r_square)) {
6609e5dd7070Spatrick if (!Bindings.empty()) {
6610e5dd7070Spatrick if (Tok.is(tok::comma))
6611e5dd7070Spatrick ConsumeToken();
6612e5dd7070Spatrick else {
6613e5dd7070Spatrick if (Tok.is(tok::identifier)) {
6614e5dd7070Spatrick SourceLocation EndLoc = getEndOfPreviousToken();
6615e5dd7070Spatrick Diag(EndLoc, diag::err_expected)
6616e5dd7070Spatrick << tok::comma << FixItHint::CreateInsertion(EndLoc, ",");
6617e5dd7070Spatrick } else {
6618e5dd7070Spatrick Diag(Tok, diag::err_expected_comma_or_rsquare);
6619e5dd7070Spatrick }
6620e5dd7070Spatrick
6621e5dd7070Spatrick SkipUntil(tok::r_square, tok::comma, tok::identifier,
6622e5dd7070Spatrick StopAtSemi | StopBeforeMatch);
6623e5dd7070Spatrick if (Tok.is(tok::comma))
6624e5dd7070Spatrick ConsumeToken();
6625e5dd7070Spatrick else if (Tok.isNot(tok::identifier))
6626e5dd7070Spatrick break;
6627e5dd7070Spatrick }
6628e5dd7070Spatrick }
6629e5dd7070Spatrick
6630e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
6631e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::identifier;
6632e5dd7070Spatrick break;
6633e5dd7070Spatrick }
6634e5dd7070Spatrick
6635e5dd7070Spatrick Bindings.push_back({Tok.getIdentifierInfo(), Tok.getLocation()});
6636e5dd7070Spatrick ConsumeToken();
6637e5dd7070Spatrick }
6638e5dd7070Spatrick
6639e5dd7070Spatrick if (Tok.isNot(tok::r_square))
6640e5dd7070Spatrick // We've already diagnosed a problem here.
6641e5dd7070Spatrick T.skipToEnd();
6642e5dd7070Spatrick else {
6643e5dd7070Spatrick // C++17 does not allow the identifier-list in a structured binding
6644e5dd7070Spatrick // to be empty.
6645e5dd7070Spatrick if (Bindings.empty())
6646e5dd7070Spatrick Diag(Tok.getLocation(), diag::ext_decomp_decl_empty);
6647e5dd7070Spatrick
6648e5dd7070Spatrick T.consumeClose();
6649e5dd7070Spatrick }
6650e5dd7070Spatrick
6651e5dd7070Spatrick return D.setDecompositionBindings(T.getOpenLocation(), Bindings,
6652e5dd7070Spatrick T.getCloseLocation());
6653e5dd7070Spatrick }
6654e5dd7070Spatrick
6655e5dd7070Spatrick /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
6656e5dd7070Spatrick /// only called before the identifier, so these are most likely just grouping
6657e5dd7070Spatrick /// parens for precedence. If we find that these are actually function
6658e5dd7070Spatrick /// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
6659e5dd7070Spatrick ///
6660e5dd7070Spatrick /// direct-declarator:
6661e5dd7070Spatrick /// '(' declarator ')'
6662e5dd7070Spatrick /// [GNU] '(' attributes declarator ')'
6663e5dd7070Spatrick /// direct-declarator '(' parameter-type-list ')'
6664e5dd7070Spatrick /// direct-declarator '(' identifier-list[opt] ')'
6665e5dd7070Spatrick /// [GNU] direct-declarator '(' parameter-forward-declarations
6666e5dd7070Spatrick /// parameter-type-list[opt] ')'
6667e5dd7070Spatrick ///
ParseParenDeclarator(Declarator & D)6668e5dd7070Spatrick void Parser::ParseParenDeclarator(Declarator &D) {
6669e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
6670e5dd7070Spatrick T.consumeOpen();
6671e5dd7070Spatrick
6672e5dd7070Spatrick assert(!D.isPastIdentifier() && "Should be called before passing identifier");
6673e5dd7070Spatrick
6674e5dd7070Spatrick // Eat any attributes before we look at whether this is a grouping or function
6675e5dd7070Spatrick // declarator paren. If this is a grouping paren, the attribute applies to
6676e5dd7070Spatrick // the type being built up, for example:
6677e5dd7070Spatrick // int (__attribute__(()) *x)(long y)
6678e5dd7070Spatrick // If this ends up not being a grouping paren, the attribute applies to the
6679e5dd7070Spatrick // first argument, for example:
6680e5dd7070Spatrick // int (__attribute__(()) int x)
6681e5dd7070Spatrick // In either case, we need to eat any attributes to be able to determine what
6682e5dd7070Spatrick // sort of paren this is.
6683e5dd7070Spatrick //
6684e5dd7070Spatrick ParsedAttributes attrs(AttrFactory);
6685e5dd7070Spatrick bool RequiresArg = false;
6686e5dd7070Spatrick if (Tok.is(tok::kw___attribute)) {
6687e5dd7070Spatrick ParseGNUAttributes(attrs);
6688e5dd7070Spatrick
6689e5dd7070Spatrick // We require that the argument list (if this is a non-grouping paren) be
6690e5dd7070Spatrick // present even if the attribute list was empty.
6691e5dd7070Spatrick RequiresArg = true;
6692e5dd7070Spatrick }
6693e5dd7070Spatrick
6694e5dd7070Spatrick // Eat any Microsoft extensions.
6695e5dd7070Spatrick ParseMicrosoftTypeAttributes(attrs);
6696e5dd7070Spatrick
6697e5dd7070Spatrick // Eat any Borland extensions.
6698e5dd7070Spatrick if (Tok.is(tok::kw___pascal))
6699e5dd7070Spatrick ParseBorlandTypeAttributes(attrs);
6700e5dd7070Spatrick
6701e5dd7070Spatrick // If we haven't past the identifier yet (or where the identifier would be
6702e5dd7070Spatrick // stored, if this is an abstract declarator), then this is probably just
6703e5dd7070Spatrick // grouping parens. However, if this could be an abstract-declarator, then
6704e5dd7070Spatrick // this could also be the start of function arguments (consider 'void()').
6705e5dd7070Spatrick bool isGrouping;
6706e5dd7070Spatrick
6707e5dd7070Spatrick if (!D.mayOmitIdentifier()) {
6708e5dd7070Spatrick // If this can't be an abstract-declarator, this *must* be a grouping
6709e5dd7070Spatrick // paren, because we haven't seen the identifier yet.
6710e5dd7070Spatrick isGrouping = true;
6711e5dd7070Spatrick } else if (Tok.is(tok::r_paren) || // 'int()' is a function.
6712e5dd7070Spatrick (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) &&
6713e5dd7070Spatrick NextToken().is(tok::r_paren)) || // C++ int(...)
6714*12c85518Srobert isDeclarationSpecifier(
6715*12c85518Srobert ImplicitTypenameContext::No) || // 'int(int)' is a function.
6716e5dd7070Spatrick isCXX11AttributeSpecifier()) { // 'int([[]]int)' is a function.
6717e5dd7070Spatrick // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
6718e5dd7070Spatrick // considered to be a type, not a K&R identifier-list.
6719e5dd7070Spatrick isGrouping = false;
6720e5dd7070Spatrick } else {
6721e5dd7070Spatrick // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
6722e5dd7070Spatrick isGrouping = true;
6723e5dd7070Spatrick }
6724e5dd7070Spatrick
6725e5dd7070Spatrick // If this is a grouping paren, handle:
6726e5dd7070Spatrick // direct-declarator: '(' declarator ')'
6727e5dd7070Spatrick // direct-declarator: '(' attributes declarator ')'
6728e5dd7070Spatrick if (isGrouping) {
6729e5dd7070Spatrick SourceLocation EllipsisLoc = D.getEllipsisLoc();
6730e5dd7070Spatrick D.setEllipsisLoc(SourceLocation());
6731e5dd7070Spatrick
6732e5dd7070Spatrick bool hadGroupingParens = D.hasGroupingParens();
6733e5dd7070Spatrick D.setGroupingParens(true);
6734e5dd7070Spatrick ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
6735e5dd7070Spatrick // Match the ')'.
6736e5dd7070Spatrick T.consumeClose();
6737e5dd7070Spatrick D.AddTypeInfo(
6738e5dd7070Spatrick DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()),
6739e5dd7070Spatrick std::move(attrs), T.getCloseLocation());
6740e5dd7070Spatrick
6741e5dd7070Spatrick D.setGroupingParens(hadGroupingParens);
6742e5dd7070Spatrick
6743e5dd7070Spatrick // An ellipsis cannot be placed outside parentheses.
6744e5dd7070Spatrick if (EllipsisLoc.isValid())
6745e5dd7070Spatrick DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
6746e5dd7070Spatrick
6747e5dd7070Spatrick return;
6748e5dd7070Spatrick }
6749e5dd7070Spatrick
6750e5dd7070Spatrick // Okay, if this wasn't a grouping paren, it must be the start of a function
6751e5dd7070Spatrick // argument list. Recognize that this declarator will never have an
6752e5dd7070Spatrick // identifier (and remember where it would have been), then call into
6753e5dd7070Spatrick // ParseFunctionDeclarator to handle of argument list.
6754e5dd7070Spatrick D.SetIdentifier(nullptr, Tok.getLocation());
6755e5dd7070Spatrick
6756e5dd7070Spatrick // Enter function-declaration scope, limiting any declarators to the
6757e5dd7070Spatrick // function prototype scope, including parameter declarators.
6758e5dd7070Spatrick ParseScope PrototypeScope(this,
6759e5dd7070Spatrick Scope::FunctionPrototypeScope | Scope::DeclScope |
6760e5dd7070Spatrick (D.isFunctionDeclaratorAFunctionDeclaration()
6761e5dd7070Spatrick ? Scope::FunctionDeclarationScope : 0));
6762e5dd7070Spatrick ParseFunctionDeclarator(D, attrs, T, false, RequiresArg);
6763e5dd7070Spatrick PrototypeScope.Exit();
6764e5dd7070Spatrick }
6765e5dd7070Spatrick
InitCXXThisScopeForDeclaratorIfRelevant(const Declarator & D,const DeclSpec & DS,std::optional<Sema::CXXThisScopeRAII> & ThisScope)6766e5dd7070Spatrick void Parser::InitCXXThisScopeForDeclaratorIfRelevant(
6767e5dd7070Spatrick const Declarator &D, const DeclSpec &DS,
6768*12c85518Srobert std::optional<Sema::CXXThisScopeRAII> &ThisScope) {
6769e5dd7070Spatrick // C++11 [expr.prim.general]p3:
6770e5dd7070Spatrick // If a declaration declares a member function or member function
6771e5dd7070Spatrick // template of a class X, the expression this is a prvalue of type
6772e5dd7070Spatrick // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
6773e5dd7070Spatrick // and the end of the function-definition, member-declarator, or
6774e5dd7070Spatrick // declarator.
6775e5dd7070Spatrick // FIXME: currently, "static" case isn't handled correctly.
6776a9ac8606Spatrick bool IsCXX11MemberFunction =
6777a9ac8606Spatrick getLangOpts().CPlusPlus11 &&
6778e5dd7070Spatrick D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
6779a9ac8606Spatrick (D.getContext() == DeclaratorContext::Member
6780e5dd7070Spatrick ? !D.getDeclSpec().isFriendSpecified()
6781a9ac8606Spatrick : D.getContext() == DeclaratorContext::File &&
6782e5dd7070Spatrick D.getCXXScopeSpec().isValid() &&
6783e5dd7070Spatrick Actions.CurContext->isRecord());
6784e5dd7070Spatrick if (!IsCXX11MemberFunction)
6785e5dd7070Spatrick return;
6786e5dd7070Spatrick
6787e5dd7070Spatrick Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
6788e5dd7070Spatrick if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)
6789e5dd7070Spatrick Q.addConst();
6790e5dd7070Spatrick // FIXME: Collect C++ address spaces.
6791e5dd7070Spatrick // If there are multiple different address spaces, the source is invalid.
6792e5dd7070Spatrick // Carry on using the first addr space for the qualifiers of 'this'.
6793e5dd7070Spatrick // The diagnostic will be given later while creating the function
6794e5dd7070Spatrick // prototype for the method.
6795e5dd7070Spatrick if (getLangOpts().OpenCLCPlusPlus) {
6796e5dd7070Spatrick for (ParsedAttr &attr : DS.getAttributes()) {
6797e5dd7070Spatrick LangAS ASIdx = attr.asOpenCLLangAS();
6798e5dd7070Spatrick if (ASIdx != LangAS::Default) {
6799e5dd7070Spatrick Q.addAddressSpace(ASIdx);
6800e5dd7070Spatrick break;
6801e5dd7070Spatrick }
6802e5dd7070Spatrick }
6803e5dd7070Spatrick }
6804e5dd7070Spatrick ThisScope.emplace(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
6805e5dd7070Spatrick IsCXX11MemberFunction);
6806e5dd7070Spatrick }
6807e5dd7070Spatrick
6808e5dd7070Spatrick /// ParseFunctionDeclarator - We are after the identifier and have parsed the
6809e5dd7070Spatrick /// declarator D up to a paren, which indicates that we are parsing function
6810e5dd7070Spatrick /// arguments.
6811e5dd7070Spatrick ///
6812*12c85518Srobert /// If FirstArgAttrs is non-null, then the caller parsed those attributes
6813*12c85518Srobert /// immediately after the open paren - they will be applied to the DeclSpec
6814*12c85518Srobert /// of the first parameter.
6815e5dd7070Spatrick ///
6816e5dd7070Spatrick /// If RequiresArg is true, then the first argument of the function is required
6817e5dd7070Spatrick /// to be present and required to not be an identifier list.
6818e5dd7070Spatrick ///
6819e5dd7070Spatrick /// For C++, after the parameter-list, it also parses the cv-qualifier-seq[opt],
6820e5dd7070Spatrick /// (C++11) ref-qualifier[opt], exception-specification[opt],
6821e5dd7070Spatrick /// (C++11) attribute-specifier-seq[opt], (C++11) trailing-return-type[opt] and
6822e5dd7070Spatrick /// (C++2a) the trailing requires-clause.
6823e5dd7070Spatrick ///
6824e5dd7070Spatrick /// [C++11] exception-specification:
6825e5dd7070Spatrick /// dynamic-exception-specification
6826e5dd7070Spatrick /// noexcept-specification
6827e5dd7070Spatrick ///
ParseFunctionDeclarator(Declarator & D,ParsedAttributes & FirstArgAttrs,BalancedDelimiterTracker & Tracker,bool IsAmbiguous,bool RequiresArg)6828e5dd7070Spatrick void Parser::ParseFunctionDeclarator(Declarator &D,
6829e5dd7070Spatrick ParsedAttributes &FirstArgAttrs,
6830e5dd7070Spatrick BalancedDelimiterTracker &Tracker,
6831e5dd7070Spatrick bool IsAmbiguous,
6832e5dd7070Spatrick bool RequiresArg) {
6833e5dd7070Spatrick assert(getCurScope()->isFunctionPrototypeScope() &&
6834e5dd7070Spatrick "Should call from a Function scope");
6835e5dd7070Spatrick // lparen is already consumed!
6836e5dd7070Spatrick assert(D.isPastIdentifier() && "Should not call before identifier!");
6837e5dd7070Spatrick
6838e5dd7070Spatrick // This should be true when the function has typed arguments.
6839e5dd7070Spatrick // Otherwise, it is treated as a K&R-style function.
6840e5dd7070Spatrick bool HasProto = false;
6841e5dd7070Spatrick // Build up an array of information about the parsed arguments.
6842e5dd7070Spatrick SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
6843e5dd7070Spatrick // Remember where we see an ellipsis, if any.
6844e5dd7070Spatrick SourceLocation EllipsisLoc;
6845e5dd7070Spatrick
6846e5dd7070Spatrick DeclSpec DS(AttrFactory);
6847e5dd7070Spatrick bool RefQualifierIsLValueRef = true;
6848e5dd7070Spatrick SourceLocation RefQualifierLoc;
6849e5dd7070Spatrick ExceptionSpecificationType ESpecType = EST_None;
6850e5dd7070Spatrick SourceRange ESpecRange;
6851e5dd7070Spatrick SmallVector<ParsedType, 2> DynamicExceptions;
6852e5dd7070Spatrick SmallVector<SourceRange, 2> DynamicExceptionRanges;
6853e5dd7070Spatrick ExprResult NoexceptExpr;
6854e5dd7070Spatrick CachedTokens *ExceptionSpecTokens = nullptr;
6855*12c85518Srobert ParsedAttributes FnAttrs(AttrFactory);
6856e5dd7070Spatrick TypeResult TrailingReturnType;
6857a9ac8606Spatrick SourceLocation TrailingReturnTypeLoc;
6858e5dd7070Spatrick
6859e5dd7070Spatrick /* LocalEndLoc is the end location for the local FunctionTypeLoc.
6860e5dd7070Spatrick EndLoc is the end location for the function declarator.
6861e5dd7070Spatrick They differ for trailing return types. */
6862e5dd7070Spatrick SourceLocation StartLoc, LocalEndLoc, EndLoc;
6863e5dd7070Spatrick SourceLocation LParenLoc, RParenLoc;
6864e5dd7070Spatrick LParenLoc = Tracker.getOpenLocation();
6865e5dd7070Spatrick StartLoc = LParenLoc;
6866e5dd7070Spatrick
6867e5dd7070Spatrick if (isFunctionDeclaratorIdentifierList()) {
6868e5dd7070Spatrick if (RequiresArg)
6869e5dd7070Spatrick Diag(Tok, diag::err_argument_required_after_attribute);
6870e5dd7070Spatrick
6871e5dd7070Spatrick ParseFunctionDeclaratorIdentifierList(D, ParamInfo);
6872e5dd7070Spatrick
6873e5dd7070Spatrick Tracker.consumeClose();
6874e5dd7070Spatrick RParenLoc = Tracker.getCloseLocation();
6875e5dd7070Spatrick LocalEndLoc = RParenLoc;
6876e5dd7070Spatrick EndLoc = RParenLoc;
6877e5dd7070Spatrick
6878e5dd7070Spatrick // If there are attributes following the identifier list, parse them and
6879e5dd7070Spatrick // prohibit them.
6880e5dd7070Spatrick MaybeParseCXX11Attributes(FnAttrs);
6881e5dd7070Spatrick ProhibitAttributes(FnAttrs);
6882e5dd7070Spatrick } else {
6883e5dd7070Spatrick if (Tok.isNot(tok::r_paren))
6884*12c85518Srobert ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc);
6885e5dd7070Spatrick else if (RequiresArg)
6886e5dd7070Spatrick Diag(Tok, diag::err_argument_required_after_attribute);
6887e5dd7070Spatrick
6888*12c85518Srobert // OpenCL disallows functions without a prototype, but it doesn't enforce
6889*12c85518Srobert // strict prototypes as in C2x because it allows a function definition to
6890*12c85518Srobert // have an identifier list. See OpenCL 3.0 6.11/g for more details.
6891*12c85518Srobert HasProto = ParamInfo.size() || getLangOpts().requiresStrictPrototypes() ||
6892*12c85518Srobert getLangOpts().OpenCL;
6893e5dd7070Spatrick
6894e5dd7070Spatrick // If we have the closing ')', eat it.
6895e5dd7070Spatrick Tracker.consumeClose();
6896e5dd7070Spatrick RParenLoc = Tracker.getCloseLocation();
6897e5dd7070Spatrick LocalEndLoc = RParenLoc;
6898e5dd7070Spatrick EndLoc = RParenLoc;
6899e5dd7070Spatrick
6900e5dd7070Spatrick if (getLangOpts().CPlusPlus) {
6901e5dd7070Spatrick // FIXME: Accept these components in any order, and produce fixits to
6902e5dd7070Spatrick // correct the order if the user gets it wrong. Ideally we should deal
6903e5dd7070Spatrick // with the pure-specifier in the same way.
6904e5dd7070Spatrick
6905e5dd7070Spatrick // Parse cv-qualifier-seq[opt].
6906e5dd7070Spatrick ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed,
6907e5dd7070Spatrick /*AtomicAllowed*/ false,
6908e5dd7070Spatrick /*IdentifierRequired=*/false,
6909e5dd7070Spatrick llvm::function_ref<void()>([&]() {
6910e5dd7070Spatrick Actions.CodeCompleteFunctionQualifiers(DS, D);
6911e5dd7070Spatrick }));
6912e5dd7070Spatrick if (!DS.getSourceRange().getEnd().isInvalid()) {
6913e5dd7070Spatrick EndLoc = DS.getSourceRange().getEnd();
6914e5dd7070Spatrick }
6915e5dd7070Spatrick
6916e5dd7070Spatrick // Parse ref-qualifier[opt].
6917e5dd7070Spatrick if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
6918e5dd7070Spatrick EndLoc = RefQualifierLoc;
6919e5dd7070Spatrick
6920*12c85518Srobert std::optional<Sema::CXXThisScopeRAII> ThisScope;
6921e5dd7070Spatrick InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);
6922e5dd7070Spatrick
6923e5dd7070Spatrick // Parse exception-specification[opt].
6924a9ac8606Spatrick // FIXME: Per [class.mem]p6, all exception-specifications at class scope
6925a9ac8606Spatrick // should be delayed, including those for non-members (eg, friend
6926a9ac8606Spatrick // declarations). But only applying this to member declarations is
6927a9ac8606Spatrick // consistent with what other implementations do.
6928e5dd7070Spatrick bool Delayed = D.isFirstDeclarationOfMember() &&
6929e5dd7070Spatrick D.isFunctionDeclaratorAFunctionDeclaration();
6930e5dd7070Spatrick if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) &&
6931e5dd7070Spatrick GetLookAheadToken(0).is(tok::kw_noexcept) &&
6932e5dd7070Spatrick GetLookAheadToken(1).is(tok::l_paren) &&
6933e5dd7070Spatrick GetLookAheadToken(2).is(tok::kw_noexcept) &&
6934e5dd7070Spatrick GetLookAheadToken(3).is(tok::l_paren) &&
6935e5dd7070Spatrick GetLookAheadToken(4).is(tok::identifier) &&
6936e5dd7070Spatrick GetLookAheadToken(4).getIdentifierInfo()->isStr("swap")) {
6937e5dd7070Spatrick // HACK: We've got an exception-specification
6938e5dd7070Spatrick // noexcept(noexcept(swap(...)))
6939e5dd7070Spatrick // or
6940e5dd7070Spatrick // noexcept(noexcept(swap(...)) && noexcept(swap(...)))
6941e5dd7070Spatrick // on a 'swap' member function. This is a libstdc++ bug; the lookup
6942e5dd7070Spatrick // for 'swap' will only find the function we're currently declaring,
6943e5dd7070Spatrick // whereas it expects to find a non-member swap through ADL. Turn off
6944e5dd7070Spatrick // delayed parsing to give it a chance to find what it expects.
6945e5dd7070Spatrick Delayed = false;
6946e5dd7070Spatrick }
6947e5dd7070Spatrick ESpecType = tryParseExceptionSpecification(Delayed,
6948e5dd7070Spatrick ESpecRange,
6949e5dd7070Spatrick DynamicExceptions,
6950e5dd7070Spatrick DynamicExceptionRanges,
6951e5dd7070Spatrick NoexceptExpr,
6952e5dd7070Spatrick ExceptionSpecTokens);
6953e5dd7070Spatrick if (ESpecType != EST_None)
6954e5dd7070Spatrick EndLoc = ESpecRange.getEnd();
6955e5dd7070Spatrick
6956e5dd7070Spatrick // Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes
6957e5dd7070Spatrick // after the exception-specification.
6958e5dd7070Spatrick MaybeParseCXX11Attributes(FnAttrs);
6959e5dd7070Spatrick
6960e5dd7070Spatrick // Parse trailing-return-type[opt].
6961e5dd7070Spatrick LocalEndLoc = EndLoc;
6962e5dd7070Spatrick if (getLangOpts().CPlusPlus11 && Tok.is(tok::arrow)) {
6963e5dd7070Spatrick Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);
6964e5dd7070Spatrick if (D.getDeclSpec().getTypeSpecType() == TST_auto)
6965e5dd7070Spatrick StartLoc = D.getDeclSpec().getTypeSpecTypeLoc();
6966e5dd7070Spatrick LocalEndLoc = Tok.getLocation();
6967e5dd7070Spatrick SourceRange Range;
6968e5dd7070Spatrick TrailingReturnType =
6969e5dd7070Spatrick ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit());
6970a9ac8606Spatrick TrailingReturnTypeLoc = Range.getBegin();
6971e5dd7070Spatrick EndLoc = Range.getEnd();
6972e5dd7070Spatrick }
6973e5dd7070Spatrick } else if (standardAttributesAllowed()) {
6974e5dd7070Spatrick MaybeParseCXX11Attributes(FnAttrs);
6975e5dd7070Spatrick }
6976e5dd7070Spatrick }
6977e5dd7070Spatrick
6978e5dd7070Spatrick // Collect non-parameter declarations from the prototype if this is a function
6979e5dd7070Spatrick // declaration. They will be moved into the scope of the function. Only do
6980e5dd7070Spatrick // this in C and not C++, where the decls will continue to live in the
6981e5dd7070Spatrick // surrounding context.
6982e5dd7070Spatrick SmallVector<NamedDecl *, 0> DeclsInPrototype;
6983*12c85518Srobert if (getCurScope()->isFunctionDeclarationScope() && !getLangOpts().CPlusPlus) {
6984e5dd7070Spatrick for (Decl *D : getCurScope()->decls()) {
6985e5dd7070Spatrick NamedDecl *ND = dyn_cast<NamedDecl>(D);
6986e5dd7070Spatrick if (!ND || isa<ParmVarDecl>(ND))
6987e5dd7070Spatrick continue;
6988e5dd7070Spatrick DeclsInPrototype.push_back(ND);
6989e5dd7070Spatrick }
6990e5dd7070Spatrick }
6991e5dd7070Spatrick
6992e5dd7070Spatrick // Remember that we parsed a function type, and remember the attributes.
6993e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getFunction(
6994e5dd7070Spatrick HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(),
6995e5dd7070Spatrick ParamInfo.size(), EllipsisLoc, RParenLoc,
6996e5dd7070Spatrick RefQualifierIsLValueRef, RefQualifierLoc,
6997e5dd7070Spatrick /*MutableLoc=*/SourceLocation(),
6998e5dd7070Spatrick ESpecType, ESpecRange, DynamicExceptions.data(),
6999e5dd7070Spatrick DynamicExceptionRanges.data(), DynamicExceptions.size(),
7000e5dd7070Spatrick NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
7001e5dd7070Spatrick ExceptionSpecTokens, DeclsInPrototype, StartLoc,
7002a9ac8606Spatrick LocalEndLoc, D, TrailingReturnType, TrailingReturnTypeLoc,
7003a9ac8606Spatrick &DS),
7004e5dd7070Spatrick std::move(FnAttrs), EndLoc);
7005e5dd7070Spatrick }
7006e5dd7070Spatrick
7007e5dd7070Spatrick /// ParseRefQualifier - Parses a member function ref-qualifier. Returns
7008e5dd7070Spatrick /// true if a ref-qualifier is found.
ParseRefQualifier(bool & RefQualifierIsLValueRef,SourceLocation & RefQualifierLoc)7009e5dd7070Spatrick bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,
7010e5dd7070Spatrick SourceLocation &RefQualifierLoc) {
7011e5dd7070Spatrick if (Tok.isOneOf(tok::amp, tok::ampamp)) {
7012e5dd7070Spatrick Diag(Tok, getLangOpts().CPlusPlus11 ?
7013e5dd7070Spatrick diag::warn_cxx98_compat_ref_qualifier :
7014e5dd7070Spatrick diag::ext_ref_qualifier);
7015e5dd7070Spatrick
7016e5dd7070Spatrick RefQualifierIsLValueRef = Tok.is(tok::amp);
7017e5dd7070Spatrick RefQualifierLoc = ConsumeToken();
7018e5dd7070Spatrick return true;
7019e5dd7070Spatrick }
7020e5dd7070Spatrick return false;
7021e5dd7070Spatrick }
7022e5dd7070Spatrick
7023e5dd7070Spatrick /// isFunctionDeclaratorIdentifierList - This parameter list may have an
7024e5dd7070Spatrick /// identifier list form for a K&R-style function: void foo(a,b,c)
7025e5dd7070Spatrick ///
7026e5dd7070Spatrick /// Note that identifier-lists are only allowed for normal declarators, not for
7027e5dd7070Spatrick /// abstract-declarators.
isFunctionDeclaratorIdentifierList()7028e5dd7070Spatrick bool Parser::isFunctionDeclaratorIdentifierList() {
7029*12c85518Srobert return !getLangOpts().requiresStrictPrototypes()
7030e5dd7070Spatrick && Tok.is(tok::identifier)
7031e5dd7070Spatrick && !TryAltiVecVectorToken()
7032e5dd7070Spatrick // K&R identifier lists can't have typedefs as identifiers, per C99
7033e5dd7070Spatrick // 6.7.5.3p11.
7034e5dd7070Spatrick && (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename))
7035e5dd7070Spatrick // Identifier lists follow a really simple grammar: the identifiers can
7036e5dd7070Spatrick // be followed *only* by a ", identifier" or ")". However, K&R
7037e5dd7070Spatrick // identifier lists are really rare in the brave new modern world, and
7038e5dd7070Spatrick // it is very common for someone to typo a type in a non-K&R style
7039e5dd7070Spatrick // list. If we are presented with something like: "void foo(intptr x,
7040e5dd7070Spatrick // float y)", we don't want to start parsing the function declarator as
7041e5dd7070Spatrick // though it is a K&R style declarator just because intptr is an
7042e5dd7070Spatrick // invalid type.
7043e5dd7070Spatrick //
7044e5dd7070Spatrick // To handle this, we check to see if the token after the first
7045e5dd7070Spatrick // identifier is a "," or ")". Only then do we parse it as an
7046e5dd7070Spatrick // identifier list.
7047e5dd7070Spatrick && (!Tok.is(tok::eof) &&
7048e5dd7070Spatrick (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));
7049e5dd7070Spatrick }
7050e5dd7070Spatrick
7051e5dd7070Spatrick /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
7052e5dd7070Spatrick /// we found a K&R-style identifier list instead of a typed parameter list.
7053e5dd7070Spatrick ///
7054e5dd7070Spatrick /// After returning, ParamInfo will hold the parsed parameters.
7055e5dd7070Spatrick ///
7056e5dd7070Spatrick /// identifier-list: [C99 6.7.5]
7057e5dd7070Spatrick /// identifier
7058e5dd7070Spatrick /// identifier-list ',' identifier
7059e5dd7070Spatrick ///
ParseFunctionDeclaratorIdentifierList(Declarator & D,SmallVectorImpl<DeclaratorChunk::ParamInfo> & ParamInfo)7060e5dd7070Spatrick void Parser::ParseFunctionDeclaratorIdentifierList(
7061e5dd7070Spatrick Declarator &D,
7062e5dd7070Spatrick SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) {
7063*12c85518Srobert // We should never reach this point in C2x or C++.
7064*12c85518Srobert assert(!getLangOpts().requiresStrictPrototypes() &&
7065*12c85518Srobert "Cannot parse an identifier list in C2x or C++");
7066*12c85518Srobert
7067e5dd7070Spatrick // If there was no identifier specified for the declarator, either we are in
7068e5dd7070Spatrick // an abstract-declarator, or we are in a parameter declarator which was found
7069e5dd7070Spatrick // to be abstract. In abstract-declarators, identifier lists are not valid:
7070e5dd7070Spatrick // diagnose this.
7071e5dd7070Spatrick if (!D.getIdentifier())
7072e5dd7070Spatrick Diag(Tok, diag::ext_ident_list_in_param);
7073e5dd7070Spatrick
7074e5dd7070Spatrick // Maintain an efficient lookup of params we have seen so far.
7075e5dd7070Spatrick llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
7076e5dd7070Spatrick
7077e5dd7070Spatrick do {
7078e5dd7070Spatrick // If this isn't an identifier, report the error and skip until ')'.
7079e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
7080e5dd7070Spatrick Diag(Tok, diag::err_expected) << tok::identifier;
7081e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
7082e5dd7070Spatrick // Forget we parsed anything.
7083e5dd7070Spatrick ParamInfo.clear();
7084e5dd7070Spatrick return;
7085e5dd7070Spatrick }
7086e5dd7070Spatrick
7087e5dd7070Spatrick IdentifierInfo *ParmII = Tok.getIdentifierInfo();
7088e5dd7070Spatrick
7089e5dd7070Spatrick // Reject 'typedef int y; int test(x, y)', but continue parsing.
7090e5dd7070Spatrick if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope()))
7091e5dd7070Spatrick Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
7092e5dd7070Spatrick
7093e5dd7070Spatrick // Verify that the argument identifier has not already been mentioned.
7094e5dd7070Spatrick if (!ParamsSoFar.insert(ParmII).second) {
7095e5dd7070Spatrick Diag(Tok, diag::err_param_redefinition) << ParmII;
7096e5dd7070Spatrick } else {
7097e5dd7070Spatrick // Remember this identifier in ParamInfo.
7098e5dd7070Spatrick ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
7099e5dd7070Spatrick Tok.getLocation(),
7100e5dd7070Spatrick nullptr));
7101e5dd7070Spatrick }
7102e5dd7070Spatrick
7103e5dd7070Spatrick // Eat the identifier.
7104e5dd7070Spatrick ConsumeToken();
7105e5dd7070Spatrick // The list continues if we see a comma.
7106e5dd7070Spatrick } while (TryConsumeToken(tok::comma));
7107e5dd7070Spatrick }
7108e5dd7070Spatrick
7109e5dd7070Spatrick /// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
7110e5dd7070Spatrick /// after the opening parenthesis. This function will not parse a K&R-style
7111e5dd7070Spatrick /// identifier list.
7112e5dd7070Spatrick ///
7113e5dd7070Spatrick /// DeclContext is the context of the declarator being parsed. If FirstArgAttrs
7114e5dd7070Spatrick /// is non-null, then the caller parsed those attributes immediately after the
7115*12c85518Srobert /// open paren - they will be applied to the DeclSpec of the first parameter.
7116e5dd7070Spatrick ///
7117e5dd7070Spatrick /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will
7118e5dd7070Spatrick /// be the location of the ellipsis, if any was parsed.
7119e5dd7070Spatrick ///
7120e5dd7070Spatrick /// parameter-type-list: [C99 6.7.5]
7121e5dd7070Spatrick /// parameter-list
7122e5dd7070Spatrick /// parameter-list ',' '...'
7123e5dd7070Spatrick /// [C++] parameter-list '...'
7124e5dd7070Spatrick ///
7125e5dd7070Spatrick /// parameter-list: [C99 6.7.5]
7126e5dd7070Spatrick /// parameter-declaration
7127e5dd7070Spatrick /// parameter-list ',' parameter-declaration
7128e5dd7070Spatrick ///
7129e5dd7070Spatrick /// parameter-declaration: [C99 6.7.5]
7130e5dd7070Spatrick /// declaration-specifiers declarator
7131e5dd7070Spatrick /// [C++] declaration-specifiers declarator '=' assignment-expression
7132e5dd7070Spatrick /// [C++11] initializer-clause
7133e5dd7070Spatrick /// [GNU] declaration-specifiers declarator attributes
7134e5dd7070Spatrick /// declaration-specifiers abstract-declarator[opt]
7135e5dd7070Spatrick /// [C++] declaration-specifiers abstract-declarator[opt]
7136e5dd7070Spatrick /// '=' assignment-expression
7137e5dd7070Spatrick /// [GNU] declaration-specifiers abstract-declarator[opt] attributes
7138e5dd7070Spatrick /// [C++11] attribute-specifier-seq parameter-declaration
7139e5dd7070Spatrick ///
ParseParameterDeclarationClause(DeclaratorContext DeclaratorCtx,ParsedAttributes & FirstArgAttrs,SmallVectorImpl<DeclaratorChunk::ParamInfo> & ParamInfo,SourceLocation & EllipsisLoc,bool IsACXXFunctionDeclaration)7140e5dd7070Spatrick void Parser::ParseParameterDeclarationClause(
7141*12c85518Srobert DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs,
7142e5dd7070Spatrick SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
7143*12c85518Srobert SourceLocation &EllipsisLoc, bool IsACXXFunctionDeclaration) {
7144e5dd7070Spatrick
7145e5dd7070Spatrick // Avoid exceeding the maximum function scope depth.
7146e5dd7070Spatrick // See https://bugs.llvm.org/show_bug.cgi?id=19607
7147e5dd7070Spatrick // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with
7148e5dd7070Spatrick // getFunctionPrototypeDepth() - 1.
7149e5dd7070Spatrick if (getCurScope()->getFunctionPrototypeDepth() - 1 >
7150e5dd7070Spatrick ParmVarDecl::getMaxFunctionScopeDepth()) {
7151e5dd7070Spatrick Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded)
7152e5dd7070Spatrick << ParmVarDecl::getMaxFunctionScopeDepth();
7153e5dd7070Spatrick cutOffParsing();
7154e5dd7070Spatrick return;
7155e5dd7070Spatrick }
7156e5dd7070Spatrick
7157*12c85518Srobert // C++2a [temp.res]p5
7158*12c85518Srobert // A qualified-id is assumed to name a type if
7159*12c85518Srobert // - [...]
7160*12c85518Srobert // - it is a decl-specifier of the decl-specifier-seq of a
7161*12c85518Srobert // - [...]
7162*12c85518Srobert // - parameter-declaration in a member-declaration [...]
7163*12c85518Srobert // - parameter-declaration in a declarator of a function or function
7164*12c85518Srobert // template declaration whose declarator-id is qualified [...]
7165*12c85518Srobert // - parameter-declaration in a lambda-declarator [...]
7166*12c85518Srobert auto AllowImplicitTypename = ImplicitTypenameContext::No;
7167*12c85518Srobert if (DeclaratorCtx == DeclaratorContext::Member ||
7168*12c85518Srobert DeclaratorCtx == DeclaratorContext::LambdaExpr ||
7169*12c85518Srobert DeclaratorCtx == DeclaratorContext::RequiresExpr ||
7170*12c85518Srobert IsACXXFunctionDeclaration) {
7171*12c85518Srobert AllowImplicitTypename = ImplicitTypenameContext::Yes;
7172*12c85518Srobert }
7173*12c85518Srobert
7174e5dd7070Spatrick do {
7175e5dd7070Spatrick // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
7176e5dd7070Spatrick // before deciding this was a parameter-declaration-clause.
7177e5dd7070Spatrick if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
7178e5dd7070Spatrick break;
7179e5dd7070Spatrick
7180e5dd7070Spatrick // Parse the declaration-specifiers.
7181e5dd7070Spatrick // Just use the ParsingDeclaration "scope" of the declarator.
7182e5dd7070Spatrick DeclSpec DS(AttrFactory);
7183e5dd7070Spatrick
7184*12c85518Srobert ParsedAttributes ArgDeclAttrs(AttrFactory);
7185*12c85518Srobert ParsedAttributes ArgDeclSpecAttrs(AttrFactory);
7186*12c85518Srobert
7187*12c85518Srobert if (FirstArgAttrs.Range.isValid()) {
7188*12c85518Srobert // If the caller parsed attributes for the first argument, add them now.
7189*12c85518Srobert // Take them so that we only apply the attributes to the first parameter.
7190*12c85518Srobert // We have already started parsing the decl-specifier sequence, so don't
7191*12c85518Srobert // parse any parameter-declaration pieces that precede it.
7192*12c85518Srobert ArgDeclSpecAttrs.takeAllFrom(FirstArgAttrs);
7193*12c85518Srobert } else {
7194e5dd7070Spatrick // Parse any C++11 attributes.
7195*12c85518Srobert MaybeParseCXX11Attributes(ArgDeclAttrs);
7196e5dd7070Spatrick
7197e5dd7070Spatrick // Skip any Microsoft attributes before a param.
7198*12c85518Srobert MaybeParseMicrosoftAttributes(ArgDeclSpecAttrs);
7199*12c85518Srobert }
7200e5dd7070Spatrick
7201e5dd7070Spatrick SourceLocation DSStart = Tok.getLocation();
7202e5dd7070Spatrick
7203*12c85518Srobert ParseDeclarationSpecifiers(DS, /*TemplateInfo=*/ParsedTemplateInfo(),
7204*12c85518Srobert AS_none, DeclSpecContext::DSC_normal,
7205*12c85518Srobert /*LateAttrs=*/nullptr, AllowImplicitTypename);
7206*12c85518Srobert DS.takeAttributesFrom(ArgDeclSpecAttrs);
7207e5dd7070Spatrick
7208e5dd7070Spatrick // Parse the declarator. This is "PrototypeContext" or
7209e5dd7070Spatrick // "LambdaExprParameterContext", because we must accept either
7210e5dd7070Spatrick // 'declarator' or 'abstract-declarator' here.
7211*12c85518Srobert Declarator ParmDeclarator(DS, ArgDeclAttrs,
7212*12c85518Srobert DeclaratorCtx == DeclaratorContext::RequiresExpr
7213a9ac8606Spatrick ? DeclaratorContext::RequiresExpr
7214a9ac8606Spatrick : DeclaratorCtx == DeclaratorContext::LambdaExpr
7215a9ac8606Spatrick ? DeclaratorContext::LambdaExprParameter
7216a9ac8606Spatrick : DeclaratorContext::Prototype);
7217e5dd7070Spatrick ParseDeclarator(ParmDeclarator);
7218e5dd7070Spatrick
7219e5dd7070Spatrick // Parse GNU attributes, if present.
7220e5dd7070Spatrick MaybeParseGNUAttributes(ParmDeclarator);
7221*12c85518Srobert if (getLangOpts().HLSL)
7222*12c85518Srobert MaybeParseHLSLSemantics(DS.getAttributes());
7223e5dd7070Spatrick
7224e5dd7070Spatrick if (Tok.is(tok::kw_requires)) {
7225e5dd7070Spatrick // User tried to define a requires clause in a parameter declaration,
7226e5dd7070Spatrick // which is surely not a function declaration.
7227e5dd7070Spatrick // void f(int (*g)(int, int) requires true);
7228e5dd7070Spatrick Diag(Tok,
7229e5dd7070Spatrick diag::err_requires_clause_on_declarator_not_declaring_a_function);
7230e5dd7070Spatrick ConsumeToken();
7231e5dd7070Spatrick Actions.CorrectDelayedTyposInExpr(
7232e5dd7070Spatrick ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
7233e5dd7070Spatrick }
7234e5dd7070Spatrick
7235e5dd7070Spatrick // Remember this parsed parameter in ParamInfo.
7236e5dd7070Spatrick IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
7237e5dd7070Spatrick
7238e5dd7070Spatrick // DefArgToks is used when the parsing of default arguments needs
7239e5dd7070Spatrick // to be delayed.
7240e5dd7070Spatrick std::unique_ptr<CachedTokens> DefArgToks;
7241e5dd7070Spatrick
7242e5dd7070Spatrick // If no parameter was specified, verify that *something* was specified,
7243e5dd7070Spatrick // otherwise we have a missing type and identifier.
7244e5dd7070Spatrick if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr &&
7245e5dd7070Spatrick ParmDeclarator.getNumTypeObjects() == 0) {
7246e5dd7070Spatrick // Completely missing, emit error.
7247e5dd7070Spatrick Diag(DSStart, diag::err_missing_param);
7248e5dd7070Spatrick } else {
7249e5dd7070Spatrick // Otherwise, we have something. Add it and let semantic analysis try
7250e5dd7070Spatrick // to grok it and add the result to the ParamInfo we are building.
7251e5dd7070Spatrick
7252e5dd7070Spatrick // Last chance to recover from a misplaced ellipsis in an attempted
7253e5dd7070Spatrick // parameter pack declaration.
7254e5dd7070Spatrick if (Tok.is(tok::ellipsis) &&
7255e5dd7070Spatrick (NextToken().isNot(tok::r_paren) ||
7256e5dd7070Spatrick (!ParmDeclarator.getEllipsisLoc().isValid() &&
7257e5dd7070Spatrick !Actions.isUnexpandedParameterPackPermitted())) &&
7258e5dd7070Spatrick Actions.containsUnexpandedParameterPacks(ParmDeclarator))
7259e5dd7070Spatrick DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator);
7260e5dd7070Spatrick
7261ec727ea7Spatrick // Now we are at the point where declarator parsing is finished.
7262ec727ea7Spatrick //
7263ec727ea7Spatrick // Try to catch keywords in place of the identifier in a declarator, and
7264ec727ea7Spatrick // in particular the common case where:
7265ec727ea7Spatrick // 1 identifier comes at the end of the declarator
7266ec727ea7Spatrick // 2 if the identifier is dropped, the declarator is valid but anonymous
7267ec727ea7Spatrick // (no identifier)
7268ec727ea7Spatrick // 3 declarator parsing succeeds, and then we have a trailing keyword,
7269ec727ea7Spatrick // which is never valid in a param list (e.g. missing a ',')
7270ec727ea7Spatrick // And we can't handle this in ParseDeclarator because in general keywords
7271ec727ea7Spatrick // may be allowed to follow the declarator. (And in some cases there'd be
7272ec727ea7Spatrick // better recovery like inserting punctuation). ParseDeclarator is just
7273ec727ea7Spatrick // treating this as an anonymous parameter, and fortunately at this point
7274ec727ea7Spatrick // we've already almost done that.
7275ec727ea7Spatrick //
7276ec727ea7Spatrick // We care about case 1) where the declarator type should be known, and
7277ec727ea7Spatrick // the identifier should be null.
7278*12c85518Srobert if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName() &&
7279*12c85518Srobert Tok.isNot(tok::raw_identifier) && !Tok.isAnnotation() &&
7280*12c85518Srobert Tok.getIdentifierInfo() &&
7281ec727ea7Spatrick Tok.getIdentifierInfo()->isKeyword(getLangOpts())) {
7282ec727ea7Spatrick Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok);
7283ec727ea7Spatrick // Consume the keyword.
7284ec727ea7Spatrick ConsumeToken();
7285ec727ea7Spatrick }
7286e5dd7070Spatrick // Inform the actions module about the parameter declarator, so it gets
7287e5dd7070Spatrick // added to the current scope.
7288e5dd7070Spatrick Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);
7289e5dd7070Spatrick // Parse the default argument, if any. We parse the default
7290e5dd7070Spatrick // arguments in all dialects; the semantic analysis in
7291e5dd7070Spatrick // ActOnParamDefaultArgument will reject the default argument in
7292e5dd7070Spatrick // C.
7293e5dd7070Spatrick if (Tok.is(tok::equal)) {
7294e5dd7070Spatrick SourceLocation EqualLoc = Tok.getLocation();
7295e5dd7070Spatrick
7296e5dd7070Spatrick // Parse the default argument
7297a9ac8606Spatrick if (DeclaratorCtx == DeclaratorContext::Member) {
7298e5dd7070Spatrick // If we're inside a class definition, cache the tokens
7299e5dd7070Spatrick // corresponding to the default argument. We'll actually parse
7300e5dd7070Spatrick // them when we see the end of the class definition.
7301e5dd7070Spatrick DefArgToks.reset(new CachedTokens);
7302e5dd7070Spatrick
7303e5dd7070Spatrick SourceLocation ArgStartLoc = NextToken().getLocation();
7304e5dd7070Spatrick if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
7305e5dd7070Spatrick DefArgToks.reset();
7306e5dd7070Spatrick Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
7307e5dd7070Spatrick } else {
7308e5dd7070Spatrick Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
7309e5dd7070Spatrick ArgStartLoc);
7310e5dd7070Spatrick }
7311e5dd7070Spatrick } else {
7312e5dd7070Spatrick // Consume the '='.
7313e5dd7070Spatrick ConsumeToken();
7314e5dd7070Spatrick
7315e5dd7070Spatrick // The argument isn't actually potentially evaluated unless it is
7316e5dd7070Spatrick // used.
7317e5dd7070Spatrick EnterExpressionEvaluationContext Eval(
7318e5dd7070Spatrick Actions,
7319e5dd7070Spatrick Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed,
7320e5dd7070Spatrick Param);
7321e5dd7070Spatrick
7322e5dd7070Spatrick ExprResult DefArgResult;
7323e5dd7070Spatrick if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
7324e5dd7070Spatrick Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
7325e5dd7070Spatrick DefArgResult = ParseBraceInitializer();
7326*12c85518Srobert } else {
7327*12c85518Srobert if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {
7328*12c85518Srobert Diag(Tok, diag::err_stmt_expr_in_default_arg) << 0;
7329*12c85518Srobert Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
7330*12c85518Srobert // Skip the statement expression and continue parsing
7331*12c85518Srobert SkipUntil(tok::comma, StopBeforeMatch);
7332*12c85518Srobert continue;
7333*12c85518Srobert }
7334e5dd7070Spatrick DefArgResult = ParseAssignmentExpression();
7335*12c85518Srobert }
7336e5dd7070Spatrick DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
7337e5dd7070Spatrick if (DefArgResult.isInvalid()) {
7338e5dd7070Spatrick Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
7339e5dd7070Spatrick SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
7340e5dd7070Spatrick } else {
7341e5dd7070Spatrick // Inform the actions module about the default argument
7342e5dd7070Spatrick Actions.ActOnParamDefaultArgument(Param, EqualLoc,
7343e5dd7070Spatrick DefArgResult.get());
7344e5dd7070Spatrick }
7345e5dd7070Spatrick }
7346e5dd7070Spatrick }
7347e5dd7070Spatrick
7348e5dd7070Spatrick ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
7349e5dd7070Spatrick ParmDeclarator.getIdentifierLoc(),
7350e5dd7070Spatrick Param, std::move(DefArgToks)));
7351e5dd7070Spatrick }
7352e5dd7070Spatrick
7353e5dd7070Spatrick if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
7354e5dd7070Spatrick if (!getLangOpts().CPlusPlus) {
7355e5dd7070Spatrick // We have ellipsis without a preceding ',', which is ill-formed
7356e5dd7070Spatrick // in C. Complain and provide the fix.
7357e5dd7070Spatrick Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
7358e5dd7070Spatrick << FixItHint::CreateInsertion(EllipsisLoc, ", ");
7359e5dd7070Spatrick } else if (ParmDeclarator.getEllipsisLoc().isValid() ||
7360e5dd7070Spatrick Actions.containsUnexpandedParameterPacks(ParmDeclarator)) {
7361e5dd7070Spatrick // It looks like this was supposed to be a parameter pack. Warn and
7362e5dd7070Spatrick // point out where the ellipsis should have gone.
7363e5dd7070Spatrick SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc();
7364e5dd7070Spatrick Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg)
7365e5dd7070Spatrick << ParmEllipsis.isValid() << ParmEllipsis;
7366e5dd7070Spatrick if (ParmEllipsis.isValid()) {
7367e5dd7070Spatrick Diag(ParmEllipsis,
7368e5dd7070Spatrick diag::note_misplaced_ellipsis_vararg_existing_ellipsis);
7369e5dd7070Spatrick } else {
7370e5dd7070Spatrick Diag(ParmDeclarator.getIdentifierLoc(),
7371e5dd7070Spatrick diag::note_misplaced_ellipsis_vararg_add_ellipsis)
7372e5dd7070Spatrick << FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(),
7373e5dd7070Spatrick "...")
7374e5dd7070Spatrick << !ParmDeclarator.hasName();
7375e5dd7070Spatrick }
7376e5dd7070Spatrick Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma)
7377e5dd7070Spatrick << FixItHint::CreateInsertion(EllipsisLoc, ", ");
7378e5dd7070Spatrick }
7379e5dd7070Spatrick
7380e5dd7070Spatrick // We can't have any more parameters after an ellipsis.
7381e5dd7070Spatrick break;
7382e5dd7070Spatrick }
7383e5dd7070Spatrick
7384e5dd7070Spatrick // If the next token is a comma, consume it and keep reading arguments.
7385e5dd7070Spatrick } while (TryConsumeToken(tok::comma));
7386e5dd7070Spatrick }
7387e5dd7070Spatrick
7388e5dd7070Spatrick /// [C90] direct-declarator '[' constant-expression[opt] ']'
7389e5dd7070Spatrick /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
7390e5dd7070Spatrick /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
7391e5dd7070Spatrick /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
7392e5dd7070Spatrick /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
7393e5dd7070Spatrick /// [C++11] direct-declarator '[' constant-expression[opt] ']'
7394e5dd7070Spatrick /// attribute-specifier-seq[opt]
ParseBracketDeclarator(Declarator & D)7395e5dd7070Spatrick void Parser::ParseBracketDeclarator(Declarator &D) {
7396e5dd7070Spatrick if (CheckProhibitedCXX11Attribute())
7397e5dd7070Spatrick return;
7398e5dd7070Spatrick
7399e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_square);
7400e5dd7070Spatrick T.consumeOpen();
7401e5dd7070Spatrick
7402e5dd7070Spatrick // C array syntax has many features, but by-far the most common is [] and [4].
7403e5dd7070Spatrick // This code does a fast path to handle some of the most obvious cases.
7404e5dd7070Spatrick if (Tok.getKind() == tok::r_square) {
7405e5dd7070Spatrick T.consumeClose();
7406e5dd7070Spatrick ParsedAttributes attrs(AttrFactory);
7407e5dd7070Spatrick MaybeParseCXX11Attributes(attrs);
7408e5dd7070Spatrick
7409e5dd7070Spatrick // Remember that we parsed the empty array type.
7410e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
7411e5dd7070Spatrick T.getOpenLocation(),
7412e5dd7070Spatrick T.getCloseLocation()),
7413e5dd7070Spatrick std::move(attrs), T.getCloseLocation());
7414e5dd7070Spatrick return;
7415e5dd7070Spatrick } else if (Tok.getKind() == tok::numeric_constant &&
7416e5dd7070Spatrick GetLookAheadToken(1).is(tok::r_square)) {
7417e5dd7070Spatrick // [4] is very common. Parse the numeric constant expression.
7418e5dd7070Spatrick ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope()));
7419e5dd7070Spatrick ConsumeToken();
7420e5dd7070Spatrick
7421e5dd7070Spatrick T.consumeClose();
7422e5dd7070Spatrick ParsedAttributes attrs(AttrFactory);
7423e5dd7070Spatrick MaybeParseCXX11Attributes(attrs);
7424e5dd7070Spatrick
7425e5dd7070Spatrick // Remember that we parsed a array type, and remember its features.
7426e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(),
7427e5dd7070Spatrick T.getOpenLocation(),
7428e5dd7070Spatrick T.getCloseLocation()),
7429e5dd7070Spatrick std::move(attrs), T.getCloseLocation());
7430e5dd7070Spatrick return;
7431e5dd7070Spatrick } else if (Tok.getKind() == tok::code_completion) {
7432a9ac8606Spatrick cutOffParsing();
7433e5dd7070Spatrick Actions.CodeCompleteBracketDeclarator(getCurScope());
7434a9ac8606Spatrick return;
7435e5dd7070Spatrick }
7436e5dd7070Spatrick
7437e5dd7070Spatrick // If valid, this location is the position where we read the 'static' keyword.
7438e5dd7070Spatrick SourceLocation StaticLoc;
7439e5dd7070Spatrick TryConsumeToken(tok::kw_static, StaticLoc);
7440e5dd7070Spatrick
7441e5dd7070Spatrick // If there is a type-qualifier-list, read it now.
7442e5dd7070Spatrick // Type qualifiers in an array subscript are a C99 feature.
7443e5dd7070Spatrick DeclSpec DS(AttrFactory);
7444e5dd7070Spatrick ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed);
7445e5dd7070Spatrick
7446e5dd7070Spatrick // If we haven't already read 'static', check to see if there is one after the
7447e5dd7070Spatrick // type-qualifier-list.
7448e5dd7070Spatrick if (!StaticLoc.isValid())
7449e5dd7070Spatrick TryConsumeToken(tok::kw_static, StaticLoc);
7450e5dd7070Spatrick
7451e5dd7070Spatrick // Handle "direct-declarator [ type-qual-list[opt] * ]".
7452e5dd7070Spatrick bool isStar = false;
7453e5dd7070Spatrick ExprResult NumElements;
7454e5dd7070Spatrick
7455e5dd7070Spatrick // Handle the case where we have '[*]' as the array size. However, a leading
7456e5dd7070Spatrick // star could be the start of an expression, for example 'X[*p + 4]'. Verify
7457e5dd7070Spatrick // the token after the star is a ']'. Since stars in arrays are
7458e5dd7070Spatrick // infrequent, use of lookahead is not costly here.
7459e5dd7070Spatrick if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) {
7460e5dd7070Spatrick ConsumeToken(); // Eat the '*'.
7461e5dd7070Spatrick
7462e5dd7070Spatrick if (StaticLoc.isValid()) {
7463e5dd7070Spatrick Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
7464e5dd7070Spatrick StaticLoc = SourceLocation(); // Drop the static.
7465e5dd7070Spatrick }
7466e5dd7070Spatrick isStar = true;
7467e5dd7070Spatrick } else if (Tok.isNot(tok::r_square)) {
7468e5dd7070Spatrick // Note, in C89, this production uses the constant-expr production instead
7469e5dd7070Spatrick // of assignment-expr. The only difference is that assignment-expr allows
7470e5dd7070Spatrick // things like '=' and '*='. Sema rejects these in C89 mode because they
7471e5dd7070Spatrick // are not i-c-e's, so we don't need to distinguish between the two here.
7472e5dd7070Spatrick
7473e5dd7070Spatrick // Parse the constant-expression or assignment-expression now (depending
7474e5dd7070Spatrick // on dialect).
7475e5dd7070Spatrick if (getLangOpts().CPlusPlus) {
7476e5dd7070Spatrick NumElements = ParseConstantExpression();
7477e5dd7070Spatrick } else {
7478e5dd7070Spatrick EnterExpressionEvaluationContext Unevaluated(
7479e5dd7070Spatrick Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
7480e5dd7070Spatrick NumElements =
7481e5dd7070Spatrick Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
7482e5dd7070Spatrick }
7483e5dd7070Spatrick } else {
7484e5dd7070Spatrick if (StaticLoc.isValid()) {
7485e5dd7070Spatrick Diag(StaticLoc, diag::err_unspecified_size_with_static);
7486e5dd7070Spatrick StaticLoc = SourceLocation(); // Drop the static.
7487e5dd7070Spatrick }
7488e5dd7070Spatrick }
7489e5dd7070Spatrick
7490e5dd7070Spatrick // If there was an error parsing the assignment-expression, recover.
7491e5dd7070Spatrick if (NumElements.isInvalid()) {
7492e5dd7070Spatrick D.setInvalidType(true);
7493e5dd7070Spatrick // If the expression was invalid, skip it.
7494e5dd7070Spatrick SkipUntil(tok::r_square, StopAtSemi);
7495e5dd7070Spatrick return;
7496e5dd7070Spatrick }
7497e5dd7070Spatrick
7498e5dd7070Spatrick T.consumeClose();
7499e5dd7070Spatrick
7500e5dd7070Spatrick MaybeParseCXX11Attributes(DS.getAttributes());
7501e5dd7070Spatrick
7502e5dd7070Spatrick // Remember that we parsed a array type, and remember its features.
7503e5dd7070Spatrick D.AddTypeInfo(
7504e5dd7070Spatrick DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(),
7505e5dd7070Spatrick isStar, NumElements.get(), T.getOpenLocation(),
7506e5dd7070Spatrick T.getCloseLocation()),
7507e5dd7070Spatrick std::move(DS.getAttributes()), T.getCloseLocation());
7508e5dd7070Spatrick }
7509e5dd7070Spatrick
7510e5dd7070Spatrick /// Diagnose brackets before an identifier.
ParseMisplacedBracketDeclarator(Declarator & D)7511e5dd7070Spatrick void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
7512e5dd7070Spatrick assert(Tok.is(tok::l_square) && "Missing opening bracket");
7513e5dd7070Spatrick assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier");
7514e5dd7070Spatrick
7515e5dd7070Spatrick SourceLocation StartBracketLoc = Tok.getLocation();
7516*12c85518Srobert Declarator TempDeclarator(D.getDeclSpec(), ParsedAttributesView::none(),
7517*12c85518Srobert D.getContext());
7518e5dd7070Spatrick
7519e5dd7070Spatrick while (Tok.is(tok::l_square)) {
7520e5dd7070Spatrick ParseBracketDeclarator(TempDeclarator);
7521e5dd7070Spatrick }
7522e5dd7070Spatrick
7523e5dd7070Spatrick // Stuff the location of the start of the brackets into the Declarator.
7524e5dd7070Spatrick // The diagnostics from ParseDirectDeclarator will make more sense if
7525e5dd7070Spatrick // they use this location instead.
7526e5dd7070Spatrick if (Tok.is(tok::semi))
7527e5dd7070Spatrick D.getName().EndLocation = StartBracketLoc;
7528e5dd7070Spatrick
7529e5dd7070Spatrick SourceLocation SuggestParenLoc = Tok.getLocation();
7530e5dd7070Spatrick
7531e5dd7070Spatrick // Now that the brackets are removed, try parsing the declarator again.
7532e5dd7070Spatrick ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
7533e5dd7070Spatrick
7534e5dd7070Spatrick // Something went wrong parsing the brackets, in which case,
7535e5dd7070Spatrick // ParseBracketDeclarator has emitted an error, and we don't need to emit
7536e5dd7070Spatrick // one here.
7537e5dd7070Spatrick if (TempDeclarator.getNumTypeObjects() == 0)
7538e5dd7070Spatrick return;
7539e5dd7070Spatrick
7540e5dd7070Spatrick // Determine if parens will need to be suggested in the diagnostic.
7541e5dd7070Spatrick bool NeedParens = false;
7542e5dd7070Spatrick if (D.getNumTypeObjects() != 0) {
7543e5dd7070Spatrick switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) {
7544e5dd7070Spatrick case DeclaratorChunk::Pointer:
7545e5dd7070Spatrick case DeclaratorChunk::Reference:
7546e5dd7070Spatrick case DeclaratorChunk::BlockPointer:
7547e5dd7070Spatrick case DeclaratorChunk::MemberPointer:
7548e5dd7070Spatrick case DeclaratorChunk::Pipe:
7549e5dd7070Spatrick NeedParens = true;
7550e5dd7070Spatrick break;
7551e5dd7070Spatrick case DeclaratorChunk::Array:
7552e5dd7070Spatrick case DeclaratorChunk::Function:
7553e5dd7070Spatrick case DeclaratorChunk::Paren:
7554e5dd7070Spatrick break;
7555e5dd7070Spatrick }
7556e5dd7070Spatrick }
7557e5dd7070Spatrick
7558e5dd7070Spatrick if (NeedParens) {
7559e5dd7070Spatrick // Create a DeclaratorChunk for the inserted parens.
7560e5dd7070Spatrick SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
7561e5dd7070Spatrick D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc),
7562e5dd7070Spatrick SourceLocation());
7563e5dd7070Spatrick }
7564e5dd7070Spatrick
7565e5dd7070Spatrick // Adding back the bracket info to the end of the Declarator.
7566e5dd7070Spatrick for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {
7567e5dd7070Spatrick const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);
7568e5dd7070Spatrick D.AddTypeInfo(Chunk, SourceLocation());
7569e5dd7070Spatrick }
7570e5dd7070Spatrick
7571e5dd7070Spatrick // The missing identifier would have been diagnosed in ParseDirectDeclarator.
7572e5dd7070Spatrick // If parentheses are required, always suggest them.
7573e5dd7070Spatrick if (!D.getIdentifier() && !NeedParens)
7574e5dd7070Spatrick return;
7575e5dd7070Spatrick
7576e5dd7070Spatrick SourceLocation EndBracketLoc = TempDeclarator.getEndLoc();
7577e5dd7070Spatrick
7578e5dd7070Spatrick // Generate the move bracket error message.
7579e5dd7070Spatrick SourceRange BracketRange(StartBracketLoc, EndBracketLoc);
7580e5dd7070Spatrick SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
7581e5dd7070Spatrick
7582e5dd7070Spatrick if (NeedParens) {
7583e5dd7070Spatrick Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
7584e5dd7070Spatrick << getLangOpts().CPlusPlus
7585e5dd7070Spatrick << FixItHint::CreateInsertion(SuggestParenLoc, "(")
7586e5dd7070Spatrick << FixItHint::CreateInsertion(EndLoc, ")")
7587e5dd7070Spatrick << FixItHint::CreateInsertionFromRange(
7588e5dd7070Spatrick EndLoc, CharSourceRange(BracketRange, true))
7589e5dd7070Spatrick << FixItHint::CreateRemoval(BracketRange);
7590e5dd7070Spatrick } else {
7591e5dd7070Spatrick Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
7592e5dd7070Spatrick << getLangOpts().CPlusPlus
7593e5dd7070Spatrick << FixItHint::CreateInsertionFromRange(
7594e5dd7070Spatrick EndLoc, CharSourceRange(BracketRange, true))
7595e5dd7070Spatrick << FixItHint::CreateRemoval(BracketRange);
7596e5dd7070Spatrick }
7597e5dd7070Spatrick }
7598e5dd7070Spatrick
7599e5dd7070Spatrick /// [GNU] typeof-specifier:
7600e5dd7070Spatrick /// typeof ( expressions )
7601e5dd7070Spatrick /// typeof ( type-name )
7602e5dd7070Spatrick /// [GNU/C++] typeof unary-expression
7603*12c85518Srobert /// [C2x] typeof-specifier:
7604*12c85518Srobert /// typeof '(' typeof-specifier-argument ')'
7605*12c85518Srobert /// typeof_unqual '(' typeof-specifier-argument ')'
7606*12c85518Srobert ///
7607*12c85518Srobert /// typeof-specifier-argument:
7608*12c85518Srobert /// expression
7609*12c85518Srobert /// type-name
7610e5dd7070Spatrick ///
ParseTypeofSpecifier(DeclSpec & DS)7611e5dd7070Spatrick void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
7612*12c85518Srobert assert(Tok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&
7613*12c85518Srobert "Not a typeof specifier");
7614*12c85518Srobert
7615*12c85518Srobert bool IsUnqual = Tok.is(tok::kw_typeof_unqual);
7616*12c85518Srobert const IdentifierInfo *II = Tok.getIdentifierInfo();
7617*12c85518Srobert if (getLangOpts().C2x && !II->getName().startswith("__"))
7618*12c85518Srobert Diag(Tok.getLocation(), diag::warn_c2x_compat_typeof_type_specifier)
7619*12c85518Srobert << IsUnqual;
7620*12c85518Srobert
7621e5dd7070Spatrick Token OpTok = Tok;
7622e5dd7070Spatrick SourceLocation StartLoc = ConsumeToken();
7623*12c85518Srobert bool HasParens = Tok.is(tok::l_paren);
7624e5dd7070Spatrick
7625e5dd7070Spatrick EnterExpressionEvaluationContext Unevaluated(
7626e5dd7070Spatrick Actions, Sema::ExpressionEvaluationContext::Unevaluated,
7627e5dd7070Spatrick Sema::ReuseLambdaContextDecl);
7628e5dd7070Spatrick
7629e5dd7070Spatrick bool isCastExpr;
7630e5dd7070Spatrick ParsedType CastTy;
7631e5dd7070Spatrick SourceRange CastRange;
7632e5dd7070Spatrick ExprResult Operand = Actions.CorrectDelayedTyposInExpr(
7633e5dd7070Spatrick ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));
7634*12c85518Srobert if (HasParens)
7635*12c85518Srobert DS.setTypeArgumentRange(CastRange);
7636e5dd7070Spatrick
7637e5dd7070Spatrick if (CastRange.getEnd().isInvalid())
7638e5dd7070Spatrick // FIXME: Not accurate, the range gets one token more than it should.
7639e5dd7070Spatrick DS.SetRangeEnd(Tok.getLocation());
7640e5dd7070Spatrick else
7641e5dd7070Spatrick DS.SetRangeEnd(CastRange.getEnd());
7642e5dd7070Spatrick
7643e5dd7070Spatrick if (isCastExpr) {
7644e5dd7070Spatrick if (!CastTy) {
7645e5dd7070Spatrick DS.SetTypeSpecError();
7646e5dd7070Spatrick return;
7647e5dd7070Spatrick }
7648e5dd7070Spatrick
7649e5dd7070Spatrick const char *PrevSpec = nullptr;
7650e5dd7070Spatrick unsigned DiagID;
7651e5dd7070Spatrick // Check for duplicate type specifiers (e.g. "int typeof(int)").
7652*12c85518Srobert if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualType
7653*12c85518Srobert : DeclSpec::TST_typeofType,
7654*12c85518Srobert StartLoc, PrevSpec,
7655e5dd7070Spatrick DiagID, CastTy,
7656e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
7657e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
7658e5dd7070Spatrick return;
7659e5dd7070Spatrick }
7660e5dd7070Spatrick
7661e5dd7070Spatrick // If we get here, the operand to the typeof was an expression.
7662e5dd7070Spatrick if (Operand.isInvalid()) {
7663e5dd7070Spatrick DS.SetTypeSpecError();
7664e5dd7070Spatrick return;
7665e5dd7070Spatrick }
7666e5dd7070Spatrick
7667e5dd7070Spatrick // We might need to transform the operand if it is potentially evaluated.
7668e5dd7070Spatrick Operand = Actions.HandleExprEvaluationContextForTypeof(Operand.get());
7669e5dd7070Spatrick if (Operand.isInvalid()) {
7670e5dd7070Spatrick DS.SetTypeSpecError();
7671e5dd7070Spatrick return;
7672e5dd7070Spatrick }
7673e5dd7070Spatrick
7674e5dd7070Spatrick const char *PrevSpec = nullptr;
7675e5dd7070Spatrick unsigned DiagID;
7676e5dd7070Spatrick // Check for duplicate type specifiers (e.g. "int typeof(int)").
7677*12c85518Srobert if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualExpr
7678*12c85518Srobert : DeclSpec::TST_typeofExpr,
7679*12c85518Srobert StartLoc, PrevSpec,
7680e5dd7070Spatrick DiagID, Operand.get(),
7681e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
7682e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
7683e5dd7070Spatrick }
7684e5dd7070Spatrick
7685e5dd7070Spatrick /// [C11] atomic-specifier:
7686e5dd7070Spatrick /// _Atomic ( type-name )
7687e5dd7070Spatrick ///
ParseAtomicSpecifier(DeclSpec & DS)7688e5dd7070Spatrick void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
7689e5dd7070Spatrick assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) &&
7690e5dd7070Spatrick "Not an atomic specifier");
7691e5dd7070Spatrick
7692e5dd7070Spatrick SourceLocation StartLoc = ConsumeToken();
7693e5dd7070Spatrick BalancedDelimiterTracker T(*this, tok::l_paren);
7694e5dd7070Spatrick if (T.consumeOpen())
7695e5dd7070Spatrick return;
7696e5dd7070Spatrick
7697e5dd7070Spatrick TypeResult Result = ParseTypeName();
7698e5dd7070Spatrick if (Result.isInvalid()) {
7699e5dd7070Spatrick SkipUntil(tok::r_paren, StopAtSemi);
7700e5dd7070Spatrick return;
7701e5dd7070Spatrick }
7702e5dd7070Spatrick
7703e5dd7070Spatrick // Match the ')'
7704e5dd7070Spatrick T.consumeClose();
7705e5dd7070Spatrick
7706e5dd7070Spatrick if (T.getCloseLocation().isInvalid())
7707e5dd7070Spatrick return;
7708e5dd7070Spatrick
7709*12c85518Srobert DS.setTypeArgumentRange(T.getRange());
7710e5dd7070Spatrick DS.SetRangeEnd(T.getCloseLocation());
7711e5dd7070Spatrick
7712e5dd7070Spatrick const char *PrevSpec = nullptr;
7713e5dd7070Spatrick unsigned DiagID;
7714e5dd7070Spatrick if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
7715e5dd7070Spatrick DiagID, Result.get(),
7716e5dd7070Spatrick Actions.getASTContext().getPrintingPolicy()))
7717e5dd7070Spatrick Diag(StartLoc, DiagID) << PrevSpec;
7718e5dd7070Spatrick }
7719e5dd7070Spatrick
7720e5dd7070Spatrick /// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
7721e5dd7070Spatrick /// from TryAltiVecVectorToken.
TryAltiVecVectorTokenOutOfLine()7722e5dd7070Spatrick bool Parser::TryAltiVecVectorTokenOutOfLine() {
7723e5dd7070Spatrick Token Next = NextToken();
7724e5dd7070Spatrick switch (Next.getKind()) {
7725e5dd7070Spatrick default: return false;
7726e5dd7070Spatrick case tok::kw_short:
7727e5dd7070Spatrick case tok::kw_long:
7728e5dd7070Spatrick case tok::kw_signed:
7729e5dd7070Spatrick case tok::kw_unsigned:
7730e5dd7070Spatrick case tok::kw_void:
7731e5dd7070Spatrick case tok::kw_char:
7732e5dd7070Spatrick case tok::kw_int:
7733e5dd7070Spatrick case tok::kw_float:
7734e5dd7070Spatrick case tok::kw_double:
7735e5dd7070Spatrick case tok::kw_bool:
7736a9ac8606Spatrick case tok::kw__Bool:
7737e5dd7070Spatrick case tok::kw___bool:
7738e5dd7070Spatrick case tok::kw___pixel:
7739e5dd7070Spatrick Tok.setKind(tok::kw___vector);
7740e5dd7070Spatrick return true;
7741e5dd7070Spatrick case tok::identifier:
7742e5dd7070Spatrick if (Next.getIdentifierInfo() == Ident_pixel) {
7743e5dd7070Spatrick Tok.setKind(tok::kw___vector);
7744e5dd7070Spatrick return true;
7745e5dd7070Spatrick }
7746a9ac8606Spatrick if (Next.getIdentifierInfo() == Ident_bool ||
7747a9ac8606Spatrick Next.getIdentifierInfo() == Ident_Bool) {
7748e5dd7070Spatrick Tok.setKind(tok::kw___vector);
7749e5dd7070Spatrick return true;
7750e5dd7070Spatrick }
7751e5dd7070Spatrick return false;
7752e5dd7070Spatrick }
7753e5dd7070Spatrick }
7754e5dd7070Spatrick
TryAltiVecTokenOutOfLine(DeclSpec & DS,SourceLocation Loc,const char * & PrevSpec,unsigned & DiagID,bool & isInvalid)7755e5dd7070Spatrick bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
7756e5dd7070Spatrick const char *&PrevSpec, unsigned &DiagID,
7757e5dd7070Spatrick bool &isInvalid) {
7758e5dd7070Spatrick const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
7759e5dd7070Spatrick if (Tok.getIdentifierInfo() == Ident_vector) {
7760e5dd7070Spatrick Token Next = NextToken();
7761e5dd7070Spatrick switch (Next.getKind()) {
7762e5dd7070Spatrick case tok::kw_short:
7763e5dd7070Spatrick case tok::kw_long:
7764e5dd7070Spatrick case tok::kw_signed:
7765e5dd7070Spatrick case tok::kw_unsigned:
7766e5dd7070Spatrick case tok::kw_void:
7767e5dd7070Spatrick case tok::kw_char:
7768e5dd7070Spatrick case tok::kw_int:
7769e5dd7070Spatrick case tok::kw_float:
7770e5dd7070Spatrick case tok::kw_double:
7771e5dd7070Spatrick case tok::kw_bool:
7772a9ac8606Spatrick case tok::kw__Bool:
7773e5dd7070Spatrick case tok::kw___bool:
7774e5dd7070Spatrick case tok::kw___pixel:
7775e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
7776e5dd7070Spatrick return true;
7777e5dd7070Spatrick case tok::identifier:
7778e5dd7070Spatrick if (Next.getIdentifierInfo() == Ident_pixel) {
7779e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
7780e5dd7070Spatrick return true;
7781e5dd7070Spatrick }
7782a9ac8606Spatrick if (Next.getIdentifierInfo() == Ident_bool ||
7783a9ac8606Spatrick Next.getIdentifierInfo() == Ident_Bool) {
7784a9ac8606Spatrick isInvalid =
7785a9ac8606Spatrick DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
7786e5dd7070Spatrick return true;
7787e5dd7070Spatrick }
7788e5dd7070Spatrick break;
7789e5dd7070Spatrick default:
7790e5dd7070Spatrick break;
7791e5dd7070Spatrick }
7792e5dd7070Spatrick } else if ((Tok.getIdentifierInfo() == Ident_pixel) &&
7793e5dd7070Spatrick DS.isTypeAltiVecVector()) {
7794e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
7795e5dd7070Spatrick return true;
7796e5dd7070Spatrick } else if ((Tok.getIdentifierInfo() == Ident_bool) &&
7797e5dd7070Spatrick DS.isTypeAltiVecVector()) {
7798e5dd7070Spatrick isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
7799e5dd7070Spatrick return true;
7800e5dd7070Spatrick }
7801e5dd7070Spatrick return false;
7802e5dd7070Spatrick }
7803*12c85518Srobert
DiagnoseBitIntUse(const Token & Tok)7804*12c85518Srobert void Parser::DiagnoseBitIntUse(const Token &Tok) {
7805*12c85518Srobert // If the token is for _ExtInt, diagnose it as being deprecated. Otherwise,
7806*12c85518Srobert // the token is about _BitInt and gets (potentially) diagnosed as use of an
7807*12c85518Srobert // extension.
7808*12c85518Srobert assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) &&
7809*12c85518Srobert "expected either an _ExtInt or _BitInt token!");
7810*12c85518Srobert
7811*12c85518Srobert SourceLocation Loc = Tok.getLocation();
7812*12c85518Srobert if (Tok.is(tok::kw__ExtInt)) {
7813*12c85518Srobert Diag(Loc, diag::warn_ext_int_deprecated)
7814*12c85518Srobert << FixItHint::CreateReplacement(Loc, "_BitInt");
7815*12c85518Srobert } else {
7816*12c85518Srobert // In C2x mode, diagnose that the use is not compatible with pre-C2x modes.
7817*12c85518Srobert // Otherwise, diagnose that the use is a Clang extension.
7818*12c85518Srobert if (getLangOpts().C2x)
7819*12c85518Srobert Diag(Loc, diag::warn_c17_compat_bit_int);
7820*12c85518Srobert else
7821*12c85518Srobert Diag(Loc, diag::ext_bit_int) << getLangOpts().CPlusPlus;
7822*12c85518Srobert }
7823*12c85518Srobert }
7824