10b57cec5SDimitry Andric //===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the Declaration portions of the Parser interfaces.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
140b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
150b57cec5SDimitry Andric #include "clang/AST/PrettyDeclStackTrace.h"
160b57cec5SDimitry Andric #include "clang/Basic/AddressSpaces.h"
1781ad6265SDimitry Andric #include "clang/Basic/AttributeCommonInfo.h"
180b57cec5SDimitry Andric #include "clang/Basic/Attributes.h"
190b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
200b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
215f757f3fSDimitry Andric #include "clang/Basic/TokenKinds.h"
220b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h"
2381ad6265SDimitry Andric #include "clang/Parse/Parser.h"
2481ad6265SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h"
2506c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h"
260b57cec5SDimitry Andric #include "clang/Sema/Lookup.h"
270b57cec5SDimitry Andric #include "clang/Sema/ParsedTemplate.h"
280b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
29*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCUDA.h"
30*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h"
31e8d8bef9SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
32*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h"
33*0fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenMP.h"
340b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
350b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
360b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
37bdd1243dSDimitry Andric #include <optional>
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric using namespace clang;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
420b57cec5SDimitry Andric // C99 6.7: Declarations.
430b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric /// ParseTypeName
460b57cec5SDimitry Andric /// type-name: [C99 6.7.6]
470b57cec5SDimitry Andric /// specifier-qualifier-list abstract-declarator[opt]
480b57cec5SDimitry Andric ///
490b57cec5SDimitry Andric /// Called type-id in C++.
ParseTypeName(SourceRange * Range,DeclaratorContext Context,AccessSpecifier AS,Decl ** OwnedType,ParsedAttributes * Attrs)5081ad6265SDimitry Andric TypeResult Parser::ParseTypeName(SourceRange *Range, DeclaratorContext Context,
5181ad6265SDimitry Andric AccessSpecifier AS, Decl **OwnedType,
520b57cec5SDimitry Andric ParsedAttributes *Attrs) {
530b57cec5SDimitry Andric DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
540b57cec5SDimitry Andric if (DSC == DeclSpecContext::DSC_normal)
550b57cec5SDimitry Andric DSC = DeclSpecContext::DSC_type_specifier;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric // Parse the common declaration-specifiers piece.
580b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
590b57cec5SDimitry Andric if (Attrs)
600b57cec5SDimitry Andric DS.addAttributes(*Attrs);
610b57cec5SDimitry Andric ParseSpecifierQualifierList(DS, AS, DSC);
620b57cec5SDimitry Andric if (OwnedType)
630b57cec5SDimitry Andric *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;
640b57cec5SDimitry Andric
6506c3fb27SDimitry Andric // Move declspec attributes to ParsedAttributes
6606c3fb27SDimitry Andric if (Attrs) {
6706c3fb27SDimitry Andric llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;
6806c3fb27SDimitry Andric for (ParsedAttr &AL : DS.getAttributes()) {
6906c3fb27SDimitry Andric if (AL.isDeclspecAttribute())
7006c3fb27SDimitry Andric ToBeMoved.push_back(&AL);
7106c3fb27SDimitry Andric }
7206c3fb27SDimitry Andric
7306c3fb27SDimitry Andric for (ParsedAttr *AL : ToBeMoved)
7406c3fb27SDimitry Andric Attrs->takeOneFrom(DS.getAttributes(), AL);
7506c3fb27SDimitry Andric }
7606c3fb27SDimitry Andric
770b57cec5SDimitry Andric // Parse the abstract-declarator, if present.
7881ad6265SDimitry Andric Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
790b57cec5SDimitry Andric ParseDeclarator(DeclaratorInfo);
800b57cec5SDimitry Andric if (Range)
810b57cec5SDimitry Andric *Range = DeclaratorInfo.getSourceRange();
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric if (DeclaratorInfo.isInvalidType())
840b57cec5SDimitry Andric return true;
850b57cec5SDimitry Andric
867a6dacacSDimitry Andric return Actions.ActOnTypeName(DeclaratorInfo);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric /// Normalizes an attribute name by dropping prefixed and suffixed __.
normalizeAttrName(StringRef Name)900b57cec5SDimitry Andric static StringRef normalizeAttrName(StringRef Name) {
915f757f3fSDimitry Andric if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))
920b57cec5SDimitry Andric return Name.drop_front(2).drop_back(2);
930b57cec5SDimitry Andric return Name;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric
96*0fca6ea1SDimitry Andric /// returns true iff attribute is annotated with `LateAttrParseExperimentalExt`
97*0fca6ea1SDimitry Andric /// in `Attr.td`.
IsAttributeLateParsedExperimentalExt(const IdentifierInfo & II)98*0fca6ea1SDimitry Andric static bool IsAttributeLateParsedExperimentalExt(const IdentifierInfo &II) {
99*0fca6ea1SDimitry Andric #define CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST
100*0fca6ea1SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
101*0fca6ea1SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
102*0fca6ea1SDimitry Andric .Default(false);
103*0fca6ea1SDimitry Andric #undef CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST
104*0fca6ea1SDimitry Andric }
105*0fca6ea1SDimitry Andric
106*0fca6ea1SDimitry Andric /// returns true iff attribute is annotated with `LateAttrParseStandard` in
107*0fca6ea1SDimitry Andric /// `Attr.td`.
IsAttributeLateParsedStandard(const IdentifierInfo & II)108*0fca6ea1SDimitry Andric static bool IsAttributeLateParsedStandard(const IdentifierInfo &II) {
1090b57cec5SDimitry Andric #define CLANG_ATTR_LATE_PARSED_LIST
1100b57cec5SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
1110b57cec5SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
1120b57cec5SDimitry Andric .Default(false);
1130b57cec5SDimitry Andric #undef CLANG_ATTR_LATE_PARSED_LIST
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric /// Check if the a start and end source location expand to the same macro.
FindLocsWithCommonFileID(Preprocessor & PP,SourceLocation StartLoc,SourceLocation EndLoc)117a7dea167SDimitry Andric static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc,
1180b57cec5SDimitry Andric SourceLocation EndLoc) {
1190b57cec5SDimitry Andric if (!StartLoc.isMacroID() || !EndLoc.isMacroID())
1200b57cec5SDimitry Andric return false;
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric SourceManager &SM = PP.getSourceManager();
1230b57cec5SDimitry Andric if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc))
1240b57cec5SDimitry Andric return false;
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric bool AttrStartIsInMacro =
1270b57cec5SDimitry Andric Lexer::isAtStartOfMacroExpansion(StartLoc, SM, PP.getLangOpts());
1280b57cec5SDimitry Andric bool AttrEndIsInMacro =
1290b57cec5SDimitry Andric Lexer::isAtEndOfMacroExpansion(EndLoc, SM, PP.getLangOpts());
1300b57cec5SDimitry Andric return AttrStartIsInMacro && AttrEndIsInMacro;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
ParseAttributes(unsigned WhichAttrKinds,ParsedAttributes & Attrs,LateParsedAttrList * LateAttrs)13381ad6265SDimitry Andric void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
134fe6060f1SDimitry Andric LateParsedAttrList *LateAttrs) {
135fe6060f1SDimitry Andric bool MoreToParse;
136fe6060f1SDimitry Andric do {
137fe6060f1SDimitry Andric // Assume there's nothing left to parse, but if any attributes are in fact
138fe6060f1SDimitry Andric // parsed, loop to ensure all specified attribute combinations are parsed.
139fe6060f1SDimitry Andric MoreToParse = false;
140fe6060f1SDimitry Andric if (WhichAttrKinds & PAKM_CXX11)
14181ad6265SDimitry Andric MoreToParse |= MaybeParseCXX11Attributes(Attrs);
142fe6060f1SDimitry Andric if (WhichAttrKinds & PAKM_GNU)
14381ad6265SDimitry Andric MoreToParse |= MaybeParseGNUAttributes(Attrs, LateAttrs);
144fe6060f1SDimitry Andric if (WhichAttrKinds & PAKM_Declspec)
14581ad6265SDimitry Andric MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs);
146fe6060f1SDimitry Andric } while (MoreToParse);
147fe6060f1SDimitry Andric }
148fe6060f1SDimitry Andric
1490b57cec5SDimitry Andric /// ParseGNUAttributes - Parse a non-empty attributes list.
1500b57cec5SDimitry Andric ///
1510b57cec5SDimitry Andric /// [GNU] attributes:
1520b57cec5SDimitry Andric /// attribute
1530b57cec5SDimitry Andric /// attributes attribute
1540b57cec5SDimitry Andric ///
1550b57cec5SDimitry Andric /// [GNU] attribute:
1560b57cec5SDimitry Andric /// '__attribute__' '(' '(' attribute-list ')' ')'
1570b57cec5SDimitry Andric ///
1580b57cec5SDimitry Andric /// [GNU] attribute-list:
1590b57cec5SDimitry Andric /// attrib
1600b57cec5SDimitry Andric /// attribute_list ',' attrib
1610b57cec5SDimitry Andric ///
1620b57cec5SDimitry Andric /// [GNU] attrib:
1630b57cec5SDimitry Andric /// empty
1640b57cec5SDimitry Andric /// attrib-name
1650b57cec5SDimitry Andric /// attrib-name '(' identifier ')'
1660b57cec5SDimitry Andric /// attrib-name '(' identifier ',' nonempty-expr-list ')'
1670b57cec5SDimitry Andric /// attrib-name '(' argument-expression-list [C99 6.5.2] ')'
1680b57cec5SDimitry Andric ///
1690b57cec5SDimitry Andric /// [GNU] attrib-name:
1700b57cec5SDimitry Andric /// identifier
1710b57cec5SDimitry Andric /// typespec
1720b57cec5SDimitry Andric /// typequal
1730b57cec5SDimitry Andric /// storageclass
1740b57cec5SDimitry Andric ///
1750b57cec5SDimitry Andric /// Whether an attribute takes an 'identifier' is determined by the
1760b57cec5SDimitry Andric /// attrib-name. GCC's behavior here is not worth imitating:
1770b57cec5SDimitry Andric ///
1780b57cec5SDimitry Andric /// * In C mode, if the attribute argument list starts with an identifier
1790b57cec5SDimitry Andric /// followed by a ',' or an ')', and the identifier doesn't resolve to
1800b57cec5SDimitry Andric /// a type, it is parsed as an identifier. If the attribute actually
1810b57cec5SDimitry Andric /// wanted an expression, it's out of luck (but it turns out that no
1820b57cec5SDimitry Andric /// attributes work that way, because C constant expressions are very
1830b57cec5SDimitry Andric /// limited).
1840b57cec5SDimitry Andric /// * In C++ mode, if the attribute argument list starts with an identifier,
1850b57cec5SDimitry Andric /// and the attribute *wants* an identifier, it is parsed as an identifier.
1860b57cec5SDimitry Andric /// At block scope, any additional tokens between the identifier and the
1870b57cec5SDimitry Andric /// ',' or ')' are ignored, otherwise they produce a parse error.
1880b57cec5SDimitry Andric ///
1890b57cec5SDimitry Andric /// We follow the C++ model, but don't allow junk after the identifier.
ParseGNUAttributes(ParsedAttributes & Attrs,LateParsedAttrList * LateAttrs,Declarator * D)19081ad6265SDimitry Andric void Parser::ParseGNUAttributes(ParsedAttributes &Attrs,
191fe6060f1SDimitry Andric LateParsedAttrList *LateAttrs, Declarator *D) {
1920b57cec5SDimitry Andric assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
1930b57cec5SDimitry Andric
19481ad6265SDimitry Andric SourceLocation StartLoc = Tok.getLocation();
19581ad6265SDimitry Andric SourceLocation EndLoc = StartLoc;
196fe6060f1SDimitry Andric
1970b57cec5SDimitry Andric while (Tok.is(tok::kw___attribute)) {
1980b57cec5SDimitry Andric SourceLocation AttrTokLoc = ConsumeToken();
199fe6060f1SDimitry Andric unsigned OldNumAttrs = Attrs.size();
2000b57cec5SDimitry Andric unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0;
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
2030b57cec5SDimitry Andric "attribute")) {
2040b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
2050b57cec5SDimitry Andric return;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
2080b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
2090b57cec5SDimitry Andric return;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
2120b57cec5SDimitry Andric do {
2130b57cec5SDimitry Andric // Eat preceeding commas to allow __attribute__((,,,foo))
2140b57cec5SDimitry Andric while (TryConsumeToken(tok::comma))
2150b57cec5SDimitry Andric ;
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric // Expect an identifier or declaration specifier (const, int, etc.)
2180b57cec5SDimitry Andric if (Tok.isAnnotation())
2190b57cec5SDimitry Andric break;
220349cc55cSDimitry Andric if (Tok.is(tok::code_completion)) {
221349cc55cSDimitry Andric cutOffParsing();
222*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteAttribute(
223*0fca6ea1SDimitry Andric AttributeCommonInfo::Syntax::AS_GNU);
224349cc55cSDimitry Andric break;
225349cc55cSDimitry Andric }
2260b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
2270b57cec5SDimitry Andric if (!AttrName)
2280b57cec5SDimitry Andric break;
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
233fe6060f1SDimitry Andric Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
23406c3fb27SDimitry Andric ParsedAttr::Form::GNU());
2350b57cec5SDimitry Andric continue;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric
238*0fca6ea1SDimitry Andric bool LateParse = false;
239*0fca6ea1SDimitry Andric if (!LateAttrs)
240*0fca6ea1SDimitry Andric LateParse = false;
241*0fca6ea1SDimitry Andric else if (LateAttrs->lateAttrParseExperimentalExtOnly()) {
242*0fca6ea1SDimitry Andric // The caller requested that this attribute **only** be late
243*0fca6ea1SDimitry Andric // parsed for `LateAttrParseExperimentalExt` attributes. This will
244*0fca6ea1SDimitry Andric // only be late parsed if the experimental language option is enabled.
245*0fca6ea1SDimitry Andric LateParse = getLangOpts().ExperimentalLateParseAttributes &&
246*0fca6ea1SDimitry Andric IsAttributeLateParsedExperimentalExt(*AttrName);
247*0fca6ea1SDimitry Andric } else {
248*0fca6ea1SDimitry Andric // The caller did not restrict late parsing to only
249*0fca6ea1SDimitry Andric // `LateAttrParseExperimentalExt` attributes so late parse
250*0fca6ea1SDimitry Andric // both `LateAttrParseStandard` and `LateAttrParseExperimentalExt`
251*0fca6ea1SDimitry Andric // attributes.
252*0fca6ea1SDimitry Andric LateParse = IsAttributeLateParsedExperimentalExt(*AttrName) ||
253*0fca6ea1SDimitry Andric IsAttributeLateParsedStandard(*AttrName);
254*0fca6ea1SDimitry Andric }
255*0fca6ea1SDimitry Andric
2560b57cec5SDimitry Andric // Handle "parameterized" attributes
257*0fca6ea1SDimitry Andric if (!LateParse) {
25881ad6265SDimitry Andric ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr,
25906c3fb27SDimitry Andric SourceLocation(), ParsedAttr::Form::GNU(), D);
2600b57cec5SDimitry Andric continue;
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric // Handle attributes with arguments that require late parsing.
2640b57cec5SDimitry Andric LateParsedAttribute *LA =
2650b57cec5SDimitry Andric new LateParsedAttribute(this, *AttrName, AttrNameLoc);
2660b57cec5SDimitry Andric LateAttrs->push_back(LA);
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric // Attributes in a class are parsed at the end of the class, along
2690b57cec5SDimitry Andric // with other late-parsed declarations.
2700b57cec5SDimitry Andric if (!ClassStack.empty() && !LateAttrs->parseSoon())
2710b57cec5SDimitry Andric getCurrentClass().LateParsedDeclarations.push_back(LA);
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it
2740b57cec5SDimitry Andric // recursively consumes balanced parens.
2750b57cec5SDimitry Andric LA->Toks.push_back(Tok);
2760b57cec5SDimitry Andric ConsumeParen();
2770b57cec5SDimitry Andric // Consume everything up to and including the matching right parens.
2780b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::r_paren, LA->Toks, /*StopAtSemi=*/true);
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric Token Eof;
2810b57cec5SDimitry Andric Eof.startToken();
2820b57cec5SDimitry Andric Eof.setLocation(Tok.getLocation());
2830b57cec5SDimitry Andric LA->Toks.push_back(Eof);
2840b57cec5SDimitry Andric } while (Tok.is(tok::comma));
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric if (ExpectAndConsume(tok::r_paren))
2870b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
2880b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
2890b57cec5SDimitry Andric if (ExpectAndConsume(tok::r_paren))
2900b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
29181ad6265SDimitry Andric EndLoc = Loc;
2920b57cec5SDimitry Andric
2930b57cec5SDimitry Andric // If this was declared in a macro, attach the macro IdentifierInfo to the
2940b57cec5SDimitry Andric // parsed attribute.
2950b57cec5SDimitry Andric auto &SM = PP.getSourceManager();
2960b57cec5SDimitry Andric if (!SM.isWrittenInBuiltinFile(SM.getSpellingLoc(AttrTokLoc)) &&
2970b57cec5SDimitry Andric FindLocsWithCommonFileID(PP, AttrTokLoc, Loc)) {
2980b57cec5SDimitry Andric CharSourceRange ExpansionRange = SM.getExpansionRange(AttrTokLoc);
2990b57cec5SDimitry Andric StringRef FoundName =
3000b57cec5SDimitry Andric Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts());
3010b57cec5SDimitry Andric IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName);
3020b57cec5SDimitry Andric
303fe6060f1SDimitry Andric for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i)
304fe6060f1SDimitry Andric Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin());
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric if (LateAttrs) {
3070b57cec5SDimitry Andric for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i)
3080b57cec5SDimitry Andric (*LateAttrs)[i]->MacroII = MacroII;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric }
312fe6060f1SDimitry Andric
31381ad6265SDimitry Andric Attrs.Range = SourceRange(StartLoc, EndLoc);
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric
3160b57cec5SDimitry Andric /// Determine whether the given attribute has an identifier argument.
attributeHasIdentifierArg(const IdentifierInfo & II)3170b57cec5SDimitry Andric static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
3180b57cec5SDimitry Andric #define CLANG_ATTR_IDENTIFIER_ARG_LIST
3190b57cec5SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3200b57cec5SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
3210b57cec5SDimitry Andric .Default(false);
3220b57cec5SDimitry Andric #undef CLANG_ATTR_IDENTIFIER_ARG_LIST
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric
3255f757f3fSDimitry Andric /// Determine whether the given attribute has an identifier argument.
3265f757f3fSDimitry Andric static ParsedAttributeArgumentsProperties
attributeStringLiteralListArg(const llvm::Triple & T,const IdentifierInfo & II)327*0fca6ea1SDimitry Andric attributeStringLiteralListArg(const llvm::Triple &T, const IdentifierInfo &II) {
3285f757f3fSDimitry Andric #define CLANG_ATTR_STRING_LITERAL_ARG_LIST
3295f757f3fSDimitry Andric return llvm::StringSwitch<uint32_t>(normalizeAttrName(II.getName()))
3305f757f3fSDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
3315f757f3fSDimitry Andric .Default(0);
3325f757f3fSDimitry Andric #undef CLANG_ATTR_STRING_LITERAL_ARG_LIST
3335f757f3fSDimitry Andric }
3345f757f3fSDimitry Andric
3350b57cec5SDimitry Andric /// Determine whether the given attribute has a variadic identifier argument.
attributeHasVariadicIdentifierArg(const IdentifierInfo & II)3360b57cec5SDimitry Andric static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) {
3370b57cec5SDimitry Andric #define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
3380b57cec5SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3390b57cec5SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
3400b57cec5SDimitry Andric .Default(false);
3410b57cec5SDimitry Andric #undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric
3440b57cec5SDimitry Andric /// Determine whether the given attribute treats kw_this as an identifier.
attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo & II)3450b57cec5SDimitry Andric static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) {
3460b57cec5SDimitry Andric #define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
3470b57cec5SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3480b57cec5SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
3490b57cec5SDimitry Andric .Default(false);
3500b57cec5SDimitry Andric #undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric
35381ad6265SDimitry Andric /// Determine if an attribute accepts parameter packs.
attributeAcceptsExprPack(const IdentifierInfo & II)35481ad6265SDimitry Andric static bool attributeAcceptsExprPack(const IdentifierInfo &II) {
35581ad6265SDimitry Andric #define CLANG_ATTR_ACCEPTS_EXPR_PACK
35681ad6265SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
35781ad6265SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
35881ad6265SDimitry Andric .Default(false);
35981ad6265SDimitry Andric #undef CLANG_ATTR_ACCEPTS_EXPR_PACK
36081ad6265SDimitry Andric }
36181ad6265SDimitry Andric
3620b57cec5SDimitry Andric /// Determine whether the given attribute parses a type argument.
attributeIsTypeArgAttr(const IdentifierInfo & II)3630b57cec5SDimitry Andric static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
3640b57cec5SDimitry Andric #define CLANG_ATTR_TYPE_ARG_LIST
3650b57cec5SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3660b57cec5SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
3670b57cec5SDimitry Andric .Default(false);
3680b57cec5SDimitry Andric #undef CLANG_ATTR_TYPE_ARG_LIST
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric
371*0fca6ea1SDimitry Andric /// Determine whether the given attribute takes identifier arguments.
attributeHasStrictIdentifierArgs(const IdentifierInfo & II)372*0fca6ea1SDimitry Andric static bool attributeHasStrictIdentifierArgs(const IdentifierInfo &II) {
373*0fca6ea1SDimitry Andric #define CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
374*0fca6ea1SDimitry Andric return (llvm::StringSwitch<uint64_t>(normalizeAttrName(II.getName()))
375*0fca6ea1SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
376*0fca6ea1SDimitry Andric .Default(0)) != 0;
377*0fca6ea1SDimitry Andric #undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
378*0fca6ea1SDimitry Andric }
379*0fca6ea1SDimitry Andric
380*0fca6ea1SDimitry Andric /// Determine whether the given attribute takes an identifier argument at a
381*0fca6ea1SDimitry Andric /// specific index
attributeHasStrictIdentifierArgAtIndex(const IdentifierInfo & II,size_t argIndex)382*0fca6ea1SDimitry Andric static bool attributeHasStrictIdentifierArgAtIndex(const IdentifierInfo &II,
383*0fca6ea1SDimitry Andric size_t argIndex) {
384*0fca6ea1SDimitry Andric #define CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
385*0fca6ea1SDimitry Andric return (llvm::StringSwitch<uint64_t>(normalizeAttrName(II.getName()))
386*0fca6ea1SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
387*0fca6ea1SDimitry Andric .Default(0)) &
388*0fca6ea1SDimitry Andric (1ull << argIndex);
389*0fca6ea1SDimitry Andric #undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST
390*0fca6ea1SDimitry Andric }
391*0fca6ea1SDimitry Andric
3920b57cec5SDimitry Andric /// Determine whether the given attribute requires parsing its arguments
3930b57cec5SDimitry Andric /// in an unevaluated context or not.
attributeParsedArgsUnevaluated(const IdentifierInfo & II)3940b57cec5SDimitry Andric static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {
3950b57cec5SDimitry Andric #define CLANG_ATTR_ARG_CONTEXT_LIST
3960b57cec5SDimitry Andric return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3970b57cec5SDimitry Andric #include "clang/Parse/AttrParserStringSwitches.inc"
3980b57cec5SDimitry Andric .Default(false);
3990b57cec5SDimitry Andric #undef CLANG_ATTR_ARG_CONTEXT_LIST
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric
ParseIdentifierLoc()4020b57cec5SDimitry Andric IdentifierLoc *Parser::ParseIdentifierLoc() {
4030b57cec5SDimitry Andric assert(Tok.is(tok::identifier) && "expected an identifier");
4040b57cec5SDimitry Andric IdentifierLoc *IL = IdentifierLoc::create(Actions.Context,
4050b57cec5SDimitry Andric Tok.getLocation(),
4060b57cec5SDimitry Andric Tok.getIdentifierInfo());
4070b57cec5SDimitry Andric ConsumeToken();
4080b57cec5SDimitry Andric return IL;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
ParseAttributeWithTypeArg(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)4110b57cec5SDimitry Andric void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
4120b57cec5SDimitry Andric SourceLocation AttrNameLoc,
4130b57cec5SDimitry Andric ParsedAttributes &Attrs,
4140b57cec5SDimitry Andric IdentifierInfo *ScopeName,
4150b57cec5SDimitry Andric SourceLocation ScopeLoc,
41606c3fb27SDimitry Andric ParsedAttr::Form Form) {
4170b57cec5SDimitry Andric BalancedDelimiterTracker Parens(*this, tok::l_paren);
4180b57cec5SDimitry Andric Parens.consumeOpen();
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric TypeResult T;
4210b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren))
4220b57cec5SDimitry Andric T = ParseTypeName();
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric if (Parens.consumeClose())
4250b57cec5SDimitry Andric return;
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric if (T.isInvalid())
4280b57cec5SDimitry Andric return;
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric if (T.isUsable())
4310b57cec5SDimitry Andric Attrs.addNewTypeAttr(&AttrName,
4320b57cec5SDimitry Andric SourceRange(AttrNameLoc, Parens.getCloseLocation()),
43306c3fb27SDimitry Andric ScopeName, ScopeLoc, T.get(), Form);
4340b57cec5SDimitry Andric else
4350b57cec5SDimitry Andric Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
43606c3fb27SDimitry Andric ScopeName, ScopeLoc, nullptr, 0, Form);
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric
4395f757f3fSDimitry Andric ExprResult
ParseUnevaluatedStringInAttribute(const IdentifierInfo & AttrName)4405f757f3fSDimitry Andric Parser::ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName) {
4415f757f3fSDimitry Andric if (Tok.is(tok::l_paren)) {
4425f757f3fSDimitry Andric BalancedDelimiterTracker Paren(*this, tok::l_paren);
4435f757f3fSDimitry Andric Paren.consumeOpen();
4445f757f3fSDimitry Andric ExprResult Res = ParseUnevaluatedStringInAttribute(AttrName);
4455f757f3fSDimitry Andric Paren.consumeClose();
4465f757f3fSDimitry Andric return Res;
4475f757f3fSDimitry Andric }
4485f757f3fSDimitry Andric if (!isTokenStringLiteral()) {
4495f757f3fSDimitry Andric Diag(Tok.getLocation(), diag::err_expected_string_literal)
4505f757f3fSDimitry Andric << /*in attribute...*/ 4 << AttrName.getName();
4515f757f3fSDimitry Andric return ExprError();
4525f757f3fSDimitry Andric }
4535f757f3fSDimitry Andric return ParseUnevaluatedStringLiteralExpression();
4545f757f3fSDimitry Andric }
4555f757f3fSDimitry Andric
ParseAttributeArgumentList(const IdentifierInfo & AttrName,SmallVectorImpl<Expr * > & Exprs,ParsedAttributeArgumentsProperties ArgsProperties)4565f757f3fSDimitry Andric bool Parser::ParseAttributeArgumentList(
4575f757f3fSDimitry Andric const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs,
4585f757f3fSDimitry Andric ParsedAttributeArgumentsProperties ArgsProperties) {
4595f757f3fSDimitry Andric bool SawError = false;
4605f757f3fSDimitry Andric unsigned Arg = 0;
4615f757f3fSDimitry Andric while (true) {
4625f757f3fSDimitry Andric ExprResult Expr;
4635f757f3fSDimitry Andric if (ArgsProperties.isStringLiteralArg(Arg)) {
4645f757f3fSDimitry Andric Expr = ParseUnevaluatedStringInAttribute(AttrName);
4655f757f3fSDimitry Andric } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
4665f757f3fSDimitry Andric Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
4675f757f3fSDimitry Andric Expr = ParseBraceInitializer();
4685f757f3fSDimitry Andric } else {
4695f757f3fSDimitry Andric Expr = ParseAssignmentExpression();
4705f757f3fSDimitry Andric }
4715f757f3fSDimitry Andric Expr = Actions.CorrectDelayedTyposInExpr(Expr);
4725f757f3fSDimitry Andric
4735f757f3fSDimitry Andric if (Tok.is(tok::ellipsis))
4745f757f3fSDimitry Andric Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
4755f757f3fSDimitry Andric else if (Tok.is(tok::code_completion)) {
4765f757f3fSDimitry Andric // There's nothing to suggest in here as we parsed a full expression.
4775f757f3fSDimitry Andric // Instead fail and propagate the error since caller might have something
4785f757f3fSDimitry Andric // the suggest, e.g. signature help in function call. Note that this is
4795f757f3fSDimitry Andric // performed before pushing the \p Expr, so that signature help can report
4805f757f3fSDimitry Andric // current argument correctly.
4815f757f3fSDimitry Andric SawError = true;
4825f757f3fSDimitry Andric cutOffParsing();
4835f757f3fSDimitry Andric break;
4845f757f3fSDimitry Andric }
4855f757f3fSDimitry Andric
4865f757f3fSDimitry Andric if (Expr.isInvalid()) {
4875f757f3fSDimitry Andric SawError = true;
4885f757f3fSDimitry Andric break;
4895f757f3fSDimitry Andric }
4905f757f3fSDimitry Andric
491*0fca6ea1SDimitry Andric if (Actions.DiagnoseUnexpandedParameterPack(Expr.get())) {
492*0fca6ea1SDimitry Andric SawError = true;
493*0fca6ea1SDimitry Andric break;
494*0fca6ea1SDimitry Andric }
495*0fca6ea1SDimitry Andric
4965f757f3fSDimitry Andric Exprs.push_back(Expr.get());
4975f757f3fSDimitry Andric
4985f757f3fSDimitry Andric if (Tok.isNot(tok::comma))
4995f757f3fSDimitry Andric break;
5005f757f3fSDimitry Andric // Move to the next argument, remember where the comma was.
5015f757f3fSDimitry Andric Token Comma = Tok;
5025f757f3fSDimitry Andric ConsumeToken();
5035f757f3fSDimitry Andric checkPotentialAngleBracketDelimiter(Comma);
5045f757f3fSDimitry Andric Arg++;
5055f757f3fSDimitry Andric }
5065f757f3fSDimitry Andric
5075f757f3fSDimitry Andric if (SawError) {
5085f757f3fSDimitry Andric // Ensure typos get diagnosed when errors were encountered while parsing the
5095f757f3fSDimitry Andric // expression list.
5105f757f3fSDimitry Andric for (auto &E : Exprs) {
5115f757f3fSDimitry Andric ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E);
5125f757f3fSDimitry Andric if (Expr.isUsable())
5135f757f3fSDimitry Andric E = Expr.get();
5145f757f3fSDimitry Andric }
5155f757f3fSDimitry Andric }
5165f757f3fSDimitry Andric return SawError;
5175f757f3fSDimitry Andric }
5185f757f3fSDimitry Andric
ParseAttributeArgsCommon(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)5190b57cec5SDimitry Andric unsigned Parser::ParseAttributeArgsCommon(
5200b57cec5SDimitry Andric IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
5210b57cec5SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
52206c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
5230b57cec5SDimitry Andric // Ignore the left paren location for now.
5240b57cec5SDimitry Andric ConsumeParen();
5250b57cec5SDimitry Andric
5260b57cec5SDimitry Andric bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName);
527a7dea167SDimitry Andric bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName);
52881ad6265SDimitry Andric bool AttributeHasVariadicIdentifierArg =
52981ad6265SDimitry Andric attributeHasVariadicIdentifierArg(*AttrName);
5300b57cec5SDimitry Andric
5310b57cec5SDimitry Andric // Interpret "kw_this" as an identifier if the attributed requests it.
5320b57cec5SDimitry Andric if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
5330b57cec5SDimitry Andric Tok.setKind(tok::identifier);
5340b57cec5SDimitry Andric
5350b57cec5SDimitry Andric ArgsVector ArgExprs;
5360b57cec5SDimitry Andric if (Tok.is(tok::identifier)) {
5370b57cec5SDimitry Andric // If this attribute wants an 'identifier' argument, make it so.
53881ad6265SDimitry Andric bool IsIdentifierArg = AttributeHasVariadicIdentifierArg ||
53981ad6265SDimitry Andric attributeHasIdentifierArg(*AttrName);
5400b57cec5SDimitry Andric ParsedAttr::Kind AttrKind =
54106c3fb27SDimitry Andric ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric // If we don't know how to parse this attribute, but this is the only
5440b57cec5SDimitry Andric // token in this argument, assume it's meant to be an identifier.
5450b57cec5SDimitry Andric if (AttrKind == ParsedAttr::UnknownAttribute ||
5460b57cec5SDimitry Andric AttrKind == ParsedAttr::IgnoredAttribute) {
5470b57cec5SDimitry Andric const Token &Next = NextToken();
5480b57cec5SDimitry Andric IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric
5510b57cec5SDimitry Andric if (IsIdentifierArg)
5520b57cec5SDimitry Andric ArgExprs.push_back(ParseIdentifierLoc());
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric
555a7dea167SDimitry Andric ParsedType TheParsedType;
5560b57cec5SDimitry Andric if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
5570b57cec5SDimitry Andric // Eat the comma.
5580b57cec5SDimitry Andric if (!ArgExprs.empty())
5590b57cec5SDimitry Andric ConsumeToken();
5600b57cec5SDimitry Andric
561a7dea167SDimitry Andric if (AttributeIsTypeArgAttr) {
56281ad6265SDimitry Andric // FIXME: Multiple type arguments are not implemented.
563a7dea167SDimitry Andric TypeResult T = ParseTypeName();
564a7dea167SDimitry Andric if (T.isInvalid()) {
565a7dea167SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
566a7dea167SDimitry Andric return 0;
567a7dea167SDimitry Andric }
568a7dea167SDimitry Andric if (T.isUsable())
569a7dea167SDimitry Andric TheParsedType = T.get();
570*0fca6ea1SDimitry Andric } else if (AttributeHasVariadicIdentifierArg ||
571*0fca6ea1SDimitry Andric attributeHasStrictIdentifierArgs(*AttrName)) {
57281ad6265SDimitry Andric // Parse variadic identifier arg. This can either consume identifiers or
57381ad6265SDimitry Andric // expressions. Variadic identifier args do not support parameter packs
57481ad6265SDimitry Andric // because those are typically used for attributes with enumeration
57581ad6265SDimitry Andric // arguments, and those enumerations are not something the user could
57681ad6265SDimitry Andric // express via a pack.
57781ad6265SDimitry Andric do {
57881ad6265SDimitry Andric // Interpret "kw_this" as an identifier if the attributed requests it.
57981ad6265SDimitry Andric if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
58081ad6265SDimitry Andric Tok.setKind(tok::identifier);
58181ad6265SDimitry Andric
582*0fca6ea1SDimitry Andric if (Tok.is(tok::identifier) && attributeHasStrictIdentifierArgAtIndex(
583*0fca6ea1SDimitry Andric *AttrName, ArgExprs.size())) {
584*0fca6ea1SDimitry Andric ArgExprs.push_back(ParseIdentifierLoc());
585*0fca6ea1SDimitry Andric continue;
586*0fca6ea1SDimitry Andric }
587*0fca6ea1SDimitry Andric
58881ad6265SDimitry Andric ExprResult ArgExpr;
58981ad6265SDimitry Andric if (Tok.is(tok::identifier)) {
5900b57cec5SDimitry Andric ArgExprs.push_back(ParseIdentifierLoc());
5910b57cec5SDimitry Andric } else {
5920b57cec5SDimitry Andric bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
5930b57cec5SDimitry Andric EnterExpressionEvaluationContext Unevaluated(
5940b57cec5SDimitry Andric Actions,
5950b57cec5SDimitry Andric Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
596*0fca6ea1SDimitry Andric : Sema::ExpressionEvaluationContext::ConstantEvaluated,
597*0fca6ea1SDimitry Andric nullptr,
598*0fca6ea1SDimitry Andric Sema::ExpressionEvaluationContextRecord::EK_AttrArgument);
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric ExprResult ArgExpr(
6010b57cec5SDimitry Andric Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
60281ad6265SDimitry Andric
6030b57cec5SDimitry Andric if (ArgExpr.isInvalid()) {
6040b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
6050b57cec5SDimitry Andric return 0;
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric ArgExprs.push_back(ArgExpr.get());
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric // Eat the comma, move to the next argument
6100b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma));
61181ad6265SDimitry Andric } else {
61281ad6265SDimitry Andric // General case. Parse all available expressions.
61381ad6265SDimitry Andric bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
61481ad6265SDimitry Andric EnterExpressionEvaluationContext Unevaluated(
615*0fca6ea1SDimitry Andric Actions,
616*0fca6ea1SDimitry Andric Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
617*0fca6ea1SDimitry Andric : Sema::ExpressionEvaluationContext::ConstantEvaluated,
618*0fca6ea1SDimitry Andric nullptr,
619*0fca6ea1SDimitry Andric Sema::ExpressionEvaluationContextRecord::ExpressionKind::
620*0fca6ea1SDimitry Andric EK_AttrArgument);
62181ad6265SDimitry Andric
62281ad6265SDimitry Andric ExprVector ParsedExprs;
6235f757f3fSDimitry Andric ParsedAttributeArgumentsProperties ArgProperties =
624*0fca6ea1SDimitry Andric attributeStringLiteralListArg(getTargetInfo().getTriple(), *AttrName);
6255f757f3fSDimitry Andric if (ParseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties)) {
62681ad6265SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
62781ad6265SDimitry Andric return 0;
62881ad6265SDimitry Andric }
62981ad6265SDimitry Andric
63081ad6265SDimitry Andric // Pack expansion must currently be explicitly supported by an attribute.
63181ad6265SDimitry Andric for (size_t I = 0; I < ParsedExprs.size(); ++I) {
63281ad6265SDimitry Andric if (!isa<PackExpansionExpr>(ParsedExprs[I]))
63381ad6265SDimitry Andric continue;
63481ad6265SDimitry Andric
63581ad6265SDimitry Andric if (!attributeAcceptsExprPack(*AttrName)) {
63681ad6265SDimitry Andric Diag(Tok.getLocation(),
63781ad6265SDimitry Andric diag::err_attribute_argument_parm_pack_not_supported)
63881ad6265SDimitry Andric << AttrName;
63981ad6265SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
64081ad6265SDimitry Andric return 0;
64181ad6265SDimitry Andric }
64281ad6265SDimitry Andric }
64381ad6265SDimitry Andric
64481ad6265SDimitry Andric ArgExprs.insert(ArgExprs.end(), ParsedExprs.begin(), ParsedExprs.end());
64581ad6265SDimitry Andric }
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric
6480b57cec5SDimitry Andric SourceLocation RParen = Tok.getLocation();
6490b57cec5SDimitry Andric if (!ExpectAndConsume(tok::r_paren)) {
6500b57cec5SDimitry Andric SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
651a7dea167SDimitry Andric
652a7dea167SDimitry Andric if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) {
653a7dea167SDimitry Andric Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen),
65406c3fb27SDimitry Andric ScopeName, ScopeLoc, TheParsedType, Form);
655a7dea167SDimitry Andric } else {
6560b57cec5SDimitry Andric Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
65706c3fb27SDimitry Andric ArgExprs.data(), ArgExprs.size(), Form);
6580b57cec5SDimitry Andric }
659a7dea167SDimitry Andric }
6600b57cec5SDimitry Andric
6610b57cec5SDimitry Andric if (EndLoc)
6620b57cec5SDimitry Andric *EndLoc = RParen;
6630b57cec5SDimitry Andric
664a7dea167SDimitry Andric return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull());
6650b57cec5SDimitry Andric }
6660b57cec5SDimitry Andric
6670b57cec5SDimitry Andric /// Parse the arguments to a parameterized GNU attribute or
6680b57cec5SDimitry Andric /// a C++11 attribute in "gnu" namespace.
ParseGNUAttributeArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form,Declarator * D)66981ad6265SDimitry Andric void Parser::ParseGNUAttributeArgs(
67081ad6265SDimitry Andric IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
67181ad6265SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
67206c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form, Declarator *D) {
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
6750b57cec5SDimitry Andric
6760b57cec5SDimitry Andric ParsedAttr::Kind AttrKind =
67706c3fb27SDimitry Andric ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
6780b57cec5SDimitry Andric
6790b57cec5SDimitry Andric if (AttrKind == ParsedAttr::AT_Availability) {
6800b57cec5SDimitry Andric ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
68106c3fb27SDimitry Andric ScopeLoc, Form);
6820b57cec5SDimitry Andric return;
6830b57cec5SDimitry Andric } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) {
6840b57cec5SDimitry Andric ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
68506c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
6860b57cec5SDimitry Andric return;
6870b57cec5SDimitry Andric } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) {
6880b57cec5SDimitry Andric ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
68906c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
6900b57cec5SDimitry Andric return;
691e8d8bef9SDimitry Andric } else if (AttrKind == ParsedAttr::AT_SwiftNewType) {
692e8d8bef9SDimitry Andric ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
69306c3fb27SDimitry Andric ScopeLoc, Form);
694e8d8bef9SDimitry Andric return;
6950b57cec5SDimitry Andric } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {
6960b57cec5SDimitry Andric ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
69706c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
6980b57cec5SDimitry Andric return;
6990b57cec5SDimitry Andric } else if (attributeIsTypeArgAttr(*AttrName)) {
70081ad6265SDimitry Andric ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, ScopeName,
70106c3fb27SDimitry Andric ScopeLoc, Form);
7020b57cec5SDimitry Andric return;
703*0fca6ea1SDimitry Andric } else if (AttrKind == ParsedAttr::AT_CountedBy ||
704*0fca6ea1SDimitry Andric AttrKind == ParsedAttr::AT_CountedByOrNull ||
705*0fca6ea1SDimitry Andric AttrKind == ParsedAttr::AT_SizedBy ||
706*0fca6ea1SDimitry Andric AttrKind == ParsedAttr::AT_SizedByOrNull) {
707*0fca6ea1SDimitry Andric ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
708*0fca6ea1SDimitry Andric Form);
709*0fca6ea1SDimitry Andric return;
710*0fca6ea1SDimitry Andric } else if (AttrKind == ParsedAttr::AT_CXXAssume) {
711*0fca6ea1SDimitry Andric ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
712*0fca6ea1SDimitry Andric return;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
7150b57cec5SDimitry Andric // These may refer to the function arguments, but need to be parsed early to
7160b57cec5SDimitry Andric // participate in determining whether it's a redeclaration.
717bdd1243dSDimitry Andric std::optional<ParseScope> PrototypeScope;
7180b57cec5SDimitry Andric if (normalizeAttrName(AttrName->getName()) == "enable_if" &&
7190b57cec5SDimitry Andric D && D->isFunctionDeclarator()) {
7200b57cec5SDimitry Andric DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
7210b57cec5SDimitry Andric PrototypeScope.emplace(this, Scope::FunctionPrototypeScope |
7220b57cec5SDimitry Andric Scope::FunctionDeclarationScope |
7230b57cec5SDimitry Andric Scope::DeclScope);
7240b57cec5SDimitry Andric for (unsigned i = 0; i != FTI.NumParams; ++i) {
7250b57cec5SDimitry Andric ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
7260b57cec5SDimitry Andric Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric
7300b57cec5SDimitry Andric ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
73106c3fb27SDimitry Andric ScopeLoc, Form);
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric
ParseClangAttributeArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)7340b57cec5SDimitry Andric unsigned Parser::ParseClangAttributeArgs(
7350b57cec5SDimitry Andric IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
7360b57cec5SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
73706c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
7380b57cec5SDimitry Andric assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric ParsedAttr::Kind AttrKind =
74106c3fb27SDimitry Andric ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());
7420b57cec5SDimitry Andric
7430b57cec5SDimitry Andric switch (AttrKind) {
7440b57cec5SDimitry Andric default:
7450b57cec5SDimitry Andric return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
74606c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
7470b57cec5SDimitry Andric case ParsedAttr::AT_ExternalSourceSymbol:
7480b57cec5SDimitry Andric ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
74906c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
7500b57cec5SDimitry Andric break;
7510b57cec5SDimitry Andric case ParsedAttr::AT_Availability:
7520b57cec5SDimitry Andric ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
75306c3fb27SDimitry Andric ScopeLoc, Form);
7540b57cec5SDimitry Andric break;
7550b57cec5SDimitry Andric case ParsedAttr::AT_ObjCBridgeRelated:
7560b57cec5SDimitry Andric ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
75706c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
7580b57cec5SDimitry Andric break;
759e8d8bef9SDimitry Andric case ParsedAttr::AT_SwiftNewType:
760e8d8bef9SDimitry Andric ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
76106c3fb27SDimitry Andric ScopeLoc, Form);
762e8d8bef9SDimitry Andric break;
7630b57cec5SDimitry Andric case ParsedAttr::AT_TypeTagForDatatype:
7640b57cec5SDimitry Andric ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
76506c3fb27SDimitry Andric ScopeName, ScopeLoc, Form);
7660b57cec5SDimitry Andric break;
767*0fca6ea1SDimitry Andric
768*0fca6ea1SDimitry Andric case ParsedAttr::AT_CXXAssume:
769*0fca6ea1SDimitry Andric ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
770*0fca6ea1SDimitry Andric break;
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric
ParseMicrosoftDeclSpecArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs)7750b57cec5SDimitry Andric bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
7760b57cec5SDimitry Andric SourceLocation AttrNameLoc,
7770b57cec5SDimitry Andric ParsedAttributes &Attrs) {
77881ad6265SDimitry Andric unsigned ExistingAttrs = Attrs.size();
77981ad6265SDimitry Andric
7800b57cec5SDimitry Andric // If the attribute isn't known, we will not attempt to parse any
7810b57cec5SDimitry Andric // arguments.
78281ad6265SDimitry Andric if (!hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, AttrName,
7830b57cec5SDimitry Andric getTargetInfo(), getLangOpts())) {
7840b57cec5SDimitry Andric // Eat the left paren, then skip to the ending right paren.
7850b57cec5SDimitry Andric ConsumeParen();
7860b57cec5SDimitry Andric SkipUntil(tok::r_paren);
7870b57cec5SDimitry Andric return false;
7880b57cec5SDimitry Andric }
7890b57cec5SDimitry Andric
7900b57cec5SDimitry Andric SourceLocation OpenParenLoc = Tok.getLocation();
7910b57cec5SDimitry Andric
7920b57cec5SDimitry Andric if (AttrName->getName() == "property") {
7930b57cec5SDimitry Andric // The property declspec is more complex in that it can take one or two
7940b57cec5SDimitry Andric // assignment expressions as a parameter, but the lhs of the assignment
7950b57cec5SDimitry Andric // must be named get or put.
7960b57cec5SDimitry Andric
7970b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
7980b57cec5SDimitry Andric T.expectAndConsume(diag::err_expected_lparen_after,
7990b57cec5SDimitry Andric AttrName->getNameStart(), tok::r_paren);
8000b57cec5SDimitry Andric
8010b57cec5SDimitry Andric enum AccessorKind {
8020b57cec5SDimitry Andric AK_Invalid = -1,
8030b57cec5SDimitry Andric AK_Put = 0,
8040b57cec5SDimitry Andric AK_Get = 1 // indices into AccessorNames
8050b57cec5SDimitry Andric };
8060b57cec5SDimitry Andric IdentifierInfo *AccessorNames[] = {nullptr, nullptr};
8070b57cec5SDimitry Andric bool HasInvalidAccessor = false;
8080b57cec5SDimitry Andric
8090b57cec5SDimitry Andric // Parse the accessor specifications.
8100b57cec5SDimitry Andric while (true) {
8110b57cec5SDimitry Andric // Stop if this doesn't look like an accessor spec.
8120b57cec5SDimitry Andric if (!Tok.is(tok::identifier)) {
8130b57cec5SDimitry Andric // If the user wrote a completely empty list, use a special diagnostic.
8140b57cec5SDimitry Andric if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
8150b57cec5SDimitry Andric AccessorNames[AK_Put] == nullptr &&
8160b57cec5SDimitry Andric AccessorNames[AK_Get] == nullptr) {
8170b57cec5SDimitry Andric Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);
8180b57cec5SDimitry Andric break;
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor);
8220b57cec5SDimitry Andric break;
8230b57cec5SDimitry Andric }
8240b57cec5SDimitry Andric
8250b57cec5SDimitry Andric AccessorKind Kind;
8260b57cec5SDimitry Andric SourceLocation KindLoc = Tok.getLocation();
8270b57cec5SDimitry Andric StringRef KindStr = Tok.getIdentifierInfo()->getName();
8280b57cec5SDimitry Andric if (KindStr == "get") {
8290b57cec5SDimitry Andric Kind = AK_Get;
8300b57cec5SDimitry Andric } else if (KindStr == "put") {
8310b57cec5SDimitry Andric Kind = AK_Put;
8320b57cec5SDimitry Andric
8330b57cec5SDimitry Andric // Recover from the common mistake of using 'set' instead of 'put'.
8340b57cec5SDimitry Andric } else if (KindStr == "set") {
8350b57cec5SDimitry Andric Diag(KindLoc, diag::err_ms_property_has_set_accessor)
8360b57cec5SDimitry Andric << FixItHint::CreateReplacement(KindLoc, "put");
8370b57cec5SDimitry Andric Kind = AK_Put;
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andric // Handle the mistake of forgetting the accessor kind by skipping
8400b57cec5SDimitry Andric // this accessor.
8410b57cec5SDimitry Andric } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
8420b57cec5SDimitry Andric Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
8430b57cec5SDimitry Andric ConsumeToken();
8440b57cec5SDimitry Andric HasInvalidAccessor = true;
8450b57cec5SDimitry Andric goto next_property_accessor;
8460b57cec5SDimitry Andric
8470b57cec5SDimitry Andric // Otherwise, complain about the unknown accessor kind.
8480b57cec5SDimitry Andric } else {
8490b57cec5SDimitry Andric Diag(KindLoc, diag::err_ms_property_unknown_accessor);
8500b57cec5SDimitry Andric HasInvalidAccessor = true;
8510b57cec5SDimitry Andric Kind = AK_Invalid;
8520b57cec5SDimitry Andric
8530b57cec5SDimitry Andric // Try to keep parsing unless it doesn't look like an accessor spec.
8540b57cec5SDimitry Andric if (!NextToken().is(tok::equal))
8550b57cec5SDimitry Andric break;
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric
8580b57cec5SDimitry Andric // Consume the identifier.
8590b57cec5SDimitry Andric ConsumeToken();
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric // Consume the '='.
8620b57cec5SDimitry Andric if (!TryConsumeToken(tok::equal)) {
8630b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
8640b57cec5SDimitry Andric << KindStr;
8650b57cec5SDimitry Andric break;
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric // Expect the method name.
8690b57cec5SDimitry Andric if (!Tok.is(tok::identifier)) {
8700b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name);
8710b57cec5SDimitry Andric break;
8720b57cec5SDimitry Andric }
8730b57cec5SDimitry Andric
8740b57cec5SDimitry Andric if (Kind == AK_Invalid) {
8750b57cec5SDimitry Andric // Just drop invalid accessors.
8760b57cec5SDimitry Andric } else if (AccessorNames[Kind] != nullptr) {
8770b57cec5SDimitry Andric // Complain about the repeated accessor, ignore it, and keep parsing.
8780b57cec5SDimitry Andric Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
8790b57cec5SDimitry Andric } else {
8800b57cec5SDimitry Andric AccessorNames[Kind] = Tok.getIdentifierInfo();
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric ConsumeToken();
8830b57cec5SDimitry Andric
8840b57cec5SDimitry Andric next_property_accessor:
8850b57cec5SDimitry Andric // Keep processing accessors until we run out.
8860b57cec5SDimitry Andric if (TryConsumeToken(tok::comma))
8870b57cec5SDimitry Andric continue;
8880b57cec5SDimitry Andric
8890b57cec5SDimitry Andric // If we run into the ')', stop without consuming it.
8900b57cec5SDimitry Andric if (Tok.is(tok::r_paren))
8910b57cec5SDimitry Andric break;
8920b57cec5SDimitry Andric
8930b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
8940b57cec5SDimitry Andric break;
8950b57cec5SDimitry Andric }
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andric // Only add the property attribute if it was well-formed.
8980b57cec5SDimitry Andric if (!HasInvalidAccessor)
8990b57cec5SDimitry Andric Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),
9000b57cec5SDimitry Andric AccessorNames[AK_Get], AccessorNames[AK_Put],
90106c3fb27SDimitry Andric ParsedAttr::Form::Declspec());
9020b57cec5SDimitry Andric T.skipToEnd();
9030b57cec5SDimitry Andric return !HasInvalidAccessor;
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric
9060b57cec5SDimitry Andric unsigned NumArgs =
9070b57cec5SDimitry Andric ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
90806c3fb27SDimitry Andric SourceLocation(), ParsedAttr::Form::Declspec());
9090b57cec5SDimitry Andric
9100b57cec5SDimitry Andric // If this attribute's args were parsed, and it was expected to have
9110b57cec5SDimitry Andric // arguments but none were provided, emit a diagnostic.
91281ad6265SDimitry Andric if (ExistingAttrs < Attrs.size() && Attrs.back().getMaxArgs() && !NumArgs) {
9130b57cec5SDimitry Andric Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;
9140b57cec5SDimitry Andric return false;
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric return true;
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric /// [MS] decl-specifier:
9200b57cec5SDimitry Andric /// __declspec ( extended-decl-modifier-seq )
9210b57cec5SDimitry Andric ///
9220b57cec5SDimitry Andric /// [MS] extended-decl-modifier-seq:
9230b57cec5SDimitry Andric /// extended-decl-modifier[opt]
9240b57cec5SDimitry Andric /// extended-decl-modifier extended-decl-modifier-seq
ParseMicrosoftDeclSpecs(ParsedAttributes & Attrs)92581ad6265SDimitry Andric void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) {
9260b57cec5SDimitry Andric assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled");
9270b57cec5SDimitry Andric assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
9280b57cec5SDimitry Andric
92981ad6265SDimitry Andric SourceLocation StartLoc = Tok.getLocation();
93081ad6265SDimitry Andric SourceLocation EndLoc = StartLoc;
93181ad6265SDimitry Andric
9320b57cec5SDimitry Andric while (Tok.is(tok::kw___declspec)) {
9330b57cec5SDimitry Andric ConsumeToken();
9340b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
9350b57cec5SDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
9360b57cec5SDimitry Andric tok::r_paren))
9370b57cec5SDimitry Andric return;
9380b57cec5SDimitry Andric
9390b57cec5SDimitry Andric // An empty declspec is perfectly legal and should not warn. Additionally,
9400b57cec5SDimitry Andric // you can specify multiple attributes per declspec.
9410b57cec5SDimitry Andric while (Tok.isNot(tok::r_paren)) {
9420b57cec5SDimitry Andric // Attribute not present.
9430b57cec5SDimitry Andric if (TryConsumeToken(tok::comma))
9440b57cec5SDimitry Andric continue;
9450b57cec5SDimitry Andric
946349cc55cSDimitry Andric if (Tok.is(tok::code_completion)) {
947349cc55cSDimitry Andric cutOffParsing();
948*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteAttribute(
949*0fca6ea1SDimitry Andric AttributeCommonInfo::AS_Declspec);
950349cc55cSDimitry Andric return;
951349cc55cSDimitry Andric }
952349cc55cSDimitry Andric
9530b57cec5SDimitry Andric // We expect either a well-known identifier or a generic string. Anything
9540b57cec5SDimitry Andric // else is a malformed declspec.
9550b57cec5SDimitry Andric bool IsString = Tok.getKind() == tok::string_literal;
9560b57cec5SDimitry Andric if (!IsString && Tok.getKind() != tok::identifier &&
9570b57cec5SDimitry Andric Tok.getKind() != tok::kw_restrict) {
9580b57cec5SDimitry Andric Diag(Tok, diag::err_ms_declspec_type);
9590b57cec5SDimitry Andric T.skipToEnd();
9600b57cec5SDimitry Andric return;
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric
9630b57cec5SDimitry Andric IdentifierInfo *AttrName;
9640b57cec5SDimitry Andric SourceLocation AttrNameLoc;
9650b57cec5SDimitry Andric if (IsString) {
9660b57cec5SDimitry Andric SmallString<8> StrBuffer;
9670b57cec5SDimitry Andric bool Invalid = false;
9680b57cec5SDimitry Andric StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
9690b57cec5SDimitry Andric if (Invalid) {
9700b57cec5SDimitry Andric T.skipToEnd();
9710b57cec5SDimitry Andric return;
9720b57cec5SDimitry Andric }
9730b57cec5SDimitry Andric AttrName = PP.getIdentifierInfo(Str);
9740b57cec5SDimitry Andric AttrNameLoc = ConsumeStringToken();
9750b57cec5SDimitry Andric } else {
9760b57cec5SDimitry Andric AttrName = Tok.getIdentifierInfo();
9770b57cec5SDimitry Andric AttrNameLoc = ConsumeToken();
9780b57cec5SDimitry Andric }
9790b57cec5SDimitry Andric
9800b57cec5SDimitry Andric bool AttrHandled = false;
9810b57cec5SDimitry Andric
9820b57cec5SDimitry Andric // Parse attribute arguments.
9830b57cec5SDimitry Andric if (Tok.is(tok::l_paren))
9840b57cec5SDimitry Andric AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
9850b57cec5SDimitry Andric else if (AttrName->getName() == "property")
9860b57cec5SDimitry Andric // The property attribute must have an argument list.
9870b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_lparen_after)
9880b57cec5SDimitry Andric << AttrName->getName();
9890b57cec5SDimitry Andric
9900b57cec5SDimitry Andric if (!AttrHandled)
9910b57cec5SDimitry Andric Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
99206c3fb27SDimitry Andric ParsedAttr::Form::Declspec());
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric T.consumeClose();
99581ad6265SDimitry Andric EndLoc = T.getCloseLocation();
9960b57cec5SDimitry Andric }
99781ad6265SDimitry Andric
99881ad6265SDimitry Andric Attrs.Range = SourceRange(StartLoc, EndLoc);
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric
ParseMicrosoftTypeAttributes(ParsedAttributes & attrs)10010b57cec5SDimitry Andric void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
10020b57cec5SDimitry Andric // Treat these like attributes
10030b57cec5SDimitry Andric while (true) {
100406c3fb27SDimitry Andric auto Kind = Tok.getKind();
100506c3fb27SDimitry Andric switch (Kind) {
10060b57cec5SDimitry Andric case tok::kw___fastcall:
10070b57cec5SDimitry Andric case tok::kw___stdcall:
10080b57cec5SDimitry Andric case tok::kw___thiscall:
10090b57cec5SDimitry Andric case tok::kw___regcall:
10100b57cec5SDimitry Andric case tok::kw___cdecl:
10110b57cec5SDimitry Andric case tok::kw___vectorcall:
10120b57cec5SDimitry Andric case tok::kw___ptr64:
10130b57cec5SDimitry Andric case tok::kw___w64:
10140b57cec5SDimitry Andric case tok::kw___ptr32:
10150b57cec5SDimitry Andric case tok::kw___sptr:
10160b57cec5SDimitry Andric case tok::kw___uptr: {
10170b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
10180b57cec5SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
10190b57cec5SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
102006c3fb27SDimitry Andric Kind);
10210b57cec5SDimitry Andric break;
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric default:
10240b57cec5SDimitry Andric return;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric }
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric
ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes & attrs)102906c3fb27SDimitry Andric void Parser::ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes &attrs) {
103006c3fb27SDimitry Andric assert(Tok.is(tok::kw___funcref));
103106c3fb27SDimitry Andric SourceLocation StartLoc = Tok.getLocation();
103206c3fb27SDimitry Andric if (!getTargetInfo().getTriple().isWasm()) {
103306c3fb27SDimitry Andric ConsumeToken();
103406c3fb27SDimitry Andric Diag(StartLoc, diag::err_wasm_funcref_not_wasm);
103506c3fb27SDimitry Andric return;
103606c3fb27SDimitry Andric }
103706c3fb27SDimitry Andric
103806c3fb27SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
103906c3fb27SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
104006c3fb27SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, /*ScopeName=*/nullptr,
104106c3fb27SDimitry Andric /*ScopeLoc=*/SourceLocation{}, /*Args=*/nullptr, /*numArgs=*/0,
104206c3fb27SDimitry Andric tok::kw___funcref);
104306c3fb27SDimitry Andric }
104406c3fb27SDimitry Andric
DiagnoseAndSkipExtendedMicrosoftTypeAttributes()10450b57cec5SDimitry Andric void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() {
10460b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation();
10470b57cec5SDimitry Andric SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes();
10480b57cec5SDimitry Andric
10490b57cec5SDimitry Andric if (EndLoc.isValid()) {
10500b57cec5SDimitry Andric SourceRange Range(StartLoc, EndLoc);
10510b57cec5SDimitry Andric Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range;
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric }
10540b57cec5SDimitry Andric
SkipExtendedMicrosoftTypeAttributes()10550b57cec5SDimitry Andric SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() {
10560b57cec5SDimitry Andric SourceLocation EndLoc;
10570b57cec5SDimitry Andric
10580b57cec5SDimitry Andric while (true) {
10590b57cec5SDimitry Andric switch (Tok.getKind()) {
10600b57cec5SDimitry Andric case tok::kw_const:
10610b57cec5SDimitry Andric case tok::kw_volatile:
10620b57cec5SDimitry Andric case tok::kw___fastcall:
10630b57cec5SDimitry Andric case tok::kw___stdcall:
10640b57cec5SDimitry Andric case tok::kw___thiscall:
10650b57cec5SDimitry Andric case tok::kw___cdecl:
10660b57cec5SDimitry Andric case tok::kw___vectorcall:
10670b57cec5SDimitry Andric case tok::kw___ptr32:
10680b57cec5SDimitry Andric case tok::kw___ptr64:
10690b57cec5SDimitry Andric case tok::kw___w64:
10700b57cec5SDimitry Andric case tok::kw___unaligned:
10710b57cec5SDimitry Andric case tok::kw___sptr:
10720b57cec5SDimitry Andric case tok::kw___uptr:
10730b57cec5SDimitry Andric EndLoc = ConsumeToken();
10740b57cec5SDimitry Andric break;
10750b57cec5SDimitry Andric default:
10760b57cec5SDimitry Andric return EndLoc;
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric }
10790b57cec5SDimitry Andric }
10800b57cec5SDimitry Andric
ParseBorlandTypeAttributes(ParsedAttributes & attrs)10810b57cec5SDimitry Andric void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
10820b57cec5SDimitry Andric // Treat these like attributes
10830b57cec5SDimitry Andric while (Tok.is(tok::kw___pascal)) {
10840b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
10850b57cec5SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
10860b57cec5SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
108706c3fb27SDimitry Andric tok::kw___pascal);
10880b57cec5SDimitry Andric }
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric
ParseOpenCLKernelAttributes(ParsedAttributes & attrs)10910b57cec5SDimitry Andric void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) {
10920b57cec5SDimitry Andric // Treat these like attributes
10930b57cec5SDimitry Andric while (Tok.is(tok::kw___kernel)) {
10940b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
10950b57cec5SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
10960b57cec5SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
109706c3fb27SDimitry Andric tok::kw___kernel);
10980b57cec5SDimitry Andric }
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric
ParseCUDAFunctionAttributes(ParsedAttributes & attrs)110181ad6265SDimitry Andric void Parser::ParseCUDAFunctionAttributes(ParsedAttributes &attrs) {
110281ad6265SDimitry Andric while (Tok.is(tok::kw___noinline__)) {
110381ad6265SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
110481ad6265SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
110581ad6265SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
110606c3fb27SDimitry Andric tok::kw___noinline__);
110781ad6265SDimitry Andric }
110881ad6265SDimitry Andric }
110981ad6265SDimitry Andric
ParseOpenCLQualifiers(ParsedAttributes & Attrs)11100b57cec5SDimitry Andric void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
11110b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
11120b57cec5SDimitry Andric SourceLocation AttrNameLoc = Tok.getLocation();
11130b57cec5SDimitry Andric Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
111406c3fb27SDimitry Andric Tok.getKind());
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric
isHLSLQualifier(const Token & Tok) const1117bdd1243dSDimitry Andric bool Parser::isHLSLQualifier(const Token &Tok) const {
1118bdd1243dSDimitry Andric return Tok.is(tok::kw_groupshared);
1119bdd1243dSDimitry Andric }
1120bdd1243dSDimitry Andric
ParseHLSLQualifiers(ParsedAttributes & Attrs)1121bdd1243dSDimitry Andric void Parser::ParseHLSLQualifiers(ParsedAttributes &Attrs) {
1122bdd1243dSDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
112306c3fb27SDimitry Andric auto Kind = Tok.getKind();
1124bdd1243dSDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
112506c3fb27SDimitry Andric Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind);
1126bdd1243dSDimitry Andric }
1127bdd1243dSDimitry Andric
ParseNullabilityTypeSpecifiers(ParsedAttributes & attrs)11280b57cec5SDimitry Andric void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
11290b57cec5SDimitry Andric // Treat these like attributes, even though they're type specifiers.
11300b57cec5SDimitry Andric while (true) {
113106c3fb27SDimitry Andric auto Kind = Tok.getKind();
113206c3fb27SDimitry Andric switch (Kind) {
11330b57cec5SDimitry Andric case tok::kw__Nonnull:
11340b57cec5SDimitry Andric case tok::kw__Nullable:
1135e8d8bef9SDimitry Andric case tok::kw__Nullable_result:
11360b57cec5SDimitry Andric case tok::kw__Null_unspecified: {
11370b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
11380b57cec5SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken();
11390b57cec5SDimitry Andric if (!getLangOpts().ObjC)
11400b57cec5SDimitry Andric Diag(AttrNameLoc, diag::ext_nullability)
11410b57cec5SDimitry Andric << AttrName;
11420b57cec5SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
114306c3fb27SDimitry Andric Kind);
11440b57cec5SDimitry Andric break;
11450b57cec5SDimitry Andric }
11460b57cec5SDimitry Andric default:
11470b57cec5SDimitry Andric return;
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric }
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric
VersionNumberSeparator(const char Separator)11520b57cec5SDimitry Andric static bool VersionNumberSeparator(const char Separator) {
11530b57cec5SDimitry Andric return (Separator == '.' || Separator == '_');
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andric /// Parse a version number.
11570b57cec5SDimitry Andric ///
11580b57cec5SDimitry Andric /// version:
11590b57cec5SDimitry Andric /// simple-integer
11600b57cec5SDimitry Andric /// simple-integer '.' simple-integer
11610b57cec5SDimitry Andric /// simple-integer '_' simple-integer
11620b57cec5SDimitry Andric /// simple-integer '.' simple-integer '.' simple-integer
11630b57cec5SDimitry Andric /// simple-integer '_' simple-integer '_' simple-integer
ParseVersionTuple(SourceRange & Range)11640b57cec5SDimitry Andric VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
11650b57cec5SDimitry Andric Range = SourceRange(Tok.getLocation(), Tok.getEndLoc());
11660b57cec5SDimitry Andric
11670b57cec5SDimitry Andric if (!Tok.is(tok::numeric_constant)) {
11680b57cec5SDimitry Andric Diag(Tok, diag::err_expected_version);
11690b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren,
11700b57cec5SDimitry Andric StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
11710b57cec5SDimitry Andric return VersionTuple();
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric
11740b57cec5SDimitry Andric // Parse the major (and possibly minor and subminor) versions, which
11750b57cec5SDimitry Andric // are stored in the numeric constant. We utilize a quirk of the
11760b57cec5SDimitry Andric // lexer, which is that it handles something like 1.2.3 as a single
11770b57cec5SDimitry Andric // numeric constant, rather than two separate tokens.
11780b57cec5SDimitry Andric SmallString<512> Buffer;
11790b57cec5SDimitry Andric Buffer.resize(Tok.getLength()+1);
11800b57cec5SDimitry Andric const char *ThisTokBegin = &Buffer[0];
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric // Get the spelling of the token, which eliminates trigraphs, etc.
11830b57cec5SDimitry Andric bool Invalid = false;
11840b57cec5SDimitry Andric unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);
11850b57cec5SDimitry Andric if (Invalid)
11860b57cec5SDimitry Andric return VersionTuple();
11870b57cec5SDimitry Andric
11880b57cec5SDimitry Andric // Parse the major version.
11890b57cec5SDimitry Andric unsigned AfterMajor = 0;
11900b57cec5SDimitry Andric unsigned Major = 0;
11910b57cec5SDimitry Andric while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) {
11920b57cec5SDimitry Andric Major = Major * 10 + ThisTokBegin[AfterMajor] - '0';
11930b57cec5SDimitry Andric ++AfterMajor;
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andric if (AfterMajor == 0) {
11970b57cec5SDimitry Andric Diag(Tok, diag::err_expected_version);
11980b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren,
11990b57cec5SDimitry Andric StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
12000b57cec5SDimitry Andric return VersionTuple();
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric
12030b57cec5SDimitry Andric if (AfterMajor == ActualLength) {
12040b57cec5SDimitry Andric ConsumeToken();
12050b57cec5SDimitry Andric
12060b57cec5SDimitry Andric // We only had a single version component.
12070b57cec5SDimitry Andric if (Major == 0) {
12080b57cec5SDimitry Andric Diag(Tok, diag::err_zero_version);
12090b57cec5SDimitry Andric return VersionTuple();
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric
12120b57cec5SDimitry Andric return VersionTuple(Major);
12130b57cec5SDimitry Andric }
12140b57cec5SDimitry Andric
12150b57cec5SDimitry Andric const char AfterMajorSeparator = ThisTokBegin[AfterMajor];
12160b57cec5SDimitry Andric if (!VersionNumberSeparator(AfterMajorSeparator)
12170b57cec5SDimitry Andric || (AfterMajor + 1 == ActualLength)) {
12180b57cec5SDimitry Andric Diag(Tok, diag::err_expected_version);
12190b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren,
12200b57cec5SDimitry Andric StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
12210b57cec5SDimitry Andric return VersionTuple();
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric
12240b57cec5SDimitry Andric // Parse the minor version.
12250b57cec5SDimitry Andric unsigned AfterMinor = AfterMajor + 1;
12260b57cec5SDimitry Andric unsigned Minor = 0;
12270b57cec5SDimitry Andric while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) {
12280b57cec5SDimitry Andric Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0';
12290b57cec5SDimitry Andric ++AfterMinor;
12300b57cec5SDimitry Andric }
12310b57cec5SDimitry Andric
12320b57cec5SDimitry Andric if (AfterMinor == ActualLength) {
12330b57cec5SDimitry Andric ConsumeToken();
12340b57cec5SDimitry Andric
12350b57cec5SDimitry Andric // We had major.minor.
12360b57cec5SDimitry Andric if (Major == 0 && Minor == 0) {
12370b57cec5SDimitry Andric Diag(Tok, diag::err_zero_version);
12380b57cec5SDimitry Andric return VersionTuple();
12390b57cec5SDimitry Andric }
12400b57cec5SDimitry Andric
12410b57cec5SDimitry Andric return VersionTuple(Major, Minor);
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric
12440b57cec5SDimitry Andric const char AfterMinorSeparator = ThisTokBegin[AfterMinor];
12450b57cec5SDimitry Andric // If what follows is not a '.' or '_', we have a problem.
12460b57cec5SDimitry Andric if (!VersionNumberSeparator(AfterMinorSeparator)) {
12470b57cec5SDimitry Andric Diag(Tok, diag::err_expected_version);
12480b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren,
12490b57cec5SDimitry Andric StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
12500b57cec5SDimitry Andric return VersionTuple();
12510b57cec5SDimitry Andric }
12520b57cec5SDimitry Andric
12530b57cec5SDimitry Andric // Warn if separators, be it '.' or '_', do not match.
12540b57cec5SDimitry Andric if (AfterMajorSeparator != AfterMinorSeparator)
12550b57cec5SDimitry Andric Diag(Tok, diag::warn_expected_consistent_version_separator);
12560b57cec5SDimitry Andric
12570b57cec5SDimitry Andric // Parse the subminor version.
12580b57cec5SDimitry Andric unsigned AfterSubminor = AfterMinor + 1;
12590b57cec5SDimitry Andric unsigned Subminor = 0;
12600b57cec5SDimitry Andric while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) {
12610b57cec5SDimitry Andric Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0';
12620b57cec5SDimitry Andric ++AfterSubminor;
12630b57cec5SDimitry Andric }
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andric if (AfterSubminor != ActualLength) {
12660b57cec5SDimitry Andric Diag(Tok, diag::err_expected_version);
12670b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren,
12680b57cec5SDimitry Andric StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
12690b57cec5SDimitry Andric return VersionTuple();
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric ConsumeToken();
12720b57cec5SDimitry Andric return VersionTuple(Major, Minor, Subminor);
12730b57cec5SDimitry Andric }
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric /// Parse the contents of the "availability" attribute.
12760b57cec5SDimitry Andric ///
12770b57cec5SDimitry Andric /// availability-attribute:
12780b57cec5SDimitry Andric /// 'availability' '(' platform ',' opt-strict version-arg-list,
12790b57cec5SDimitry Andric /// opt-replacement, opt-message')'
12800b57cec5SDimitry Andric ///
12810b57cec5SDimitry Andric /// platform:
12820b57cec5SDimitry Andric /// identifier
12830b57cec5SDimitry Andric ///
12840b57cec5SDimitry Andric /// opt-strict:
12850b57cec5SDimitry Andric /// 'strict' ','
12860b57cec5SDimitry Andric ///
12870b57cec5SDimitry Andric /// version-arg-list:
12880b57cec5SDimitry Andric /// version-arg
12890b57cec5SDimitry Andric /// version-arg ',' version-arg-list
12900b57cec5SDimitry Andric ///
12910b57cec5SDimitry Andric /// version-arg:
12920b57cec5SDimitry Andric /// 'introduced' '=' version
12930b57cec5SDimitry Andric /// 'deprecated' '=' version
12940b57cec5SDimitry Andric /// 'obsoleted' = version
12950b57cec5SDimitry Andric /// 'unavailable'
12960b57cec5SDimitry Andric /// opt-replacement:
12970b57cec5SDimitry Andric /// 'replacement' '=' <string>
12980b57cec5SDimitry Andric /// opt-message:
12990b57cec5SDimitry Andric /// 'message' '=' <string>
ParseAvailabilityAttribute(IdentifierInfo & Availability,SourceLocation AvailabilityLoc,ParsedAttributes & attrs,SourceLocation * endLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)130006c3fb27SDimitry Andric void Parser::ParseAvailabilityAttribute(
130106c3fb27SDimitry Andric IdentifierInfo &Availability, SourceLocation AvailabilityLoc,
130206c3fb27SDimitry Andric ParsedAttributes &attrs, SourceLocation *endLoc, IdentifierInfo *ScopeName,
130306c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
13040b57cec5SDimitry Andric enum { Introduced, Deprecated, Obsoleted, Unknown };
13050b57cec5SDimitry Andric AvailabilityChange Changes[Unknown];
13060b57cec5SDimitry Andric ExprResult MessageExpr, ReplacementExpr;
1307*0fca6ea1SDimitry Andric IdentifierLoc *EnvironmentLoc = nullptr;
13080b57cec5SDimitry Andric
13090b57cec5SDimitry Andric // Opening '('.
13100b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
13110b57cec5SDimitry Andric if (T.consumeOpen()) {
13120b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren;
13130b57cec5SDimitry Andric return;
13140b57cec5SDimitry Andric }
13150b57cec5SDimitry Andric
13160b57cec5SDimitry Andric // Parse the platform name.
13170b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
13180b57cec5SDimitry Andric Diag(Tok, diag::err_availability_expected_platform);
13190b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
13200b57cec5SDimitry Andric return;
13210b57cec5SDimitry Andric }
13220b57cec5SDimitry Andric IdentifierLoc *Platform = ParseIdentifierLoc();
13230b57cec5SDimitry Andric if (const IdentifierInfo *const Ident = Platform->Ident) {
1324*0fca6ea1SDimitry Andric // Disallow xrOS for availability attributes.
1325*0fca6ea1SDimitry Andric if (Ident->getName().contains("xrOS") || Ident->getName().contains("xros"))
1326*0fca6ea1SDimitry Andric Diag(Platform->Loc, diag::warn_availability_unknown_platform) << Ident;
13270b57cec5SDimitry Andric // Canonicalize platform name from "macosx" to "macos".
1328*0fca6ea1SDimitry Andric else if (Ident->getName() == "macosx")
13290b57cec5SDimitry Andric Platform->Ident = PP.getIdentifierInfo("macos");
13300b57cec5SDimitry Andric // Canonicalize platform name from "macosx_app_extension" to
13310b57cec5SDimitry Andric // "macos_app_extension".
13320b57cec5SDimitry Andric else if (Ident->getName() == "macosx_app_extension")
13330b57cec5SDimitry Andric Platform->Ident = PP.getIdentifierInfo("macos_app_extension");
13340b57cec5SDimitry Andric else
13350b57cec5SDimitry Andric Platform->Ident = PP.getIdentifierInfo(
13360b57cec5SDimitry Andric AvailabilityAttr::canonicalizePlatformName(Ident->getName()));
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric
13390b57cec5SDimitry Andric // Parse the ',' following the platform name.
13400b57cec5SDimitry Andric if (ExpectAndConsume(tok::comma)) {
13410b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
13420b57cec5SDimitry Andric return;
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric
13450b57cec5SDimitry Andric // If we haven't grabbed the pointers for the identifiers
13460b57cec5SDimitry Andric // "introduced", "deprecated", and "obsoleted", do so now.
13470b57cec5SDimitry Andric if (!Ident_introduced) {
13480b57cec5SDimitry Andric Ident_introduced = PP.getIdentifierInfo("introduced");
13490b57cec5SDimitry Andric Ident_deprecated = PP.getIdentifierInfo("deprecated");
13500b57cec5SDimitry Andric Ident_obsoleted = PP.getIdentifierInfo("obsoleted");
13510b57cec5SDimitry Andric Ident_unavailable = PP.getIdentifierInfo("unavailable");
13520b57cec5SDimitry Andric Ident_message = PP.getIdentifierInfo("message");
13530b57cec5SDimitry Andric Ident_strict = PP.getIdentifierInfo("strict");
13540b57cec5SDimitry Andric Ident_replacement = PP.getIdentifierInfo("replacement");
1355*0fca6ea1SDimitry Andric Ident_environment = PP.getIdentifierInfo("environment");
13560b57cec5SDimitry Andric }
13570b57cec5SDimitry Andric
13580b57cec5SDimitry Andric // Parse the optional "strict", the optional "replacement" and the set of
13590b57cec5SDimitry Andric // introductions/deprecations/removals.
13600b57cec5SDimitry Andric SourceLocation UnavailableLoc, StrictLoc;
13610b57cec5SDimitry Andric do {
13620b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
13630b57cec5SDimitry Andric Diag(Tok, diag::err_availability_expected_change);
13640b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
13650b57cec5SDimitry Andric return;
13660b57cec5SDimitry Andric }
13670b57cec5SDimitry Andric IdentifierInfo *Keyword = Tok.getIdentifierInfo();
13680b57cec5SDimitry Andric SourceLocation KeywordLoc = ConsumeToken();
13690b57cec5SDimitry Andric
13700b57cec5SDimitry Andric if (Keyword == Ident_strict) {
13710b57cec5SDimitry Andric if (StrictLoc.isValid()) {
13720b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_availability_redundant)
13730b57cec5SDimitry Andric << Keyword << SourceRange(StrictLoc);
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric StrictLoc = KeywordLoc;
13760b57cec5SDimitry Andric continue;
13770b57cec5SDimitry Andric }
13780b57cec5SDimitry Andric
13790b57cec5SDimitry Andric if (Keyword == Ident_unavailable) {
13800b57cec5SDimitry Andric if (UnavailableLoc.isValid()) {
13810b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_availability_redundant)
13820b57cec5SDimitry Andric << Keyword << SourceRange(UnavailableLoc);
13830b57cec5SDimitry Andric }
13840b57cec5SDimitry Andric UnavailableLoc = KeywordLoc;
13850b57cec5SDimitry Andric continue;
13860b57cec5SDimitry Andric }
13870b57cec5SDimitry Andric
13880b57cec5SDimitry Andric if (Keyword == Ident_deprecated && Platform->Ident &&
13890b57cec5SDimitry Andric Platform->Ident->isStr("swift")) {
13900b57cec5SDimitry Andric // For swift, we deprecate for all versions.
13910b57cec5SDimitry Andric if (Changes[Deprecated].KeywordLoc.isValid()) {
13920b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_availability_redundant)
13930b57cec5SDimitry Andric << Keyword
13940b57cec5SDimitry Andric << SourceRange(Changes[Deprecated].KeywordLoc);
13950b57cec5SDimitry Andric }
13960b57cec5SDimitry Andric
13970b57cec5SDimitry Andric Changes[Deprecated].KeywordLoc = KeywordLoc;
13980b57cec5SDimitry Andric // Use a fake version here.
13990b57cec5SDimitry Andric Changes[Deprecated].Version = VersionTuple(1);
14000b57cec5SDimitry Andric continue;
14010b57cec5SDimitry Andric }
14020b57cec5SDimitry Andric
1403*0fca6ea1SDimitry Andric if (Keyword == Ident_environment) {
1404*0fca6ea1SDimitry Andric if (EnvironmentLoc != nullptr) {
1405*0fca6ea1SDimitry Andric Diag(KeywordLoc, diag::err_availability_redundant)
1406*0fca6ea1SDimitry Andric << Keyword << SourceRange(EnvironmentLoc->Loc);
1407*0fca6ea1SDimitry Andric }
1408*0fca6ea1SDimitry Andric }
1409*0fca6ea1SDimitry Andric
14100b57cec5SDimitry Andric if (Tok.isNot(tok::equal)) {
14110b57cec5SDimitry Andric Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
14120b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
14130b57cec5SDimitry Andric return;
14140b57cec5SDimitry Andric }
14150b57cec5SDimitry Andric ConsumeToken();
14160b57cec5SDimitry Andric if (Keyword == Ident_message || Keyword == Ident_replacement) {
14175f757f3fSDimitry Andric if (!isTokenStringLiteral()) {
14180b57cec5SDimitry Andric Diag(Tok, diag::err_expected_string_literal)
14190b57cec5SDimitry Andric << /*Source='availability attribute'*/2;
14200b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
14210b57cec5SDimitry Andric return;
14220b57cec5SDimitry Andric }
14235f757f3fSDimitry Andric if (Keyword == Ident_message) {
14245f757f3fSDimitry Andric MessageExpr = ParseUnevaluatedStringLiteralExpression();
14250b57cec5SDimitry Andric break;
14265f757f3fSDimitry Andric } else {
14275f757f3fSDimitry Andric ReplacementExpr = ParseUnevaluatedStringLiteralExpression();
14280b57cec5SDimitry Andric continue;
14290b57cec5SDimitry Andric }
14305f757f3fSDimitry Andric }
1431*0fca6ea1SDimitry Andric if (Keyword == Ident_environment) {
1432*0fca6ea1SDimitry Andric if (Tok.isNot(tok::identifier)) {
1433*0fca6ea1SDimitry Andric Diag(Tok, diag::err_availability_expected_environment);
1434*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
1435*0fca6ea1SDimitry Andric return;
1436*0fca6ea1SDimitry Andric }
1437*0fca6ea1SDimitry Andric EnvironmentLoc = ParseIdentifierLoc();
1438*0fca6ea1SDimitry Andric continue;
1439*0fca6ea1SDimitry Andric }
14400b57cec5SDimitry Andric
14410b57cec5SDimitry Andric // Special handling of 'NA' only when applied to introduced or
14420b57cec5SDimitry Andric // deprecated.
14430b57cec5SDimitry Andric if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) &&
14440b57cec5SDimitry Andric Tok.is(tok::identifier)) {
14450b57cec5SDimitry Andric IdentifierInfo *NA = Tok.getIdentifierInfo();
14460b57cec5SDimitry Andric if (NA->getName() == "NA") {
14470b57cec5SDimitry Andric ConsumeToken();
14480b57cec5SDimitry Andric if (Keyword == Ident_introduced)
14490b57cec5SDimitry Andric UnavailableLoc = KeywordLoc;
14500b57cec5SDimitry Andric continue;
14510b57cec5SDimitry Andric }
14520b57cec5SDimitry Andric }
14530b57cec5SDimitry Andric
14540b57cec5SDimitry Andric SourceRange VersionRange;
14550b57cec5SDimitry Andric VersionTuple Version = ParseVersionTuple(VersionRange);
14560b57cec5SDimitry Andric
14570b57cec5SDimitry Andric if (Version.empty()) {
14580b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
14590b57cec5SDimitry Andric return;
14600b57cec5SDimitry Andric }
14610b57cec5SDimitry Andric
14620b57cec5SDimitry Andric unsigned Index;
14630b57cec5SDimitry Andric if (Keyword == Ident_introduced)
14640b57cec5SDimitry Andric Index = Introduced;
14650b57cec5SDimitry Andric else if (Keyword == Ident_deprecated)
14660b57cec5SDimitry Andric Index = Deprecated;
14670b57cec5SDimitry Andric else if (Keyword == Ident_obsoleted)
14680b57cec5SDimitry Andric Index = Obsoleted;
14690b57cec5SDimitry Andric else
14700b57cec5SDimitry Andric Index = Unknown;
14710b57cec5SDimitry Andric
14720b57cec5SDimitry Andric if (Index < Unknown) {
14730b57cec5SDimitry Andric if (!Changes[Index].KeywordLoc.isInvalid()) {
14740b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_availability_redundant)
14750b57cec5SDimitry Andric << Keyword
14760b57cec5SDimitry Andric << SourceRange(Changes[Index].KeywordLoc,
14770b57cec5SDimitry Andric Changes[Index].VersionRange.getEnd());
14780b57cec5SDimitry Andric }
14790b57cec5SDimitry Andric
14800b57cec5SDimitry Andric Changes[Index].KeywordLoc = KeywordLoc;
14810b57cec5SDimitry Andric Changes[Index].Version = Version;
14820b57cec5SDimitry Andric Changes[Index].VersionRange = VersionRange;
14830b57cec5SDimitry Andric } else {
14840b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_availability_unknown_change)
14850b57cec5SDimitry Andric << Keyword << VersionRange;
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric
14880b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma));
14890b57cec5SDimitry Andric
14900b57cec5SDimitry Andric // Closing ')'.
14910b57cec5SDimitry Andric if (T.consumeClose())
14920b57cec5SDimitry Andric return;
14930b57cec5SDimitry Andric
14940b57cec5SDimitry Andric if (endLoc)
14950b57cec5SDimitry Andric *endLoc = T.getCloseLocation();
14960b57cec5SDimitry Andric
14970b57cec5SDimitry Andric // The 'unavailable' availability cannot be combined with any other
14980b57cec5SDimitry Andric // availability changes. Make sure that hasn't happened.
14990b57cec5SDimitry Andric if (UnavailableLoc.isValid()) {
15000b57cec5SDimitry Andric bool Complained = false;
15010b57cec5SDimitry Andric for (unsigned Index = Introduced; Index != Unknown; ++Index) {
15020b57cec5SDimitry Andric if (Changes[Index].KeywordLoc.isValid()) {
15030b57cec5SDimitry Andric if (!Complained) {
15040b57cec5SDimitry Andric Diag(UnavailableLoc, diag::warn_availability_and_unavailable)
15050b57cec5SDimitry Andric << SourceRange(Changes[Index].KeywordLoc,
15060b57cec5SDimitry Andric Changes[Index].VersionRange.getEnd());
15070b57cec5SDimitry Andric Complained = true;
15080b57cec5SDimitry Andric }
15090b57cec5SDimitry Andric
15100b57cec5SDimitry Andric // Clear out the availability.
15110b57cec5SDimitry Andric Changes[Index] = AvailabilityChange();
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric }
15140b57cec5SDimitry Andric }
15150b57cec5SDimitry Andric
15160b57cec5SDimitry Andric // Record this attribute
15170b57cec5SDimitry Andric attrs.addNew(&Availability,
151806c3fb27SDimitry Andric SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName,
151906c3fb27SDimitry Andric ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated],
152006c3fb27SDimitry Andric Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), Form,
1521*0fca6ea1SDimitry Andric StrictLoc, ReplacementExpr.get(), EnvironmentLoc);
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric
15240b57cec5SDimitry Andric /// Parse the contents of the "external_source_symbol" attribute.
15250b57cec5SDimitry Andric ///
15260b57cec5SDimitry Andric /// external-source-symbol-attribute:
15270b57cec5SDimitry Andric /// 'external_source_symbol' '(' keyword-arg-list ')'
15280b57cec5SDimitry Andric ///
15290b57cec5SDimitry Andric /// keyword-arg-list:
15300b57cec5SDimitry Andric /// keyword-arg
15310b57cec5SDimitry Andric /// keyword-arg ',' keyword-arg-list
15320b57cec5SDimitry Andric ///
15330b57cec5SDimitry Andric /// keyword-arg:
15340b57cec5SDimitry Andric /// 'language' '=' <string>
15350b57cec5SDimitry Andric /// 'defined_in' '=' <string>
153606c3fb27SDimitry Andric /// 'USR' '=' <string>
15370b57cec5SDimitry Andric /// 'generated_declaration'
ParseExternalSourceSymbolAttribute(IdentifierInfo & ExternalSourceSymbol,SourceLocation Loc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)15380b57cec5SDimitry Andric void Parser::ParseExternalSourceSymbolAttribute(
15390b57cec5SDimitry Andric IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,
15400b57cec5SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
154106c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
15420b57cec5SDimitry Andric // Opening '('.
15430b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
15440b57cec5SDimitry Andric if (T.expectAndConsume())
15450b57cec5SDimitry Andric return;
15460b57cec5SDimitry Andric
15470b57cec5SDimitry Andric // Initialize the pointers for the keyword identifiers when required.
15480b57cec5SDimitry Andric if (!Ident_language) {
15490b57cec5SDimitry Andric Ident_language = PP.getIdentifierInfo("language");
15500b57cec5SDimitry Andric Ident_defined_in = PP.getIdentifierInfo("defined_in");
15510b57cec5SDimitry Andric Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration");
155206c3fb27SDimitry Andric Ident_USR = PP.getIdentifierInfo("USR");
15530b57cec5SDimitry Andric }
15540b57cec5SDimitry Andric
15550b57cec5SDimitry Andric ExprResult Language;
15560b57cec5SDimitry Andric bool HasLanguage = false;
15570b57cec5SDimitry Andric ExprResult DefinedInExpr;
15580b57cec5SDimitry Andric bool HasDefinedIn = false;
15590b57cec5SDimitry Andric IdentifierLoc *GeneratedDeclaration = nullptr;
156006c3fb27SDimitry Andric ExprResult USR;
156106c3fb27SDimitry Andric bool HasUSR = false;
15620b57cec5SDimitry Andric
15630b57cec5SDimitry Andric // Parse the language/defined_in/generated_declaration keywords
15640b57cec5SDimitry Andric do {
15650b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
15660b57cec5SDimitry Andric Diag(Tok, diag::err_external_source_symbol_expected_keyword);
15670b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
15680b57cec5SDimitry Andric return;
15690b57cec5SDimitry Andric }
15700b57cec5SDimitry Andric
15710b57cec5SDimitry Andric SourceLocation KeywordLoc = Tok.getLocation();
15720b57cec5SDimitry Andric IdentifierInfo *Keyword = Tok.getIdentifierInfo();
15730b57cec5SDimitry Andric if (Keyword == Ident_generated_declaration) {
15740b57cec5SDimitry Andric if (GeneratedDeclaration) {
15750b57cec5SDimitry Andric Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword;
15760b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
15770b57cec5SDimitry Andric return;
15780b57cec5SDimitry Andric }
15790b57cec5SDimitry Andric GeneratedDeclaration = ParseIdentifierLoc();
15800b57cec5SDimitry Andric continue;
15810b57cec5SDimitry Andric }
15820b57cec5SDimitry Andric
158306c3fb27SDimitry Andric if (Keyword != Ident_language && Keyword != Ident_defined_in &&
158406c3fb27SDimitry Andric Keyword != Ident_USR) {
15850b57cec5SDimitry Andric Diag(Tok, diag::err_external_source_symbol_expected_keyword);
15860b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
15870b57cec5SDimitry Andric return;
15880b57cec5SDimitry Andric }
15890b57cec5SDimitry Andric
15900b57cec5SDimitry Andric ConsumeToken();
15910b57cec5SDimitry Andric if (ExpectAndConsume(tok::equal, diag::err_expected_after,
15920b57cec5SDimitry Andric Keyword->getName())) {
15930b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
15940b57cec5SDimitry Andric return;
15950b57cec5SDimitry Andric }
15960b57cec5SDimitry Andric
159706c3fb27SDimitry Andric bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn,
159806c3fb27SDimitry Andric HadUSR = HasUSR;
15990b57cec5SDimitry Andric if (Keyword == Ident_language)
16000b57cec5SDimitry Andric HasLanguage = true;
160106c3fb27SDimitry Andric else if (Keyword == Ident_USR)
160206c3fb27SDimitry Andric HasUSR = true;
16030b57cec5SDimitry Andric else
16040b57cec5SDimitry Andric HasDefinedIn = true;
16050b57cec5SDimitry Andric
16065f757f3fSDimitry Andric if (!isTokenStringLiteral()) {
16070b57cec5SDimitry Andric Diag(Tok, diag::err_expected_string_literal)
16080b57cec5SDimitry Andric << /*Source='external_source_symbol attribute'*/ 3
160906c3fb27SDimitry Andric << /*language | source container | USR*/ (
161006c3fb27SDimitry Andric Keyword == Ident_language
161106c3fb27SDimitry Andric ? 0
161206c3fb27SDimitry Andric : (Keyword == Ident_defined_in ? 1 : 2));
16130b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
16140b57cec5SDimitry Andric continue;
16150b57cec5SDimitry Andric }
16160b57cec5SDimitry Andric if (Keyword == Ident_language) {
16170b57cec5SDimitry Andric if (HadLanguage) {
16180b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
16190b57cec5SDimitry Andric << Keyword;
16205f757f3fSDimitry Andric ParseUnevaluatedStringLiteralExpression();
16210b57cec5SDimitry Andric continue;
16220b57cec5SDimitry Andric }
16235f757f3fSDimitry Andric Language = ParseUnevaluatedStringLiteralExpression();
162406c3fb27SDimitry Andric } else if (Keyword == Ident_USR) {
162506c3fb27SDimitry Andric if (HadUSR) {
162606c3fb27SDimitry Andric Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
162706c3fb27SDimitry Andric << Keyword;
16285f757f3fSDimitry Andric ParseUnevaluatedStringLiteralExpression();
162906c3fb27SDimitry Andric continue;
163006c3fb27SDimitry Andric }
16315f757f3fSDimitry Andric USR = ParseUnevaluatedStringLiteralExpression();
16320b57cec5SDimitry Andric } else {
16330b57cec5SDimitry Andric assert(Keyword == Ident_defined_in && "Invalid clause keyword!");
16340b57cec5SDimitry Andric if (HadDefinedIn) {
16350b57cec5SDimitry Andric Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
16360b57cec5SDimitry Andric << Keyword;
16375f757f3fSDimitry Andric ParseUnevaluatedStringLiteralExpression();
16380b57cec5SDimitry Andric continue;
16390b57cec5SDimitry Andric }
16405f757f3fSDimitry Andric DefinedInExpr = ParseUnevaluatedStringLiteralExpression();
16410b57cec5SDimitry Andric }
16420b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma));
16430b57cec5SDimitry Andric
16440b57cec5SDimitry Andric // Closing ')'.
16450b57cec5SDimitry Andric if (T.consumeClose())
16460b57cec5SDimitry Andric return;
16470b57cec5SDimitry Andric if (EndLoc)
16480b57cec5SDimitry Andric *EndLoc = T.getCloseLocation();
16490b57cec5SDimitry Andric
165006c3fb27SDimitry Andric ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), GeneratedDeclaration,
165106c3fb27SDimitry Andric USR.get()};
16520b57cec5SDimitry Andric Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()),
165306c3fb27SDimitry Andric ScopeName, ScopeLoc, Args, std::size(Args), Form);
16540b57cec5SDimitry Andric }
16550b57cec5SDimitry Andric
16560b57cec5SDimitry Andric /// Parse the contents of the "objc_bridge_related" attribute.
16570b57cec5SDimitry Andric /// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
16580b57cec5SDimitry Andric /// related_class:
16590b57cec5SDimitry Andric /// Identifier
16600b57cec5SDimitry Andric ///
16610b57cec5SDimitry Andric /// opt-class_method:
16620b57cec5SDimitry Andric /// Identifier: | <empty>
16630b57cec5SDimitry Andric ///
16640b57cec5SDimitry Andric /// opt-instance_method:
16650b57cec5SDimitry Andric /// Identifier | <empty>
16660b57cec5SDimitry Andric ///
ParseObjCBridgeRelatedAttribute(IdentifierInfo & ObjCBridgeRelated,SourceLocation ObjCBridgeRelatedLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)166781ad6265SDimitry Andric void Parser::ParseObjCBridgeRelatedAttribute(
166881ad6265SDimitry Andric IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc,
166981ad6265SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
167006c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
16710b57cec5SDimitry Andric // Opening '('.
16720b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
16730b57cec5SDimitry Andric if (T.consumeOpen()) {
16740b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren;
16750b57cec5SDimitry Andric return;
16760b57cec5SDimitry Andric }
16770b57cec5SDimitry Andric
16780b57cec5SDimitry Andric // Parse the related class name.
16790b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
16800b57cec5SDimitry Andric Diag(Tok, diag::err_objcbridge_related_expected_related_class);
16810b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
16820b57cec5SDimitry Andric return;
16830b57cec5SDimitry Andric }
16840b57cec5SDimitry Andric IdentifierLoc *RelatedClass = ParseIdentifierLoc();
16850b57cec5SDimitry Andric if (ExpectAndConsume(tok::comma)) {
16860b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
16870b57cec5SDimitry Andric return;
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric
16900b57cec5SDimitry Andric // Parse class method name. It's non-optional in the sense that a trailing
16910b57cec5SDimitry Andric // comma is required, but it can be the empty string, and then we record a
16920b57cec5SDimitry Andric // nullptr.
16930b57cec5SDimitry Andric IdentifierLoc *ClassMethod = nullptr;
16940b57cec5SDimitry Andric if (Tok.is(tok::identifier)) {
16950b57cec5SDimitry Andric ClassMethod = ParseIdentifierLoc();
16960b57cec5SDimitry Andric if (!TryConsumeToken(tok::colon)) {
16970b57cec5SDimitry Andric Diag(Tok, diag::err_objcbridge_related_selector_name);
16980b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
16990b57cec5SDimitry Andric return;
17000b57cec5SDimitry Andric }
17010b57cec5SDimitry Andric }
17020b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma)) {
17030b57cec5SDimitry Andric if (Tok.is(tok::colon))
17040b57cec5SDimitry Andric Diag(Tok, diag::err_objcbridge_related_selector_name);
17050b57cec5SDimitry Andric else
17060b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::comma;
17070b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
17080b57cec5SDimitry Andric return;
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric
17110b57cec5SDimitry Andric // Parse instance method name. Also non-optional but empty string is
17120b57cec5SDimitry Andric // permitted.
17130b57cec5SDimitry Andric IdentifierLoc *InstanceMethod = nullptr;
17140b57cec5SDimitry Andric if (Tok.is(tok::identifier))
17150b57cec5SDimitry Andric InstanceMethod = ParseIdentifierLoc();
17160b57cec5SDimitry Andric else if (Tok.isNot(tok::r_paren)) {
17170b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::r_paren;
17180b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
17190b57cec5SDimitry Andric return;
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric
17220b57cec5SDimitry Andric // Closing ')'.
17230b57cec5SDimitry Andric if (T.consumeClose())
17240b57cec5SDimitry Andric return;
17250b57cec5SDimitry Andric
172681ad6265SDimitry Andric if (EndLoc)
172781ad6265SDimitry Andric *EndLoc = T.getCloseLocation();
17280b57cec5SDimitry Andric
17290b57cec5SDimitry Andric // Record this attribute
173081ad6265SDimitry Andric Attrs.addNew(&ObjCBridgeRelated,
17310b57cec5SDimitry Andric SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
173281ad6265SDimitry Andric ScopeName, ScopeLoc, RelatedClass, ClassMethod, InstanceMethod,
173306c3fb27SDimitry Andric Form);
17340b57cec5SDimitry Andric }
17350b57cec5SDimitry Andric
ParseSwiftNewTypeAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)1736e8d8bef9SDimitry Andric void Parser::ParseSwiftNewTypeAttribute(
1737e8d8bef9SDimitry Andric IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
1738e8d8bef9SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
173906c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
1740e8d8bef9SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
1741e8d8bef9SDimitry Andric
1742e8d8bef9SDimitry Andric // Opening '('
1743e8d8bef9SDimitry Andric if (T.consumeOpen()) {
1744e8d8bef9SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren;
1745e8d8bef9SDimitry Andric return;
1746e8d8bef9SDimitry Andric }
1747e8d8bef9SDimitry Andric
1748e8d8bef9SDimitry Andric if (Tok.is(tok::r_paren)) {
1749e8d8bef9SDimitry Andric Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
1750e8d8bef9SDimitry Andric T.consumeClose();
1751e8d8bef9SDimitry Andric return;
1752e8d8bef9SDimitry Andric }
1753e8d8bef9SDimitry Andric if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
1754e8d8bef9SDimitry Andric Diag(Tok, diag::warn_attribute_type_not_supported)
1755e8d8bef9SDimitry Andric << &AttrName << Tok.getIdentifierInfo();
1756e8d8bef9SDimitry Andric if (!isTokenSpecial())
1757e8d8bef9SDimitry Andric ConsumeToken();
1758e8d8bef9SDimitry Andric T.consumeClose();
1759e8d8bef9SDimitry Andric return;
1760e8d8bef9SDimitry Andric }
1761e8d8bef9SDimitry Andric
1762e8d8bef9SDimitry Andric auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
1763e8d8bef9SDimitry Andric Tok.getIdentifierInfo());
1764e8d8bef9SDimitry Andric ConsumeToken();
1765e8d8bef9SDimitry Andric
1766e8d8bef9SDimitry Andric // Closing ')'
1767e8d8bef9SDimitry Andric if (T.consumeClose())
1768e8d8bef9SDimitry Andric return;
1769e8d8bef9SDimitry Andric if (EndLoc)
1770e8d8bef9SDimitry Andric *EndLoc = T.getCloseLocation();
1771e8d8bef9SDimitry Andric
1772e8d8bef9SDimitry Andric ArgsUnion Args[] = {SwiftType};
1773e8d8bef9SDimitry Andric Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()),
177406c3fb27SDimitry Andric ScopeName, ScopeLoc, Args, std::size(Args), Form);
1775e8d8bef9SDimitry Andric }
1776e8d8bef9SDimitry Andric
ParseTypeTagForDatatypeAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)177706c3fb27SDimitry Andric void Parser::ParseTypeTagForDatatypeAttribute(
177806c3fb27SDimitry Andric IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
177906c3fb27SDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
178006c3fb27SDimitry Andric SourceLocation ScopeLoc, ParsedAttr::Form Form) {
17810b57cec5SDimitry Andric assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
17820b57cec5SDimitry Andric
17830b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
17840b57cec5SDimitry Andric T.consumeOpen();
17850b57cec5SDimitry Andric
17860b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
17870b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier;
17880b57cec5SDimitry Andric T.skipToEnd();
17890b57cec5SDimitry Andric return;
17900b57cec5SDimitry Andric }
17910b57cec5SDimitry Andric IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
17920b57cec5SDimitry Andric
17930b57cec5SDimitry Andric if (ExpectAndConsume(tok::comma)) {
17940b57cec5SDimitry Andric T.skipToEnd();
17950b57cec5SDimitry Andric return;
17960b57cec5SDimitry Andric }
17970b57cec5SDimitry Andric
17980b57cec5SDimitry Andric SourceRange MatchingCTypeRange;
17990b57cec5SDimitry Andric TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange);
18000b57cec5SDimitry Andric if (MatchingCType.isInvalid()) {
18010b57cec5SDimitry Andric T.skipToEnd();
18020b57cec5SDimitry Andric return;
18030b57cec5SDimitry Andric }
18040b57cec5SDimitry Andric
18050b57cec5SDimitry Andric bool LayoutCompatible = false;
18060b57cec5SDimitry Andric bool MustBeNull = false;
18070b57cec5SDimitry Andric while (TryConsumeToken(tok::comma)) {
18080b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
18090b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier;
18100b57cec5SDimitry Andric T.skipToEnd();
18110b57cec5SDimitry Andric return;
18120b57cec5SDimitry Andric }
18130b57cec5SDimitry Andric IdentifierInfo *Flag = Tok.getIdentifierInfo();
18140b57cec5SDimitry Andric if (Flag->isStr("layout_compatible"))
18150b57cec5SDimitry Andric LayoutCompatible = true;
18160b57cec5SDimitry Andric else if (Flag->isStr("must_be_null"))
18170b57cec5SDimitry Andric MustBeNull = true;
18180b57cec5SDimitry Andric else {
18190b57cec5SDimitry Andric Diag(Tok, diag::err_type_safety_unknown_flag) << Flag;
18200b57cec5SDimitry Andric T.skipToEnd();
18210b57cec5SDimitry Andric return;
18220b57cec5SDimitry Andric }
18230b57cec5SDimitry Andric ConsumeToken(); // consume flag
18240b57cec5SDimitry Andric }
18250b57cec5SDimitry Andric
18260b57cec5SDimitry Andric if (!T.consumeClose()) {
18270b57cec5SDimitry Andric Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc,
18280b57cec5SDimitry Andric ArgumentKind, MatchingCType.get(),
182906c3fb27SDimitry Andric LayoutCompatible, MustBeNull, Form);
18300b57cec5SDimitry Andric }
18310b57cec5SDimitry Andric
18320b57cec5SDimitry Andric if (EndLoc)
18330b57cec5SDimitry Andric *EndLoc = T.getCloseLocation();
18340b57cec5SDimitry Andric }
18350b57cec5SDimitry Andric
18360b57cec5SDimitry Andric /// DiagnoseProhibitedCXX11Attribute - We have found the opening square brackets
18370b57cec5SDimitry Andric /// of a C++11 attribute-specifier in a location where an attribute is not
18380b57cec5SDimitry Andric /// permitted. By C++11 [dcl.attr.grammar]p6, this is ill-formed. Diagnose this
18390b57cec5SDimitry Andric /// situation.
18400b57cec5SDimitry Andric ///
18410b57cec5SDimitry Andric /// \return \c true if we skipped an attribute-like chunk of tokens, \c false if
18420b57cec5SDimitry Andric /// this doesn't appear to actually be an attribute-specifier, and the caller
18430b57cec5SDimitry Andric /// should try to parse it.
DiagnoseProhibitedCXX11Attribute()18440b57cec5SDimitry Andric bool Parser::DiagnoseProhibitedCXX11Attribute() {
18450b57cec5SDimitry Andric assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square));
18460b57cec5SDimitry Andric
18470b57cec5SDimitry Andric switch (isCXX11AttributeSpecifier(/*Disambiguate*/true)) {
18480b57cec5SDimitry Andric case CAK_NotAttributeSpecifier:
18490b57cec5SDimitry Andric // No diagnostic: we're in Obj-C++11 and this is not actually an attribute.
18500b57cec5SDimitry Andric return false;
18510b57cec5SDimitry Andric
18520b57cec5SDimitry Andric case CAK_InvalidAttributeSpecifier:
18530b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_l_square_l_square_not_attribute);
18540b57cec5SDimitry Andric return false;
18550b57cec5SDimitry Andric
18560b57cec5SDimitry Andric case CAK_AttributeSpecifier:
18570b57cec5SDimitry Andric // Parse and discard the attributes.
18580b57cec5SDimitry Andric SourceLocation BeginLoc = ConsumeBracket();
18590b57cec5SDimitry Andric ConsumeBracket();
18600b57cec5SDimitry Andric SkipUntil(tok::r_square);
18610b57cec5SDimitry Andric assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied");
18620b57cec5SDimitry Andric SourceLocation EndLoc = ConsumeBracket();
18630b57cec5SDimitry Andric Diag(BeginLoc, diag::err_attributes_not_allowed)
18640b57cec5SDimitry Andric << SourceRange(BeginLoc, EndLoc);
18650b57cec5SDimitry Andric return true;
18660b57cec5SDimitry Andric }
18670b57cec5SDimitry Andric llvm_unreachable("All cases handled above.");
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric
18700b57cec5SDimitry Andric /// We have found the opening square brackets of a C++11
18710b57cec5SDimitry Andric /// attribute-specifier in a location where an attribute is not permitted, but
18720b57cec5SDimitry Andric /// we know where the attributes ought to be written. Parse them anyway, and
18730b57cec5SDimitry Andric /// provide a fixit moving them to the right place.
DiagnoseMisplacedCXX11Attribute(ParsedAttributes & Attrs,SourceLocation CorrectLocation)187481ad6265SDimitry Andric void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs,
18750b57cec5SDimitry Andric SourceLocation CorrectLocation) {
18760b57cec5SDimitry Andric assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
187706c3fb27SDimitry Andric Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute());
18780b57cec5SDimitry Andric
18790b57cec5SDimitry Andric // Consume the attributes.
188006c3fb27SDimitry Andric auto Keyword =
188106c3fb27SDimitry Andric Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;
18820b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
18830b57cec5SDimitry Andric ParseCXX11Attributes(Attrs);
18840b57cec5SDimitry Andric CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
18850b57cec5SDimitry Andric // FIXME: use err_attributes_misplaced
188606c3fb27SDimitry Andric (Keyword ? Diag(Loc, diag::err_keyword_not_allowed) << Keyword
188706c3fb27SDimitry Andric : Diag(Loc, diag::err_attributes_not_allowed))
18880b57cec5SDimitry Andric << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
18890b57cec5SDimitry Andric << FixItHint::CreateRemoval(AttrRange);
18900b57cec5SDimitry Andric }
18910b57cec5SDimitry Andric
DiagnoseProhibitedAttributes(const ParsedAttributesView & Attrs,const SourceLocation CorrectLocation)18920b57cec5SDimitry Andric void Parser::DiagnoseProhibitedAttributes(
189306c3fb27SDimitry Andric const ParsedAttributesView &Attrs, const SourceLocation CorrectLocation) {
189406c3fb27SDimitry Andric auto *FirstAttr = Attrs.empty() ? nullptr : &Attrs.front();
18950b57cec5SDimitry Andric if (CorrectLocation.isValid()) {
189606c3fb27SDimitry Andric CharSourceRange AttrRange(Attrs.Range, true);
189706c3fb27SDimitry Andric (FirstAttr && FirstAttr->isRegularKeywordAttribute()
189806c3fb27SDimitry Andric ? Diag(CorrectLocation, diag::err_keyword_misplaced) << FirstAttr
189906c3fb27SDimitry Andric : Diag(CorrectLocation, diag::err_attributes_misplaced))
19000b57cec5SDimitry Andric << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
19010b57cec5SDimitry Andric << FixItHint::CreateRemoval(AttrRange);
190206c3fb27SDimitry Andric } else {
190306c3fb27SDimitry Andric const SourceRange &Range = Attrs.Range;
190406c3fb27SDimitry Andric (FirstAttr && FirstAttr->isRegularKeywordAttribute()
190506c3fb27SDimitry Andric ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr
190606c3fb27SDimitry Andric : Diag(Range.getBegin(), diag::err_attributes_not_allowed))
190706c3fb27SDimitry Andric << Range;
190806c3fb27SDimitry Andric }
19090b57cec5SDimitry Andric }
19100b57cec5SDimitry Andric
ProhibitCXX11Attributes(ParsedAttributes & Attrs,unsigned AttrDiagID,unsigned KeywordDiagID,bool DiagnoseEmptyAttrs,bool WarnOnUnknownAttrs)191106c3fb27SDimitry Andric void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs,
191206c3fb27SDimitry Andric unsigned AttrDiagID,
191306c3fb27SDimitry Andric unsigned KeywordDiagID,
191481ad6265SDimitry Andric bool DiagnoseEmptyAttrs,
191581ad6265SDimitry Andric bool WarnOnUnknownAttrs) {
1916fe6060f1SDimitry Andric
1917fe6060f1SDimitry Andric if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) {
1918fe6060f1SDimitry Andric // An attribute list has been parsed, but it was empty.
1919fe6060f1SDimitry Andric // This is the case for [[]].
1920fe6060f1SDimitry Andric const auto &LangOpts = getLangOpts();
1921fe6060f1SDimitry Andric auto &SM = PP.getSourceManager();
1922fe6060f1SDimitry Andric Token FirstLSquare;
1923fe6060f1SDimitry Andric Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts);
1924fe6060f1SDimitry Andric
1925fe6060f1SDimitry Andric if (FirstLSquare.is(tok::l_square)) {
1926bdd1243dSDimitry Andric std::optional<Token> SecondLSquare =
1927fe6060f1SDimitry Andric Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts);
1928fe6060f1SDimitry Andric
1929fe6060f1SDimitry Andric if (SecondLSquare && SecondLSquare->is(tok::l_square)) {
1930fe6060f1SDimitry Andric // The attribute range starts with [[, but is empty. So this must
1931fe6060f1SDimitry Andric // be [[]], which we are supposed to diagnose because
1932fe6060f1SDimitry Andric // DiagnoseEmptyAttrs is true.
193306c3fb27SDimitry Andric Diag(Attrs.Range.getBegin(), AttrDiagID) << Attrs.Range;
1934fe6060f1SDimitry Andric return;
1935fe6060f1SDimitry Andric }
1936fe6060f1SDimitry Andric }
1937fe6060f1SDimitry Andric }
1938fe6060f1SDimitry Andric
19390b57cec5SDimitry Andric for (const ParsedAttr &AL : Attrs) {
194006c3fb27SDimitry Andric if (AL.isRegularKeywordAttribute()) {
194106c3fb27SDimitry Andric Diag(AL.getLoc(), KeywordDiagID) << AL;
194206c3fb27SDimitry Andric AL.setInvalid();
194306c3fb27SDimitry Andric continue;
194406c3fb27SDimitry Andric }
19455f757f3fSDimitry Andric if (!AL.isStandardAttributeSyntax())
19460b57cec5SDimitry Andric continue;
194781ad6265SDimitry Andric if (AL.getKind() == ParsedAttr::UnknownAttribute) {
194881ad6265SDimitry Andric if (WarnOnUnknownAttrs)
1949e8d8bef9SDimitry Andric Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
1950e8d8bef9SDimitry Andric << AL << AL.getRange();
195181ad6265SDimitry Andric } else {
195206c3fb27SDimitry Andric Diag(AL.getLoc(), AttrDiagID) << AL;
19530b57cec5SDimitry Andric AL.setInvalid();
19540b57cec5SDimitry Andric }
19550b57cec5SDimitry Andric }
19560b57cec5SDimitry Andric }
19570b57cec5SDimitry Andric
DiagnoseCXX11AttributeExtension(ParsedAttributes & Attrs)195881ad6265SDimitry Andric void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) {
1959fe6060f1SDimitry Andric for (const ParsedAttr &PA : Attrs) {
19605f757f3fSDimitry Andric if (PA.isStandardAttributeSyntax() || PA.isRegularKeywordAttribute())
196106c3fb27SDimitry Andric Diag(PA.getLoc(), diag::ext_cxx11_attr_placement)
196206c3fb27SDimitry Andric << PA << PA.isRegularKeywordAttribute() << PA.getRange();
1963fe6060f1SDimitry Andric }
1964fe6060f1SDimitry Andric }
1965fe6060f1SDimitry Andric
19660b57cec5SDimitry Andric // Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
19670b57cec5SDimitry Andric // applies to var, not the type Foo.
19680b57cec5SDimitry Andric // As an exception to the rule, __declspec(align(...)) before the
19690b57cec5SDimitry Andric // class-key affects the type instead of the variable.
19700b57cec5SDimitry Andric // Also, Microsoft-style [attributes] seem to affect the type instead of the
19710b57cec5SDimitry Andric // variable.
19720b57cec5SDimitry Andric // This function moves attributes that should apply to the type off DS to Attrs.
stripTypeAttributesOffDeclSpec(ParsedAttributes & Attrs,DeclSpec & DS,TagUseKind TUK)197381ad6265SDimitry Andric void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs,
1974*0fca6ea1SDimitry Andric DeclSpec &DS, TagUseKind TUK) {
1975*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Reference)
19760b57cec5SDimitry Andric return;
19770b57cec5SDimitry Andric
19780b57cec5SDimitry Andric llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;
19790b57cec5SDimitry Andric
19800b57cec5SDimitry Andric for (ParsedAttr &AL : DS.getAttributes()) {
19810b57cec5SDimitry Andric if ((AL.getKind() == ParsedAttr::AT_Aligned &&
19820b57cec5SDimitry Andric AL.isDeclspecAttribute()) ||
19830b57cec5SDimitry Andric AL.isMicrosoftAttribute())
19840b57cec5SDimitry Andric ToBeMoved.push_back(&AL);
19850b57cec5SDimitry Andric }
19860b57cec5SDimitry Andric
19870b57cec5SDimitry Andric for (ParsedAttr *AL : ToBeMoved) {
19880b57cec5SDimitry Andric DS.getAttributes().remove(AL);
19890b57cec5SDimitry Andric Attrs.addAtEnd(AL);
19900b57cec5SDimitry Andric }
19910b57cec5SDimitry Andric }
19920b57cec5SDimitry Andric
19930b57cec5SDimitry Andric /// ParseDeclaration - Parse a full 'declaration', which consists of
19940b57cec5SDimitry Andric /// declaration-specifiers, some number of declarators, and a semicolon.
19950b57cec5SDimitry Andric /// 'Context' should be a DeclaratorContext value. This returns the
19960b57cec5SDimitry Andric /// location of the semicolon in DeclEnd.
19970b57cec5SDimitry Andric ///
19980b57cec5SDimitry Andric /// declaration: [C99 6.7]
19990b57cec5SDimitry Andric /// block-declaration ->
20000b57cec5SDimitry Andric /// simple-declaration
20010b57cec5SDimitry Andric /// others [FIXME]
20020b57cec5SDimitry Andric /// [C++] template-declaration
20030b57cec5SDimitry Andric /// [C++] namespace-definition
20040b57cec5SDimitry Andric /// [C++] using-directive
20050b57cec5SDimitry Andric /// [C++] using-declaration
20060b57cec5SDimitry Andric /// [C++11/C11] static_assert-declaration
20070b57cec5SDimitry Andric /// others... [FIXME]
20080b57cec5SDimitry Andric ///
ParseDeclaration(DeclaratorContext Context,SourceLocation & DeclEnd,ParsedAttributes & DeclAttrs,ParsedAttributes & DeclSpecAttrs,SourceLocation * DeclSpecStart)200981ad6265SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
201081ad6265SDimitry Andric SourceLocation &DeclEnd,
201181ad6265SDimitry Andric ParsedAttributes &DeclAttrs,
201281ad6265SDimitry Andric ParsedAttributes &DeclSpecAttrs,
2013a7dea167SDimitry Andric SourceLocation *DeclSpecStart) {
20140b57cec5SDimitry Andric ParenBraceBracketBalancer BalancerRAIIObj(*this);
20150b57cec5SDimitry Andric // Must temporarily exit the objective-c container scope for
20160b57cec5SDimitry Andric // parsing c none objective-c decls.
20170b57cec5SDimitry Andric ObjCDeclContextSwitch ObjCDC(*this);
20180b57cec5SDimitry Andric
20190b57cec5SDimitry Andric Decl *SingleDecl = nullptr;
20200b57cec5SDimitry Andric switch (Tok.getKind()) {
20210b57cec5SDimitry Andric case tok::kw_template:
20220b57cec5SDimitry Andric case tok::kw_export:
202381ad6265SDimitry Andric ProhibitAttributes(DeclAttrs);
202481ad6265SDimitry Andric ProhibitAttributes(DeclSpecAttrs);
2025*0fca6ea1SDimitry Andric return ParseDeclarationStartingWithTemplate(Context, DeclEnd, DeclAttrs);
20260b57cec5SDimitry Andric case tok::kw_inline:
20270b57cec5SDimitry Andric // Could be the start of an inline namespace. Allowed as an ext in C++03.
20280b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) {
202981ad6265SDimitry Andric ProhibitAttributes(DeclAttrs);
203081ad6265SDimitry Andric ProhibitAttributes(DeclSpecAttrs);
20310b57cec5SDimitry Andric SourceLocation InlineLoc = ConsumeToken();
20320b57cec5SDimitry Andric return ParseNamespace(Context, DeclEnd, InlineLoc);
20330b57cec5SDimitry Andric }
203481ad6265SDimitry Andric return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,
203581ad6265SDimitry Andric true, nullptr, DeclSpecStart);
2036bdd1243dSDimitry Andric
2037bdd1243dSDimitry Andric case tok::kw_cbuffer:
2038bdd1243dSDimitry Andric case tok::kw_tbuffer:
2039bdd1243dSDimitry Andric SingleDecl = ParseHLSLBuffer(DeclEnd);
2040bdd1243dSDimitry Andric break;
20410b57cec5SDimitry Andric case tok::kw_namespace:
204281ad6265SDimitry Andric ProhibitAttributes(DeclAttrs);
204381ad6265SDimitry Andric ProhibitAttributes(DeclSpecAttrs);
20440b57cec5SDimitry Andric return ParseNamespace(Context, DeclEnd);
204581ad6265SDimitry Andric case tok::kw_using: {
204681ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory);
204781ad6265SDimitry Andric takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs);
20480b57cec5SDimitry Andric return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
204981ad6265SDimitry Andric DeclEnd, Attrs);
205081ad6265SDimitry Andric }
20510b57cec5SDimitry Andric case tok::kw_static_assert:
20520b57cec5SDimitry Andric case tok::kw__Static_assert:
205381ad6265SDimitry Andric ProhibitAttributes(DeclAttrs);
205481ad6265SDimitry Andric ProhibitAttributes(DeclSpecAttrs);
20550b57cec5SDimitry Andric SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
20560b57cec5SDimitry Andric break;
20570b57cec5SDimitry Andric default:
205881ad6265SDimitry Andric return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,
205981ad6265SDimitry Andric true, nullptr, DeclSpecStart);
20600b57cec5SDimitry Andric }
20610b57cec5SDimitry Andric
20620b57cec5SDimitry Andric // This routine returns a DeclGroup, if the thing we parsed only contains a
20630b57cec5SDimitry Andric // single decl, convert it now.
20640b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(SingleDecl);
20650b57cec5SDimitry Andric }
20660b57cec5SDimitry Andric
20670b57cec5SDimitry Andric /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
20680b57cec5SDimitry Andric /// declaration-specifiers init-declarator-list[opt] ';'
20690b57cec5SDimitry Andric /// [C++11] attribute-specifier-seq decl-specifier-seq[opt]
20700b57cec5SDimitry Andric /// init-declarator-list ';'
20710b57cec5SDimitry Andric ///[C90/C++]init-declarator-list ';' [TODO]
20720b57cec5SDimitry Andric /// [OMP] threadprivate-directive
20730b57cec5SDimitry Andric /// [OMP] allocate-directive [TODO]
20740b57cec5SDimitry Andric ///
20750b57cec5SDimitry Andric /// for-range-declaration: [C++11 6.5p1: stmt.ranged]
20760b57cec5SDimitry Andric /// attribute-specifier-seq[opt] type-specifier-seq declarator
20770b57cec5SDimitry Andric ///
20780b57cec5SDimitry Andric /// If RequireSemi is false, this does not check for a ';' at the end of the
20790b57cec5SDimitry Andric /// declaration. If it is true, it checks for and eats it.
20800b57cec5SDimitry Andric ///
20810b57cec5SDimitry Andric /// If FRI is non-null, we might be parsing a for-range-declaration instead
20820b57cec5SDimitry Andric /// of a simple-declaration. If we find that we are, we also parse the
20830b57cec5SDimitry Andric /// for-range-initializer, and place it here.
2084a7dea167SDimitry Andric ///
2085a7dea167SDimitry Andric /// DeclSpecStart is used when decl-specifiers are parsed before parsing
2086a7dea167SDimitry Andric /// the Declaration. The SourceLocation for this Decl is set to
2087a7dea167SDimitry Andric /// DeclSpecStart if DeclSpecStart is non-null.
ParseSimpleDeclaration(DeclaratorContext Context,SourceLocation & DeclEnd,ParsedAttributes & DeclAttrs,ParsedAttributes & DeclSpecAttrs,bool RequireSemi,ForRangeInit * FRI,SourceLocation * DeclSpecStart)2088a7dea167SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
2089a7dea167SDimitry Andric DeclaratorContext Context, SourceLocation &DeclEnd,
209081ad6265SDimitry Andric ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs,
209181ad6265SDimitry Andric bool RequireSemi, ForRangeInit *FRI, SourceLocation *DeclSpecStart) {
209281ad6265SDimitry Andric // Need to retain these for diagnostics before we add them to the DeclSepc.
209381ad6265SDimitry Andric ParsedAttributesView OriginalDeclSpecAttrs;
209481ad6265SDimitry Andric OriginalDeclSpecAttrs.addAll(DeclSpecAttrs.begin(), DeclSpecAttrs.end());
209581ad6265SDimitry Andric OriginalDeclSpecAttrs.Range = DeclSpecAttrs.Range;
209681ad6265SDimitry Andric
20970b57cec5SDimitry Andric // Parse the common declaration-specifiers piece.
20980b57cec5SDimitry Andric ParsingDeclSpec DS(*this);
209981ad6265SDimitry Andric DS.takeAttributesFrom(DeclSpecAttrs);
21000b57cec5SDimitry Andric
2101*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo;
21020b57cec5SDimitry Andric DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);
2103*0fca6ea1SDimitry Andric ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DSContext);
21040b57cec5SDimitry Andric
21050b57cec5SDimitry Andric // If we had a free-standing type definition with a missing semicolon, we
21060b57cec5SDimitry Andric // may get this far before the problem becomes obvious.
21070b57cec5SDimitry Andric if (DS.hasTagDefinition() &&
21080b57cec5SDimitry Andric DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext))
21090b57cec5SDimitry Andric return nullptr;
21100b57cec5SDimitry Andric
21110b57cec5SDimitry Andric // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
21120b57cec5SDimitry Andric // declaration-specifiers init-declarator-list[opt] ';'
21130b57cec5SDimitry Andric if (Tok.is(tok::semi)) {
211481ad6265SDimitry Andric ProhibitAttributes(DeclAttrs);
21150b57cec5SDimitry Andric DeclEnd = Tok.getLocation();
21160b57cec5SDimitry Andric if (RequireSemi) ConsumeToken();
21170b57cec5SDimitry Andric RecordDecl *AnonRecord = nullptr;
211881ad6265SDimitry Andric Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
211981ad6265SDimitry Andric getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
21205f757f3fSDimitry Andric Actions.ActOnDefinedDeclarationSpecifier(TheDecl);
21210b57cec5SDimitry Andric DS.complete(TheDecl);
21220b57cec5SDimitry Andric if (AnonRecord) {
21230b57cec5SDimitry Andric Decl* decls[] = {AnonRecord, TheDecl};
21240b57cec5SDimitry Andric return Actions.BuildDeclaratorGroup(decls);
21250b57cec5SDimitry Andric }
21260b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(TheDecl);
21270b57cec5SDimitry Andric }
21280b57cec5SDimitry Andric
21295f757f3fSDimitry Andric if (DS.hasTagDefinition())
21305f757f3fSDimitry Andric Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());
21315f757f3fSDimitry Andric
2132a7dea167SDimitry Andric if (DeclSpecStart)
2133a7dea167SDimitry Andric DS.SetRangeStart(*DeclSpecStart);
2134a7dea167SDimitry Andric
2135*0fca6ea1SDimitry Andric return ParseDeclGroup(DS, Context, DeclAttrs, TemplateInfo, &DeclEnd, FRI);
21360b57cec5SDimitry Andric }
21370b57cec5SDimitry Andric
21380b57cec5SDimitry Andric /// Returns true if this might be the start of a declarator, or a common typo
21390b57cec5SDimitry Andric /// for a declarator.
MightBeDeclarator(DeclaratorContext Context)21400b57cec5SDimitry Andric bool Parser::MightBeDeclarator(DeclaratorContext Context) {
21410b57cec5SDimitry Andric switch (Tok.getKind()) {
21420b57cec5SDimitry Andric case tok::annot_cxxscope:
21430b57cec5SDimitry Andric case tok::annot_template_id:
21440b57cec5SDimitry Andric case tok::caret:
21450b57cec5SDimitry Andric case tok::code_completion:
21460b57cec5SDimitry Andric case tok::coloncolon:
21470b57cec5SDimitry Andric case tok::ellipsis:
21480b57cec5SDimitry Andric case tok::kw___attribute:
21490b57cec5SDimitry Andric case tok::kw_operator:
21500b57cec5SDimitry Andric case tok::l_paren:
21510b57cec5SDimitry Andric case tok::star:
21520b57cec5SDimitry Andric return true;
21530b57cec5SDimitry Andric
21540b57cec5SDimitry Andric case tok::amp:
21550b57cec5SDimitry Andric case tok::ampamp:
21560b57cec5SDimitry Andric return getLangOpts().CPlusPlus;
21570b57cec5SDimitry Andric
21580b57cec5SDimitry Andric case tok::l_square: // Might be an attribute on an unnamed bit-field.
2159e8d8bef9SDimitry Andric return Context == DeclaratorContext::Member && getLangOpts().CPlusPlus11 &&
2160e8d8bef9SDimitry Andric NextToken().is(tok::l_square);
21610b57cec5SDimitry Andric
21620b57cec5SDimitry Andric case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
2163e8d8bef9SDimitry Andric return Context == DeclaratorContext::Member || getLangOpts().CPlusPlus;
21640b57cec5SDimitry Andric
21650b57cec5SDimitry Andric case tok::identifier:
21660b57cec5SDimitry Andric switch (NextToken().getKind()) {
21670b57cec5SDimitry Andric case tok::code_completion:
21680b57cec5SDimitry Andric case tok::coloncolon:
21690b57cec5SDimitry Andric case tok::comma:
21700b57cec5SDimitry Andric case tok::equal:
21710b57cec5SDimitry Andric case tok::equalequal: // Might be a typo for '='.
21720b57cec5SDimitry Andric case tok::kw_alignas:
21730b57cec5SDimitry Andric case tok::kw_asm:
21740b57cec5SDimitry Andric case tok::kw___attribute:
21750b57cec5SDimitry Andric case tok::l_brace:
21760b57cec5SDimitry Andric case tok::l_paren:
21770b57cec5SDimitry Andric case tok::l_square:
21780b57cec5SDimitry Andric case tok::less:
21790b57cec5SDimitry Andric case tok::r_brace:
21800b57cec5SDimitry Andric case tok::r_paren:
21810b57cec5SDimitry Andric case tok::r_square:
21820b57cec5SDimitry Andric case tok::semi:
21830b57cec5SDimitry Andric return true;
21840b57cec5SDimitry Andric
21850b57cec5SDimitry Andric case tok::colon:
21860b57cec5SDimitry Andric // At namespace scope, 'identifier:' is probably a typo for 'identifier::'
21870b57cec5SDimitry Andric // and in block scope it's probably a label. Inside a class definition,
21880b57cec5SDimitry Andric // this is a bit-field.
2189e8d8bef9SDimitry Andric return Context == DeclaratorContext::Member ||
2190e8d8bef9SDimitry Andric (getLangOpts().CPlusPlus && Context == DeclaratorContext::File);
21910b57cec5SDimitry Andric
21920b57cec5SDimitry Andric case tok::identifier: // Possible virt-specifier.
21930b57cec5SDimitry Andric return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
21940b57cec5SDimitry Andric
21950b57cec5SDimitry Andric default:
219606c3fb27SDimitry Andric return Tok.isRegularKeywordAttribute();
21970b57cec5SDimitry Andric }
21980b57cec5SDimitry Andric
21990b57cec5SDimitry Andric default:
220006c3fb27SDimitry Andric return Tok.isRegularKeywordAttribute();
22010b57cec5SDimitry Andric }
22020b57cec5SDimitry Andric }
22030b57cec5SDimitry Andric
22040b57cec5SDimitry Andric /// Skip until we reach something which seems like a sensible place to pick
22050b57cec5SDimitry Andric /// up parsing after a malformed declaration. This will sometimes stop sooner
22060b57cec5SDimitry Andric /// than SkipUntil(tok::r_brace) would, but will never stop later.
SkipMalformedDecl()22070b57cec5SDimitry Andric void Parser::SkipMalformedDecl() {
22080b57cec5SDimitry Andric while (true) {
22090b57cec5SDimitry Andric switch (Tok.getKind()) {
22100b57cec5SDimitry Andric case tok::l_brace:
22110b57cec5SDimitry Andric // Skip until matching }, then stop. We've probably skipped over
22120b57cec5SDimitry Andric // a malformed class or function definition or similar.
22130b57cec5SDimitry Andric ConsumeBrace();
22140b57cec5SDimitry Andric SkipUntil(tok::r_brace);
22150b57cec5SDimitry Andric if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) {
22160b57cec5SDimitry Andric // This declaration isn't over yet. Keep skipping.
22170b57cec5SDimitry Andric continue;
22180b57cec5SDimitry Andric }
22190b57cec5SDimitry Andric TryConsumeToken(tok::semi);
22200b57cec5SDimitry Andric return;
22210b57cec5SDimitry Andric
22220b57cec5SDimitry Andric case tok::l_square:
22230b57cec5SDimitry Andric ConsumeBracket();
22240b57cec5SDimitry Andric SkipUntil(tok::r_square);
22250b57cec5SDimitry Andric continue;
22260b57cec5SDimitry Andric
22270b57cec5SDimitry Andric case tok::l_paren:
22280b57cec5SDimitry Andric ConsumeParen();
22290b57cec5SDimitry Andric SkipUntil(tok::r_paren);
22300b57cec5SDimitry Andric continue;
22310b57cec5SDimitry Andric
22320b57cec5SDimitry Andric case tok::r_brace:
22330b57cec5SDimitry Andric return;
22340b57cec5SDimitry Andric
22350b57cec5SDimitry Andric case tok::semi:
22360b57cec5SDimitry Andric ConsumeToken();
22370b57cec5SDimitry Andric return;
22380b57cec5SDimitry Andric
22390b57cec5SDimitry Andric case tok::kw_inline:
22400b57cec5SDimitry Andric // 'inline namespace' at the start of a line is almost certainly
22410b57cec5SDimitry Andric // a good place to pick back up parsing, except in an Objective-C
22420b57cec5SDimitry Andric // @interface context.
22430b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) &&
22440b57cec5SDimitry Andric (!ParsingInObjCContainer || CurParsedObjCImpl))
22450b57cec5SDimitry Andric return;
22460b57cec5SDimitry Andric break;
22470b57cec5SDimitry Andric
22480b57cec5SDimitry Andric case tok::kw_namespace:
22490b57cec5SDimitry Andric // 'namespace' at the start of a line is almost certainly a good
22500b57cec5SDimitry Andric // place to pick back up parsing, except in an Objective-C
22510b57cec5SDimitry Andric // @interface context.
22520b57cec5SDimitry Andric if (Tok.isAtStartOfLine() &&
22530b57cec5SDimitry Andric (!ParsingInObjCContainer || CurParsedObjCImpl))
22540b57cec5SDimitry Andric return;
22550b57cec5SDimitry Andric break;
22560b57cec5SDimitry Andric
22570b57cec5SDimitry Andric case tok::at:
22580b57cec5SDimitry Andric // @end is very much like } in Objective-C contexts.
22590b57cec5SDimitry Andric if (NextToken().isObjCAtKeyword(tok::objc_end) &&
22600b57cec5SDimitry Andric ParsingInObjCContainer)
22610b57cec5SDimitry Andric return;
22620b57cec5SDimitry Andric break;
22630b57cec5SDimitry Andric
22640b57cec5SDimitry Andric case tok::minus:
22650b57cec5SDimitry Andric case tok::plus:
22660b57cec5SDimitry Andric // - and + probably start new method declarations in Objective-C contexts.
22670b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && ParsingInObjCContainer)
22680b57cec5SDimitry Andric return;
22690b57cec5SDimitry Andric break;
22700b57cec5SDimitry Andric
22710b57cec5SDimitry Andric case tok::eof:
22720b57cec5SDimitry Andric case tok::annot_module_begin:
22730b57cec5SDimitry Andric case tok::annot_module_end:
22740b57cec5SDimitry Andric case tok::annot_module_include:
227506c3fb27SDimitry Andric case tok::annot_repl_input_end:
22760b57cec5SDimitry Andric return;
22770b57cec5SDimitry Andric
22780b57cec5SDimitry Andric default:
22790b57cec5SDimitry Andric break;
22800b57cec5SDimitry Andric }
22810b57cec5SDimitry Andric
22820b57cec5SDimitry Andric ConsumeAnyToken();
22830b57cec5SDimitry Andric }
22840b57cec5SDimitry Andric }
22850b57cec5SDimitry Andric
22860b57cec5SDimitry Andric /// ParseDeclGroup - Having concluded that this is either a function
22870b57cec5SDimitry Andric /// definition or a group of object declarations, actually parse the
22880b57cec5SDimitry Andric /// result.
ParseDeclGroup(ParsingDeclSpec & DS,DeclaratorContext Context,ParsedAttributes & Attrs,ParsedTemplateInfo & TemplateInfo,SourceLocation * DeclEnd,ForRangeInit * FRI)22890b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
22900b57cec5SDimitry Andric DeclaratorContext Context,
229181ad6265SDimitry Andric ParsedAttributes &Attrs,
2292*0fca6ea1SDimitry Andric ParsedTemplateInfo &TemplateInfo,
22930b57cec5SDimitry Andric SourceLocation *DeclEnd,
22940b57cec5SDimitry Andric ForRangeInit *FRI) {
22950b57cec5SDimitry Andric // Parse the first declarator.
229681ad6265SDimitry Andric // Consume all of the attributes from `Attrs` by moving them to our own local
229781ad6265SDimitry Andric // list. This ensures that we will not attempt to interpret them as statement
229881ad6265SDimitry Andric // attributes higher up the callchain.
229981ad6265SDimitry Andric ParsedAttributes LocalAttrs(AttrFactory);
230081ad6265SDimitry Andric LocalAttrs.takeAllFrom(Attrs);
230181ad6265SDimitry Andric ParsingDeclarator D(*this, DS, LocalAttrs, Context);
2302*0fca6ea1SDimitry Andric if (TemplateInfo.TemplateParams)
2303*0fca6ea1SDimitry Andric D.setTemplateParameterLists(*TemplateInfo.TemplateParams);
2304*0fca6ea1SDimitry Andric
2305*0fca6ea1SDimitry Andric bool IsTemplateSpecOrInst =
2306*0fca6ea1SDimitry Andric (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
2307*0fca6ea1SDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
2308*0fca6ea1SDimitry Andric SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
2309*0fca6ea1SDimitry Andric
23100b57cec5SDimitry Andric ParseDeclarator(D);
23110b57cec5SDimitry Andric
2312*0fca6ea1SDimitry Andric if (IsTemplateSpecOrInst)
2313*0fca6ea1SDimitry Andric SAC.done();
2314*0fca6ea1SDimitry Andric
23150b57cec5SDimitry Andric // Bail out if the first declarator didn't seem well-formed.
23160b57cec5SDimitry Andric if (!D.hasName() && !D.mayOmitIdentifier()) {
23170b57cec5SDimitry Andric SkipMalformedDecl();
23180b57cec5SDimitry Andric return nullptr;
23190b57cec5SDimitry Andric }
23200b57cec5SDimitry Andric
2321bdd1243dSDimitry Andric if (getLangOpts().HLSL)
2322*0fca6ea1SDimitry Andric MaybeParseHLSLAnnotations(D);
2323bdd1243dSDimitry Andric
2324480093f4SDimitry Andric if (Tok.is(tok::kw_requires))
2325480093f4SDimitry Andric ParseTrailingRequiresClause(D);
2326480093f4SDimitry Andric
23270b57cec5SDimitry Andric // Save late-parsed attributes for now; they need to be parsed in the
23280b57cec5SDimitry Andric // appropriate function scope after the function Decl has been constructed.
23290b57cec5SDimitry Andric // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList.
23300b57cec5SDimitry Andric LateParsedAttrList LateParsedAttrs(true);
23310b57cec5SDimitry Andric if (D.isFunctionDeclarator()) {
23320b57cec5SDimitry Andric MaybeParseGNUAttributes(D, &LateParsedAttrs);
23330b57cec5SDimitry Andric
23340b57cec5SDimitry Andric // The _Noreturn keyword can't appear here, unlike the GNU noreturn
23350b57cec5SDimitry Andric // attribute. If we find the keyword here, tell the user to put it
23360b57cec5SDimitry Andric // at the start instead.
23370b57cec5SDimitry Andric if (Tok.is(tok::kw__Noreturn)) {
23380b57cec5SDimitry Andric SourceLocation Loc = ConsumeToken();
23390b57cec5SDimitry Andric const char *PrevSpec;
23400b57cec5SDimitry Andric unsigned DiagID;
23410b57cec5SDimitry Andric
23420b57cec5SDimitry Andric // We can offer a fixit if it's valid to mark this function as _Noreturn
23430b57cec5SDimitry Andric // and we don't have any other declarators in this declaration.
23440b57cec5SDimitry Andric bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
23450b57cec5SDimitry Andric MaybeParseGNUAttributes(D, &LateParsedAttrs);
23460b57cec5SDimitry Andric Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try);
23470b57cec5SDimitry Andric
23480b57cec5SDimitry Andric Diag(Loc, diag::err_c11_noreturn_misplaced)
23490b57cec5SDimitry Andric << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())
23500b57cec5SDimitry Andric << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ")
23510b57cec5SDimitry Andric : FixItHint());
23520b57cec5SDimitry Andric }
23530b57cec5SDimitry Andric
23540b57cec5SDimitry Andric // Check to see if we have a function *definition* which must have a body.
23555ffd83dbSDimitry Andric if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) {
23565ffd83dbSDimitry Andric cutOffParsing();
2357*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteAfterFunctionEquals(D);
23585ffd83dbSDimitry Andric return nullptr;
23595ffd83dbSDimitry Andric }
2360349cc55cSDimitry Andric // We're at the point where the parsing of function declarator is finished.
2361349cc55cSDimitry Andric //
2362349cc55cSDimitry Andric // A common error is that users accidently add a virtual specifier
2363349cc55cSDimitry Andric // (e.g. override) in an out-line method definition.
2364349cc55cSDimitry Andric // We attempt to recover by stripping all these specifiers coming after
2365349cc55cSDimitry Andric // the declarator.
2366349cc55cSDimitry Andric while (auto Specifier = isCXX11VirtSpecifier()) {
2367349cc55cSDimitry Andric Diag(Tok, diag::err_virt_specifier_outside_class)
2368349cc55cSDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier)
2369349cc55cSDimitry Andric << FixItHint::CreateRemoval(Tok.getLocation());
2370349cc55cSDimitry Andric ConsumeToken();
2371349cc55cSDimitry Andric }
23720b57cec5SDimitry Andric // Look at the next token to make sure that this isn't a function
23730b57cec5SDimitry Andric // declaration. We have to check this because __attribute__ might be the
23740b57cec5SDimitry Andric // start of a function definition in GCC-extended K&R C.
23755ffd83dbSDimitry Andric if (!isDeclarationAfterDeclarator()) {
23760b57cec5SDimitry Andric
23770b57cec5SDimitry Andric // Function definitions are only allowed at file scope and in C++ classes.
23780b57cec5SDimitry Andric // The C++ inline method definition case is handled elsewhere, so we only
23790b57cec5SDimitry Andric // need to handle the file scope definition case.
2380e8d8bef9SDimitry Andric if (Context == DeclaratorContext::File) {
23810b57cec5SDimitry Andric if (isStartOfFunctionDefinition(D)) {
2382*0fca6ea1SDimitry Andric // C++23 [dcl.typedef] p1:
2383*0fca6ea1SDimitry Andric // The typedef specifier shall not be [...], and it shall not be
2384*0fca6ea1SDimitry Andric // used in the decl-specifier-seq of a parameter-declaration nor in
2385*0fca6ea1SDimitry Andric // the decl-specifier-seq of a function-definition.
23860b57cec5SDimitry Andric if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
2387*0fca6ea1SDimitry Andric // If the user intended to write 'typename', we should have already
2388*0fca6ea1SDimitry Andric // suggested adding it elsewhere. In any case, recover by ignoring
2389*0fca6ea1SDimitry Andric // 'typedef' and suggest removing it.
2390*0fca6ea1SDimitry Andric Diag(DS.getStorageClassSpecLoc(),
2391*0fca6ea1SDimitry Andric diag::err_function_declared_typedef)
2392*0fca6ea1SDimitry Andric << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
23930b57cec5SDimitry Andric DS.ClearStorageClassSpecs();
23940b57cec5SDimitry Andric }
2395*0fca6ea1SDimitry Andric Decl *TheDecl = nullptr;
23960b57cec5SDimitry Andric
2397*0fca6ea1SDimitry Andric if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
2398*0fca6ea1SDimitry Andric if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
2399*0fca6ea1SDimitry Andric // If the declarator-id is not a template-id, issue a diagnostic
2400*0fca6ea1SDimitry Andric // and recover by ignoring the 'template' keyword.
2401*0fca6ea1SDimitry Andric Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
2402*0fca6ea1SDimitry Andric TheDecl = ParseFunctionDefinition(D, ParsedTemplateInfo(),
24035ffd83dbSDimitry Andric &LateParsedAttrs);
2404*0fca6ea1SDimitry Andric } else {
2405*0fca6ea1SDimitry Andric SourceLocation LAngleLoc =
2406*0fca6ea1SDimitry Andric PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
2407*0fca6ea1SDimitry Andric Diag(D.getIdentifierLoc(),
2408*0fca6ea1SDimitry Andric diag::err_explicit_instantiation_with_definition)
2409*0fca6ea1SDimitry Andric << SourceRange(TemplateInfo.TemplateLoc)
2410*0fca6ea1SDimitry Andric << FixItHint::CreateInsertion(LAngleLoc, "<>");
2411*0fca6ea1SDimitry Andric
2412*0fca6ea1SDimitry Andric // Recover as if it were an explicit specialization.
2413*0fca6ea1SDimitry Andric TemplateParameterLists FakedParamLists;
2414*0fca6ea1SDimitry Andric FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
2415*0fca6ea1SDimitry Andric 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,
2416*0fca6ea1SDimitry Andric std::nullopt, LAngleLoc, nullptr));
2417*0fca6ea1SDimitry Andric
2418*0fca6ea1SDimitry Andric TheDecl = ParseFunctionDefinition(
2419*0fca6ea1SDimitry Andric D,
2420*0fca6ea1SDimitry Andric ParsedTemplateInfo(&FakedParamLists,
2421*0fca6ea1SDimitry Andric /*isSpecialization=*/true,
2422*0fca6ea1SDimitry Andric /*lastParameterListWasEmpty=*/true),
2423*0fca6ea1SDimitry Andric &LateParsedAttrs);
2424*0fca6ea1SDimitry Andric }
2425*0fca6ea1SDimitry Andric } else {
2426*0fca6ea1SDimitry Andric TheDecl =
2427*0fca6ea1SDimitry Andric ParseFunctionDefinition(D, TemplateInfo, &LateParsedAttrs);
2428*0fca6ea1SDimitry Andric }
2429*0fca6ea1SDimitry Andric
24300b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(TheDecl);
24310b57cec5SDimitry Andric }
24320b57cec5SDimitry Andric
243306c3fb27SDimitry Andric if (isDeclarationSpecifier(ImplicitTypenameContext::No) ||
243406c3fb27SDimitry Andric Tok.is(tok::kw_namespace)) {
243506c3fb27SDimitry Andric // If there is an invalid declaration specifier or a namespace
243606c3fb27SDimitry Andric // definition right after the function prototype, then we must be in a
243706c3fb27SDimitry Andric // missing semicolon case where this isn't actually a body. Just fall
243806c3fb27SDimitry Andric // through into the code that handles it as a prototype, and let the
243906c3fb27SDimitry Andric // top-level code handle the erroneous declspec where it would
244006c3fb27SDimitry Andric // otherwise expect a comma or semicolon. Note that
244106c3fb27SDimitry Andric // isDeclarationSpecifier already covers 'inline namespace', since
244206c3fb27SDimitry Andric // 'inline' can be a declaration specifier.
24430b57cec5SDimitry Andric } else {
24440b57cec5SDimitry Andric Diag(Tok, diag::err_expected_fn_body);
24450b57cec5SDimitry Andric SkipUntil(tok::semi);
24460b57cec5SDimitry Andric return nullptr;
24470b57cec5SDimitry Andric }
24480b57cec5SDimitry Andric } else {
24490b57cec5SDimitry Andric if (Tok.is(tok::l_brace)) {
24500b57cec5SDimitry Andric Diag(Tok, diag::err_function_definition_not_allowed);
24510b57cec5SDimitry Andric SkipMalformedDecl();
24520b57cec5SDimitry Andric return nullptr;
24530b57cec5SDimitry Andric }
24540b57cec5SDimitry Andric }
24550b57cec5SDimitry Andric }
24565ffd83dbSDimitry Andric }
24570b57cec5SDimitry Andric
24580b57cec5SDimitry Andric if (ParseAsmAttributesAfterDeclarator(D))
24590b57cec5SDimitry Andric return nullptr;
24600b57cec5SDimitry Andric
24610b57cec5SDimitry Andric // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we
24620b57cec5SDimitry Andric // must parse and analyze the for-range-initializer before the declaration is
24630b57cec5SDimitry Andric // analyzed.
24640b57cec5SDimitry Andric //
24650b57cec5SDimitry Andric // Handle the Objective-C for-in loop variable similarly, although we
24660b57cec5SDimitry Andric // don't need to parse the container in advance.
24670b57cec5SDimitry Andric if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {
24680b57cec5SDimitry Andric bool IsForRangeLoop = false;
24690b57cec5SDimitry Andric if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
24700b57cec5SDimitry Andric IsForRangeLoop = true;
2471*0fca6ea1SDimitry Andric EnterExpressionEvaluationContext ForRangeInitContext(
2472*0fca6ea1SDimitry Andric Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
2473*0fca6ea1SDimitry Andric /*LambdaContextDecl=*/nullptr,
2474*0fca6ea1SDimitry Andric Sema::ExpressionEvaluationContextRecord::EK_Other,
2475*0fca6ea1SDimitry Andric getLangOpts().CPlusPlus23);
2476*0fca6ea1SDimitry Andric
2477*0fca6ea1SDimitry Andric // P2718R0 - Lifetime extension in range-based for loops.
2478*0fca6ea1SDimitry Andric if (getLangOpts().CPlusPlus23) {
2479*0fca6ea1SDimitry Andric auto &LastRecord = Actions.ExprEvalContexts.back();
2480*0fca6ea1SDimitry Andric LastRecord.InLifetimeExtendingContext = true;
2481*0fca6ea1SDimitry Andric }
2482*0fca6ea1SDimitry Andric
2483a7dea167SDimitry Andric if (getLangOpts().OpenMP)
2484*0fca6ea1SDimitry Andric Actions.OpenMP().startOpenMPCXXRangeFor();
24850b57cec5SDimitry Andric if (Tok.is(tok::l_brace))
24860b57cec5SDimitry Andric FRI->RangeExpr = ParseBraceInitializer();
24870b57cec5SDimitry Andric else
24880b57cec5SDimitry Andric FRI->RangeExpr = ParseExpression();
2489*0fca6ea1SDimitry Andric
2490*0fca6ea1SDimitry Andric // Before c++23, ForRangeLifetimeExtendTemps should be empty.
2491*0fca6ea1SDimitry Andric assert(
2492*0fca6ea1SDimitry Andric getLangOpts().CPlusPlus23 ||
2493*0fca6ea1SDimitry Andric Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps.empty());
2494*0fca6ea1SDimitry Andric
2495*0fca6ea1SDimitry Andric // Move the collected materialized temporaries into ForRangeInit before
2496*0fca6ea1SDimitry Andric // ForRangeInitContext exit.
2497*0fca6ea1SDimitry Andric FRI->LifetimeExtendTemps = std::move(
2498*0fca6ea1SDimitry Andric Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps);
24990b57cec5SDimitry Andric }
25000b57cec5SDimitry Andric
25010b57cec5SDimitry Andric Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
25020b57cec5SDimitry Andric if (IsForRangeLoop) {
25030b57cec5SDimitry Andric Actions.ActOnCXXForRangeDecl(ThisDecl);
25040b57cec5SDimitry Andric } else {
25050b57cec5SDimitry Andric // Obj-C for loop
25060b57cec5SDimitry Andric if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl))
25070b57cec5SDimitry Andric VD->setObjCForDecl(true);
25080b57cec5SDimitry Andric }
25090b57cec5SDimitry Andric Actions.FinalizeDeclaration(ThisDecl);
25100b57cec5SDimitry Andric D.complete(ThisDecl);
25110b57cec5SDimitry Andric return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);
25120b57cec5SDimitry Andric }
25130b57cec5SDimitry Andric
25140b57cec5SDimitry Andric SmallVector<Decl *, 8> DeclsInGroup;
2515*0fca6ea1SDimitry Andric Decl *FirstDecl =
2516*0fca6ea1SDimitry Andric ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo, FRI);
25170b57cec5SDimitry Andric if (LateParsedAttrs.size() > 0)
25180b57cec5SDimitry Andric ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);
25190b57cec5SDimitry Andric D.complete(FirstDecl);
25200b57cec5SDimitry Andric if (FirstDecl)
25210b57cec5SDimitry Andric DeclsInGroup.push_back(FirstDecl);
25220b57cec5SDimitry Andric
2523e8d8bef9SDimitry Andric bool ExpectSemi = Context != DeclaratorContext::ForInit;
25240b57cec5SDimitry Andric
25250b57cec5SDimitry Andric // If we don't have a comma, it is either the end of the list (a ';') or an
25260b57cec5SDimitry Andric // error, bail out.
25270b57cec5SDimitry Andric SourceLocation CommaLoc;
25280b57cec5SDimitry Andric while (TryConsumeToken(tok::comma, CommaLoc)) {
25290b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) {
25300b57cec5SDimitry Andric // This comma was followed by a line-break and something which can't be
25310b57cec5SDimitry Andric // the start of a declarator. The comma was probably a typo for a
25320b57cec5SDimitry Andric // semicolon.
25330b57cec5SDimitry Andric Diag(CommaLoc, diag::err_expected_semi_declaration)
25340b57cec5SDimitry Andric << FixItHint::CreateReplacement(CommaLoc, ";");
25350b57cec5SDimitry Andric ExpectSemi = false;
25360b57cec5SDimitry Andric break;
25370b57cec5SDimitry Andric }
25380b57cec5SDimitry Andric
2539*0fca6ea1SDimitry Andric // C++23 [temp.pre]p5:
2540*0fca6ea1SDimitry Andric // In a template-declaration, explicit specialization, or explicit
2541*0fca6ea1SDimitry Andric // instantiation the init-declarator-list in the declaration shall
2542*0fca6ea1SDimitry Andric // contain at most one declarator.
2543*0fca6ea1SDimitry Andric if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
2544*0fca6ea1SDimitry Andric D.isFirstDeclarator()) {
2545*0fca6ea1SDimitry Andric Diag(CommaLoc, diag::err_multiple_template_declarators)
2546*0fca6ea1SDimitry Andric << TemplateInfo.Kind;
2547*0fca6ea1SDimitry Andric }
2548*0fca6ea1SDimitry Andric
25490b57cec5SDimitry Andric // Parse the next declarator.
25500b57cec5SDimitry Andric D.clear();
25510b57cec5SDimitry Andric D.setCommaLoc(CommaLoc);
25520b57cec5SDimitry Andric
25530b57cec5SDimitry Andric // Accept attributes in an init-declarator. In the first declarator in a
25540b57cec5SDimitry Andric // declaration, these would be part of the declspec. In subsequent
25550b57cec5SDimitry Andric // declarators, they become part of the declarator itself, so that they
25560b57cec5SDimitry Andric // don't apply to declarators after *this* one. Examples:
25570b57cec5SDimitry Andric // short __attribute__((common)) var; -> declspec
25580b57cec5SDimitry Andric // short var __attribute__((common)); -> declarator
25590b57cec5SDimitry Andric // short x, __attribute__((common)) var; -> declarator
25600b57cec5SDimitry Andric MaybeParseGNUAttributes(D);
25610b57cec5SDimitry Andric
25620b57cec5SDimitry Andric // MSVC parses but ignores qualifiers after the comma as an extension.
25630b57cec5SDimitry Andric if (getLangOpts().MicrosoftExt)
25640b57cec5SDimitry Andric DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
25650b57cec5SDimitry Andric
25660b57cec5SDimitry Andric ParseDeclarator(D);
2567bdd1243dSDimitry Andric
2568bdd1243dSDimitry Andric if (getLangOpts().HLSL)
2569*0fca6ea1SDimitry Andric MaybeParseHLSLAnnotations(D);
2570bdd1243dSDimitry Andric
25710b57cec5SDimitry Andric if (!D.isInvalidType()) {
2572480093f4SDimitry Andric // C++2a [dcl.decl]p1
2573480093f4SDimitry Andric // init-declarator:
2574480093f4SDimitry Andric // declarator initializer[opt]
2575480093f4SDimitry Andric // declarator requires-clause
2576480093f4SDimitry Andric if (Tok.is(tok::kw_requires))
2577480093f4SDimitry Andric ParseTrailingRequiresClause(D);
2578*0fca6ea1SDimitry Andric Decl *ThisDecl = ParseDeclarationAfterDeclarator(D, TemplateInfo);
25790b57cec5SDimitry Andric D.complete(ThisDecl);
25800b57cec5SDimitry Andric if (ThisDecl)
25810b57cec5SDimitry Andric DeclsInGroup.push_back(ThisDecl);
25820b57cec5SDimitry Andric }
25830b57cec5SDimitry Andric }
25840b57cec5SDimitry Andric
25850b57cec5SDimitry Andric if (DeclEnd)
25860b57cec5SDimitry Andric *DeclEnd = Tok.getLocation();
25870b57cec5SDimitry Andric
2588e8d8bef9SDimitry Andric if (ExpectSemi && ExpectAndConsumeSemi(
2589e8d8bef9SDimitry Andric Context == DeclaratorContext::File
25900b57cec5SDimitry Andric ? diag::err_invalid_token_after_toplevel_declarator
25910b57cec5SDimitry Andric : diag::err_expected_semi_declaration)) {
25920b57cec5SDimitry Andric // Okay, there was no semicolon and one was expected. If we see a
25930b57cec5SDimitry Andric // declaration specifier, just assume it was missing and continue parsing.
25940b57cec5SDimitry Andric // Otherwise things are very confused and we skip to recover.
259506c3fb27SDimitry Andric if (!isDeclarationSpecifier(ImplicitTypenameContext::No))
259606c3fb27SDimitry Andric SkipMalformedDecl();
25970b57cec5SDimitry Andric }
25980b57cec5SDimitry Andric
25990b57cec5SDimitry Andric return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
26000b57cec5SDimitry Andric }
26010b57cec5SDimitry Andric
26020b57cec5SDimitry Andric /// Parse an optional simple-asm-expr and attributes, and attach them to a
26030b57cec5SDimitry Andric /// declarator. Returns true on an error.
ParseAsmAttributesAfterDeclarator(Declarator & D)26040b57cec5SDimitry Andric bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
26050b57cec5SDimitry Andric // If a simple-asm-expr is present, parse it.
26060b57cec5SDimitry Andric if (Tok.is(tok::kw_asm)) {
26070b57cec5SDimitry Andric SourceLocation Loc;
2608480093f4SDimitry Andric ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));
26090b57cec5SDimitry Andric if (AsmLabel.isInvalid()) {
26100b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch);
26110b57cec5SDimitry Andric return true;
26120b57cec5SDimitry Andric }
26130b57cec5SDimitry Andric
26140b57cec5SDimitry Andric D.setAsmLabel(AsmLabel.get());
26150b57cec5SDimitry Andric D.SetRangeEnd(Loc);
26160b57cec5SDimitry Andric }
26170b57cec5SDimitry Andric
26180b57cec5SDimitry Andric MaybeParseGNUAttributes(D);
26190b57cec5SDimitry Andric return false;
26200b57cec5SDimitry Andric }
26210b57cec5SDimitry Andric
26220b57cec5SDimitry Andric /// Parse 'declaration' after parsing 'declaration-specifiers
26230b57cec5SDimitry Andric /// declarator'. This method parses the remainder of the declaration
26240b57cec5SDimitry Andric /// (including any attributes or initializer, among other things) and
26250b57cec5SDimitry Andric /// finalizes the declaration.
26260b57cec5SDimitry Andric ///
26270b57cec5SDimitry Andric /// init-declarator: [C99 6.7]
26280b57cec5SDimitry Andric /// declarator
26290b57cec5SDimitry Andric /// declarator '=' initializer
26300b57cec5SDimitry Andric /// [GNU] declarator simple-asm-expr[opt] attributes[opt]
26310b57cec5SDimitry Andric /// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer
26320b57cec5SDimitry Andric /// [C++] declarator initializer[opt]
26330b57cec5SDimitry Andric ///
26340b57cec5SDimitry Andric /// [C++] initializer:
26350b57cec5SDimitry Andric /// [C++] '=' initializer-clause
26360b57cec5SDimitry Andric /// [C++] '(' expression-list ')'
26370b57cec5SDimitry Andric /// [C++0x] '=' 'default' [TODO]
26380b57cec5SDimitry Andric /// [C++0x] '=' 'delete'
26390b57cec5SDimitry Andric /// [C++0x] braced-init-list
26400b57cec5SDimitry Andric ///
26410b57cec5SDimitry Andric /// According to the standard grammar, =default and =delete are function
26420b57cec5SDimitry Andric /// definitions, but that definitely doesn't fit with the parser here.
26430b57cec5SDimitry Andric ///
ParseDeclarationAfterDeclarator(Declarator & D,const ParsedTemplateInfo & TemplateInfo)26440b57cec5SDimitry Andric Decl *Parser::ParseDeclarationAfterDeclarator(
26450b57cec5SDimitry Andric Declarator &D, const ParsedTemplateInfo &TemplateInfo) {
26460b57cec5SDimitry Andric if (ParseAsmAttributesAfterDeclarator(D))
26470b57cec5SDimitry Andric return nullptr;
26480b57cec5SDimitry Andric
26490b57cec5SDimitry Andric return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
26500b57cec5SDimitry Andric }
26510b57cec5SDimitry Andric
ParseDeclarationAfterDeclaratorAndAttributes(Declarator & D,const ParsedTemplateInfo & TemplateInfo,ForRangeInit * FRI)26520b57cec5SDimitry Andric Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
26530b57cec5SDimitry Andric Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
26540b57cec5SDimitry Andric // RAII type used to track whether we're inside an initializer.
26550b57cec5SDimitry Andric struct InitializerScopeRAII {
26560b57cec5SDimitry Andric Parser &P;
26570b57cec5SDimitry Andric Declarator &D;
26580b57cec5SDimitry Andric Decl *ThisDecl;
2659*0fca6ea1SDimitry Andric bool Entered;
26600b57cec5SDimitry Andric
26610b57cec5SDimitry Andric InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
2662*0fca6ea1SDimitry Andric : P(P), D(D), ThisDecl(ThisDecl), Entered(false) {
26630b57cec5SDimitry Andric if (ThisDecl && P.getLangOpts().CPlusPlus) {
26640b57cec5SDimitry Andric Scope *S = nullptr;
26650b57cec5SDimitry Andric if (D.getCXXScopeSpec().isSet()) {
26660b57cec5SDimitry Andric P.EnterScope(0);
26670b57cec5SDimitry Andric S = P.getCurScope();
26680b57cec5SDimitry Andric }
2669*0fca6ea1SDimitry Andric if (ThisDecl && !ThisDecl->isInvalidDecl()) {
26700b57cec5SDimitry Andric P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
2671*0fca6ea1SDimitry Andric Entered = true;
26720b57cec5SDimitry Andric }
26730b57cec5SDimitry Andric }
2674*0fca6ea1SDimitry Andric }
2675*0fca6ea1SDimitry Andric ~InitializerScopeRAII() {
26760b57cec5SDimitry Andric if (ThisDecl && P.getLangOpts().CPlusPlus) {
26770b57cec5SDimitry Andric Scope *S = nullptr;
26780b57cec5SDimitry Andric if (D.getCXXScopeSpec().isSet())
26790b57cec5SDimitry Andric S = P.getCurScope();
2680*0fca6ea1SDimitry Andric
2681*0fca6ea1SDimitry Andric if (Entered)
26820b57cec5SDimitry Andric P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
26830b57cec5SDimitry Andric if (S)
26840b57cec5SDimitry Andric P.ExitScope();
26850b57cec5SDimitry Andric }
26860b57cec5SDimitry Andric ThisDecl = nullptr;
26870b57cec5SDimitry Andric }
26880b57cec5SDimitry Andric };
26890b57cec5SDimitry Andric
2690e8d8bef9SDimitry Andric enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced };
2691e8d8bef9SDimitry Andric InitKind TheInitKind;
2692e8d8bef9SDimitry Andric // If a '==' or '+=' is found, suggest a fixit to '='.
2693e8d8bef9SDimitry Andric if (isTokenEqualOrEqualTypo())
2694e8d8bef9SDimitry Andric TheInitKind = InitKind::Equal;
2695e8d8bef9SDimitry Andric else if (Tok.is(tok::l_paren))
2696e8d8bef9SDimitry Andric TheInitKind = InitKind::CXXDirect;
2697e8d8bef9SDimitry Andric else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
2698e8d8bef9SDimitry Andric (!CurParsedObjCImpl || !D.isFunctionDeclarator()))
2699e8d8bef9SDimitry Andric TheInitKind = InitKind::CXXBraced;
2700e8d8bef9SDimitry Andric else
2701e8d8bef9SDimitry Andric TheInitKind = InitKind::Uninitialized;
2702e8d8bef9SDimitry Andric if (TheInitKind != InitKind::Uninitialized)
2703e8d8bef9SDimitry Andric D.setHasInitializer();
2704e8d8bef9SDimitry Andric
2705e8d8bef9SDimitry Andric // Inform Sema that we just parsed this declarator.
27060b57cec5SDimitry Andric Decl *ThisDecl = nullptr;
2707e8d8bef9SDimitry Andric Decl *OuterDecl = nullptr;
27080b57cec5SDimitry Andric switch (TemplateInfo.Kind) {
27090b57cec5SDimitry Andric case ParsedTemplateInfo::NonTemplate:
27100b57cec5SDimitry Andric ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
27110b57cec5SDimitry Andric break;
27120b57cec5SDimitry Andric
27130b57cec5SDimitry Andric case ParsedTemplateInfo::Template:
27140b57cec5SDimitry Andric case ParsedTemplateInfo::ExplicitSpecialization: {
27150b57cec5SDimitry Andric ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
27160b57cec5SDimitry Andric *TemplateInfo.TemplateParams,
27170b57cec5SDimitry Andric D);
2718e8d8bef9SDimitry Andric if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl)) {
27190b57cec5SDimitry Andric // Re-direct this decl to refer to the templated decl so that we can
27200b57cec5SDimitry Andric // initialize it.
27210b57cec5SDimitry Andric ThisDecl = VT->getTemplatedDecl();
2722e8d8bef9SDimitry Andric OuterDecl = VT;
2723e8d8bef9SDimitry Andric }
27240b57cec5SDimitry Andric break;
27250b57cec5SDimitry Andric }
27260b57cec5SDimitry Andric case ParsedTemplateInfo::ExplicitInstantiation: {
27270b57cec5SDimitry Andric if (Tok.is(tok::semi)) {
27280b57cec5SDimitry Andric DeclResult ThisRes = Actions.ActOnExplicitInstantiation(
27290b57cec5SDimitry Andric getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
27300b57cec5SDimitry Andric if (ThisRes.isInvalid()) {
27310b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch);
27320b57cec5SDimitry Andric return nullptr;
27330b57cec5SDimitry Andric }
27340b57cec5SDimitry Andric ThisDecl = ThisRes.get();
27350b57cec5SDimitry Andric } else {
27360b57cec5SDimitry Andric // FIXME: This check should be for a variable template instantiation only.
27370b57cec5SDimitry Andric
27380b57cec5SDimitry Andric // Check that this is a valid instantiation
27390b57cec5SDimitry Andric if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
27400b57cec5SDimitry Andric // If the declarator-id is not a template-id, issue a diagnostic and
27410b57cec5SDimitry Andric // recover by ignoring the 'template' keyword.
27420b57cec5SDimitry Andric Diag(Tok, diag::err_template_defn_explicit_instantiation)
27430b57cec5SDimitry Andric << 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
27440b57cec5SDimitry Andric ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
27450b57cec5SDimitry Andric } else {
27460b57cec5SDimitry Andric SourceLocation LAngleLoc =
27470b57cec5SDimitry Andric PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
27480b57cec5SDimitry Andric Diag(D.getIdentifierLoc(),
27490b57cec5SDimitry Andric diag::err_explicit_instantiation_with_definition)
27500b57cec5SDimitry Andric << SourceRange(TemplateInfo.TemplateLoc)
27510b57cec5SDimitry Andric << FixItHint::CreateInsertion(LAngleLoc, "<>");
27520b57cec5SDimitry Andric
27530b57cec5SDimitry Andric // Recover as if it were an explicit specialization.
27540b57cec5SDimitry Andric TemplateParameterLists FakedParamLists;
27550b57cec5SDimitry Andric FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
2756bdd1243dSDimitry Andric 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,
2757bdd1243dSDimitry Andric std::nullopt, LAngleLoc, nullptr));
27580b57cec5SDimitry Andric
27590b57cec5SDimitry Andric ThisDecl =
27600b57cec5SDimitry Andric Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
27610b57cec5SDimitry Andric }
27620b57cec5SDimitry Andric }
27630b57cec5SDimitry Andric break;
27640b57cec5SDimitry Andric }
27650b57cec5SDimitry Andric }
27660b57cec5SDimitry Andric
2767*0fca6ea1SDimitry Andric SemaCUDA::CUDATargetContextRAII X(Actions.CUDA(),
2768*0fca6ea1SDimitry Andric SemaCUDA::CTCK_InitGlobalVar, ThisDecl);
2769e8d8bef9SDimitry Andric switch (TheInitKind) {
27700b57cec5SDimitry Andric // Parse declarator '=' initializer.
2771e8d8bef9SDimitry Andric case InitKind::Equal: {
27720b57cec5SDimitry Andric SourceLocation EqualLoc = ConsumeToken();
27730b57cec5SDimitry Andric
27740b57cec5SDimitry Andric if (Tok.is(tok::kw_delete)) {
27750b57cec5SDimitry Andric if (D.isFunctionDeclarator())
27760b57cec5SDimitry Andric Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
27770b57cec5SDimitry Andric << 1 /* delete */;
27780b57cec5SDimitry Andric else
27790b57cec5SDimitry Andric Diag(ConsumeToken(), diag::err_deleted_non_function);
2780*0fca6ea1SDimitry Andric SkipDeletedFunctionBody();
27810b57cec5SDimitry Andric } else if (Tok.is(tok::kw_default)) {
27820b57cec5SDimitry Andric if (D.isFunctionDeclarator())
27830b57cec5SDimitry Andric Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
27840b57cec5SDimitry Andric << 0 /* default */;
27850b57cec5SDimitry Andric else
2786480093f4SDimitry Andric Diag(ConsumeToken(), diag::err_default_special_members)
27875ffd83dbSDimitry Andric << getLangOpts().CPlusPlus20;
27880b57cec5SDimitry Andric } else {
27890b57cec5SDimitry Andric InitializerScopeRAII InitScope(*this, D, ThisDecl);
27900b57cec5SDimitry Andric
27910b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) {
2792fe6060f1SDimitry Andric cutOffParsing();
2793*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),
2794*0fca6ea1SDimitry Andric ThisDecl);
27950b57cec5SDimitry Andric Actions.FinalizeDeclaration(ThisDecl);
27960b57cec5SDimitry Andric return nullptr;
27970b57cec5SDimitry Andric }
27980b57cec5SDimitry Andric
27990b57cec5SDimitry Andric PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
28000b57cec5SDimitry Andric ExprResult Init = ParseInitializer();
28010b57cec5SDimitry Andric
28020b57cec5SDimitry Andric // If this is the only decl in (possibly) range based for statement,
28030b57cec5SDimitry Andric // our best guess is that the user meant ':' instead of '='.
28040b57cec5SDimitry Andric if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) {
28050b57cec5SDimitry Andric Diag(EqualLoc, diag::err_single_decl_assign_in_for_range)
28060b57cec5SDimitry Andric << FixItHint::CreateReplacement(EqualLoc, ":");
28070b57cec5SDimitry Andric // We are trying to stop parser from looking for ';' in this for
28080b57cec5SDimitry Andric // statement, therefore preventing spurious errors to be issued.
28090b57cec5SDimitry Andric FRI->ColonLoc = EqualLoc;
28100b57cec5SDimitry Andric Init = ExprError();
28110b57cec5SDimitry Andric FRI->RangeExpr = Init;
28120b57cec5SDimitry Andric }
28130b57cec5SDimitry Andric
28140b57cec5SDimitry Andric if (Init.isInvalid()) {
28150b57cec5SDimitry Andric SmallVector<tok::TokenKind, 2> StopTokens;
28160b57cec5SDimitry Andric StopTokens.push_back(tok::comma);
2817e8d8bef9SDimitry Andric if (D.getContext() == DeclaratorContext::ForInit ||
2818e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::SelectionInit)
28190b57cec5SDimitry Andric StopTokens.push_back(tok::r_paren);
28200b57cec5SDimitry Andric SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
28210b57cec5SDimitry Andric Actions.ActOnInitializerError(ThisDecl);
28220b57cec5SDimitry Andric } else
28230b57cec5SDimitry Andric Actions.AddInitializerToDecl(ThisDecl, Init.get(),
28240b57cec5SDimitry Andric /*DirectInit=*/false);
28250b57cec5SDimitry Andric }
2826e8d8bef9SDimitry Andric break;
2827e8d8bef9SDimitry Andric }
2828e8d8bef9SDimitry Andric case InitKind::CXXDirect: {
28290b57cec5SDimitry Andric // Parse C++ direct initializer: '(' expression-list ')'
28300b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
28310b57cec5SDimitry Andric T.consumeOpen();
28320b57cec5SDimitry Andric
28330b57cec5SDimitry Andric ExprVector Exprs;
28340b57cec5SDimitry Andric
28350b57cec5SDimitry Andric InitializerScopeRAII InitScope(*this, D, ThisDecl);
28360b57cec5SDimitry Andric
28370b57cec5SDimitry Andric auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
28380b57cec5SDimitry Andric auto RunSignatureHelp = [&]() {
2839*0fca6ea1SDimitry Andric QualType PreferredType =
2840*0fca6ea1SDimitry Andric Actions.CodeCompletion().ProduceConstructorSignatureHelp(
284104eeddc0SDimitry Andric ThisVarDecl->getType()->getCanonicalTypeInternal(),
284204eeddc0SDimitry Andric ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
284304eeddc0SDimitry Andric /*Braced=*/false);
28440b57cec5SDimitry Andric CalledSignatureHelp = true;
28450b57cec5SDimitry Andric return PreferredType;
28460b57cec5SDimitry Andric };
28470b57cec5SDimitry Andric auto SetPreferredType = [&] {
28480b57cec5SDimitry Andric PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
28490b57cec5SDimitry Andric };
28500b57cec5SDimitry Andric
28510b57cec5SDimitry Andric llvm::function_ref<void()> ExpressionStarts;
28520b57cec5SDimitry Andric if (ThisVarDecl) {
28530b57cec5SDimitry Andric // ParseExpressionList can sometimes succeed even when ThisDecl is not
28540b57cec5SDimitry Andric // VarDecl. This is an error and it is reported in a call to
28550b57cec5SDimitry Andric // Actions.ActOnInitializerError(). However, we call
28560b57cec5SDimitry Andric // ProduceConstructorSignatureHelp only on VarDecls.
28570b57cec5SDimitry Andric ExpressionStarts = SetPreferredType;
28580b57cec5SDimitry Andric }
2859297eecfbSDimitry Andric
2860297eecfbSDimitry Andric bool SawError = ParseExpressionList(Exprs, ExpressionStarts);
2861297eecfbSDimitry Andric
2862297eecfbSDimitry Andric if (SawError) {
28630b57cec5SDimitry Andric if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
2864*0fca6ea1SDimitry Andric Actions.CodeCompletion().ProduceConstructorSignatureHelp(
286504eeddc0SDimitry Andric ThisVarDecl->getType()->getCanonicalTypeInternal(),
286604eeddc0SDimitry Andric ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
286704eeddc0SDimitry Andric /*Braced=*/false);
28680b57cec5SDimitry Andric CalledSignatureHelp = true;
28690b57cec5SDimitry Andric }
28700b57cec5SDimitry Andric Actions.ActOnInitializerError(ThisDecl);
28710b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
28720b57cec5SDimitry Andric } else {
28730b57cec5SDimitry Andric // Match the ')'.
28740b57cec5SDimitry Andric T.consumeClose();
28750b57cec5SDimitry Andric
28760b57cec5SDimitry Andric ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
28770b57cec5SDimitry Andric T.getCloseLocation(),
28780b57cec5SDimitry Andric Exprs);
28790b57cec5SDimitry Andric Actions.AddInitializerToDecl(ThisDecl, Initializer.get(),
28800b57cec5SDimitry Andric /*DirectInit=*/true);
28810b57cec5SDimitry Andric }
2882e8d8bef9SDimitry Andric break;
2883e8d8bef9SDimitry Andric }
2884e8d8bef9SDimitry Andric case InitKind::CXXBraced: {
28850b57cec5SDimitry Andric // Parse C++0x braced-init-list.
28860b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
28870b57cec5SDimitry Andric
28880b57cec5SDimitry Andric InitializerScopeRAII InitScope(*this, D, ThisDecl);
28890b57cec5SDimitry Andric
28905ffd83dbSDimitry Andric PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
28910b57cec5SDimitry Andric ExprResult Init(ParseBraceInitializer());
28920b57cec5SDimitry Andric
28930b57cec5SDimitry Andric if (Init.isInvalid()) {
28940b57cec5SDimitry Andric Actions.ActOnInitializerError(ThisDecl);
28950b57cec5SDimitry Andric } else
28960b57cec5SDimitry Andric Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true);
2897e8d8bef9SDimitry Andric break;
2898e8d8bef9SDimitry Andric }
2899e8d8bef9SDimitry Andric case InitKind::Uninitialized: {
29000b57cec5SDimitry Andric Actions.ActOnUninitializedDecl(ThisDecl);
2901e8d8bef9SDimitry Andric break;
2902e8d8bef9SDimitry Andric }
29030b57cec5SDimitry Andric }
29040b57cec5SDimitry Andric
29050b57cec5SDimitry Andric Actions.FinalizeDeclaration(ThisDecl);
2906e8d8bef9SDimitry Andric return OuterDecl ? OuterDecl : ThisDecl;
29070b57cec5SDimitry Andric }
29080b57cec5SDimitry Andric
29090b57cec5SDimitry Andric /// ParseSpecifierQualifierList
29100b57cec5SDimitry Andric /// specifier-qualifier-list:
29110b57cec5SDimitry Andric /// type-specifier specifier-qualifier-list[opt]
29120b57cec5SDimitry Andric /// type-qualifier specifier-qualifier-list[opt]
29130b57cec5SDimitry Andric /// [GNU] attributes specifier-qualifier-list[opt]
29140b57cec5SDimitry Andric ///
ParseSpecifierQualifierList(DeclSpec & DS,ImplicitTypenameContext AllowImplicitTypename,AccessSpecifier AS,DeclSpecContext DSC)2915bdd1243dSDimitry Andric void Parser::ParseSpecifierQualifierList(
2916bdd1243dSDimitry Andric DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename,
2917bdd1243dSDimitry Andric AccessSpecifier AS, DeclSpecContext DSC) {
2918*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo;
29190b57cec5SDimitry Andric /// specifier-qualifier-list is a subset of declaration-specifiers. Just
29200b57cec5SDimitry Andric /// parse declaration-specifiers and complain about extra stuff.
29210b57cec5SDimitry Andric /// TODO: diagnose attribute-specifiers and alignment-specifiers.
2922*0fca6ea1SDimitry Andric ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, nullptr,
2923bdd1243dSDimitry Andric AllowImplicitTypename);
29240b57cec5SDimitry Andric
29250b57cec5SDimitry Andric // Validate declspec for type-name.
29260b57cec5SDimitry Andric unsigned Specs = DS.getParsedSpecifiers();
29270b57cec5SDimitry Andric if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {
29280b57cec5SDimitry Andric Diag(Tok, diag::err_expected_type);
29290b57cec5SDimitry Andric DS.SetTypeSpecError();
29300b57cec5SDimitry Andric } else if (Specs == DeclSpec::PQ_None && !DS.hasAttributes()) {
29310b57cec5SDimitry Andric Diag(Tok, diag::err_typename_requires_specqual);
29320b57cec5SDimitry Andric if (!DS.hasTypeSpecifier())
29330b57cec5SDimitry Andric DS.SetTypeSpecError();
29340b57cec5SDimitry Andric }
29350b57cec5SDimitry Andric
29360b57cec5SDimitry Andric // Issue diagnostic and remove storage class if present.
29370b57cec5SDimitry Andric if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
29380b57cec5SDimitry Andric if (DS.getStorageClassSpecLoc().isValid())
29390b57cec5SDimitry Andric Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);
29400b57cec5SDimitry Andric else
29410b57cec5SDimitry Andric Diag(DS.getThreadStorageClassSpecLoc(),
29420b57cec5SDimitry Andric diag::err_typename_invalid_storageclass);
29430b57cec5SDimitry Andric DS.ClearStorageClassSpecs();
29440b57cec5SDimitry Andric }
29450b57cec5SDimitry Andric
29460b57cec5SDimitry Andric // Issue diagnostic and remove function specifier if present.
29470b57cec5SDimitry Andric if (Specs & DeclSpec::PQ_FunctionSpecifier) {
29480b57cec5SDimitry Andric if (DS.isInlineSpecified())
29490b57cec5SDimitry Andric Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
29500b57cec5SDimitry Andric if (DS.isVirtualSpecified())
29510b57cec5SDimitry Andric Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
29520b57cec5SDimitry Andric if (DS.hasExplicitSpecifier())
29530b57cec5SDimitry Andric Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
2954bdd1243dSDimitry Andric if (DS.isNoreturnSpecified())
2955bdd1243dSDimitry Andric Diag(DS.getNoreturnSpecLoc(), diag::err_typename_invalid_functionspec);
29560b57cec5SDimitry Andric DS.ClearFunctionSpecs();
29570b57cec5SDimitry Andric }
29580b57cec5SDimitry Andric
29590b57cec5SDimitry Andric // Issue diagnostic and remove constexpr specifier if present.
29600b57cec5SDimitry Andric if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) {
29610b57cec5SDimitry Andric Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr)
2962e8d8bef9SDimitry Andric << static_cast<int>(DS.getConstexprSpecifier());
29630b57cec5SDimitry Andric DS.ClearConstexprSpec();
29640b57cec5SDimitry Andric }
29650b57cec5SDimitry Andric }
29660b57cec5SDimitry Andric
29670b57cec5SDimitry Andric /// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the
29680b57cec5SDimitry Andric /// specified token is valid after the identifier in a declarator which
29690b57cec5SDimitry Andric /// immediately follows the declspec. For example, these things are valid:
29700b57cec5SDimitry Andric ///
29710b57cec5SDimitry Andric /// int x [ 4]; // direct-declarator
29720b57cec5SDimitry Andric /// int x ( int y); // direct-declarator
29730b57cec5SDimitry Andric /// int(int x ) // direct-declarator
29740b57cec5SDimitry Andric /// int x ; // simple-declaration
29750b57cec5SDimitry Andric /// int x = 17; // init-declarator-list
29760b57cec5SDimitry Andric /// int x , y; // init-declarator-list
29770b57cec5SDimitry Andric /// int x __asm__ ("foo"); // init-declarator-list
29780b57cec5SDimitry Andric /// int x : 4; // struct-declarator
29790b57cec5SDimitry Andric /// int x { 5}; // C++'0x unified initializers
29800b57cec5SDimitry Andric ///
29810b57cec5SDimitry Andric /// This is not, because 'x' does not immediately follow the declspec (though
29820b57cec5SDimitry Andric /// ')' happens to be valid anyway).
29830b57cec5SDimitry Andric /// int (x)
29840b57cec5SDimitry Andric ///
isValidAfterIdentifierInDeclarator(const Token & T)29850b57cec5SDimitry Andric static bool isValidAfterIdentifierInDeclarator(const Token &T) {
29860b57cec5SDimitry Andric return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi,
29870b57cec5SDimitry Andric tok::comma, tok::equal, tok::kw_asm, tok::l_brace,
29880b57cec5SDimitry Andric tok::colon);
29890b57cec5SDimitry Andric }
29900b57cec5SDimitry Andric
29910b57cec5SDimitry Andric /// ParseImplicitInt - This method is called when we have an non-typename
29920b57cec5SDimitry Andric /// identifier in a declspec (which normally terminates the decl spec) when
29930b57cec5SDimitry Andric /// the declspec has no type specifier. In this case, the declspec is either
29940b57cec5SDimitry Andric /// malformed or is "implicit int" (in K&R and C89).
29950b57cec5SDimitry Andric ///
29960b57cec5SDimitry Andric /// This method handles diagnosing this prettily and returns false if the
29970b57cec5SDimitry Andric /// declspec is done being processed. If it recovers and thinks there may be
29980b57cec5SDimitry Andric /// other pieces of declspec after it, it returns true.
29990b57cec5SDimitry Andric ///
ParseImplicitInt(DeclSpec & DS,CXXScopeSpec * SS,ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSC,ParsedAttributes & Attrs)30000b57cec5SDimitry Andric bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
3001*0fca6ea1SDimitry Andric ParsedTemplateInfo &TemplateInfo,
30020b57cec5SDimitry Andric AccessSpecifier AS, DeclSpecContext DSC,
300381ad6265SDimitry Andric ParsedAttributes &Attrs) {
30040b57cec5SDimitry Andric assert(Tok.is(tok::identifier) && "should have identifier");
30050b57cec5SDimitry Andric
30060b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
30070b57cec5SDimitry Andric // If we see an identifier that is not a type name, we normally would
30080b57cec5SDimitry Andric // parse it as the identifier being declared. However, when a typename
30090b57cec5SDimitry Andric // is typo'd or the definition is not included, this will incorrectly
30100b57cec5SDimitry Andric // parse the typename as the identifier name and fall over misparsing
30110b57cec5SDimitry Andric // later parts of the diagnostic.
30120b57cec5SDimitry Andric //
30130b57cec5SDimitry Andric // As such, we try to do some look-ahead in cases where this would
30140b57cec5SDimitry Andric // otherwise be an "implicit-int" case to see if this is invalid. For
30150b57cec5SDimitry Andric // example: "static foo_t x = 4;" In this case, if we parsed foo_t as
30160b57cec5SDimitry Andric // an identifier with implicit int, we'd get a parse error because the
30170b57cec5SDimitry Andric // next token is obviously invalid for a type. Parse these as a case
30180b57cec5SDimitry Andric // with an invalid type specifier.
30190b57cec5SDimitry Andric assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
30200b57cec5SDimitry Andric
30210b57cec5SDimitry Andric // Since we know that this either implicit int (which is rare) or an
30220b57cec5SDimitry Andric // error, do lookahead to try to do better recovery. This never applies
30230b57cec5SDimitry Andric // within a type specifier. Outside of C++, we allow this even if the
30240b57cec5SDimitry Andric // language doesn't "officially" support implicit int -- we support
302581ad6265SDimitry Andric // implicit int as an extension in some language modes.
302681ad6265SDimitry Andric if (!isTypeSpecifier(DSC) && getLangOpts().isImplicitIntAllowed() &&
30270b57cec5SDimitry Andric isValidAfterIdentifierInDeclarator(NextToken())) {
30280b57cec5SDimitry Andric // If this token is valid for implicit int, e.g. "static x = 4", then
30290b57cec5SDimitry Andric // we just avoid eating the identifier, so it will be parsed as the
30300b57cec5SDimitry Andric // identifier in the declarator.
30310b57cec5SDimitry Andric return false;
30320b57cec5SDimitry Andric }
30330b57cec5SDimitry Andric
30340b57cec5SDimitry Andric // Early exit as Sema has a dedicated missing_actual_pipe_type diagnostic
30350b57cec5SDimitry Andric // for incomplete declarations such as `pipe p`.
30360b57cec5SDimitry Andric if (getLangOpts().OpenCLCPlusPlus && DS.isTypeSpecPipe())
30370b57cec5SDimitry Andric return false;
30380b57cec5SDimitry Andric
30390b57cec5SDimitry Andric if (getLangOpts().CPlusPlus &&
30400b57cec5SDimitry Andric DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
30410b57cec5SDimitry Andric // Don't require a type specifier if we have the 'auto' storage class
30420b57cec5SDimitry Andric // specifier in C++98 -- we'll promote it to a type specifier.
30430b57cec5SDimitry Andric if (SS)
30440b57cec5SDimitry Andric AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
30450b57cec5SDimitry Andric return false;
30460b57cec5SDimitry Andric }
30470b57cec5SDimitry Andric
30480b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && (!SS || SS->isEmpty()) &&
30490b57cec5SDimitry Andric getLangOpts().MSVCCompat) {
30500b57cec5SDimitry Andric // Lookup of an unqualified type name has failed in MSVC compatibility mode.
30510b57cec5SDimitry Andric // Give Sema a chance to recover if we are in a template with dependent base
30520b57cec5SDimitry Andric // classes.
30530b57cec5SDimitry Andric if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(
30540b57cec5SDimitry Andric *Tok.getIdentifierInfo(), Tok.getLocation(),
30550b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_template_type_arg)) {
30560b57cec5SDimitry Andric const char *PrevSpec;
30570b57cec5SDimitry Andric unsigned DiagID;
30580b57cec5SDimitry Andric DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
30590b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy());
30600b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getLocation());
30610b57cec5SDimitry Andric ConsumeToken();
30620b57cec5SDimitry Andric return false;
30630b57cec5SDimitry Andric }
30640b57cec5SDimitry Andric }
30650b57cec5SDimitry Andric
30660b57cec5SDimitry Andric // Otherwise, if we don't consume this token, we are going to emit an
30670b57cec5SDimitry Andric // error anyway. Try to recover from various common problems. Check
30680b57cec5SDimitry Andric // to see if this was a reference to a tag name without a tag specified.
30690b57cec5SDimitry Andric // This is a common problem in C (saying 'foo' instead of 'struct foo').
30700b57cec5SDimitry Andric //
30710b57cec5SDimitry Andric // C++ doesn't need this, and isTagName doesn't take SS.
30720b57cec5SDimitry Andric if (SS == nullptr) {
30730b57cec5SDimitry Andric const char *TagName = nullptr, *FixitTagName = nullptr;
30740b57cec5SDimitry Andric tok::TokenKind TagKind = tok::unknown;
30750b57cec5SDimitry Andric
30760b57cec5SDimitry Andric switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {
30770b57cec5SDimitry Andric default: break;
30780b57cec5SDimitry Andric case DeclSpec::TST_enum:
30790b57cec5SDimitry Andric TagName="enum" ; FixitTagName = "enum " ; TagKind=tok::kw_enum ;break;
30800b57cec5SDimitry Andric case DeclSpec::TST_union:
30810b57cec5SDimitry Andric TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break;
30820b57cec5SDimitry Andric case DeclSpec::TST_struct:
30830b57cec5SDimitry Andric TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break;
30840b57cec5SDimitry Andric case DeclSpec::TST_interface:
30850b57cec5SDimitry Andric TagName="__interface"; FixitTagName = "__interface ";
30860b57cec5SDimitry Andric TagKind=tok::kw___interface;break;
30870b57cec5SDimitry Andric case DeclSpec::TST_class:
30880b57cec5SDimitry Andric TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break;
30890b57cec5SDimitry Andric }
30900b57cec5SDimitry Andric
30910b57cec5SDimitry Andric if (TagName) {
30920b57cec5SDimitry Andric IdentifierInfo *TokenName = Tok.getIdentifierInfo();
30930b57cec5SDimitry Andric LookupResult R(Actions, TokenName, SourceLocation(),
30940b57cec5SDimitry Andric Sema::LookupOrdinaryName);
30950b57cec5SDimitry Andric
30960b57cec5SDimitry Andric Diag(Loc, diag::err_use_of_tag_name_without_tag)
30970b57cec5SDimitry Andric << TokenName << TagName << getLangOpts().CPlusPlus
30980b57cec5SDimitry Andric << FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);
30990b57cec5SDimitry Andric
3100*0fca6ea1SDimitry Andric if (Actions.LookupName(R, getCurScope())) {
31010b57cec5SDimitry Andric for (LookupResult::iterator I = R.begin(), IEnd = R.end();
31020b57cec5SDimitry Andric I != IEnd; ++I)
31030b57cec5SDimitry Andric Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
31040b57cec5SDimitry Andric << TokenName << TagName;
31050b57cec5SDimitry Andric }
31060b57cec5SDimitry Andric
31070b57cec5SDimitry Andric // Parse this as a tag as if the missing tag were present.
31080b57cec5SDimitry Andric if (TagKind == tok::kw_enum)
31090b57cec5SDimitry Andric ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,
31100b57cec5SDimitry Andric DeclSpecContext::DSC_normal);
31110b57cec5SDimitry Andric else
31120b57cec5SDimitry Andric ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
31130b57cec5SDimitry Andric /*EnteringContext*/ false,
31140b57cec5SDimitry Andric DeclSpecContext::DSC_normal, Attrs);
31150b57cec5SDimitry Andric return true;
31160b57cec5SDimitry Andric }
31170b57cec5SDimitry Andric }
31180b57cec5SDimitry Andric
31190b57cec5SDimitry Andric // Determine whether this identifier could plausibly be the name of something
31200b57cec5SDimitry Andric // being declared (with a missing type).
31210b57cec5SDimitry Andric if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||
31220b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_class)) {
31230b57cec5SDimitry Andric // Look ahead to the next token to try to figure out what this declaration
31240b57cec5SDimitry Andric // was supposed to be.
31250b57cec5SDimitry Andric switch (NextToken().getKind()) {
31260b57cec5SDimitry Andric case tok::l_paren: {
31270b57cec5SDimitry Andric // static x(4); // 'x' is not a type
31280b57cec5SDimitry Andric // x(int n); // 'x' is not a type
31290b57cec5SDimitry Andric // x (*p)[]; // 'x' is a type
31300b57cec5SDimitry Andric //
31310b57cec5SDimitry Andric // Since we're in an error case, we can afford to perform a tentative
31320b57cec5SDimitry Andric // parse to determine which case we're in.
31330b57cec5SDimitry Andric TentativeParsingAction PA(*this);
31340b57cec5SDimitry Andric ConsumeToken();
31350b57cec5SDimitry Andric TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
31360b57cec5SDimitry Andric PA.Revert();
31370b57cec5SDimitry Andric
31380b57cec5SDimitry Andric if (TPR != TPResult::False) {
31390b57cec5SDimitry Andric // The identifier is followed by a parenthesized declarator.
31400b57cec5SDimitry Andric // It's supposed to be a type.
31410b57cec5SDimitry Andric break;
31420b57cec5SDimitry Andric }
31430b57cec5SDimitry Andric
31440b57cec5SDimitry Andric // If we're in a context where we could be declaring a constructor,
31450b57cec5SDimitry Andric // check whether this is a constructor declaration with a bogus name.
31460b57cec5SDimitry Andric if (DSC == DeclSpecContext::DSC_class ||
31470b57cec5SDimitry Andric (DSC == DeclSpecContext::DSC_top_level && SS)) {
31480b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
31490b57cec5SDimitry Andric if (Actions.isCurrentClassNameTypo(II, SS)) {
31500b57cec5SDimitry Andric Diag(Loc, diag::err_constructor_bad_name)
31510b57cec5SDimitry Andric << Tok.getIdentifierInfo() << II
31520b57cec5SDimitry Andric << FixItHint::CreateReplacement(Tok.getLocation(), II->getName());
31530b57cec5SDimitry Andric Tok.setIdentifierInfo(II);
31540b57cec5SDimitry Andric }
31550b57cec5SDimitry Andric }
31560b57cec5SDimitry Andric // Fall through.
3157bdd1243dSDimitry Andric [[fallthrough]];
31580b57cec5SDimitry Andric }
31590b57cec5SDimitry Andric case tok::comma:
31600b57cec5SDimitry Andric case tok::equal:
31610b57cec5SDimitry Andric case tok::kw_asm:
31620b57cec5SDimitry Andric case tok::l_brace:
31630b57cec5SDimitry Andric case tok::l_square:
31640b57cec5SDimitry Andric case tok::semi:
31650b57cec5SDimitry Andric // This looks like a variable or function declaration. The type is
31660b57cec5SDimitry Andric // probably missing. We're done parsing decl-specifiers.
31670b57cec5SDimitry Andric // But only if we are not in a function prototype scope.
31680b57cec5SDimitry Andric if (getCurScope()->isFunctionPrototypeScope())
31690b57cec5SDimitry Andric break;
31700b57cec5SDimitry Andric if (SS)
31710b57cec5SDimitry Andric AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
31720b57cec5SDimitry Andric return false;
31730b57cec5SDimitry Andric
31740b57cec5SDimitry Andric default:
31750b57cec5SDimitry Andric // This is probably supposed to be a type. This includes cases like:
31760b57cec5SDimitry Andric // int f(itn);
31775ffd83dbSDimitry Andric // struct S { unsigned : 4; };
31780b57cec5SDimitry Andric break;
31790b57cec5SDimitry Andric }
31800b57cec5SDimitry Andric }
31810b57cec5SDimitry Andric
31820b57cec5SDimitry Andric // This is almost certainly an invalid type name. Let Sema emit a diagnostic
31830b57cec5SDimitry Andric // and attempt to recover.
31840b57cec5SDimitry Andric ParsedType T;
31850b57cec5SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
31860b57cec5SDimitry Andric bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less);
31870b57cec5SDimitry Andric Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,
31880b57cec5SDimitry Andric IsTemplateName);
31890b57cec5SDimitry Andric if (T) {
31900b57cec5SDimitry Andric // The action has suggested that the type T could be used. Set that as
31910b57cec5SDimitry Andric // the type in the declaration specifiers, consume the would-be type
31920b57cec5SDimitry Andric // name token, and we're done.
31930b57cec5SDimitry Andric const char *PrevSpec;
31940b57cec5SDimitry Andric unsigned DiagID;
31950b57cec5SDimitry Andric DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
31960b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy());
31970b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getLocation());
31980b57cec5SDimitry Andric ConsumeToken();
31990b57cec5SDimitry Andric // There may be other declaration specifiers after this.
32000b57cec5SDimitry Andric return true;
32010b57cec5SDimitry Andric } else if (II != Tok.getIdentifierInfo()) {
32020b57cec5SDimitry Andric // If no type was suggested, the correction is to a keyword
32030b57cec5SDimitry Andric Tok.setKind(II->getTokenID());
32040b57cec5SDimitry Andric // There may be other declaration specifiers after this.
32050b57cec5SDimitry Andric return true;
32060b57cec5SDimitry Andric }
32070b57cec5SDimitry Andric
32080b57cec5SDimitry Andric // Otherwise, the action had no suggestion for us. Mark this as an error.
32090b57cec5SDimitry Andric DS.SetTypeSpecError();
32100b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getLocation());
32110b57cec5SDimitry Andric ConsumeToken();
32120b57cec5SDimitry Andric
32130b57cec5SDimitry Andric // Eat any following template arguments.
32140b57cec5SDimitry Andric if (IsTemplateName) {
32150b57cec5SDimitry Andric SourceLocation LAngle, RAngle;
32160b57cec5SDimitry Andric TemplateArgList Args;
32170b57cec5SDimitry Andric ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle);
32180b57cec5SDimitry Andric }
32190b57cec5SDimitry Andric
32200b57cec5SDimitry Andric // TODO: Could inject an invalid typedef decl in an enclosing scope to
32210b57cec5SDimitry Andric // avoid rippling error messages on subsequent uses of the same type,
32220b57cec5SDimitry Andric // could be useful if #include was forgotten.
32230b57cec5SDimitry Andric return true;
32240b57cec5SDimitry Andric }
32250b57cec5SDimitry Andric
32260b57cec5SDimitry Andric /// Determine the declaration specifier context from the declarator
32270b57cec5SDimitry Andric /// context.
32280b57cec5SDimitry Andric ///
32290b57cec5SDimitry Andric /// \param Context the declarator context, which is one of the
32300b57cec5SDimitry Andric /// DeclaratorContext enumerator values.
32310b57cec5SDimitry Andric Parser::DeclSpecContext
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context)32320b57cec5SDimitry Andric Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
3233bdd1243dSDimitry Andric switch (Context) {
3234bdd1243dSDimitry Andric case DeclaratorContext::Member:
32350b57cec5SDimitry Andric return DeclSpecContext::DSC_class;
3236bdd1243dSDimitry Andric case DeclaratorContext::File:
32370b57cec5SDimitry Andric return DeclSpecContext::DSC_top_level;
3238bdd1243dSDimitry Andric case DeclaratorContext::TemplateParam:
32390b57cec5SDimitry Andric return DeclSpecContext::DSC_template_param;
3240bdd1243dSDimitry Andric case DeclaratorContext::TemplateArg:
3241bdd1243dSDimitry Andric return DeclSpecContext::DSC_template_arg;
3242bdd1243dSDimitry Andric case DeclaratorContext::TemplateTypeArg:
32430b57cec5SDimitry Andric return DeclSpecContext::DSC_template_type_arg;
3244bdd1243dSDimitry Andric case DeclaratorContext::TrailingReturn:
3245bdd1243dSDimitry Andric case DeclaratorContext::TrailingReturnVar:
32460b57cec5SDimitry Andric return DeclSpecContext::DSC_trailing;
3247bdd1243dSDimitry Andric case DeclaratorContext::AliasDecl:
3248bdd1243dSDimitry Andric case DeclaratorContext::AliasTemplate:
32490b57cec5SDimitry Andric return DeclSpecContext::DSC_alias_declaration;
3250bdd1243dSDimitry Andric case DeclaratorContext::Association:
325181ad6265SDimitry Andric return DeclSpecContext::DSC_association;
3252bdd1243dSDimitry Andric case DeclaratorContext::TypeName:
3253bdd1243dSDimitry Andric return DeclSpecContext::DSC_type_specifier;
3254bdd1243dSDimitry Andric case DeclaratorContext::Condition:
3255bdd1243dSDimitry Andric return DeclSpecContext::DSC_condition;
3256bdd1243dSDimitry Andric case DeclaratorContext::ConversionId:
3257bdd1243dSDimitry Andric return DeclSpecContext::DSC_conv_operator;
325806c3fb27SDimitry Andric case DeclaratorContext::CXXNew:
325906c3fb27SDimitry Andric return DeclSpecContext::DSC_new;
3260bdd1243dSDimitry Andric case DeclaratorContext::Prototype:
3261bdd1243dSDimitry Andric case DeclaratorContext::ObjCResult:
3262bdd1243dSDimitry Andric case DeclaratorContext::ObjCParameter:
3263bdd1243dSDimitry Andric case DeclaratorContext::KNRTypeList:
3264bdd1243dSDimitry Andric case DeclaratorContext::FunctionalCast:
3265bdd1243dSDimitry Andric case DeclaratorContext::Block:
3266bdd1243dSDimitry Andric case DeclaratorContext::ForInit:
3267bdd1243dSDimitry Andric case DeclaratorContext::SelectionInit:
3268bdd1243dSDimitry Andric case DeclaratorContext::CXXCatch:
3269bdd1243dSDimitry Andric case DeclaratorContext::ObjCCatch:
3270bdd1243dSDimitry Andric case DeclaratorContext::BlockLiteral:
3271bdd1243dSDimitry Andric case DeclaratorContext::LambdaExpr:
3272bdd1243dSDimitry Andric case DeclaratorContext::LambdaExprParameter:
3273bdd1243dSDimitry Andric case DeclaratorContext::RequiresExpr:
32740b57cec5SDimitry Andric return DeclSpecContext::DSC_normal;
32750b57cec5SDimitry Andric }
32760b57cec5SDimitry Andric
3277bdd1243dSDimitry Andric llvm_unreachable("Missing DeclaratorContext case");
3278bdd1243dSDimitry Andric }
3279bdd1243dSDimitry Andric
32800b57cec5SDimitry Andric /// ParseAlignArgument - Parse the argument to an alignment-specifier.
32810b57cec5SDimitry Andric ///
32820b57cec5SDimitry Andric /// [C11] type-id
32830b57cec5SDimitry Andric /// [C11] constant-expression
32840b57cec5SDimitry Andric /// [C++0x] type-id ...[opt]
32850b57cec5SDimitry Andric /// [C++0x] assignment-expression ...[opt]
ParseAlignArgument(StringRef KWName,SourceLocation Start,SourceLocation & EllipsisLoc,bool & IsType,ParsedType & TypeResult)328606c3fb27SDimitry Andric ExprResult Parser::ParseAlignArgument(StringRef KWName, SourceLocation Start,
328706c3fb27SDimitry Andric SourceLocation &EllipsisLoc, bool &IsType,
328806c3fb27SDimitry Andric ParsedType &TypeResult) {
32890b57cec5SDimitry Andric ExprResult ER;
32900b57cec5SDimitry Andric if (isTypeIdInParens()) {
32910b57cec5SDimitry Andric SourceLocation TypeLoc = Tok.getLocation();
32920b57cec5SDimitry Andric ParsedType Ty = ParseTypeName().get();
32930b57cec5SDimitry Andric SourceRange TypeRange(Start, Tok.getLocation());
329406c3fb27SDimitry Andric if (Actions.ActOnAlignasTypeArgument(KWName, Ty, TypeLoc, TypeRange))
329506c3fb27SDimitry Andric return ExprError();
329606c3fb27SDimitry Andric TypeResult = Ty;
329706c3fb27SDimitry Andric IsType = true;
329806c3fb27SDimitry Andric } else {
32990b57cec5SDimitry Andric ER = ParseConstantExpression();
330006c3fb27SDimitry Andric IsType = false;
330106c3fb27SDimitry Andric }
33020b57cec5SDimitry Andric
33030b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11)
33040b57cec5SDimitry Andric TryConsumeToken(tok::ellipsis, EllipsisLoc);
33050b57cec5SDimitry Andric
33060b57cec5SDimitry Andric return ER;
33070b57cec5SDimitry Andric }
33080b57cec5SDimitry Andric
33090b57cec5SDimitry Andric /// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the
33100b57cec5SDimitry Andric /// attribute to Attrs.
33110b57cec5SDimitry Andric ///
33120b57cec5SDimitry Andric /// alignment-specifier:
33130b57cec5SDimitry Andric /// [C11] '_Alignas' '(' type-id ')'
33140b57cec5SDimitry Andric /// [C11] '_Alignas' '(' constant-expression ')'
33150b57cec5SDimitry Andric /// [C++11] 'alignas' '(' type-id ...[opt] ')'
33160b57cec5SDimitry Andric /// [C++11] 'alignas' '(' assignment-expression ...[opt] ')'
ParseAlignmentSpecifier(ParsedAttributes & Attrs,SourceLocation * EndLoc)33170b57cec5SDimitry Andric void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
33180b57cec5SDimitry Andric SourceLocation *EndLoc) {
33190b57cec5SDimitry Andric assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) &&
33200b57cec5SDimitry Andric "Not an alignment-specifier!");
332106c3fb27SDimitry Andric Token KWTok = Tok;
332206c3fb27SDimitry Andric IdentifierInfo *KWName = KWTok.getIdentifierInfo();
332306c3fb27SDimitry Andric auto Kind = KWTok.getKind();
33240b57cec5SDimitry Andric SourceLocation KWLoc = ConsumeToken();
33250b57cec5SDimitry Andric
33260b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
33270b57cec5SDimitry Andric if (T.expectAndConsume())
33280b57cec5SDimitry Andric return;
33290b57cec5SDimitry Andric
333006c3fb27SDimitry Andric bool IsType;
333106c3fb27SDimitry Andric ParsedType TypeResult;
33320b57cec5SDimitry Andric SourceLocation EllipsisLoc;
333306c3fb27SDimitry Andric ExprResult ArgExpr =
333406c3fb27SDimitry Andric ParseAlignArgument(PP.getSpelling(KWTok), T.getOpenLocation(),
333506c3fb27SDimitry Andric EllipsisLoc, IsType, TypeResult);
33360b57cec5SDimitry Andric if (ArgExpr.isInvalid()) {
33370b57cec5SDimitry Andric T.skipToEnd();
33380b57cec5SDimitry Andric return;
33390b57cec5SDimitry Andric }
33400b57cec5SDimitry Andric
33410b57cec5SDimitry Andric T.consumeClose();
33420b57cec5SDimitry Andric if (EndLoc)
33430b57cec5SDimitry Andric *EndLoc = T.getCloseLocation();
33440b57cec5SDimitry Andric
334506c3fb27SDimitry Andric if (IsType) {
334606c3fb27SDimitry Andric Attrs.addNewTypeAttr(KWName, KWLoc, nullptr, KWLoc, TypeResult, Kind,
334706c3fb27SDimitry Andric EllipsisLoc);
334806c3fb27SDimitry Andric } else {
33490b57cec5SDimitry Andric ArgsVector ArgExprs;
33500b57cec5SDimitry Andric ArgExprs.push_back(ArgExpr.get());
335106c3fb27SDimitry Andric Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1, Kind,
335206c3fb27SDimitry Andric EllipsisLoc);
335306c3fb27SDimitry Andric }
33540b57cec5SDimitry Andric }
33550b57cec5SDimitry Andric
DistributeCLateParsedAttrs(Decl * Dcl,LateParsedAttrList * LateAttrs)3356*0fca6ea1SDimitry Andric void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
3357*0fca6ea1SDimitry Andric LateParsedAttrList *LateAttrs) {
3358*0fca6ea1SDimitry Andric if (!LateAttrs)
3359*0fca6ea1SDimitry Andric return;
3360*0fca6ea1SDimitry Andric
3361*0fca6ea1SDimitry Andric if (Dcl) {
3362*0fca6ea1SDimitry Andric for (auto *LateAttr : *LateAttrs) {
3363*0fca6ea1SDimitry Andric if (LateAttr->Decls.empty())
3364*0fca6ea1SDimitry Andric LateAttr->addDecl(Dcl);
3365*0fca6ea1SDimitry Andric }
3366*0fca6ea1SDimitry Andric }
3367*0fca6ea1SDimitry Andric }
3368*0fca6ea1SDimitry Andric
3369*0fca6ea1SDimitry Andric /// Bounds attributes (e.g., counted_by):
3370*0fca6ea1SDimitry Andric /// AttrName '(' expression ')'
ParseBoundsAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Form Form)3371*0fca6ea1SDimitry Andric void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
3372*0fca6ea1SDimitry Andric SourceLocation AttrNameLoc,
3373*0fca6ea1SDimitry Andric ParsedAttributes &Attrs,
3374*0fca6ea1SDimitry Andric IdentifierInfo *ScopeName,
3375*0fca6ea1SDimitry Andric SourceLocation ScopeLoc,
3376*0fca6ea1SDimitry Andric ParsedAttr::Form Form) {
3377*0fca6ea1SDimitry Andric assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
3378*0fca6ea1SDimitry Andric
3379*0fca6ea1SDimitry Andric BalancedDelimiterTracker Parens(*this, tok::l_paren);
3380*0fca6ea1SDimitry Andric Parens.consumeOpen();
3381*0fca6ea1SDimitry Andric
3382*0fca6ea1SDimitry Andric if (Tok.is(tok::r_paren)) {
3383*0fca6ea1SDimitry Andric Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
3384*0fca6ea1SDimitry Andric Parens.consumeClose();
3385*0fca6ea1SDimitry Andric return;
3386*0fca6ea1SDimitry Andric }
3387*0fca6ea1SDimitry Andric
3388*0fca6ea1SDimitry Andric ArgsVector ArgExprs;
3389*0fca6ea1SDimitry Andric // Don't evaluate argument when the attribute is ignored.
3390*0fca6ea1SDimitry Andric using ExpressionKind =
3391*0fca6ea1SDimitry Andric Sema::ExpressionEvaluationContextRecord::ExpressionKind;
3392*0fca6ea1SDimitry Andric EnterExpressionEvaluationContext EC(
3393*0fca6ea1SDimitry Andric Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
3394*0fca6ea1SDimitry Andric ExpressionKind::EK_AttrArgument);
3395*0fca6ea1SDimitry Andric
3396*0fca6ea1SDimitry Andric ExprResult ArgExpr(
3397*0fca6ea1SDimitry Andric Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
3398*0fca6ea1SDimitry Andric
3399*0fca6ea1SDimitry Andric if (ArgExpr.isInvalid()) {
3400*0fca6ea1SDimitry Andric Parens.skipToEnd();
3401*0fca6ea1SDimitry Andric return;
3402*0fca6ea1SDimitry Andric }
3403*0fca6ea1SDimitry Andric
3404*0fca6ea1SDimitry Andric ArgExprs.push_back(ArgExpr.get());
3405*0fca6ea1SDimitry Andric Parens.consumeClose();
3406*0fca6ea1SDimitry Andric
3407*0fca6ea1SDimitry Andric ASTContext &Ctx = Actions.getASTContext();
3408*0fca6ea1SDimitry Andric
3409*0fca6ea1SDimitry Andric ArgExprs.push_back(IntegerLiteral::Create(
3410*0fca6ea1SDimitry Andric Ctx, llvm::APInt(Ctx.getTypeSize(Ctx.getSizeType()), 0),
3411*0fca6ea1SDimitry Andric Ctx.getSizeType(), SourceLocation()));
3412*0fca6ea1SDimitry Andric
3413*0fca6ea1SDimitry Andric Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
3414*0fca6ea1SDimitry Andric ScopeName, ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form);
3415*0fca6ea1SDimitry Andric }
3416*0fca6ea1SDimitry Andric
ParseExtIntegerArgument()34175ffd83dbSDimitry Andric ExprResult Parser::ParseExtIntegerArgument() {
34180eae32dcSDimitry Andric assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) &&
34190eae32dcSDimitry Andric "Not an extended int type");
34205ffd83dbSDimitry Andric ConsumeToken();
34215ffd83dbSDimitry Andric
34225ffd83dbSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
34235ffd83dbSDimitry Andric if (T.expectAndConsume())
34245ffd83dbSDimitry Andric return ExprError();
34255ffd83dbSDimitry Andric
34265ffd83dbSDimitry Andric ExprResult ER = ParseConstantExpression();
34275ffd83dbSDimitry Andric if (ER.isInvalid()) {
34285ffd83dbSDimitry Andric T.skipToEnd();
34295ffd83dbSDimitry Andric return ExprError();
34305ffd83dbSDimitry Andric }
34315ffd83dbSDimitry Andric
34325ffd83dbSDimitry Andric if(T.consumeClose())
34335ffd83dbSDimitry Andric return ExprError();
34345ffd83dbSDimitry Andric return ER;
34355ffd83dbSDimitry Andric }
34365ffd83dbSDimitry Andric
34370b57cec5SDimitry Andric /// Determine whether we're looking at something that might be a declarator
34380b57cec5SDimitry Andric /// in a simple-declaration. If it can't possibly be a declarator, maybe
34390b57cec5SDimitry Andric /// diagnose a missing semicolon after a prior tag definition in the decl
34400b57cec5SDimitry Andric /// specifier.
34410b57cec5SDimitry Andric ///
34420b57cec5SDimitry Andric /// \return \c true if an error occurred and this can't be any kind of
34430b57cec5SDimitry Andric /// declaration.
34440b57cec5SDimitry Andric bool
DiagnoseMissingSemiAfterTagDefinition(DeclSpec & DS,AccessSpecifier AS,DeclSpecContext DSContext,LateParsedAttrList * LateAttrs)34450b57cec5SDimitry Andric Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
34460b57cec5SDimitry Andric DeclSpecContext DSContext,
34470b57cec5SDimitry Andric LateParsedAttrList *LateAttrs) {
34480b57cec5SDimitry Andric assert(DS.hasTagDefinition() && "shouldn't call this");
34490b57cec5SDimitry Andric
34500b57cec5SDimitry Andric bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
34510b57cec5SDimitry Andric DSContext == DeclSpecContext::DSC_top_level);
34520b57cec5SDimitry Andric
34530b57cec5SDimitry Andric if (getLangOpts().CPlusPlus &&
34540b57cec5SDimitry Andric Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
34550b57cec5SDimitry Andric tok::annot_template_id) &&
34560b57cec5SDimitry Andric TryAnnotateCXXScopeToken(EnteringContext)) {
34570b57cec5SDimitry Andric SkipMalformedDecl();
34580b57cec5SDimitry Andric return true;
34590b57cec5SDimitry Andric }
34600b57cec5SDimitry Andric
34610b57cec5SDimitry Andric bool HasScope = Tok.is(tok::annot_cxxscope);
34620b57cec5SDimitry Andric // Make a copy in case GetLookAheadToken invalidates the result of NextToken.
34630b57cec5SDimitry Andric Token AfterScope = HasScope ? NextToken() : Tok;
34640b57cec5SDimitry Andric
34650b57cec5SDimitry Andric // Determine whether the following tokens could possibly be a
34660b57cec5SDimitry Andric // declarator.
34670b57cec5SDimitry Andric bool MightBeDeclarator = true;
34680b57cec5SDimitry Andric if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) {
34690b57cec5SDimitry Andric // A declarator-id can't start with 'typename'.
34700b57cec5SDimitry Andric MightBeDeclarator = false;
34710b57cec5SDimitry Andric } else if (AfterScope.is(tok::annot_template_id)) {
34720b57cec5SDimitry Andric // If we have a type expressed as a template-id, this cannot be a
34730b57cec5SDimitry Andric // declarator-id (such a type cannot be redeclared in a simple-declaration).
34740b57cec5SDimitry Andric TemplateIdAnnotation *Annot =
34750b57cec5SDimitry Andric static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());
34760b57cec5SDimitry Andric if (Annot->Kind == TNK_Type_template)
34770b57cec5SDimitry Andric MightBeDeclarator = false;
34780b57cec5SDimitry Andric } else if (AfterScope.is(tok::identifier)) {
34790b57cec5SDimitry Andric const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken();
34800b57cec5SDimitry Andric
34810b57cec5SDimitry Andric // These tokens cannot come after the declarator-id in a
34820b57cec5SDimitry Andric // simple-declaration, and are likely to come after a type-specifier.
34830b57cec5SDimitry Andric if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier,
34840b57cec5SDimitry Andric tok::annot_cxxscope, tok::coloncolon)) {
34850b57cec5SDimitry Andric // Missing a semicolon.
34860b57cec5SDimitry Andric MightBeDeclarator = false;
34870b57cec5SDimitry Andric } else if (HasScope) {
34880b57cec5SDimitry Andric // If the declarator-id has a scope specifier, it must redeclare a
34890b57cec5SDimitry Andric // previously-declared entity. If that's a type (and this is not a
34900b57cec5SDimitry Andric // typedef), that's an error.
34910b57cec5SDimitry Andric CXXScopeSpec SS;
34920b57cec5SDimitry Andric Actions.RestoreNestedNameSpecifierAnnotation(
34930b57cec5SDimitry Andric Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
34940b57cec5SDimitry Andric IdentifierInfo *Name = AfterScope.getIdentifierInfo();
34950b57cec5SDimitry Andric Sema::NameClassification Classification = Actions.ClassifyName(
34960b57cec5SDimitry Andric getCurScope(), SS, Name, AfterScope.getLocation(), Next,
3497a7dea167SDimitry Andric /*CCC=*/nullptr);
34980b57cec5SDimitry Andric switch (Classification.getKind()) {
34990b57cec5SDimitry Andric case Sema::NC_Error:
35000b57cec5SDimitry Andric SkipMalformedDecl();
35010b57cec5SDimitry Andric return true;
35020b57cec5SDimitry Andric
35030b57cec5SDimitry Andric case Sema::NC_Keyword:
3504a7dea167SDimitry Andric llvm_unreachable("typo correction is not possible here");
35050b57cec5SDimitry Andric
35060b57cec5SDimitry Andric case Sema::NC_Type:
35070b57cec5SDimitry Andric case Sema::NC_TypeTemplate:
3508a7dea167SDimitry Andric case Sema::NC_UndeclaredNonType:
3509a7dea167SDimitry Andric case Sema::NC_UndeclaredTemplate:
35100b57cec5SDimitry Andric // Not a previously-declared non-type entity.
35110b57cec5SDimitry Andric MightBeDeclarator = false;
35120b57cec5SDimitry Andric break;
35130b57cec5SDimitry Andric
35140b57cec5SDimitry Andric case Sema::NC_Unknown:
3515a7dea167SDimitry Andric case Sema::NC_NonType:
3516a7dea167SDimitry Andric case Sema::NC_DependentNonType:
3517e8d8bef9SDimitry Andric case Sema::NC_OverloadSet:
35180b57cec5SDimitry Andric case Sema::NC_VarTemplate:
35190b57cec5SDimitry Andric case Sema::NC_FunctionTemplate:
352055e4f9d5SDimitry Andric case Sema::NC_Concept:
35210b57cec5SDimitry Andric // Might be a redeclaration of a prior entity.
35220b57cec5SDimitry Andric break;
35230b57cec5SDimitry Andric }
35240b57cec5SDimitry Andric }
35250b57cec5SDimitry Andric }
35260b57cec5SDimitry Andric
35270b57cec5SDimitry Andric if (MightBeDeclarator)
35280b57cec5SDimitry Andric return false;
35290b57cec5SDimitry Andric
35300b57cec5SDimitry Andric const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
35310b57cec5SDimitry Andric Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()),
35320b57cec5SDimitry Andric diag::err_expected_after)
35330b57cec5SDimitry Andric << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;
35340b57cec5SDimitry Andric
35350b57cec5SDimitry Andric // Try to recover from the typo, by dropping the tag definition and parsing
35360b57cec5SDimitry Andric // the problematic tokens as a type.
35370b57cec5SDimitry Andric //
35380b57cec5SDimitry Andric // FIXME: Split the DeclSpec into pieces for the standalone
35390b57cec5SDimitry Andric // declaration and pieces for the following declaration, instead
35400b57cec5SDimitry Andric // of assuming that all the other pieces attach to new declaration,
35410b57cec5SDimitry Andric // and call ParsedFreeStandingDeclSpec as appropriate.
35420b57cec5SDimitry Andric DS.ClearTypeSpecType();
35430b57cec5SDimitry Andric ParsedTemplateInfo NotATemplate;
35440b57cec5SDimitry Andric ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);
35450b57cec5SDimitry Andric return false;
35460b57cec5SDimitry Andric }
35470b57cec5SDimitry Andric
35480b57cec5SDimitry Andric /// ParseDeclarationSpecifiers
35490b57cec5SDimitry Andric /// declaration-specifiers: [C99 6.7]
35500b57cec5SDimitry Andric /// storage-class-specifier declaration-specifiers[opt]
35510b57cec5SDimitry Andric /// type-specifier declaration-specifiers[opt]
35520b57cec5SDimitry Andric /// [C99] function-specifier declaration-specifiers[opt]
35530b57cec5SDimitry Andric /// [C11] alignment-specifier declaration-specifiers[opt]
35540b57cec5SDimitry Andric /// [GNU] attributes declaration-specifiers[opt]
35550b57cec5SDimitry Andric /// [Clang] '__module_private__' declaration-specifiers[opt]
35560b57cec5SDimitry Andric /// [ObjC1] '__kindof' declaration-specifiers[opt]
35570b57cec5SDimitry Andric ///
35580b57cec5SDimitry Andric /// storage-class-specifier: [C99 6.7.1]
35590b57cec5SDimitry Andric /// 'typedef'
35600b57cec5SDimitry Andric /// 'extern'
35610b57cec5SDimitry Andric /// 'static'
35620b57cec5SDimitry Andric /// 'auto'
35630b57cec5SDimitry Andric /// 'register'
35640b57cec5SDimitry Andric /// [C++] 'mutable'
35650b57cec5SDimitry Andric /// [C++11] 'thread_local'
35660b57cec5SDimitry Andric /// [C11] '_Thread_local'
35670b57cec5SDimitry Andric /// [GNU] '__thread'
35680b57cec5SDimitry Andric /// function-specifier: [C99 6.7.4]
35690b57cec5SDimitry Andric /// [C99] 'inline'
35700b57cec5SDimitry Andric /// [C++] 'virtual'
35710b57cec5SDimitry Andric /// [C++] 'explicit'
35720b57cec5SDimitry Andric /// [OpenCL] '__kernel'
35730b57cec5SDimitry Andric /// 'friend': [C++ dcl.friend]
35740b57cec5SDimitry Andric /// 'constexpr': [C++0x dcl.constexpr]
ParseDeclarationSpecifiers(DeclSpec & DS,ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSContext,LateParsedAttrList * LateAttrs,ImplicitTypenameContext AllowImplicitTypename)3575bdd1243dSDimitry Andric void Parser::ParseDeclarationSpecifiers(
3576*0fca6ea1SDimitry Andric DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS,
3577bdd1243dSDimitry Andric DeclSpecContext DSContext, LateParsedAttrList *LateAttrs,
3578bdd1243dSDimitry Andric ImplicitTypenameContext AllowImplicitTypename) {
35790b57cec5SDimitry Andric if (DS.getSourceRange().isInvalid()) {
35800b57cec5SDimitry Andric // Start the range at the current token but make the end of the range
35810b57cec5SDimitry Andric // invalid. This will make the entire range invalid unless we successfully
35820b57cec5SDimitry Andric // consume a token.
35830b57cec5SDimitry Andric DS.SetRangeStart(Tok.getLocation());
35840b57cec5SDimitry Andric DS.SetRangeEnd(SourceLocation());
35850b57cec5SDimitry Andric }
35860b57cec5SDimitry Andric
3587bdd1243dSDimitry Andric // If we are in a operator context, convert it back into a type specifier
3588bdd1243dSDimitry Andric // context for better error handling later on.
3589bdd1243dSDimitry Andric if (DSContext == DeclSpecContext::DSC_conv_operator) {
3590bdd1243dSDimitry Andric // No implicit typename here.
3591bdd1243dSDimitry Andric AllowImplicitTypename = ImplicitTypenameContext::No;
3592bdd1243dSDimitry Andric DSContext = DeclSpecContext::DSC_type_specifier;
3593bdd1243dSDimitry Andric }
3594bdd1243dSDimitry Andric
35950b57cec5SDimitry Andric bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
35960b57cec5SDimitry Andric DSContext == DeclSpecContext::DSC_top_level);
35970b57cec5SDimitry Andric bool AttrsLastTime = false;
359881ad6265SDimitry Andric ParsedAttributes attrs(AttrFactory);
35990b57cec5SDimitry Andric // We use Sema's policy to get bool macros right.
36000b57cec5SDimitry Andric PrintingPolicy Policy = Actions.getPrintingPolicy();
360104eeddc0SDimitry Andric while (true) {
36020b57cec5SDimitry Andric bool isInvalid = false;
36030b57cec5SDimitry Andric bool isStorageClass = false;
36040b57cec5SDimitry Andric const char *PrevSpec = nullptr;
36050b57cec5SDimitry Andric unsigned DiagID = 0;
36060b57cec5SDimitry Andric
36070b57cec5SDimitry Andric // This value needs to be set to the location of the last token if the last
36080b57cec5SDimitry Andric // token of the specifier is already consumed.
36090b57cec5SDimitry Andric SourceLocation ConsumedEnd;
36100b57cec5SDimitry Andric
36110b57cec5SDimitry Andric // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
36120b57cec5SDimitry Andric // implementation for VS2013 uses _Atomic as an identifier for one of the
36130b57cec5SDimitry Andric // classes in <atomic>.
36140b57cec5SDimitry Andric //
36150b57cec5SDimitry Andric // A typedef declaration containing _Atomic<...> is among the places where
36160b57cec5SDimitry Andric // the class is used. If we are currently parsing such a declaration, treat
36170b57cec5SDimitry Andric // the token as an identifier.
36180b57cec5SDimitry Andric if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
36190b57cec5SDimitry Andric DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef &&
36200b57cec5SDimitry Andric !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less))
36210b57cec5SDimitry Andric Tok.setKind(tok::identifier);
36220b57cec5SDimitry Andric
36230b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
36240b57cec5SDimitry Andric
3625fe6060f1SDimitry Andric // Helper for image types in OpenCL.
3626fe6060f1SDimitry Andric auto handleOpenCLImageKW = [&] (StringRef Ext, TypeSpecifierType ImageTypeSpec) {
3627fe6060f1SDimitry Andric // Check if the image type is supported and otherwise turn the keyword into an identifier
3628fe6060f1SDimitry Andric // because image types from extensions are not reserved identifiers.
3629fe6060f1SDimitry Andric if (!StringRef(Ext).empty() && !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) {
3630fe6060f1SDimitry Andric Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
3631fe6060f1SDimitry Andric Tok.setKind(tok::identifier);
3632fe6060f1SDimitry Andric return false;
3633fe6060f1SDimitry Andric }
3634fe6060f1SDimitry Andric isInvalid = DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy);
3635fe6060f1SDimitry Andric return true;
3636fe6060f1SDimitry Andric };
3637fe6060f1SDimitry Andric
3638349cc55cSDimitry Andric // Turn off usual access checking for template specializations and
3639349cc55cSDimitry Andric // instantiations.
3640349cc55cSDimitry Andric bool IsTemplateSpecOrInst =
3641349cc55cSDimitry Andric (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
3642349cc55cSDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
3643349cc55cSDimitry Andric
36440b57cec5SDimitry Andric switch (Tok.getKind()) {
36450b57cec5SDimitry Andric default:
364606c3fb27SDimitry Andric if (Tok.isRegularKeywordAttribute())
364706c3fb27SDimitry Andric goto Attribute;
364806c3fb27SDimitry Andric
36490b57cec5SDimitry Andric DoneWithDeclSpec:
36500b57cec5SDimitry Andric if (!AttrsLastTime)
36510b57cec5SDimitry Andric ProhibitAttributes(attrs);
36520b57cec5SDimitry Andric else {
36535f757f3fSDimitry Andric // Reject C++11 / C23 attributes that aren't type attributes.
365481ad6265SDimitry Andric for (const ParsedAttr &PA : attrs) {
36555f757f3fSDimitry Andric if (!PA.isCXX11Attribute() && !PA.isC23Attribute() &&
365606c3fb27SDimitry Andric !PA.isRegularKeywordAttribute())
365781ad6265SDimitry Andric continue;
365881ad6265SDimitry Andric if (PA.getKind() == ParsedAttr::UnknownAttribute)
365981ad6265SDimitry Andric // We will warn about the unknown attribute elsewhere (in
366081ad6265SDimitry Andric // SemaDeclAttr.cpp)
366181ad6265SDimitry Andric continue;
366281ad6265SDimitry Andric // GCC ignores this attribute when placed on the DeclSpec in [[]]
366381ad6265SDimitry Andric // syntax, so we do the same.
366481ad6265SDimitry Andric if (PA.getKind() == ParsedAttr::AT_VectorSize) {
366581ad6265SDimitry Andric Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA;
366681ad6265SDimitry Andric PA.setInvalid();
366781ad6265SDimitry Andric continue;
366881ad6265SDimitry Andric }
366981ad6265SDimitry Andric // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they
367081ad6265SDimitry Andric // are type attributes, because we historically haven't allowed these
36715f757f3fSDimitry Andric // to be used as type attributes in C++11 / C23 syntax.
367281ad6265SDimitry Andric if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound &&
367381ad6265SDimitry Andric PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)
367481ad6265SDimitry Andric continue;
367506c3fb27SDimitry Andric Diag(PA.getLoc(), diag::err_attribute_not_type_attr)
367606c3fb27SDimitry Andric << PA << PA.isRegularKeywordAttribute();
367781ad6265SDimitry Andric PA.setInvalid();
367881ad6265SDimitry Andric }
36790b57cec5SDimitry Andric
36800b57cec5SDimitry Andric DS.takeAttributesFrom(attrs);
36810b57cec5SDimitry Andric }
36820b57cec5SDimitry Andric
36830b57cec5SDimitry Andric // If this is not a declaration specifier token, we're done reading decl
36840b57cec5SDimitry Andric // specifiers. First verify that DeclSpec's are consistent.
36850b57cec5SDimitry Andric DS.Finish(Actions, Policy);
36860b57cec5SDimitry Andric return;
36870b57cec5SDimitry Andric
3688*0fca6ea1SDimitry Andric // alignment-specifier
3689*0fca6ea1SDimitry Andric case tok::kw__Alignas:
3690*0fca6ea1SDimitry Andric diagnoseUseOfC11Keyword(Tok);
3691*0fca6ea1SDimitry Andric [[fallthrough]];
36920b57cec5SDimitry Andric case tok::kw_alignas:
3693*0fca6ea1SDimitry Andric // _Alignas and alignas (C23, not C++) should parse the same way. The C++
3694*0fca6ea1SDimitry Andric // parsing for alignas happens through the usual attribute parsing. This
3695*0fca6ea1SDimitry Andric // ensures that an alignas specifier can appear in a type position in C
3696*0fca6ea1SDimitry Andric // despite that not being valid in C++.
3697*0fca6ea1SDimitry Andric if (getLangOpts().C23 || Tok.getKind() == tok::kw__Alignas) {
3698*0fca6ea1SDimitry Andric if (Tok.getKind() == tok::kw_alignas)
3699*0fca6ea1SDimitry Andric Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
3700*0fca6ea1SDimitry Andric ParseAlignmentSpecifier(DS.getAttributes());
3701*0fca6ea1SDimitry Andric continue;
3702*0fca6ea1SDimitry Andric }
3703*0fca6ea1SDimitry Andric [[fallthrough]];
3704*0fca6ea1SDimitry Andric case tok::l_square:
370506c3fb27SDimitry Andric if (!isAllowedCXX11AttributeSpecifier())
37060b57cec5SDimitry Andric goto DoneWithDeclSpec;
37070b57cec5SDimitry Andric
370806c3fb27SDimitry Andric Attribute:
37090b57cec5SDimitry Andric ProhibitAttributes(attrs);
37100b57cec5SDimitry Andric // FIXME: It would be good to recover by accepting the attributes,
37110b57cec5SDimitry Andric // but attempting to do that now would cause serious
37120b57cec5SDimitry Andric // madness in terms of diagnostics.
37130b57cec5SDimitry Andric attrs.clear();
37140b57cec5SDimitry Andric attrs.Range = SourceRange();
37150b57cec5SDimitry Andric
37160b57cec5SDimitry Andric ParseCXX11Attributes(attrs);
37170b57cec5SDimitry Andric AttrsLastTime = true;
37180b57cec5SDimitry Andric continue;
37190b57cec5SDimitry Andric
37200b57cec5SDimitry Andric case tok::code_completion: {
3721*0fca6ea1SDimitry Andric SemaCodeCompletion::ParserCompletionContext CCC =
3722*0fca6ea1SDimitry Andric SemaCodeCompletion::PCC_Namespace;
37230b57cec5SDimitry Andric if (DS.hasTypeSpecifier()) {
37240b57cec5SDimitry Andric bool AllowNonIdentifiers
37250b57cec5SDimitry Andric = (getCurScope()->getFlags() & (Scope::ControlScope |
37260b57cec5SDimitry Andric Scope::BlockScope |
37270b57cec5SDimitry Andric Scope::TemplateParamScope |
37280b57cec5SDimitry Andric Scope::FunctionPrototypeScope |
37290b57cec5SDimitry Andric Scope::AtCatchScope)) == 0;
37300b57cec5SDimitry Andric bool AllowNestedNameSpecifiers
37310b57cec5SDimitry Andric = DSContext == DeclSpecContext::DSC_top_level ||
37320b57cec5SDimitry Andric (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
37330b57cec5SDimitry Andric
3734fe6060f1SDimitry Andric cutOffParsing();
3735*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteDeclSpec(
3736*0fca6ea1SDimitry Andric getCurScope(), DS, AllowNonIdentifiers, AllowNestedNameSpecifiers);
3737fe6060f1SDimitry Andric return;
37380b57cec5SDimitry Andric }
37390b57cec5SDimitry Andric
3740bdd1243dSDimitry Andric // Class context can appear inside a function/block, so prioritise that.
3741bdd1243dSDimitry Andric if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
3742*0fca6ea1SDimitry Andric CCC = DSContext == DeclSpecContext::DSC_class
3743*0fca6ea1SDimitry Andric ? SemaCodeCompletion::PCC_MemberTemplate
3744*0fca6ea1SDimitry Andric : SemaCodeCompletion::PCC_Template;
37450b57cec5SDimitry Andric else if (DSContext == DeclSpecContext::DSC_class)
3746*0fca6ea1SDimitry Andric CCC = SemaCodeCompletion::PCC_Class;
3747bdd1243dSDimitry Andric else if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
3748*0fca6ea1SDimitry Andric CCC = SemaCodeCompletion::PCC_LocalDeclarationSpecifiers;
37490b57cec5SDimitry Andric else if (CurParsedObjCImpl)
3750*0fca6ea1SDimitry Andric CCC = SemaCodeCompletion::PCC_ObjCImplementation;
37510b57cec5SDimitry Andric
3752fe6060f1SDimitry Andric cutOffParsing();
3753*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteOrdinaryName(getCurScope(), CCC);
3754fe6060f1SDimitry Andric return;
37550b57cec5SDimitry Andric }
37560b57cec5SDimitry Andric
37570b57cec5SDimitry Andric case tok::coloncolon: // ::foo::bar
37580b57cec5SDimitry Andric // C++ scope specifier. Annotate and loop, or bail out on error.
37591db9f3b2SDimitry Andric if (getLangOpts().CPlusPlus &&
37601db9f3b2SDimitry Andric TryAnnotateCXXScopeToken(EnteringContext)) {
37610b57cec5SDimitry Andric if (!DS.hasTypeSpecifier())
37620b57cec5SDimitry Andric DS.SetTypeSpecError();
37630b57cec5SDimitry Andric goto DoneWithDeclSpec;
37640b57cec5SDimitry Andric }
37650b57cec5SDimitry Andric if (Tok.is(tok::coloncolon)) // ::new or ::delete
37660b57cec5SDimitry Andric goto DoneWithDeclSpec;
37670b57cec5SDimitry Andric continue;
37680b57cec5SDimitry Andric
37690b57cec5SDimitry Andric case tok::annot_cxxscope: {
37700b57cec5SDimitry Andric if (DS.hasTypeSpecifier() || DS.isTypeAltiVecVector())
37710b57cec5SDimitry Andric goto DoneWithDeclSpec;
37720b57cec5SDimitry Andric
37730b57cec5SDimitry Andric CXXScopeSpec SS;
377406c3fb27SDimitry Andric if (TemplateInfo.TemplateParams)
377506c3fb27SDimitry Andric SS.setTemplateParamLists(*TemplateInfo.TemplateParams);
37760b57cec5SDimitry Andric Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
37770b57cec5SDimitry Andric Tok.getAnnotationRange(),
37780b57cec5SDimitry Andric SS);
37790b57cec5SDimitry Andric
37800b57cec5SDimitry Andric // We are looking for a qualified typename.
37810b57cec5SDimitry Andric Token Next = NextToken();
37825ffd83dbSDimitry Andric
37835ffd83dbSDimitry Andric TemplateIdAnnotation *TemplateId = Next.is(tok::annot_template_id)
37845ffd83dbSDimitry Andric ? takeTemplateIdAnnotation(Next)
37855ffd83dbSDimitry Andric : nullptr;
37865ffd83dbSDimitry Andric if (TemplateId && TemplateId->hasInvalidName()) {
37875ffd83dbSDimitry Andric // We found something like 'T::U<Args> x', but U is not a template.
37885ffd83dbSDimitry Andric // Assume it was supposed to be a type.
37895ffd83dbSDimitry Andric DS.SetTypeSpecError();
37905ffd83dbSDimitry Andric ConsumeAnnotationToken();
37915ffd83dbSDimitry Andric break;
37925ffd83dbSDimitry Andric }
37935ffd83dbSDimitry Andric
37945ffd83dbSDimitry Andric if (TemplateId && TemplateId->Kind == TNK_Type_template) {
37950b57cec5SDimitry Andric // We have a qualified template-id, e.g., N::A<int>
37960b57cec5SDimitry Andric
37970b57cec5SDimitry Andric // If this would be a valid constructor declaration with template
37980b57cec5SDimitry Andric // arguments, we will reject the attempt to form an invalid type-id
37990b57cec5SDimitry Andric // referring to the injected-class-name when we annotate the token,
38000b57cec5SDimitry Andric // per C++ [class.qual]p2.
38010b57cec5SDimitry Andric //
38020b57cec5SDimitry Andric // To improve diagnostics for this case, parse the declaration as a
38030b57cec5SDimitry Andric // constructor (and reject the extra template arguments later).
38040b57cec5SDimitry Andric if ((DSContext == DeclSpecContext::DSC_top_level ||
38050b57cec5SDimitry Andric DSContext == DeclSpecContext::DSC_class) &&
38060b57cec5SDimitry Andric TemplateId->Name &&
38070b57cec5SDimitry Andric Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
3808bdd1243dSDimitry Andric isConstructorDeclarator(/*Unqualified=*/false,
3809bdd1243dSDimitry Andric /*DeductionGuide=*/false,
3810bdd1243dSDimitry Andric DS.isFriendSpecified())) {
38110b57cec5SDimitry Andric // The user meant this to be an out-of-line constructor
38120b57cec5SDimitry Andric // definition, but template arguments are not allowed
38130b57cec5SDimitry Andric // there. Just allow this as a constructor; we'll
38140b57cec5SDimitry Andric // complain about it later.
38150b57cec5SDimitry Andric goto DoneWithDeclSpec;
38160b57cec5SDimitry Andric }
38170b57cec5SDimitry Andric
38180b57cec5SDimitry Andric DS.getTypeSpecScope() = SS;
38190b57cec5SDimitry Andric ConsumeAnnotationToken(); // The C++ scope.
38200b57cec5SDimitry Andric assert(Tok.is(tok::annot_template_id) &&
38210b57cec5SDimitry Andric "ParseOptionalCXXScopeSpecifier not working");
3822bdd1243dSDimitry Andric AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
382355e4f9d5SDimitry Andric continue;
382455e4f9d5SDimitry Andric }
382555e4f9d5SDimitry Andric
382606c3fb27SDimitry Andric if (TemplateId && TemplateId->Kind == TNK_Concept_template) {
382755e4f9d5SDimitry Andric DS.getTypeSpecScope() = SS;
382806c3fb27SDimitry Andric // This is probably a qualified placeholder-specifier, e.g., ::C<int>
382906c3fb27SDimitry Andric // auto ... Consume the scope annotation and continue to consume the
383006c3fb27SDimitry Andric // template-id as a placeholder-specifier. Let the next iteration
383106c3fb27SDimitry Andric // diagnose a missing auto.
383255e4f9d5SDimitry Andric ConsumeAnnotationToken();
38330b57cec5SDimitry Andric continue;
38340b57cec5SDimitry Andric }
38350b57cec5SDimitry Andric
38360b57cec5SDimitry Andric if (Next.is(tok::annot_typename)) {
38370b57cec5SDimitry Andric DS.getTypeSpecScope() = SS;
38380b57cec5SDimitry Andric ConsumeAnnotationToken(); // The C++ scope.
38395ffd83dbSDimitry Andric TypeResult T = getTypeAnnotation(Tok);
38400b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
38410b57cec5SDimitry Andric Tok.getAnnotationEndLoc(),
38420b57cec5SDimitry Andric PrevSpec, DiagID, T, Policy);
38430b57cec5SDimitry Andric if (isInvalid)
38440b57cec5SDimitry Andric break;
38450b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getAnnotationEndLoc());
38460b57cec5SDimitry Andric ConsumeAnnotationToken(); // The typename
38470b57cec5SDimitry Andric }
38480b57cec5SDimitry Andric
3849bdd1243dSDimitry Andric if (AllowImplicitTypename == ImplicitTypenameContext::Yes &&
3850bdd1243dSDimitry Andric Next.is(tok::annot_template_id) &&
3851bdd1243dSDimitry Andric static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
3852bdd1243dSDimitry Andric ->Kind == TNK_Dependent_template_name) {
3853bdd1243dSDimitry Andric DS.getTypeSpecScope() = SS;
3854bdd1243dSDimitry Andric ConsumeAnnotationToken(); // The C++ scope.
3855bdd1243dSDimitry Andric AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
3856bdd1243dSDimitry Andric continue;
3857bdd1243dSDimitry Andric }
3858bdd1243dSDimitry Andric
38590b57cec5SDimitry Andric if (Next.isNot(tok::identifier))
38600b57cec5SDimitry Andric goto DoneWithDeclSpec;
38610b57cec5SDimitry Andric
38620b57cec5SDimitry Andric // Check whether this is a constructor declaration. If we're in a
38630b57cec5SDimitry Andric // context where the identifier could be a class name, and it has the
38640b57cec5SDimitry Andric // shape of a constructor declaration, process it as one.
38650b57cec5SDimitry Andric if ((DSContext == DeclSpecContext::DSC_top_level ||
38660b57cec5SDimitry Andric DSContext == DeclSpecContext::DSC_class) &&
38670b57cec5SDimitry Andric Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
38680b57cec5SDimitry Andric &SS) &&
3869bdd1243dSDimitry Andric isConstructorDeclarator(/*Unqualified=*/false,
3870bdd1243dSDimitry Andric /*DeductionGuide=*/false,
387106c3fb27SDimitry Andric DS.isFriendSpecified(),
387206c3fb27SDimitry Andric &TemplateInfo))
38730b57cec5SDimitry Andric goto DoneWithDeclSpec;
38740b57cec5SDimitry Andric
3875349cc55cSDimitry Andric // C++20 [temp.spec] 13.9/6.
3876349cc55cSDimitry Andric // This disables the access checking rules for function template explicit
3877349cc55cSDimitry Andric // instantiation and explicit specialization:
3878349cc55cSDimitry Andric // - `return type`.
3879349cc55cSDimitry Andric SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
3880349cc55cSDimitry Andric
3881bdd1243dSDimitry Andric ParsedType TypeRep = Actions.getTypeName(
3882bdd1243dSDimitry Andric *Next.getIdentifierInfo(), Next.getLocation(), getCurScope(), &SS,
3883bdd1243dSDimitry Andric false, false, nullptr,
38840b57cec5SDimitry Andric /*IsCtorOrDtorName=*/false,
38850b57cec5SDimitry Andric /*WantNontrivialTypeSourceInfo=*/true,
3886bdd1243dSDimitry Andric isClassTemplateDeductionContext(DSContext), AllowImplicitTypename);
38870b57cec5SDimitry Andric
3888349cc55cSDimitry Andric if (IsTemplateSpecOrInst)
3889349cc55cSDimitry Andric SAC.done();
3890349cc55cSDimitry Andric
38910b57cec5SDimitry Andric // If the referenced identifier is not a type, then this declspec is
38920b57cec5SDimitry Andric // erroneous: We already checked about that it has no type specifier, and
38930b57cec5SDimitry Andric // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
38940b57cec5SDimitry Andric // typename.
38950b57cec5SDimitry Andric if (!TypeRep) {
389655e4f9d5SDimitry Andric if (TryAnnotateTypeConstraint())
389755e4f9d5SDimitry Andric goto DoneWithDeclSpec;
38985ffd83dbSDimitry Andric if (Tok.isNot(tok::annot_cxxscope) ||
38995ffd83dbSDimitry Andric NextToken().isNot(tok::identifier))
3900aec4c088SDimitry Andric continue;
39010b57cec5SDimitry Andric // Eat the scope spec so the identifier is current.
39020b57cec5SDimitry Andric ConsumeAnnotationToken();
390381ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory);
39040b57cec5SDimitry Andric if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {
39050b57cec5SDimitry Andric if (!Attrs.empty()) {
39060b57cec5SDimitry Andric AttrsLastTime = true;
39070b57cec5SDimitry Andric attrs.takeAllFrom(Attrs);
39080b57cec5SDimitry Andric }
39090b57cec5SDimitry Andric continue;
39100b57cec5SDimitry Andric }
39110b57cec5SDimitry Andric goto DoneWithDeclSpec;
39120b57cec5SDimitry Andric }
39130b57cec5SDimitry Andric
39140b57cec5SDimitry Andric DS.getTypeSpecScope() = SS;
39150b57cec5SDimitry Andric ConsumeAnnotationToken(); // The C++ scope.
39160b57cec5SDimitry Andric
39170b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
39180b57cec5SDimitry Andric DiagID, TypeRep, Policy);
39190b57cec5SDimitry Andric if (isInvalid)
39200b57cec5SDimitry Andric break;
39210b57cec5SDimitry Andric
39220b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getLocation());
39230b57cec5SDimitry Andric ConsumeToken(); // The typename.
39240b57cec5SDimitry Andric
39250b57cec5SDimitry Andric continue;
39260b57cec5SDimitry Andric }
39270b57cec5SDimitry Andric
39280b57cec5SDimitry Andric case tok::annot_typename: {
39290b57cec5SDimitry Andric // If we've previously seen a tag definition, we were almost surely
39300b57cec5SDimitry Andric // missing a semicolon after it.
39310b57cec5SDimitry Andric if (DS.hasTypeSpecifier() && DS.hasTagDefinition())
39320b57cec5SDimitry Andric goto DoneWithDeclSpec;
39330b57cec5SDimitry Andric
39345ffd83dbSDimitry Andric TypeResult T = getTypeAnnotation(Tok);
39350b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
39360b57cec5SDimitry Andric DiagID, T, Policy);
39370b57cec5SDimitry Andric if (isInvalid)
39380b57cec5SDimitry Andric break;
39390b57cec5SDimitry Andric
39400b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getAnnotationEndLoc());
39410b57cec5SDimitry Andric ConsumeAnnotationToken(); // The typename
39420b57cec5SDimitry Andric
39430b57cec5SDimitry Andric continue;
39440b57cec5SDimitry Andric }
39450b57cec5SDimitry Andric
39460b57cec5SDimitry Andric case tok::kw___is_signed:
39470b57cec5SDimitry Andric // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang
39480b57cec5SDimitry Andric // typically treats it as a trait. If we see __is_signed as it appears
39490b57cec5SDimitry Andric // in libstdc++, e.g.,
39500b57cec5SDimitry Andric //
39510b57cec5SDimitry Andric // static const bool __is_signed;
39520b57cec5SDimitry Andric //
39530b57cec5SDimitry Andric // then treat __is_signed as an identifier rather than as a keyword.
39540b57cec5SDimitry Andric if (DS.getTypeSpecType() == TST_bool &&
39550b57cec5SDimitry Andric DS.getTypeQualifiers() == DeclSpec::TQ_const &&
39560b57cec5SDimitry Andric DS.getStorageClassSpec() == DeclSpec::SCS_static)
39570b57cec5SDimitry Andric TryKeywordIdentFallback(true);
39580b57cec5SDimitry Andric
39590b57cec5SDimitry Andric // We're done with the declaration-specifiers.
39600b57cec5SDimitry Andric goto DoneWithDeclSpec;
39610b57cec5SDimitry Andric
39620b57cec5SDimitry Andric // typedef-name
39630b57cec5SDimitry Andric case tok::kw___super:
39640b57cec5SDimitry Andric case tok::kw_decltype:
3965bdd1243dSDimitry Andric case tok::identifier:
3966bdd1243dSDimitry Andric ParseIdentifier: {
39670b57cec5SDimitry Andric // This identifier can only be a typedef name if we haven't already seen
39680b57cec5SDimitry Andric // a type-specifier. Without this check we misparse:
39690b57cec5SDimitry Andric // typedef int X; struct Y { short X; }; as 'short int'.
39700b57cec5SDimitry Andric if (DS.hasTypeSpecifier())
39710b57cec5SDimitry Andric goto DoneWithDeclSpec;
39720b57cec5SDimitry Andric
39730b57cec5SDimitry Andric // If the token is an identifier named "__declspec" and Microsoft
39740b57cec5SDimitry Andric // extensions are not enabled, it is likely that there will be cascading
39750b57cec5SDimitry Andric // parse errors if this really is a __declspec attribute. Attempt to
39760b57cec5SDimitry Andric // recognize that scenario and recover gracefully.
39770b57cec5SDimitry Andric if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) &&
3978*0fca6ea1SDimitry Andric Tok.getIdentifierInfo()->getName() == "__declspec") {
39790b57cec5SDimitry Andric Diag(Loc, diag::err_ms_attributes_not_enabled);
39800b57cec5SDimitry Andric
39810b57cec5SDimitry Andric // The next token should be an open paren. If it is, eat the entire
39820b57cec5SDimitry Andric // attribute declaration and continue.
39830b57cec5SDimitry Andric if (NextToken().is(tok::l_paren)) {
39840b57cec5SDimitry Andric // Consume the __declspec identifier.
39850b57cec5SDimitry Andric ConsumeToken();
39860b57cec5SDimitry Andric
39870b57cec5SDimitry Andric // Eat the parens and everything between them.
39880b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
39890b57cec5SDimitry Andric if (T.consumeOpen()) {
39900b57cec5SDimitry Andric assert(false && "Not a left paren?");
39910b57cec5SDimitry Andric return;
39920b57cec5SDimitry Andric }
39930b57cec5SDimitry Andric T.skipToEnd();
39940b57cec5SDimitry Andric continue;
39950b57cec5SDimitry Andric }
39960b57cec5SDimitry Andric }
39970b57cec5SDimitry Andric
39980b57cec5SDimitry Andric // In C++, check to see if this is a scope specifier like foo::bar::, if
39990b57cec5SDimitry Andric // so handle it as such. This is important for ctor parsing.
40000b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) {
4001349cc55cSDimitry Andric // C++20 [temp.spec] 13.9/6.
4002349cc55cSDimitry Andric // This disables the access checking rules for function template
4003349cc55cSDimitry Andric // explicit instantiation and explicit specialization:
4004349cc55cSDimitry Andric // - `return type`.
4005349cc55cSDimitry Andric SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
4006349cc55cSDimitry Andric
4007349cc55cSDimitry Andric const bool Success = TryAnnotateCXXScopeToken(EnteringContext);
4008349cc55cSDimitry Andric
4009349cc55cSDimitry Andric if (IsTemplateSpecOrInst)
4010349cc55cSDimitry Andric SAC.done();
4011349cc55cSDimitry Andric
4012349cc55cSDimitry Andric if (Success) {
4013349cc55cSDimitry Andric if (IsTemplateSpecOrInst)
4014349cc55cSDimitry Andric SAC.redelay();
40150b57cec5SDimitry Andric DS.SetTypeSpecError();
40160b57cec5SDimitry Andric goto DoneWithDeclSpec;
40170b57cec5SDimitry Andric }
4018349cc55cSDimitry Andric
40190b57cec5SDimitry Andric if (!Tok.is(tok::identifier))
40200b57cec5SDimitry Andric continue;
40210b57cec5SDimitry Andric }
40220b57cec5SDimitry Andric
40230b57cec5SDimitry Andric // Check for need to substitute AltiVec keyword tokens.
40240b57cec5SDimitry Andric if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
40250b57cec5SDimitry Andric break;
40260b57cec5SDimitry Andric
40270b57cec5SDimitry Andric // [AltiVec] 2.2: [If the 'vector' specifier is used] The syntax does not
40280b57cec5SDimitry Andric // allow the use of a typedef name as a type specifier.
40290b57cec5SDimitry Andric if (DS.isTypeAltiVecVector())
40300b57cec5SDimitry Andric goto DoneWithDeclSpec;
40310b57cec5SDimitry Andric
40320b57cec5SDimitry Andric if (DSContext == DeclSpecContext::DSC_objc_method_result &&
40330b57cec5SDimitry Andric isObjCInstancetype()) {
4034*0fca6ea1SDimitry Andric ParsedType TypeRep = Actions.ObjC().ActOnObjCInstanceType(Loc);
40350b57cec5SDimitry Andric assert(TypeRep);
40360b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
40370b57cec5SDimitry Andric DiagID, TypeRep, Policy);
40380b57cec5SDimitry Andric if (isInvalid)
40390b57cec5SDimitry Andric break;
40400b57cec5SDimitry Andric
40410b57cec5SDimitry Andric DS.SetRangeEnd(Loc);
40420b57cec5SDimitry Andric ConsumeToken();
40430b57cec5SDimitry Andric continue;
40440b57cec5SDimitry Andric }
40450b57cec5SDimitry Andric
40460b57cec5SDimitry Andric // If we're in a context where the identifier could be a class name,
40470b57cec5SDimitry Andric // check whether this is a constructor declaration.
40480b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
40490b57cec5SDimitry Andric Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
4050bdd1243dSDimitry Andric isConstructorDeclarator(/*Unqualified=*/true,
4051bdd1243dSDimitry Andric /*DeductionGuide=*/false,
4052bdd1243dSDimitry Andric DS.isFriendSpecified()))
40530b57cec5SDimitry Andric goto DoneWithDeclSpec;
40540b57cec5SDimitry Andric
40550b57cec5SDimitry Andric ParsedType TypeRep = Actions.getTypeName(
40560b57cec5SDimitry Andric *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,
40570b57cec5SDimitry Andric false, false, nullptr, false, false,
40580b57cec5SDimitry Andric isClassTemplateDeductionContext(DSContext));
40590b57cec5SDimitry Andric
40600b57cec5SDimitry Andric // If this is not a typedef name, don't parse it as part of the declspec,
40610b57cec5SDimitry Andric // it must be an implicit int or an error.
40620b57cec5SDimitry Andric if (!TypeRep) {
406355e4f9d5SDimitry Andric if (TryAnnotateTypeConstraint())
406455e4f9d5SDimitry Andric goto DoneWithDeclSpec;
40655ffd83dbSDimitry Andric if (Tok.isNot(tok::identifier))
4066aec4c088SDimitry Andric continue;
406781ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory);
40680b57cec5SDimitry Andric if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) {
40690b57cec5SDimitry Andric if (!Attrs.empty()) {
40700b57cec5SDimitry Andric AttrsLastTime = true;
40710b57cec5SDimitry Andric attrs.takeAllFrom(Attrs);
40720b57cec5SDimitry Andric }
40730b57cec5SDimitry Andric continue;
40740b57cec5SDimitry Andric }
40750b57cec5SDimitry Andric goto DoneWithDeclSpec;
40760b57cec5SDimitry Andric }
40770b57cec5SDimitry Andric
40780b57cec5SDimitry Andric // Likewise, if this is a context where the identifier could be a template
40790b57cec5SDimitry Andric // name, check whether this is a deduction guide declaration.
408006c3fb27SDimitry Andric CXXScopeSpec SS;
40810b57cec5SDimitry Andric if (getLangOpts().CPlusPlus17 &&
40820b57cec5SDimitry Andric (DSContext == DeclSpecContext::DSC_class ||
40830b57cec5SDimitry Andric DSContext == DeclSpecContext::DSC_top_level) &&
40840b57cec5SDimitry Andric Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
408506c3fb27SDimitry Andric Tok.getLocation(), SS) &&
40860b57cec5SDimitry Andric isConstructorDeclarator(/*Unqualified*/ true,
40870b57cec5SDimitry Andric /*DeductionGuide*/ true))
40880b57cec5SDimitry Andric goto DoneWithDeclSpec;
40890b57cec5SDimitry Andric
40900b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
40910b57cec5SDimitry Andric DiagID, TypeRep, Policy);
40920b57cec5SDimitry Andric if (isInvalid)
40930b57cec5SDimitry Andric break;
40940b57cec5SDimitry Andric
40950b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getLocation());
40960b57cec5SDimitry Andric ConsumeToken(); // The identifier
40970b57cec5SDimitry Andric
40980b57cec5SDimitry Andric // Objective-C supports type arguments and protocol references
40990b57cec5SDimitry Andric // following an Objective-C object or object pointer
41000b57cec5SDimitry Andric // type. Handle either one of them.
41010b57cec5SDimitry Andric if (Tok.is(tok::less) && getLangOpts().ObjC) {
41020b57cec5SDimitry Andric SourceLocation NewEndLoc;
41030b57cec5SDimitry Andric TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers(
41040b57cec5SDimitry Andric Loc, TypeRep, /*consumeLastToken=*/true,
41050b57cec5SDimitry Andric NewEndLoc);
41060b57cec5SDimitry Andric if (NewTypeRep.isUsable()) {
41070b57cec5SDimitry Andric DS.UpdateTypeRep(NewTypeRep.get());
41080b57cec5SDimitry Andric DS.SetRangeEnd(NewEndLoc);
41090b57cec5SDimitry Andric }
41100b57cec5SDimitry Andric }
41110b57cec5SDimitry Andric
41120b57cec5SDimitry Andric // Need to support trailing type qualifiers (e.g. "id<p> const").
41130b57cec5SDimitry Andric // If a type specifier follows, it will be diagnosed elsewhere.
41140b57cec5SDimitry Andric continue;
41150b57cec5SDimitry Andric }
41160b57cec5SDimitry Andric
411755e4f9d5SDimitry Andric // type-name or placeholder-specifier
41180b57cec5SDimitry Andric case tok::annot_template_id: {
41190b57cec5SDimitry Andric TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
41205ffd83dbSDimitry Andric
41215ffd83dbSDimitry Andric if (TemplateId->hasInvalidName()) {
41225ffd83dbSDimitry Andric DS.SetTypeSpecError();
41235ffd83dbSDimitry Andric break;
41245ffd83dbSDimitry Andric }
41255ffd83dbSDimitry Andric
412655e4f9d5SDimitry Andric if (TemplateId->Kind == TNK_Concept_template) {
41275ffd83dbSDimitry Andric // If we've already diagnosed that this type-constraint has invalid
4128bdd1243dSDimitry Andric // arguments, drop it and just form 'auto' or 'decltype(auto)'.
41295ffd83dbSDimitry Andric if (TemplateId->hasInvalidArgs())
41305ffd83dbSDimitry Andric TemplateId = nullptr;
41315ffd83dbSDimitry Andric
4132bdd1243dSDimitry Andric // Any of the following tokens are likely the start of the user
4133bdd1243dSDimitry Andric // forgetting 'auto' or 'decltype(auto)', so diagnose.
4134bdd1243dSDimitry Andric // Note: if updating this list, please make sure we update
4135bdd1243dSDimitry Andric // isCXXDeclarationSpecifier's check for IsPlaceholderSpecifier to have
4136bdd1243dSDimitry Andric // a matching list.
4137bdd1243dSDimitry Andric if (NextToken().isOneOf(tok::identifier, tok::kw_const,
4138bdd1243dSDimitry Andric tok::kw_volatile, tok::kw_restrict, tok::amp,
4139bdd1243dSDimitry Andric tok::ampamp)) {
414055e4f9d5SDimitry Andric Diag(Loc, diag::err_placeholder_expected_auto_or_decltype_auto)
414155e4f9d5SDimitry Andric << FixItHint::CreateInsertion(NextToken().getLocation(), "auto");
414255e4f9d5SDimitry Andric // Attempt to continue as if 'auto' was placed here.
414355e4f9d5SDimitry Andric isInvalid = DS.SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID,
414455e4f9d5SDimitry Andric TemplateId, Policy);
414555e4f9d5SDimitry Andric break;
414655e4f9d5SDimitry Andric }
414755e4f9d5SDimitry Andric if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
414855e4f9d5SDimitry Andric goto DoneWithDeclSpec;
414906c3fb27SDimitry Andric
415006c3fb27SDimitry Andric if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))
415106c3fb27SDimitry Andric TemplateId = nullptr;
415206c3fb27SDimitry Andric
415355e4f9d5SDimitry Andric ConsumeAnnotationToken();
415455e4f9d5SDimitry Andric SourceLocation AutoLoc = Tok.getLocation();
415555e4f9d5SDimitry Andric if (TryConsumeToken(tok::kw_decltype)) {
415655e4f9d5SDimitry Andric BalancedDelimiterTracker Tracker(*this, tok::l_paren);
415755e4f9d5SDimitry Andric if (Tracker.consumeOpen()) {
415855e4f9d5SDimitry Andric // Something like `void foo(Iterator decltype i)`
415955e4f9d5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren;
416055e4f9d5SDimitry Andric } else {
416155e4f9d5SDimitry Andric if (!TryConsumeToken(tok::kw_auto)) {
416255e4f9d5SDimitry Andric // Something like `void foo(Iterator decltype(int) i)`
416355e4f9d5SDimitry Andric Tracker.skipToEnd();
416455e4f9d5SDimitry Andric Diag(Tok, diag::err_placeholder_expected_auto_or_decltype_auto)
416555e4f9d5SDimitry Andric << FixItHint::CreateReplacement(SourceRange(AutoLoc,
416655e4f9d5SDimitry Andric Tok.getLocation()),
416755e4f9d5SDimitry Andric "auto");
416855e4f9d5SDimitry Andric } else {
416955e4f9d5SDimitry Andric Tracker.consumeClose();
417055e4f9d5SDimitry Andric }
417155e4f9d5SDimitry Andric }
417255e4f9d5SDimitry Andric ConsumedEnd = Tok.getLocation();
4173bdd1243dSDimitry Andric DS.setTypeArgumentRange(Tracker.getRange());
417455e4f9d5SDimitry Andric // Even if something went wrong above, continue as if we've seen
417555e4f9d5SDimitry Andric // `decltype(auto)`.
417655e4f9d5SDimitry Andric isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec,
417755e4f9d5SDimitry Andric DiagID, TemplateId, Policy);
417855e4f9d5SDimitry Andric } else {
417904eeddc0SDimitry Andric isInvalid = DS.SetTypeSpecType(TST_auto, AutoLoc, PrevSpec, DiagID,
418055e4f9d5SDimitry Andric TemplateId, Policy);
418155e4f9d5SDimitry Andric }
418255e4f9d5SDimitry Andric break;
418355e4f9d5SDimitry Andric }
418455e4f9d5SDimitry Andric
41850b57cec5SDimitry Andric if (TemplateId->Kind != TNK_Type_template &&
41860b57cec5SDimitry Andric TemplateId->Kind != TNK_Undeclared_template) {
41870b57cec5SDimitry Andric // This template-id does not refer to a type name, so we're
41880b57cec5SDimitry Andric // done with the type-specifiers.
41890b57cec5SDimitry Andric goto DoneWithDeclSpec;
41900b57cec5SDimitry Andric }
41910b57cec5SDimitry Andric
41920b57cec5SDimitry Andric // If we're in a context where the template-id could be a
41930b57cec5SDimitry Andric // constructor name or specialization, check whether this is a
41940b57cec5SDimitry Andric // constructor declaration.
41950b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
41960b57cec5SDimitry Andric Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
4197bdd1243dSDimitry Andric isConstructorDeclarator(/*Unqualified=*/true,
4198bdd1243dSDimitry Andric /*DeductionGuide=*/false,
4199bdd1243dSDimitry Andric DS.isFriendSpecified()))
42000b57cec5SDimitry Andric goto DoneWithDeclSpec;
42010b57cec5SDimitry Andric
42020b57cec5SDimitry Andric // Turn the template-id annotation token into a type annotation
42030b57cec5SDimitry Andric // token, then try again to parse it as a type-specifier.
420455e4f9d5SDimitry Andric CXXScopeSpec SS;
4205bdd1243dSDimitry Andric AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
42060b57cec5SDimitry Andric continue;
42070b57cec5SDimitry Andric }
42080b57cec5SDimitry Andric
4209fe6060f1SDimitry Andric // Attributes support.
42100b57cec5SDimitry Andric case tok::kw___attribute:
42110b57cec5SDimitry Andric case tok::kw___declspec:
421281ad6265SDimitry Andric ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), LateAttrs);
42130b57cec5SDimitry Andric continue;
42140b57cec5SDimitry Andric
42150b57cec5SDimitry Andric // Microsoft single token adornments.
42160b57cec5SDimitry Andric case tok::kw___forceinline: {
42170b57cec5SDimitry Andric isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);
42180b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo();
42190b57cec5SDimitry Andric SourceLocation AttrNameLoc = Tok.getLocation();
42200b57cec5SDimitry Andric DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,
422106c3fb27SDimitry Andric nullptr, 0, tok::kw___forceinline);
42220b57cec5SDimitry Andric break;
42230b57cec5SDimitry Andric }
42240b57cec5SDimitry Andric
42250b57cec5SDimitry Andric case tok::kw___unaligned:
42260b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,
42270b57cec5SDimitry Andric getLangOpts());
42280b57cec5SDimitry Andric break;
42290b57cec5SDimitry Andric
42300b57cec5SDimitry Andric case tok::kw___sptr:
42310b57cec5SDimitry Andric case tok::kw___uptr:
42320b57cec5SDimitry Andric case tok::kw___ptr64:
42330b57cec5SDimitry Andric case tok::kw___ptr32:
42340b57cec5SDimitry Andric case tok::kw___w64:
42350b57cec5SDimitry Andric case tok::kw___cdecl:
42360b57cec5SDimitry Andric case tok::kw___stdcall:
42370b57cec5SDimitry Andric case tok::kw___fastcall:
42380b57cec5SDimitry Andric case tok::kw___thiscall:
42390b57cec5SDimitry Andric case tok::kw___regcall:
42400b57cec5SDimitry Andric case tok::kw___vectorcall:
42410b57cec5SDimitry Andric ParseMicrosoftTypeAttributes(DS.getAttributes());
42420b57cec5SDimitry Andric continue;
42430b57cec5SDimitry Andric
424406c3fb27SDimitry Andric case tok::kw___funcref:
424506c3fb27SDimitry Andric ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes());
424606c3fb27SDimitry Andric continue;
424706c3fb27SDimitry Andric
42480b57cec5SDimitry Andric // Borland single token adornments.
42490b57cec5SDimitry Andric case tok::kw___pascal:
42500b57cec5SDimitry Andric ParseBorlandTypeAttributes(DS.getAttributes());
42510b57cec5SDimitry Andric continue;
42520b57cec5SDimitry Andric
42530b57cec5SDimitry Andric // OpenCL single token adornments.
42540b57cec5SDimitry Andric case tok::kw___kernel:
42550b57cec5SDimitry Andric ParseOpenCLKernelAttributes(DS.getAttributes());
42560b57cec5SDimitry Andric continue;
42570b57cec5SDimitry Andric
425881ad6265SDimitry Andric // CUDA/HIP single token adornments.
425981ad6265SDimitry Andric case tok::kw___noinline__:
426081ad6265SDimitry Andric ParseCUDAFunctionAttributes(DS.getAttributes());
426181ad6265SDimitry Andric continue;
426281ad6265SDimitry Andric
42630b57cec5SDimitry Andric // Nullability type specifiers.
42640b57cec5SDimitry Andric case tok::kw__Nonnull:
42650b57cec5SDimitry Andric case tok::kw__Nullable:
4266e8d8bef9SDimitry Andric case tok::kw__Nullable_result:
42670b57cec5SDimitry Andric case tok::kw__Null_unspecified:
42680b57cec5SDimitry Andric ParseNullabilityTypeSpecifiers(DS.getAttributes());
42690b57cec5SDimitry Andric continue;
42700b57cec5SDimitry Andric
42710b57cec5SDimitry Andric // Objective-C 'kindof' types.
42720b57cec5SDimitry Andric case tok::kw___kindof:
42730b57cec5SDimitry Andric DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
427406c3fb27SDimitry Andric nullptr, 0, tok::kw___kindof);
42750b57cec5SDimitry Andric (void)ConsumeToken();
42760b57cec5SDimitry Andric continue;
42770b57cec5SDimitry Andric
42780b57cec5SDimitry Andric // storage-class-specifier
42790b57cec5SDimitry Andric case tok::kw_typedef:
42800b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
42810b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
42820b57cec5SDimitry Andric isStorageClass = true;
42830b57cec5SDimitry Andric break;
42840b57cec5SDimitry Andric case tok::kw_extern:
42850b57cec5SDimitry Andric if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
42860b57cec5SDimitry Andric Diag(Tok, diag::ext_thread_before) << "extern";
42870b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
42880b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
42890b57cec5SDimitry Andric isStorageClass = true;
42900b57cec5SDimitry Andric break;
42910b57cec5SDimitry Andric case tok::kw___private_extern__:
42920b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
42930b57cec5SDimitry Andric Loc, PrevSpec, DiagID, Policy);
42940b57cec5SDimitry Andric isStorageClass = true;
42950b57cec5SDimitry Andric break;
42960b57cec5SDimitry Andric case tok::kw_static:
42970b57cec5SDimitry Andric if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
42980b57cec5SDimitry Andric Diag(Tok, diag::ext_thread_before) << "static";
42990b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
43000b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
43010b57cec5SDimitry Andric isStorageClass = true;
43020b57cec5SDimitry Andric break;
43030b57cec5SDimitry Andric case tok::kw_auto:
43045f757f3fSDimitry Andric if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
43050b57cec5SDimitry Andric if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
43060b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
43070b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
43085f757f3fSDimitry Andric if (!isInvalid && !getLangOpts().C23)
43090b57cec5SDimitry Andric Diag(Tok, diag::ext_auto_storage_class)
43100b57cec5SDimitry Andric << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
43110b57cec5SDimitry Andric } else
43120b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
43130b57cec5SDimitry Andric DiagID, Policy);
43140b57cec5SDimitry Andric } else
43150b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
43160b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
43170b57cec5SDimitry Andric isStorageClass = true;
43180b57cec5SDimitry Andric break;
43190b57cec5SDimitry Andric case tok::kw___auto_type:
43200b57cec5SDimitry Andric Diag(Tok, diag::ext_auto_type);
43210b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
43220b57cec5SDimitry Andric DiagID, Policy);
43230b57cec5SDimitry Andric break;
43240b57cec5SDimitry Andric case tok::kw_register:
43250b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
43260b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
43270b57cec5SDimitry Andric isStorageClass = true;
43280b57cec5SDimitry Andric break;
43290b57cec5SDimitry Andric case tok::kw_mutable:
43300b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
43310b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
43320b57cec5SDimitry Andric isStorageClass = true;
43330b57cec5SDimitry Andric break;
43340b57cec5SDimitry Andric case tok::kw___thread:
43350b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
43360b57cec5SDimitry Andric PrevSpec, DiagID);
43370b57cec5SDimitry Andric isStorageClass = true;
43380b57cec5SDimitry Andric break;
43390b57cec5SDimitry Andric case tok::kw_thread_local:
43405f757f3fSDimitry Andric if (getLangOpts().C23)
43415f757f3fSDimitry Andric Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
4342b121cb00SDimitry Andric // We map thread_local to _Thread_local in C23 mode so it retains the C
4343b121cb00SDimitry Andric // semantics rather than getting the C++ semantics.
4344b121cb00SDimitry Andric // FIXME: diagnostics will show _Thread_local when the user wrote
4345b121cb00SDimitry Andric // thread_local in source in C23 mode; we need some general way to
4346b121cb00SDimitry Andric // identify which way the user spelled the keyword in source.
4347b121cb00SDimitry Andric isInvalid = DS.SetStorageClassSpecThread(
43485f757f3fSDimitry Andric getLangOpts().C23 ? DeclSpec::TSCS__Thread_local
4349b121cb00SDimitry Andric : DeclSpec::TSCS_thread_local,
4350b121cb00SDimitry Andric Loc, PrevSpec, DiagID);
43510b57cec5SDimitry Andric isStorageClass = true;
43520b57cec5SDimitry Andric break;
43530b57cec5SDimitry Andric case tok::kw__Thread_local:
4354*0fca6ea1SDimitry Andric diagnoseUseOfC11Keyword(Tok);
43550b57cec5SDimitry Andric isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
43560b57cec5SDimitry Andric Loc, PrevSpec, DiagID);
43570b57cec5SDimitry Andric isStorageClass = true;
43580b57cec5SDimitry Andric break;
43590b57cec5SDimitry Andric
43600b57cec5SDimitry Andric // function-specifier
43610b57cec5SDimitry Andric case tok::kw_inline:
43620b57cec5SDimitry Andric isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);
43630b57cec5SDimitry Andric break;
43640b57cec5SDimitry Andric case tok::kw_virtual:
43650b57cec5SDimitry Andric // C++ for OpenCL does not allow virtual function qualifier, to avoid
43660b57cec5SDimitry Andric // function pointers restricted in OpenCL v2.0 s6.9.a.
4367e8d8bef9SDimitry Andric if (getLangOpts().OpenCLCPlusPlus &&
4368fe6060f1SDimitry Andric !getActions().getOpenCLOptions().isAvailableOption(
4369fe6060f1SDimitry Andric "__cl_clang_function_pointers", getLangOpts())) {
43700b57cec5SDimitry Andric DiagID = diag::err_openclcxx_virtual_function;
43710b57cec5SDimitry Andric PrevSpec = Tok.getIdentifierInfo()->getNameStart();
43720b57cec5SDimitry Andric isInvalid = true;
4373e8d8bef9SDimitry Andric } else {
43740b57cec5SDimitry Andric isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
43750b57cec5SDimitry Andric }
43760b57cec5SDimitry Andric break;
43770b57cec5SDimitry Andric case tok::kw_explicit: {
43780b57cec5SDimitry Andric SourceLocation ExplicitLoc = Loc;
43790b57cec5SDimitry Andric SourceLocation CloseParenLoc;
43800b57cec5SDimitry Andric ExplicitSpecifier ExplicitSpec(nullptr, ExplicitSpecKind::ResolvedTrue);
43810b57cec5SDimitry Andric ConsumedEnd = ExplicitLoc;
43820b57cec5SDimitry Andric ConsumeToken(); // kw_explicit
43830b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) {
43845ffd83dbSDimitry Andric if (getLangOpts().CPlusPlus20 || isExplicitBool() == TPResult::True) {
43855ffd83dbSDimitry Andric Diag(Tok.getLocation(), getLangOpts().CPlusPlus20
438655e4f9d5SDimitry Andric ? diag::warn_cxx17_compat_explicit_bool
438755e4f9d5SDimitry Andric : diag::ext_explicit_bool);
438855e4f9d5SDimitry Andric
43890b57cec5SDimitry Andric ExprResult ExplicitExpr(static_cast<Expr *>(nullptr));
43900b57cec5SDimitry Andric BalancedDelimiterTracker Tracker(*this, tok::l_paren);
43910b57cec5SDimitry Andric Tracker.consumeOpen();
43925f757f3fSDimitry Andric
43935f757f3fSDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated(
43945f757f3fSDimitry Andric Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
43955f757f3fSDimitry Andric
43965f757f3fSDimitry Andric ExplicitExpr = ParseConstantExpressionInExprEvalContext();
43970b57cec5SDimitry Andric ConsumedEnd = Tok.getLocation();
43980b57cec5SDimitry Andric if (ExplicitExpr.isUsable()) {
43990b57cec5SDimitry Andric CloseParenLoc = Tok.getLocation();
44000b57cec5SDimitry Andric Tracker.consumeClose();
44010b57cec5SDimitry Andric ExplicitSpec =
44020b57cec5SDimitry Andric Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get());
44030b57cec5SDimitry Andric } else
44040b57cec5SDimitry Andric Tracker.skipToEnd();
440555e4f9d5SDimitry Andric } else {
44065ffd83dbSDimitry Andric Diag(Tok.getLocation(), diag::warn_cxx20_compat_explicit_bool);
44070b57cec5SDimitry Andric }
440855e4f9d5SDimitry Andric }
44090b57cec5SDimitry Andric isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID,
44100b57cec5SDimitry Andric ExplicitSpec, CloseParenLoc);
44110b57cec5SDimitry Andric break;
44120b57cec5SDimitry Andric }
44130b57cec5SDimitry Andric case tok::kw__Noreturn:
4414*0fca6ea1SDimitry Andric diagnoseUseOfC11Keyword(Tok);
44150b57cec5SDimitry Andric isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
44160b57cec5SDimitry Andric break;
44170b57cec5SDimitry Andric
44180b57cec5SDimitry Andric // friend
44190b57cec5SDimitry Andric case tok::kw_friend:
4420*0fca6ea1SDimitry Andric if (DSContext == DeclSpecContext::DSC_class) {
44210b57cec5SDimitry Andric isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
4422*0fca6ea1SDimitry Andric Scope *CurS = getCurScope();
4423*0fca6ea1SDimitry Andric if (!isInvalid && CurS)
4424*0fca6ea1SDimitry Andric CurS->setFlags(CurS->getFlags() | Scope::FriendScope);
4425*0fca6ea1SDimitry Andric } else {
44260b57cec5SDimitry Andric PrevSpec = ""; // not actually used by the diagnostic
44270b57cec5SDimitry Andric DiagID = diag::err_friend_invalid_in_context;
44280b57cec5SDimitry Andric isInvalid = true;
44290b57cec5SDimitry Andric }
44300b57cec5SDimitry Andric break;
44310b57cec5SDimitry Andric
44320b57cec5SDimitry Andric // Modules
44330b57cec5SDimitry Andric case tok::kw___module_private__:
44340b57cec5SDimitry Andric isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);
44350b57cec5SDimitry Andric break;
44360b57cec5SDimitry Andric
4437a7dea167SDimitry Andric // constexpr, consteval, constinit specifiers
44380b57cec5SDimitry Andric case tok::kw_constexpr:
4439*0fca6ea1SDimitry Andric if (getLangOpts().C23)
4440*0fca6ea1SDimitry Andric Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
4441e8d8bef9SDimitry Andric isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
4442e8d8bef9SDimitry Andric PrevSpec, DiagID);
44430b57cec5SDimitry Andric break;
44440b57cec5SDimitry Andric case tok::kw_consteval:
4445e8d8bef9SDimitry Andric isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Consteval, Loc,
4446e8d8bef9SDimitry Andric PrevSpec, DiagID);
44470b57cec5SDimitry Andric break;
4448a7dea167SDimitry Andric case tok::kw_constinit:
4449e8d8bef9SDimitry Andric isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constinit, Loc,
4450e8d8bef9SDimitry Andric PrevSpec, DiagID);
4451a7dea167SDimitry Andric break;
44520b57cec5SDimitry Andric
44530b57cec5SDimitry Andric // type-specifier
44540b57cec5SDimitry Andric case tok::kw_short:
4455e8d8bef9SDimitry Andric isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Short, Loc, PrevSpec,
44560b57cec5SDimitry Andric DiagID, Policy);
44570b57cec5SDimitry Andric break;
44580b57cec5SDimitry Andric case tok::kw_long:
4459e8d8bef9SDimitry Andric if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Long)
4460e8d8bef9SDimitry Andric isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Long, Loc, PrevSpec,
44610b57cec5SDimitry Andric DiagID, Policy);
44620b57cec5SDimitry Andric else
4463e8d8bef9SDimitry Andric isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,
4464e8d8bef9SDimitry Andric PrevSpec, DiagID, Policy);
44650b57cec5SDimitry Andric break;
44660b57cec5SDimitry Andric case tok::kw___int64:
4467e8d8bef9SDimitry Andric isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,
4468e8d8bef9SDimitry Andric PrevSpec, DiagID, Policy);
44690b57cec5SDimitry Andric break;
44700b57cec5SDimitry Andric case tok::kw_signed:
4471e8d8bef9SDimitry Andric isInvalid =
4472e8d8bef9SDimitry Andric DS.SetTypeSpecSign(TypeSpecifierSign::Signed, Loc, PrevSpec, DiagID);
44730b57cec5SDimitry Andric break;
44740b57cec5SDimitry Andric case tok::kw_unsigned:
4475e8d8bef9SDimitry Andric isInvalid = DS.SetTypeSpecSign(TypeSpecifierSign::Unsigned, Loc, PrevSpec,
44760b57cec5SDimitry Andric DiagID);
44770b57cec5SDimitry Andric break;
44780b57cec5SDimitry Andric case tok::kw__Complex:
4479a7dea167SDimitry Andric if (!getLangOpts().C99)
4480a7dea167SDimitry Andric Diag(Tok, diag::ext_c99_feature) << Tok.getName();
44810b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
44820b57cec5SDimitry Andric DiagID);
44830b57cec5SDimitry Andric break;
44840b57cec5SDimitry Andric case tok::kw__Imaginary:
4485a7dea167SDimitry Andric if (!getLangOpts().C99)
4486a7dea167SDimitry Andric Diag(Tok, diag::ext_c99_feature) << Tok.getName();
44870b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
44880b57cec5SDimitry Andric DiagID);
44890b57cec5SDimitry Andric break;
44900b57cec5SDimitry Andric case tok::kw_void:
44910b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
44920b57cec5SDimitry Andric DiagID, Policy);
44930b57cec5SDimitry Andric break;
44940b57cec5SDimitry Andric case tok::kw_char:
44950b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
44960b57cec5SDimitry Andric DiagID, Policy);
44970b57cec5SDimitry Andric break;
44980b57cec5SDimitry Andric case tok::kw_int:
44990b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
45000b57cec5SDimitry Andric DiagID, Policy);
45010b57cec5SDimitry Andric break;
45020eae32dcSDimitry Andric case tok::kw__ExtInt:
45030eae32dcSDimitry Andric case tok::kw__BitInt: {
45040eae32dcSDimitry Andric DiagnoseBitIntUse(Tok);
45055ffd83dbSDimitry Andric ExprResult ER = ParseExtIntegerArgument();
45065ffd83dbSDimitry Andric if (ER.isInvalid())
45075ffd83dbSDimitry Andric continue;
45080eae32dcSDimitry Andric isInvalid = DS.SetBitIntType(Loc, ER.get(), PrevSpec, DiagID, Policy);
45095ffd83dbSDimitry Andric ConsumedEnd = PrevTokLocation;
45105ffd83dbSDimitry Andric break;
45115ffd83dbSDimitry Andric }
45120b57cec5SDimitry Andric case tok::kw___int128:
45130b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
45140b57cec5SDimitry Andric DiagID, Policy);
45150b57cec5SDimitry Andric break;
45160b57cec5SDimitry Andric case tok::kw_half:
45170b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
45180b57cec5SDimitry Andric DiagID, Policy);
45190b57cec5SDimitry Andric break;
45205ffd83dbSDimitry Andric case tok::kw___bf16:
45215ffd83dbSDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec,
45225ffd83dbSDimitry Andric DiagID, Policy);
45235ffd83dbSDimitry Andric break;
45240b57cec5SDimitry Andric case tok::kw_float:
45250b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
45260b57cec5SDimitry Andric DiagID, Policy);
45270b57cec5SDimitry Andric break;
45280b57cec5SDimitry Andric case tok::kw_double:
45290b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
45300b57cec5SDimitry Andric DiagID, Policy);
45310b57cec5SDimitry Andric break;
45320b57cec5SDimitry Andric case tok::kw__Float16:
45330b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,
45340b57cec5SDimitry Andric DiagID, Policy);
45350b57cec5SDimitry Andric break;
45360b57cec5SDimitry Andric case tok::kw__Accum:
45375f757f3fSDimitry Andric assert(getLangOpts().FixedPoint &&
45385f757f3fSDimitry Andric "This keyword is only used when fixed point types are enabled "
45395f757f3fSDimitry Andric "with `-ffixed-point`");
45405f757f3fSDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, DiagID,
45415f757f3fSDimitry Andric Policy);
45420b57cec5SDimitry Andric break;
45430b57cec5SDimitry Andric case tok::kw__Fract:
45445f757f3fSDimitry Andric assert(getLangOpts().FixedPoint &&
45455f757f3fSDimitry Andric "This keyword is only used when fixed point types are enabled "
45465f757f3fSDimitry Andric "with `-ffixed-point`");
45475f757f3fSDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, DiagID,
45485f757f3fSDimitry Andric Policy);
45490b57cec5SDimitry Andric break;
45500b57cec5SDimitry Andric case tok::kw__Sat:
45515f757f3fSDimitry Andric assert(getLangOpts().FixedPoint &&
45525f757f3fSDimitry Andric "This keyword is only used when fixed point types are enabled "
45535f757f3fSDimitry Andric "with `-ffixed-point`");
45540b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID);
45550b57cec5SDimitry Andric break;
45560b57cec5SDimitry Andric case tok::kw___float128:
45570b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
45580b57cec5SDimitry Andric DiagID, Policy);
45590b57cec5SDimitry Andric break;
4560349cc55cSDimitry Andric case tok::kw___ibm128:
4561349cc55cSDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec,
4562349cc55cSDimitry Andric DiagID, Policy);
4563349cc55cSDimitry Andric break;
45640b57cec5SDimitry Andric case tok::kw_wchar_t:
45650b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
45660b57cec5SDimitry Andric DiagID, Policy);
45670b57cec5SDimitry Andric break;
45680b57cec5SDimitry Andric case tok::kw_char8_t:
45690b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec,
45700b57cec5SDimitry Andric DiagID, Policy);
45710b57cec5SDimitry Andric break;
45720b57cec5SDimitry Andric case tok::kw_char16_t:
45730b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
45740b57cec5SDimitry Andric DiagID, Policy);
45750b57cec5SDimitry Andric break;
45760b57cec5SDimitry Andric case tok::kw_char32_t:
45770b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
45780b57cec5SDimitry Andric DiagID, Policy);
45790b57cec5SDimitry Andric break;
45800b57cec5SDimitry Andric case tok::kw_bool:
45815f757f3fSDimitry Andric if (getLangOpts().C23)
45825f757f3fSDimitry Andric Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
458306c3fb27SDimitry Andric [[fallthrough]];
45840b57cec5SDimitry Andric case tok::kw__Bool:
4585a7dea167SDimitry Andric if (Tok.is(tok::kw__Bool) && !getLangOpts().C99)
4586a7dea167SDimitry Andric Diag(Tok, diag::ext_c99_feature) << Tok.getName();
4587a7dea167SDimitry Andric
45880b57cec5SDimitry Andric if (Tok.is(tok::kw_bool) &&
45890b57cec5SDimitry Andric DS.getTypeSpecType() != DeclSpec::TST_unspecified &&
45900b57cec5SDimitry Andric DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
45910b57cec5SDimitry Andric PrevSpec = ""; // Not used by the diagnostic.
45920b57cec5SDimitry Andric DiagID = diag::err_bool_redeclaration;
45930b57cec5SDimitry Andric // For better error recovery.
45940b57cec5SDimitry Andric Tok.setKind(tok::identifier);
45950b57cec5SDimitry Andric isInvalid = true;
45960b57cec5SDimitry Andric } else {
45970b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
45980b57cec5SDimitry Andric DiagID, Policy);
45990b57cec5SDimitry Andric }
46000b57cec5SDimitry Andric break;
46010b57cec5SDimitry Andric case tok::kw__Decimal32:
46020b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
46030b57cec5SDimitry Andric DiagID, Policy);
46040b57cec5SDimitry Andric break;
46050b57cec5SDimitry Andric case tok::kw__Decimal64:
46060b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
46070b57cec5SDimitry Andric DiagID, Policy);
46080b57cec5SDimitry Andric break;
46090b57cec5SDimitry Andric case tok::kw__Decimal128:
46100b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
46110b57cec5SDimitry Andric DiagID, Policy);
46120b57cec5SDimitry Andric break;
46130b57cec5SDimitry Andric case tok::kw___vector:
46140b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
46150b57cec5SDimitry Andric break;
46160b57cec5SDimitry Andric case tok::kw___pixel:
46170b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
46180b57cec5SDimitry Andric break;
46190b57cec5SDimitry Andric case tok::kw___bool:
46200b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
46210b57cec5SDimitry Andric break;
46220b57cec5SDimitry Andric case tok::kw_pipe:
4623349cc55cSDimitry Andric if (!getLangOpts().OpenCL ||
4624349cc55cSDimitry Andric getLangOpts().getOpenCLCompatibleVersion() < 200) {
4625fe6060f1SDimitry Andric // OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier
4626fe6060f1SDimitry Andric // should support the "pipe" word as identifier.
46270b57cec5SDimitry Andric Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
4628fe6060f1SDimitry Andric Tok.setKind(tok::identifier);
46290b57cec5SDimitry Andric goto DoneWithDeclSpec;
46306e75b2fbSDimitry Andric } else if (!getLangOpts().OpenCLPipes) {
46316e75b2fbSDimitry Andric DiagID = diag::err_opencl_unknown_type_specifier;
46326e75b2fbSDimitry Andric PrevSpec = Tok.getIdentifierInfo()->getNameStart();
46336e75b2fbSDimitry Andric isInvalid = true;
46346e75b2fbSDimitry Andric } else
46350b57cec5SDimitry Andric isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
46360b57cec5SDimitry Andric break;
4637fe6060f1SDimitry Andric // We only need to enumerate each image type once.
4638fe6060f1SDimitry Andric #define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
4639fe6060f1SDimitry Andric #define IMAGE_WRITE_TYPE(Type, Id, Ext)
4640fe6060f1SDimitry Andric #define IMAGE_READ_TYPE(ImgType, Id, Ext) \
46410b57cec5SDimitry Andric case tok::kw_##ImgType##_t: \
4642fe6060f1SDimitry Andric if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \
4643fe6060f1SDimitry Andric goto DoneWithDeclSpec; \
46440b57cec5SDimitry Andric break;
46450b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
46460b57cec5SDimitry Andric case tok::kw___unknown_anytype:
46470b57cec5SDimitry Andric isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
46480b57cec5SDimitry Andric PrevSpec, DiagID, Policy);
46490b57cec5SDimitry Andric break;
46500b57cec5SDimitry Andric
46510b57cec5SDimitry Andric // class-specifier:
46520b57cec5SDimitry Andric case tok::kw_class:
46530b57cec5SDimitry Andric case tok::kw_struct:
46540b57cec5SDimitry Andric case tok::kw___interface:
46550b57cec5SDimitry Andric case tok::kw_union: {
46560b57cec5SDimitry Andric tok::TokenKind Kind = Tok.getKind();
46570b57cec5SDimitry Andric ConsumeToken();
46580b57cec5SDimitry Andric
46590b57cec5SDimitry Andric // These are attributes following class specifiers.
46600b57cec5SDimitry Andric // To produce better diagnostic, we parse them when
46610b57cec5SDimitry Andric // parsing class specifier.
466281ad6265SDimitry Andric ParsedAttributes Attributes(AttrFactory);
46630b57cec5SDimitry Andric ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS,
46640b57cec5SDimitry Andric EnteringContext, DSContext, Attributes);
46650b57cec5SDimitry Andric
46660b57cec5SDimitry Andric // If there are attributes following class specifier,
46670b57cec5SDimitry Andric // take them over and handle them here.
46680b57cec5SDimitry Andric if (!Attributes.empty()) {
46690b57cec5SDimitry Andric AttrsLastTime = true;
46700b57cec5SDimitry Andric attrs.takeAllFrom(Attributes);
46710b57cec5SDimitry Andric }
46720b57cec5SDimitry Andric continue;
46730b57cec5SDimitry Andric }
46740b57cec5SDimitry Andric
46750b57cec5SDimitry Andric // enum-specifier:
46760b57cec5SDimitry Andric case tok::kw_enum:
46770b57cec5SDimitry Andric ConsumeToken();
46780b57cec5SDimitry Andric ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext);
46790b57cec5SDimitry Andric continue;
46800b57cec5SDimitry Andric
46810b57cec5SDimitry Andric // cv-qualifier:
46820b57cec5SDimitry Andric case tok::kw_const:
46830b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
46840b57cec5SDimitry Andric getLangOpts());
46850b57cec5SDimitry Andric break;
46860b57cec5SDimitry Andric case tok::kw_volatile:
46870b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
46880b57cec5SDimitry Andric getLangOpts());
46890b57cec5SDimitry Andric break;
46900b57cec5SDimitry Andric case tok::kw_restrict:
46910b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
46920b57cec5SDimitry Andric getLangOpts());
46930b57cec5SDimitry Andric break;
46940b57cec5SDimitry Andric
46950b57cec5SDimitry Andric // C++ typename-specifier:
46960b57cec5SDimitry Andric case tok::kw_typename:
46970b57cec5SDimitry Andric if (TryAnnotateTypeOrScopeToken()) {
46980b57cec5SDimitry Andric DS.SetTypeSpecError();
46990b57cec5SDimitry Andric goto DoneWithDeclSpec;
47000b57cec5SDimitry Andric }
47010b57cec5SDimitry Andric if (!Tok.is(tok::kw_typename))
47020b57cec5SDimitry Andric continue;
47030b57cec5SDimitry Andric break;
47040b57cec5SDimitry Andric
47055f757f3fSDimitry Andric // C23/GNU typeof support.
47060b57cec5SDimitry Andric case tok::kw_typeof:
4707bdd1243dSDimitry Andric case tok::kw_typeof_unqual:
47080b57cec5SDimitry Andric ParseTypeofSpecifier(DS);
47090b57cec5SDimitry Andric continue;
47100b57cec5SDimitry Andric
47110b57cec5SDimitry Andric case tok::annot_decltype:
47120b57cec5SDimitry Andric ParseDecltypeSpecifier(DS);
47130b57cec5SDimitry Andric continue;
47140b57cec5SDimitry Andric
4715*0fca6ea1SDimitry Andric case tok::annot_pack_indexing_type:
4716*0fca6ea1SDimitry Andric ParsePackIndexingType(DS);
4717*0fca6ea1SDimitry Andric continue;
4718*0fca6ea1SDimitry Andric
47190b57cec5SDimitry Andric case tok::annot_pragma_pack:
47200b57cec5SDimitry Andric HandlePragmaPack();
47210b57cec5SDimitry Andric continue;
47220b57cec5SDimitry Andric
47230b57cec5SDimitry Andric case tok::annot_pragma_ms_pragma:
47240b57cec5SDimitry Andric HandlePragmaMSPragma();
47250b57cec5SDimitry Andric continue;
47260b57cec5SDimitry Andric
47270b57cec5SDimitry Andric case tok::annot_pragma_ms_vtordisp:
47280b57cec5SDimitry Andric HandlePragmaMSVtorDisp();
47290b57cec5SDimitry Andric continue;
47300b57cec5SDimitry Andric
47310b57cec5SDimitry Andric case tok::annot_pragma_ms_pointers_to_members:
47320b57cec5SDimitry Andric HandlePragmaMSPointersToMembers();
47330b57cec5SDimitry Andric continue;
47340b57cec5SDimitry Andric
4735bdd1243dSDimitry Andric #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
4736bdd1243dSDimitry Andric #include "clang/Basic/TransformTypeTraits.def"
4737bdd1243dSDimitry Andric // HACK: libstdc++ already uses '__remove_cv' as an alias template so we
4738bdd1243dSDimitry Andric // work around this by expecting all transform type traits to be suffixed
4739bdd1243dSDimitry Andric // with '('. They're an identifier otherwise.
4740bdd1243dSDimitry Andric if (!MaybeParseTypeTransformTypeSpecifier(DS))
4741bdd1243dSDimitry Andric goto ParseIdentifier;
47420b57cec5SDimitry Andric continue;
47430b57cec5SDimitry Andric
47440b57cec5SDimitry Andric case tok::kw__Atomic:
47450b57cec5SDimitry Andric // C11 6.7.2.4/4:
47460b57cec5SDimitry Andric // If the _Atomic keyword is immediately followed by a left parenthesis,
47470b57cec5SDimitry Andric // it is interpreted as a type specifier (with a type name), not as a
47480b57cec5SDimitry Andric // type qualifier.
4749*0fca6ea1SDimitry Andric diagnoseUseOfC11Keyword(Tok);
47500b57cec5SDimitry Andric if (NextToken().is(tok::l_paren)) {
47510b57cec5SDimitry Andric ParseAtomicSpecifier(DS);
47520b57cec5SDimitry Andric continue;
47530b57cec5SDimitry Andric }
47540b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
47550b57cec5SDimitry Andric getLangOpts());
47560b57cec5SDimitry Andric break;
47570b57cec5SDimitry Andric
47580b57cec5SDimitry Andric // OpenCL address space qualifiers:
47590b57cec5SDimitry Andric case tok::kw___generic:
47600b57cec5SDimitry Andric // generic address space is introduced only in OpenCL v2.0
47610b57cec5SDimitry Andric // see OpenCL C Spec v2.0 s6.5.5
4762fe6060f1SDimitry Andric // OpenCL v3.0 introduces __opencl_c_generic_address_space
4763fe6060f1SDimitry Andric // feature macro to indicate if generic address space is supported
4764fe6060f1SDimitry Andric if (!Actions.getLangOpts().OpenCLGenericAddressSpace) {
47650b57cec5SDimitry Andric DiagID = diag::err_opencl_unknown_type_specifier;
47660b57cec5SDimitry Andric PrevSpec = Tok.getIdentifierInfo()->getNameStart();
47670b57cec5SDimitry Andric isInvalid = true;
47680b57cec5SDimitry Andric break;
4769480093f4SDimitry Andric }
4770bdd1243dSDimitry Andric [[fallthrough]];
47710b57cec5SDimitry Andric case tok::kw_private:
4772480093f4SDimitry Andric // It's fine (but redundant) to check this for __generic on the
4773480093f4SDimitry Andric // fallthrough path; we only form the __generic token in OpenCL mode.
4774480093f4SDimitry Andric if (!getLangOpts().OpenCL)
4775480093f4SDimitry Andric goto DoneWithDeclSpec;
4776bdd1243dSDimitry Andric [[fallthrough]];
47770b57cec5SDimitry Andric case tok::kw___private:
47780b57cec5SDimitry Andric case tok::kw___global:
47790b57cec5SDimitry Andric case tok::kw___local:
47800b57cec5SDimitry Andric case tok::kw___constant:
47810b57cec5SDimitry Andric // OpenCL access qualifiers:
47820b57cec5SDimitry Andric case tok::kw___read_only:
47830b57cec5SDimitry Andric case tok::kw___write_only:
47840b57cec5SDimitry Andric case tok::kw___read_write:
47850b57cec5SDimitry Andric ParseOpenCLQualifiers(DS.getAttributes());
47860b57cec5SDimitry Andric break;
47870b57cec5SDimitry Andric
4788bdd1243dSDimitry Andric case tok::kw_groupshared:
47895f757f3fSDimitry Andric case tok::kw_in:
47905f757f3fSDimitry Andric case tok::kw_inout:
47915f757f3fSDimitry Andric case tok::kw_out:
4792bdd1243dSDimitry Andric // NOTE: ParseHLSLQualifiers will consume the qualifier token.
4793bdd1243dSDimitry Andric ParseHLSLQualifiers(DS.getAttributes());
4794bdd1243dSDimitry Andric continue;
4795bdd1243dSDimitry Andric
47960b57cec5SDimitry Andric case tok::less:
47970b57cec5SDimitry Andric // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
47980b57cec5SDimitry Andric // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
47990b57cec5SDimitry Andric // but we support it.
48000b57cec5SDimitry Andric if (DS.hasTypeSpecifier() || !getLangOpts().ObjC)
48010b57cec5SDimitry Andric goto DoneWithDeclSpec;
48020b57cec5SDimitry Andric
48030b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation();
48040b57cec5SDimitry Andric SourceLocation EndLoc;
48050b57cec5SDimitry Andric TypeResult Type = parseObjCProtocolQualifierType(EndLoc);
48060b57cec5SDimitry Andric if (Type.isUsable()) {
48070b57cec5SDimitry Andric if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, StartLoc,
48080b57cec5SDimitry Andric PrevSpec, DiagID, Type.get(),
48090b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
48100b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
48110b57cec5SDimitry Andric
48120b57cec5SDimitry Andric DS.SetRangeEnd(EndLoc);
48130b57cec5SDimitry Andric } else {
48140b57cec5SDimitry Andric DS.SetTypeSpecError();
48150b57cec5SDimitry Andric }
48160b57cec5SDimitry Andric
48170b57cec5SDimitry Andric // Need to support trailing type qualifiers (e.g. "id<p> const").
48180b57cec5SDimitry Andric // If a type specifier follows, it will be diagnosed elsewhere.
48190b57cec5SDimitry Andric continue;
48200b57cec5SDimitry Andric }
48210b57cec5SDimitry Andric
48220b57cec5SDimitry Andric DS.SetRangeEnd(ConsumedEnd.isValid() ? ConsumedEnd : Tok.getLocation());
48230b57cec5SDimitry Andric
48240b57cec5SDimitry Andric // If the specifier wasn't legal, issue a diagnostic.
48250b57cec5SDimitry Andric if (isInvalid) {
48260b57cec5SDimitry Andric assert(PrevSpec && "Method did not return previous specifier!");
48270b57cec5SDimitry Andric assert(DiagID);
48280b57cec5SDimitry Andric
48290b57cec5SDimitry Andric if (DiagID == diag::ext_duplicate_declspec ||
48300b57cec5SDimitry Andric DiagID == diag::ext_warn_duplicate_declspec ||
48310b57cec5SDimitry Andric DiagID == diag::err_duplicate_declspec)
48320b57cec5SDimitry Andric Diag(Loc, DiagID) << PrevSpec
48330b57cec5SDimitry Andric << FixItHint::CreateRemoval(
48340b57cec5SDimitry Andric SourceRange(Loc, DS.getEndLoc()));
48350b57cec5SDimitry Andric else if (DiagID == diag::err_opencl_unknown_type_specifier) {
4836349cc55cSDimitry Andric Diag(Loc, DiagID) << getLangOpts().getOpenCLVersionString() << PrevSpec
4837349cc55cSDimitry Andric << isStorageClass;
48380b57cec5SDimitry Andric } else
48390b57cec5SDimitry Andric Diag(Loc, DiagID) << PrevSpec;
48400b57cec5SDimitry Andric }
48410b57cec5SDimitry Andric
48420b57cec5SDimitry Andric if (DiagID != diag::err_bool_redeclaration && ConsumedEnd.isInvalid())
48430b57cec5SDimitry Andric // After an error the next token can be an annotation token.
48440b57cec5SDimitry Andric ConsumeAnyToken();
48450b57cec5SDimitry Andric
48460b57cec5SDimitry Andric AttrsLastTime = false;
48470b57cec5SDimitry Andric }
48480b57cec5SDimitry Andric }
48490b57cec5SDimitry Andric
DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec & DS,Parser & P)4850*0fca6ea1SDimitry Andric static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS,
4851*0fca6ea1SDimitry Andric Parser &P) {
4852*0fca6ea1SDimitry Andric
4853*0fca6ea1SDimitry Andric if (DS.getTypeSpecType() != DeclSpec::TST_struct)
4854*0fca6ea1SDimitry Andric return;
4855*0fca6ea1SDimitry Andric
4856*0fca6ea1SDimitry Andric auto *RD = dyn_cast<RecordDecl>(DS.getRepAsDecl());
4857*0fca6ea1SDimitry Andric // We're only interested in unnamed, non-anonymous struct
4858*0fca6ea1SDimitry Andric if (!RD || !RD->getName().empty() || RD->isAnonymousStructOrUnion())
4859*0fca6ea1SDimitry Andric return;
4860*0fca6ea1SDimitry Andric
4861*0fca6ea1SDimitry Andric for (auto *I : RD->decls()) {
4862*0fca6ea1SDimitry Andric auto *VD = dyn_cast<ValueDecl>(I);
4863*0fca6ea1SDimitry Andric if (!VD)
4864*0fca6ea1SDimitry Andric continue;
4865*0fca6ea1SDimitry Andric
4866*0fca6ea1SDimitry Andric auto *CAT = VD->getType()->getAs<CountAttributedType>();
4867*0fca6ea1SDimitry Andric if (!CAT)
4868*0fca6ea1SDimitry Andric continue;
4869*0fca6ea1SDimitry Andric
4870*0fca6ea1SDimitry Andric for (const auto &DD : CAT->dependent_decls()) {
4871*0fca6ea1SDimitry Andric if (!RD->containsDecl(DD.getDecl())) {
4872*0fca6ea1SDimitry Andric P.Diag(VD->getBeginLoc(), diag::err_count_attr_param_not_in_same_struct)
4873*0fca6ea1SDimitry Andric << DD.getDecl() << CAT->getKind() << CAT->isArrayType();
4874*0fca6ea1SDimitry Andric P.Diag(DD.getDecl()->getBeginLoc(),
4875*0fca6ea1SDimitry Andric diag::note_flexible_array_counted_by_attr_field)
4876*0fca6ea1SDimitry Andric << DD.getDecl();
4877*0fca6ea1SDimitry Andric }
4878*0fca6ea1SDimitry Andric }
4879*0fca6ea1SDimitry Andric }
4880*0fca6ea1SDimitry Andric }
4881*0fca6ea1SDimitry Andric
48820b57cec5SDimitry Andric /// ParseStructDeclaration - Parse a struct declaration without the terminating
48830b57cec5SDimitry Andric /// semicolon.
48840b57cec5SDimitry Andric ///
48850b57cec5SDimitry Andric /// Note that a struct declaration refers to a declaration in a struct,
48860b57cec5SDimitry Andric /// not to the declaration of a struct.
48870b57cec5SDimitry Andric ///
48880b57cec5SDimitry Andric /// struct-declaration:
48895f757f3fSDimitry Andric /// [C23] attributes-specifier-seq[opt]
48900b57cec5SDimitry Andric /// specifier-qualifier-list struct-declarator-list
48910b57cec5SDimitry Andric /// [GNU] __extension__ struct-declaration
48920b57cec5SDimitry Andric /// [GNU] specifier-qualifier-list
48930b57cec5SDimitry Andric /// struct-declarator-list:
48940b57cec5SDimitry Andric /// struct-declarator
48950b57cec5SDimitry Andric /// struct-declarator-list ',' struct-declarator
48960b57cec5SDimitry Andric /// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator
48970b57cec5SDimitry Andric /// struct-declarator:
48980b57cec5SDimitry Andric /// declarator
48990b57cec5SDimitry Andric /// [GNU] declarator attributes[opt]
49000b57cec5SDimitry Andric /// declarator[opt] ':' constant-expression
49010b57cec5SDimitry Andric /// [GNU] declarator[opt] ':' constant-expression attributes[opt]
49020b57cec5SDimitry Andric ///
ParseStructDeclaration(ParsingDeclSpec & DS,llvm::function_ref<Decl * (ParsingFieldDeclarator &)> FieldsCallback,LateParsedAttrList * LateFieldAttrs)49030b57cec5SDimitry Andric void Parser::ParseStructDeclaration(
49040b57cec5SDimitry Andric ParsingDeclSpec &DS,
4905*0fca6ea1SDimitry Andric llvm::function_ref<Decl *(ParsingFieldDeclarator &)> FieldsCallback,
4906*0fca6ea1SDimitry Andric LateParsedAttrList *LateFieldAttrs) {
49070b57cec5SDimitry Andric
49080b57cec5SDimitry Andric if (Tok.is(tok::kw___extension__)) {
49090b57cec5SDimitry Andric // __extension__ silences extension warnings in the subexpression.
49100b57cec5SDimitry Andric ExtensionRAIIObject O(Diags); // Use RAII to do this.
49110b57cec5SDimitry Andric ConsumeToken();
4912*0fca6ea1SDimitry Andric return ParseStructDeclaration(DS, FieldsCallback, LateFieldAttrs);
49130b57cec5SDimitry Andric }
49140b57cec5SDimitry Andric
49150b57cec5SDimitry Andric // Parse leading attributes.
491681ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory);
49170b57cec5SDimitry Andric MaybeParseCXX11Attributes(Attrs);
49180b57cec5SDimitry Andric
49190b57cec5SDimitry Andric // Parse the common specifier-qualifiers-list piece.
49200b57cec5SDimitry Andric ParseSpecifierQualifierList(DS);
49210b57cec5SDimitry Andric
49220b57cec5SDimitry Andric // If there are no declarators, this is a free-standing declaration
49230b57cec5SDimitry Andric // specifier. Let the actions module cope with it.
49240b57cec5SDimitry Andric if (Tok.is(tok::semi)) {
49255f757f3fSDimitry Andric // C23 6.7.2.1p9 : "The optional attribute specifier sequence in a
492681ad6265SDimitry Andric // member declaration appertains to each of the members declared by the
492781ad6265SDimitry Andric // member declarator list; it shall not appear if the optional member
492881ad6265SDimitry Andric // declarator list is omitted."
492981ad6265SDimitry Andric ProhibitAttributes(Attrs);
49300b57cec5SDimitry Andric RecordDecl *AnonRecord = nullptr;
493181ad6265SDimitry Andric Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
493281ad6265SDimitry Andric getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);
49330b57cec5SDimitry Andric assert(!AnonRecord && "Did not expect anonymous struct or union here");
49340b57cec5SDimitry Andric DS.complete(TheDecl);
49350b57cec5SDimitry Andric return;
49360b57cec5SDimitry Andric }
49370b57cec5SDimitry Andric
49380b57cec5SDimitry Andric // Read struct-declarators until we find the semicolon.
49390b57cec5SDimitry Andric bool FirstDeclarator = true;
49400b57cec5SDimitry Andric SourceLocation CommaLoc;
494104eeddc0SDimitry Andric while (true) {
494281ad6265SDimitry Andric ParsingFieldDeclarator DeclaratorInfo(*this, DS, Attrs);
49430b57cec5SDimitry Andric DeclaratorInfo.D.setCommaLoc(CommaLoc);
49440b57cec5SDimitry Andric
49450b57cec5SDimitry Andric // Attributes are only allowed here on successive declarators.
4946e8d8bef9SDimitry Andric if (!FirstDeclarator) {
4947e8d8bef9SDimitry Andric // However, this does not apply for [[]] attributes (which could show up
4948e8d8bef9SDimitry Andric // before or after the __attribute__ attributes).
4949e8d8bef9SDimitry Andric DiagnoseAndSkipCXX11Attributes();
49500b57cec5SDimitry Andric MaybeParseGNUAttributes(DeclaratorInfo.D);
4951e8d8bef9SDimitry Andric DiagnoseAndSkipCXX11Attributes();
4952e8d8bef9SDimitry Andric }
49530b57cec5SDimitry Andric
49540b57cec5SDimitry Andric /// struct-declarator: declarator
49550b57cec5SDimitry Andric /// struct-declarator: declarator[opt] ':' constant-expression
49560b57cec5SDimitry Andric if (Tok.isNot(tok::colon)) {
49570b57cec5SDimitry Andric // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
49580b57cec5SDimitry Andric ColonProtectionRAIIObject X(*this);
49590b57cec5SDimitry Andric ParseDeclarator(DeclaratorInfo.D);
49600b57cec5SDimitry Andric } else
49610b57cec5SDimitry Andric DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation());
49620b57cec5SDimitry Andric
4963*0fca6ea1SDimitry Andric // Here, we now know that the unnamed struct is not an anonymous struct.
4964*0fca6ea1SDimitry Andric // Report an error if a counted_by attribute refers to a field in a
4965*0fca6ea1SDimitry Andric // different named struct.
4966*0fca6ea1SDimitry Andric DiagnoseCountAttributedTypeInUnnamedAnon(DS, *this);
4967*0fca6ea1SDimitry Andric
49680b57cec5SDimitry Andric if (TryConsumeToken(tok::colon)) {
49690b57cec5SDimitry Andric ExprResult Res(ParseConstantExpression());
49700b57cec5SDimitry Andric if (Res.isInvalid())
49710b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch);
49720b57cec5SDimitry Andric else
49730b57cec5SDimitry Andric DeclaratorInfo.BitfieldSize = Res.get();
49740b57cec5SDimitry Andric }
49750b57cec5SDimitry Andric
49760b57cec5SDimitry Andric // If attributes exist after the declarator, parse them.
4977*0fca6ea1SDimitry Andric MaybeParseGNUAttributes(DeclaratorInfo.D, LateFieldAttrs);
49780b57cec5SDimitry Andric
49790b57cec5SDimitry Andric // We're done with this declarator; invoke the callback.
4980*0fca6ea1SDimitry Andric Decl *Field = FieldsCallback(DeclaratorInfo);
4981*0fca6ea1SDimitry Andric if (Field)
4982*0fca6ea1SDimitry Andric DistributeCLateParsedAttrs(Field, LateFieldAttrs);
49830b57cec5SDimitry Andric
49840b57cec5SDimitry Andric // If we don't have a comma, it is either the end of the list (a ';')
49850b57cec5SDimitry Andric // or an error, bail out.
49860b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma, CommaLoc))
49870b57cec5SDimitry Andric return;
49880b57cec5SDimitry Andric
49890b57cec5SDimitry Andric FirstDeclarator = false;
49900b57cec5SDimitry Andric }
49910b57cec5SDimitry Andric }
49920b57cec5SDimitry Andric
4993*0fca6ea1SDimitry Andric // TODO: All callers of this function should be moved to
4994*0fca6ea1SDimitry Andric // `Parser::ParseLexedAttributeList`.
ParseLexedCAttributeList(LateParsedAttrList & LAs,bool EnterScope,ParsedAttributes * OutAttrs)4995*0fca6ea1SDimitry Andric void Parser::ParseLexedCAttributeList(LateParsedAttrList &LAs, bool EnterScope,
4996*0fca6ea1SDimitry Andric ParsedAttributes *OutAttrs) {
4997*0fca6ea1SDimitry Andric assert(LAs.parseSoon() &&
4998*0fca6ea1SDimitry Andric "Attribute list should be marked for immediate parsing.");
4999*0fca6ea1SDimitry Andric for (auto *LA : LAs) {
5000*0fca6ea1SDimitry Andric ParseLexedCAttribute(*LA, EnterScope, OutAttrs);
5001*0fca6ea1SDimitry Andric delete LA;
5002*0fca6ea1SDimitry Andric }
5003*0fca6ea1SDimitry Andric LAs.clear();
5004*0fca6ea1SDimitry Andric }
5005*0fca6ea1SDimitry Andric
5006*0fca6ea1SDimitry Andric /// Finish parsing an attribute for which parsing was delayed.
5007*0fca6ea1SDimitry Andric /// This will be called at the end of parsing a class declaration
5008*0fca6ea1SDimitry Andric /// for each LateParsedAttribute. We consume the saved tokens and
5009*0fca6ea1SDimitry Andric /// create an attribute with the arguments filled in. We add this
5010*0fca6ea1SDimitry Andric /// to the Attribute list for the decl.
ParseLexedCAttribute(LateParsedAttribute & LA,bool EnterScope,ParsedAttributes * OutAttrs)5011*0fca6ea1SDimitry Andric void Parser::ParseLexedCAttribute(LateParsedAttribute &LA, bool EnterScope,
5012*0fca6ea1SDimitry Andric ParsedAttributes *OutAttrs) {
5013*0fca6ea1SDimitry Andric // Create a fake EOF so that attribute parsing won't go off the end of the
5014*0fca6ea1SDimitry Andric // attribute.
5015*0fca6ea1SDimitry Andric Token AttrEnd;
5016*0fca6ea1SDimitry Andric AttrEnd.startToken();
5017*0fca6ea1SDimitry Andric AttrEnd.setKind(tok::eof);
5018*0fca6ea1SDimitry Andric AttrEnd.setLocation(Tok.getLocation());
5019*0fca6ea1SDimitry Andric AttrEnd.setEofData(LA.Toks.data());
5020*0fca6ea1SDimitry Andric LA.Toks.push_back(AttrEnd);
5021*0fca6ea1SDimitry Andric
5022*0fca6ea1SDimitry Andric // Append the current token at the end of the new token stream so that it
5023*0fca6ea1SDimitry Andric // doesn't get lost.
5024*0fca6ea1SDimitry Andric LA.Toks.push_back(Tok);
5025*0fca6ea1SDimitry Andric PP.EnterTokenStream(LA.Toks, /*DisableMacroExpansion=*/true,
5026*0fca6ea1SDimitry Andric /*IsReinject=*/true);
5027*0fca6ea1SDimitry Andric // Drop the current token and bring the first cached one. It's the same token
5028*0fca6ea1SDimitry Andric // as when we entered this function.
5029*0fca6ea1SDimitry Andric ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
5030*0fca6ea1SDimitry Andric
5031*0fca6ea1SDimitry Andric // TODO: Use `EnterScope`
5032*0fca6ea1SDimitry Andric (void)EnterScope;
5033*0fca6ea1SDimitry Andric
5034*0fca6ea1SDimitry Andric ParsedAttributes Attrs(AttrFactory);
5035*0fca6ea1SDimitry Andric
5036*0fca6ea1SDimitry Andric assert(LA.Decls.size() <= 1 &&
5037*0fca6ea1SDimitry Andric "late field attribute expects to have at most one declaration.");
5038*0fca6ea1SDimitry Andric
5039*0fca6ea1SDimitry Andric // Dispatch based on the attribute and parse it
5040*0fca6ea1SDimitry Andric ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr, nullptr,
5041*0fca6ea1SDimitry Andric SourceLocation(), ParsedAttr::Form::GNU(), nullptr);
5042*0fca6ea1SDimitry Andric
5043*0fca6ea1SDimitry Andric for (auto *D : LA.Decls)
5044*0fca6ea1SDimitry Andric Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs);
5045*0fca6ea1SDimitry Andric
5046*0fca6ea1SDimitry Andric // Due to a parsing error, we either went over the cached tokens or
5047*0fca6ea1SDimitry Andric // there are still cached tokens left, so we skip the leftover tokens.
5048*0fca6ea1SDimitry Andric while (Tok.isNot(tok::eof))
5049*0fca6ea1SDimitry Andric ConsumeAnyToken();
5050*0fca6ea1SDimitry Andric
5051*0fca6ea1SDimitry Andric // Consume the fake EOF token if it's there
5052*0fca6ea1SDimitry Andric if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())
5053*0fca6ea1SDimitry Andric ConsumeAnyToken();
5054*0fca6ea1SDimitry Andric
5055*0fca6ea1SDimitry Andric if (OutAttrs) {
5056*0fca6ea1SDimitry Andric OutAttrs->takeAllFrom(Attrs);
5057*0fca6ea1SDimitry Andric }
5058*0fca6ea1SDimitry Andric }
5059*0fca6ea1SDimitry Andric
50600b57cec5SDimitry Andric /// ParseStructUnionBody
50610b57cec5SDimitry Andric /// struct-contents:
50620b57cec5SDimitry Andric /// struct-declaration-list
50630b57cec5SDimitry Andric /// [EXT] empty
5064e8d8bef9SDimitry Andric /// [GNU] "struct-declaration-list" without terminating ';'
50650b57cec5SDimitry Andric /// struct-declaration-list:
50660b57cec5SDimitry Andric /// struct-declaration
50670b57cec5SDimitry Andric /// struct-declaration-list struct-declaration
50680b57cec5SDimitry Andric /// [OBC] '@' 'defs' '(' class-name ')'
50690b57cec5SDimitry Andric ///
ParseStructUnionBody(SourceLocation RecordLoc,DeclSpec::TST TagType,RecordDecl * TagDecl)50700b57cec5SDimitry Andric void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
50715ffd83dbSDimitry Andric DeclSpec::TST TagType, RecordDecl *TagDecl) {
50720b57cec5SDimitry Andric PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
50730b57cec5SDimitry Andric "parsing struct/union body");
50740b57cec5SDimitry Andric assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
50750b57cec5SDimitry Andric
50760b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace);
50770b57cec5SDimitry Andric if (T.consumeOpen())
50780b57cec5SDimitry Andric return;
50790b57cec5SDimitry Andric
50800b57cec5SDimitry Andric ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
50810b57cec5SDimitry Andric Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
50820b57cec5SDimitry Andric
5083*0fca6ea1SDimitry Andric // `LateAttrParseExperimentalExtOnly=true` requests that only attributes
5084*0fca6ea1SDimitry Andric // marked with `LateAttrParseExperimentalExt` are late parsed.
5085*0fca6ea1SDimitry Andric LateParsedAttrList LateFieldAttrs(/*PSoon=*/true,
5086*0fca6ea1SDimitry Andric /*LateAttrParseExperimentalExtOnly=*/true);
5087*0fca6ea1SDimitry Andric
50880b57cec5SDimitry Andric // While we still have something to read, read the declarations in the struct.
50890b57cec5SDimitry Andric while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
50900b57cec5SDimitry Andric Tok.isNot(tok::eof)) {
50910b57cec5SDimitry Andric // Each iteration of this loop reads one struct-declaration.
50920b57cec5SDimitry Andric
50930b57cec5SDimitry Andric // Check for extraneous top-level semicolon.
50940b57cec5SDimitry Andric if (Tok.is(tok::semi)) {
50950b57cec5SDimitry Andric ConsumeExtraSemi(InsideStruct, TagType);
50960b57cec5SDimitry Andric continue;
50970b57cec5SDimitry Andric }
50980b57cec5SDimitry Andric
50990b57cec5SDimitry Andric // Parse _Static_assert declaration.
5100d409305fSDimitry Andric if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) {
51010b57cec5SDimitry Andric SourceLocation DeclEnd;
51020b57cec5SDimitry Andric ParseStaticAssertDeclaration(DeclEnd);
51030b57cec5SDimitry Andric continue;
51040b57cec5SDimitry Andric }
51050b57cec5SDimitry Andric
51060b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_pack)) {
51070b57cec5SDimitry Andric HandlePragmaPack();
51080b57cec5SDimitry Andric continue;
51090b57cec5SDimitry Andric }
51100b57cec5SDimitry Andric
51110b57cec5SDimitry Andric if (Tok.is(tok::annot_pragma_align)) {
51120b57cec5SDimitry Andric HandlePragmaAlign();
51130b57cec5SDimitry Andric continue;
51140b57cec5SDimitry Andric }
51150b57cec5SDimitry Andric
5116fe6060f1SDimitry Andric if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
51170b57cec5SDimitry Andric // Result can be ignored, because it must be always empty.
51180b57cec5SDimitry Andric AccessSpecifier AS = AS_none;
511981ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory);
51200b57cec5SDimitry Andric (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
51210b57cec5SDimitry Andric continue;
51220b57cec5SDimitry Andric }
51230b57cec5SDimitry Andric
51245f757f3fSDimitry Andric if (Tok.is(tok::annot_pragma_openacc)) {
51255f757f3fSDimitry Andric ParseOpenACCDirectiveDecl();
51265f757f3fSDimitry Andric continue;
51275f757f3fSDimitry Andric }
51285f757f3fSDimitry Andric
5129a7dea167SDimitry Andric if (tok::isPragmaAnnotation(Tok.getKind())) {
5130a7dea167SDimitry Andric Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)
5131a7dea167SDimitry Andric << DeclSpec::getSpecifierName(
5132a7dea167SDimitry Andric TagType, Actions.getASTContext().getPrintingPolicy());
5133a7dea167SDimitry Andric ConsumeAnnotationToken();
5134a7dea167SDimitry Andric continue;
5135a7dea167SDimitry Andric }
5136a7dea167SDimitry Andric
51370b57cec5SDimitry Andric if (!Tok.is(tok::at)) {
5138*0fca6ea1SDimitry Andric auto CFieldCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
51390b57cec5SDimitry Andric // Install the declarator into the current TagDecl.
51400b57cec5SDimitry Andric Decl *Field =
51410b57cec5SDimitry Andric Actions.ActOnField(getCurScope(), TagDecl,
51420b57cec5SDimitry Andric FD.D.getDeclSpec().getSourceRange().getBegin(),
51430b57cec5SDimitry Andric FD.D, FD.BitfieldSize);
51440b57cec5SDimitry Andric FD.complete(Field);
5145*0fca6ea1SDimitry Andric return Field;
51460b57cec5SDimitry Andric };
51470b57cec5SDimitry Andric
51480b57cec5SDimitry Andric // Parse all the comma separated declarators.
51490b57cec5SDimitry Andric ParsingDeclSpec DS(*this);
5150*0fca6ea1SDimitry Andric ParseStructDeclaration(DS, CFieldCallback, &LateFieldAttrs);
51510b57cec5SDimitry Andric } else { // Handle @defs
51520b57cec5SDimitry Andric ConsumeToken();
51530b57cec5SDimitry Andric if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
51540b57cec5SDimitry Andric Diag(Tok, diag::err_unexpected_at);
51550b57cec5SDimitry Andric SkipUntil(tok::semi);
51560b57cec5SDimitry Andric continue;
51570b57cec5SDimitry Andric }
51580b57cec5SDimitry Andric ConsumeToken();
51590b57cec5SDimitry Andric ExpectAndConsume(tok::l_paren);
51600b57cec5SDimitry Andric if (!Tok.is(tok::identifier)) {
51610b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier;
51620b57cec5SDimitry Andric SkipUntil(tok::semi);
51630b57cec5SDimitry Andric continue;
51640b57cec5SDimitry Andric }
51650b57cec5SDimitry Andric SmallVector<Decl *, 16> Fields;
5166*0fca6ea1SDimitry Andric Actions.ObjC().ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),
51670b57cec5SDimitry Andric Tok.getIdentifierInfo(), Fields);
51680b57cec5SDimitry Andric ConsumeToken();
51690b57cec5SDimitry Andric ExpectAndConsume(tok::r_paren);
51700b57cec5SDimitry Andric }
51710b57cec5SDimitry Andric
51720b57cec5SDimitry Andric if (TryConsumeToken(tok::semi))
51730b57cec5SDimitry Andric continue;
51740b57cec5SDimitry Andric
51750b57cec5SDimitry Andric if (Tok.is(tok::r_brace)) {
51760b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
51770b57cec5SDimitry Andric break;
51780b57cec5SDimitry Andric }
51790b57cec5SDimitry Andric
51800b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
51810b57cec5SDimitry Andric // Skip to end of block or statement to avoid ext-warning on extra ';'.
51820b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
51830b57cec5SDimitry Andric // If we stopped at a ';', eat it.
51840b57cec5SDimitry Andric TryConsumeToken(tok::semi);
51850b57cec5SDimitry Andric }
51860b57cec5SDimitry Andric
51870b57cec5SDimitry Andric T.consumeClose();
51880b57cec5SDimitry Andric
51890b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory);
51900b57cec5SDimitry Andric // If attributes exist after struct contents, parse them.
5191*0fca6ea1SDimitry Andric MaybeParseGNUAttributes(attrs, &LateFieldAttrs);
5192*0fca6ea1SDimitry Andric
5193*0fca6ea1SDimitry Andric // Late parse field attributes if necessary.
5194*0fca6ea1SDimitry Andric ParseLexedCAttributeList(LateFieldAttrs, /*EnterScope=*/false);
51950b57cec5SDimitry Andric
519681ad6265SDimitry Andric SmallVector<Decl *, 32> FieldDecls(TagDecl->fields());
51975ffd83dbSDimitry Andric
51980b57cec5SDimitry Andric Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls,
51990b57cec5SDimitry Andric T.getOpenLocation(), T.getCloseLocation(), attrs);
52000b57cec5SDimitry Andric StructScope.Exit();
52010b57cec5SDimitry Andric Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());
52020b57cec5SDimitry Andric }
52030b57cec5SDimitry Andric
52040b57cec5SDimitry Andric /// ParseEnumSpecifier
52050b57cec5SDimitry Andric /// enum-specifier: [C99 6.7.2.2]
52060b57cec5SDimitry Andric /// 'enum' identifier[opt] '{' enumerator-list '}'
52070b57cec5SDimitry Andric ///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'
52080b57cec5SDimitry Andric /// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
52090b57cec5SDimitry Andric /// '}' attributes[opt]
52100b57cec5SDimitry Andric /// [MS] 'enum' __declspec[opt] identifier[opt] '{' enumerator-list ',' [opt]
52110b57cec5SDimitry Andric /// '}'
52120b57cec5SDimitry Andric /// 'enum' identifier
52130b57cec5SDimitry Andric /// [GNU] 'enum' attributes[opt] identifier
52140b57cec5SDimitry Andric ///
52150b57cec5SDimitry Andric /// [C++11] enum-head '{' enumerator-list[opt] '}'
52160b57cec5SDimitry Andric /// [C++11] enum-head '{' enumerator-list ',' '}'
52170b57cec5SDimitry Andric ///
52180b57cec5SDimitry Andric /// enum-head: [C++11]
52190b57cec5SDimitry Andric /// enum-key attribute-specifier-seq[opt] identifier[opt] enum-base[opt]
52200b57cec5SDimitry Andric /// enum-key attribute-specifier-seq[opt] nested-name-specifier
52210b57cec5SDimitry Andric /// identifier enum-base[opt]
52220b57cec5SDimitry Andric ///
52230b57cec5SDimitry Andric /// enum-key: [C++11]
52240b57cec5SDimitry Andric /// 'enum'
52250b57cec5SDimitry Andric /// 'enum' 'class'
52260b57cec5SDimitry Andric /// 'enum' 'struct'
52270b57cec5SDimitry Andric ///
52280b57cec5SDimitry Andric /// enum-base: [C++11]
52290b57cec5SDimitry Andric /// ':' type-specifier-seq
52300b57cec5SDimitry Andric ///
52310b57cec5SDimitry Andric /// [C++] elaborated-type-specifier:
52325ffd83dbSDimitry Andric /// [C++] 'enum' nested-name-specifier[opt] identifier
52330b57cec5SDimitry Andric ///
ParseEnumSpecifier(SourceLocation StartLoc,DeclSpec & DS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSC)52340b57cec5SDimitry Andric void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
52350b57cec5SDimitry Andric const ParsedTemplateInfo &TemplateInfo,
52360b57cec5SDimitry Andric AccessSpecifier AS, DeclSpecContext DSC) {
52370b57cec5SDimitry Andric // Parse the tag portion of this.
52380b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) {
52390b57cec5SDimitry Andric // Code completion for an enum name.
5240fe6060f1SDimitry Andric cutOffParsing();
5241*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);
5242bdd1243dSDimitry Andric DS.SetTypeSpecError(); // Needed by ActOnUsingDeclaration.
5243fe6060f1SDimitry Andric return;
52440b57cec5SDimitry Andric }
52450b57cec5SDimitry Andric
52460b57cec5SDimitry Andric // If attributes exist after tag, parse them.
524781ad6265SDimitry Andric ParsedAttributes attrs(AttrFactory);
5248fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
52490b57cec5SDimitry Andric
52500b57cec5SDimitry Andric SourceLocation ScopedEnumKWLoc;
52510b57cec5SDimitry Andric bool IsScopedUsingClassTag = false;
52520b57cec5SDimitry Andric
52530b57cec5SDimitry Andric // In C++11, recognize 'enum class' and 'enum struct'.
525481ad6265SDimitry Andric if (Tok.isOneOf(tok::kw_class, tok::kw_struct) && getLangOpts().CPlusPlus) {
52550b57cec5SDimitry Andric Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum
52560b57cec5SDimitry Andric : diag::ext_scoped_enum);
52570b57cec5SDimitry Andric IsScopedUsingClassTag = Tok.is(tok::kw_class);
52580b57cec5SDimitry Andric ScopedEnumKWLoc = ConsumeToken();
52590b57cec5SDimitry Andric
52600b57cec5SDimitry Andric // Attributes are not allowed between these keywords. Diagnose,
52610b57cec5SDimitry Andric // but then just treat them like they appeared in the right place.
52620b57cec5SDimitry Andric ProhibitAttributes(attrs);
52630b57cec5SDimitry Andric
52640b57cec5SDimitry Andric // They are allowed afterwards, though.
5265fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
52660b57cec5SDimitry Andric }
52670b57cec5SDimitry Andric
52680b57cec5SDimitry Andric // C++11 [temp.explicit]p12:
52690b57cec5SDimitry Andric // The usual access controls do not apply to names used to specify
52700b57cec5SDimitry Andric // explicit instantiations.
52710b57cec5SDimitry Andric // We extend this to also cover explicit specializations. Note that
52720b57cec5SDimitry Andric // we don't suppress if this turns out to be an elaborated type
52730b57cec5SDimitry Andric // specifier.
52740b57cec5SDimitry Andric bool shouldDelayDiagsInTag =
52750b57cec5SDimitry Andric (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
52760b57cec5SDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
52770b57cec5SDimitry Andric SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
52780b57cec5SDimitry Andric
52795ffd83dbSDimitry Andric // Determine whether this declaration is permitted to have an enum-base.
52805ffd83dbSDimitry Andric AllowDefiningTypeSpec AllowEnumSpecifier =
528181ad6265SDimitry Andric isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus);
52825ffd83dbSDimitry Andric bool CanBeOpaqueEnumDeclaration =
52835ffd83dbSDimitry Andric DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC);
52845ffd83dbSDimitry Andric bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC ||
52855ffd83dbSDimitry Andric getLangOpts().MicrosoftExt) &&
52865ffd83dbSDimitry Andric (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes ||
52875ffd83dbSDimitry Andric CanBeOpaqueEnumDeclaration);
52880b57cec5SDimitry Andric
52890b57cec5SDimitry Andric CXXScopeSpec &SS = DS.getTypeSpecScope();
52900b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) {
52915ffd83dbSDimitry Andric // "enum foo : bar;" is not a potential typo for "enum foo::bar;".
52925ffd83dbSDimitry Andric ColonProtectionRAIIObject X(*this);
52930b57cec5SDimitry Andric
52940b57cec5SDimitry Andric CXXScopeSpec Spec;
52955ffd83dbSDimitry Andric if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,
529604eeddc0SDimitry Andric /*ObjectHasErrors=*/false,
52970b57cec5SDimitry Andric /*EnteringContext=*/true))
52980b57cec5SDimitry Andric return;
52990b57cec5SDimitry Andric
53000b57cec5SDimitry Andric if (Spec.isSet() && Tok.isNot(tok::identifier)) {
53010b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier;
5302bdd1243dSDimitry Andric DS.SetTypeSpecError();
53030b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) {
53040b57cec5SDimitry Andric // Has no name and is not a definition.
53050b57cec5SDimitry Andric // Skip the rest of this declarator, up until the comma or semicolon.
53060b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi);
53070b57cec5SDimitry Andric return;
53080b57cec5SDimitry Andric }
53090b57cec5SDimitry Andric }
53100b57cec5SDimitry Andric
53110b57cec5SDimitry Andric SS = Spec;
53120b57cec5SDimitry Andric }
53130b57cec5SDimitry Andric
53145ffd83dbSDimitry Andric // Must have either 'enum name' or 'enum {...}' or (rarely) 'enum : T { ... }'.
53150b57cec5SDimitry Andric if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
53165ffd83dbSDimitry Andric Tok.isNot(tok::colon)) {
53170b57cec5SDimitry Andric Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
53180b57cec5SDimitry Andric
5319bdd1243dSDimitry Andric DS.SetTypeSpecError();
53200b57cec5SDimitry Andric // Skip the rest of this declarator, up until the comma or semicolon.
53210b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi);
53220b57cec5SDimitry Andric return;
53230b57cec5SDimitry Andric }
53240b57cec5SDimitry Andric
53250b57cec5SDimitry Andric // If an identifier is present, consume and remember it.
53260b57cec5SDimitry Andric IdentifierInfo *Name = nullptr;
53270b57cec5SDimitry Andric SourceLocation NameLoc;
53280b57cec5SDimitry Andric if (Tok.is(tok::identifier)) {
53290b57cec5SDimitry Andric Name = Tok.getIdentifierInfo();
53300b57cec5SDimitry Andric NameLoc = ConsumeToken();
53310b57cec5SDimitry Andric }
53320b57cec5SDimitry Andric
53330b57cec5SDimitry Andric if (!Name && ScopedEnumKWLoc.isValid()) {
53340b57cec5SDimitry Andric // C++0x 7.2p2: The optional identifier shall not be omitted in the
53350b57cec5SDimitry Andric // declaration of a scoped enumeration.
53360b57cec5SDimitry Andric Diag(Tok, diag::err_scoped_enum_missing_identifier);
53370b57cec5SDimitry Andric ScopedEnumKWLoc = SourceLocation();
53380b57cec5SDimitry Andric IsScopedUsingClassTag = false;
53390b57cec5SDimitry Andric }
53400b57cec5SDimitry Andric
53410b57cec5SDimitry Andric // Okay, end the suppression area. We'll decide whether to emit the
53420b57cec5SDimitry Andric // diagnostics in a second.
53430b57cec5SDimitry Andric if (shouldDelayDiagsInTag)
53440b57cec5SDimitry Andric diagsFromTag.done();
53450b57cec5SDimitry Andric
53460b57cec5SDimitry Andric TypeResult BaseType;
53475ffd83dbSDimitry Andric SourceRange BaseRange;
53485ffd83dbSDimitry Andric
534981ad6265SDimitry Andric bool CanBeBitfield =
535081ad6265SDimitry Andric getCurScope()->isClassScope() && ScopedEnumKWLoc.isInvalid() && Name;
53510b57cec5SDimitry Andric
53520b57cec5SDimitry Andric // Parse the fixed underlying type.
53535ffd83dbSDimitry Andric if (Tok.is(tok::colon)) {
53545ffd83dbSDimitry Andric // This might be an enum-base or part of some unrelated enclosing context.
53555ffd83dbSDimitry Andric //
53565ffd83dbSDimitry Andric // 'enum E : base' is permitted in two circumstances:
53575ffd83dbSDimitry Andric //
53585ffd83dbSDimitry Andric // 1) As a defining-type-specifier, when followed by '{'.
53595ffd83dbSDimitry Andric // 2) As the sole constituent of a complete declaration -- when DS is empty
53605ffd83dbSDimitry Andric // and the next token is ';'.
53615ffd83dbSDimitry Andric //
53625ffd83dbSDimitry Andric // The restriction to defining-type-specifiers is important to allow parsing
53635ffd83dbSDimitry Andric // a ? new enum E : int{}
53645ffd83dbSDimitry Andric // _Generic(a, enum E : int{})
53655ffd83dbSDimitry Andric // properly.
53665ffd83dbSDimitry Andric //
53675ffd83dbSDimitry Andric // One additional consideration applies:
53685ffd83dbSDimitry Andric //
53695ffd83dbSDimitry Andric // C++ [dcl.enum]p1:
53705ffd83dbSDimitry Andric // A ':' following "enum nested-name-specifier[opt] identifier" within
53715ffd83dbSDimitry Andric // the decl-specifier-seq of a member-declaration is parsed as part of
53725ffd83dbSDimitry Andric // an enum-base.
53735ffd83dbSDimitry Andric //
53745ffd83dbSDimitry Andric // Other language modes supporting enumerations with fixed underlying types
53755ffd83dbSDimitry Andric // do not have clear rules on this, so we disambiguate to determine whether
53765ffd83dbSDimitry Andric // the tokens form a bit-field width or an enum-base.
53770b57cec5SDimitry Andric
53785ffd83dbSDimitry Andric if (CanBeBitfield && !isEnumBase(CanBeOpaqueEnumDeclaration)) {
53795ffd83dbSDimitry Andric // Outside C++11, do not interpret the tokens as an enum-base if they do
53805ffd83dbSDimitry Andric // not make sense as one. In C++11, it's an error if this happens.
53815ffd83dbSDimitry Andric if (getLangOpts().CPlusPlus11)
53825ffd83dbSDimitry Andric Diag(Tok.getLocation(), diag::err_anonymous_enum_bitfield);
53835ffd83dbSDimitry Andric } else if (CanHaveEnumBase || !ColonIsSacred) {
53845ffd83dbSDimitry Andric SourceLocation ColonLoc = ConsumeToken();
53850b57cec5SDimitry Andric
53865ffd83dbSDimitry Andric // Parse a type-specifier-seq as a type. We can't just ParseTypeName here,
53875ffd83dbSDimitry Andric // because under -fms-extensions,
53885ffd83dbSDimitry Andric // enum E : int *p;
53895ffd83dbSDimitry Andric // declares 'enum E : int; E *p;' not 'enum E : int*; E p;'.
53905ffd83dbSDimitry Andric DeclSpec DS(AttrFactory);
5391bdd1243dSDimitry Andric // enum-base is not assumed to be a type and therefore requires the
5392bdd1243dSDimitry Andric // typename keyword [p0634r3].
5393bdd1243dSDimitry Andric ParseSpecifierQualifierList(DS, ImplicitTypenameContext::No, AS,
5394bdd1243dSDimitry Andric DeclSpecContext::DSC_type_specifier);
539581ad6265SDimitry Andric Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
539681ad6265SDimitry Andric DeclaratorContext::TypeName);
53977a6dacacSDimitry Andric BaseType = Actions.ActOnTypeName(DeclaratorInfo);
53980b57cec5SDimitry Andric
53995ffd83dbSDimitry Andric BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());
54000b57cec5SDimitry Andric
54015f757f3fSDimitry Andric if (!getLangOpts().ObjC && !getLangOpts().C23) {
54020b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11)
54035ffd83dbSDimitry Andric Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
54045ffd83dbSDimitry Andric << BaseRange;
54050b57cec5SDimitry Andric else if (getLangOpts().CPlusPlus)
54065ffd83dbSDimitry Andric Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
54075ffd83dbSDimitry Andric << BaseRange;
54080b57cec5SDimitry Andric else if (getLangOpts().MicrosoftExt)
54095ffd83dbSDimitry Andric Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
54105ffd83dbSDimitry Andric << BaseRange;
54110b57cec5SDimitry Andric else
54125ffd83dbSDimitry Andric Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)
54135ffd83dbSDimitry Andric << BaseRange;
54140b57cec5SDimitry Andric }
54150b57cec5SDimitry Andric }
54160b57cec5SDimitry Andric }
54170b57cec5SDimitry Andric
54180b57cec5SDimitry Andric // There are four options here. If we have 'friend enum foo;' then this is a
54190b57cec5SDimitry Andric // friend declaration, and cannot have an accompanying definition. If we have
54200b57cec5SDimitry Andric // 'enum foo;', then this is a forward declaration. If we have
54210b57cec5SDimitry Andric // 'enum foo {...' then this is a definition. Otherwise we have something
54220b57cec5SDimitry Andric // like 'enum foo xyz', a reference.
54230b57cec5SDimitry Andric //
54240b57cec5SDimitry Andric // This is needed to handle stuff like this right (C99 6.7.2.3p11):
54250b57cec5SDimitry Andric // enum foo {..}; void bar() { enum foo; } <- new foo in bar.
54260b57cec5SDimitry Andric // enum foo {..}; void bar() { enum foo x; } <- use of old foo.
54270b57cec5SDimitry Andric //
5428*0fca6ea1SDimitry Andric TagUseKind TUK;
54295ffd83dbSDimitry Andric if (AllowEnumSpecifier == AllowDefiningTypeSpec::No)
5430*0fca6ea1SDimitry Andric TUK = TagUseKind::Reference;
54315ffd83dbSDimitry Andric else if (Tok.is(tok::l_brace)) {
54320b57cec5SDimitry Andric if (DS.isFriendSpecified()) {
54330b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
54340b57cec5SDimitry Andric << SourceRange(DS.getFriendSpecLoc());
54350b57cec5SDimitry Andric ConsumeBrace();
54360b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi);
54375ffd83dbSDimitry Andric // Discard any other definition-only pieces.
54385ffd83dbSDimitry Andric attrs.clear();
54395ffd83dbSDimitry Andric ScopedEnumKWLoc = SourceLocation();
54405ffd83dbSDimitry Andric IsScopedUsingClassTag = false;
54415ffd83dbSDimitry Andric BaseType = TypeResult();
5442*0fca6ea1SDimitry Andric TUK = TagUseKind::Friend;
54430b57cec5SDimitry Andric } else {
5444*0fca6ea1SDimitry Andric TUK = TagUseKind::Definition;
54450b57cec5SDimitry Andric }
54460b57cec5SDimitry Andric } else if (!isTypeSpecifier(DSC) &&
54470b57cec5SDimitry Andric (Tok.is(tok::semi) ||
54480b57cec5SDimitry Andric (Tok.isAtStartOfLine() &&
54490b57cec5SDimitry Andric !isValidAfterTypeSpecifier(CanBeBitfield)))) {
54505ffd83dbSDimitry Andric // An opaque-enum-declaration is required to be standalone (no preceding or
54515ffd83dbSDimitry Andric // following tokens in the declaration). Sema enforces this separately by
54525ffd83dbSDimitry Andric // diagnosing anything else in the DeclSpec.
5453*0fca6ea1SDimitry Andric TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration;
54540b57cec5SDimitry Andric if (Tok.isNot(tok::semi)) {
54550b57cec5SDimitry Andric // A semicolon was missing after this declaration. Diagnose and recover.
54560b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
54570b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject=*/true);
54580b57cec5SDimitry Andric Tok.setKind(tok::semi);
54590b57cec5SDimitry Andric }
54600b57cec5SDimitry Andric } else {
5461*0fca6ea1SDimitry Andric TUK = TagUseKind::Reference;
54620b57cec5SDimitry Andric }
54630b57cec5SDimitry Andric
54645ffd83dbSDimitry Andric bool IsElaboratedTypeSpecifier =
5465*0fca6ea1SDimitry Andric TUK == TagUseKind::Reference || TUK == TagUseKind::Friend;
54665ffd83dbSDimitry Andric
54675ffd83dbSDimitry Andric // If this is an elaborated type specifier nested in a larger declaration,
54685ffd83dbSDimitry Andric // and we delayed diagnostics before, just merge them into the current pool.
5469*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Reference && shouldDelayDiagsInTag) {
54700b57cec5SDimitry Andric diagsFromTag.redelay();
54710b57cec5SDimitry Andric }
54720b57cec5SDimitry Andric
54730b57cec5SDimitry Andric MultiTemplateParamsArg TParams;
54740b57cec5SDimitry Andric if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
5475*0fca6ea1SDimitry Andric TUK != TagUseKind::Reference) {
54760b57cec5SDimitry Andric if (!getLangOpts().CPlusPlus11 || !SS.isSet()) {
54770b57cec5SDimitry Andric // Skip the rest of this declarator, up until the comma or semicolon.
54780b57cec5SDimitry Andric Diag(Tok, diag::err_enum_template);
54790b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi);
54800b57cec5SDimitry Andric return;
54810b57cec5SDimitry Andric }
54820b57cec5SDimitry Andric
54830b57cec5SDimitry Andric if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
54840b57cec5SDimitry Andric // Enumerations can't be explicitly instantiated.
54850b57cec5SDimitry Andric DS.SetTypeSpecError();
54860b57cec5SDimitry Andric Diag(StartLoc, diag::err_explicit_instantiation_enum);
54870b57cec5SDimitry Andric return;
54880b57cec5SDimitry Andric }
54890b57cec5SDimitry Andric
54900b57cec5SDimitry Andric assert(TemplateInfo.TemplateParams && "no template parameters");
54910b57cec5SDimitry Andric TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(),
54920b57cec5SDimitry Andric TemplateInfo.TemplateParams->size());
549306c3fb27SDimitry Andric SS.setTemplateParamLists(TParams);
54940b57cec5SDimitry Andric }
54950b57cec5SDimitry Andric
5496*0fca6ea1SDimitry Andric if (!Name && TUK != TagUseKind::Definition) {
54970b57cec5SDimitry Andric Diag(Tok, diag::err_enumerator_unnamed_no_def);
54980b57cec5SDimitry Andric
5499bdd1243dSDimitry Andric DS.SetTypeSpecError();
55000b57cec5SDimitry Andric // Skip the rest of this declarator, up until the comma or semicolon.
55010b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi);
55020b57cec5SDimitry Andric return;
55030b57cec5SDimitry Andric }
55040b57cec5SDimitry Andric
55055ffd83dbSDimitry Andric // An elaborated-type-specifier has a much more constrained grammar:
55065ffd83dbSDimitry Andric //
55075ffd83dbSDimitry Andric // 'enum' nested-name-specifier[opt] identifier
55085ffd83dbSDimitry Andric //
55095ffd83dbSDimitry Andric // If we parsed any other bits, reject them now.
55105ffd83dbSDimitry Andric //
55115ffd83dbSDimitry Andric // MSVC and (for now at least) Objective-C permit a full enum-specifier
55125ffd83dbSDimitry Andric // or opaque-enum-declaration anywhere.
55135ffd83dbSDimitry Andric if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt &&
55145ffd83dbSDimitry Andric !getLangOpts().ObjC) {
5515fe6060f1SDimitry Andric ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
551606c3fb27SDimitry Andric diag::err_keyword_not_allowed,
5517fe6060f1SDimitry Andric /*DiagnoseEmptyAttrs=*/true);
55185ffd83dbSDimitry Andric if (BaseType.isUsable())
55195ffd83dbSDimitry Andric Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier)
55205ffd83dbSDimitry Andric << (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange;
55215ffd83dbSDimitry Andric else if (ScopedEnumKWLoc.isValid())
55225ffd83dbSDimitry Andric Diag(ScopedEnumKWLoc, diag::ext_elaborated_enum_class)
55235ffd83dbSDimitry Andric << FixItHint::CreateRemoval(ScopedEnumKWLoc) << IsScopedUsingClassTag;
55245ffd83dbSDimitry Andric }
55255ffd83dbSDimitry Andric
55260b57cec5SDimitry Andric stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
55270b57cec5SDimitry Andric
5528*0fca6ea1SDimitry Andric SkipBodyInfo SkipBody;
5529*0fca6ea1SDimitry Andric if (!Name && TUK == TagUseKind::Definition && Tok.is(tok::l_brace) &&
55300b57cec5SDimitry Andric NextToken().is(tok::identifier))
55310b57cec5SDimitry Andric SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(),
55320b57cec5SDimitry Andric NextToken().getIdentifierInfo(),
55330b57cec5SDimitry Andric NextToken().getLocation());
55340b57cec5SDimitry Andric
55350b57cec5SDimitry Andric bool Owned = false;
55360b57cec5SDimitry Andric bool IsDependent = false;
55370b57cec5SDimitry Andric const char *PrevSpec = nullptr;
55380b57cec5SDimitry Andric unsigned DiagID;
5539bdd1243dSDimitry Andric Decl *TagDecl =
5540bdd1243dSDimitry Andric Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS,
5541bdd1243dSDimitry Andric Name, NameLoc, attrs, AS, DS.getModulePrivateSpecLoc(),
5542bdd1243dSDimitry Andric TParams, Owned, IsDependent, ScopedEnumKWLoc,
5543bdd1243dSDimitry Andric IsScopedUsingClassTag,
5544bdd1243dSDimitry Andric BaseType, DSC == DeclSpecContext::DSC_type_specifier,
55450b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_template_param ||
55460b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_template_type_arg,
55471ac55f4cSDimitry Andric OffsetOfState, &SkipBody).get();
55480b57cec5SDimitry Andric
55490b57cec5SDimitry Andric if (SkipBody.ShouldSkip) {
5550*0fca6ea1SDimitry Andric assert(TUK == TagUseKind::Definition && "can only skip a definition");
55510b57cec5SDimitry Andric
55520b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace);
55530b57cec5SDimitry Andric T.consumeOpen();
55540b57cec5SDimitry Andric T.skipToEnd();
55550b57cec5SDimitry Andric
55560b57cec5SDimitry Andric if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
55571ac55f4cSDimitry Andric NameLoc.isValid() ? NameLoc : StartLoc,
55581ac55f4cSDimitry Andric PrevSpec, DiagID, TagDecl, Owned,
55590b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
55600b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
55610b57cec5SDimitry Andric return;
55620b57cec5SDimitry Andric }
55630b57cec5SDimitry Andric
55640b57cec5SDimitry Andric if (IsDependent) {
55650b57cec5SDimitry Andric // This enum has a dependent nested-name-specifier. Handle it as a
55660b57cec5SDimitry Andric // dependent tag.
55670b57cec5SDimitry Andric if (!Name) {
55680b57cec5SDimitry Andric DS.SetTypeSpecError();
55690b57cec5SDimitry Andric Diag(Tok, diag::err_expected_type_name_after_typename);
55700b57cec5SDimitry Andric return;
55710b57cec5SDimitry Andric }
55720b57cec5SDimitry Andric
55730b57cec5SDimitry Andric TypeResult Type = Actions.ActOnDependentTag(
55740b57cec5SDimitry Andric getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc);
55750b57cec5SDimitry Andric if (Type.isInvalid()) {
55760b57cec5SDimitry Andric DS.SetTypeSpecError();
55770b57cec5SDimitry Andric return;
55780b57cec5SDimitry Andric }
55790b57cec5SDimitry Andric
55800b57cec5SDimitry Andric if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
55810b57cec5SDimitry Andric NameLoc.isValid() ? NameLoc : StartLoc,
55820b57cec5SDimitry Andric PrevSpec, DiagID, Type.get(),
55830b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
55840b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
55850b57cec5SDimitry Andric
55860b57cec5SDimitry Andric return;
55870b57cec5SDimitry Andric }
55880b57cec5SDimitry Andric
55890b57cec5SDimitry Andric if (!TagDecl) {
55900b57cec5SDimitry Andric // The action failed to produce an enumeration tag. If this is a
55910b57cec5SDimitry Andric // definition, consume the entire definition.
5592*0fca6ea1SDimitry Andric if (Tok.is(tok::l_brace) && TUK != TagUseKind::Reference) {
55930b57cec5SDimitry Andric ConsumeBrace();
55940b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi);
55950b57cec5SDimitry Andric }
55960b57cec5SDimitry Andric
55970b57cec5SDimitry Andric DS.SetTypeSpecError();
55980b57cec5SDimitry Andric return;
55990b57cec5SDimitry Andric }
56000b57cec5SDimitry Andric
5601*0fca6ea1SDimitry Andric if (Tok.is(tok::l_brace) && TUK == TagUseKind::Definition) {
56020b57cec5SDimitry Andric Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl;
56030b57cec5SDimitry Andric ParseEnumBody(StartLoc, D);
56040b57cec5SDimitry Andric if (SkipBody.CheckSameAsPrevious &&
560581ad6265SDimitry Andric !Actions.ActOnDuplicateDefinition(TagDecl, SkipBody)) {
56060b57cec5SDimitry Andric DS.SetTypeSpecError();
56070b57cec5SDimitry Andric return;
56080b57cec5SDimitry Andric }
56090b57cec5SDimitry Andric }
56100b57cec5SDimitry Andric
56110b57cec5SDimitry Andric if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
56121ac55f4cSDimitry Andric NameLoc.isValid() ? NameLoc : StartLoc,
56131ac55f4cSDimitry Andric PrevSpec, DiagID, TagDecl, Owned,
56140b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
56150b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
56160b57cec5SDimitry Andric }
56170b57cec5SDimitry Andric
56180b57cec5SDimitry Andric /// ParseEnumBody - Parse a {} enclosed enumerator-list.
56190b57cec5SDimitry Andric /// enumerator-list:
56200b57cec5SDimitry Andric /// enumerator
56210b57cec5SDimitry Andric /// enumerator-list ',' enumerator
56220b57cec5SDimitry Andric /// enumerator:
56230b57cec5SDimitry Andric /// enumeration-constant attributes[opt]
56240b57cec5SDimitry Andric /// enumeration-constant attributes[opt] '=' constant-expression
56250b57cec5SDimitry Andric /// enumeration-constant:
56260b57cec5SDimitry Andric /// identifier
56270b57cec5SDimitry Andric ///
ParseEnumBody(SourceLocation StartLoc,Decl * EnumDecl)56280b57cec5SDimitry Andric void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
56290b57cec5SDimitry Andric // Enter the scope of the enum body and start the definition.
56300b57cec5SDimitry Andric ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope);
56310b57cec5SDimitry Andric Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
56320b57cec5SDimitry Andric
56330b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace);
56340b57cec5SDimitry Andric T.consumeOpen();
56350b57cec5SDimitry Andric
56360b57cec5SDimitry Andric // C does not allow an empty enumerator-list, C++ does [dcl.enum].
56370b57cec5SDimitry Andric if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)
56380b57cec5SDimitry Andric Diag(Tok, diag::err_empty_enum);
56390b57cec5SDimitry Andric
56400b57cec5SDimitry Andric SmallVector<Decl *, 32> EnumConstantDecls;
56410b57cec5SDimitry Andric SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
56420b57cec5SDimitry Andric
56430b57cec5SDimitry Andric Decl *LastEnumConstDecl = nullptr;
56440b57cec5SDimitry Andric
56450b57cec5SDimitry Andric // Parse the enumerator-list.
56460b57cec5SDimitry Andric while (Tok.isNot(tok::r_brace)) {
56470b57cec5SDimitry Andric // Parse enumerator. If failed, try skipping till the start of the next
56480b57cec5SDimitry Andric // enumerator definition.
56490b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
56500b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
56510b57cec5SDimitry Andric if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&
56520b57cec5SDimitry Andric TryConsumeToken(tok::comma))
56530b57cec5SDimitry Andric continue;
56540b57cec5SDimitry Andric break;
56550b57cec5SDimitry Andric }
56560b57cec5SDimitry Andric IdentifierInfo *Ident = Tok.getIdentifierInfo();
56570b57cec5SDimitry Andric SourceLocation IdentLoc = ConsumeToken();
56580b57cec5SDimitry Andric
56590b57cec5SDimitry Andric // If attributes exist after the enumerator, parse them.
566081ad6265SDimitry Andric ParsedAttributes attrs(AttrFactory);
56610b57cec5SDimitry Andric MaybeParseGNUAttributes(attrs);
566206c3fb27SDimitry Andric if (isAllowedCXX11AttributeSpecifier()) {
56630b57cec5SDimitry Andric if (getLangOpts().CPlusPlus)
56640b57cec5SDimitry Andric Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
56650b57cec5SDimitry Andric ? diag::warn_cxx14_compat_ns_enum_attribute
56660b57cec5SDimitry Andric : diag::ext_ns_enum_attribute)
56670b57cec5SDimitry Andric << 1 /*enumerator*/;
56680b57cec5SDimitry Andric ParseCXX11Attributes(attrs);
56690b57cec5SDimitry Andric }
56700b57cec5SDimitry Andric
56710b57cec5SDimitry Andric SourceLocation EqualLoc;
56720b57cec5SDimitry Andric ExprResult AssignedVal;
56730b57cec5SDimitry Andric EnumAvailabilityDiags.emplace_back(*this);
56740b57cec5SDimitry Andric
5675a7dea167SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated(
5676a7dea167SDimitry Andric Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
56770b57cec5SDimitry Andric if (TryConsumeToken(tok::equal, EqualLoc)) {
5678a7dea167SDimitry Andric AssignedVal = ParseConstantExpressionInExprEvalContext();
56790b57cec5SDimitry Andric if (AssignedVal.isInvalid())
56800b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
56810b57cec5SDimitry Andric }
56820b57cec5SDimitry Andric
56830b57cec5SDimitry Andric // Install the enumerator constant into EnumDecl.
56840b57cec5SDimitry Andric Decl *EnumConstDecl = Actions.ActOnEnumConstant(
56850b57cec5SDimitry Andric getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs,
56860b57cec5SDimitry Andric EqualLoc, AssignedVal.get());
56870b57cec5SDimitry Andric EnumAvailabilityDiags.back().done();
56880b57cec5SDimitry Andric
56890b57cec5SDimitry Andric EnumConstantDecls.push_back(EnumConstDecl);
56900b57cec5SDimitry Andric LastEnumConstDecl = EnumConstDecl;
56910b57cec5SDimitry Andric
56920b57cec5SDimitry Andric if (Tok.is(tok::identifier)) {
56930b57cec5SDimitry Andric // We're missing a comma between enumerators.
56940b57cec5SDimitry Andric SourceLocation Loc = getEndOfPreviousToken();
56950b57cec5SDimitry Andric Diag(Loc, diag::err_enumerator_list_missing_comma)
56960b57cec5SDimitry Andric << FixItHint::CreateInsertion(Loc, ", ");
56970b57cec5SDimitry Andric continue;
56980b57cec5SDimitry Andric }
56990b57cec5SDimitry Andric
57000b57cec5SDimitry Andric // Emumerator definition must be finished, only comma or r_brace are
57010b57cec5SDimitry Andric // allowed here.
57020b57cec5SDimitry Andric SourceLocation CommaLoc;
57030b57cec5SDimitry Andric if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {
57040b57cec5SDimitry Andric if (EqualLoc.isValid())
57050b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace
57060b57cec5SDimitry Andric << tok::comma;
57070b57cec5SDimitry Andric else
57080b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);
57090b57cec5SDimitry Andric if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {
57100b57cec5SDimitry Andric if (TryConsumeToken(tok::comma, CommaLoc))
57110b57cec5SDimitry Andric continue;
57120b57cec5SDimitry Andric } else {
57130b57cec5SDimitry Andric break;
57140b57cec5SDimitry Andric }
57150b57cec5SDimitry Andric }
57160b57cec5SDimitry Andric
57170b57cec5SDimitry Andric // If comma is followed by r_brace, emit appropriate warning.
57180b57cec5SDimitry Andric if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {
57190b57cec5SDimitry Andric if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
57200b57cec5SDimitry Andric Diag(CommaLoc, getLangOpts().CPlusPlus ?
57210b57cec5SDimitry Andric diag::ext_enumerator_list_comma_cxx :
57220b57cec5SDimitry Andric diag::ext_enumerator_list_comma_c)
57230b57cec5SDimitry Andric << FixItHint::CreateRemoval(CommaLoc);
57240b57cec5SDimitry Andric else if (getLangOpts().CPlusPlus11)
57250b57cec5SDimitry Andric Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
57260b57cec5SDimitry Andric << FixItHint::CreateRemoval(CommaLoc);
57270b57cec5SDimitry Andric break;
57280b57cec5SDimitry Andric }
57290b57cec5SDimitry Andric }
57300b57cec5SDimitry Andric
57310b57cec5SDimitry Andric // Eat the }.
57320b57cec5SDimitry Andric T.consumeClose();
57330b57cec5SDimitry Andric
57340b57cec5SDimitry Andric // If attributes exist after the identifier list, parse them.
57350b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory);
57360b57cec5SDimitry Andric MaybeParseGNUAttributes(attrs);
57370b57cec5SDimitry Andric
57380b57cec5SDimitry Andric Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls,
57390b57cec5SDimitry Andric getCurScope(), attrs);
57400b57cec5SDimitry Andric
57410b57cec5SDimitry Andric // Now handle enum constant availability diagnostics.
57420b57cec5SDimitry Andric assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());
57430b57cec5SDimitry Andric for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) {
57440b57cec5SDimitry Andric ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
57450b57cec5SDimitry Andric EnumAvailabilityDiags[i].redelay();
57460b57cec5SDimitry Andric PD.complete(EnumConstantDecls[i]);
57470b57cec5SDimitry Andric }
57480b57cec5SDimitry Andric
57490b57cec5SDimitry Andric EnumScope.Exit();
57500b57cec5SDimitry Andric Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getRange());
57510b57cec5SDimitry Andric
57520b57cec5SDimitry Andric // The next token must be valid after an enum definition. If not, a ';'
57530b57cec5SDimitry Andric // was probably forgotten.
575481ad6265SDimitry Andric bool CanBeBitfield = getCurScope()->isClassScope();
57550b57cec5SDimitry Andric if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
57560b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
57570b57cec5SDimitry Andric // Push this token back into the preprocessor and change our current token
57580b57cec5SDimitry Andric // to ';' so that the rest of the code recovers as though there were an
57590b57cec5SDimitry Andric // ';' after the definition.
57600b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject=*/true);
57610b57cec5SDimitry Andric Tok.setKind(tok::semi);
57620b57cec5SDimitry Andric }
57630b57cec5SDimitry Andric }
57640b57cec5SDimitry Andric
57650b57cec5SDimitry Andric /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
57660b57cec5SDimitry Andric /// is definitely a type-specifier. Return false if it isn't part of a type
57670b57cec5SDimitry Andric /// specifier or if we're not sure.
isKnownToBeTypeSpecifier(const Token & Tok) const57680b57cec5SDimitry Andric bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
57690b57cec5SDimitry Andric switch (Tok.getKind()) {
57700b57cec5SDimitry Andric default: return false;
57710b57cec5SDimitry Andric // type-specifiers
57720b57cec5SDimitry Andric case tok::kw_short:
57730b57cec5SDimitry Andric case tok::kw_long:
57740b57cec5SDimitry Andric case tok::kw___int64:
57750b57cec5SDimitry Andric case tok::kw___int128:
57760b57cec5SDimitry Andric case tok::kw_signed:
57770b57cec5SDimitry Andric case tok::kw_unsigned:
57780b57cec5SDimitry Andric case tok::kw__Complex:
57790b57cec5SDimitry Andric case tok::kw__Imaginary:
57800b57cec5SDimitry Andric case tok::kw_void:
57810b57cec5SDimitry Andric case tok::kw_char:
57820b57cec5SDimitry Andric case tok::kw_wchar_t:
57830b57cec5SDimitry Andric case tok::kw_char8_t:
57840b57cec5SDimitry Andric case tok::kw_char16_t:
57850b57cec5SDimitry Andric case tok::kw_char32_t:
57860b57cec5SDimitry Andric case tok::kw_int:
57875ffd83dbSDimitry Andric case tok::kw__ExtInt:
57880eae32dcSDimitry Andric case tok::kw__BitInt:
57895ffd83dbSDimitry Andric case tok::kw___bf16:
57900b57cec5SDimitry Andric case tok::kw_half:
57910b57cec5SDimitry Andric case tok::kw_float:
57920b57cec5SDimitry Andric case tok::kw_double:
57930b57cec5SDimitry Andric case tok::kw__Accum:
57940b57cec5SDimitry Andric case tok::kw__Fract:
57950b57cec5SDimitry Andric case tok::kw__Float16:
57960b57cec5SDimitry Andric case tok::kw___float128:
5797349cc55cSDimitry Andric case tok::kw___ibm128:
57980b57cec5SDimitry Andric case tok::kw_bool:
57990b57cec5SDimitry Andric case tok::kw__Bool:
58000b57cec5SDimitry Andric case tok::kw__Decimal32:
58010b57cec5SDimitry Andric case tok::kw__Decimal64:
58020b57cec5SDimitry Andric case tok::kw__Decimal128:
58030b57cec5SDimitry Andric case tok::kw___vector:
58040b57cec5SDimitry Andric #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
58050b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
58060b57cec5SDimitry Andric
58070b57cec5SDimitry Andric // struct-or-union-specifier (C99) or class-specifier (C++)
58080b57cec5SDimitry Andric case tok::kw_class:
58090b57cec5SDimitry Andric case tok::kw_struct:
58100b57cec5SDimitry Andric case tok::kw___interface:
58110b57cec5SDimitry Andric case tok::kw_union:
58120b57cec5SDimitry Andric // enum-specifier
58130b57cec5SDimitry Andric case tok::kw_enum:
58140b57cec5SDimitry Andric
58150b57cec5SDimitry Andric // typedef-name
58160b57cec5SDimitry Andric case tok::annot_typename:
58170b57cec5SDimitry Andric return true;
58180b57cec5SDimitry Andric }
58190b57cec5SDimitry Andric }
58200b57cec5SDimitry Andric
58210b57cec5SDimitry Andric /// isTypeSpecifierQualifier - Return true if the current token could be the
58220b57cec5SDimitry Andric /// start of a specifier-qualifier-list.
isTypeSpecifierQualifier()58230b57cec5SDimitry Andric bool Parser::isTypeSpecifierQualifier() {
58240b57cec5SDimitry Andric switch (Tok.getKind()) {
58250b57cec5SDimitry Andric default: return false;
58260b57cec5SDimitry Andric
58270b57cec5SDimitry Andric case tok::identifier: // foo::bar
58280b57cec5SDimitry Andric if (TryAltiVecVectorToken())
58290b57cec5SDimitry Andric return true;
5830bdd1243dSDimitry Andric [[fallthrough]];
58310b57cec5SDimitry Andric case tok::kw_typename: // typename T::type
58320b57cec5SDimitry Andric // Annotate typenames and C++ scope specifiers. If we get one, just
58330b57cec5SDimitry Andric // recurse to handle whatever we get.
58340b57cec5SDimitry Andric if (TryAnnotateTypeOrScopeToken())
58350b57cec5SDimitry Andric return true;
58360b57cec5SDimitry Andric if (Tok.is(tok::identifier))
58370b57cec5SDimitry Andric return false;
58380b57cec5SDimitry Andric return isTypeSpecifierQualifier();
58390b57cec5SDimitry Andric
58400b57cec5SDimitry Andric case tok::coloncolon: // ::foo::bar
58410b57cec5SDimitry Andric if (NextToken().is(tok::kw_new) || // ::new
58420b57cec5SDimitry Andric NextToken().is(tok::kw_delete)) // ::delete
58430b57cec5SDimitry Andric return false;
58440b57cec5SDimitry Andric
58450b57cec5SDimitry Andric if (TryAnnotateTypeOrScopeToken())
58460b57cec5SDimitry Andric return true;
58470b57cec5SDimitry Andric return isTypeSpecifierQualifier();
58480b57cec5SDimitry Andric
58490b57cec5SDimitry Andric // GNU attributes support.
58500b57cec5SDimitry Andric case tok::kw___attribute:
58515f757f3fSDimitry Andric // C23/GNU typeof support.
58520b57cec5SDimitry Andric case tok::kw_typeof:
5853bdd1243dSDimitry Andric case tok::kw_typeof_unqual:
58540b57cec5SDimitry Andric
58550b57cec5SDimitry Andric // type-specifiers
58560b57cec5SDimitry Andric case tok::kw_short:
58570b57cec5SDimitry Andric case tok::kw_long:
58580b57cec5SDimitry Andric case tok::kw___int64:
58590b57cec5SDimitry Andric case tok::kw___int128:
58600b57cec5SDimitry Andric case tok::kw_signed:
58610b57cec5SDimitry Andric case tok::kw_unsigned:
58620b57cec5SDimitry Andric case tok::kw__Complex:
58630b57cec5SDimitry Andric case tok::kw__Imaginary:
58640b57cec5SDimitry Andric case tok::kw_void:
58650b57cec5SDimitry Andric case tok::kw_char:
58660b57cec5SDimitry Andric case tok::kw_wchar_t:
58670b57cec5SDimitry Andric case tok::kw_char8_t:
58680b57cec5SDimitry Andric case tok::kw_char16_t:
58690b57cec5SDimitry Andric case tok::kw_char32_t:
58700b57cec5SDimitry Andric case tok::kw_int:
58715ffd83dbSDimitry Andric case tok::kw__ExtInt:
58720eae32dcSDimitry Andric case tok::kw__BitInt:
58730b57cec5SDimitry Andric case tok::kw_half:
58745ffd83dbSDimitry Andric case tok::kw___bf16:
58750b57cec5SDimitry Andric case tok::kw_float:
58760b57cec5SDimitry Andric case tok::kw_double:
58770b57cec5SDimitry Andric case tok::kw__Accum:
58780b57cec5SDimitry Andric case tok::kw__Fract:
58790b57cec5SDimitry Andric case tok::kw__Float16:
58800b57cec5SDimitry Andric case tok::kw___float128:
5881349cc55cSDimitry Andric case tok::kw___ibm128:
58820b57cec5SDimitry Andric case tok::kw_bool:
58830b57cec5SDimitry Andric case tok::kw__Bool:
58840b57cec5SDimitry Andric case tok::kw__Decimal32:
58850b57cec5SDimitry Andric case tok::kw__Decimal64:
58860b57cec5SDimitry Andric case tok::kw__Decimal128:
58870b57cec5SDimitry Andric case tok::kw___vector:
58880b57cec5SDimitry Andric #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
58890b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
58900b57cec5SDimitry Andric
58910b57cec5SDimitry Andric // struct-or-union-specifier (C99) or class-specifier (C++)
58920b57cec5SDimitry Andric case tok::kw_class:
58930b57cec5SDimitry Andric case tok::kw_struct:
58940b57cec5SDimitry Andric case tok::kw___interface:
58950b57cec5SDimitry Andric case tok::kw_union:
58960b57cec5SDimitry Andric // enum-specifier
58970b57cec5SDimitry Andric case tok::kw_enum:
58980b57cec5SDimitry Andric
58990b57cec5SDimitry Andric // type-qualifier
59000b57cec5SDimitry Andric case tok::kw_const:
59010b57cec5SDimitry Andric case tok::kw_volatile:
59020b57cec5SDimitry Andric case tok::kw_restrict:
59030b57cec5SDimitry Andric case tok::kw__Sat:
59040b57cec5SDimitry Andric
59050b57cec5SDimitry Andric // Debugger support.
59060b57cec5SDimitry Andric case tok::kw___unknown_anytype:
59070b57cec5SDimitry Andric
59080b57cec5SDimitry Andric // typedef-name
59090b57cec5SDimitry Andric case tok::annot_typename:
59100b57cec5SDimitry Andric return true;
59110b57cec5SDimitry Andric
59120b57cec5SDimitry Andric // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
59130b57cec5SDimitry Andric case tok::less:
59140b57cec5SDimitry Andric return getLangOpts().ObjC;
59150b57cec5SDimitry Andric
59160b57cec5SDimitry Andric case tok::kw___cdecl:
59170b57cec5SDimitry Andric case tok::kw___stdcall:
59180b57cec5SDimitry Andric case tok::kw___fastcall:
59190b57cec5SDimitry Andric case tok::kw___thiscall:
59200b57cec5SDimitry Andric case tok::kw___regcall:
59210b57cec5SDimitry Andric case tok::kw___vectorcall:
59220b57cec5SDimitry Andric case tok::kw___w64:
59230b57cec5SDimitry Andric case tok::kw___ptr64:
59240b57cec5SDimitry Andric case tok::kw___ptr32:
59250b57cec5SDimitry Andric case tok::kw___pascal:
59260b57cec5SDimitry Andric case tok::kw___unaligned:
59270b57cec5SDimitry Andric
59280b57cec5SDimitry Andric case tok::kw__Nonnull:
59290b57cec5SDimitry Andric case tok::kw__Nullable:
5930e8d8bef9SDimitry Andric case tok::kw__Nullable_result:
59310b57cec5SDimitry Andric case tok::kw__Null_unspecified:
59320b57cec5SDimitry Andric
59330b57cec5SDimitry Andric case tok::kw___kindof:
59340b57cec5SDimitry Andric
59350b57cec5SDimitry Andric case tok::kw___private:
59360b57cec5SDimitry Andric case tok::kw___local:
59370b57cec5SDimitry Andric case tok::kw___global:
59380b57cec5SDimitry Andric case tok::kw___constant:
59390b57cec5SDimitry Andric case tok::kw___generic:
59400b57cec5SDimitry Andric case tok::kw___read_only:
59410b57cec5SDimitry Andric case tok::kw___read_write:
59420b57cec5SDimitry Andric case tok::kw___write_only:
594306c3fb27SDimitry Andric case tok::kw___funcref:
59440b57cec5SDimitry Andric return true;
59450b57cec5SDimitry Andric
59460b57cec5SDimitry Andric case tok::kw_private:
59470b57cec5SDimitry Andric return getLangOpts().OpenCL;
59480b57cec5SDimitry Andric
59490b57cec5SDimitry Andric // C11 _Atomic
59500b57cec5SDimitry Andric case tok::kw__Atomic:
59510b57cec5SDimitry Andric return true;
59525f757f3fSDimitry Andric
59535f757f3fSDimitry Andric // HLSL type qualifiers
59545f757f3fSDimitry Andric case tok::kw_groupshared:
59555f757f3fSDimitry Andric case tok::kw_in:
59565f757f3fSDimitry Andric case tok::kw_inout:
59575f757f3fSDimitry Andric case tok::kw_out:
59585f757f3fSDimitry Andric return getLangOpts().HLSL;
59590b57cec5SDimitry Andric }
59600b57cec5SDimitry Andric }
59610b57cec5SDimitry Andric
ParseTopLevelStmtDecl()5962bdd1243dSDimitry Andric Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
5963bdd1243dSDimitry Andric assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode");
5964bdd1243dSDimitry Andric
5965bdd1243dSDimitry Andric // Parse a top-level-stmt.
5966bdd1243dSDimitry Andric Parser::StmtVector Stmts;
5967bdd1243dSDimitry Andric ParsedStmtContext SubStmtCtx = ParsedStmtContext();
5968*0fca6ea1SDimitry Andric ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
5969*0fca6ea1SDimitry Andric Scope::CompoundStmtScope);
5970*0fca6ea1SDimitry Andric TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
5971bdd1243dSDimitry Andric StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
5972bdd1243dSDimitry Andric if (!R.isUsable())
5973bdd1243dSDimitry Andric return nullptr;
5974bdd1243dSDimitry Andric
5975*0fca6ea1SDimitry Andric Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());
597606c3fb27SDimitry Andric
597706c3fb27SDimitry Andric if (Tok.is(tok::annot_repl_input_end) &&
597806c3fb27SDimitry Andric Tok.getAnnotationValue() != nullptr) {
597906c3fb27SDimitry Andric ConsumeAnnotationToken();
5980*0fca6ea1SDimitry Andric TLSD->setSemiMissing();
598106c3fb27SDimitry Andric }
598206c3fb27SDimitry Andric
5983*0fca6ea1SDimitry Andric SmallVector<Decl *, 2> DeclsInGroup;
5984*0fca6ea1SDimitry Andric DeclsInGroup.push_back(TLSD);
5985*0fca6ea1SDimitry Andric
5986bdd1243dSDimitry Andric // Currently happens for things like -fms-extensions and use `__if_exists`.
5987*0fca6ea1SDimitry Andric for (Stmt *S : Stmts) {
5988*0fca6ea1SDimitry Andric // Here we should be safe as `__if_exists` and friends are not introducing
5989*0fca6ea1SDimitry Andric // new variables which need to live outside file scope.
5990*0fca6ea1SDimitry Andric TopLevelStmtDecl *D = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
5991*0fca6ea1SDimitry Andric Actions.ActOnFinishTopLevelStmtDecl(D, S);
5992*0fca6ea1SDimitry Andric DeclsInGroup.push_back(D);
5993*0fca6ea1SDimitry Andric }
5994bdd1243dSDimitry Andric
5995bdd1243dSDimitry Andric return Actions.BuildDeclaratorGroup(DeclsInGroup);
5996bdd1243dSDimitry Andric }
5997bdd1243dSDimitry Andric
59980b57cec5SDimitry Andric /// isDeclarationSpecifier() - Return true if the current token is part of a
59990b57cec5SDimitry Andric /// declaration specifier.
60000b57cec5SDimitry Andric ///
6001bdd1243dSDimitry Andric /// \param AllowImplicitTypename whether this is a context where T::type [T
6002bdd1243dSDimitry Andric /// dependent] can appear.
60030b57cec5SDimitry Andric /// \param DisambiguatingWithExpression True to indicate that the purpose of
60040b57cec5SDimitry Andric /// this check is to disambiguate between an expression and a declaration.
isDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,bool DisambiguatingWithExpression)6005bdd1243dSDimitry Andric bool Parser::isDeclarationSpecifier(
6006bdd1243dSDimitry Andric ImplicitTypenameContext AllowImplicitTypename,
6007bdd1243dSDimitry Andric bool DisambiguatingWithExpression) {
60080b57cec5SDimitry Andric switch (Tok.getKind()) {
60090b57cec5SDimitry Andric default: return false;
60100b57cec5SDimitry Andric
60116e75b2fbSDimitry Andric // OpenCL 2.0 and later define this keyword.
60120b57cec5SDimitry Andric case tok::kw_pipe:
6013349cc55cSDimitry Andric return getLangOpts().OpenCL &&
6014349cc55cSDimitry Andric getLangOpts().getOpenCLCompatibleVersion() >= 200;
60150b57cec5SDimitry Andric
60160b57cec5SDimitry Andric case tok::identifier: // foo::bar
60170b57cec5SDimitry Andric // Unfortunate hack to support "Class.factoryMethod" notation.
60180b57cec5SDimitry Andric if (getLangOpts().ObjC && NextToken().is(tok::period))
60190b57cec5SDimitry Andric return false;
60200b57cec5SDimitry Andric if (TryAltiVecVectorToken())
60210b57cec5SDimitry Andric return true;
6022bdd1243dSDimitry Andric [[fallthrough]];
60230b57cec5SDimitry Andric case tok::kw_decltype: // decltype(T())::type
60240b57cec5SDimitry Andric case tok::kw_typename: // typename T::type
60250b57cec5SDimitry Andric // Annotate typenames and C++ scope specifiers. If we get one, just
60260b57cec5SDimitry Andric // recurse to handle whatever we get.
6027bdd1243dSDimitry Andric if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))
60280b57cec5SDimitry Andric return true;
602913138422SDimitry Andric if (TryAnnotateTypeConstraint())
603013138422SDimitry Andric return true;
60310b57cec5SDimitry Andric if (Tok.is(tok::identifier))
60320b57cec5SDimitry Andric return false;
60330b57cec5SDimitry Andric
60340b57cec5SDimitry Andric // If we're in Objective-C and we have an Objective-C class type followed
60350b57cec5SDimitry Andric // by an identifier and then either ':' or ']', in a place where an
60360b57cec5SDimitry Andric // expression is permitted, then this is probably a class message send
60370b57cec5SDimitry Andric // missing the initial '['. In this case, we won't consider this to be
60380b57cec5SDimitry Andric // the start of a declaration.
60390b57cec5SDimitry Andric if (DisambiguatingWithExpression &&
60400b57cec5SDimitry Andric isStartOfObjCClassMessageMissingOpenBracket())
60410b57cec5SDimitry Andric return false;
60420b57cec5SDimitry Andric
6043bdd1243dSDimitry Andric return isDeclarationSpecifier(AllowImplicitTypename);
60440b57cec5SDimitry Andric
60450b57cec5SDimitry Andric case tok::coloncolon: // ::foo::bar
6046bdd1243dSDimitry Andric if (!getLangOpts().CPlusPlus)
6047bdd1243dSDimitry Andric return false;
60480b57cec5SDimitry Andric if (NextToken().is(tok::kw_new) || // ::new
60490b57cec5SDimitry Andric NextToken().is(tok::kw_delete)) // ::delete
60500b57cec5SDimitry Andric return false;
60510b57cec5SDimitry Andric
60520b57cec5SDimitry Andric // Annotate typenames and C++ scope specifiers. If we get one, just
60530b57cec5SDimitry Andric // recurse to handle whatever we get.
60540b57cec5SDimitry Andric if (TryAnnotateTypeOrScopeToken())
60550b57cec5SDimitry Andric return true;
6056bdd1243dSDimitry Andric return isDeclarationSpecifier(ImplicitTypenameContext::No);
60570b57cec5SDimitry Andric
60580b57cec5SDimitry Andric // storage-class-specifier
60590b57cec5SDimitry Andric case tok::kw_typedef:
60600b57cec5SDimitry Andric case tok::kw_extern:
60610b57cec5SDimitry Andric case tok::kw___private_extern__:
60620b57cec5SDimitry Andric case tok::kw_static:
60630b57cec5SDimitry Andric case tok::kw_auto:
60640b57cec5SDimitry Andric case tok::kw___auto_type:
60650b57cec5SDimitry Andric case tok::kw_register:
60660b57cec5SDimitry Andric case tok::kw___thread:
60670b57cec5SDimitry Andric case tok::kw_thread_local:
60680b57cec5SDimitry Andric case tok::kw__Thread_local:
60690b57cec5SDimitry Andric
60700b57cec5SDimitry Andric // Modules
60710b57cec5SDimitry Andric case tok::kw___module_private__:
60720b57cec5SDimitry Andric
60730b57cec5SDimitry Andric // Debugger support
60740b57cec5SDimitry Andric case tok::kw___unknown_anytype:
60750b57cec5SDimitry Andric
60760b57cec5SDimitry Andric // type-specifiers
60770b57cec5SDimitry Andric case tok::kw_short:
60780b57cec5SDimitry Andric case tok::kw_long:
60790b57cec5SDimitry Andric case tok::kw___int64:
60800b57cec5SDimitry Andric case tok::kw___int128:
60810b57cec5SDimitry Andric case tok::kw_signed:
60820b57cec5SDimitry Andric case tok::kw_unsigned:
60830b57cec5SDimitry Andric case tok::kw__Complex:
60840b57cec5SDimitry Andric case tok::kw__Imaginary:
60850b57cec5SDimitry Andric case tok::kw_void:
60860b57cec5SDimitry Andric case tok::kw_char:
60870b57cec5SDimitry Andric case tok::kw_wchar_t:
60880b57cec5SDimitry Andric case tok::kw_char8_t:
60890b57cec5SDimitry Andric case tok::kw_char16_t:
60900b57cec5SDimitry Andric case tok::kw_char32_t:
60910b57cec5SDimitry Andric
60920b57cec5SDimitry Andric case tok::kw_int:
60935ffd83dbSDimitry Andric case tok::kw__ExtInt:
60940eae32dcSDimitry Andric case tok::kw__BitInt:
60950b57cec5SDimitry Andric case tok::kw_half:
60965ffd83dbSDimitry Andric case tok::kw___bf16:
60970b57cec5SDimitry Andric case tok::kw_float:
60980b57cec5SDimitry Andric case tok::kw_double:
60990b57cec5SDimitry Andric case tok::kw__Accum:
61000b57cec5SDimitry Andric case tok::kw__Fract:
61010b57cec5SDimitry Andric case tok::kw__Float16:
61020b57cec5SDimitry Andric case tok::kw___float128:
6103349cc55cSDimitry Andric case tok::kw___ibm128:
61040b57cec5SDimitry Andric case tok::kw_bool:
61050b57cec5SDimitry Andric case tok::kw__Bool:
61060b57cec5SDimitry Andric case tok::kw__Decimal32:
61070b57cec5SDimitry Andric case tok::kw__Decimal64:
61080b57cec5SDimitry Andric case tok::kw__Decimal128:
61090b57cec5SDimitry Andric case tok::kw___vector:
61100b57cec5SDimitry Andric
61110b57cec5SDimitry Andric // struct-or-union-specifier (C99) or class-specifier (C++)
61120b57cec5SDimitry Andric case tok::kw_class:
61130b57cec5SDimitry Andric case tok::kw_struct:
61140b57cec5SDimitry Andric case tok::kw_union:
61150b57cec5SDimitry Andric case tok::kw___interface:
61160b57cec5SDimitry Andric // enum-specifier
61170b57cec5SDimitry Andric case tok::kw_enum:
61180b57cec5SDimitry Andric
61190b57cec5SDimitry Andric // type-qualifier
61200b57cec5SDimitry Andric case tok::kw_const:
61210b57cec5SDimitry Andric case tok::kw_volatile:
61220b57cec5SDimitry Andric case tok::kw_restrict:
61230b57cec5SDimitry Andric case tok::kw__Sat:
61240b57cec5SDimitry Andric
61250b57cec5SDimitry Andric // function-specifier
61260b57cec5SDimitry Andric case tok::kw_inline:
61270b57cec5SDimitry Andric case tok::kw_virtual:
61280b57cec5SDimitry Andric case tok::kw_explicit:
61290b57cec5SDimitry Andric case tok::kw__Noreturn:
61300b57cec5SDimitry Andric
61310b57cec5SDimitry Andric // alignment-specifier
61320b57cec5SDimitry Andric case tok::kw__Alignas:
61330b57cec5SDimitry Andric
61340b57cec5SDimitry Andric // friend keyword.
61350b57cec5SDimitry Andric case tok::kw_friend:
61360b57cec5SDimitry Andric
61370b57cec5SDimitry Andric // static_assert-declaration
6138d409305fSDimitry Andric case tok::kw_static_assert:
61390b57cec5SDimitry Andric case tok::kw__Static_assert:
61400b57cec5SDimitry Andric
61415f757f3fSDimitry Andric // C23/GNU typeof support.
61420b57cec5SDimitry Andric case tok::kw_typeof:
6143bdd1243dSDimitry Andric case tok::kw_typeof_unqual:
61440b57cec5SDimitry Andric
61450b57cec5SDimitry Andric // GNU attributes.
61460b57cec5SDimitry Andric case tok::kw___attribute:
61470b57cec5SDimitry Andric
61480b57cec5SDimitry Andric // C++11 decltype and constexpr.
61490b57cec5SDimitry Andric case tok::annot_decltype:
6150*0fca6ea1SDimitry Andric case tok::annot_pack_indexing_type:
61510b57cec5SDimitry Andric case tok::kw_constexpr:
61520b57cec5SDimitry Andric
6153a7dea167SDimitry Andric // C++20 consteval and constinit.
61540b57cec5SDimitry Andric case tok::kw_consteval:
6155a7dea167SDimitry Andric case tok::kw_constinit:
61560b57cec5SDimitry Andric
61570b57cec5SDimitry Andric // C11 _Atomic
61580b57cec5SDimitry Andric case tok::kw__Atomic:
61590b57cec5SDimitry Andric return true;
61600b57cec5SDimitry Andric
6161*0fca6ea1SDimitry Andric case tok::kw_alignas:
6162*0fca6ea1SDimitry Andric // alignas is a type-specifier-qualifier in C23, which is a kind of
6163*0fca6ea1SDimitry Andric // declaration-specifier. Outside of C23 mode (including in C++), it is not.
6164*0fca6ea1SDimitry Andric return getLangOpts().C23;
6165*0fca6ea1SDimitry Andric
61660b57cec5SDimitry Andric // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
61670b57cec5SDimitry Andric case tok::less:
61680b57cec5SDimitry Andric return getLangOpts().ObjC;
61690b57cec5SDimitry Andric
61700b57cec5SDimitry Andric // typedef-name
61710b57cec5SDimitry Andric case tok::annot_typename:
61720b57cec5SDimitry Andric return !DisambiguatingWithExpression ||
61730b57cec5SDimitry Andric !isStartOfObjCClassMessageMissingOpenBracket();
61740b57cec5SDimitry Andric
6175480093f4SDimitry Andric // placeholder-type-specifier
6176480093f4SDimitry Andric case tok::annot_template_id: {
61775ffd83dbSDimitry Andric TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
61785ffd83dbSDimitry Andric if (TemplateId->hasInvalidName())
61795ffd83dbSDimitry Andric return true;
61805ffd83dbSDimitry Andric // FIXME: What about type templates that have only been annotated as
61815ffd83dbSDimitry Andric // annot_template_id, not as annot_typename?
618213138422SDimitry Andric return isTypeConstraintAnnotation() &&
6183480093f4SDimitry Andric (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));
6184480093f4SDimitry Andric }
61855ffd83dbSDimitry Andric
61865ffd83dbSDimitry Andric case tok::annot_cxxscope: {
61875ffd83dbSDimitry Andric TemplateIdAnnotation *TemplateId =
61885ffd83dbSDimitry Andric NextToken().is(tok::annot_template_id)
61895ffd83dbSDimitry Andric ? takeTemplateIdAnnotation(NextToken())
61905ffd83dbSDimitry Andric : nullptr;
61915ffd83dbSDimitry Andric if (TemplateId && TemplateId->hasInvalidName())
61925ffd83dbSDimitry Andric return true;
61935ffd83dbSDimitry Andric // FIXME: What about type templates that have only been annotated as
61945ffd83dbSDimitry Andric // annot_template_id, not as annot_typename?
619513138422SDimitry Andric if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())
619613138422SDimitry Andric return true;
619713138422SDimitry Andric return isTypeConstraintAnnotation() &&
619813138422SDimitry Andric GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);
61995ffd83dbSDimitry Andric }
62005ffd83dbSDimitry Andric
62010b57cec5SDimitry Andric case tok::kw___declspec:
62020b57cec5SDimitry Andric case tok::kw___cdecl:
62030b57cec5SDimitry Andric case tok::kw___stdcall:
62040b57cec5SDimitry Andric case tok::kw___fastcall:
62050b57cec5SDimitry Andric case tok::kw___thiscall:
62060b57cec5SDimitry Andric case tok::kw___regcall:
62070b57cec5SDimitry Andric case tok::kw___vectorcall:
62080b57cec5SDimitry Andric case tok::kw___w64:
62090b57cec5SDimitry Andric case tok::kw___sptr:
62100b57cec5SDimitry Andric case tok::kw___uptr:
62110b57cec5SDimitry Andric case tok::kw___ptr64:
62120b57cec5SDimitry Andric case tok::kw___ptr32:
62130b57cec5SDimitry Andric case tok::kw___forceinline:
62140b57cec5SDimitry Andric case tok::kw___pascal:
62150b57cec5SDimitry Andric case tok::kw___unaligned:
62160b57cec5SDimitry Andric
62170b57cec5SDimitry Andric case tok::kw__Nonnull:
62180b57cec5SDimitry Andric case tok::kw__Nullable:
6219e8d8bef9SDimitry Andric case tok::kw__Nullable_result:
62200b57cec5SDimitry Andric case tok::kw__Null_unspecified:
62210b57cec5SDimitry Andric
62220b57cec5SDimitry Andric case tok::kw___kindof:
62230b57cec5SDimitry Andric
62240b57cec5SDimitry Andric case tok::kw___private:
62250b57cec5SDimitry Andric case tok::kw___local:
62260b57cec5SDimitry Andric case tok::kw___global:
62270b57cec5SDimitry Andric case tok::kw___constant:
62280b57cec5SDimitry Andric case tok::kw___generic:
62290b57cec5SDimitry Andric case tok::kw___read_only:
62300b57cec5SDimitry Andric case tok::kw___read_write:
62310b57cec5SDimitry Andric case tok::kw___write_only:
62320b57cec5SDimitry Andric #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
62330b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
62340b57cec5SDimitry Andric
623506c3fb27SDimitry Andric case tok::kw___funcref:
6236bdd1243dSDimitry Andric case tok::kw_groupshared:
62370b57cec5SDimitry Andric return true;
62380b57cec5SDimitry Andric
62390b57cec5SDimitry Andric case tok::kw_private:
62400b57cec5SDimitry Andric return getLangOpts().OpenCL;
62410b57cec5SDimitry Andric }
62420b57cec5SDimitry Andric }
62430b57cec5SDimitry Andric
isConstructorDeclarator(bool IsUnqualified,bool DeductionGuide,DeclSpec::FriendSpecified IsFriend,const ParsedTemplateInfo * TemplateInfo)6244bdd1243dSDimitry Andric bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide,
624506c3fb27SDimitry Andric DeclSpec::FriendSpecified IsFriend,
624606c3fb27SDimitry Andric const ParsedTemplateInfo *TemplateInfo) {
62475f757f3fSDimitry Andric RevertingTentativeParsingAction TPA(*this);
62480b57cec5SDimitry Andric // Parse the C++ scope specifier.
62490b57cec5SDimitry Andric CXXScopeSpec SS;
625006c3fb27SDimitry Andric if (TemplateInfo && TemplateInfo->TemplateParams)
625106c3fb27SDimitry Andric SS.setTemplateParamLists(*TemplateInfo->TemplateParams);
625206c3fb27SDimitry Andric
62535ffd83dbSDimitry Andric if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
625404eeddc0SDimitry Andric /*ObjectHasErrors=*/false,
62550b57cec5SDimitry Andric /*EnteringContext=*/true)) {
62560b57cec5SDimitry Andric return false;
62570b57cec5SDimitry Andric }
62580b57cec5SDimitry Andric
62590b57cec5SDimitry Andric // Parse the constructor name.
62600b57cec5SDimitry Andric if (Tok.is(tok::identifier)) {
62610b57cec5SDimitry Andric // We already know that we have a constructor name; just consume
62620b57cec5SDimitry Andric // the token.
62630b57cec5SDimitry Andric ConsumeToken();
62640b57cec5SDimitry Andric } else if (Tok.is(tok::annot_template_id)) {
62650b57cec5SDimitry Andric ConsumeAnnotationToken();
62660b57cec5SDimitry Andric } else {
62670b57cec5SDimitry Andric return false;
62680b57cec5SDimitry Andric }
62690b57cec5SDimitry Andric
62700b57cec5SDimitry Andric // There may be attributes here, appertaining to the constructor name or type
62710b57cec5SDimitry Andric // we just stepped past.
62720b57cec5SDimitry Andric SkipCXX11Attributes();
62730b57cec5SDimitry Andric
62740b57cec5SDimitry Andric // Current class name must be followed by a left parenthesis.
62750b57cec5SDimitry Andric if (Tok.isNot(tok::l_paren)) {
62760b57cec5SDimitry Andric return false;
62770b57cec5SDimitry Andric }
62780b57cec5SDimitry Andric ConsumeParen();
62790b57cec5SDimitry Andric
62800b57cec5SDimitry Andric // A right parenthesis, or ellipsis followed by a right parenthesis signals
62810b57cec5SDimitry Andric // that we have a constructor.
62820b57cec5SDimitry Andric if (Tok.is(tok::r_paren) ||
62830b57cec5SDimitry Andric (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) {
62840b57cec5SDimitry Andric return true;
62850b57cec5SDimitry Andric }
62860b57cec5SDimitry Andric
62870b57cec5SDimitry Andric // A C++11 attribute here signals that we have a constructor, and is an
62880b57cec5SDimitry Andric // attribute on the first constructor parameter.
62890b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11 &&
62900b57cec5SDimitry Andric isCXX11AttributeSpecifier(/*Disambiguate*/ false,
62910b57cec5SDimitry Andric /*OuterMightBeMessageSend*/ true)) {
62920b57cec5SDimitry Andric return true;
62930b57cec5SDimitry Andric }
62940b57cec5SDimitry Andric
62950b57cec5SDimitry Andric // If we need to, enter the specified scope.
62960b57cec5SDimitry Andric DeclaratorScopeObj DeclScopeObj(*this, SS);
62970b57cec5SDimitry Andric if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
62980b57cec5SDimitry Andric DeclScopeObj.EnterDeclaratorScope();
62990b57cec5SDimitry Andric
63000b57cec5SDimitry Andric // Optionally skip Microsoft attributes.
63010b57cec5SDimitry Andric ParsedAttributes Attrs(AttrFactory);
63020b57cec5SDimitry Andric MaybeParseMicrosoftAttributes(Attrs);
63030b57cec5SDimitry Andric
63040b57cec5SDimitry Andric // Check whether the next token(s) are part of a declaration
63050b57cec5SDimitry Andric // specifier, in which case we have the start of a parameter and,
63060b57cec5SDimitry Andric // therefore, we know that this is a constructor.
6307bdd1243dSDimitry Andric // Due to an ambiguity with implicit typename, the above is not enough.
6308bdd1243dSDimitry Andric // Additionally, check to see if we are a friend.
630906c3fb27SDimitry Andric // If we parsed a scope specifier as well as friend,
631006c3fb27SDimitry Andric // we might be parsing a friend constructor.
63110b57cec5SDimitry Andric bool IsConstructor = false;
63125f757f3fSDimitry Andric ImplicitTypenameContext ITC = IsFriend && !SS.isSet()
631306c3fb27SDimitry Andric ? ImplicitTypenameContext::No
63145f757f3fSDimitry Andric : ImplicitTypenameContext::Yes;
63155f757f3fSDimitry Andric // Constructors cannot have this parameters, but we support that scenario here
63165f757f3fSDimitry Andric // to improve diagnostic.
63175f757f3fSDimitry Andric if (Tok.is(tok::kw_this)) {
63185f757f3fSDimitry Andric ConsumeToken();
63195f757f3fSDimitry Andric return isDeclarationSpecifier(ITC);
63205f757f3fSDimitry Andric }
63215f757f3fSDimitry Andric
63225f757f3fSDimitry Andric if (isDeclarationSpecifier(ITC))
63230b57cec5SDimitry Andric IsConstructor = true;
63240b57cec5SDimitry Andric else if (Tok.is(tok::identifier) ||
63250b57cec5SDimitry Andric (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) {
63260b57cec5SDimitry Andric // We've seen "C ( X" or "C ( X::Y", but "X" / "X::Y" is not a type.
63270b57cec5SDimitry Andric // This might be a parenthesized member name, but is more likely to
63280b57cec5SDimitry Andric // be a constructor declaration with an invalid argument type. Keep
63290b57cec5SDimitry Andric // looking.
63300b57cec5SDimitry Andric if (Tok.is(tok::annot_cxxscope))
63310b57cec5SDimitry Andric ConsumeAnnotationToken();
63320b57cec5SDimitry Andric ConsumeToken();
63330b57cec5SDimitry Andric
63340b57cec5SDimitry Andric // If this is not a constructor, we must be parsing a declarator,
63350b57cec5SDimitry Andric // which must have one of the following syntactic forms (see the
63360b57cec5SDimitry Andric // grammar extract at the start of ParseDirectDeclarator):
63370b57cec5SDimitry Andric switch (Tok.getKind()) {
63380b57cec5SDimitry Andric case tok::l_paren:
63390b57cec5SDimitry Andric // C(X ( int));
63400b57cec5SDimitry Andric case tok::l_square:
63410b57cec5SDimitry Andric // C(X [ 5]);
63420b57cec5SDimitry Andric // C(X [ [attribute]]);
63430b57cec5SDimitry Andric case tok::coloncolon:
63440b57cec5SDimitry Andric // C(X :: Y);
63450b57cec5SDimitry Andric // C(X :: *p);
63460b57cec5SDimitry Andric // Assume this isn't a constructor, rather than assuming it's a
63470b57cec5SDimitry Andric // constructor with an unnamed parameter of an ill-formed type.
63480b57cec5SDimitry Andric break;
63490b57cec5SDimitry Andric
63500b57cec5SDimitry Andric case tok::r_paren:
63510b57cec5SDimitry Andric // C(X )
63520b57cec5SDimitry Andric
63530b57cec5SDimitry Andric // Skip past the right-paren and any following attributes to get to
63540b57cec5SDimitry Andric // the function body or trailing-return-type.
63550b57cec5SDimitry Andric ConsumeParen();
63560b57cec5SDimitry Andric SkipCXX11Attributes();
63570b57cec5SDimitry Andric
63580b57cec5SDimitry Andric if (DeductionGuide) {
63590b57cec5SDimitry Andric // C(X) -> ... is a deduction guide.
63600b57cec5SDimitry Andric IsConstructor = Tok.is(tok::arrow);
63610b57cec5SDimitry Andric break;
63620b57cec5SDimitry Andric }
63630b57cec5SDimitry Andric if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
63640b57cec5SDimitry Andric // Assume these were meant to be constructors:
63650b57cec5SDimitry Andric // C(X) : (the name of a bit-field cannot be parenthesized).
63660b57cec5SDimitry Andric // C(X) try (this is otherwise ill-formed).
63670b57cec5SDimitry Andric IsConstructor = true;
63680b57cec5SDimitry Andric }
63690b57cec5SDimitry Andric if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) {
63700b57cec5SDimitry Andric // If we have a constructor name within the class definition,
63710b57cec5SDimitry Andric // assume these were meant to be constructors:
63720b57cec5SDimitry Andric // C(X) {
63730b57cec5SDimitry Andric // C(X) ;
63740b57cec5SDimitry Andric // ... because otherwise we would be declaring a non-static data
63750b57cec5SDimitry Andric // member that is ill-formed because it's of the same type as its
63760b57cec5SDimitry Andric // surrounding class.
63770b57cec5SDimitry Andric //
63780b57cec5SDimitry Andric // FIXME: We can actually do this whether or not the name is qualified,
63790b57cec5SDimitry Andric // because if it is qualified in this context it must be being used as
63800b57cec5SDimitry Andric // a constructor name.
63810b57cec5SDimitry Andric // currently, so we're somewhat conservative here.
63820b57cec5SDimitry Andric IsConstructor = IsUnqualified;
63830b57cec5SDimitry Andric }
63840b57cec5SDimitry Andric break;
63850b57cec5SDimitry Andric
63860b57cec5SDimitry Andric default:
63870b57cec5SDimitry Andric IsConstructor = true;
63880b57cec5SDimitry Andric break;
63890b57cec5SDimitry Andric }
63900b57cec5SDimitry Andric }
63910b57cec5SDimitry Andric return IsConstructor;
63920b57cec5SDimitry Andric }
63930b57cec5SDimitry Andric
63940b57cec5SDimitry Andric /// ParseTypeQualifierListOpt
63950b57cec5SDimitry Andric /// type-qualifier-list: [C99 6.7.5]
63960b57cec5SDimitry Andric /// type-qualifier
63970b57cec5SDimitry Andric /// [vendor] attributes
63980b57cec5SDimitry Andric /// [ only if AttrReqs & AR_VendorAttributesParsed ]
63990b57cec5SDimitry Andric /// type-qualifier-list type-qualifier
64000b57cec5SDimitry Andric /// [vendor] type-qualifier-list attributes
64010b57cec5SDimitry Andric /// [ only if AttrReqs & AR_VendorAttributesParsed ]
64020b57cec5SDimitry Andric /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
64030b57cec5SDimitry Andric /// [ only if AttReqs & AR_CXX11AttributesParsed ]
64040b57cec5SDimitry Andric /// Note: vendor can be GNU, MS, etc and can be explicitly controlled via
64050b57cec5SDimitry Andric /// AttrRequirements bitmask values.
ParseTypeQualifierListOpt(DeclSpec & DS,unsigned AttrReqs,bool AtomicAllowed,bool IdentifierRequired,std::optional<llvm::function_ref<void ()>> CodeCompletionHandler)64060b57cec5SDimitry Andric void Parser::ParseTypeQualifierListOpt(
64070b57cec5SDimitry Andric DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
64080b57cec5SDimitry Andric bool IdentifierRequired,
6409bdd1243dSDimitry Andric std::optional<llvm::function_ref<void()>> CodeCompletionHandler) {
641006c3fb27SDimitry Andric if ((AttrReqs & AR_CXX11AttributesParsed) &&
641106c3fb27SDimitry Andric isAllowedCXX11AttributeSpecifier()) {
641281ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory);
641381ad6265SDimitry Andric ParseCXX11Attributes(Attrs);
641481ad6265SDimitry Andric DS.takeAttributesFrom(Attrs);
64150b57cec5SDimitry Andric }
64160b57cec5SDimitry Andric
64170b57cec5SDimitry Andric SourceLocation EndLoc;
64180b57cec5SDimitry Andric
641904eeddc0SDimitry Andric while (true) {
64200b57cec5SDimitry Andric bool isInvalid = false;
64210b57cec5SDimitry Andric const char *PrevSpec = nullptr;
64220b57cec5SDimitry Andric unsigned DiagID = 0;
64230b57cec5SDimitry Andric SourceLocation Loc = Tok.getLocation();
64240b57cec5SDimitry Andric
64250b57cec5SDimitry Andric switch (Tok.getKind()) {
64260b57cec5SDimitry Andric case tok::code_completion:
6427fe6060f1SDimitry Andric cutOffParsing();
64280b57cec5SDimitry Andric if (CodeCompletionHandler)
64290b57cec5SDimitry Andric (*CodeCompletionHandler)();
64300b57cec5SDimitry Andric else
6431*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteTypeQualifiers(DS);
6432fe6060f1SDimitry Andric return;
64330b57cec5SDimitry Andric
64340b57cec5SDimitry Andric case tok::kw_const:
64350b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
64360b57cec5SDimitry Andric getLangOpts());
64370b57cec5SDimitry Andric break;
64380b57cec5SDimitry Andric case tok::kw_volatile:
64390b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
64400b57cec5SDimitry Andric getLangOpts());
64410b57cec5SDimitry Andric break;
64420b57cec5SDimitry Andric case tok::kw_restrict:
64430b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
64440b57cec5SDimitry Andric getLangOpts());
64450b57cec5SDimitry Andric break;
64460b57cec5SDimitry Andric case tok::kw__Atomic:
64470b57cec5SDimitry Andric if (!AtomicAllowed)
64480b57cec5SDimitry Andric goto DoneWithTypeQuals;
6449*0fca6ea1SDimitry Andric diagnoseUseOfC11Keyword(Tok);
64500b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
64510b57cec5SDimitry Andric getLangOpts());
64520b57cec5SDimitry Andric break;
64530b57cec5SDimitry Andric
64540b57cec5SDimitry Andric // OpenCL qualifiers:
64550b57cec5SDimitry Andric case tok::kw_private:
64560b57cec5SDimitry Andric if (!getLangOpts().OpenCL)
64570b57cec5SDimitry Andric goto DoneWithTypeQuals;
6458bdd1243dSDimitry Andric [[fallthrough]];
64590b57cec5SDimitry Andric case tok::kw___private:
64600b57cec5SDimitry Andric case tok::kw___global:
64610b57cec5SDimitry Andric case tok::kw___local:
64620b57cec5SDimitry Andric case tok::kw___constant:
64630b57cec5SDimitry Andric case tok::kw___generic:
64640b57cec5SDimitry Andric case tok::kw___read_only:
64650b57cec5SDimitry Andric case tok::kw___write_only:
64660b57cec5SDimitry Andric case tok::kw___read_write:
64670b57cec5SDimitry Andric ParseOpenCLQualifiers(DS.getAttributes());
64680b57cec5SDimitry Andric break;
64690b57cec5SDimitry Andric
6470bdd1243dSDimitry Andric case tok::kw_groupshared:
64715f757f3fSDimitry Andric case tok::kw_in:
64725f757f3fSDimitry Andric case tok::kw_inout:
64735f757f3fSDimitry Andric case tok::kw_out:
6474bdd1243dSDimitry Andric // NOTE: ParseHLSLQualifiers will consume the qualifier token.
6475bdd1243dSDimitry Andric ParseHLSLQualifiers(DS.getAttributes());
6476bdd1243dSDimitry Andric continue;
6477bdd1243dSDimitry Andric
64780b57cec5SDimitry Andric case tok::kw___unaligned:
64790b57cec5SDimitry Andric isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,
64800b57cec5SDimitry Andric getLangOpts());
64810b57cec5SDimitry Andric break;
64820b57cec5SDimitry Andric case tok::kw___uptr:
64830b57cec5SDimitry Andric // GNU libc headers in C mode use '__uptr' as an identifier which conflicts
64840b57cec5SDimitry Andric // with the MS modifier keyword.
64850b57cec5SDimitry Andric if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus &&
64860b57cec5SDimitry Andric IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) {
64870b57cec5SDimitry Andric if (TryKeywordIdentFallback(false))
64880b57cec5SDimitry Andric continue;
64890b57cec5SDimitry Andric }
6490bdd1243dSDimitry Andric [[fallthrough]];
64910b57cec5SDimitry Andric case tok::kw___sptr:
64920b57cec5SDimitry Andric case tok::kw___w64:
64930b57cec5SDimitry Andric case tok::kw___ptr64:
64940b57cec5SDimitry Andric case tok::kw___ptr32:
64950b57cec5SDimitry Andric case tok::kw___cdecl:
64960b57cec5SDimitry Andric case tok::kw___stdcall:
64970b57cec5SDimitry Andric case tok::kw___fastcall:
64980b57cec5SDimitry Andric case tok::kw___thiscall:
64990b57cec5SDimitry Andric case tok::kw___regcall:
65000b57cec5SDimitry Andric case tok::kw___vectorcall:
65010b57cec5SDimitry Andric if (AttrReqs & AR_DeclspecAttributesParsed) {
65020b57cec5SDimitry Andric ParseMicrosoftTypeAttributes(DS.getAttributes());
65030b57cec5SDimitry Andric continue;
65040b57cec5SDimitry Andric }
65050b57cec5SDimitry Andric goto DoneWithTypeQuals;
650606c3fb27SDimitry Andric
650706c3fb27SDimitry Andric case tok::kw___funcref:
650806c3fb27SDimitry Andric ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes());
650906c3fb27SDimitry Andric continue;
651006c3fb27SDimitry Andric goto DoneWithTypeQuals;
651106c3fb27SDimitry Andric
65120b57cec5SDimitry Andric case tok::kw___pascal:
65130b57cec5SDimitry Andric if (AttrReqs & AR_VendorAttributesParsed) {
65140b57cec5SDimitry Andric ParseBorlandTypeAttributes(DS.getAttributes());
65150b57cec5SDimitry Andric continue;
65160b57cec5SDimitry Andric }
65170b57cec5SDimitry Andric goto DoneWithTypeQuals;
65180b57cec5SDimitry Andric
65190b57cec5SDimitry Andric // Nullability type specifiers.
65200b57cec5SDimitry Andric case tok::kw__Nonnull:
65210b57cec5SDimitry Andric case tok::kw__Nullable:
6522e8d8bef9SDimitry Andric case tok::kw__Nullable_result:
65230b57cec5SDimitry Andric case tok::kw__Null_unspecified:
65240b57cec5SDimitry Andric ParseNullabilityTypeSpecifiers(DS.getAttributes());
65250b57cec5SDimitry Andric continue;
65260b57cec5SDimitry Andric
65270b57cec5SDimitry Andric // Objective-C 'kindof' types.
65280b57cec5SDimitry Andric case tok::kw___kindof:
65290b57cec5SDimitry Andric DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
653006c3fb27SDimitry Andric nullptr, 0, tok::kw___kindof);
65310b57cec5SDimitry Andric (void)ConsumeToken();
65320b57cec5SDimitry Andric continue;
65330b57cec5SDimitry Andric
65340b57cec5SDimitry Andric case tok::kw___attribute:
65350b57cec5SDimitry Andric if (AttrReqs & AR_GNUAttributesParsedAndRejected)
65360b57cec5SDimitry Andric // When GNU attributes are expressly forbidden, diagnose their usage.
65370b57cec5SDimitry Andric Diag(Tok, diag::err_attributes_not_allowed);
65380b57cec5SDimitry Andric
65390b57cec5SDimitry Andric // Parse the attributes even if they are rejected to ensure that error
65400b57cec5SDimitry Andric // recovery is graceful.
65410b57cec5SDimitry Andric if (AttrReqs & AR_GNUAttributesParsed ||
65420b57cec5SDimitry Andric AttrReqs & AR_GNUAttributesParsedAndRejected) {
65430b57cec5SDimitry Andric ParseGNUAttributes(DS.getAttributes());
65440b57cec5SDimitry Andric continue; // do *not* consume the next token!
65450b57cec5SDimitry Andric }
65460b57cec5SDimitry Andric // otherwise, FALL THROUGH!
6547bdd1243dSDimitry Andric [[fallthrough]];
65480b57cec5SDimitry Andric default:
65490b57cec5SDimitry Andric DoneWithTypeQuals:
65500b57cec5SDimitry Andric // If this is not a type-qualifier token, we're done reading type
65510b57cec5SDimitry Andric // qualifiers. First verify that DeclSpec's are consistent.
65520b57cec5SDimitry Andric DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
65530b57cec5SDimitry Andric if (EndLoc.isValid())
65540b57cec5SDimitry Andric DS.SetRangeEnd(EndLoc);
65550b57cec5SDimitry Andric return;
65560b57cec5SDimitry Andric }
65570b57cec5SDimitry Andric
65580b57cec5SDimitry Andric // If the specifier combination wasn't legal, issue a diagnostic.
65590b57cec5SDimitry Andric if (isInvalid) {
65600b57cec5SDimitry Andric assert(PrevSpec && "Method did not return previous specifier!");
65610b57cec5SDimitry Andric Diag(Tok, DiagID) << PrevSpec;
65620b57cec5SDimitry Andric }
65630b57cec5SDimitry Andric EndLoc = ConsumeToken();
65640b57cec5SDimitry Andric }
65650b57cec5SDimitry Andric }
65660b57cec5SDimitry Andric
65670b57cec5SDimitry Andric /// ParseDeclarator - Parse and verify a newly-initialized declarator.
ParseDeclarator(Declarator & D)65680b57cec5SDimitry Andric void Parser::ParseDeclarator(Declarator &D) {
65690b57cec5SDimitry Andric /// This implements the 'declarator' production in the C grammar, then checks
65700b57cec5SDimitry Andric /// for well-formedness and issues diagnostics.
657181ad6265SDimitry Andric Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {
65720b57cec5SDimitry Andric ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
657381ad6265SDimitry Andric });
65740b57cec5SDimitry Andric }
65750b57cec5SDimitry Andric
isPtrOperatorToken(tok::TokenKind Kind,const LangOptions & Lang,DeclaratorContext TheContext)65760b57cec5SDimitry Andric static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
65770b57cec5SDimitry Andric DeclaratorContext TheContext) {
65780b57cec5SDimitry Andric if (Kind == tok::star || Kind == tok::caret)
65790b57cec5SDimitry Andric return true;
65800b57cec5SDimitry Andric
65816e75b2fbSDimitry Andric // OpenCL 2.0 and later define this keyword.
6582349cc55cSDimitry Andric if (Kind == tok::kw_pipe && Lang.OpenCL &&
6583349cc55cSDimitry Andric Lang.getOpenCLCompatibleVersion() >= 200)
65840b57cec5SDimitry Andric return true;
65850b57cec5SDimitry Andric
65860b57cec5SDimitry Andric if (!Lang.CPlusPlus)
65870b57cec5SDimitry Andric return false;
65880b57cec5SDimitry Andric
65890b57cec5SDimitry Andric if (Kind == tok::amp)
65900b57cec5SDimitry Andric return true;
65910b57cec5SDimitry Andric
65920b57cec5SDimitry Andric // We parse rvalue refs in C++03, because otherwise the errors are scary.
65930b57cec5SDimitry Andric // But we must not parse them in conversion-type-ids and new-type-ids, since
65940b57cec5SDimitry Andric // those can be legitimately followed by a && operator.
65950b57cec5SDimitry Andric // (The same thing can in theory happen after a trailing-return-type, but
65960b57cec5SDimitry Andric // since those are a C++11 feature, there is no rejects-valid issue there.)
65970b57cec5SDimitry Andric if (Kind == tok::ampamp)
6598e8d8bef9SDimitry Andric return Lang.CPlusPlus11 || (TheContext != DeclaratorContext::ConversionId &&
6599e8d8bef9SDimitry Andric TheContext != DeclaratorContext::CXXNew);
66000b57cec5SDimitry Andric
66010b57cec5SDimitry Andric return false;
66020b57cec5SDimitry Andric }
66030b57cec5SDimitry Andric
66040b57cec5SDimitry Andric // Indicates whether the given declarator is a pipe declarator.
isPipeDeclarator(const Declarator & D)660581ad6265SDimitry Andric static bool isPipeDeclarator(const Declarator &D) {
66060b57cec5SDimitry Andric const unsigned NumTypes = D.getNumTypeObjects();
66070b57cec5SDimitry Andric
66080b57cec5SDimitry Andric for (unsigned Idx = 0; Idx != NumTypes; ++Idx)
66090b57cec5SDimitry Andric if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)
66100b57cec5SDimitry Andric return true;
66110b57cec5SDimitry Andric
66120b57cec5SDimitry Andric return false;
66130b57cec5SDimitry Andric }
66140b57cec5SDimitry Andric
66150b57cec5SDimitry Andric /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
66160b57cec5SDimitry Andric /// is parsed by the function passed to it. Pass null, and the direct-declarator
66170b57cec5SDimitry Andric /// isn't parsed at all, making this function effectively parse the C++
66180b57cec5SDimitry Andric /// ptr-operator production.
66190b57cec5SDimitry Andric ///
66200b57cec5SDimitry Andric /// If the grammar of this construct is extended, matching changes must also be
66210b57cec5SDimitry Andric /// made to TryParseDeclarator and MightBeDeclarator, and possibly to
66220b57cec5SDimitry Andric /// isConstructorDeclarator.
66230b57cec5SDimitry Andric ///
66240b57cec5SDimitry Andric /// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]
66250b57cec5SDimitry Andric /// [C] pointer[opt] direct-declarator
66260b57cec5SDimitry Andric /// [C++] direct-declarator
66270b57cec5SDimitry Andric /// [C++] ptr-operator declarator
66280b57cec5SDimitry Andric ///
66290b57cec5SDimitry Andric /// pointer: [C99 6.7.5]
66300b57cec5SDimitry Andric /// '*' type-qualifier-list[opt]
66310b57cec5SDimitry Andric /// '*' type-qualifier-list[opt] pointer
66320b57cec5SDimitry Andric ///
66330b57cec5SDimitry Andric /// ptr-operator:
66340b57cec5SDimitry Andric /// '*' cv-qualifier-seq[opt]
66350b57cec5SDimitry Andric /// '&'
66360b57cec5SDimitry Andric /// [C++0x] '&&'
66370b57cec5SDimitry Andric /// [GNU] '&' restrict[opt] attributes[opt]
66380b57cec5SDimitry Andric /// [GNU?] '&&' restrict[opt] attributes[opt]
66390b57cec5SDimitry Andric /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
ParseDeclaratorInternal(Declarator & D,DirectDeclParseFunction DirectDeclParser)66400b57cec5SDimitry Andric void Parser::ParseDeclaratorInternal(Declarator &D,
66410b57cec5SDimitry Andric DirectDeclParseFunction DirectDeclParser) {
66420b57cec5SDimitry Andric if (Diags.hasAllExtensionsSilenced())
66430b57cec5SDimitry Andric D.setExtension();
66440b57cec5SDimitry Andric
66450b57cec5SDimitry Andric // C++ member pointers start with a '::' or a nested-name.
66460b57cec5SDimitry Andric // Member pointers get special handling, since there's no place for the
66470b57cec5SDimitry Andric // scope spec in the generic path below.
66480b57cec5SDimitry Andric if (getLangOpts().CPlusPlus &&
66490b57cec5SDimitry Andric (Tok.is(tok::coloncolon) || Tok.is(tok::kw_decltype) ||
66500b57cec5SDimitry Andric (Tok.is(tok::identifier) &&
66510b57cec5SDimitry Andric (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
66520b57cec5SDimitry Andric Tok.is(tok::annot_cxxscope))) {
6653e8d8bef9SDimitry Andric bool EnteringContext = D.getContext() == DeclaratorContext::File ||
6654e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::Member;
66550b57cec5SDimitry Andric CXXScopeSpec SS;
665606c3fb27SDimitry Andric SS.setTemplateParamLists(D.getTemplateParameterLists());
66575ffd83dbSDimitry Andric ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
665804eeddc0SDimitry Andric /*ObjectHasErrors=*/false, EnteringContext);
66590b57cec5SDimitry Andric
66600b57cec5SDimitry Andric if (SS.isNotEmpty()) {
66610b57cec5SDimitry Andric if (Tok.isNot(tok::star)) {
66620b57cec5SDimitry Andric // The scope spec really belongs to the direct-declarator.
66630b57cec5SDimitry Andric if (D.mayHaveIdentifier())
66640b57cec5SDimitry Andric D.getCXXScopeSpec() = SS;
66650b57cec5SDimitry Andric else
66660b57cec5SDimitry Andric AnnotateScopeToken(SS, true);
66670b57cec5SDimitry Andric
66680b57cec5SDimitry Andric if (DirectDeclParser)
66690b57cec5SDimitry Andric (this->*DirectDeclParser)(D);
66700b57cec5SDimitry Andric return;
66710b57cec5SDimitry Andric }
66720b57cec5SDimitry Andric
6673e8d8bef9SDimitry Andric if (SS.isValid()) {
6674e8d8bef9SDimitry Andric checkCompoundToken(SS.getEndLoc(), tok::coloncolon,
6675e8d8bef9SDimitry Andric CompoundToken::MemberPtr);
6676e8d8bef9SDimitry Andric }
6677e8d8bef9SDimitry Andric
66785ffd83dbSDimitry Andric SourceLocation StarLoc = ConsumeToken();
66795ffd83dbSDimitry Andric D.SetRangeEnd(StarLoc);
66800b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
66810b57cec5SDimitry Andric ParseTypeQualifierListOpt(DS);
66820b57cec5SDimitry Andric D.ExtendWithDeclSpec(DS);
66830b57cec5SDimitry Andric
66840b57cec5SDimitry Andric // Recurse to parse whatever is left.
668581ad6265SDimitry Andric Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {
66860b57cec5SDimitry Andric ParseDeclaratorInternal(D, DirectDeclParser);
668781ad6265SDimitry Andric });
66880b57cec5SDimitry Andric
66890b57cec5SDimitry Andric // Sema will have to catch (syntactically invalid) pointers into global
66900b57cec5SDimitry Andric // scope. It has to catch pointers into namespace scope anyway.
66910b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
66925ffd83dbSDimitry Andric SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()),
66930b57cec5SDimitry Andric std::move(DS.getAttributes()),
66940b57cec5SDimitry Andric /* Don't replace range end. */ SourceLocation());
66950b57cec5SDimitry Andric return;
66960b57cec5SDimitry Andric }
66970b57cec5SDimitry Andric }
66980b57cec5SDimitry Andric
66990b57cec5SDimitry Andric tok::TokenKind Kind = Tok.getKind();
67000b57cec5SDimitry Andric
670181ad6265SDimitry Andric if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclarator(D)) {
67020b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
67030b57cec5SDimitry Andric ParseTypeQualifierListOpt(DS);
67040b57cec5SDimitry Andric
67050b57cec5SDimitry Andric D.AddTypeInfo(
67060b57cec5SDimitry Andric DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
67070b57cec5SDimitry Andric std::move(DS.getAttributes()), SourceLocation());
67080b57cec5SDimitry Andric }
67090b57cec5SDimitry Andric
67100b57cec5SDimitry Andric // Not a pointer, C++ reference, or block.
67110b57cec5SDimitry Andric if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {
67120b57cec5SDimitry Andric if (DirectDeclParser)
67130b57cec5SDimitry Andric (this->*DirectDeclParser)(D);
67140b57cec5SDimitry Andric return;
67150b57cec5SDimitry Andric }
67160b57cec5SDimitry Andric
67170b57cec5SDimitry Andric // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,
67180b57cec5SDimitry Andric // '&&' -> rvalue reference
67190b57cec5SDimitry Andric SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&.
67200b57cec5SDimitry Andric D.SetRangeEnd(Loc);
67210b57cec5SDimitry Andric
67220b57cec5SDimitry Andric if (Kind == tok::star || Kind == tok::caret) {
67230b57cec5SDimitry Andric // Is a pointer.
67240b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
67250b57cec5SDimitry Andric
67260b57cec5SDimitry Andric // GNU attributes are not allowed here in a new-type-id, but Declspec and
67270b57cec5SDimitry Andric // C++11 attributes are allowed.
67280b57cec5SDimitry Andric unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |
6729e8d8bef9SDimitry Andric ((D.getContext() != DeclaratorContext::CXXNew)
67300b57cec5SDimitry Andric ? AR_GNUAttributesParsed
67310b57cec5SDimitry Andric : AR_GNUAttributesParsedAndRejected);
67320b57cec5SDimitry Andric ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());
67330b57cec5SDimitry Andric D.ExtendWithDeclSpec(DS);
67340b57cec5SDimitry Andric
67350b57cec5SDimitry Andric // Recursively parse the declarator.
673681ad6265SDimitry Andric Actions.runWithSufficientStackSpace(
673781ad6265SDimitry Andric D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });
67380b57cec5SDimitry Andric if (Kind == tok::star)
67390b57cec5SDimitry Andric // Remember that we parsed a pointer type, and remember the type-quals.
67400b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getPointer(
67410b57cec5SDimitry Andric DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(),
67420b57cec5SDimitry Andric DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(),
67430b57cec5SDimitry Andric DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()),
67440b57cec5SDimitry Andric std::move(DS.getAttributes()), SourceLocation());
67450b57cec5SDimitry Andric else
67460b57cec5SDimitry Andric // Remember that we parsed a Block type, and remember the type-quals.
67470b57cec5SDimitry Andric D.AddTypeInfo(
67480b57cec5SDimitry Andric DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc),
67490b57cec5SDimitry Andric std::move(DS.getAttributes()), SourceLocation());
67500b57cec5SDimitry Andric } else {
67510b57cec5SDimitry Andric // Is a reference
67520b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
67530b57cec5SDimitry Andric
67540b57cec5SDimitry Andric // Complain about rvalue references in C++03, but then go on and build
67550b57cec5SDimitry Andric // the declarator.
67560b57cec5SDimitry Andric if (Kind == tok::ampamp)
67570b57cec5SDimitry Andric Diag(Loc, getLangOpts().CPlusPlus11 ?
67580b57cec5SDimitry Andric diag::warn_cxx98_compat_rvalue_reference :
67590b57cec5SDimitry Andric diag::ext_rvalue_reference);
67600b57cec5SDimitry Andric
67610b57cec5SDimitry Andric // GNU-style and C++11 attributes are allowed here, as is restrict.
67620b57cec5SDimitry Andric ParseTypeQualifierListOpt(DS);
67630b57cec5SDimitry Andric D.ExtendWithDeclSpec(DS);
67640b57cec5SDimitry Andric
67650b57cec5SDimitry Andric // C++ 8.3.2p1: cv-qualified references are ill-formed except when the
67660b57cec5SDimitry Andric // cv-qualifiers are introduced through the use of a typedef or of a
67670b57cec5SDimitry Andric // template type argument, in which case the cv-qualifiers are ignored.
67680b57cec5SDimitry Andric if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
67690b57cec5SDimitry Andric if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
67700b57cec5SDimitry Andric Diag(DS.getConstSpecLoc(),
67710b57cec5SDimitry Andric diag::err_invalid_reference_qualifier_application) << "const";
67720b57cec5SDimitry Andric if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
67730b57cec5SDimitry Andric Diag(DS.getVolatileSpecLoc(),
67740b57cec5SDimitry Andric diag::err_invalid_reference_qualifier_application) << "volatile";
67750b57cec5SDimitry Andric // 'restrict' is permitted as an extension.
67760b57cec5SDimitry Andric if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
67770b57cec5SDimitry Andric Diag(DS.getAtomicSpecLoc(),
67780b57cec5SDimitry Andric diag::err_invalid_reference_qualifier_application) << "_Atomic";
67790b57cec5SDimitry Andric }
67800b57cec5SDimitry Andric
67810b57cec5SDimitry Andric // Recursively parse the declarator.
678281ad6265SDimitry Andric Actions.runWithSufficientStackSpace(
678381ad6265SDimitry Andric D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });
67840b57cec5SDimitry Andric
67850b57cec5SDimitry Andric if (D.getNumTypeObjects() > 0) {
67860b57cec5SDimitry Andric // C++ [dcl.ref]p4: There shall be no references to references.
67870b57cec5SDimitry Andric DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);
67880b57cec5SDimitry Andric if (InnerChunk.Kind == DeclaratorChunk::Reference) {
67890b57cec5SDimitry Andric if (const IdentifierInfo *II = D.getIdentifier())
67900b57cec5SDimitry Andric Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
67910b57cec5SDimitry Andric << II;
67920b57cec5SDimitry Andric else
67930b57cec5SDimitry Andric Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
67940b57cec5SDimitry Andric << "type name";
67950b57cec5SDimitry Andric
67960b57cec5SDimitry Andric // Once we've complained about the reference-to-reference, we
67970b57cec5SDimitry Andric // can go ahead and build the (technically ill-formed)
67980b57cec5SDimitry Andric // declarator: reference collapsing will take care of it.
67990b57cec5SDimitry Andric }
68000b57cec5SDimitry Andric }
68010b57cec5SDimitry Andric
68020b57cec5SDimitry Andric // Remember that we parsed a reference type.
68030b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
68040b57cec5SDimitry Andric Kind == tok::amp),
68050b57cec5SDimitry Andric std::move(DS.getAttributes()), SourceLocation());
68060b57cec5SDimitry Andric }
68070b57cec5SDimitry Andric }
68080b57cec5SDimitry Andric
68090b57cec5SDimitry Andric // When correcting from misplaced brackets before the identifier, the location
68100b57cec5SDimitry Andric // is saved inside the declarator so that other diagnostic messages can use
68110b57cec5SDimitry Andric // them. This extracts and returns that location, or returns the provided
68120b57cec5SDimitry Andric // location if a stored location does not exist.
getMissingDeclaratorIdLoc(Declarator & D,SourceLocation Loc)68130b57cec5SDimitry Andric static SourceLocation getMissingDeclaratorIdLoc(Declarator &D,
68140b57cec5SDimitry Andric SourceLocation Loc) {
68150b57cec5SDimitry Andric if (D.getName().StartLocation.isInvalid() &&
68160b57cec5SDimitry Andric D.getName().EndLocation.isValid())
68170b57cec5SDimitry Andric return D.getName().EndLocation;
68180b57cec5SDimitry Andric
68190b57cec5SDimitry Andric return Loc;
68200b57cec5SDimitry Andric }
68210b57cec5SDimitry Andric
68220b57cec5SDimitry Andric /// ParseDirectDeclarator
68230b57cec5SDimitry Andric /// direct-declarator: [C99 6.7.5]
68240b57cec5SDimitry Andric /// [C99] identifier
68250b57cec5SDimitry Andric /// '(' declarator ')'
68260b57cec5SDimitry Andric /// [GNU] '(' attributes declarator ')'
68270b57cec5SDimitry Andric /// [C90] direct-declarator '[' constant-expression[opt] ']'
68280b57cec5SDimitry Andric /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
68290b57cec5SDimitry Andric /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
68300b57cec5SDimitry Andric /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
68310b57cec5SDimitry Andric /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
68320b57cec5SDimitry Andric /// [C++11] direct-declarator '[' constant-expression[opt] ']'
68330b57cec5SDimitry Andric /// attribute-specifier-seq[opt]
68340b57cec5SDimitry Andric /// direct-declarator '(' parameter-type-list ')'
68350b57cec5SDimitry Andric /// direct-declarator '(' identifier-list[opt] ')'
68360b57cec5SDimitry Andric /// [GNU] direct-declarator '(' parameter-forward-declarations
68370b57cec5SDimitry Andric /// parameter-type-list[opt] ')'
68380b57cec5SDimitry Andric /// [C++] direct-declarator '(' parameter-declaration-clause ')'
68390b57cec5SDimitry Andric /// cv-qualifier-seq[opt] exception-specification[opt]
68400b57cec5SDimitry Andric /// [C++11] direct-declarator '(' parameter-declaration-clause ')'
68410b57cec5SDimitry Andric /// attribute-specifier-seq[opt] cv-qualifier-seq[opt]
68420b57cec5SDimitry Andric /// ref-qualifier[opt] exception-specification[opt]
68430b57cec5SDimitry Andric /// [C++] declarator-id
68440b57cec5SDimitry Andric /// [C++11] declarator-id attribute-specifier-seq[opt]
68450b57cec5SDimitry Andric ///
68460b57cec5SDimitry Andric /// declarator-id: [C++ 8]
68470b57cec5SDimitry Andric /// '...'[opt] id-expression
68480b57cec5SDimitry Andric /// '::'[opt] nested-name-specifier[opt] type-name
68490b57cec5SDimitry Andric ///
68500b57cec5SDimitry Andric /// id-expression: [C++ 5.1]
68510b57cec5SDimitry Andric /// unqualified-id
68520b57cec5SDimitry Andric /// qualified-id
68530b57cec5SDimitry Andric ///
68540b57cec5SDimitry Andric /// unqualified-id: [C++ 5.1]
68550b57cec5SDimitry Andric /// identifier
68560b57cec5SDimitry Andric /// operator-function-id
68570b57cec5SDimitry Andric /// conversion-function-id
68580b57cec5SDimitry Andric /// '~' class-name
68590b57cec5SDimitry Andric /// template-id
68600b57cec5SDimitry Andric ///
68610b57cec5SDimitry Andric /// C++17 adds the following, which we also handle here:
68620b57cec5SDimitry Andric ///
68630b57cec5SDimitry Andric /// simple-declaration:
68640b57cec5SDimitry Andric /// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';'
68650b57cec5SDimitry Andric ///
68660b57cec5SDimitry Andric /// Note, any additional constructs added here may need corresponding changes
68670b57cec5SDimitry Andric /// in isConstructorDeclarator.
ParseDirectDeclarator(Declarator & D)68680b57cec5SDimitry Andric void Parser::ParseDirectDeclarator(Declarator &D) {
68690b57cec5SDimitry Andric DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
68700b57cec5SDimitry Andric
68710b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
68720b57cec5SDimitry Andric // This might be a C++17 structured binding.
68730b57cec5SDimitry Andric if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() &&
68740b57cec5SDimitry Andric D.getCXXScopeSpec().isEmpty())
68750b57cec5SDimitry Andric return ParseDecompositionDeclarator(D);
68760b57cec5SDimitry Andric
68770b57cec5SDimitry Andric // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
68780b57cec5SDimitry Andric // this context it is a bitfield. Also in range-based for statement colon
68790b57cec5SDimitry Andric // may delimit for-range-declaration.
68800b57cec5SDimitry Andric ColonProtectionRAIIObject X(
6881e8d8bef9SDimitry Andric *this, D.getContext() == DeclaratorContext::Member ||
6882e8d8bef9SDimitry Andric (D.getContext() == DeclaratorContext::ForInit &&
68830b57cec5SDimitry Andric getLangOpts().CPlusPlus11));
68840b57cec5SDimitry Andric
68850b57cec5SDimitry Andric // ParseDeclaratorInternal might already have parsed the scope.
68860b57cec5SDimitry Andric if (D.getCXXScopeSpec().isEmpty()) {
6887e8d8bef9SDimitry Andric bool EnteringContext = D.getContext() == DeclaratorContext::File ||
6888e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::Member;
68895ffd83dbSDimitry Andric ParseOptionalCXXScopeSpecifier(
68905ffd83dbSDimitry Andric D.getCXXScopeSpec(), /*ObjectType=*/nullptr,
689104eeddc0SDimitry Andric /*ObjectHasErrors=*/false, EnteringContext);
68920b57cec5SDimitry Andric }
68930b57cec5SDimitry Andric
6894*0fca6ea1SDimitry Andric // C++23 [basic.scope.namespace]p1:
6895*0fca6ea1SDimitry Andric // For each non-friend redeclaration or specialization whose target scope
6896*0fca6ea1SDimitry Andric // is or is contained by the scope, the portion after the declarator-id,
6897*0fca6ea1SDimitry Andric // class-head-name, or enum-head-name is also included in the scope.
6898*0fca6ea1SDimitry Andric // C++23 [basic.scope.class]p1:
6899*0fca6ea1SDimitry Andric // For each non-friend redeclaration or specialization whose target scope
6900*0fca6ea1SDimitry Andric // is or is contained by the scope, the portion after the declarator-id,
6901*0fca6ea1SDimitry Andric // class-head-name, or enum-head-name is also included in the scope.
6902*0fca6ea1SDimitry Andric //
6903*0fca6ea1SDimitry Andric // FIXME: We should not be doing this for friend declarations; they have
6904*0fca6ea1SDimitry Andric // their own special lookup semantics specified by [basic.lookup.unqual]p6.
69050b57cec5SDimitry Andric if (D.getCXXScopeSpec().isValid()) {
69060b57cec5SDimitry Andric if (Actions.ShouldEnterDeclaratorScope(getCurScope(),
69070b57cec5SDimitry Andric D.getCXXScopeSpec()))
69080b57cec5SDimitry Andric // Change the declaration context for name lookup, until this function
69090b57cec5SDimitry Andric // is exited (and the declarator has been parsed).
69100b57cec5SDimitry Andric DeclScopeObj.EnterDeclaratorScope();
69110b57cec5SDimitry Andric else if (getObjCDeclContext()) {
69120b57cec5SDimitry Andric // Ensure that we don't interpret the next token as an identifier when
69130b57cec5SDimitry Andric // dealing with declarations in an Objective-C container.
69140b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
69150b57cec5SDimitry Andric D.setInvalidType(true);
69160b57cec5SDimitry Andric ConsumeToken();
69170b57cec5SDimitry Andric goto PastIdentifier;
69180b57cec5SDimitry Andric }
69190b57cec5SDimitry Andric }
69200b57cec5SDimitry Andric
69210b57cec5SDimitry Andric // C++0x [dcl.fct]p14:
69220b57cec5SDimitry Andric // There is a syntactic ambiguity when an ellipsis occurs at the end of a
69230b57cec5SDimitry Andric // parameter-declaration-clause without a preceding comma. In this case,
69240b57cec5SDimitry Andric // the ellipsis is parsed as part of the abstract-declarator if the type
69250b57cec5SDimitry Andric // of the parameter either names a template parameter pack that has not
69260b57cec5SDimitry Andric // been expanded or contains auto; otherwise, it is parsed as part of the
69270b57cec5SDimitry Andric // parameter-declaration-clause.
69280b57cec5SDimitry Andric if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
6929e8d8bef9SDimitry Andric !((D.getContext() == DeclaratorContext::Prototype ||
6930e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::LambdaExprParameter ||
6931e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::BlockLiteral) &&
6932e8d8bef9SDimitry Andric NextToken().is(tok::r_paren) && !D.hasGroupingParens() &&
69330b57cec5SDimitry Andric !Actions.containsUnexpandedParameterPacks(D) &&
69340b57cec5SDimitry Andric D.getDeclSpec().getTypeSpecType() != TST_auto)) {
69350b57cec5SDimitry Andric SourceLocation EllipsisLoc = ConsumeToken();
69360b57cec5SDimitry Andric if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) {
69370b57cec5SDimitry Andric // The ellipsis was put in the wrong place. Recover, and explain to
69380b57cec5SDimitry Andric // the user what they should have done.
69390b57cec5SDimitry Andric ParseDeclarator(D);
69400b57cec5SDimitry Andric if (EllipsisLoc.isValid())
69410b57cec5SDimitry Andric DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
69420b57cec5SDimitry Andric return;
69430b57cec5SDimitry Andric } else
69440b57cec5SDimitry Andric D.setEllipsisLoc(EllipsisLoc);
69450b57cec5SDimitry Andric
69460b57cec5SDimitry Andric // The ellipsis can't be followed by a parenthesized declarator. We
69470b57cec5SDimitry Andric // check for that in ParseParenDeclarator, after we have disambiguated
69480b57cec5SDimitry Andric // the l_paren token.
69490b57cec5SDimitry Andric }
69500b57cec5SDimitry Andric
69510b57cec5SDimitry Andric if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
69520b57cec5SDimitry Andric tok::tilde)) {
69530b57cec5SDimitry Andric // We found something that indicates the start of an unqualified-id.
69540b57cec5SDimitry Andric // Parse that unqualified-id.
69550b57cec5SDimitry Andric bool AllowConstructorName;
69560b57cec5SDimitry Andric bool AllowDeductionGuide;
69570b57cec5SDimitry Andric if (D.getDeclSpec().hasTypeSpecifier()) {
69580b57cec5SDimitry Andric AllowConstructorName = false;
69590b57cec5SDimitry Andric AllowDeductionGuide = false;
69600b57cec5SDimitry Andric } else if (D.getCXXScopeSpec().isSet()) {
6961e8d8bef9SDimitry Andric AllowConstructorName = (D.getContext() == DeclaratorContext::File ||
6962e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::Member);
69630b57cec5SDimitry Andric AllowDeductionGuide = false;
69640b57cec5SDimitry Andric } else {
6965e8d8bef9SDimitry Andric AllowConstructorName = (D.getContext() == DeclaratorContext::Member);
6966e8d8bef9SDimitry Andric AllowDeductionGuide = (D.getContext() == DeclaratorContext::File ||
6967e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::Member);
69680b57cec5SDimitry Andric }
69690b57cec5SDimitry Andric
69700b57cec5SDimitry Andric bool HadScope = D.getCXXScopeSpec().isValid();
6971*0fca6ea1SDimitry Andric SourceLocation TemplateKWLoc;
69720b57cec5SDimitry Andric if (ParseUnqualifiedId(D.getCXXScopeSpec(),
69735ffd83dbSDimitry Andric /*ObjectType=*/nullptr,
69745ffd83dbSDimitry Andric /*ObjectHadErrors=*/false,
69750b57cec5SDimitry Andric /*EnteringContext=*/true,
69760b57cec5SDimitry Andric /*AllowDestructorName=*/true, AllowConstructorName,
6977*0fca6ea1SDimitry Andric AllowDeductionGuide, &TemplateKWLoc,
6978*0fca6ea1SDimitry Andric D.getName()) ||
69790b57cec5SDimitry Andric // Once we're past the identifier, if the scope was bad, mark the
69800b57cec5SDimitry Andric // whole declarator bad.
69810b57cec5SDimitry Andric D.getCXXScopeSpec().isInvalid()) {
69820b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
69830b57cec5SDimitry Andric D.setInvalidType(true);
69840b57cec5SDimitry Andric } else {
69850b57cec5SDimitry Andric // ParseUnqualifiedId might have parsed a scope specifier during error
69860b57cec5SDimitry Andric // recovery. If it did so, enter that scope.
69870b57cec5SDimitry Andric if (!HadScope && D.getCXXScopeSpec().isValid() &&
69880b57cec5SDimitry Andric Actions.ShouldEnterDeclaratorScope(getCurScope(),
69890b57cec5SDimitry Andric D.getCXXScopeSpec()))
69900b57cec5SDimitry Andric DeclScopeObj.EnterDeclaratorScope();
69910b57cec5SDimitry Andric
69920b57cec5SDimitry Andric // Parsed the unqualified-id; update range information and move along.
69930b57cec5SDimitry Andric if (D.getSourceRange().getBegin().isInvalid())
69940b57cec5SDimitry Andric D.SetRangeBegin(D.getName().getSourceRange().getBegin());
69950b57cec5SDimitry Andric D.SetRangeEnd(D.getName().getSourceRange().getEnd());
69960b57cec5SDimitry Andric }
69970b57cec5SDimitry Andric goto PastIdentifier;
69980b57cec5SDimitry Andric }
69990b57cec5SDimitry Andric
70000b57cec5SDimitry Andric if (D.getCXXScopeSpec().isNotEmpty()) {
70010b57cec5SDimitry Andric // We have a scope specifier but no following unqualified-id.
70020b57cec5SDimitry Andric Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()),
70030b57cec5SDimitry Andric diag::err_expected_unqualified_id)
70040b57cec5SDimitry Andric << /*C++*/1;
70050b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
70060b57cec5SDimitry Andric goto PastIdentifier;
70070b57cec5SDimitry Andric }
70080b57cec5SDimitry Andric } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
70090b57cec5SDimitry Andric assert(!getLangOpts().CPlusPlus &&
70100b57cec5SDimitry Andric "There's a C++-specific check for tok::identifier above");
70110b57cec5SDimitry Andric assert(Tok.getIdentifierInfo() && "Not an identifier?");
70120b57cec5SDimitry Andric D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
70130b57cec5SDimitry Andric D.SetRangeEnd(Tok.getLocation());
70140b57cec5SDimitry Andric ConsumeToken();
70150b57cec5SDimitry Andric goto PastIdentifier;
70160b57cec5SDimitry Andric } else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) {
70170b57cec5SDimitry Andric // We're not allowed an identifier here, but we got one. Try to figure out
70180b57cec5SDimitry Andric // if the user was trying to attach a name to the type, or whether the name
70190b57cec5SDimitry Andric // is some unrelated trailing syntax.
70200b57cec5SDimitry Andric bool DiagnoseIdentifier = false;
70210b57cec5SDimitry Andric if (D.hasGroupingParens())
70220b57cec5SDimitry Andric // An identifier within parens is unlikely to be intended to be anything
70230b57cec5SDimitry Andric // other than a name being "declared".
70240b57cec5SDimitry Andric DiagnoseIdentifier = true;
7025e8d8bef9SDimitry Andric else if (D.getContext() == DeclaratorContext::TemplateArg)
70260b57cec5SDimitry Andric // T<int N> is an accidental identifier; T<int N indicates a missing '>'.
70270b57cec5SDimitry Andric DiagnoseIdentifier =
70280b57cec5SDimitry Andric NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
7029e8d8bef9SDimitry Andric else if (D.getContext() == DeclaratorContext::AliasDecl ||
7030e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::AliasTemplate)
70310b57cec5SDimitry Andric // The most likely error is that the ';' was forgotten.
70320b57cec5SDimitry Andric DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
7033e8d8bef9SDimitry Andric else if ((D.getContext() == DeclaratorContext::TrailingReturn ||
7034e8d8bef9SDimitry Andric D.getContext() == DeclaratorContext::TrailingReturnVar) &&
70350b57cec5SDimitry Andric !isCXX11VirtSpecifier(Tok))
70360b57cec5SDimitry Andric DiagnoseIdentifier = NextToken().isOneOf(
70370b57cec5SDimitry Andric tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
70380b57cec5SDimitry Andric if (DiagnoseIdentifier) {
70390b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
70400b57cec5SDimitry Andric << FixItHint::CreateRemoval(Tok.getLocation());
70410b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
70420b57cec5SDimitry Andric ConsumeToken();
70430b57cec5SDimitry Andric goto PastIdentifier;
70440b57cec5SDimitry Andric }
70450b57cec5SDimitry Andric }
70460b57cec5SDimitry Andric
70470b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) {
70480b57cec5SDimitry Andric // If this might be an abstract-declarator followed by a direct-initializer,
70490b57cec5SDimitry Andric // check whether this is a valid declarator chunk. If it can't be, assume
70500b57cec5SDimitry Andric // that it's an initializer instead.
70510b57cec5SDimitry Andric if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
70520b57cec5SDimitry Andric RevertingTentativeParsingAction PA(*this);
705306c3fb27SDimitry Andric if (TryParseDeclarator(true, D.mayHaveIdentifier(), true,
705406c3fb27SDimitry Andric D.getDeclSpec().getTypeSpecType() == TST_auto) ==
70550b57cec5SDimitry Andric TPResult::False) {
70560b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
70570b57cec5SDimitry Andric goto PastIdentifier;
70580b57cec5SDimitry Andric }
70590b57cec5SDimitry Andric }
70600b57cec5SDimitry Andric
70610b57cec5SDimitry Andric // direct-declarator: '(' declarator ')'
70620b57cec5SDimitry Andric // direct-declarator: '(' attributes declarator ')'
70630b57cec5SDimitry Andric // Example: 'char (*X)' or 'int (*XX)(void)'
70640b57cec5SDimitry Andric ParseParenDeclarator(D);
70650b57cec5SDimitry Andric
70660b57cec5SDimitry Andric // If the declarator was parenthesized, we entered the declarator
70670b57cec5SDimitry Andric // scope when parsing the parenthesized declarator, then exited
70680b57cec5SDimitry Andric // the scope already. Re-enter the scope, if we need to.
70690b57cec5SDimitry Andric if (D.getCXXScopeSpec().isSet()) {
70700b57cec5SDimitry Andric // If there was an error parsing parenthesized declarator, declarator
70710b57cec5SDimitry Andric // scope may have been entered before. Don't do it again.
70720b57cec5SDimitry Andric if (!D.isInvalidType() &&
70730b57cec5SDimitry Andric Actions.ShouldEnterDeclaratorScope(getCurScope(),
70740b57cec5SDimitry Andric D.getCXXScopeSpec()))
70750b57cec5SDimitry Andric // Change the declaration context for name lookup, until this function
70760b57cec5SDimitry Andric // is exited (and the declarator has been parsed).
70770b57cec5SDimitry Andric DeclScopeObj.EnterDeclaratorScope();
70780b57cec5SDimitry Andric }
70790b57cec5SDimitry Andric } else if (D.mayOmitIdentifier()) {
70800b57cec5SDimitry Andric // This could be something simple like "int" (in which case the declarator
70810b57cec5SDimitry Andric // portion is empty), if an abstract-declarator is allowed.
70820b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
70830b57cec5SDimitry Andric
70840b57cec5SDimitry Andric // The grammar for abstract-pack-declarator does not allow grouping parens.
70850b57cec5SDimitry Andric // FIXME: Revisit this once core issue 1488 is resolved.
70860b57cec5SDimitry Andric if (D.hasEllipsis() && D.hasGroupingParens())
70870b57cec5SDimitry Andric Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()),
70880b57cec5SDimitry Andric diag::ext_abstract_pack_declarator_parens);
70890b57cec5SDimitry Andric } else {
70900b57cec5SDimitry Andric if (Tok.getKind() == tok::annot_pragma_parser_crash)
70910b57cec5SDimitry Andric LLVM_BUILTIN_TRAP;
70920b57cec5SDimitry Andric if (Tok.is(tok::l_square))
70930b57cec5SDimitry Andric return ParseMisplacedBracketDeclarator(D);
7094e8d8bef9SDimitry Andric if (D.getContext() == DeclaratorContext::Member) {
70950b57cec5SDimitry Andric // Objective-C++: Detect C++ keywords and try to prevent further errors by
70960b57cec5SDimitry Andric // treating these keyword as valid member names.
70970b57cec5SDimitry Andric if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&
70985f757f3fSDimitry Andric !Tok.isAnnotation() && Tok.getIdentifierInfo() &&
70990b57cec5SDimitry Andric Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) {
71000b57cec5SDimitry Andric Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
71010b57cec5SDimitry Andric diag::err_expected_member_name_or_semi_objcxx_keyword)
71020b57cec5SDimitry Andric << Tok.getIdentifierInfo()
71030b57cec5SDimitry Andric << (D.getDeclSpec().isEmpty() ? SourceRange()
71040b57cec5SDimitry Andric : D.getDeclSpec().getSourceRange());
71050b57cec5SDimitry Andric D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
71060b57cec5SDimitry Andric D.SetRangeEnd(Tok.getLocation());
71070b57cec5SDimitry Andric ConsumeToken();
71080b57cec5SDimitry Andric goto PastIdentifier;
71090b57cec5SDimitry Andric }
71100b57cec5SDimitry Andric Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
71110b57cec5SDimitry Andric diag::err_expected_member_name_or_semi)
71120b57cec5SDimitry Andric << (D.getDeclSpec().isEmpty() ? SourceRange()
71130b57cec5SDimitry Andric : D.getDeclSpec().getSourceRange());
7114972a253aSDimitry Andric } else {
7115972a253aSDimitry Andric if (Tok.getKind() == tok::TokenKind::kw_while) {
7116972a253aSDimitry Andric Diag(Tok, diag::err_while_loop_outside_of_a_function);
71170b57cec5SDimitry Andric } else if (getLangOpts().CPlusPlus) {
71180b57cec5SDimitry Andric if (Tok.isOneOf(tok::period, tok::arrow))
71190b57cec5SDimitry Andric Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
71200b57cec5SDimitry Andric else {
71210b57cec5SDimitry Andric SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
71220b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && Loc.isValid())
71230b57cec5SDimitry Andric Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
71240b57cec5SDimitry Andric << getLangOpts().CPlusPlus;
71250b57cec5SDimitry Andric else
71260b57cec5SDimitry Andric Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
71270b57cec5SDimitry Andric diag::err_expected_unqualified_id)
71280b57cec5SDimitry Andric << getLangOpts().CPlusPlus;
71290b57cec5SDimitry Andric }
71300b57cec5SDimitry Andric } else {
71310b57cec5SDimitry Andric Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
71320b57cec5SDimitry Andric diag::err_expected_either)
71330b57cec5SDimitry Andric << tok::identifier << tok::l_paren;
71340b57cec5SDimitry Andric }
7135972a253aSDimitry Andric }
71360b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
71370b57cec5SDimitry Andric D.setInvalidType(true);
71380b57cec5SDimitry Andric }
71390b57cec5SDimitry Andric
71400b57cec5SDimitry Andric PastIdentifier:
71410b57cec5SDimitry Andric assert(D.isPastIdentifier() &&
71420b57cec5SDimitry Andric "Haven't past the location of the identifier yet?");
71430b57cec5SDimitry Andric
71440b57cec5SDimitry Andric // Don't parse attributes unless we have parsed an unparenthesized name.
71450b57cec5SDimitry Andric if (D.hasName() && !D.getNumTypeObjects())
71460b57cec5SDimitry Andric MaybeParseCXX11Attributes(D);
71470b57cec5SDimitry Andric
714804eeddc0SDimitry Andric while (true) {
71490b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) {
715055e4f9d5SDimitry Andric bool IsFunctionDeclaration = D.isFunctionDeclaratorAFunctionDeclaration();
71510b57cec5SDimitry Andric // Enter function-declaration scope, limiting any declarators to the
71520b57cec5SDimitry Andric // function prototype scope, including parameter declarators.
71530b57cec5SDimitry Andric ParseScope PrototypeScope(this,
71540b57cec5SDimitry Andric Scope::FunctionPrototypeScope|Scope::DeclScope|
715555e4f9d5SDimitry Andric (IsFunctionDeclaration
71560b57cec5SDimitry Andric ? Scope::FunctionDeclarationScope : 0));
71570b57cec5SDimitry Andric
71580b57cec5SDimitry Andric // The paren may be part of a C++ direct initializer, eg. "int x(1);".
71590b57cec5SDimitry Andric // In such a case, check if we actually have a function declarator; if it
71600b57cec5SDimitry Andric // is not, the declarator has been fully parsed.
71610b57cec5SDimitry Andric bool IsAmbiguous = false;
71620b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
7163bdd1243dSDimitry Andric // C++2a [temp.res]p5
7164bdd1243dSDimitry Andric // A qualified-id is assumed to name a type if
7165bdd1243dSDimitry Andric // - [...]
7166bdd1243dSDimitry Andric // - it is a decl-specifier of the decl-specifier-seq of a
7167bdd1243dSDimitry Andric // - [...]
7168bdd1243dSDimitry Andric // - parameter-declaration in a member-declaration [...]
7169bdd1243dSDimitry Andric // - parameter-declaration in a declarator of a function or function
7170bdd1243dSDimitry Andric // template declaration whose declarator-id is qualified [...]
7171bdd1243dSDimitry Andric auto AllowImplicitTypename = ImplicitTypenameContext::No;
7172bdd1243dSDimitry Andric if (D.getCXXScopeSpec().isSet())
7173bdd1243dSDimitry Andric AllowImplicitTypename =
7174bdd1243dSDimitry Andric (ImplicitTypenameContext)Actions.isDeclaratorFunctionLike(D);
7175bdd1243dSDimitry Andric else if (D.getContext() == DeclaratorContext::Member) {
7176bdd1243dSDimitry Andric AllowImplicitTypename = ImplicitTypenameContext::Yes;
7177bdd1243dSDimitry Andric }
7178bdd1243dSDimitry Andric
71790b57cec5SDimitry Andric // The name of the declarator, if any, is tentatively declared within
71800b57cec5SDimitry Andric // a possible direct initializer.
71810b57cec5SDimitry Andric TentativelyDeclaredIdentifiers.push_back(D.getIdentifier());
7182bdd1243dSDimitry Andric bool IsFunctionDecl =
7183bdd1243dSDimitry Andric isCXXFunctionDeclarator(&IsAmbiguous, AllowImplicitTypename);
71840b57cec5SDimitry Andric TentativelyDeclaredIdentifiers.pop_back();
71850b57cec5SDimitry Andric if (!IsFunctionDecl)
71860b57cec5SDimitry Andric break;
71870b57cec5SDimitry Andric }
71880b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory);
71890b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
71900b57cec5SDimitry Andric T.consumeOpen();
719155e4f9d5SDimitry Andric if (IsFunctionDeclaration)
719255e4f9d5SDimitry Andric Actions.ActOnStartFunctionDeclarationDeclarator(D,
719355e4f9d5SDimitry Andric TemplateParameterDepth);
71940b57cec5SDimitry Andric ParseFunctionDeclarator(D, attrs, T, IsAmbiguous);
719555e4f9d5SDimitry Andric if (IsFunctionDeclaration)
719655e4f9d5SDimitry Andric Actions.ActOnFinishFunctionDeclarationDeclarator(D);
71970b57cec5SDimitry Andric PrototypeScope.Exit();
71980b57cec5SDimitry Andric } else if (Tok.is(tok::l_square)) {
71990b57cec5SDimitry Andric ParseBracketDeclarator(D);
720006c3fb27SDimitry Andric } else if (Tok.isRegularKeywordAttribute()) {
720106c3fb27SDimitry Andric // For consistency with attribute parsing.
720206c3fb27SDimitry Andric Diag(Tok, diag::err_keyword_not_allowed) << Tok.getIdentifierInfo();
72037a6dacacSDimitry Andric bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind());
720406c3fb27SDimitry Andric ConsumeToken();
72057a6dacacSDimitry Andric if (TakesArgs) {
72067a6dacacSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
72077a6dacacSDimitry Andric if (!T.consumeOpen())
72087a6dacacSDimitry Andric T.skipToEnd();
72097a6dacacSDimitry Andric }
7210480093f4SDimitry Andric } else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) {
7211480093f4SDimitry Andric // This declarator is declaring a function, but the requires clause is
7212480093f4SDimitry Andric // in the wrong place:
7213480093f4SDimitry Andric // void (f() requires true);
7214480093f4SDimitry Andric // instead of
7215480093f4SDimitry Andric // void f() requires true;
7216480093f4SDimitry Andric // or
7217480093f4SDimitry Andric // void (f()) requires true;
7218480093f4SDimitry Andric Diag(Tok, diag::err_requires_clause_inside_parens);
7219480093f4SDimitry Andric ConsumeToken();
7220480093f4SDimitry Andric ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr(
7221480093f4SDimitry Andric ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
7222480093f4SDimitry Andric if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() &&
7223480093f4SDimitry Andric !D.hasTrailingRequiresClause())
7224480093f4SDimitry Andric // We're already ill-formed if we got here but we'll accept it anyway.
7225480093f4SDimitry Andric D.setTrailingRequiresClause(TrailingRequiresClause.get());
72260b57cec5SDimitry Andric } else {
72270b57cec5SDimitry Andric break;
72280b57cec5SDimitry Andric }
72290b57cec5SDimitry Andric }
72300b57cec5SDimitry Andric }
72310b57cec5SDimitry Andric
ParseDecompositionDeclarator(Declarator & D)72320b57cec5SDimitry Andric void Parser::ParseDecompositionDeclarator(Declarator &D) {
72330b57cec5SDimitry Andric assert(Tok.is(tok::l_square));
72340b57cec5SDimitry Andric
7235*0fca6ea1SDimitry Andric TentativeParsingAction PA(*this);
72360b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_square);
72370b57cec5SDimitry Andric T.consumeOpen();
72380b57cec5SDimitry Andric
7239*0fca6ea1SDimitry Andric if (isCXX11AttributeSpecifier())
7240*0fca6ea1SDimitry Andric DiagnoseAndSkipCXX11Attributes();
7241*0fca6ea1SDimitry Andric
7242*0fca6ea1SDimitry Andric // If this doesn't look like a structured binding, maybe it's a misplaced
7243*0fca6ea1SDimitry Andric // array declarator.
7244*0fca6ea1SDimitry Andric if (!(Tok.is(tok::identifier) &&
7245*0fca6ea1SDimitry Andric NextToken().isOneOf(tok::comma, tok::r_square, tok::kw_alignas,
7246*0fca6ea1SDimitry Andric tok::l_square)) &&
7247*0fca6ea1SDimitry Andric !(Tok.is(tok::r_square) &&
7248*0fca6ea1SDimitry Andric NextToken().isOneOf(tok::equal, tok::l_brace))) {
7249*0fca6ea1SDimitry Andric PA.Revert();
7250*0fca6ea1SDimitry Andric return ParseMisplacedBracketDeclarator(D);
7251*0fca6ea1SDimitry Andric }
7252*0fca6ea1SDimitry Andric
72530b57cec5SDimitry Andric SmallVector<DecompositionDeclarator::Binding, 32> Bindings;
72540b57cec5SDimitry Andric while (Tok.isNot(tok::r_square)) {
72550b57cec5SDimitry Andric if (!Bindings.empty()) {
72560b57cec5SDimitry Andric if (Tok.is(tok::comma))
72570b57cec5SDimitry Andric ConsumeToken();
72580b57cec5SDimitry Andric else {
72590b57cec5SDimitry Andric if (Tok.is(tok::identifier)) {
72600b57cec5SDimitry Andric SourceLocation EndLoc = getEndOfPreviousToken();
72610b57cec5SDimitry Andric Diag(EndLoc, diag::err_expected)
72620b57cec5SDimitry Andric << tok::comma << FixItHint::CreateInsertion(EndLoc, ",");
72630b57cec5SDimitry Andric } else {
72640b57cec5SDimitry Andric Diag(Tok, diag::err_expected_comma_or_rsquare);
72650b57cec5SDimitry Andric }
72660b57cec5SDimitry Andric
72670b57cec5SDimitry Andric SkipUntil(tok::r_square, tok::comma, tok::identifier,
72680b57cec5SDimitry Andric StopAtSemi | StopBeforeMatch);
72690b57cec5SDimitry Andric if (Tok.is(tok::comma))
72700b57cec5SDimitry Andric ConsumeToken();
72710b57cec5SDimitry Andric else if (Tok.isNot(tok::identifier))
72720b57cec5SDimitry Andric break;
72730b57cec5SDimitry Andric }
72740b57cec5SDimitry Andric }
72750b57cec5SDimitry Andric
7276*0fca6ea1SDimitry Andric if (isCXX11AttributeSpecifier())
7277*0fca6ea1SDimitry Andric DiagnoseAndSkipCXX11Attributes();
7278*0fca6ea1SDimitry Andric
72790b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
72800b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier;
72810b57cec5SDimitry Andric break;
72820b57cec5SDimitry Andric }
72830b57cec5SDimitry Andric
7284*0fca6ea1SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo();
7285*0fca6ea1SDimitry Andric SourceLocation Loc = Tok.getLocation();
72860b57cec5SDimitry Andric ConsumeToken();
7287*0fca6ea1SDimitry Andric
7288*0fca6ea1SDimitry Andric ParsedAttributes Attrs(AttrFactory);
7289*0fca6ea1SDimitry Andric if (isCXX11AttributeSpecifier()) {
7290*0fca6ea1SDimitry Andric Diag(Tok, getLangOpts().CPlusPlus26
7291*0fca6ea1SDimitry Andric ? diag::warn_cxx23_compat_decl_attrs_on_binding
7292*0fca6ea1SDimitry Andric : diag::ext_decl_attrs_on_binding);
7293*0fca6ea1SDimitry Andric MaybeParseCXX11Attributes(Attrs);
7294*0fca6ea1SDimitry Andric }
7295*0fca6ea1SDimitry Andric
7296*0fca6ea1SDimitry Andric Bindings.push_back({II, Loc, std::move(Attrs)});
72970b57cec5SDimitry Andric }
72980b57cec5SDimitry Andric
72990b57cec5SDimitry Andric if (Tok.isNot(tok::r_square))
73000b57cec5SDimitry Andric // We've already diagnosed a problem here.
73010b57cec5SDimitry Andric T.skipToEnd();
73020b57cec5SDimitry Andric else {
73030b57cec5SDimitry Andric // C++17 does not allow the identifier-list in a structured binding
73040b57cec5SDimitry Andric // to be empty.
73050b57cec5SDimitry Andric if (Bindings.empty())
73060b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::ext_decomp_decl_empty);
73070b57cec5SDimitry Andric
73080b57cec5SDimitry Andric T.consumeClose();
73090b57cec5SDimitry Andric }
73100b57cec5SDimitry Andric
7311*0fca6ea1SDimitry Andric PA.Commit();
7312*0fca6ea1SDimitry Andric
73130b57cec5SDimitry Andric return D.setDecompositionBindings(T.getOpenLocation(), Bindings,
73140b57cec5SDimitry Andric T.getCloseLocation());
73150b57cec5SDimitry Andric }
73160b57cec5SDimitry Andric
73170b57cec5SDimitry Andric /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
73180b57cec5SDimitry Andric /// only called before the identifier, so these are most likely just grouping
73190b57cec5SDimitry Andric /// parens for precedence. If we find that these are actually function
73200b57cec5SDimitry Andric /// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
73210b57cec5SDimitry Andric ///
73220b57cec5SDimitry Andric /// direct-declarator:
73230b57cec5SDimitry Andric /// '(' declarator ')'
73240b57cec5SDimitry Andric /// [GNU] '(' attributes declarator ')'
73250b57cec5SDimitry Andric /// direct-declarator '(' parameter-type-list ')'
73260b57cec5SDimitry Andric /// direct-declarator '(' identifier-list[opt] ')'
73270b57cec5SDimitry Andric /// [GNU] direct-declarator '(' parameter-forward-declarations
73280b57cec5SDimitry Andric /// parameter-type-list[opt] ')'
73290b57cec5SDimitry Andric ///
ParseParenDeclarator(Declarator & D)73300b57cec5SDimitry Andric void Parser::ParseParenDeclarator(Declarator &D) {
73310b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
73320b57cec5SDimitry Andric T.consumeOpen();
73330b57cec5SDimitry Andric
73340b57cec5SDimitry Andric assert(!D.isPastIdentifier() && "Should be called before passing identifier");
73350b57cec5SDimitry Andric
73360b57cec5SDimitry Andric // Eat any attributes before we look at whether this is a grouping or function
73370b57cec5SDimitry Andric // declarator paren. If this is a grouping paren, the attribute applies to
73380b57cec5SDimitry Andric // the type being built up, for example:
73390b57cec5SDimitry Andric // int (__attribute__(()) *x)(long y)
73400b57cec5SDimitry Andric // If this ends up not being a grouping paren, the attribute applies to the
73410b57cec5SDimitry Andric // first argument, for example:
73420b57cec5SDimitry Andric // int (__attribute__(()) int x)
73430b57cec5SDimitry Andric // In either case, we need to eat any attributes to be able to determine what
73440b57cec5SDimitry Andric // sort of paren this is.
73450b57cec5SDimitry Andric //
73460b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory);
73470b57cec5SDimitry Andric bool RequiresArg = false;
73480b57cec5SDimitry Andric if (Tok.is(tok::kw___attribute)) {
73490b57cec5SDimitry Andric ParseGNUAttributes(attrs);
73500b57cec5SDimitry Andric
73510b57cec5SDimitry Andric // We require that the argument list (if this is a non-grouping paren) be
73520b57cec5SDimitry Andric // present even if the attribute list was empty.
73530b57cec5SDimitry Andric RequiresArg = true;
73540b57cec5SDimitry Andric }
73550b57cec5SDimitry Andric
73560b57cec5SDimitry Andric // Eat any Microsoft extensions.
73570b57cec5SDimitry Andric ParseMicrosoftTypeAttributes(attrs);
73580b57cec5SDimitry Andric
73590b57cec5SDimitry Andric // Eat any Borland extensions.
73600b57cec5SDimitry Andric if (Tok.is(tok::kw___pascal))
73610b57cec5SDimitry Andric ParseBorlandTypeAttributes(attrs);
73620b57cec5SDimitry Andric
73630b57cec5SDimitry Andric // If we haven't past the identifier yet (or where the identifier would be
73640b57cec5SDimitry Andric // stored, if this is an abstract declarator), then this is probably just
73650b57cec5SDimitry Andric // grouping parens. However, if this could be an abstract-declarator, then
73660b57cec5SDimitry Andric // this could also be the start of function arguments (consider 'void()').
73670b57cec5SDimitry Andric bool isGrouping;
73680b57cec5SDimitry Andric
73690b57cec5SDimitry Andric if (!D.mayOmitIdentifier()) {
73700b57cec5SDimitry Andric // If this can't be an abstract-declarator, this *must* be a grouping
73710b57cec5SDimitry Andric // paren, because we haven't seen the identifier yet.
73720b57cec5SDimitry Andric isGrouping = true;
73730b57cec5SDimitry Andric } else if (Tok.is(tok::r_paren) || // 'int()' is a function.
73740b57cec5SDimitry Andric (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) &&
73750b57cec5SDimitry Andric NextToken().is(tok::r_paren)) || // C++ int(...)
7376bdd1243dSDimitry Andric isDeclarationSpecifier(
7377bdd1243dSDimitry Andric ImplicitTypenameContext::No) || // 'int(int)' is a function.
73780b57cec5SDimitry Andric isCXX11AttributeSpecifier()) { // 'int([[]]int)' is a function.
73790b57cec5SDimitry Andric // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
73800b57cec5SDimitry Andric // considered to be a type, not a K&R identifier-list.
73810b57cec5SDimitry Andric isGrouping = false;
73820b57cec5SDimitry Andric } else {
73830b57cec5SDimitry Andric // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
73840b57cec5SDimitry Andric isGrouping = true;
73850b57cec5SDimitry Andric }
73860b57cec5SDimitry Andric
73870b57cec5SDimitry Andric // If this is a grouping paren, handle:
73880b57cec5SDimitry Andric // direct-declarator: '(' declarator ')'
73890b57cec5SDimitry Andric // direct-declarator: '(' attributes declarator ')'
73900b57cec5SDimitry Andric if (isGrouping) {
73910b57cec5SDimitry Andric SourceLocation EllipsisLoc = D.getEllipsisLoc();
73920b57cec5SDimitry Andric D.setEllipsisLoc(SourceLocation());
73930b57cec5SDimitry Andric
73940b57cec5SDimitry Andric bool hadGroupingParens = D.hasGroupingParens();
73950b57cec5SDimitry Andric D.setGroupingParens(true);
73960b57cec5SDimitry Andric ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
73970b57cec5SDimitry Andric // Match the ')'.
73980b57cec5SDimitry Andric T.consumeClose();
73990b57cec5SDimitry Andric D.AddTypeInfo(
74000b57cec5SDimitry Andric DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()),
74010b57cec5SDimitry Andric std::move(attrs), T.getCloseLocation());
74020b57cec5SDimitry Andric
74030b57cec5SDimitry Andric D.setGroupingParens(hadGroupingParens);
74040b57cec5SDimitry Andric
74050b57cec5SDimitry Andric // An ellipsis cannot be placed outside parentheses.
74060b57cec5SDimitry Andric if (EllipsisLoc.isValid())
74070b57cec5SDimitry Andric DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
74080b57cec5SDimitry Andric
74090b57cec5SDimitry Andric return;
74100b57cec5SDimitry Andric }
74110b57cec5SDimitry Andric
74120b57cec5SDimitry Andric // Okay, if this wasn't a grouping paren, it must be the start of a function
74130b57cec5SDimitry Andric // argument list. Recognize that this declarator will never have an
74140b57cec5SDimitry Andric // identifier (and remember where it would have been), then call into
74150b57cec5SDimitry Andric // ParseFunctionDeclarator to handle of argument list.
74160b57cec5SDimitry Andric D.SetIdentifier(nullptr, Tok.getLocation());
74170b57cec5SDimitry Andric
74180b57cec5SDimitry Andric // Enter function-declaration scope, limiting any declarators to the
74190b57cec5SDimitry Andric // function prototype scope, including parameter declarators.
74200b57cec5SDimitry Andric ParseScope PrototypeScope(this,
74210b57cec5SDimitry Andric Scope::FunctionPrototypeScope | Scope::DeclScope |
74220b57cec5SDimitry Andric (D.isFunctionDeclaratorAFunctionDeclaration()
74230b57cec5SDimitry Andric ? Scope::FunctionDeclarationScope : 0));
74240b57cec5SDimitry Andric ParseFunctionDeclarator(D, attrs, T, false, RequiresArg);
74250b57cec5SDimitry Andric PrototypeScope.Exit();
74260b57cec5SDimitry Andric }
74270b57cec5SDimitry Andric
InitCXXThisScopeForDeclaratorIfRelevant(const Declarator & D,const DeclSpec & DS,std::optional<Sema::CXXThisScopeRAII> & ThisScope)7428480093f4SDimitry Andric void Parser::InitCXXThisScopeForDeclaratorIfRelevant(
7429480093f4SDimitry Andric const Declarator &D, const DeclSpec &DS,
7430bdd1243dSDimitry Andric std::optional<Sema::CXXThisScopeRAII> &ThisScope) {
7431480093f4SDimitry Andric // C++11 [expr.prim.general]p3:
7432480093f4SDimitry Andric // If a declaration declares a member function or member function
7433480093f4SDimitry Andric // template of a class X, the expression this is a prvalue of type
7434480093f4SDimitry Andric // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
7435480093f4SDimitry Andric // and the end of the function-definition, member-declarator, or
7436480093f4SDimitry Andric // declarator.
7437480093f4SDimitry Andric // FIXME: currently, "static" case isn't handled correctly.
7438e8d8bef9SDimitry Andric bool IsCXX11MemberFunction =
7439e8d8bef9SDimitry Andric getLangOpts().CPlusPlus11 &&
7440480093f4SDimitry Andric D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
7441e8d8bef9SDimitry Andric (D.getContext() == DeclaratorContext::Member
7442480093f4SDimitry Andric ? !D.getDeclSpec().isFriendSpecified()
7443e8d8bef9SDimitry Andric : D.getContext() == DeclaratorContext::File &&
7444480093f4SDimitry Andric D.getCXXScopeSpec().isValid() &&
7445480093f4SDimitry Andric Actions.CurContext->isRecord());
7446480093f4SDimitry Andric if (!IsCXX11MemberFunction)
7447480093f4SDimitry Andric return;
7448480093f4SDimitry Andric
7449480093f4SDimitry Andric Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
7450480093f4SDimitry Andric if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)
7451480093f4SDimitry Andric Q.addConst();
7452480093f4SDimitry Andric // FIXME: Collect C++ address spaces.
7453480093f4SDimitry Andric // If there are multiple different address spaces, the source is invalid.
7454480093f4SDimitry Andric // Carry on using the first addr space for the qualifiers of 'this'.
7455480093f4SDimitry Andric // The diagnostic will be given later while creating the function
7456480093f4SDimitry Andric // prototype for the method.
7457480093f4SDimitry Andric if (getLangOpts().OpenCLCPlusPlus) {
7458480093f4SDimitry Andric for (ParsedAttr &attr : DS.getAttributes()) {
7459480093f4SDimitry Andric LangAS ASIdx = attr.asOpenCLLangAS();
7460480093f4SDimitry Andric if (ASIdx != LangAS::Default) {
7461480093f4SDimitry Andric Q.addAddressSpace(ASIdx);
7462480093f4SDimitry Andric break;
7463480093f4SDimitry Andric }
7464480093f4SDimitry Andric }
7465480093f4SDimitry Andric }
7466480093f4SDimitry Andric ThisScope.emplace(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
7467480093f4SDimitry Andric IsCXX11MemberFunction);
7468480093f4SDimitry Andric }
7469480093f4SDimitry Andric
74700b57cec5SDimitry Andric /// ParseFunctionDeclarator - We are after the identifier and have parsed the
74710b57cec5SDimitry Andric /// declarator D up to a paren, which indicates that we are parsing function
74720b57cec5SDimitry Andric /// arguments.
74730b57cec5SDimitry Andric ///
747481ad6265SDimitry Andric /// If FirstArgAttrs is non-null, then the caller parsed those attributes
747581ad6265SDimitry Andric /// immediately after the open paren - they will be applied to the DeclSpec
747681ad6265SDimitry Andric /// of the first parameter.
74770b57cec5SDimitry Andric ///
74780b57cec5SDimitry Andric /// If RequiresArg is true, then the first argument of the function is required
74790b57cec5SDimitry Andric /// to be present and required to not be an identifier list.
74800b57cec5SDimitry Andric ///
74810b57cec5SDimitry Andric /// For C++, after the parameter-list, it also parses the cv-qualifier-seq[opt],
74820b57cec5SDimitry Andric /// (C++11) ref-qualifier[opt], exception-specification[opt],
7483480093f4SDimitry Andric /// (C++11) attribute-specifier-seq[opt], (C++11) trailing-return-type[opt] and
7484480093f4SDimitry Andric /// (C++2a) the trailing requires-clause.
74850b57cec5SDimitry Andric ///
74860b57cec5SDimitry Andric /// [C++11] exception-specification:
74870b57cec5SDimitry Andric /// dynamic-exception-specification
74880b57cec5SDimitry Andric /// noexcept-specification
74890b57cec5SDimitry Andric ///
ParseFunctionDeclarator(Declarator & D,ParsedAttributes & FirstArgAttrs,BalancedDelimiterTracker & Tracker,bool IsAmbiguous,bool RequiresArg)74900b57cec5SDimitry Andric void Parser::ParseFunctionDeclarator(Declarator &D,
74910b57cec5SDimitry Andric ParsedAttributes &FirstArgAttrs,
74920b57cec5SDimitry Andric BalancedDelimiterTracker &Tracker,
74930b57cec5SDimitry Andric bool IsAmbiguous,
74940b57cec5SDimitry Andric bool RequiresArg) {
74950b57cec5SDimitry Andric assert(getCurScope()->isFunctionPrototypeScope() &&
74960b57cec5SDimitry Andric "Should call from a Function scope");
74970b57cec5SDimitry Andric // lparen is already consumed!
74980b57cec5SDimitry Andric assert(D.isPastIdentifier() && "Should not call before identifier!");
74990b57cec5SDimitry Andric
75000b57cec5SDimitry Andric // This should be true when the function has typed arguments.
75010b57cec5SDimitry Andric // Otherwise, it is treated as a K&R-style function.
75020b57cec5SDimitry Andric bool HasProto = false;
75030b57cec5SDimitry Andric // Build up an array of information about the parsed arguments.
75040b57cec5SDimitry Andric SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
75050b57cec5SDimitry Andric // Remember where we see an ellipsis, if any.
75060b57cec5SDimitry Andric SourceLocation EllipsisLoc;
75070b57cec5SDimitry Andric
75080b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
75090b57cec5SDimitry Andric bool RefQualifierIsLValueRef = true;
75100b57cec5SDimitry Andric SourceLocation RefQualifierLoc;
75110b57cec5SDimitry Andric ExceptionSpecificationType ESpecType = EST_None;
75120b57cec5SDimitry Andric SourceRange ESpecRange;
75130b57cec5SDimitry Andric SmallVector<ParsedType, 2> DynamicExceptions;
75140b57cec5SDimitry Andric SmallVector<SourceRange, 2> DynamicExceptionRanges;
75150b57cec5SDimitry Andric ExprResult NoexceptExpr;
75160b57cec5SDimitry Andric CachedTokens *ExceptionSpecTokens = nullptr;
751781ad6265SDimitry Andric ParsedAttributes FnAttrs(AttrFactory);
75180b57cec5SDimitry Andric TypeResult TrailingReturnType;
7519e8d8bef9SDimitry Andric SourceLocation TrailingReturnTypeLoc;
75200b57cec5SDimitry Andric
75210b57cec5SDimitry Andric /* LocalEndLoc is the end location for the local FunctionTypeLoc.
75220b57cec5SDimitry Andric EndLoc is the end location for the function declarator.
75230b57cec5SDimitry Andric They differ for trailing return types. */
75240b57cec5SDimitry Andric SourceLocation StartLoc, LocalEndLoc, EndLoc;
75250b57cec5SDimitry Andric SourceLocation LParenLoc, RParenLoc;
75260b57cec5SDimitry Andric LParenLoc = Tracker.getOpenLocation();
75270b57cec5SDimitry Andric StartLoc = LParenLoc;
75280b57cec5SDimitry Andric
75290b57cec5SDimitry Andric if (isFunctionDeclaratorIdentifierList()) {
75300b57cec5SDimitry Andric if (RequiresArg)
75310b57cec5SDimitry Andric Diag(Tok, diag::err_argument_required_after_attribute);
75320b57cec5SDimitry Andric
75330b57cec5SDimitry Andric ParseFunctionDeclaratorIdentifierList(D, ParamInfo);
75340b57cec5SDimitry Andric
75350b57cec5SDimitry Andric Tracker.consumeClose();
75360b57cec5SDimitry Andric RParenLoc = Tracker.getCloseLocation();
75370b57cec5SDimitry Andric LocalEndLoc = RParenLoc;
75380b57cec5SDimitry Andric EndLoc = RParenLoc;
75390b57cec5SDimitry Andric
75400b57cec5SDimitry Andric // If there are attributes following the identifier list, parse them and
75410b57cec5SDimitry Andric // prohibit them.
75420b57cec5SDimitry Andric MaybeParseCXX11Attributes(FnAttrs);
75430b57cec5SDimitry Andric ProhibitAttributes(FnAttrs);
75440b57cec5SDimitry Andric } else {
75450b57cec5SDimitry Andric if (Tok.isNot(tok::r_paren))
7546bdd1243dSDimitry Andric ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc);
75470b57cec5SDimitry Andric else if (RequiresArg)
75480b57cec5SDimitry Andric Diag(Tok, diag::err_argument_required_after_attribute);
75490b57cec5SDimitry Andric
755081ad6265SDimitry Andric // OpenCL disallows functions without a prototype, but it doesn't enforce
75515f757f3fSDimitry Andric // strict prototypes as in C23 because it allows a function definition to
755281ad6265SDimitry Andric // have an identifier list. See OpenCL 3.0 6.11/g for more details.
755381ad6265SDimitry Andric HasProto = ParamInfo.size() || getLangOpts().requiresStrictPrototypes() ||
755481ad6265SDimitry Andric getLangOpts().OpenCL;
75550b57cec5SDimitry Andric
75560b57cec5SDimitry Andric // If we have the closing ')', eat it.
75570b57cec5SDimitry Andric Tracker.consumeClose();
75580b57cec5SDimitry Andric RParenLoc = Tracker.getCloseLocation();
75590b57cec5SDimitry Andric LocalEndLoc = RParenLoc;
75600b57cec5SDimitry Andric EndLoc = RParenLoc;
75610b57cec5SDimitry Andric
75620b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) {
75630b57cec5SDimitry Andric // FIXME: Accept these components in any order, and produce fixits to
75640b57cec5SDimitry Andric // correct the order if the user gets it wrong. Ideally we should deal
75650b57cec5SDimitry Andric // with the pure-specifier in the same way.
75660b57cec5SDimitry Andric
75670b57cec5SDimitry Andric // Parse cv-qualifier-seq[opt].
7568*0fca6ea1SDimitry Andric ParseTypeQualifierListOpt(
7569*0fca6ea1SDimitry Andric DS, AR_NoAttributesParsed,
75700b57cec5SDimitry Andric /*AtomicAllowed*/ false,
7571*0fca6ea1SDimitry Andric /*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() {
7572*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D);
75730b57cec5SDimitry Andric }));
75740b57cec5SDimitry Andric if (!DS.getSourceRange().getEnd().isInvalid()) {
75750b57cec5SDimitry Andric EndLoc = DS.getSourceRange().getEnd();
75760b57cec5SDimitry Andric }
75770b57cec5SDimitry Andric
75780b57cec5SDimitry Andric // Parse ref-qualifier[opt].
75790b57cec5SDimitry Andric if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
75800b57cec5SDimitry Andric EndLoc = RefQualifierLoc;
75810b57cec5SDimitry Andric
7582bdd1243dSDimitry Andric std::optional<Sema::CXXThisScopeRAII> ThisScope;
7583480093f4SDimitry Andric InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);
75840b57cec5SDimitry Andric
7585*0fca6ea1SDimitry Andric // C++ [class.mem.general]p8:
7586*0fca6ea1SDimitry Andric // A complete-class context of a class (template) is a
7587*0fca6ea1SDimitry Andric // - function body,
7588*0fca6ea1SDimitry Andric // - default argument,
7589*0fca6ea1SDimitry Andric // - default template argument,
7590*0fca6ea1SDimitry Andric // - noexcept-specifier, or
7591*0fca6ea1SDimitry Andric // - default member initializer
7592*0fca6ea1SDimitry Andric // within the member-specification of the class or class template.
7593*0fca6ea1SDimitry Andric //
7594*0fca6ea1SDimitry Andric // Parse exception-specification[opt]. If we are in the
7595*0fca6ea1SDimitry Andric // member-specification of a class or class template, this is a
7596*0fca6ea1SDimitry Andric // complete-class context and parsing of the noexcept-specifier should be
7597*0fca6ea1SDimitry Andric // delayed (even if this is a friend declaration).
7598*0fca6ea1SDimitry Andric bool Delayed = D.getContext() == DeclaratorContext::Member &&
75990b57cec5SDimitry Andric D.isFunctionDeclaratorAFunctionDeclaration();
76000b57cec5SDimitry Andric if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) &&
76010b57cec5SDimitry Andric GetLookAheadToken(0).is(tok::kw_noexcept) &&
76020b57cec5SDimitry Andric GetLookAheadToken(1).is(tok::l_paren) &&
76030b57cec5SDimitry Andric GetLookAheadToken(2).is(tok::kw_noexcept) &&
76040b57cec5SDimitry Andric GetLookAheadToken(3).is(tok::l_paren) &&
76050b57cec5SDimitry Andric GetLookAheadToken(4).is(tok::identifier) &&
76060b57cec5SDimitry Andric GetLookAheadToken(4).getIdentifierInfo()->isStr("swap")) {
76070b57cec5SDimitry Andric // HACK: We've got an exception-specification
76080b57cec5SDimitry Andric // noexcept(noexcept(swap(...)))
76090b57cec5SDimitry Andric // or
76100b57cec5SDimitry Andric // noexcept(noexcept(swap(...)) && noexcept(swap(...)))
76110b57cec5SDimitry Andric // on a 'swap' member function. This is a libstdc++ bug; the lookup
76120b57cec5SDimitry Andric // for 'swap' will only find the function we're currently declaring,
76130b57cec5SDimitry Andric // whereas it expects to find a non-member swap through ADL. Turn off
76140b57cec5SDimitry Andric // delayed parsing to give it a chance to find what it expects.
76150b57cec5SDimitry Andric Delayed = false;
76160b57cec5SDimitry Andric }
76170b57cec5SDimitry Andric ESpecType = tryParseExceptionSpecification(Delayed,
76180b57cec5SDimitry Andric ESpecRange,
76190b57cec5SDimitry Andric DynamicExceptions,
76200b57cec5SDimitry Andric DynamicExceptionRanges,
76210b57cec5SDimitry Andric NoexceptExpr,
76220b57cec5SDimitry Andric ExceptionSpecTokens);
76230b57cec5SDimitry Andric if (ESpecType != EST_None)
76240b57cec5SDimitry Andric EndLoc = ESpecRange.getEnd();
76250b57cec5SDimitry Andric
76260b57cec5SDimitry Andric // Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes
76270b57cec5SDimitry Andric // after the exception-specification.
76280b57cec5SDimitry Andric MaybeParseCXX11Attributes(FnAttrs);
76290b57cec5SDimitry Andric
76300b57cec5SDimitry Andric // Parse trailing-return-type[opt].
76310b57cec5SDimitry Andric LocalEndLoc = EndLoc;
76320b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11 && Tok.is(tok::arrow)) {
76330b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);
76340b57cec5SDimitry Andric if (D.getDeclSpec().getTypeSpecType() == TST_auto)
76350b57cec5SDimitry Andric StartLoc = D.getDeclSpec().getTypeSpecTypeLoc();
76360b57cec5SDimitry Andric LocalEndLoc = Tok.getLocation();
76370b57cec5SDimitry Andric SourceRange Range;
76380b57cec5SDimitry Andric TrailingReturnType =
76390b57cec5SDimitry Andric ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit());
7640e8d8bef9SDimitry Andric TrailingReturnTypeLoc = Range.getBegin();
76410b57cec5SDimitry Andric EndLoc = Range.getEnd();
76420b57cec5SDimitry Andric }
764306c3fb27SDimitry Andric } else {
76440b57cec5SDimitry Andric MaybeParseCXX11Attributes(FnAttrs);
76450b57cec5SDimitry Andric }
76460b57cec5SDimitry Andric }
76470b57cec5SDimitry Andric
76480b57cec5SDimitry Andric // Collect non-parameter declarations from the prototype if this is a function
76490b57cec5SDimitry Andric // declaration. They will be moved into the scope of the function. Only do
76500b57cec5SDimitry Andric // this in C and not C++, where the decls will continue to live in the
76510b57cec5SDimitry Andric // surrounding context.
76520b57cec5SDimitry Andric SmallVector<NamedDecl *, 0> DeclsInPrototype;
765381ad6265SDimitry Andric if (getCurScope()->isFunctionDeclarationScope() && !getLangOpts().CPlusPlus) {
76540b57cec5SDimitry Andric for (Decl *D : getCurScope()->decls()) {
76550b57cec5SDimitry Andric NamedDecl *ND = dyn_cast<NamedDecl>(D);
76560b57cec5SDimitry Andric if (!ND || isa<ParmVarDecl>(ND))
76570b57cec5SDimitry Andric continue;
76580b57cec5SDimitry Andric DeclsInPrototype.push_back(ND);
76590b57cec5SDimitry Andric }
766006c3fb27SDimitry Andric // Sort DeclsInPrototype based on raw encoding of the source location.
766106c3fb27SDimitry Andric // Scope::decls() is iterating over a SmallPtrSet so sort the Decls before
766206c3fb27SDimitry Andric // moving to DeclContext. This provides a stable ordering for traversing
766306c3fb27SDimitry Andric // Decls in DeclContext, which is important for tasks like ASTWriter for
766406c3fb27SDimitry Andric // deterministic output.
766506c3fb27SDimitry Andric llvm::sort(DeclsInPrototype, [](Decl *D1, Decl *D2) {
766606c3fb27SDimitry Andric return D1->getLocation().getRawEncoding() <
766706c3fb27SDimitry Andric D2->getLocation().getRawEncoding();
766806c3fb27SDimitry Andric });
76690b57cec5SDimitry Andric }
76700b57cec5SDimitry Andric
76710b57cec5SDimitry Andric // Remember that we parsed a function type, and remember the attributes.
76720b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getFunction(
76730b57cec5SDimitry Andric HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(),
76740b57cec5SDimitry Andric ParamInfo.size(), EllipsisLoc, RParenLoc,
76750b57cec5SDimitry Andric RefQualifierIsLValueRef, RefQualifierLoc,
76760b57cec5SDimitry Andric /*MutableLoc=*/SourceLocation(),
76770b57cec5SDimitry Andric ESpecType, ESpecRange, DynamicExceptions.data(),
76780b57cec5SDimitry Andric DynamicExceptionRanges.data(), DynamicExceptions.size(),
76790b57cec5SDimitry Andric NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
76800b57cec5SDimitry Andric ExceptionSpecTokens, DeclsInPrototype, StartLoc,
7681e8d8bef9SDimitry Andric LocalEndLoc, D, TrailingReturnType, TrailingReturnTypeLoc,
7682e8d8bef9SDimitry Andric &DS),
76830b57cec5SDimitry Andric std::move(FnAttrs), EndLoc);
76840b57cec5SDimitry Andric }
76850b57cec5SDimitry Andric
76860b57cec5SDimitry Andric /// ParseRefQualifier - Parses a member function ref-qualifier. Returns
76870b57cec5SDimitry Andric /// true if a ref-qualifier is found.
ParseRefQualifier(bool & RefQualifierIsLValueRef,SourceLocation & RefQualifierLoc)76880b57cec5SDimitry Andric bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,
76890b57cec5SDimitry Andric SourceLocation &RefQualifierLoc) {
76900b57cec5SDimitry Andric if (Tok.isOneOf(tok::amp, tok::ampamp)) {
76910b57cec5SDimitry Andric Diag(Tok, getLangOpts().CPlusPlus11 ?
76920b57cec5SDimitry Andric diag::warn_cxx98_compat_ref_qualifier :
76930b57cec5SDimitry Andric diag::ext_ref_qualifier);
76940b57cec5SDimitry Andric
76950b57cec5SDimitry Andric RefQualifierIsLValueRef = Tok.is(tok::amp);
76960b57cec5SDimitry Andric RefQualifierLoc = ConsumeToken();
76970b57cec5SDimitry Andric return true;
76980b57cec5SDimitry Andric }
76990b57cec5SDimitry Andric return false;
77000b57cec5SDimitry Andric }
77010b57cec5SDimitry Andric
77020b57cec5SDimitry Andric /// isFunctionDeclaratorIdentifierList - This parameter list may have an
77030b57cec5SDimitry Andric /// identifier list form for a K&R-style function: void foo(a,b,c)
77040b57cec5SDimitry Andric ///
77050b57cec5SDimitry Andric /// Note that identifier-lists are only allowed for normal declarators, not for
77060b57cec5SDimitry Andric /// abstract-declarators.
isFunctionDeclaratorIdentifierList()77070b57cec5SDimitry Andric bool Parser::isFunctionDeclaratorIdentifierList() {
770881ad6265SDimitry Andric return !getLangOpts().requiresStrictPrototypes()
77090b57cec5SDimitry Andric && Tok.is(tok::identifier)
77100b57cec5SDimitry Andric && !TryAltiVecVectorToken()
77110b57cec5SDimitry Andric // K&R identifier lists can't have typedefs as identifiers, per C99
77120b57cec5SDimitry Andric // 6.7.5.3p11.
77130b57cec5SDimitry Andric && (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename))
77140b57cec5SDimitry Andric // Identifier lists follow a really simple grammar: the identifiers can
77150b57cec5SDimitry Andric // be followed *only* by a ", identifier" or ")". However, K&R
77160b57cec5SDimitry Andric // identifier lists are really rare in the brave new modern world, and
77170b57cec5SDimitry Andric // it is very common for someone to typo a type in a non-K&R style
77180b57cec5SDimitry Andric // list. If we are presented with something like: "void foo(intptr x,
77190b57cec5SDimitry Andric // float y)", we don't want to start parsing the function declarator as
77200b57cec5SDimitry Andric // though it is a K&R style declarator just because intptr is an
77210b57cec5SDimitry Andric // invalid type.
77220b57cec5SDimitry Andric //
77230b57cec5SDimitry Andric // To handle this, we check to see if the token after the first
77240b57cec5SDimitry Andric // identifier is a "," or ")". Only then do we parse it as an
77250b57cec5SDimitry Andric // identifier list.
77260b57cec5SDimitry Andric && (!Tok.is(tok::eof) &&
77270b57cec5SDimitry Andric (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));
77280b57cec5SDimitry Andric }
77290b57cec5SDimitry Andric
77300b57cec5SDimitry Andric /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
77310b57cec5SDimitry Andric /// we found a K&R-style identifier list instead of a typed parameter list.
77320b57cec5SDimitry Andric ///
77330b57cec5SDimitry Andric /// After returning, ParamInfo will hold the parsed parameters.
77340b57cec5SDimitry Andric ///
77350b57cec5SDimitry Andric /// identifier-list: [C99 6.7.5]
77360b57cec5SDimitry Andric /// identifier
77370b57cec5SDimitry Andric /// identifier-list ',' identifier
77380b57cec5SDimitry Andric ///
ParseFunctionDeclaratorIdentifierList(Declarator & D,SmallVectorImpl<DeclaratorChunk::ParamInfo> & ParamInfo)77390b57cec5SDimitry Andric void Parser::ParseFunctionDeclaratorIdentifierList(
77400b57cec5SDimitry Andric Declarator &D,
77410b57cec5SDimitry Andric SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) {
77425f757f3fSDimitry Andric // We should never reach this point in C23 or C++.
774381ad6265SDimitry Andric assert(!getLangOpts().requiresStrictPrototypes() &&
77445f757f3fSDimitry Andric "Cannot parse an identifier list in C23 or C++");
774581ad6265SDimitry Andric
77460b57cec5SDimitry Andric // If there was no identifier specified for the declarator, either we are in
77470b57cec5SDimitry Andric // an abstract-declarator, or we are in a parameter declarator which was found
77480b57cec5SDimitry Andric // to be abstract. In abstract-declarators, identifier lists are not valid:
77490b57cec5SDimitry Andric // diagnose this.
77500b57cec5SDimitry Andric if (!D.getIdentifier())
77510b57cec5SDimitry Andric Diag(Tok, diag::ext_ident_list_in_param);
77520b57cec5SDimitry Andric
77530b57cec5SDimitry Andric // Maintain an efficient lookup of params we have seen so far.
77540b57cec5SDimitry Andric llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
77550b57cec5SDimitry Andric
77560b57cec5SDimitry Andric do {
77570b57cec5SDimitry Andric // If this isn't an identifier, report the error and skip until ')'.
77580b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) {
77590b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier;
77600b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
77610b57cec5SDimitry Andric // Forget we parsed anything.
77620b57cec5SDimitry Andric ParamInfo.clear();
77630b57cec5SDimitry Andric return;
77640b57cec5SDimitry Andric }
77650b57cec5SDimitry Andric
77660b57cec5SDimitry Andric IdentifierInfo *ParmII = Tok.getIdentifierInfo();
77670b57cec5SDimitry Andric
77680b57cec5SDimitry Andric // Reject 'typedef int y; int test(x, y)', but continue parsing.
77690b57cec5SDimitry Andric if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope()))
77700b57cec5SDimitry Andric Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
77710b57cec5SDimitry Andric
77720b57cec5SDimitry Andric // Verify that the argument identifier has not already been mentioned.
77730b57cec5SDimitry Andric if (!ParamsSoFar.insert(ParmII).second) {
77740b57cec5SDimitry Andric Diag(Tok, diag::err_param_redefinition) << ParmII;
77750b57cec5SDimitry Andric } else {
77760b57cec5SDimitry Andric // Remember this identifier in ParamInfo.
77770b57cec5SDimitry Andric ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
77780b57cec5SDimitry Andric Tok.getLocation(),
77790b57cec5SDimitry Andric nullptr));
77800b57cec5SDimitry Andric }
77810b57cec5SDimitry Andric
77820b57cec5SDimitry Andric // Eat the identifier.
77830b57cec5SDimitry Andric ConsumeToken();
77840b57cec5SDimitry Andric // The list continues if we see a comma.
77850b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma));
77860b57cec5SDimitry Andric }
77870b57cec5SDimitry Andric
77880b57cec5SDimitry Andric /// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
77890b57cec5SDimitry Andric /// after the opening parenthesis. This function will not parse a K&R-style
77900b57cec5SDimitry Andric /// identifier list.
77910b57cec5SDimitry Andric ///
779255e4f9d5SDimitry Andric /// DeclContext is the context of the declarator being parsed. If FirstArgAttrs
779355e4f9d5SDimitry Andric /// is non-null, then the caller parsed those attributes immediately after the
779481ad6265SDimitry Andric /// open paren - they will be applied to the DeclSpec of the first parameter.
77950b57cec5SDimitry Andric ///
77960b57cec5SDimitry Andric /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will
77970b57cec5SDimitry Andric /// be the location of the ellipsis, if any was parsed.
77980b57cec5SDimitry Andric ///
77990b57cec5SDimitry Andric /// parameter-type-list: [C99 6.7.5]
78000b57cec5SDimitry Andric /// parameter-list
78010b57cec5SDimitry Andric /// parameter-list ',' '...'
78020b57cec5SDimitry Andric /// [C++] parameter-list '...'
78030b57cec5SDimitry Andric ///
78040b57cec5SDimitry Andric /// parameter-list: [C99 6.7.5]
78050b57cec5SDimitry Andric /// parameter-declaration
78060b57cec5SDimitry Andric /// parameter-list ',' parameter-declaration
78070b57cec5SDimitry Andric ///
78080b57cec5SDimitry Andric /// parameter-declaration: [C99 6.7.5]
78090b57cec5SDimitry Andric /// declaration-specifiers declarator
78100b57cec5SDimitry Andric /// [C++] declaration-specifiers declarator '=' assignment-expression
78110b57cec5SDimitry Andric /// [C++11] initializer-clause
78120b57cec5SDimitry Andric /// [GNU] declaration-specifiers declarator attributes
78130b57cec5SDimitry Andric /// declaration-specifiers abstract-declarator[opt]
78140b57cec5SDimitry Andric /// [C++] declaration-specifiers abstract-declarator[opt]
78150b57cec5SDimitry Andric /// '=' assignment-expression
78160b57cec5SDimitry Andric /// [GNU] declaration-specifiers abstract-declarator[opt] attributes
78170b57cec5SDimitry Andric /// [C++11] attribute-specifier-seq parameter-declaration
78185f757f3fSDimitry Andric /// [C++2b] attribute-specifier-seq 'this' parameter-declaration
78190b57cec5SDimitry Andric ///
ParseParameterDeclarationClause(DeclaratorContext DeclaratorCtx,ParsedAttributes & FirstArgAttrs,SmallVectorImpl<DeclaratorChunk::ParamInfo> & ParamInfo,SourceLocation & EllipsisLoc,bool IsACXXFunctionDeclaration)78200b57cec5SDimitry Andric void Parser::ParseParameterDeclarationClause(
782181ad6265SDimitry Andric DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs,
78220b57cec5SDimitry Andric SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
7823bdd1243dSDimitry Andric SourceLocation &EllipsisLoc, bool IsACXXFunctionDeclaration) {
7824480093f4SDimitry Andric
7825480093f4SDimitry Andric // Avoid exceeding the maximum function scope depth.
7826480093f4SDimitry Andric // See https://bugs.llvm.org/show_bug.cgi?id=19607
7827480093f4SDimitry Andric // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with
7828480093f4SDimitry Andric // getFunctionPrototypeDepth() - 1.
7829480093f4SDimitry Andric if (getCurScope()->getFunctionPrototypeDepth() - 1 >
7830480093f4SDimitry Andric ParmVarDecl::getMaxFunctionScopeDepth()) {
7831480093f4SDimitry Andric Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded)
7832480093f4SDimitry Andric << ParmVarDecl::getMaxFunctionScopeDepth();
7833480093f4SDimitry Andric cutOffParsing();
7834480093f4SDimitry Andric return;
7835480093f4SDimitry Andric }
7836480093f4SDimitry Andric
7837bdd1243dSDimitry Andric // C++2a [temp.res]p5
7838bdd1243dSDimitry Andric // A qualified-id is assumed to name a type if
7839bdd1243dSDimitry Andric // - [...]
7840bdd1243dSDimitry Andric // - it is a decl-specifier of the decl-specifier-seq of a
7841bdd1243dSDimitry Andric // - [...]
7842bdd1243dSDimitry Andric // - parameter-declaration in a member-declaration [...]
7843bdd1243dSDimitry Andric // - parameter-declaration in a declarator of a function or function
7844bdd1243dSDimitry Andric // template declaration whose declarator-id is qualified [...]
7845bdd1243dSDimitry Andric // - parameter-declaration in a lambda-declarator [...]
7846bdd1243dSDimitry Andric auto AllowImplicitTypename = ImplicitTypenameContext::No;
7847bdd1243dSDimitry Andric if (DeclaratorCtx == DeclaratorContext::Member ||
7848bdd1243dSDimitry Andric DeclaratorCtx == DeclaratorContext::LambdaExpr ||
7849bdd1243dSDimitry Andric DeclaratorCtx == DeclaratorContext::RequiresExpr ||
7850bdd1243dSDimitry Andric IsACXXFunctionDeclaration) {
7851bdd1243dSDimitry Andric AllowImplicitTypename = ImplicitTypenameContext::Yes;
7852bdd1243dSDimitry Andric }
7853bdd1243dSDimitry Andric
78540b57cec5SDimitry Andric do {
78550b57cec5SDimitry Andric // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
78560b57cec5SDimitry Andric // before deciding this was a parameter-declaration-clause.
78570b57cec5SDimitry Andric if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
78580b57cec5SDimitry Andric break;
78590b57cec5SDimitry Andric
78600b57cec5SDimitry Andric // Parse the declaration-specifiers.
78610b57cec5SDimitry Andric // Just use the ParsingDeclaration "scope" of the declarator.
78620b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
78630b57cec5SDimitry Andric
786481ad6265SDimitry Andric ParsedAttributes ArgDeclAttrs(AttrFactory);
786581ad6265SDimitry Andric ParsedAttributes ArgDeclSpecAttrs(AttrFactory);
786681ad6265SDimitry Andric
786781ad6265SDimitry Andric if (FirstArgAttrs.Range.isValid()) {
786881ad6265SDimitry Andric // If the caller parsed attributes for the first argument, add them now.
786981ad6265SDimitry Andric // Take them so that we only apply the attributes to the first parameter.
787081ad6265SDimitry Andric // We have already started parsing the decl-specifier sequence, so don't
787181ad6265SDimitry Andric // parse any parameter-declaration pieces that precede it.
787281ad6265SDimitry Andric ArgDeclSpecAttrs.takeAllFrom(FirstArgAttrs);
787381ad6265SDimitry Andric } else {
78740b57cec5SDimitry Andric // Parse any C++11 attributes.
787581ad6265SDimitry Andric MaybeParseCXX11Attributes(ArgDeclAttrs);
78760b57cec5SDimitry Andric
78770b57cec5SDimitry Andric // Skip any Microsoft attributes before a param.
787881ad6265SDimitry Andric MaybeParseMicrosoftAttributes(ArgDeclSpecAttrs);
787981ad6265SDimitry Andric }
78800b57cec5SDimitry Andric
78810b57cec5SDimitry Andric SourceLocation DSStart = Tok.getLocation();
78820b57cec5SDimitry Andric
78835f757f3fSDimitry Andric // Parse a C++23 Explicit Object Parameter
78845f757f3fSDimitry Andric // We do that in all language modes to produce a better diagnostic.
78855f757f3fSDimitry Andric SourceLocation ThisLoc;
7886*0fca6ea1SDimitry Andric if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) {
78875f757f3fSDimitry Andric ThisLoc = ConsumeToken();
7888*0fca6ea1SDimitry Andric // C++23 [dcl.fct]p6:
7889*0fca6ea1SDimitry Andric // An explicit-object-parameter-declaration is a parameter-declaration
7890*0fca6ea1SDimitry Andric // with a this specifier. An explicit-object-parameter-declaration
7891*0fca6ea1SDimitry Andric // shall appear only as the first parameter-declaration of a
7892*0fca6ea1SDimitry Andric // parameter-declaration-list of either:
7893*0fca6ea1SDimitry Andric // - a member-declarator that declares a member function, or
7894*0fca6ea1SDimitry Andric // - a lambda-declarator.
7895*0fca6ea1SDimitry Andric //
7896*0fca6ea1SDimitry Andric // The parameter-declaration-list of a requires-expression is not such
7897*0fca6ea1SDimitry Andric // a context.
7898*0fca6ea1SDimitry Andric if (DeclaratorCtx == DeclaratorContext::RequiresExpr)
7899*0fca6ea1SDimitry Andric Diag(ThisLoc, diag::err_requires_expr_explicit_object_parameter);
7900*0fca6ea1SDimitry Andric }
79015f757f3fSDimitry Andric
7902*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo;
7903*0fca6ea1SDimitry Andric ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none,
7904*0fca6ea1SDimitry Andric DeclSpecContext::DSC_normal,
7905bdd1243dSDimitry Andric /*LateAttrs=*/nullptr, AllowImplicitTypename);
79065f757f3fSDimitry Andric
790781ad6265SDimitry Andric DS.takeAttributesFrom(ArgDeclSpecAttrs);
79080b57cec5SDimitry Andric
79090b57cec5SDimitry Andric // Parse the declarator. This is "PrototypeContext" or
79100b57cec5SDimitry Andric // "LambdaExprParameterContext", because we must accept either
79110b57cec5SDimitry Andric // 'declarator' or 'abstract-declarator' here.
791281ad6265SDimitry Andric Declarator ParmDeclarator(DS, ArgDeclAttrs,
791381ad6265SDimitry Andric DeclaratorCtx == DeclaratorContext::RequiresExpr
7914e8d8bef9SDimitry Andric ? DeclaratorContext::RequiresExpr
7915e8d8bef9SDimitry Andric : DeclaratorCtx == DeclaratorContext::LambdaExpr
7916e8d8bef9SDimitry Andric ? DeclaratorContext::LambdaExprParameter
7917e8d8bef9SDimitry Andric : DeclaratorContext::Prototype);
79180b57cec5SDimitry Andric ParseDeclarator(ParmDeclarator);
79190b57cec5SDimitry Andric
79205f757f3fSDimitry Andric if (ThisLoc.isValid())
79215f757f3fSDimitry Andric ParmDeclarator.SetRangeBegin(ThisLoc);
79225f757f3fSDimitry Andric
79230b57cec5SDimitry Andric // Parse GNU attributes, if present.
79240b57cec5SDimitry Andric MaybeParseGNUAttributes(ParmDeclarator);
7925bdd1243dSDimitry Andric if (getLangOpts().HLSL)
7926*0fca6ea1SDimitry Andric MaybeParseHLSLAnnotations(DS.getAttributes());
79270b57cec5SDimitry Andric
7928480093f4SDimitry Andric if (Tok.is(tok::kw_requires)) {
7929480093f4SDimitry Andric // User tried to define a requires clause in a parameter declaration,
7930480093f4SDimitry Andric // which is surely not a function declaration.
7931480093f4SDimitry Andric // void f(int (*g)(int, int) requires true);
7932480093f4SDimitry Andric Diag(Tok,
7933480093f4SDimitry Andric diag::err_requires_clause_on_declarator_not_declaring_a_function);
7934480093f4SDimitry Andric ConsumeToken();
7935480093f4SDimitry Andric Actions.CorrectDelayedTyposInExpr(
7936480093f4SDimitry Andric ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
7937480093f4SDimitry Andric }
7938480093f4SDimitry Andric
79390b57cec5SDimitry Andric // Remember this parsed parameter in ParamInfo.
7940*0fca6ea1SDimitry Andric const IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
79410b57cec5SDimitry Andric
79420b57cec5SDimitry Andric // DefArgToks is used when the parsing of default arguments needs
79430b57cec5SDimitry Andric // to be delayed.
79440b57cec5SDimitry Andric std::unique_ptr<CachedTokens> DefArgToks;
79450b57cec5SDimitry Andric
79460b57cec5SDimitry Andric // If no parameter was specified, verify that *something* was specified,
79470b57cec5SDimitry Andric // otherwise we have a missing type and identifier.
79480b57cec5SDimitry Andric if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr &&
79490b57cec5SDimitry Andric ParmDeclarator.getNumTypeObjects() == 0) {
79500b57cec5SDimitry Andric // Completely missing, emit error.
79510b57cec5SDimitry Andric Diag(DSStart, diag::err_missing_param);
79520b57cec5SDimitry Andric } else {
79530b57cec5SDimitry Andric // Otherwise, we have something. Add it and let semantic analysis try
79540b57cec5SDimitry Andric // to grok it and add the result to the ParamInfo we are building.
79550b57cec5SDimitry Andric
79560b57cec5SDimitry Andric // Last chance to recover from a misplaced ellipsis in an attempted
79570b57cec5SDimitry Andric // parameter pack declaration.
79580b57cec5SDimitry Andric if (Tok.is(tok::ellipsis) &&
79590b57cec5SDimitry Andric (NextToken().isNot(tok::r_paren) ||
79600b57cec5SDimitry Andric (!ParmDeclarator.getEllipsisLoc().isValid() &&
79610b57cec5SDimitry Andric !Actions.isUnexpandedParameterPackPermitted())) &&
79620b57cec5SDimitry Andric Actions.containsUnexpandedParameterPacks(ParmDeclarator))
79630b57cec5SDimitry Andric DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator);
79640b57cec5SDimitry Andric
79655ffd83dbSDimitry Andric // Now we are at the point where declarator parsing is finished.
79665ffd83dbSDimitry Andric //
79675ffd83dbSDimitry Andric // Try to catch keywords in place of the identifier in a declarator, and
79685ffd83dbSDimitry Andric // in particular the common case where:
79695ffd83dbSDimitry Andric // 1 identifier comes at the end of the declarator
79705ffd83dbSDimitry Andric // 2 if the identifier is dropped, the declarator is valid but anonymous
79715ffd83dbSDimitry Andric // (no identifier)
79725ffd83dbSDimitry Andric // 3 declarator parsing succeeds, and then we have a trailing keyword,
79735ffd83dbSDimitry Andric // which is never valid in a param list (e.g. missing a ',')
79745ffd83dbSDimitry Andric // And we can't handle this in ParseDeclarator because in general keywords
79755ffd83dbSDimitry Andric // may be allowed to follow the declarator. (And in some cases there'd be
79765ffd83dbSDimitry Andric // better recovery like inserting punctuation). ParseDeclarator is just
79775ffd83dbSDimitry Andric // treating this as an anonymous parameter, and fortunately at this point
79785ffd83dbSDimitry Andric // we've already almost done that.
79795ffd83dbSDimitry Andric //
79805ffd83dbSDimitry Andric // We care about case 1) where the declarator type should be known, and
79815ffd83dbSDimitry Andric // the identifier should be null.
79824824e7fdSDimitry Andric if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName() &&
79834824e7fdSDimitry Andric Tok.isNot(tok::raw_identifier) && !Tok.isAnnotation() &&
79844824e7fdSDimitry Andric Tok.getIdentifierInfo() &&
79855ffd83dbSDimitry Andric Tok.getIdentifierInfo()->isKeyword(getLangOpts())) {
79865ffd83dbSDimitry Andric Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok);
79875ffd83dbSDimitry Andric // Consume the keyword.
79885ffd83dbSDimitry Andric ConsumeToken();
79895ffd83dbSDimitry Andric }
79900b57cec5SDimitry Andric // Inform the actions module about the parameter declarator, so it gets
79910b57cec5SDimitry Andric // added to the current scope.
79925f757f3fSDimitry Andric Decl *Param =
79935f757f3fSDimitry Andric Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ThisLoc);
79940b57cec5SDimitry Andric // Parse the default argument, if any. We parse the default
79950b57cec5SDimitry Andric // arguments in all dialects; the semantic analysis in
79960b57cec5SDimitry Andric // ActOnParamDefaultArgument will reject the default argument in
79970b57cec5SDimitry Andric // C.
79980b57cec5SDimitry Andric if (Tok.is(tok::equal)) {
79990b57cec5SDimitry Andric SourceLocation EqualLoc = Tok.getLocation();
80000b57cec5SDimitry Andric
80010b57cec5SDimitry Andric // Parse the default argument
8002e8d8bef9SDimitry Andric if (DeclaratorCtx == DeclaratorContext::Member) {
80030b57cec5SDimitry Andric // If we're inside a class definition, cache the tokens
80040b57cec5SDimitry Andric // corresponding to the default argument. We'll actually parse
80050b57cec5SDimitry Andric // them when we see the end of the class definition.
80060b57cec5SDimitry Andric DefArgToks.reset(new CachedTokens);
80070b57cec5SDimitry Andric
80080b57cec5SDimitry Andric SourceLocation ArgStartLoc = NextToken().getLocation();
800906c3fb27SDimitry Andric ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument);
80100b57cec5SDimitry Andric Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
80110b57cec5SDimitry Andric ArgStartLoc);
80120b57cec5SDimitry Andric } else {
80130b57cec5SDimitry Andric // Consume the '='.
80140b57cec5SDimitry Andric ConsumeToken();
80150b57cec5SDimitry Andric
80160b57cec5SDimitry Andric // The argument isn't actually potentially evaluated unless it is
80170b57cec5SDimitry Andric // used.
80180b57cec5SDimitry Andric EnterExpressionEvaluationContext Eval(
80190b57cec5SDimitry Andric Actions,
80200b57cec5SDimitry Andric Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed,
80210b57cec5SDimitry Andric Param);
80220b57cec5SDimitry Andric
80230b57cec5SDimitry Andric ExprResult DefArgResult;
80240b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
80250b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
80260b57cec5SDimitry Andric DefArgResult = ParseBraceInitializer();
802781ad6265SDimitry Andric } else {
802881ad6265SDimitry Andric if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {
802981ad6265SDimitry Andric Diag(Tok, diag::err_stmt_expr_in_default_arg) << 0;
80305f757f3fSDimitry Andric Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,
80315f757f3fSDimitry Andric /*DefaultArg=*/nullptr);
803281ad6265SDimitry Andric // Skip the statement expression and continue parsing
803381ad6265SDimitry Andric SkipUntil(tok::comma, StopBeforeMatch);
803481ad6265SDimitry Andric continue;
803581ad6265SDimitry Andric }
80360b57cec5SDimitry Andric DefArgResult = ParseAssignmentExpression();
803781ad6265SDimitry Andric }
80380b57cec5SDimitry Andric DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
80390b57cec5SDimitry Andric if (DefArgResult.isInvalid()) {
80405f757f3fSDimitry Andric Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,
80415f757f3fSDimitry Andric /*DefaultArg=*/nullptr);
80420b57cec5SDimitry Andric SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
80430b57cec5SDimitry Andric } else {
80440b57cec5SDimitry Andric // Inform the actions module about the default argument
80450b57cec5SDimitry Andric Actions.ActOnParamDefaultArgument(Param, EqualLoc,
80460b57cec5SDimitry Andric DefArgResult.get());
80470b57cec5SDimitry Andric }
80480b57cec5SDimitry Andric }
80490b57cec5SDimitry Andric }
80500b57cec5SDimitry Andric
80510b57cec5SDimitry Andric ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
80520b57cec5SDimitry Andric ParmDeclarator.getIdentifierLoc(),
80530b57cec5SDimitry Andric Param, std::move(DefArgToks)));
80540b57cec5SDimitry Andric }
80550b57cec5SDimitry Andric
80560b57cec5SDimitry Andric if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
80570b57cec5SDimitry Andric if (!getLangOpts().CPlusPlus) {
80580b57cec5SDimitry Andric // We have ellipsis without a preceding ',', which is ill-formed
80590b57cec5SDimitry Andric // in C. Complain and provide the fix.
80600b57cec5SDimitry Andric Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
80610b57cec5SDimitry Andric << FixItHint::CreateInsertion(EllipsisLoc, ", ");
80620b57cec5SDimitry Andric } else if (ParmDeclarator.getEllipsisLoc().isValid() ||
80630b57cec5SDimitry Andric Actions.containsUnexpandedParameterPacks(ParmDeclarator)) {
80640b57cec5SDimitry Andric // It looks like this was supposed to be a parameter pack. Warn and
80650b57cec5SDimitry Andric // point out where the ellipsis should have gone.
80660b57cec5SDimitry Andric SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc();
80670b57cec5SDimitry Andric Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg)
80680b57cec5SDimitry Andric << ParmEllipsis.isValid() << ParmEllipsis;
80690b57cec5SDimitry Andric if (ParmEllipsis.isValid()) {
80700b57cec5SDimitry Andric Diag(ParmEllipsis,
80710b57cec5SDimitry Andric diag::note_misplaced_ellipsis_vararg_existing_ellipsis);
80720b57cec5SDimitry Andric } else {
80730b57cec5SDimitry Andric Diag(ParmDeclarator.getIdentifierLoc(),
80740b57cec5SDimitry Andric diag::note_misplaced_ellipsis_vararg_add_ellipsis)
80750b57cec5SDimitry Andric << FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(),
80760b57cec5SDimitry Andric "...")
80770b57cec5SDimitry Andric << !ParmDeclarator.hasName();
80780b57cec5SDimitry Andric }
80790b57cec5SDimitry Andric Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma)
80800b57cec5SDimitry Andric << FixItHint::CreateInsertion(EllipsisLoc, ", ");
80810b57cec5SDimitry Andric }
80820b57cec5SDimitry Andric
80830b57cec5SDimitry Andric // We can't have any more parameters after an ellipsis.
80840b57cec5SDimitry Andric break;
80850b57cec5SDimitry Andric }
80860b57cec5SDimitry Andric
80870b57cec5SDimitry Andric // If the next token is a comma, consume it and keep reading arguments.
80880b57cec5SDimitry Andric } while (TryConsumeToken(tok::comma));
80890b57cec5SDimitry Andric }
80900b57cec5SDimitry Andric
80910b57cec5SDimitry Andric /// [C90] direct-declarator '[' constant-expression[opt] ']'
80920b57cec5SDimitry Andric /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
80930b57cec5SDimitry Andric /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
80940b57cec5SDimitry Andric /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
80950b57cec5SDimitry Andric /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
80960b57cec5SDimitry Andric /// [C++11] direct-declarator '[' constant-expression[opt] ']'
80970b57cec5SDimitry Andric /// attribute-specifier-seq[opt]
ParseBracketDeclarator(Declarator & D)80980b57cec5SDimitry Andric void Parser::ParseBracketDeclarator(Declarator &D) {
80990b57cec5SDimitry Andric if (CheckProhibitedCXX11Attribute())
81000b57cec5SDimitry Andric return;
81010b57cec5SDimitry Andric
81020b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_square);
81030b57cec5SDimitry Andric T.consumeOpen();
81040b57cec5SDimitry Andric
81050b57cec5SDimitry Andric // C array syntax has many features, but by-far the most common is [] and [4].
81060b57cec5SDimitry Andric // This code does a fast path to handle some of the most obvious cases.
81070b57cec5SDimitry Andric if (Tok.getKind() == tok::r_square) {
81080b57cec5SDimitry Andric T.consumeClose();
81090b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory);
81100b57cec5SDimitry Andric MaybeParseCXX11Attributes(attrs);
81110b57cec5SDimitry Andric
81120b57cec5SDimitry Andric // Remember that we parsed the empty array type.
81130b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
81140b57cec5SDimitry Andric T.getOpenLocation(),
81150b57cec5SDimitry Andric T.getCloseLocation()),
81160b57cec5SDimitry Andric std::move(attrs), T.getCloseLocation());
81170b57cec5SDimitry Andric return;
81180b57cec5SDimitry Andric } else if (Tok.getKind() == tok::numeric_constant &&
81190b57cec5SDimitry Andric GetLookAheadToken(1).is(tok::r_square)) {
81200b57cec5SDimitry Andric // [4] is very common. Parse the numeric constant expression.
81210b57cec5SDimitry Andric ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope()));
81220b57cec5SDimitry Andric ConsumeToken();
81230b57cec5SDimitry Andric
81240b57cec5SDimitry Andric T.consumeClose();
81250b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory);
81260b57cec5SDimitry Andric MaybeParseCXX11Attributes(attrs);
81270b57cec5SDimitry Andric
81280b57cec5SDimitry Andric // Remember that we parsed a array type, and remember its features.
81290b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(),
81300b57cec5SDimitry Andric T.getOpenLocation(),
81310b57cec5SDimitry Andric T.getCloseLocation()),
81320b57cec5SDimitry Andric std::move(attrs), T.getCloseLocation());
81330b57cec5SDimitry Andric return;
81340b57cec5SDimitry Andric } else if (Tok.getKind() == tok::code_completion) {
8135fe6060f1SDimitry Andric cutOffParsing();
8136*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteBracketDeclarator(getCurScope());
8137fe6060f1SDimitry Andric return;
81380b57cec5SDimitry Andric }
81390b57cec5SDimitry Andric
81400b57cec5SDimitry Andric // If valid, this location is the position where we read the 'static' keyword.
81410b57cec5SDimitry Andric SourceLocation StaticLoc;
81420b57cec5SDimitry Andric TryConsumeToken(tok::kw_static, StaticLoc);
81430b57cec5SDimitry Andric
81440b57cec5SDimitry Andric // If there is a type-qualifier-list, read it now.
81450b57cec5SDimitry Andric // Type qualifiers in an array subscript are a C99 feature.
81460b57cec5SDimitry Andric DeclSpec DS(AttrFactory);
81470b57cec5SDimitry Andric ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed);
81480b57cec5SDimitry Andric
81490b57cec5SDimitry Andric // If we haven't already read 'static', check to see if there is one after the
81500b57cec5SDimitry Andric // type-qualifier-list.
81510b57cec5SDimitry Andric if (!StaticLoc.isValid())
81520b57cec5SDimitry Andric TryConsumeToken(tok::kw_static, StaticLoc);
81530b57cec5SDimitry Andric
81540b57cec5SDimitry Andric // Handle "direct-declarator [ type-qual-list[opt] * ]".
81550b57cec5SDimitry Andric bool isStar = false;
81560b57cec5SDimitry Andric ExprResult NumElements;
81570b57cec5SDimitry Andric
81580b57cec5SDimitry Andric // Handle the case where we have '[*]' as the array size. However, a leading
81590b57cec5SDimitry Andric // star could be the start of an expression, for example 'X[*p + 4]'. Verify
81600b57cec5SDimitry Andric // the token after the star is a ']'. Since stars in arrays are
81610b57cec5SDimitry Andric // infrequent, use of lookahead is not costly here.
81620b57cec5SDimitry Andric if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) {
81630b57cec5SDimitry Andric ConsumeToken(); // Eat the '*'.
81640b57cec5SDimitry Andric
81650b57cec5SDimitry Andric if (StaticLoc.isValid()) {
81660b57cec5SDimitry Andric Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
81670b57cec5SDimitry Andric StaticLoc = SourceLocation(); // Drop the static.
81680b57cec5SDimitry Andric }
81690b57cec5SDimitry Andric isStar = true;
81700b57cec5SDimitry Andric } else if (Tok.isNot(tok::r_square)) {
81710b57cec5SDimitry Andric // Note, in C89, this production uses the constant-expr production instead
81720b57cec5SDimitry Andric // of assignment-expr. The only difference is that assignment-expr allows
81730b57cec5SDimitry Andric // things like '=' and '*='. Sema rejects these in C89 mode because they
81740b57cec5SDimitry Andric // are not i-c-e's, so we don't need to distinguish between the two here.
81750b57cec5SDimitry Andric
81760b57cec5SDimitry Andric // Parse the constant-expression or assignment-expression now (depending
81770b57cec5SDimitry Andric // on dialect).
81780b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) {
81795f757f3fSDimitry Andric NumElements = ParseArrayBoundExpression();
81800b57cec5SDimitry Andric } else {
81810b57cec5SDimitry Andric EnterExpressionEvaluationContext Unevaluated(
81820b57cec5SDimitry Andric Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
81830b57cec5SDimitry Andric NumElements =
81840b57cec5SDimitry Andric Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
81850b57cec5SDimitry Andric }
81860b57cec5SDimitry Andric } else {
81870b57cec5SDimitry Andric if (StaticLoc.isValid()) {
81880b57cec5SDimitry Andric Diag(StaticLoc, diag::err_unspecified_size_with_static);
81890b57cec5SDimitry Andric StaticLoc = SourceLocation(); // Drop the static.
81900b57cec5SDimitry Andric }
81910b57cec5SDimitry Andric }
81920b57cec5SDimitry Andric
81930b57cec5SDimitry Andric // If there was an error parsing the assignment-expression, recover.
81940b57cec5SDimitry Andric if (NumElements.isInvalid()) {
81950b57cec5SDimitry Andric D.setInvalidType(true);
81960b57cec5SDimitry Andric // If the expression was invalid, skip it.
81970b57cec5SDimitry Andric SkipUntil(tok::r_square, StopAtSemi);
81980b57cec5SDimitry Andric return;
81990b57cec5SDimitry Andric }
82000b57cec5SDimitry Andric
82010b57cec5SDimitry Andric T.consumeClose();
82020b57cec5SDimitry Andric
82030b57cec5SDimitry Andric MaybeParseCXX11Attributes(DS.getAttributes());
82040b57cec5SDimitry Andric
82050b57cec5SDimitry Andric // Remember that we parsed a array type, and remember its features.
82060b57cec5SDimitry Andric D.AddTypeInfo(
82070b57cec5SDimitry Andric DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(),
82080b57cec5SDimitry Andric isStar, NumElements.get(), T.getOpenLocation(),
82090b57cec5SDimitry Andric T.getCloseLocation()),
82100b57cec5SDimitry Andric std::move(DS.getAttributes()), T.getCloseLocation());
82110b57cec5SDimitry Andric }
82120b57cec5SDimitry Andric
82130b57cec5SDimitry Andric /// Diagnose brackets before an identifier.
ParseMisplacedBracketDeclarator(Declarator & D)82140b57cec5SDimitry Andric void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
82150b57cec5SDimitry Andric assert(Tok.is(tok::l_square) && "Missing opening bracket");
82160b57cec5SDimitry Andric assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier");
82170b57cec5SDimitry Andric
82180b57cec5SDimitry Andric SourceLocation StartBracketLoc = Tok.getLocation();
821981ad6265SDimitry Andric Declarator TempDeclarator(D.getDeclSpec(), ParsedAttributesView::none(),
822081ad6265SDimitry Andric D.getContext());
82210b57cec5SDimitry Andric
82220b57cec5SDimitry Andric while (Tok.is(tok::l_square)) {
82230b57cec5SDimitry Andric ParseBracketDeclarator(TempDeclarator);
82240b57cec5SDimitry Andric }
82250b57cec5SDimitry Andric
82260b57cec5SDimitry Andric // Stuff the location of the start of the brackets into the Declarator.
82270b57cec5SDimitry Andric // The diagnostics from ParseDirectDeclarator will make more sense if
82280b57cec5SDimitry Andric // they use this location instead.
82290b57cec5SDimitry Andric if (Tok.is(tok::semi))
82300b57cec5SDimitry Andric D.getName().EndLocation = StartBracketLoc;
82310b57cec5SDimitry Andric
82320b57cec5SDimitry Andric SourceLocation SuggestParenLoc = Tok.getLocation();
82330b57cec5SDimitry Andric
82340b57cec5SDimitry Andric // Now that the brackets are removed, try parsing the declarator again.
82350b57cec5SDimitry Andric ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
82360b57cec5SDimitry Andric
82370b57cec5SDimitry Andric // Something went wrong parsing the brackets, in which case,
82380b57cec5SDimitry Andric // ParseBracketDeclarator has emitted an error, and we don't need to emit
82390b57cec5SDimitry Andric // one here.
82400b57cec5SDimitry Andric if (TempDeclarator.getNumTypeObjects() == 0)
82410b57cec5SDimitry Andric return;
82420b57cec5SDimitry Andric
82430b57cec5SDimitry Andric // Determine if parens will need to be suggested in the diagnostic.
82440b57cec5SDimitry Andric bool NeedParens = false;
82450b57cec5SDimitry Andric if (D.getNumTypeObjects() != 0) {
82460b57cec5SDimitry Andric switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) {
82470b57cec5SDimitry Andric case DeclaratorChunk::Pointer:
82480b57cec5SDimitry Andric case DeclaratorChunk::Reference:
82490b57cec5SDimitry Andric case DeclaratorChunk::BlockPointer:
82500b57cec5SDimitry Andric case DeclaratorChunk::MemberPointer:
82510b57cec5SDimitry Andric case DeclaratorChunk::Pipe:
82520b57cec5SDimitry Andric NeedParens = true;
82530b57cec5SDimitry Andric break;
82540b57cec5SDimitry Andric case DeclaratorChunk::Array:
82550b57cec5SDimitry Andric case DeclaratorChunk::Function:
82560b57cec5SDimitry Andric case DeclaratorChunk::Paren:
82570b57cec5SDimitry Andric break;
82580b57cec5SDimitry Andric }
82590b57cec5SDimitry Andric }
82600b57cec5SDimitry Andric
82610b57cec5SDimitry Andric if (NeedParens) {
82620b57cec5SDimitry Andric // Create a DeclaratorChunk for the inserted parens.
82630b57cec5SDimitry Andric SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
82640b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc),
82650b57cec5SDimitry Andric SourceLocation());
82660b57cec5SDimitry Andric }
82670b57cec5SDimitry Andric
82680b57cec5SDimitry Andric // Adding back the bracket info to the end of the Declarator.
82690b57cec5SDimitry Andric for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {
82700b57cec5SDimitry Andric const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);
8271*0fca6ea1SDimitry Andric D.AddTypeInfo(Chunk, TempDeclarator.getAttributePool(), SourceLocation());
82720b57cec5SDimitry Andric }
82730b57cec5SDimitry Andric
82740b57cec5SDimitry Andric // The missing identifier would have been diagnosed in ParseDirectDeclarator.
82750b57cec5SDimitry Andric // If parentheses are required, always suggest them.
82760b57cec5SDimitry Andric if (!D.getIdentifier() && !NeedParens)
82770b57cec5SDimitry Andric return;
82780b57cec5SDimitry Andric
82790b57cec5SDimitry Andric SourceLocation EndBracketLoc = TempDeclarator.getEndLoc();
82800b57cec5SDimitry Andric
82810b57cec5SDimitry Andric // Generate the move bracket error message.
82820b57cec5SDimitry Andric SourceRange BracketRange(StartBracketLoc, EndBracketLoc);
82830b57cec5SDimitry Andric SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
82840b57cec5SDimitry Andric
82850b57cec5SDimitry Andric if (NeedParens) {
82860b57cec5SDimitry Andric Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
82870b57cec5SDimitry Andric << getLangOpts().CPlusPlus
82880b57cec5SDimitry Andric << FixItHint::CreateInsertion(SuggestParenLoc, "(")
82890b57cec5SDimitry Andric << FixItHint::CreateInsertion(EndLoc, ")")
82900b57cec5SDimitry Andric << FixItHint::CreateInsertionFromRange(
82910b57cec5SDimitry Andric EndLoc, CharSourceRange(BracketRange, true))
82920b57cec5SDimitry Andric << FixItHint::CreateRemoval(BracketRange);
82930b57cec5SDimitry Andric } else {
82940b57cec5SDimitry Andric Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
82950b57cec5SDimitry Andric << getLangOpts().CPlusPlus
82960b57cec5SDimitry Andric << FixItHint::CreateInsertionFromRange(
82970b57cec5SDimitry Andric EndLoc, CharSourceRange(BracketRange, true))
82980b57cec5SDimitry Andric << FixItHint::CreateRemoval(BracketRange);
82990b57cec5SDimitry Andric }
83000b57cec5SDimitry Andric }
83010b57cec5SDimitry Andric
83020b57cec5SDimitry Andric /// [GNU] typeof-specifier:
83030b57cec5SDimitry Andric /// typeof ( expressions )
83040b57cec5SDimitry Andric /// typeof ( type-name )
83050b57cec5SDimitry Andric /// [GNU/C++] typeof unary-expression
83065f757f3fSDimitry Andric /// [C23] typeof-specifier:
8307bdd1243dSDimitry Andric /// typeof '(' typeof-specifier-argument ')'
8308bdd1243dSDimitry Andric /// typeof_unqual '(' typeof-specifier-argument ')'
8309bdd1243dSDimitry Andric ///
8310bdd1243dSDimitry Andric /// typeof-specifier-argument:
8311bdd1243dSDimitry Andric /// expression
8312bdd1243dSDimitry Andric /// type-name
83130b57cec5SDimitry Andric ///
ParseTypeofSpecifier(DeclSpec & DS)83140b57cec5SDimitry Andric void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
8315bdd1243dSDimitry Andric assert(Tok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&
8316bdd1243dSDimitry Andric "Not a typeof specifier");
8317bdd1243dSDimitry Andric
8318bdd1243dSDimitry Andric bool IsUnqual = Tok.is(tok::kw_typeof_unqual);
8319bdd1243dSDimitry Andric const IdentifierInfo *II = Tok.getIdentifierInfo();
83205f757f3fSDimitry Andric if (getLangOpts().C23 && !II->getName().starts_with("__"))
83215f757f3fSDimitry Andric Diag(Tok.getLocation(), diag::warn_c23_compat_keyword) << Tok.getName();
8322bdd1243dSDimitry Andric
83230b57cec5SDimitry Andric Token OpTok = Tok;
83240b57cec5SDimitry Andric SourceLocation StartLoc = ConsumeToken();
8325bdd1243dSDimitry Andric bool HasParens = Tok.is(tok::l_paren);
83260b57cec5SDimitry Andric
83270b57cec5SDimitry Andric EnterExpressionEvaluationContext Unevaluated(
83280b57cec5SDimitry Andric Actions, Sema::ExpressionEvaluationContext::Unevaluated,
83290b57cec5SDimitry Andric Sema::ReuseLambdaContextDecl);
83300b57cec5SDimitry Andric
83310b57cec5SDimitry Andric bool isCastExpr;
83320b57cec5SDimitry Andric ParsedType CastTy;
83330b57cec5SDimitry Andric SourceRange CastRange;
83340b57cec5SDimitry Andric ExprResult Operand = Actions.CorrectDelayedTyposInExpr(
83350b57cec5SDimitry Andric ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));
8336bdd1243dSDimitry Andric if (HasParens)
8337bdd1243dSDimitry Andric DS.setTypeArgumentRange(CastRange);
83380b57cec5SDimitry Andric
83390b57cec5SDimitry Andric if (CastRange.getEnd().isInvalid())
83400b57cec5SDimitry Andric // FIXME: Not accurate, the range gets one token more than it should.
83410b57cec5SDimitry Andric DS.SetRangeEnd(Tok.getLocation());
83420b57cec5SDimitry Andric else
83430b57cec5SDimitry Andric DS.SetRangeEnd(CastRange.getEnd());
83440b57cec5SDimitry Andric
83450b57cec5SDimitry Andric if (isCastExpr) {
83460b57cec5SDimitry Andric if (!CastTy) {
83470b57cec5SDimitry Andric DS.SetTypeSpecError();
83480b57cec5SDimitry Andric return;
83490b57cec5SDimitry Andric }
83500b57cec5SDimitry Andric
83510b57cec5SDimitry Andric const char *PrevSpec = nullptr;
83520b57cec5SDimitry Andric unsigned DiagID;
83530b57cec5SDimitry Andric // Check for duplicate type specifiers (e.g. "int typeof(int)").
8354bdd1243dSDimitry Andric if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualType
8355bdd1243dSDimitry Andric : DeclSpec::TST_typeofType,
8356bdd1243dSDimitry Andric StartLoc, PrevSpec,
83570b57cec5SDimitry Andric DiagID, CastTy,
83580b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
83590b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
83600b57cec5SDimitry Andric return;
83610b57cec5SDimitry Andric }
83620b57cec5SDimitry Andric
83630b57cec5SDimitry Andric // If we get here, the operand to the typeof was an expression.
83640b57cec5SDimitry Andric if (Operand.isInvalid()) {
83650b57cec5SDimitry Andric DS.SetTypeSpecError();
83660b57cec5SDimitry Andric return;
83670b57cec5SDimitry Andric }
83680b57cec5SDimitry Andric
83690b57cec5SDimitry Andric // We might need to transform the operand if it is potentially evaluated.
83700b57cec5SDimitry Andric Operand = Actions.HandleExprEvaluationContextForTypeof(Operand.get());
83710b57cec5SDimitry Andric if (Operand.isInvalid()) {
83720b57cec5SDimitry Andric DS.SetTypeSpecError();
83730b57cec5SDimitry Andric return;
83740b57cec5SDimitry Andric }
83750b57cec5SDimitry Andric
83760b57cec5SDimitry Andric const char *PrevSpec = nullptr;
83770b57cec5SDimitry Andric unsigned DiagID;
83780b57cec5SDimitry Andric // Check for duplicate type specifiers (e.g. "int typeof(int)").
8379bdd1243dSDimitry Andric if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualExpr
8380bdd1243dSDimitry Andric : DeclSpec::TST_typeofExpr,
8381bdd1243dSDimitry Andric StartLoc, PrevSpec,
83820b57cec5SDimitry Andric DiagID, Operand.get(),
83830b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
83840b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
83850b57cec5SDimitry Andric }
83860b57cec5SDimitry Andric
83870b57cec5SDimitry Andric /// [C11] atomic-specifier:
83880b57cec5SDimitry Andric /// _Atomic ( type-name )
83890b57cec5SDimitry Andric ///
ParseAtomicSpecifier(DeclSpec & DS)83900b57cec5SDimitry Andric void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
83910b57cec5SDimitry Andric assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) &&
83920b57cec5SDimitry Andric "Not an atomic specifier");
83930b57cec5SDimitry Andric
83940b57cec5SDimitry Andric SourceLocation StartLoc = ConsumeToken();
83950b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren);
83960b57cec5SDimitry Andric if (T.consumeOpen())
83970b57cec5SDimitry Andric return;
83980b57cec5SDimitry Andric
83990b57cec5SDimitry Andric TypeResult Result = ParseTypeName();
84000b57cec5SDimitry Andric if (Result.isInvalid()) {
84010b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi);
84020b57cec5SDimitry Andric return;
84030b57cec5SDimitry Andric }
84040b57cec5SDimitry Andric
84050b57cec5SDimitry Andric // Match the ')'
84060b57cec5SDimitry Andric T.consumeClose();
84070b57cec5SDimitry Andric
84080b57cec5SDimitry Andric if (T.getCloseLocation().isInvalid())
84090b57cec5SDimitry Andric return;
84100b57cec5SDimitry Andric
8411bdd1243dSDimitry Andric DS.setTypeArgumentRange(T.getRange());
84120b57cec5SDimitry Andric DS.SetRangeEnd(T.getCloseLocation());
84130b57cec5SDimitry Andric
84140b57cec5SDimitry Andric const char *PrevSpec = nullptr;
84150b57cec5SDimitry Andric unsigned DiagID;
84160b57cec5SDimitry Andric if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
84170b57cec5SDimitry Andric DiagID, Result.get(),
84180b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()))
84190b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec;
84200b57cec5SDimitry Andric }
84210b57cec5SDimitry Andric
84220b57cec5SDimitry Andric /// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
84230b57cec5SDimitry Andric /// from TryAltiVecVectorToken.
TryAltiVecVectorTokenOutOfLine()84240b57cec5SDimitry Andric bool Parser::TryAltiVecVectorTokenOutOfLine() {
84250b57cec5SDimitry Andric Token Next = NextToken();
84260b57cec5SDimitry Andric switch (Next.getKind()) {
84270b57cec5SDimitry Andric default: return false;
84280b57cec5SDimitry Andric case tok::kw_short:
84290b57cec5SDimitry Andric case tok::kw_long:
84300b57cec5SDimitry Andric case tok::kw_signed:
84310b57cec5SDimitry Andric case tok::kw_unsigned:
84320b57cec5SDimitry Andric case tok::kw_void:
84330b57cec5SDimitry Andric case tok::kw_char:
84340b57cec5SDimitry Andric case tok::kw_int:
84350b57cec5SDimitry Andric case tok::kw_float:
84360b57cec5SDimitry Andric case tok::kw_double:
84370b57cec5SDimitry Andric case tok::kw_bool:
8438fe6060f1SDimitry Andric case tok::kw__Bool:
84390b57cec5SDimitry Andric case tok::kw___bool:
84400b57cec5SDimitry Andric case tok::kw___pixel:
84410b57cec5SDimitry Andric Tok.setKind(tok::kw___vector);
84420b57cec5SDimitry Andric return true;
84430b57cec5SDimitry Andric case tok::identifier:
84440b57cec5SDimitry Andric if (Next.getIdentifierInfo() == Ident_pixel) {
84450b57cec5SDimitry Andric Tok.setKind(tok::kw___vector);
84460b57cec5SDimitry Andric return true;
84470b57cec5SDimitry Andric }
8448fe6060f1SDimitry Andric if (Next.getIdentifierInfo() == Ident_bool ||
8449fe6060f1SDimitry Andric Next.getIdentifierInfo() == Ident_Bool) {
84500b57cec5SDimitry Andric Tok.setKind(tok::kw___vector);
84510b57cec5SDimitry Andric return true;
84520b57cec5SDimitry Andric }
84530b57cec5SDimitry Andric return false;
84540b57cec5SDimitry Andric }
84550b57cec5SDimitry Andric }
84560b57cec5SDimitry Andric
TryAltiVecTokenOutOfLine(DeclSpec & DS,SourceLocation Loc,const char * & PrevSpec,unsigned & DiagID,bool & isInvalid)84570b57cec5SDimitry Andric bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
84580b57cec5SDimitry Andric const char *&PrevSpec, unsigned &DiagID,
84590b57cec5SDimitry Andric bool &isInvalid) {
84600b57cec5SDimitry Andric const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
84610b57cec5SDimitry Andric if (Tok.getIdentifierInfo() == Ident_vector) {
84620b57cec5SDimitry Andric Token Next = NextToken();
84630b57cec5SDimitry Andric switch (Next.getKind()) {
84640b57cec5SDimitry Andric case tok::kw_short:
84650b57cec5SDimitry Andric case tok::kw_long:
84660b57cec5SDimitry Andric case tok::kw_signed:
84670b57cec5SDimitry Andric case tok::kw_unsigned:
84680b57cec5SDimitry Andric case tok::kw_void:
84690b57cec5SDimitry Andric case tok::kw_char:
84700b57cec5SDimitry Andric case tok::kw_int:
84710b57cec5SDimitry Andric case tok::kw_float:
84720b57cec5SDimitry Andric case tok::kw_double:
84730b57cec5SDimitry Andric case tok::kw_bool:
8474fe6060f1SDimitry Andric case tok::kw__Bool:
84750b57cec5SDimitry Andric case tok::kw___bool:
84760b57cec5SDimitry Andric case tok::kw___pixel:
84770b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
84780b57cec5SDimitry Andric return true;
84790b57cec5SDimitry Andric case tok::identifier:
84800b57cec5SDimitry Andric if (Next.getIdentifierInfo() == Ident_pixel) {
84810b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
84820b57cec5SDimitry Andric return true;
84830b57cec5SDimitry Andric }
8484fe6060f1SDimitry Andric if (Next.getIdentifierInfo() == Ident_bool ||
8485fe6060f1SDimitry Andric Next.getIdentifierInfo() == Ident_Bool) {
8486fe6060f1SDimitry Andric isInvalid =
8487fe6060f1SDimitry Andric DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
84880b57cec5SDimitry Andric return true;
84890b57cec5SDimitry Andric }
84900b57cec5SDimitry Andric break;
84910b57cec5SDimitry Andric default:
84920b57cec5SDimitry Andric break;
84930b57cec5SDimitry Andric }
84940b57cec5SDimitry Andric } else if ((Tok.getIdentifierInfo() == Ident_pixel) &&
84950b57cec5SDimitry Andric DS.isTypeAltiVecVector()) {
84960b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
84970b57cec5SDimitry Andric return true;
84980b57cec5SDimitry Andric } else if ((Tok.getIdentifierInfo() == Ident_bool) &&
84990b57cec5SDimitry Andric DS.isTypeAltiVecVector()) {
85000b57cec5SDimitry Andric isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
85010b57cec5SDimitry Andric return true;
85020b57cec5SDimitry Andric }
85030b57cec5SDimitry Andric return false;
85040b57cec5SDimitry Andric }
85050eae32dcSDimitry Andric
ParseTypeFromString(StringRef TypeStr,StringRef Context,SourceLocation IncludeLoc)85067a6dacacSDimitry Andric TypeResult Parser::ParseTypeFromString(StringRef TypeStr, StringRef Context,
85077a6dacacSDimitry Andric SourceLocation IncludeLoc) {
85087a6dacacSDimitry Andric // Consume (unexpanded) tokens up to the end-of-directive.
85097a6dacacSDimitry Andric SmallVector<Token, 4> Tokens;
85107a6dacacSDimitry Andric {
85117a6dacacSDimitry Andric // Create a new buffer from which we will parse the type.
85127a6dacacSDimitry Andric auto &SourceMgr = PP.getSourceManager();
85137a6dacacSDimitry Andric FileID FID = SourceMgr.createFileID(
85147a6dacacSDimitry Andric llvm::MemoryBuffer::getMemBufferCopy(TypeStr, Context), SrcMgr::C_User,
85157a6dacacSDimitry Andric 0, 0, IncludeLoc);
85167a6dacacSDimitry Andric
85177a6dacacSDimitry Andric // Form a new lexer that references the buffer.
85187a6dacacSDimitry Andric Lexer L(FID, SourceMgr.getBufferOrFake(FID), PP);
85197a6dacacSDimitry Andric L.setParsingPreprocessorDirective(true);
85207a6dacacSDimitry Andric
85217a6dacacSDimitry Andric // Lex the tokens from that buffer.
85227a6dacacSDimitry Andric Token Tok;
85237a6dacacSDimitry Andric do {
85247a6dacacSDimitry Andric L.Lex(Tok);
85257a6dacacSDimitry Andric Tokens.push_back(Tok);
85267a6dacacSDimitry Andric } while (Tok.isNot(tok::eod));
85277a6dacacSDimitry Andric }
85287a6dacacSDimitry Andric
85297a6dacacSDimitry Andric // Replace the "eod" token with an "eof" token identifying the end of
85307a6dacacSDimitry Andric // the provided string.
85317a6dacacSDimitry Andric Token &EndToken = Tokens.back();
85327a6dacacSDimitry Andric EndToken.startToken();
85337a6dacacSDimitry Andric EndToken.setKind(tok::eof);
85347a6dacacSDimitry Andric EndToken.setLocation(Tok.getLocation());
85357a6dacacSDimitry Andric EndToken.setEofData(TypeStr.data());
85367a6dacacSDimitry Andric
85377a6dacacSDimitry Andric // Add the current token back.
85387a6dacacSDimitry Andric Tokens.push_back(Tok);
85397a6dacacSDimitry Andric
85407a6dacacSDimitry Andric // Enter the tokens into the token stream.
85417a6dacacSDimitry Andric PP.EnterTokenStream(Tokens, /*DisableMacroExpansion=*/false,
85427a6dacacSDimitry Andric /*IsReinject=*/false);
85437a6dacacSDimitry Andric
85447a6dacacSDimitry Andric // Consume the current token so that we'll start parsing the tokens we
85457a6dacacSDimitry Andric // added to the stream.
85467a6dacacSDimitry Andric ConsumeAnyToken();
85477a6dacacSDimitry Andric
85487a6dacacSDimitry Andric // Enter a new scope.
85497a6dacacSDimitry Andric ParseScope LocalScope(this, 0);
85507a6dacacSDimitry Andric
85517a6dacacSDimitry Andric // Parse the type.
85527a6dacacSDimitry Andric TypeResult Result = ParseTypeName(nullptr);
85537a6dacacSDimitry Andric
85547a6dacacSDimitry Andric // Check if we parsed the whole thing.
85557a6dacacSDimitry Andric if (Result.isUsable() &&
85567a6dacacSDimitry Andric (Tok.isNot(tok::eof) || Tok.getEofData() != TypeStr.data())) {
85577a6dacacSDimitry Andric Diag(Tok.getLocation(), diag::err_type_unparsed);
85587a6dacacSDimitry Andric }
85597a6dacacSDimitry Andric
85607a6dacacSDimitry Andric // There could be leftover tokens (e.g. because of an error).
85617a6dacacSDimitry Andric // Skip through until we reach the 'end of directive' token.
85627a6dacacSDimitry Andric while (Tok.isNot(tok::eof))
85637a6dacacSDimitry Andric ConsumeAnyToken();
85647a6dacacSDimitry Andric
85657a6dacacSDimitry Andric // Consume the end token.
85667a6dacacSDimitry Andric if (Tok.is(tok::eof) && Tok.getEofData() == TypeStr.data())
85677a6dacacSDimitry Andric ConsumeAnyToken();
85687a6dacacSDimitry Andric return Result;
85697a6dacacSDimitry Andric }
85707a6dacacSDimitry Andric
DiagnoseBitIntUse(const Token & Tok)85710eae32dcSDimitry Andric void Parser::DiagnoseBitIntUse(const Token &Tok) {
85720eae32dcSDimitry Andric // If the token is for _ExtInt, diagnose it as being deprecated. Otherwise,
85730eae32dcSDimitry Andric // the token is about _BitInt and gets (potentially) diagnosed as use of an
85740eae32dcSDimitry Andric // extension.
85750eae32dcSDimitry Andric assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) &&
85760eae32dcSDimitry Andric "expected either an _ExtInt or _BitInt token!");
85770eae32dcSDimitry Andric
85780eae32dcSDimitry Andric SourceLocation Loc = Tok.getLocation();
85790eae32dcSDimitry Andric if (Tok.is(tok::kw__ExtInt)) {
85800eae32dcSDimitry Andric Diag(Loc, diag::warn_ext_int_deprecated)
85810eae32dcSDimitry Andric << FixItHint::CreateReplacement(Loc, "_BitInt");
85820eae32dcSDimitry Andric } else {
85835f757f3fSDimitry Andric // In C23 mode, diagnose that the use is not compatible with pre-C23 modes.
85840eae32dcSDimitry Andric // Otherwise, diagnose that the use is a Clang extension.
85855f757f3fSDimitry Andric if (getLangOpts().C23)
85865f757f3fSDimitry Andric Diag(Loc, diag::warn_c23_compat_keyword) << Tok.getName();
85870eae32dcSDimitry Andric else
85880eae32dcSDimitry Andric Diag(Loc, diag::ext_bit_int) << getLangOpts().CPlusPlus;
85890eae32dcSDimitry Andric }
85900eae32dcSDimitry Andric }
8591