17330f729Sjoerg //===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the Declaration portions of the Parser interfaces.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "clang/Parse/Parser.h"
147330f729Sjoerg #include "clang/Parse/RAIIObjectsForParser.h"
157330f729Sjoerg #include "clang/AST/ASTContext.h"
167330f729Sjoerg #include "clang/AST/DeclTemplate.h"
177330f729Sjoerg #include "clang/AST/PrettyDeclStackTrace.h"
187330f729Sjoerg #include "clang/Basic/AddressSpaces.h"
197330f729Sjoerg #include "clang/Basic/Attributes.h"
207330f729Sjoerg #include "clang/Basic/CharInfo.h"
217330f729Sjoerg #include "clang/Basic/TargetInfo.h"
227330f729Sjoerg #include "clang/Parse/ParseDiagnostic.h"
237330f729Sjoerg #include "clang/Sema/Lookup.h"
247330f729Sjoerg #include "clang/Sema/ParsedTemplate.h"
257330f729Sjoerg #include "clang/Sema/Scope.h"
26*e038c9c4Sjoerg #include "clang/Sema/SemaDiagnostic.h"
277330f729Sjoerg #include "llvm/ADT/Optional.h"
287330f729Sjoerg #include "llvm/ADT/SmallSet.h"
297330f729Sjoerg #include "llvm/ADT/SmallString.h"
307330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
317330f729Sjoerg
327330f729Sjoerg using namespace clang;
337330f729Sjoerg
347330f729Sjoerg //===----------------------------------------------------------------------===//
357330f729Sjoerg // C99 6.7: Declarations.
367330f729Sjoerg //===----------------------------------------------------------------------===//
377330f729Sjoerg
387330f729Sjoerg /// ParseTypeName
397330f729Sjoerg /// type-name: [C99 6.7.6]
407330f729Sjoerg /// specifier-qualifier-list abstract-declarator[opt]
417330f729Sjoerg ///
427330f729Sjoerg /// Called type-id in C++.
ParseTypeName(SourceRange * Range,DeclaratorContext Context,AccessSpecifier AS,Decl ** OwnedType,ParsedAttributes * Attrs)437330f729Sjoerg TypeResult Parser::ParseTypeName(SourceRange *Range,
447330f729Sjoerg DeclaratorContext Context,
457330f729Sjoerg AccessSpecifier AS,
467330f729Sjoerg Decl **OwnedType,
477330f729Sjoerg ParsedAttributes *Attrs) {
487330f729Sjoerg DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);
497330f729Sjoerg if (DSC == DeclSpecContext::DSC_normal)
507330f729Sjoerg DSC = DeclSpecContext::DSC_type_specifier;
517330f729Sjoerg
527330f729Sjoerg // Parse the common declaration-specifiers piece.
537330f729Sjoerg DeclSpec DS(AttrFactory);
547330f729Sjoerg if (Attrs)
557330f729Sjoerg DS.addAttributes(*Attrs);
567330f729Sjoerg ParseSpecifierQualifierList(DS, AS, DSC);
577330f729Sjoerg if (OwnedType)
587330f729Sjoerg *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;
597330f729Sjoerg
607330f729Sjoerg // Parse the abstract-declarator, if present.
617330f729Sjoerg Declarator DeclaratorInfo(DS, Context);
627330f729Sjoerg ParseDeclarator(DeclaratorInfo);
637330f729Sjoerg if (Range)
647330f729Sjoerg *Range = DeclaratorInfo.getSourceRange();
657330f729Sjoerg
667330f729Sjoerg if (DeclaratorInfo.isInvalidType())
677330f729Sjoerg return true;
687330f729Sjoerg
697330f729Sjoerg return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
707330f729Sjoerg }
717330f729Sjoerg
727330f729Sjoerg /// Normalizes an attribute name by dropping prefixed and suffixed __.
normalizeAttrName(StringRef Name)737330f729Sjoerg static StringRef normalizeAttrName(StringRef Name) {
747330f729Sjoerg if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
757330f729Sjoerg return Name.drop_front(2).drop_back(2);
767330f729Sjoerg return Name;
777330f729Sjoerg }
787330f729Sjoerg
797330f729Sjoerg /// isAttributeLateParsed - Return true if the attribute has arguments that
807330f729Sjoerg /// require late parsing.
isAttributeLateParsed(const IdentifierInfo & II)817330f729Sjoerg static bool isAttributeLateParsed(const IdentifierInfo &II) {
827330f729Sjoerg #define CLANG_ATTR_LATE_PARSED_LIST
837330f729Sjoerg return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
847330f729Sjoerg #include "clang/Parse/AttrParserStringSwitches.inc"
857330f729Sjoerg .Default(false);
867330f729Sjoerg #undef CLANG_ATTR_LATE_PARSED_LIST
877330f729Sjoerg }
887330f729Sjoerg
897330f729Sjoerg /// Check if the a start and end source location expand to the same macro.
FindLocsWithCommonFileID(Preprocessor & PP,SourceLocation StartLoc,SourceLocation EndLoc)907330f729Sjoerg static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc,
917330f729Sjoerg SourceLocation EndLoc) {
927330f729Sjoerg if (!StartLoc.isMacroID() || !EndLoc.isMacroID())
937330f729Sjoerg return false;
947330f729Sjoerg
957330f729Sjoerg SourceManager &SM = PP.getSourceManager();
967330f729Sjoerg if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc))
977330f729Sjoerg return false;
987330f729Sjoerg
997330f729Sjoerg bool AttrStartIsInMacro =
1007330f729Sjoerg Lexer::isAtStartOfMacroExpansion(StartLoc, SM, PP.getLangOpts());
1017330f729Sjoerg bool AttrEndIsInMacro =
1027330f729Sjoerg Lexer::isAtEndOfMacroExpansion(EndLoc, SM, PP.getLangOpts());
1037330f729Sjoerg return AttrStartIsInMacro && AttrEndIsInMacro;
1047330f729Sjoerg }
1057330f729Sjoerg
ParseAttributes(unsigned WhichAttrKinds,ParsedAttributesWithRange & Attrs,SourceLocation * End,LateParsedAttrList * LateAttrs)106*e038c9c4Sjoerg void Parser::ParseAttributes(unsigned WhichAttrKinds,
107*e038c9c4Sjoerg ParsedAttributesWithRange &Attrs,
108*e038c9c4Sjoerg SourceLocation *End,
109*e038c9c4Sjoerg LateParsedAttrList *LateAttrs) {
110*e038c9c4Sjoerg bool MoreToParse;
111*e038c9c4Sjoerg do {
112*e038c9c4Sjoerg // Assume there's nothing left to parse, but if any attributes are in fact
113*e038c9c4Sjoerg // parsed, loop to ensure all specified attribute combinations are parsed.
114*e038c9c4Sjoerg MoreToParse = false;
115*e038c9c4Sjoerg if (WhichAttrKinds & PAKM_CXX11)
116*e038c9c4Sjoerg MoreToParse |= MaybeParseCXX11Attributes(Attrs, End);
117*e038c9c4Sjoerg if (WhichAttrKinds & PAKM_GNU)
118*e038c9c4Sjoerg MoreToParse |= MaybeParseGNUAttributes(Attrs, End, LateAttrs);
119*e038c9c4Sjoerg if (WhichAttrKinds & PAKM_Declspec)
120*e038c9c4Sjoerg MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs, End);
121*e038c9c4Sjoerg } while (MoreToParse);
122*e038c9c4Sjoerg }
123*e038c9c4Sjoerg
1247330f729Sjoerg /// ParseGNUAttributes - Parse a non-empty attributes list.
1257330f729Sjoerg ///
1267330f729Sjoerg /// [GNU] attributes:
1277330f729Sjoerg /// attribute
1287330f729Sjoerg /// attributes attribute
1297330f729Sjoerg ///
1307330f729Sjoerg /// [GNU] attribute:
1317330f729Sjoerg /// '__attribute__' '(' '(' attribute-list ')' ')'
1327330f729Sjoerg ///
1337330f729Sjoerg /// [GNU] attribute-list:
1347330f729Sjoerg /// attrib
1357330f729Sjoerg /// attribute_list ',' attrib
1367330f729Sjoerg ///
1377330f729Sjoerg /// [GNU] attrib:
1387330f729Sjoerg /// empty
1397330f729Sjoerg /// attrib-name
1407330f729Sjoerg /// attrib-name '(' identifier ')'
1417330f729Sjoerg /// attrib-name '(' identifier ',' nonempty-expr-list ')'
1427330f729Sjoerg /// attrib-name '(' argument-expression-list [C99 6.5.2] ')'
1437330f729Sjoerg ///
1447330f729Sjoerg /// [GNU] attrib-name:
1457330f729Sjoerg /// identifier
1467330f729Sjoerg /// typespec
1477330f729Sjoerg /// typequal
1487330f729Sjoerg /// storageclass
1497330f729Sjoerg ///
1507330f729Sjoerg /// Whether an attribute takes an 'identifier' is determined by the
1517330f729Sjoerg /// attrib-name. GCC's behavior here is not worth imitating:
1527330f729Sjoerg ///
1537330f729Sjoerg /// * In C mode, if the attribute argument list starts with an identifier
1547330f729Sjoerg /// followed by a ',' or an ')', and the identifier doesn't resolve to
1557330f729Sjoerg /// a type, it is parsed as an identifier. If the attribute actually
1567330f729Sjoerg /// wanted an expression, it's out of luck (but it turns out that no
1577330f729Sjoerg /// attributes work that way, because C constant expressions are very
1587330f729Sjoerg /// limited).
1597330f729Sjoerg /// * In C++ mode, if the attribute argument list starts with an identifier,
1607330f729Sjoerg /// and the attribute *wants* an identifier, it is parsed as an identifier.
1617330f729Sjoerg /// At block scope, any additional tokens between the identifier and the
1627330f729Sjoerg /// ',' or ')' are ignored, otherwise they produce a parse error.
1637330f729Sjoerg ///
1647330f729Sjoerg /// We follow the C++ model, but don't allow junk after the identifier.
ParseGNUAttributes(ParsedAttributesWithRange & Attrs,SourceLocation * EndLoc,LateParsedAttrList * LateAttrs,Declarator * D)165*e038c9c4Sjoerg void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs,
166*e038c9c4Sjoerg SourceLocation *EndLoc,
167*e038c9c4Sjoerg LateParsedAttrList *LateAttrs, Declarator *D) {
1687330f729Sjoerg assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
1697330f729Sjoerg
170*e038c9c4Sjoerg SourceLocation StartLoc = Tok.getLocation(), Loc;
171*e038c9c4Sjoerg
172*e038c9c4Sjoerg if (!EndLoc)
173*e038c9c4Sjoerg EndLoc = &Loc;
174*e038c9c4Sjoerg
1757330f729Sjoerg while (Tok.is(tok::kw___attribute)) {
1767330f729Sjoerg SourceLocation AttrTokLoc = ConsumeToken();
177*e038c9c4Sjoerg unsigned OldNumAttrs = Attrs.size();
1787330f729Sjoerg unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0;
1797330f729Sjoerg
1807330f729Sjoerg if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1817330f729Sjoerg "attribute")) {
1827330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
1837330f729Sjoerg return;
1847330f729Sjoerg }
1857330f729Sjoerg if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
1867330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;
1877330f729Sjoerg return;
1887330f729Sjoerg }
1897330f729Sjoerg // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
1907330f729Sjoerg do {
1917330f729Sjoerg // Eat preceeding commas to allow __attribute__((,,,foo))
1927330f729Sjoerg while (TryConsumeToken(tok::comma))
1937330f729Sjoerg ;
1947330f729Sjoerg
1957330f729Sjoerg // Expect an identifier or declaration specifier (const, int, etc.)
1967330f729Sjoerg if (Tok.isAnnotation())
1977330f729Sjoerg break;
1987330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1997330f729Sjoerg if (!AttrName)
2007330f729Sjoerg break;
2017330f729Sjoerg
2027330f729Sjoerg SourceLocation AttrNameLoc = ConsumeToken();
2037330f729Sjoerg
2047330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
205*e038c9c4Sjoerg Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
2067330f729Sjoerg ParsedAttr::AS_GNU);
2077330f729Sjoerg continue;
2087330f729Sjoerg }
2097330f729Sjoerg
2107330f729Sjoerg // Handle "parameterized" attributes
2117330f729Sjoerg if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
212*e038c9c4Sjoerg ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, nullptr,
2137330f729Sjoerg SourceLocation(), ParsedAttr::AS_GNU, D);
2147330f729Sjoerg continue;
2157330f729Sjoerg }
2167330f729Sjoerg
2177330f729Sjoerg // Handle attributes with arguments that require late parsing.
2187330f729Sjoerg LateParsedAttribute *LA =
2197330f729Sjoerg new LateParsedAttribute(this, *AttrName, AttrNameLoc);
2207330f729Sjoerg LateAttrs->push_back(LA);
2217330f729Sjoerg
2227330f729Sjoerg // Attributes in a class are parsed at the end of the class, along
2237330f729Sjoerg // with other late-parsed declarations.
2247330f729Sjoerg if (!ClassStack.empty() && !LateAttrs->parseSoon())
2257330f729Sjoerg getCurrentClass().LateParsedDeclarations.push_back(LA);
2267330f729Sjoerg
2277330f729Sjoerg // Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it
2287330f729Sjoerg // recursively consumes balanced parens.
2297330f729Sjoerg LA->Toks.push_back(Tok);
2307330f729Sjoerg ConsumeParen();
2317330f729Sjoerg // Consume everything up to and including the matching right parens.
2327330f729Sjoerg ConsumeAndStoreUntil(tok::r_paren, LA->Toks, /*StopAtSemi=*/true);
2337330f729Sjoerg
2347330f729Sjoerg Token Eof;
2357330f729Sjoerg Eof.startToken();
2367330f729Sjoerg Eof.setLocation(Tok.getLocation());
2377330f729Sjoerg LA->Toks.push_back(Eof);
2387330f729Sjoerg } while (Tok.is(tok::comma));
2397330f729Sjoerg
2407330f729Sjoerg if (ExpectAndConsume(tok::r_paren))
2417330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
2427330f729Sjoerg SourceLocation Loc = Tok.getLocation();
2437330f729Sjoerg if (ExpectAndConsume(tok::r_paren))
2447330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
245*e038c9c4Sjoerg if (EndLoc)
246*e038c9c4Sjoerg *EndLoc = Loc;
2477330f729Sjoerg
2487330f729Sjoerg // If this was declared in a macro, attach the macro IdentifierInfo to the
2497330f729Sjoerg // parsed attribute.
2507330f729Sjoerg auto &SM = PP.getSourceManager();
2517330f729Sjoerg if (!SM.isWrittenInBuiltinFile(SM.getSpellingLoc(AttrTokLoc)) &&
2527330f729Sjoerg FindLocsWithCommonFileID(PP, AttrTokLoc, Loc)) {
2537330f729Sjoerg CharSourceRange ExpansionRange = SM.getExpansionRange(AttrTokLoc);
2547330f729Sjoerg StringRef FoundName =
2557330f729Sjoerg Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts());
2567330f729Sjoerg IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName);
2577330f729Sjoerg
258*e038c9c4Sjoerg for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i)
259*e038c9c4Sjoerg Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin());
2607330f729Sjoerg
2617330f729Sjoerg if (LateAttrs) {
2627330f729Sjoerg for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i)
2637330f729Sjoerg (*LateAttrs)[i]->MacroII = MacroII;
2647330f729Sjoerg }
2657330f729Sjoerg }
2667330f729Sjoerg }
267*e038c9c4Sjoerg
268*e038c9c4Sjoerg Attrs.Range = SourceRange(StartLoc, *EndLoc);
2697330f729Sjoerg }
2707330f729Sjoerg
2717330f729Sjoerg /// Determine whether the given attribute has an identifier argument.
attributeHasIdentifierArg(const IdentifierInfo & II)2727330f729Sjoerg static bool attributeHasIdentifierArg(const IdentifierInfo &II) {
2737330f729Sjoerg #define CLANG_ATTR_IDENTIFIER_ARG_LIST
2747330f729Sjoerg return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
2757330f729Sjoerg #include "clang/Parse/AttrParserStringSwitches.inc"
2767330f729Sjoerg .Default(false);
2777330f729Sjoerg #undef CLANG_ATTR_IDENTIFIER_ARG_LIST
2787330f729Sjoerg }
2797330f729Sjoerg
2807330f729Sjoerg /// Determine whether the given attribute has a variadic identifier argument.
attributeHasVariadicIdentifierArg(const IdentifierInfo & II)2817330f729Sjoerg static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) {
2827330f729Sjoerg #define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
2837330f729Sjoerg return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
2847330f729Sjoerg #include "clang/Parse/AttrParserStringSwitches.inc"
2857330f729Sjoerg .Default(false);
2867330f729Sjoerg #undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST
2877330f729Sjoerg }
2887330f729Sjoerg
2897330f729Sjoerg /// Determine whether the given attribute treats kw_this as an identifier.
attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo & II)2907330f729Sjoerg static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) {
2917330f729Sjoerg #define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
2927330f729Sjoerg return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
2937330f729Sjoerg #include "clang/Parse/AttrParserStringSwitches.inc"
2947330f729Sjoerg .Default(false);
2957330f729Sjoerg #undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST
2967330f729Sjoerg }
2977330f729Sjoerg
2987330f729Sjoerg /// Determine whether the given attribute parses a type argument.
attributeIsTypeArgAttr(const IdentifierInfo & II)2997330f729Sjoerg static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {
3007330f729Sjoerg #define CLANG_ATTR_TYPE_ARG_LIST
3017330f729Sjoerg return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3027330f729Sjoerg #include "clang/Parse/AttrParserStringSwitches.inc"
3037330f729Sjoerg .Default(false);
3047330f729Sjoerg #undef CLANG_ATTR_TYPE_ARG_LIST
3057330f729Sjoerg }
3067330f729Sjoerg
3077330f729Sjoerg /// Determine whether the given attribute requires parsing its arguments
3087330f729Sjoerg /// in an unevaluated context or not.
attributeParsedArgsUnevaluated(const IdentifierInfo & II)3097330f729Sjoerg static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {
3107330f729Sjoerg #define CLANG_ATTR_ARG_CONTEXT_LIST
3117330f729Sjoerg return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))
3127330f729Sjoerg #include "clang/Parse/AttrParserStringSwitches.inc"
3137330f729Sjoerg .Default(false);
3147330f729Sjoerg #undef CLANG_ATTR_ARG_CONTEXT_LIST
3157330f729Sjoerg }
3167330f729Sjoerg
ParseIdentifierLoc()3177330f729Sjoerg IdentifierLoc *Parser::ParseIdentifierLoc() {
3187330f729Sjoerg assert(Tok.is(tok::identifier) && "expected an identifier");
3197330f729Sjoerg IdentifierLoc *IL = IdentifierLoc::create(Actions.Context,
3207330f729Sjoerg Tok.getLocation(),
3217330f729Sjoerg Tok.getIdentifierInfo());
3227330f729Sjoerg ConsumeToken();
3237330f729Sjoerg return IL;
3247330f729Sjoerg }
3257330f729Sjoerg
ParseAttributeWithTypeArg(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)3267330f729Sjoerg void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
3277330f729Sjoerg SourceLocation AttrNameLoc,
3287330f729Sjoerg ParsedAttributes &Attrs,
3297330f729Sjoerg SourceLocation *EndLoc,
3307330f729Sjoerg IdentifierInfo *ScopeName,
3317330f729Sjoerg SourceLocation ScopeLoc,
3327330f729Sjoerg ParsedAttr::Syntax Syntax) {
3337330f729Sjoerg BalancedDelimiterTracker Parens(*this, tok::l_paren);
3347330f729Sjoerg Parens.consumeOpen();
3357330f729Sjoerg
3367330f729Sjoerg TypeResult T;
3377330f729Sjoerg if (Tok.isNot(tok::r_paren))
3387330f729Sjoerg T = ParseTypeName();
3397330f729Sjoerg
3407330f729Sjoerg if (Parens.consumeClose())
3417330f729Sjoerg return;
3427330f729Sjoerg
3437330f729Sjoerg if (T.isInvalid())
3447330f729Sjoerg return;
3457330f729Sjoerg
3467330f729Sjoerg if (T.isUsable())
3477330f729Sjoerg Attrs.addNewTypeAttr(&AttrName,
3487330f729Sjoerg SourceRange(AttrNameLoc, Parens.getCloseLocation()),
3497330f729Sjoerg ScopeName, ScopeLoc, T.get(), Syntax);
3507330f729Sjoerg else
3517330f729Sjoerg Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
3527330f729Sjoerg ScopeName, ScopeLoc, nullptr, 0, Syntax);
3537330f729Sjoerg }
3547330f729Sjoerg
ParseAttributeArgsCommon(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)3557330f729Sjoerg unsigned Parser::ParseAttributeArgsCommon(
3567330f729Sjoerg IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
3577330f729Sjoerg ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
3587330f729Sjoerg SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
3597330f729Sjoerg // Ignore the left paren location for now.
3607330f729Sjoerg ConsumeParen();
3617330f729Sjoerg
3627330f729Sjoerg bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName);
3637330f729Sjoerg bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName);
3647330f729Sjoerg
3657330f729Sjoerg // Interpret "kw_this" as an identifier if the attributed requests it.
3667330f729Sjoerg if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
3677330f729Sjoerg Tok.setKind(tok::identifier);
3687330f729Sjoerg
3697330f729Sjoerg ArgsVector ArgExprs;
3707330f729Sjoerg if (Tok.is(tok::identifier)) {
3717330f729Sjoerg // If this attribute wants an 'identifier' argument, make it so.
3727330f729Sjoerg bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) ||
3737330f729Sjoerg attributeHasVariadicIdentifierArg(*AttrName);
3747330f729Sjoerg ParsedAttr::Kind AttrKind =
3757330f729Sjoerg ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
3767330f729Sjoerg
3777330f729Sjoerg // If we don't know how to parse this attribute, but this is the only
3787330f729Sjoerg // token in this argument, assume it's meant to be an identifier.
3797330f729Sjoerg if (AttrKind == ParsedAttr::UnknownAttribute ||
3807330f729Sjoerg AttrKind == ParsedAttr::IgnoredAttribute) {
3817330f729Sjoerg const Token &Next = NextToken();
3827330f729Sjoerg IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);
3837330f729Sjoerg }
3847330f729Sjoerg
3857330f729Sjoerg if (IsIdentifierArg)
3867330f729Sjoerg ArgExprs.push_back(ParseIdentifierLoc());
3877330f729Sjoerg }
3887330f729Sjoerg
3897330f729Sjoerg ParsedType TheParsedType;
3907330f729Sjoerg if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
3917330f729Sjoerg // Eat the comma.
3927330f729Sjoerg if (!ArgExprs.empty())
3937330f729Sjoerg ConsumeToken();
3947330f729Sjoerg
3957330f729Sjoerg // Parse the non-empty comma-separated list of expressions.
3967330f729Sjoerg do {
3977330f729Sjoerg // Interpret "kw_this" as an identifier if the attributed requests it.
3987330f729Sjoerg if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
3997330f729Sjoerg Tok.setKind(tok::identifier);
4007330f729Sjoerg
4017330f729Sjoerg ExprResult ArgExpr;
4027330f729Sjoerg if (AttributeIsTypeArgAttr) {
4037330f729Sjoerg TypeResult T = ParseTypeName();
4047330f729Sjoerg if (T.isInvalid()) {
4057330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
4067330f729Sjoerg return 0;
4077330f729Sjoerg }
4087330f729Sjoerg if (T.isUsable())
4097330f729Sjoerg TheParsedType = T.get();
4107330f729Sjoerg break; // FIXME: Multiple type arguments are not implemented.
4117330f729Sjoerg } else if (Tok.is(tok::identifier) &&
4127330f729Sjoerg attributeHasVariadicIdentifierArg(*AttrName)) {
4137330f729Sjoerg ArgExprs.push_back(ParseIdentifierLoc());
4147330f729Sjoerg } else {
4157330f729Sjoerg bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
4167330f729Sjoerg EnterExpressionEvaluationContext Unevaluated(
4177330f729Sjoerg Actions,
4187330f729Sjoerg Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
4197330f729Sjoerg : Sema::ExpressionEvaluationContext::ConstantEvaluated);
4207330f729Sjoerg
4217330f729Sjoerg ExprResult ArgExpr(
4227330f729Sjoerg Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
4237330f729Sjoerg if (ArgExpr.isInvalid()) {
4247330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
4257330f729Sjoerg return 0;
4267330f729Sjoerg }
4277330f729Sjoerg ArgExprs.push_back(ArgExpr.get());
4287330f729Sjoerg }
4297330f729Sjoerg // Eat the comma, move to the next argument
4307330f729Sjoerg } while (TryConsumeToken(tok::comma));
4317330f729Sjoerg }
4327330f729Sjoerg
4337330f729Sjoerg SourceLocation RParen = Tok.getLocation();
4347330f729Sjoerg if (!ExpectAndConsume(tok::r_paren)) {
4357330f729Sjoerg SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
4367330f729Sjoerg
4377330f729Sjoerg if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) {
4387330f729Sjoerg Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen),
4397330f729Sjoerg ScopeName, ScopeLoc, TheParsedType, Syntax);
4407330f729Sjoerg } else {
4417330f729Sjoerg Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
4427330f729Sjoerg ArgExprs.data(), ArgExprs.size(), Syntax);
4437330f729Sjoerg }
4447330f729Sjoerg }
4457330f729Sjoerg
4467330f729Sjoerg if (EndLoc)
4477330f729Sjoerg *EndLoc = RParen;
4487330f729Sjoerg
4497330f729Sjoerg return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull());
4507330f729Sjoerg }
4517330f729Sjoerg
4527330f729Sjoerg /// Parse the arguments to a parameterized GNU attribute or
4537330f729Sjoerg /// a C++11 attribute in "gnu" namespace.
ParseGNUAttributeArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax,Declarator * D)4547330f729Sjoerg void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
4557330f729Sjoerg SourceLocation AttrNameLoc,
4567330f729Sjoerg ParsedAttributes &Attrs,
4577330f729Sjoerg SourceLocation *EndLoc,
4587330f729Sjoerg IdentifierInfo *ScopeName,
4597330f729Sjoerg SourceLocation ScopeLoc,
4607330f729Sjoerg ParsedAttr::Syntax Syntax,
4617330f729Sjoerg Declarator *D) {
4627330f729Sjoerg
4637330f729Sjoerg assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
4647330f729Sjoerg
4657330f729Sjoerg ParsedAttr::Kind AttrKind =
4667330f729Sjoerg ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
4677330f729Sjoerg
4687330f729Sjoerg if (AttrKind == ParsedAttr::AT_Availability) {
4697330f729Sjoerg ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
4707330f729Sjoerg ScopeLoc, Syntax);
4717330f729Sjoerg return;
4727330f729Sjoerg } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) {
4737330f729Sjoerg ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
4747330f729Sjoerg ScopeName, ScopeLoc, Syntax);
4757330f729Sjoerg return;
4767330f729Sjoerg } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) {
4777330f729Sjoerg ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
4787330f729Sjoerg ScopeName, ScopeLoc, Syntax);
4797330f729Sjoerg return;
480*e038c9c4Sjoerg } else if (AttrKind == ParsedAttr::AT_SwiftNewType) {
481*e038c9c4Sjoerg ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
482*e038c9c4Sjoerg ScopeLoc, Syntax);
483*e038c9c4Sjoerg return;
4847330f729Sjoerg } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {
4857330f729Sjoerg ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
4867330f729Sjoerg ScopeName, ScopeLoc, Syntax);
4877330f729Sjoerg return;
4887330f729Sjoerg } else if (attributeIsTypeArgAttr(*AttrName)) {
4897330f729Sjoerg ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
4907330f729Sjoerg ScopeLoc, Syntax);
4917330f729Sjoerg return;
4927330f729Sjoerg }
4937330f729Sjoerg
4947330f729Sjoerg // These may refer to the function arguments, but need to be parsed early to
4957330f729Sjoerg // participate in determining whether it's a redeclaration.
4967330f729Sjoerg llvm::Optional<ParseScope> PrototypeScope;
4977330f729Sjoerg if (normalizeAttrName(AttrName->getName()) == "enable_if" &&
4987330f729Sjoerg D && D->isFunctionDeclarator()) {
4997330f729Sjoerg DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
5007330f729Sjoerg PrototypeScope.emplace(this, Scope::FunctionPrototypeScope |
5017330f729Sjoerg Scope::FunctionDeclarationScope |
5027330f729Sjoerg Scope::DeclScope);
5037330f729Sjoerg for (unsigned i = 0; i != FTI.NumParams; ++i) {
5047330f729Sjoerg ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
5057330f729Sjoerg Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
5067330f729Sjoerg }
5077330f729Sjoerg }
5087330f729Sjoerg
5097330f729Sjoerg ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
5107330f729Sjoerg ScopeLoc, Syntax);
5117330f729Sjoerg }
5127330f729Sjoerg
ParseClangAttributeArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)5137330f729Sjoerg unsigned Parser::ParseClangAttributeArgs(
5147330f729Sjoerg IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
5157330f729Sjoerg ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
5167330f729Sjoerg SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
5177330f729Sjoerg assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
5187330f729Sjoerg
5197330f729Sjoerg ParsedAttr::Kind AttrKind =
5207330f729Sjoerg ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
5217330f729Sjoerg
5227330f729Sjoerg switch (AttrKind) {
5237330f729Sjoerg default:
5247330f729Sjoerg return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
5257330f729Sjoerg ScopeName, ScopeLoc, Syntax);
5267330f729Sjoerg case ParsedAttr::AT_ExternalSourceSymbol:
5277330f729Sjoerg ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
5287330f729Sjoerg ScopeName, ScopeLoc, Syntax);
5297330f729Sjoerg break;
5307330f729Sjoerg case ParsedAttr::AT_Availability:
5317330f729Sjoerg ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
5327330f729Sjoerg ScopeLoc, Syntax);
5337330f729Sjoerg break;
5347330f729Sjoerg case ParsedAttr::AT_ObjCBridgeRelated:
5357330f729Sjoerg ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
5367330f729Sjoerg ScopeName, ScopeLoc, Syntax);
5377330f729Sjoerg break;
538*e038c9c4Sjoerg case ParsedAttr::AT_SwiftNewType:
539*e038c9c4Sjoerg ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
540*e038c9c4Sjoerg ScopeLoc, Syntax);
541*e038c9c4Sjoerg break;
5427330f729Sjoerg case ParsedAttr::AT_TypeTagForDatatype:
5437330f729Sjoerg ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,
5447330f729Sjoerg ScopeName, ScopeLoc, Syntax);
5457330f729Sjoerg break;
5467330f729Sjoerg }
5477330f729Sjoerg return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;
5487330f729Sjoerg }
5497330f729Sjoerg
ParseMicrosoftDeclSpecArgs(IdentifierInfo * AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs)5507330f729Sjoerg bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
5517330f729Sjoerg SourceLocation AttrNameLoc,
5527330f729Sjoerg ParsedAttributes &Attrs) {
5537330f729Sjoerg // If the attribute isn't known, we will not attempt to parse any
5547330f729Sjoerg // arguments.
5557330f729Sjoerg if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName,
5567330f729Sjoerg getTargetInfo(), getLangOpts())) {
5577330f729Sjoerg // Eat the left paren, then skip to the ending right paren.
5587330f729Sjoerg ConsumeParen();
5597330f729Sjoerg SkipUntil(tok::r_paren);
5607330f729Sjoerg return false;
5617330f729Sjoerg }
5627330f729Sjoerg
5637330f729Sjoerg SourceLocation OpenParenLoc = Tok.getLocation();
5647330f729Sjoerg
5657330f729Sjoerg if (AttrName->getName() == "property") {
5667330f729Sjoerg // The property declspec is more complex in that it can take one or two
5677330f729Sjoerg // assignment expressions as a parameter, but the lhs of the assignment
5687330f729Sjoerg // must be named get or put.
5697330f729Sjoerg
5707330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
5717330f729Sjoerg T.expectAndConsume(diag::err_expected_lparen_after,
5727330f729Sjoerg AttrName->getNameStart(), tok::r_paren);
5737330f729Sjoerg
5747330f729Sjoerg enum AccessorKind {
5757330f729Sjoerg AK_Invalid = -1,
5767330f729Sjoerg AK_Put = 0,
5777330f729Sjoerg AK_Get = 1 // indices into AccessorNames
5787330f729Sjoerg };
5797330f729Sjoerg IdentifierInfo *AccessorNames[] = {nullptr, nullptr};
5807330f729Sjoerg bool HasInvalidAccessor = false;
5817330f729Sjoerg
5827330f729Sjoerg // Parse the accessor specifications.
5837330f729Sjoerg while (true) {
5847330f729Sjoerg // Stop if this doesn't look like an accessor spec.
5857330f729Sjoerg if (!Tok.is(tok::identifier)) {
5867330f729Sjoerg // If the user wrote a completely empty list, use a special diagnostic.
5877330f729Sjoerg if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&
5887330f729Sjoerg AccessorNames[AK_Put] == nullptr &&
5897330f729Sjoerg AccessorNames[AK_Get] == nullptr) {
5907330f729Sjoerg Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);
5917330f729Sjoerg break;
5927330f729Sjoerg }
5937330f729Sjoerg
5947330f729Sjoerg Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor);
5957330f729Sjoerg break;
5967330f729Sjoerg }
5977330f729Sjoerg
5987330f729Sjoerg AccessorKind Kind;
5997330f729Sjoerg SourceLocation KindLoc = Tok.getLocation();
6007330f729Sjoerg StringRef KindStr = Tok.getIdentifierInfo()->getName();
6017330f729Sjoerg if (KindStr == "get") {
6027330f729Sjoerg Kind = AK_Get;
6037330f729Sjoerg } else if (KindStr == "put") {
6047330f729Sjoerg Kind = AK_Put;
6057330f729Sjoerg
6067330f729Sjoerg // Recover from the common mistake of using 'set' instead of 'put'.
6077330f729Sjoerg } else if (KindStr == "set") {
6087330f729Sjoerg Diag(KindLoc, diag::err_ms_property_has_set_accessor)
6097330f729Sjoerg << FixItHint::CreateReplacement(KindLoc, "put");
6107330f729Sjoerg Kind = AK_Put;
6117330f729Sjoerg
6127330f729Sjoerg // Handle the mistake of forgetting the accessor kind by skipping
6137330f729Sjoerg // this accessor.
6147330f729Sjoerg } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {
6157330f729Sjoerg Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);
6167330f729Sjoerg ConsumeToken();
6177330f729Sjoerg HasInvalidAccessor = true;
6187330f729Sjoerg goto next_property_accessor;
6197330f729Sjoerg
6207330f729Sjoerg // Otherwise, complain about the unknown accessor kind.
6217330f729Sjoerg } else {
6227330f729Sjoerg Diag(KindLoc, diag::err_ms_property_unknown_accessor);
6237330f729Sjoerg HasInvalidAccessor = true;
6247330f729Sjoerg Kind = AK_Invalid;
6257330f729Sjoerg
6267330f729Sjoerg // Try to keep parsing unless it doesn't look like an accessor spec.
6277330f729Sjoerg if (!NextToken().is(tok::equal))
6287330f729Sjoerg break;
6297330f729Sjoerg }
6307330f729Sjoerg
6317330f729Sjoerg // Consume the identifier.
6327330f729Sjoerg ConsumeToken();
6337330f729Sjoerg
6347330f729Sjoerg // Consume the '='.
6357330f729Sjoerg if (!TryConsumeToken(tok::equal)) {
6367330f729Sjoerg Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)
6377330f729Sjoerg << KindStr;
6387330f729Sjoerg break;
6397330f729Sjoerg }
6407330f729Sjoerg
6417330f729Sjoerg // Expect the method name.
6427330f729Sjoerg if (!Tok.is(tok::identifier)) {
6437330f729Sjoerg Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name);
6447330f729Sjoerg break;
6457330f729Sjoerg }
6467330f729Sjoerg
6477330f729Sjoerg if (Kind == AK_Invalid) {
6487330f729Sjoerg // Just drop invalid accessors.
6497330f729Sjoerg } else if (AccessorNames[Kind] != nullptr) {
6507330f729Sjoerg // Complain about the repeated accessor, ignore it, and keep parsing.
6517330f729Sjoerg Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;
6527330f729Sjoerg } else {
6537330f729Sjoerg AccessorNames[Kind] = Tok.getIdentifierInfo();
6547330f729Sjoerg }
6557330f729Sjoerg ConsumeToken();
6567330f729Sjoerg
6577330f729Sjoerg next_property_accessor:
6587330f729Sjoerg // Keep processing accessors until we run out.
6597330f729Sjoerg if (TryConsumeToken(tok::comma))
6607330f729Sjoerg continue;
6617330f729Sjoerg
6627330f729Sjoerg // If we run into the ')', stop without consuming it.
6637330f729Sjoerg if (Tok.is(tok::r_paren))
6647330f729Sjoerg break;
6657330f729Sjoerg
6667330f729Sjoerg Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);
6677330f729Sjoerg break;
6687330f729Sjoerg }
6697330f729Sjoerg
6707330f729Sjoerg // Only add the property attribute if it was well-formed.
6717330f729Sjoerg if (!HasInvalidAccessor)
6727330f729Sjoerg Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),
6737330f729Sjoerg AccessorNames[AK_Get], AccessorNames[AK_Put],
6747330f729Sjoerg ParsedAttr::AS_Declspec);
6757330f729Sjoerg T.skipToEnd();
6767330f729Sjoerg return !HasInvalidAccessor;
6777330f729Sjoerg }
6787330f729Sjoerg
6797330f729Sjoerg unsigned NumArgs =
6807330f729Sjoerg ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
6817330f729Sjoerg SourceLocation(), ParsedAttr::AS_Declspec);
6827330f729Sjoerg
6837330f729Sjoerg // If this attribute's args were parsed, and it was expected to have
6847330f729Sjoerg // arguments but none were provided, emit a diagnostic.
6857330f729Sjoerg if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) {
6867330f729Sjoerg Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;
6877330f729Sjoerg return false;
6887330f729Sjoerg }
6897330f729Sjoerg return true;
6907330f729Sjoerg }
6917330f729Sjoerg
6927330f729Sjoerg /// [MS] decl-specifier:
6937330f729Sjoerg /// __declspec ( extended-decl-modifier-seq )
6947330f729Sjoerg ///
6957330f729Sjoerg /// [MS] extended-decl-modifier-seq:
6967330f729Sjoerg /// extended-decl-modifier[opt]
6977330f729Sjoerg /// extended-decl-modifier extended-decl-modifier-seq
ParseMicrosoftDeclSpecs(ParsedAttributes & Attrs,SourceLocation * End)6987330f729Sjoerg void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
6997330f729Sjoerg SourceLocation *End) {
7007330f729Sjoerg assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled");
7017330f729Sjoerg assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
7027330f729Sjoerg
7037330f729Sjoerg while (Tok.is(tok::kw___declspec)) {
7047330f729Sjoerg ConsumeToken();
7057330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
7067330f729Sjoerg if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",
7077330f729Sjoerg tok::r_paren))
7087330f729Sjoerg return;
7097330f729Sjoerg
7107330f729Sjoerg // An empty declspec is perfectly legal and should not warn. Additionally,
7117330f729Sjoerg // you can specify multiple attributes per declspec.
7127330f729Sjoerg while (Tok.isNot(tok::r_paren)) {
7137330f729Sjoerg // Attribute not present.
7147330f729Sjoerg if (TryConsumeToken(tok::comma))
7157330f729Sjoerg continue;
7167330f729Sjoerg
7177330f729Sjoerg // We expect either a well-known identifier or a generic string. Anything
7187330f729Sjoerg // else is a malformed declspec.
7197330f729Sjoerg bool IsString = Tok.getKind() == tok::string_literal;
7207330f729Sjoerg if (!IsString && Tok.getKind() != tok::identifier &&
7217330f729Sjoerg Tok.getKind() != tok::kw_restrict) {
7227330f729Sjoerg Diag(Tok, diag::err_ms_declspec_type);
7237330f729Sjoerg T.skipToEnd();
7247330f729Sjoerg return;
7257330f729Sjoerg }
7267330f729Sjoerg
7277330f729Sjoerg IdentifierInfo *AttrName;
7287330f729Sjoerg SourceLocation AttrNameLoc;
7297330f729Sjoerg if (IsString) {
7307330f729Sjoerg SmallString<8> StrBuffer;
7317330f729Sjoerg bool Invalid = false;
7327330f729Sjoerg StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
7337330f729Sjoerg if (Invalid) {
7347330f729Sjoerg T.skipToEnd();
7357330f729Sjoerg return;
7367330f729Sjoerg }
7377330f729Sjoerg AttrName = PP.getIdentifierInfo(Str);
7387330f729Sjoerg AttrNameLoc = ConsumeStringToken();
7397330f729Sjoerg } else {
7407330f729Sjoerg AttrName = Tok.getIdentifierInfo();
7417330f729Sjoerg AttrNameLoc = ConsumeToken();
7427330f729Sjoerg }
7437330f729Sjoerg
7447330f729Sjoerg bool AttrHandled = false;
7457330f729Sjoerg
7467330f729Sjoerg // Parse attribute arguments.
7477330f729Sjoerg if (Tok.is(tok::l_paren))
7487330f729Sjoerg AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);
7497330f729Sjoerg else if (AttrName->getName() == "property")
7507330f729Sjoerg // The property attribute must have an argument list.
7517330f729Sjoerg Diag(Tok.getLocation(), diag::err_expected_lparen_after)
7527330f729Sjoerg << AttrName->getName();
7537330f729Sjoerg
7547330f729Sjoerg if (!AttrHandled)
7557330f729Sjoerg Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
7567330f729Sjoerg ParsedAttr::AS_Declspec);
7577330f729Sjoerg }
7587330f729Sjoerg T.consumeClose();
7597330f729Sjoerg if (End)
7607330f729Sjoerg *End = T.getCloseLocation();
7617330f729Sjoerg }
7627330f729Sjoerg }
7637330f729Sjoerg
ParseMicrosoftTypeAttributes(ParsedAttributes & attrs)7647330f729Sjoerg void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
7657330f729Sjoerg // Treat these like attributes
7667330f729Sjoerg while (true) {
7677330f729Sjoerg switch (Tok.getKind()) {
7687330f729Sjoerg case tok::kw___fastcall:
7697330f729Sjoerg case tok::kw___stdcall:
7707330f729Sjoerg case tok::kw___thiscall:
7717330f729Sjoerg case tok::kw___regcall:
7727330f729Sjoerg case tok::kw___cdecl:
7737330f729Sjoerg case tok::kw___vectorcall:
7747330f729Sjoerg case tok::kw___ptr64:
7757330f729Sjoerg case tok::kw___w64:
7767330f729Sjoerg case tok::kw___ptr32:
7777330f729Sjoerg case tok::kw___sptr:
7787330f729Sjoerg case tok::kw___uptr: {
7797330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
7807330f729Sjoerg SourceLocation AttrNameLoc = ConsumeToken();
7817330f729Sjoerg attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
7827330f729Sjoerg ParsedAttr::AS_Keyword);
7837330f729Sjoerg break;
7847330f729Sjoerg }
7857330f729Sjoerg default:
7867330f729Sjoerg return;
7877330f729Sjoerg }
7887330f729Sjoerg }
7897330f729Sjoerg }
7907330f729Sjoerg
DiagnoseAndSkipExtendedMicrosoftTypeAttributes()7917330f729Sjoerg void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() {
7927330f729Sjoerg SourceLocation StartLoc = Tok.getLocation();
7937330f729Sjoerg SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes();
7947330f729Sjoerg
7957330f729Sjoerg if (EndLoc.isValid()) {
7967330f729Sjoerg SourceRange Range(StartLoc, EndLoc);
7977330f729Sjoerg Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range;
7987330f729Sjoerg }
7997330f729Sjoerg }
8007330f729Sjoerg
SkipExtendedMicrosoftTypeAttributes()8017330f729Sjoerg SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() {
8027330f729Sjoerg SourceLocation EndLoc;
8037330f729Sjoerg
8047330f729Sjoerg while (true) {
8057330f729Sjoerg switch (Tok.getKind()) {
8067330f729Sjoerg case tok::kw_const:
8077330f729Sjoerg case tok::kw_volatile:
8087330f729Sjoerg case tok::kw___fastcall:
8097330f729Sjoerg case tok::kw___stdcall:
8107330f729Sjoerg case tok::kw___thiscall:
8117330f729Sjoerg case tok::kw___cdecl:
8127330f729Sjoerg case tok::kw___vectorcall:
8137330f729Sjoerg case tok::kw___ptr32:
8147330f729Sjoerg case tok::kw___ptr64:
8157330f729Sjoerg case tok::kw___w64:
8167330f729Sjoerg case tok::kw___unaligned:
8177330f729Sjoerg case tok::kw___sptr:
8187330f729Sjoerg case tok::kw___uptr:
8197330f729Sjoerg EndLoc = ConsumeToken();
8207330f729Sjoerg break;
8217330f729Sjoerg default:
8227330f729Sjoerg return EndLoc;
8237330f729Sjoerg }
8247330f729Sjoerg }
8257330f729Sjoerg }
8267330f729Sjoerg
ParseBorlandTypeAttributes(ParsedAttributes & attrs)8277330f729Sjoerg void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {
8287330f729Sjoerg // Treat these like attributes
8297330f729Sjoerg while (Tok.is(tok::kw___pascal)) {
8307330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
8317330f729Sjoerg SourceLocation AttrNameLoc = ConsumeToken();
8327330f729Sjoerg attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
8337330f729Sjoerg ParsedAttr::AS_Keyword);
8347330f729Sjoerg }
8357330f729Sjoerg }
8367330f729Sjoerg
ParseOpenCLKernelAttributes(ParsedAttributes & attrs)8377330f729Sjoerg void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) {
8387330f729Sjoerg // Treat these like attributes
8397330f729Sjoerg while (Tok.is(tok::kw___kernel)) {
8407330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
8417330f729Sjoerg SourceLocation AttrNameLoc = ConsumeToken();
8427330f729Sjoerg attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
8437330f729Sjoerg ParsedAttr::AS_Keyword);
8447330f729Sjoerg }
8457330f729Sjoerg }
8467330f729Sjoerg
ParseOpenCLQualifiers(ParsedAttributes & Attrs)8477330f729Sjoerg void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {
8487330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
8497330f729Sjoerg SourceLocation AttrNameLoc = Tok.getLocation();
8507330f729Sjoerg Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
8517330f729Sjoerg ParsedAttr::AS_Keyword);
8527330f729Sjoerg }
8537330f729Sjoerg
ParseNullabilityTypeSpecifiers(ParsedAttributes & attrs)8547330f729Sjoerg void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
8557330f729Sjoerg // Treat these like attributes, even though they're type specifiers.
8567330f729Sjoerg while (true) {
8577330f729Sjoerg switch (Tok.getKind()) {
8587330f729Sjoerg case tok::kw__Nonnull:
8597330f729Sjoerg case tok::kw__Nullable:
860*e038c9c4Sjoerg case tok::kw__Nullable_result:
8617330f729Sjoerg case tok::kw__Null_unspecified: {
8627330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
8637330f729Sjoerg SourceLocation AttrNameLoc = ConsumeToken();
8647330f729Sjoerg if (!getLangOpts().ObjC)
8657330f729Sjoerg Diag(AttrNameLoc, diag::ext_nullability)
8667330f729Sjoerg << AttrName;
8677330f729Sjoerg attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
8687330f729Sjoerg ParsedAttr::AS_Keyword);
8697330f729Sjoerg break;
8707330f729Sjoerg }
8717330f729Sjoerg default:
8727330f729Sjoerg return;
8737330f729Sjoerg }
8747330f729Sjoerg }
8757330f729Sjoerg }
8767330f729Sjoerg
VersionNumberSeparator(const char Separator)8777330f729Sjoerg static bool VersionNumberSeparator(const char Separator) {
8787330f729Sjoerg return (Separator == '.' || Separator == '_');
8797330f729Sjoerg }
8807330f729Sjoerg
8817330f729Sjoerg /// Parse a version number.
8827330f729Sjoerg ///
8837330f729Sjoerg /// version:
8847330f729Sjoerg /// simple-integer
8857330f729Sjoerg /// simple-integer '.' simple-integer
8867330f729Sjoerg /// simple-integer '_' simple-integer
8877330f729Sjoerg /// simple-integer '.' simple-integer '.' simple-integer
8887330f729Sjoerg /// simple-integer '_' simple-integer '_' simple-integer
ParseVersionTuple(SourceRange & Range)8897330f729Sjoerg VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
8907330f729Sjoerg Range = SourceRange(Tok.getLocation(), Tok.getEndLoc());
8917330f729Sjoerg
8927330f729Sjoerg if (!Tok.is(tok::numeric_constant)) {
8937330f729Sjoerg Diag(Tok, diag::err_expected_version);
8947330f729Sjoerg SkipUntil(tok::comma, tok::r_paren,
8957330f729Sjoerg StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
8967330f729Sjoerg return VersionTuple();
8977330f729Sjoerg }
8987330f729Sjoerg
8997330f729Sjoerg // Parse the major (and possibly minor and subminor) versions, which
9007330f729Sjoerg // are stored in the numeric constant. We utilize a quirk of the
9017330f729Sjoerg // lexer, which is that it handles something like 1.2.3 as a single
9027330f729Sjoerg // numeric constant, rather than two separate tokens.
9037330f729Sjoerg SmallString<512> Buffer;
9047330f729Sjoerg Buffer.resize(Tok.getLength()+1);
9057330f729Sjoerg const char *ThisTokBegin = &Buffer[0];
9067330f729Sjoerg
9077330f729Sjoerg // Get the spelling of the token, which eliminates trigraphs, etc.
9087330f729Sjoerg bool Invalid = false;
9097330f729Sjoerg unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);
9107330f729Sjoerg if (Invalid)
9117330f729Sjoerg return VersionTuple();
9127330f729Sjoerg
9137330f729Sjoerg // Parse the major version.
9147330f729Sjoerg unsigned AfterMajor = 0;
9157330f729Sjoerg unsigned Major = 0;
9167330f729Sjoerg while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) {
9177330f729Sjoerg Major = Major * 10 + ThisTokBegin[AfterMajor] - '0';
9187330f729Sjoerg ++AfterMajor;
9197330f729Sjoerg }
9207330f729Sjoerg
9217330f729Sjoerg if (AfterMajor == 0) {
9227330f729Sjoerg Diag(Tok, diag::err_expected_version);
9237330f729Sjoerg SkipUntil(tok::comma, tok::r_paren,
9247330f729Sjoerg StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
9257330f729Sjoerg return VersionTuple();
9267330f729Sjoerg }
9277330f729Sjoerg
9287330f729Sjoerg if (AfterMajor == ActualLength) {
9297330f729Sjoerg ConsumeToken();
9307330f729Sjoerg
9317330f729Sjoerg // We only had a single version component.
9327330f729Sjoerg if (Major == 0) {
9337330f729Sjoerg Diag(Tok, diag::err_zero_version);
9347330f729Sjoerg return VersionTuple();
9357330f729Sjoerg }
9367330f729Sjoerg
9377330f729Sjoerg return VersionTuple(Major);
9387330f729Sjoerg }
9397330f729Sjoerg
9407330f729Sjoerg const char AfterMajorSeparator = ThisTokBegin[AfterMajor];
9417330f729Sjoerg if (!VersionNumberSeparator(AfterMajorSeparator)
9427330f729Sjoerg || (AfterMajor + 1 == ActualLength)) {
9437330f729Sjoerg Diag(Tok, diag::err_expected_version);
9447330f729Sjoerg SkipUntil(tok::comma, tok::r_paren,
9457330f729Sjoerg StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
9467330f729Sjoerg return VersionTuple();
9477330f729Sjoerg }
9487330f729Sjoerg
9497330f729Sjoerg // Parse the minor version.
9507330f729Sjoerg unsigned AfterMinor = AfterMajor + 1;
9517330f729Sjoerg unsigned Minor = 0;
9527330f729Sjoerg while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) {
9537330f729Sjoerg Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0';
9547330f729Sjoerg ++AfterMinor;
9557330f729Sjoerg }
9567330f729Sjoerg
9577330f729Sjoerg if (AfterMinor == ActualLength) {
9587330f729Sjoerg ConsumeToken();
9597330f729Sjoerg
9607330f729Sjoerg // We had major.minor.
9617330f729Sjoerg if (Major == 0 && Minor == 0) {
9627330f729Sjoerg Diag(Tok, diag::err_zero_version);
9637330f729Sjoerg return VersionTuple();
9647330f729Sjoerg }
9657330f729Sjoerg
9667330f729Sjoerg return VersionTuple(Major, Minor);
9677330f729Sjoerg }
9687330f729Sjoerg
9697330f729Sjoerg const char AfterMinorSeparator = ThisTokBegin[AfterMinor];
9707330f729Sjoerg // If what follows is not a '.' or '_', we have a problem.
9717330f729Sjoerg if (!VersionNumberSeparator(AfterMinorSeparator)) {
9727330f729Sjoerg Diag(Tok, diag::err_expected_version);
9737330f729Sjoerg SkipUntil(tok::comma, tok::r_paren,
9747330f729Sjoerg StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
9757330f729Sjoerg return VersionTuple();
9767330f729Sjoerg }
9777330f729Sjoerg
9787330f729Sjoerg // Warn if separators, be it '.' or '_', do not match.
9797330f729Sjoerg if (AfterMajorSeparator != AfterMinorSeparator)
9807330f729Sjoerg Diag(Tok, diag::warn_expected_consistent_version_separator);
9817330f729Sjoerg
9827330f729Sjoerg // Parse the subminor version.
9837330f729Sjoerg unsigned AfterSubminor = AfterMinor + 1;
9847330f729Sjoerg unsigned Subminor = 0;
9857330f729Sjoerg while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) {
9867330f729Sjoerg Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0';
9877330f729Sjoerg ++AfterSubminor;
9887330f729Sjoerg }
9897330f729Sjoerg
9907330f729Sjoerg if (AfterSubminor != ActualLength) {
9917330f729Sjoerg Diag(Tok, diag::err_expected_version);
9927330f729Sjoerg SkipUntil(tok::comma, tok::r_paren,
9937330f729Sjoerg StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
9947330f729Sjoerg return VersionTuple();
9957330f729Sjoerg }
9967330f729Sjoerg ConsumeToken();
9977330f729Sjoerg return VersionTuple(Major, Minor, Subminor);
9987330f729Sjoerg }
9997330f729Sjoerg
10007330f729Sjoerg /// Parse the contents of the "availability" attribute.
10017330f729Sjoerg ///
10027330f729Sjoerg /// availability-attribute:
10037330f729Sjoerg /// 'availability' '(' platform ',' opt-strict version-arg-list,
10047330f729Sjoerg /// opt-replacement, opt-message')'
10057330f729Sjoerg ///
10067330f729Sjoerg /// platform:
10077330f729Sjoerg /// identifier
10087330f729Sjoerg ///
10097330f729Sjoerg /// opt-strict:
10107330f729Sjoerg /// 'strict' ','
10117330f729Sjoerg ///
10127330f729Sjoerg /// version-arg-list:
10137330f729Sjoerg /// version-arg
10147330f729Sjoerg /// version-arg ',' version-arg-list
10157330f729Sjoerg ///
10167330f729Sjoerg /// version-arg:
10177330f729Sjoerg /// 'introduced' '=' version
10187330f729Sjoerg /// 'deprecated' '=' version
10197330f729Sjoerg /// 'obsoleted' = version
10207330f729Sjoerg /// 'unavailable'
10217330f729Sjoerg /// opt-replacement:
10227330f729Sjoerg /// 'replacement' '=' <string>
10237330f729Sjoerg /// opt-message:
10247330f729Sjoerg /// 'message' '=' <string>
ParseAvailabilityAttribute(IdentifierInfo & Availability,SourceLocation AvailabilityLoc,ParsedAttributes & attrs,SourceLocation * endLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)10257330f729Sjoerg void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
10267330f729Sjoerg SourceLocation AvailabilityLoc,
10277330f729Sjoerg ParsedAttributes &attrs,
10287330f729Sjoerg SourceLocation *endLoc,
10297330f729Sjoerg IdentifierInfo *ScopeName,
10307330f729Sjoerg SourceLocation ScopeLoc,
10317330f729Sjoerg ParsedAttr::Syntax Syntax) {
10327330f729Sjoerg enum { Introduced, Deprecated, Obsoleted, Unknown };
10337330f729Sjoerg AvailabilityChange Changes[Unknown];
10347330f729Sjoerg ExprResult MessageExpr, ReplacementExpr;
10357330f729Sjoerg
10367330f729Sjoerg // Opening '('.
10377330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
10387330f729Sjoerg if (T.consumeOpen()) {
10397330f729Sjoerg Diag(Tok, diag::err_expected) << tok::l_paren;
10407330f729Sjoerg return;
10417330f729Sjoerg }
10427330f729Sjoerg
10437330f729Sjoerg // Parse the platform name.
10447330f729Sjoerg if (Tok.isNot(tok::identifier)) {
10457330f729Sjoerg Diag(Tok, diag::err_availability_expected_platform);
10467330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
10477330f729Sjoerg return;
10487330f729Sjoerg }
10497330f729Sjoerg IdentifierLoc *Platform = ParseIdentifierLoc();
10507330f729Sjoerg if (const IdentifierInfo *const Ident = Platform->Ident) {
10517330f729Sjoerg // Canonicalize platform name from "macosx" to "macos".
10527330f729Sjoerg if (Ident->getName() == "macosx")
10537330f729Sjoerg Platform->Ident = PP.getIdentifierInfo("macos");
10547330f729Sjoerg // Canonicalize platform name from "macosx_app_extension" to
10557330f729Sjoerg // "macos_app_extension".
10567330f729Sjoerg else if (Ident->getName() == "macosx_app_extension")
10577330f729Sjoerg Platform->Ident = PP.getIdentifierInfo("macos_app_extension");
10587330f729Sjoerg else
10597330f729Sjoerg Platform->Ident = PP.getIdentifierInfo(
10607330f729Sjoerg AvailabilityAttr::canonicalizePlatformName(Ident->getName()));
10617330f729Sjoerg }
10627330f729Sjoerg
10637330f729Sjoerg // Parse the ',' following the platform name.
10647330f729Sjoerg if (ExpectAndConsume(tok::comma)) {
10657330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
10667330f729Sjoerg return;
10677330f729Sjoerg }
10687330f729Sjoerg
10697330f729Sjoerg // If we haven't grabbed the pointers for the identifiers
10707330f729Sjoerg // "introduced", "deprecated", and "obsoleted", do so now.
10717330f729Sjoerg if (!Ident_introduced) {
10727330f729Sjoerg Ident_introduced = PP.getIdentifierInfo("introduced");
10737330f729Sjoerg Ident_deprecated = PP.getIdentifierInfo("deprecated");
10747330f729Sjoerg Ident_obsoleted = PP.getIdentifierInfo("obsoleted");
10757330f729Sjoerg Ident_unavailable = PP.getIdentifierInfo("unavailable");
10767330f729Sjoerg Ident_message = PP.getIdentifierInfo("message");
10777330f729Sjoerg Ident_strict = PP.getIdentifierInfo("strict");
10787330f729Sjoerg Ident_replacement = PP.getIdentifierInfo("replacement");
10797330f729Sjoerg }
10807330f729Sjoerg
10817330f729Sjoerg // Parse the optional "strict", the optional "replacement" and the set of
10827330f729Sjoerg // introductions/deprecations/removals.
10837330f729Sjoerg SourceLocation UnavailableLoc, StrictLoc;
10847330f729Sjoerg do {
10857330f729Sjoerg if (Tok.isNot(tok::identifier)) {
10867330f729Sjoerg Diag(Tok, diag::err_availability_expected_change);
10877330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
10887330f729Sjoerg return;
10897330f729Sjoerg }
10907330f729Sjoerg IdentifierInfo *Keyword = Tok.getIdentifierInfo();
10917330f729Sjoerg SourceLocation KeywordLoc = ConsumeToken();
10927330f729Sjoerg
10937330f729Sjoerg if (Keyword == Ident_strict) {
10947330f729Sjoerg if (StrictLoc.isValid()) {
10957330f729Sjoerg Diag(KeywordLoc, diag::err_availability_redundant)
10967330f729Sjoerg << Keyword << SourceRange(StrictLoc);
10977330f729Sjoerg }
10987330f729Sjoerg StrictLoc = KeywordLoc;
10997330f729Sjoerg continue;
11007330f729Sjoerg }
11017330f729Sjoerg
11027330f729Sjoerg if (Keyword == Ident_unavailable) {
11037330f729Sjoerg if (UnavailableLoc.isValid()) {
11047330f729Sjoerg Diag(KeywordLoc, diag::err_availability_redundant)
11057330f729Sjoerg << Keyword << SourceRange(UnavailableLoc);
11067330f729Sjoerg }
11077330f729Sjoerg UnavailableLoc = KeywordLoc;
11087330f729Sjoerg continue;
11097330f729Sjoerg }
11107330f729Sjoerg
11117330f729Sjoerg if (Keyword == Ident_deprecated && Platform->Ident &&
11127330f729Sjoerg Platform->Ident->isStr("swift")) {
11137330f729Sjoerg // For swift, we deprecate for all versions.
11147330f729Sjoerg if (Changes[Deprecated].KeywordLoc.isValid()) {
11157330f729Sjoerg Diag(KeywordLoc, diag::err_availability_redundant)
11167330f729Sjoerg << Keyword
11177330f729Sjoerg << SourceRange(Changes[Deprecated].KeywordLoc);
11187330f729Sjoerg }
11197330f729Sjoerg
11207330f729Sjoerg Changes[Deprecated].KeywordLoc = KeywordLoc;
11217330f729Sjoerg // Use a fake version here.
11227330f729Sjoerg Changes[Deprecated].Version = VersionTuple(1);
11237330f729Sjoerg continue;
11247330f729Sjoerg }
11257330f729Sjoerg
11267330f729Sjoerg if (Tok.isNot(tok::equal)) {
11277330f729Sjoerg Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
11287330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
11297330f729Sjoerg return;
11307330f729Sjoerg }
11317330f729Sjoerg ConsumeToken();
11327330f729Sjoerg if (Keyword == Ident_message || Keyword == Ident_replacement) {
11337330f729Sjoerg if (Tok.isNot(tok::string_literal)) {
11347330f729Sjoerg Diag(Tok, diag::err_expected_string_literal)
11357330f729Sjoerg << /*Source='availability attribute'*/2;
11367330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
11377330f729Sjoerg return;
11387330f729Sjoerg }
11397330f729Sjoerg if (Keyword == Ident_message)
11407330f729Sjoerg MessageExpr = ParseStringLiteralExpression();
11417330f729Sjoerg else
11427330f729Sjoerg ReplacementExpr = ParseStringLiteralExpression();
11437330f729Sjoerg // Also reject wide string literals.
11447330f729Sjoerg if (StringLiteral *MessageStringLiteral =
11457330f729Sjoerg cast_or_null<StringLiteral>(MessageExpr.get())) {
1146*e038c9c4Sjoerg if (!MessageStringLiteral->isAscii()) {
11477330f729Sjoerg Diag(MessageStringLiteral->getSourceRange().getBegin(),
11487330f729Sjoerg diag::err_expected_string_literal)
11497330f729Sjoerg << /*Source='availability attribute'*/ 2;
11507330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
11517330f729Sjoerg return;
11527330f729Sjoerg }
11537330f729Sjoerg }
11547330f729Sjoerg if (Keyword == Ident_message)
11557330f729Sjoerg break;
11567330f729Sjoerg else
11577330f729Sjoerg continue;
11587330f729Sjoerg }
11597330f729Sjoerg
11607330f729Sjoerg // Special handling of 'NA' only when applied to introduced or
11617330f729Sjoerg // deprecated.
11627330f729Sjoerg if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) &&
11637330f729Sjoerg Tok.is(tok::identifier)) {
11647330f729Sjoerg IdentifierInfo *NA = Tok.getIdentifierInfo();
11657330f729Sjoerg if (NA->getName() == "NA") {
11667330f729Sjoerg ConsumeToken();
11677330f729Sjoerg if (Keyword == Ident_introduced)
11687330f729Sjoerg UnavailableLoc = KeywordLoc;
11697330f729Sjoerg continue;
11707330f729Sjoerg }
11717330f729Sjoerg }
11727330f729Sjoerg
11737330f729Sjoerg SourceRange VersionRange;
11747330f729Sjoerg VersionTuple Version = ParseVersionTuple(VersionRange);
11757330f729Sjoerg
11767330f729Sjoerg if (Version.empty()) {
11777330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
11787330f729Sjoerg return;
11797330f729Sjoerg }
11807330f729Sjoerg
11817330f729Sjoerg unsigned Index;
11827330f729Sjoerg if (Keyword == Ident_introduced)
11837330f729Sjoerg Index = Introduced;
11847330f729Sjoerg else if (Keyword == Ident_deprecated)
11857330f729Sjoerg Index = Deprecated;
11867330f729Sjoerg else if (Keyword == Ident_obsoleted)
11877330f729Sjoerg Index = Obsoleted;
11887330f729Sjoerg else
11897330f729Sjoerg Index = Unknown;
11907330f729Sjoerg
11917330f729Sjoerg if (Index < Unknown) {
11927330f729Sjoerg if (!Changes[Index].KeywordLoc.isInvalid()) {
11937330f729Sjoerg Diag(KeywordLoc, diag::err_availability_redundant)
11947330f729Sjoerg << Keyword
11957330f729Sjoerg << SourceRange(Changes[Index].KeywordLoc,
11967330f729Sjoerg Changes[Index].VersionRange.getEnd());
11977330f729Sjoerg }
11987330f729Sjoerg
11997330f729Sjoerg Changes[Index].KeywordLoc = KeywordLoc;
12007330f729Sjoerg Changes[Index].Version = Version;
12017330f729Sjoerg Changes[Index].VersionRange = VersionRange;
12027330f729Sjoerg } else {
12037330f729Sjoerg Diag(KeywordLoc, diag::err_availability_unknown_change)
12047330f729Sjoerg << Keyword << VersionRange;
12057330f729Sjoerg }
12067330f729Sjoerg
12077330f729Sjoerg } while (TryConsumeToken(tok::comma));
12087330f729Sjoerg
12097330f729Sjoerg // Closing ')'.
12107330f729Sjoerg if (T.consumeClose())
12117330f729Sjoerg return;
12127330f729Sjoerg
12137330f729Sjoerg if (endLoc)
12147330f729Sjoerg *endLoc = T.getCloseLocation();
12157330f729Sjoerg
12167330f729Sjoerg // The 'unavailable' availability cannot be combined with any other
12177330f729Sjoerg // availability changes. Make sure that hasn't happened.
12187330f729Sjoerg if (UnavailableLoc.isValid()) {
12197330f729Sjoerg bool Complained = false;
12207330f729Sjoerg for (unsigned Index = Introduced; Index != Unknown; ++Index) {
12217330f729Sjoerg if (Changes[Index].KeywordLoc.isValid()) {
12227330f729Sjoerg if (!Complained) {
12237330f729Sjoerg Diag(UnavailableLoc, diag::warn_availability_and_unavailable)
12247330f729Sjoerg << SourceRange(Changes[Index].KeywordLoc,
12257330f729Sjoerg Changes[Index].VersionRange.getEnd());
12267330f729Sjoerg Complained = true;
12277330f729Sjoerg }
12287330f729Sjoerg
12297330f729Sjoerg // Clear out the availability.
12307330f729Sjoerg Changes[Index] = AvailabilityChange();
12317330f729Sjoerg }
12327330f729Sjoerg }
12337330f729Sjoerg }
12347330f729Sjoerg
12357330f729Sjoerg // Record this attribute
12367330f729Sjoerg attrs.addNew(&Availability,
12377330f729Sjoerg SourceRange(AvailabilityLoc, T.getCloseLocation()),
12387330f729Sjoerg ScopeName, ScopeLoc,
12397330f729Sjoerg Platform,
12407330f729Sjoerg Changes[Introduced],
12417330f729Sjoerg Changes[Deprecated],
12427330f729Sjoerg Changes[Obsoleted],
12437330f729Sjoerg UnavailableLoc, MessageExpr.get(),
12447330f729Sjoerg Syntax, StrictLoc, ReplacementExpr.get());
12457330f729Sjoerg }
12467330f729Sjoerg
12477330f729Sjoerg /// Parse the contents of the "external_source_symbol" attribute.
12487330f729Sjoerg ///
12497330f729Sjoerg /// external-source-symbol-attribute:
12507330f729Sjoerg /// 'external_source_symbol' '(' keyword-arg-list ')'
12517330f729Sjoerg ///
12527330f729Sjoerg /// keyword-arg-list:
12537330f729Sjoerg /// keyword-arg
12547330f729Sjoerg /// keyword-arg ',' keyword-arg-list
12557330f729Sjoerg ///
12567330f729Sjoerg /// keyword-arg:
12577330f729Sjoerg /// 'language' '=' <string>
12587330f729Sjoerg /// 'defined_in' '=' <string>
12597330f729Sjoerg /// 'generated_declaration'
ParseExternalSourceSymbolAttribute(IdentifierInfo & ExternalSourceSymbol,SourceLocation Loc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)12607330f729Sjoerg void Parser::ParseExternalSourceSymbolAttribute(
12617330f729Sjoerg IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,
12627330f729Sjoerg ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
12637330f729Sjoerg SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
12647330f729Sjoerg // Opening '('.
12657330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
12667330f729Sjoerg if (T.expectAndConsume())
12677330f729Sjoerg return;
12687330f729Sjoerg
12697330f729Sjoerg // Initialize the pointers for the keyword identifiers when required.
12707330f729Sjoerg if (!Ident_language) {
12717330f729Sjoerg Ident_language = PP.getIdentifierInfo("language");
12727330f729Sjoerg Ident_defined_in = PP.getIdentifierInfo("defined_in");
12737330f729Sjoerg Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration");
12747330f729Sjoerg }
12757330f729Sjoerg
12767330f729Sjoerg ExprResult Language;
12777330f729Sjoerg bool HasLanguage = false;
12787330f729Sjoerg ExprResult DefinedInExpr;
12797330f729Sjoerg bool HasDefinedIn = false;
12807330f729Sjoerg IdentifierLoc *GeneratedDeclaration = nullptr;
12817330f729Sjoerg
12827330f729Sjoerg // Parse the language/defined_in/generated_declaration keywords
12837330f729Sjoerg do {
12847330f729Sjoerg if (Tok.isNot(tok::identifier)) {
12857330f729Sjoerg Diag(Tok, diag::err_external_source_symbol_expected_keyword);
12867330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
12877330f729Sjoerg return;
12887330f729Sjoerg }
12897330f729Sjoerg
12907330f729Sjoerg SourceLocation KeywordLoc = Tok.getLocation();
12917330f729Sjoerg IdentifierInfo *Keyword = Tok.getIdentifierInfo();
12927330f729Sjoerg if (Keyword == Ident_generated_declaration) {
12937330f729Sjoerg if (GeneratedDeclaration) {
12947330f729Sjoerg Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword;
12957330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
12967330f729Sjoerg return;
12977330f729Sjoerg }
12987330f729Sjoerg GeneratedDeclaration = ParseIdentifierLoc();
12997330f729Sjoerg continue;
13007330f729Sjoerg }
13017330f729Sjoerg
13027330f729Sjoerg if (Keyword != Ident_language && Keyword != Ident_defined_in) {
13037330f729Sjoerg Diag(Tok, diag::err_external_source_symbol_expected_keyword);
13047330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
13057330f729Sjoerg return;
13067330f729Sjoerg }
13077330f729Sjoerg
13087330f729Sjoerg ConsumeToken();
13097330f729Sjoerg if (ExpectAndConsume(tok::equal, diag::err_expected_after,
13107330f729Sjoerg Keyword->getName())) {
13117330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
13127330f729Sjoerg return;
13137330f729Sjoerg }
13147330f729Sjoerg
13157330f729Sjoerg bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn;
13167330f729Sjoerg if (Keyword == Ident_language)
13177330f729Sjoerg HasLanguage = true;
13187330f729Sjoerg else
13197330f729Sjoerg HasDefinedIn = true;
13207330f729Sjoerg
13217330f729Sjoerg if (Tok.isNot(tok::string_literal)) {
13227330f729Sjoerg Diag(Tok, diag::err_expected_string_literal)
13237330f729Sjoerg << /*Source='external_source_symbol attribute'*/ 3
13247330f729Sjoerg << /*language | source container*/ (Keyword != Ident_language);
13257330f729Sjoerg SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
13267330f729Sjoerg continue;
13277330f729Sjoerg }
13287330f729Sjoerg if (Keyword == Ident_language) {
13297330f729Sjoerg if (HadLanguage) {
13307330f729Sjoerg Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
13317330f729Sjoerg << Keyword;
13327330f729Sjoerg ParseStringLiteralExpression();
13337330f729Sjoerg continue;
13347330f729Sjoerg }
13357330f729Sjoerg Language = ParseStringLiteralExpression();
13367330f729Sjoerg } else {
13377330f729Sjoerg assert(Keyword == Ident_defined_in && "Invalid clause keyword!");
13387330f729Sjoerg if (HadDefinedIn) {
13397330f729Sjoerg Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)
13407330f729Sjoerg << Keyword;
13417330f729Sjoerg ParseStringLiteralExpression();
13427330f729Sjoerg continue;
13437330f729Sjoerg }
13447330f729Sjoerg DefinedInExpr = ParseStringLiteralExpression();
13457330f729Sjoerg }
13467330f729Sjoerg } while (TryConsumeToken(tok::comma));
13477330f729Sjoerg
13487330f729Sjoerg // Closing ')'.
13497330f729Sjoerg if (T.consumeClose())
13507330f729Sjoerg return;
13517330f729Sjoerg if (EndLoc)
13527330f729Sjoerg *EndLoc = T.getCloseLocation();
13537330f729Sjoerg
13547330f729Sjoerg ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(),
13557330f729Sjoerg GeneratedDeclaration};
13567330f729Sjoerg Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()),
13577330f729Sjoerg ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
13587330f729Sjoerg }
13597330f729Sjoerg
13607330f729Sjoerg /// Parse the contents of the "objc_bridge_related" attribute.
13617330f729Sjoerg /// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
13627330f729Sjoerg /// related_class:
13637330f729Sjoerg /// Identifier
13647330f729Sjoerg ///
13657330f729Sjoerg /// opt-class_method:
13667330f729Sjoerg /// Identifier: | <empty>
13677330f729Sjoerg ///
13687330f729Sjoerg /// opt-instance_method:
13697330f729Sjoerg /// Identifier | <empty>
13707330f729Sjoerg ///
ParseObjCBridgeRelatedAttribute(IdentifierInfo & ObjCBridgeRelated,SourceLocation ObjCBridgeRelatedLoc,ParsedAttributes & attrs,SourceLocation * endLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)13717330f729Sjoerg void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
13727330f729Sjoerg SourceLocation ObjCBridgeRelatedLoc,
13737330f729Sjoerg ParsedAttributes &attrs,
13747330f729Sjoerg SourceLocation *endLoc,
13757330f729Sjoerg IdentifierInfo *ScopeName,
13767330f729Sjoerg SourceLocation ScopeLoc,
13777330f729Sjoerg ParsedAttr::Syntax Syntax) {
13787330f729Sjoerg // Opening '('.
13797330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
13807330f729Sjoerg if (T.consumeOpen()) {
13817330f729Sjoerg Diag(Tok, diag::err_expected) << tok::l_paren;
13827330f729Sjoerg return;
13837330f729Sjoerg }
13847330f729Sjoerg
13857330f729Sjoerg // Parse the related class name.
13867330f729Sjoerg if (Tok.isNot(tok::identifier)) {
13877330f729Sjoerg Diag(Tok, diag::err_objcbridge_related_expected_related_class);
13887330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
13897330f729Sjoerg return;
13907330f729Sjoerg }
13917330f729Sjoerg IdentifierLoc *RelatedClass = ParseIdentifierLoc();
13927330f729Sjoerg if (ExpectAndConsume(tok::comma)) {
13937330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
13947330f729Sjoerg return;
13957330f729Sjoerg }
13967330f729Sjoerg
13977330f729Sjoerg // Parse class method name. It's non-optional in the sense that a trailing
13987330f729Sjoerg // comma is required, but it can be the empty string, and then we record a
13997330f729Sjoerg // nullptr.
14007330f729Sjoerg IdentifierLoc *ClassMethod = nullptr;
14017330f729Sjoerg if (Tok.is(tok::identifier)) {
14027330f729Sjoerg ClassMethod = ParseIdentifierLoc();
14037330f729Sjoerg if (!TryConsumeToken(tok::colon)) {
14047330f729Sjoerg Diag(Tok, diag::err_objcbridge_related_selector_name);
14057330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
14067330f729Sjoerg return;
14077330f729Sjoerg }
14087330f729Sjoerg }
14097330f729Sjoerg if (!TryConsumeToken(tok::comma)) {
14107330f729Sjoerg if (Tok.is(tok::colon))
14117330f729Sjoerg Diag(Tok, diag::err_objcbridge_related_selector_name);
14127330f729Sjoerg else
14137330f729Sjoerg Diag(Tok, diag::err_expected) << tok::comma;
14147330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
14157330f729Sjoerg return;
14167330f729Sjoerg }
14177330f729Sjoerg
14187330f729Sjoerg // Parse instance method name. Also non-optional but empty string is
14197330f729Sjoerg // permitted.
14207330f729Sjoerg IdentifierLoc *InstanceMethod = nullptr;
14217330f729Sjoerg if (Tok.is(tok::identifier))
14227330f729Sjoerg InstanceMethod = ParseIdentifierLoc();
14237330f729Sjoerg else if (Tok.isNot(tok::r_paren)) {
14247330f729Sjoerg Diag(Tok, diag::err_expected) << tok::r_paren;
14257330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
14267330f729Sjoerg return;
14277330f729Sjoerg }
14287330f729Sjoerg
14297330f729Sjoerg // Closing ')'.
14307330f729Sjoerg if (T.consumeClose())
14317330f729Sjoerg return;
14327330f729Sjoerg
14337330f729Sjoerg if (endLoc)
14347330f729Sjoerg *endLoc = T.getCloseLocation();
14357330f729Sjoerg
14367330f729Sjoerg // Record this attribute
14377330f729Sjoerg attrs.addNew(&ObjCBridgeRelated,
14387330f729Sjoerg SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
14397330f729Sjoerg ScopeName, ScopeLoc,
14407330f729Sjoerg RelatedClass,
14417330f729Sjoerg ClassMethod,
14427330f729Sjoerg InstanceMethod,
14437330f729Sjoerg Syntax);
14447330f729Sjoerg }
14457330f729Sjoerg
14467330f729Sjoerg
ParseSwiftNewTypeAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)1447*e038c9c4Sjoerg void Parser::ParseSwiftNewTypeAttribute(
1448*e038c9c4Sjoerg IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
1449*e038c9c4Sjoerg ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
1450*e038c9c4Sjoerg SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) {
1451*e038c9c4Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
14527330f729Sjoerg
1453*e038c9c4Sjoerg // Opening '('
1454*e038c9c4Sjoerg if (T.consumeOpen()) {
1455*e038c9c4Sjoerg Diag(Tok, diag::err_expected) << tok::l_paren;
1456*e038c9c4Sjoerg return;
14577330f729Sjoerg }
14587330f729Sjoerg
1459*e038c9c4Sjoerg if (Tok.is(tok::r_paren)) {
1460*e038c9c4Sjoerg Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
1461*e038c9c4Sjoerg T.consumeClose();
1462*e038c9c4Sjoerg return;
1463*e038c9c4Sjoerg }
1464*e038c9c4Sjoerg if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {
1465*e038c9c4Sjoerg Diag(Tok, diag::warn_attribute_type_not_supported)
1466*e038c9c4Sjoerg << &AttrName << Tok.getIdentifierInfo();
1467*e038c9c4Sjoerg if (!isTokenSpecial())
1468*e038c9c4Sjoerg ConsumeToken();
1469*e038c9c4Sjoerg T.consumeClose();
1470*e038c9c4Sjoerg return;
14717330f729Sjoerg }
14727330f729Sjoerg
1473*e038c9c4Sjoerg auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(),
1474*e038c9c4Sjoerg Tok.getIdentifierInfo());
1475*e038c9c4Sjoerg ConsumeToken();
14767330f729Sjoerg
1477*e038c9c4Sjoerg // Closing ')'
1478*e038c9c4Sjoerg if (T.consumeClose())
1479*e038c9c4Sjoerg return;
1480*e038c9c4Sjoerg if (EndLoc)
1481*e038c9c4Sjoerg *EndLoc = T.getCloseLocation();
14827330f729Sjoerg
1483*e038c9c4Sjoerg ArgsUnion Args[] = {SwiftType};
1484*e038c9c4Sjoerg Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()),
1485*e038c9c4Sjoerg ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax);
14867330f729Sjoerg }
14877330f729Sjoerg
14887330f729Sjoerg
ParseTypeTagForDatatypeAttribute(IdentifierInfo & AttrName,SourceLocation AttrNameLoc,ParsedAttributes & Attrs,SourceLocation * EndLoc,IdentifierInfo * ScopeName,SourceLocation ScopeLoc,ParsedAttr::Syntax Syntax)14897330f729Sjoerg void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
14907330f729Sjoerg SourceLocation AttrNameLoc,
14917330f729Sjoerg ParsedAttributes &Attrs,
14927330f729Sjoerg SourceLocation *EndLoc,
14937330f729Sjoerg IdentifierInfo *ScopeName,
14947330f729Sjoerg SourceLocation ScopeLoc,
14957330f729Sjoerg ParsedAttr::Syntax Syntax) {
14967330f729Sjoerg assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
14977330f729Sjoerg
14987330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
14997330f729Sjoerg T.consumeOpen();
15007330f729Sjoerg
15017330f729Sjoerg if (Tok.isNot(tok::identifier)) {
15027330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
15037330f729Sjoerg T.skipToEnd();
15047330f729Sjoerg return;
15057330f729Sjoerg }
15067330f729Sjoerg IdentifierLoc *ArgumentKind = ParseIdentifierLoc();
15077330f729Sjoerg
15087330f729Sjoerg if (ExpectAndConsume(tok::comma)) {
15097330f729Sjoerg T.skipToEnd();
15107330f729Sjoerg return;
15117330f729Sjoerg }
15127330f729Sjoerg
15137330f729Sjoerg SourceRange MatchingCTypeRange;
15147330f729Sjoerg TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange);
15157330f729Sjoerg if (MatchingCType.isInvalid()) {
15167330f729Sjoerg T.skipToEnd();
15177330f729Sjoerg return;
15187330f729Sjoerg }
15197330f729Sjoerg
15207330f729Sjoerg bool LayoutCompatible = false;
15217330f729Sjoerg bool MustBeNull = false;
15227330f729Sjoerg while (TryConsumeToken(tok::comma)) {
15237330f729Sjoerg if (Tok.isNot(tok::identifier)) {
15247330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
15257330f729Sjoerg T.skipToEnd();
15267330f729Sjoerg return;
15277330f729Sjoerg }
15287330f729Sjoerg IdentifierInfo *Flag = Tok.getIdentifierInfo();
15297330f729Sjoerg if (Flag->isStr("layout_compatible"))
15307330f729Sjoerg LayoutCompatible = true;
15317330f729Sjoerg else if (Flag->isStr("must_be_null"))
15327330f729Sjoerg MustBeNull = true;
15337330f729Sjoerg else {
15347330f729Sjoerg Diag(Tok, diag::err_type_safety_unknown_flag) << Flag;
15357330f729Sjoerg T.skipToEnd();
15367330f729Sjoerg return;
15377330f729Sjoerg }
15387330f729Sjoerg ConsumeToken(); // consume flag
15397330f729Sjoerg }
15407330f729Sjoerg
15417330f729Sjoerg if (!T.consumeClose()) {
15427330f729Sjoerg Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc,
15437330f729Sjoerg ArgumentKind, MatchingCType.get(),
15447330f729Sjoerg LayoutCompatible, MustBeNull, Syntax);
15457330f729Sjoerg }
15467330f729Sjoerg
15477330f729Sjoerg if (EndLoc)
15487330f729Sjoerg *EndLoc = T.getCloseLocation();
15497330f729Sjoerg }
15507330f729Sjoerg
15517330f729Sjoerg /// DiagnoseProhibitedCXX11Attribute - We have found the opening square brackets
15527330f729Sjoerg /// of a C++11 attribute-specifier in a location where an attribute is not
15537330f729Sjoerg /// permitted. By C++11 [dcl.attr.grammar]p6, this is ill-formed. Diagnose this
15547330f729Sjoerg /// situation.
15557330f729Sjoerg ///
15567330f729Sjoerg /// \return \c true if we skipped an attribute-like chunk of tokens, \c false if
15577330f729Sjoerg /// this doesn't appear to actually be an attribute-specifier, and the caller
15587330f729Sjoerg /// should try to parse it.
DiagnoseProhibitedCXX11Attribute()15597330f729Sjoerg bool Parser::DiagnoseProhibitedCXX11Attribute() {
15607330f729Sjoerg assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square));
15617330f729Sjoerg
15627330f729Sjoerg switch (isCXX11AttributeSpecifier(/*Disambiguate*/true)) {
15637330f729Sjoerg case CAK_NotAttributeSpecifier:
15647330f729Sjoerg // No diagnostic: we're in Obj-C++11 and this is not actually an attribute.
15657330f729Sjoerg return false;
15667330f729Sjoerg
15677330f729Sjoerg case CAK_InvalidAttributeSpecifier:
15687330f729Sjoerg Diag(Tok.getLocation(), diag::err_l_square_l_square_not_attribute);
15697330f729Sjoerg return false;
15707330f729Sjoerg
15717330f729Sjoerg case CAK_AttributeSpecifier:
15727330f729Sjoerg // Parse and discard the attributes.
15737330f729Sjoerg SourceLocation BeginLoc = ConsumeBracket();
15747330f729Sjoerg ConsumeBracket();
15757330f729Sjoerg SkipUntil(tok::r_square);
15767330f729Sjoerg assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied");
15777330f729Sjoerg SourceLocation EndLoc = ConsumeBracket();
15787330f729Sjoerg Diag(BeginLoc, diag::err_attributes_not_allowed)
15797330f729Sjoerg << SourceRange(BeginLoc, EndLoc);
15807330f729Sjoerg return true;
15817330f729Sjoerg }
15827330f729Sjoerg llvm_unreachable("All cases handled above.");
15837330f729Sjoerg }
15847330f729Sjoerg
15857330f729Sjoerg /// We have found the opening square brackets of a C++11
15867330f729Sjoerg /// attribute-specifier in a location where an attribute is not permitted, but
15877330f729Sjoerg /// we know where the attributes ought to be written. Parse them anyway, and
15887330f729Sjoerg /// provide a fixit moving them to the right place.
DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange & Attrs,SourceLocation CorrectLocation)15897330f729Sjoerg void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
15907330f729Sjoerg SourceLocation CorrectLocation) {
15917330f729Sjoerg assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
15927330f729Sjoerg Tok.is(tok::kw_alignas));
15937330f729Sjoerg
15947330f729Sjoerg // Consume the attributes.
15957330f729Sjoerg SourceLocation Loc = Tok.getLocation();
15967330f729Sjoerg ParseCXX11Attributes(Attrs);
15977330f729Sjoerg CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
15987330f729Sjoerg // FIXME: use err_attributes_misplaced
15997330f729Sjoerg Diag(Loc, diag::err_attributes_not_allowed)
16007330f729Sjoerg << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
16017330f729Sjoerg << FixItHint::CreateRemoval(AttrRange);
16027330f729Sjoerg }
16037330f729Sjoerg
DiagnoseProhibitedAttributes(const SourceRange & Range,const SourceLocation CorrectLocation)16047330f729Sjoerg void Parser::DiagnoseProhibitedAttributes(
16057330f729Sjoerg const SourceRange &Range, const SourceLocation CorrectLocation) {
16067330f729Sjoerg if (CorrectLocation.isValid()) {
16077330f729Sjoerg CharSourceRange AttrRange(Range, true);
16087330f729Sjoerg Diag(CorrectLocation, diag::err_attributes_misplaced)
16097330f729Sjoerg << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
16107330f729Sjoerg << FixItHint::CreateRemoval(AttrRange);
16117330f729Sjoerg } else
16127330f729Sjoerg Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range;
16137330f729Sjoerg }
16147330f729Sjoerg
ProhibitCXX11Attributes(ParsedAttributesWithRange & Attrs,unsigned DiagID,bool DiagnoseEmptyAttrs)16157330f729Sjoerg void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
1616*e038c9c4Sjoerg unsigned DiagID, bool DiagnoseEmptyAttrs) {
1617*e038c9c4Sjoerg
1618*e038c9c4Sjoerg if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) {
1619*e038c9c4Sjoerg // An attribute list has been parsed, but it was empty.
1620*e038c9c4Sjoerg // This is the case for [[]].
1621*e038c9c4Sjoerg const auto &LangOpts = getLangOpts();
1622*e038c9c4Sjoerg auto &SM = PP.getSourceManager();
1623*e038c9c4Sjoerg Token FirstLSquare;
1624*e038c9c4Sjoerg Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts);
1625*e038c9c4Sjoerg
1626*e038c9c4Sjoerg if (FirstLSquare.is(tok::l_square)) {
1627*e038c9c4Sjoerg llvm::Optional<Token> SecondLSquare =
1628*e038c9c4Sjoerg Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts);
1629*e038c9c4Sjoerg
1630*e038c9c4Sjoerg if (SecondLSquare && SecondLSquare->is(tok::l_square)) {
1631*e038c9c4Sjoerg // The attribute range starts with [[, but is empty. So this must
1632*e038c9c4Sjoerg // be [[]], which we are supposed to diagnose because
1633*e038c9c4Sjoerg // DiagnoseEmptyAttrs is true.
1634*e038c9c4Sjoerg Diag(Attrs.Range.getBegin(), DiagID) << Attrs.Range;
1635*e038c9c4Sjoerg return;
1636*e038c9c4Sjoerg }
1637*e038c9c4Sjoerg }
1638*e038c9c4Sjoerg }
1639*e038c9c4Sjoerg
16407330f729Sjoerg for (const ParsedAttr &AL : Attrs) {
16417330f729Sjoerg if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
16427330f729Sjoerg continue;
16437330f729Sjoerg if (AL.getKind() == ParsedAttr::UnknownAttribute)
1644*e038c9c4Sjoerg Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
1645*e038c9c4Sjoerg << AL << AL.getRange();
16467330f729Sjoerg else {
16477330f729Sjoerg Diag(AL.getLoc(), DiagID) << AL;
16487330f729Sjoerg AL.setInvalid();
16497330f729Sjoerg }
16507330f729Sjoerg }
16517330f729Sjoerg }
16527330f729Sjoerg
16537330f729Sjoerg // Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
16547330f729Sjoerg // applies to var, not the type Foo.
16557330f729Sjoerg // As an exception to the rule, __declspec(align(...)) before the
16567330f729Sjoerg // class-key affects the type instead of the variable.
16577330f729Sjoerg // Also, Microsoft-style [attributes] seem to affect the type instead of the
16587330f729Sjoerg // variable.
16597330f729Sjoerg // This function moves attributes that should apply to the type off DS to Attrs.
stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange & Attrs,DeclSpec & DS,Sema::TagUseKind TUK)16607330f729Sjoerg void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
16617330f729Sjoerg DeclSpec &DS,
16627330f729Sjoerg Sema::TagUseKind TUK) {
16637330f729Sjoerg if (TUK == Sema::TUK_Reference)
16647330f729Sjoerg return;
16657330f729Sjoerg
16667330f729Sjoerg llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;
16677330f729Sjoerg
16687330f729Sjoerg for (ParsedAttr &AL : DS.getAttributes()) {
16697330f729Sjoerg if ((AL.getKind() == ParsedAttr::AT_Aligned &&
16707330f729Sjoerg AL.isDeclspecAttribute()) ||
16717330f729Sjoerg AL.isMicrosoftAttribute())
16727330f729Sjoerg ToBeMoved.push_back(&AL);
16737330f729Sjoerg }
16747330f729Sjoerg
16757330f729Sjoerg for (ParsedAttr *AL : ToBeMoved) {
16767330f729Sjoerg DS.getAttributes().remove(AL);
16777330f729Sjoerg Attrs.addAtEnd(AL);
16787330f729Sjoerg }
16797330f729Sjoerg }
16807330f729Sjoerg
16817330f729Sjoerg /// ParseDeclaration - Parse a full 'declaration', which consists of
16827330f729Sjoerg /// declaration-specifiers, some number of declarators, and a semicolon.
16837330f729Sjoerg /// 'Context' should be a DeclaratorContext value. This returns the
16847330f729Sjoerg /// location of the semicolon in DeclEnd.
16857330f729Sjoerg ///
16867330f729Sjoerg /// declaration: [C99 6.7]
16877330f729Sjoerg /// block-declaration ->
16887330f729Sjoerg /// simple-declaration
16897330f729Sjoerg /// others [FIXME]
16907330f729Sjoerg /// [C++] template-declaration
16917330f729Sjoerg /// [C++] namespace-definition
16927330f729Sjoerg /// [C++] using-directive
16937330f729Sjoerg /// [C++] using-declaration
16947330f729Sjoerg /// [C++11/C11] static_assert-declaration
16957330f729Sjoerg /// others... [FIXME]
16967330f729Sjoerg ///
16977330f729Sjoerg Parser::DeclGroupPtrTy
ParseDeclaration(DeclaratorContext Context,SourceLocation & DeclEnd,ParsedAttributesWithRange & attrs,SourceLocation * DeclSpecStart)16987330f729Sjoerg Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd,
16997330f729Sjoerg ParsedAttributesWithRange &attrs,
17007330f729Sjoerg SourceLocation *DeclSpecStart) {
17017330f729Sjoerg ParenBraceBracketBalancer BalancerRAIIObj(*this);
17027330f729Sjoerg // Must temporarily exit the objective-c container scope for
17037330f729Sjoerg // parsing c none objective-c decls.
17047330f729Sjoerg ObjCDeclContextSwitch ObjCDC(*this);
17057330f729Sjoerg
17067330f729Sjoerg Decl *SingleDecl = nullptr;
17077330f729Sjoerg switch (Tok.getKind()) {
17087330f729Sjoerg case tok::kw_template:
17097330f729Sjoerg case tok::kw_export:
17107330f729Sjoerg ProhibitAttributes(attrs);
17117330f729Sjoerg SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs);
17127330f729Sjoerg break;
17137330f729Sjoerg case tok::kw_inline:
17147330f729Sjoerg // Could be the start of an inline namespace. Allowed as an ext in C++03.
17157330f729Sjoerg if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) {
17167330f729Sjoerg ProhibitAttributes(attrs);
17177330f729Sjoerg SourceLocation InlineLoc = ConsumeToken();
17187330f729Sjoerg return ParseNamespace(Context, DeclEnd, InlineLoc);
17197330f729Sjoerg }
17207330f729Sjoerg return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr,
17217330f729Sjoerg DeclSpecStart);
17227330f729Sjoerg case tok::kw_namespace:
17237330f729Sjoerg ProhibitAttributes(attrs);
17247330f729Sjoerg return ParseNamespace(Context, DeclEnd);
17257330f729Sjoerg case tok::kw_using:
17267330f729Sjoerg return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
17277330f729Sjoerg DeclEnd, attrs);
17287330f729Sjoerg case tok::kw_static_assert:
17297330f729Sjoerg case tok::kw__Static_assert:
17307330f729Sjoerg ProhibitAttributes(attrs);
17317330f729Sjoerg SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
17327330f729Sjoerg break;
17337330f729Sjoerg default:
17347330f729Sjoerg return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr,
17357330f729Sjoerg DeclSpecStart);
17367330f729Sjoerg }
17377330f729Sjoerg
17387330f729Sjoerg // This routine returns a DeclGroup, if the thing we parsed only contains a
17397330f729Sjoerg // single decl, convert it now.
17407330f729Sjoerg return Actions.ConvertDeclToDeclGroup(SingleDecl);
17417330f729Sjoerg }
17427330f729Sjoerg
17437330f729Sjoerg /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
17447330f729Sjoerg /// declaration-specifiers init-declarator-list[opt] ';'
17457330f729Sjoerg /// [C++11] attribute-specifier-seq decl-specifier-seq[opt]
17467330f729Sjoerg /// init-declarator-list ';'
17477330f729Sjoerg ///[C90/C++]init-declarator-list ';' [TODO]
17487330f729Sjoerg /// [OMP] threadprivate-directive
17497330f729Sjoerg /// [OMP] allocate-directive [TODO]
17507330f729Sjoerg ///
17517330f729Sjoerg /// for-range-declaration: [C++11 6.5p1: stmt.ranged]
17527330f729Sjoerg /// attribute-specifier-seq[opt] type-specifier-seq declarator
17537330f729Sjoerg ///
17547330f729Sjoerg /// If RequireSemi is false, this does not check for a ';' at the end of the
17557330f729Sjoerg /// declaration. If it is true, it checks for and eats it.
17567330f729Sjoerg ///
17577330f729Sjoerg /// If FRI is non-null, we might be parsing a for-range-declaration instead
17587330f729Sjoerg /// of a simple-declaration. If we find that we are, we also parse the
17597330f729Sjoerg /// for-range-initializer, and place it here.
17607330f729Sjoerg ///
17617330f729Sjoerg /// DeclSpecStart is used when decl-specifiers are parsed before parsing
17627330f729Sjoerg /// the Declaration. The SourceLocation for this Decl is set to
17637330f729Sjoerg /// DeclSpecStart if DeclSpecStart is non-null.
ParseSimpleDeclaration(DeclaratorContext Context,SourceLocation & DeclEnd,ParsedAttributesWithRange & Attrs,bool RequireSemi,ForRangeInit * FRI,SourceLocation * DeclSpecStart)17647330f729Sjoerg Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
17657330f729Sjoerg DeclaratorContext Context, SourceLocation &DeclEnd,
17667330f729Sjoerg ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI,
17677330f729Sjoerg SourceLocation *DeclSpecStart) {
17687330f729Sjoerg // Parse the common declaration-specifiers piece.
17697330f729Sjoerg ParsingDeclSpec DS(*this);
17707330f729Sjoerg
17717330f729Sjoerg DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);
17727330f729Sjoerg ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext);
17737330f729Sjoerg
17747330f729Sjoerg // If we had a free-standing type definition with a missing semicolon, we
17757330f729Sjoerg // may get this far before the problem becomes obvious.
17767330f729Sjoerg if (DS.hasTagDefinition() &&
17777330f729Sjoerg DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext))
17787330f729Sjoerg return nullptr;
17797330f729Sjoerg
17807330f729Sjoerg // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
17817330f729Sjoerg // declaration-specifiers init-declarator-list[opt] ';'
17827330f729Sjoerg if (Tok.is(tok::semi)) {
17837330f729Sjoerg ProhibitAttributes(Attrs);
17847330f729Sjoerg DeclEnd = Tok.getLocation();
17857330f729Sjoerg if (RequireSemi) ConsumeToken();
17867330f729Sjoerg RecordDecl *AnonRecord = nullptr;
17877330f729Sjoerg Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
17887330f729Sjoerg DS, AnonRecord);
17897330f729Sjoerg DS.complete(TheDecl);
17907330f729Sjoerg if (AnonRecord) {
17917330f729Sjoerg Decl* decls[] = {AnonRecord, TheDecl};
17927330f729Sjoerg return Actions.BuildDeclaratorGroup(decls);
17937330f729Sjoerg }
17947330f729Sjoerg return Actions.ConvertDeclToDeclGroup(TheDecl);
17957330f729Sjoerg }
17967330f729Sjoerg
17977330f729Sjoerg if (DeclSpecStart)
17987330f729Sjoerg DS.SetRangeStart(*DeclSpecStart);
17997330f729Sjoerg
18007330f729Sjoerg DS.takeAttributesFrom(Attrs);
18017330f729Sjoerg return ParseDeclGroup(DS, Context, &DeclEnd, FRI);
18027330f729Sjoerg }
18037330f729Sjoerg
18047330f729Sjoerg /// Returns true if this might be the start of a declarator, or a common typo
18057330f729Sjoerg /// for a declarator.
MightBeDeclarator(DeclaratorContext Context)18067330f729Sjoerg bool Parser::MightBeDeclarator(DeclaratorContext Context) {
18077330f729Sjoerg switch (Tok.getKind()) {
18087330f729Sjoerg case tok::annot_cxxscope:
18097330f729Sjoerg case tok::annot_template_id:
18107330f729Sjoerg case tok::caret:
18117330f729Sjoerg case tok::code_completion:
18127330f729Sjoerg case tok::coloncolon:
18137330f729Sjoerg case tok::ellipsis:
18147330f729Sjoerg case tok::kw___attribute:
18157330f729Sjoerg case tok::kw_operator:
18167330f729Sjoerg case tok::l_paren:
18177330f729Sjoerg case tok::star:
18187330f729Sjoerg return true;
18197330f729Sjoerg
18207330f729Sjoerg case tok::amp:
18217330f729Sjoerg case tok::ampamp:
18227330f729Sjoerg return getLangOpts().CPlusPlus;
18237330f729Sjoerg
18247330f729Sjoerg case tok::l_square: // Might be an attribute on an unnamed bit-field.
1825*e038c9c4Sjoerg return Context == DeclaratorContext::Member && getLangOpts().CPlusPlus11 &&
1826*e038c9c4Sjoerg NextToken().is(tok::l_square);
18277330f729Sjoerg
18287330f729Sjoerg case tok::colon: // Might be a typo for '::' or an unnamed bit-field.
1829*e038c9c4Sjoerg return Context == DeclaratorContext::Member || getLangOpts().CPlusPlus;
18307330f729Sjoerg
18317330f729Sjoerg case tok::identifier:
18327330f729Sjoerg switch (NextToken().getKind()) {
18337330f729Sjoerg case tok::code_completion:
18347330f729Sjoerg case tok::coloncolon:
18357330f729Sjoerg case tok::comma:
18367330f729Sjoerg case tok::equal:
18377330f729Sjoerg case tok::equalequal: // Might be a typo for '='.
18387330f729Sjoerg case tok::kw_alignas:
18397330f729Sjoerg case tok::kw_asm:
18407330f729Sjoerg case tok::kw___attribute:
18417330f729Sjoerg case tok::l_brace:
18427330f729Sjoerg case tok::l_paren:
18437330f729Sjoerg case tok::l_square:
18447330f729Sjoerg case tok::less:
18457330f729Sjoerg case tok::r_brace:
18467330f729Sjoerg case tok::r_paren:
18477330f729Sjoerg case tok::r_square:
18487330f729Sjoerg case tok::semi:
18497330f729Sjoerg return true;
18507330f729Sjoerg
18517330f729Sjoerg case tok::colon:
18527330f729Sjoerg // At namespace scope, 'identifier:' is probably a typo for 'identifier::'
18537330f729Sjoerg // and in block scope it's probably a label. Inside a class definition,
18547330f729Sjoerg // this is a bit-field.
1855*e038c9c4Sjoerg return Context == DeclaratorContext::Member ||
1856*e038c9c4Sjoerg (getLangOpts().CPlusPlus && Context == DeclaratorContext::File);
18577330f729Sjoerg
18587330f729Sjoerg case tok::identifier: // Possible virt-specifier.
18597330f729Sjoerg return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());
18607330f729Sjoerg
18617330f729Sjoerg default:
18627330f729Sjoerg return false;
18637330f729Sjoerg }
18647330f729Sjoerg
18657330f729Sjoerg default:
18667330f729Sjoerg return false;
18677330f729Sjoerg }
18687330f729Sjoerg }
18697330f729Sjoerg
18707330f729Sjoerg /// Skip until we reach something which seems like a sensible place to pick
18717330f729Sjoerg /// up parsing after a malformed declaration. This will sometimes stop sooner
18727330f729Sjoerg /// than SkipUntil(tok::r_brace) would, but will never stop later.
SkipMalformedDecl()18737330f729Sjoerg void Parser::SkipMalformedDecl() {
18747330f729Sjoerg while (true) {
18757330f729Sjoerg switch (Tok.getKind()) {
18767330f729Sjoerg case tok::l_brace:
18777330f729Sjoerg // Skip until matching }, then stop. We've probably skipped over
18787330f729Sjoerg // a malformed class or function definition or similar.
18797330f729Sjoerg ConsumeBrace();
18807330f729Sjoerg SkipUntil(tok::r_brace);
18817330f729Sjoerg if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) {
18827330f729Sjoerg // This declaration isn't over yet. Keep skipping.
18837330f729Sjoerg continue;
18847330f729Sjoerg }
18857330f729Sjoerg TryConsumeToken(tok::semi);
18867330f729Sjoerg return;
18877330f729Sjoerg
18887330f729Sjoerg case tok::l_square:
18897330f729Sjoerg ConsumeBracket();
18907330f729Sjoerg SkipUntil(tok::r_square);
18917330f729Sjoerg continue;
18927330f729Sjoerg
18937330f729Sjoerg case tok::l_paren:
18947330f729Sjoerg ConsumeParen();
18957330f729Sjoerg SkipUntil(tok::r_paren);
18967330f729Sjoerg continue;
18977330f729Sjoerg
18987330f729Sjoerg case tok::r_brace:
18997330f729Sjoerg return;
19007330f729Sjoerg
19017330f729Sjoerg case tok::semi:
19027330f729Sjoerg ConsumeToken();
19037330f729Sjoerg return;
19047330f729Sjoerg
19057330f729Sjoerg case tok::kw_inline:
19067330f729Sjoerg // 'inline namespace' at the start of a line is almost certainly
19077330f729Sjoerg // a good place to pick back up parsing, except in an Objective-C
19087330f729Sjoerg // @interface context.
19097330f729Sjoerg if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) &&
19107330f729Sjoerg (!ParsingInObjCContainer || CurParsedObjCImpl))
19117330f729Sjoerg return;
19127330f729Sjoerg break;
19137330f729Sjoerg
19147330f729Sjoerg case tok::kw_namespace:
19157330f729Sjoerg // 'namespace' at the start of a line is almost certainly a good
19167330f729Sjoerg // place to pick back up parsing, except in an Objective-C
19177330f729Sjoerg // @interface context.
19187330f729Sjoerg if (Tok.isAtStartOfLine() &&
19197330f729Sjoerg (!ParsingInObjCContainer || CurParsedObjCImpl))
19207330f729Sjoerg return;
19217330f729Sjoerg break;
19227330f729Sjoerg
19237330f729Sjoerg case tok::at:
19247330f729Sjoerg // @end is very much like } in Objective-C contexts.
19257330f729Sjoerg if (NextToken().isObjCAtKeyword(tok::objc_end) &&
19267330f729Sjoerg ParsingInObjCContainer)
19277330f729Sjoerg return;
19287330f729Sjoerg break;
19297330f729Sjoerg
19307330f729Sjoerg case tok::minus:
19317330f729Sjoerg case tok::plus:
19327330f729Sjoerg // - and + probably start new method declarations in Objective-C contexts.
19337330f729Sjoerg if (Tok.isAtStartOfLine() && ParsingInObjCContainer)
19347330f729Sjoerg return;
19357330f729Sjoerg break;
19367330f729Sjoerg
19377330f729Sjoerg case tok::eof:
19387330f729Sjoerg case tok::annot_module_begin:
19397330f729Sjoerg case tok::annot_module_end:
19407330f729Sjoerg case tok::annot_module_include:
19417330f729Sjoerg return;
19427330f729Sjoerg
19437330f729Sjoerg default:
19447330f729Sjoerg break;
19457330f729Sjoerg }
19467330f729Sjoerg
19477330f729Sjoerg ConsumeAnyToken();
19487330f729Sjoerg }
19497330f729Sjoerg }
19507330f729Sjoerg
19517330f729Sjoerg /// ParseDeclGroup - Having concluded that this is either a function
19527330f729Sjoerg /// definition or a group of object declarations, actually parse the
19537330f729Sjoerg /// result.
ParseDeclGroup(ParsingDeclSpec & DS,DeclaratorContext Context,SourceLocation * DeclEnd,ForRangeInit * FRI)19547330f729Sjoerg Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
19557330f729Sjoerg DeclaratorContext Context,
19567330f729Sjoerg SourceLocation *DeclEnd,
19577330f729Sjoerg ForRangeInit *FRI) {
19587330f729Sjoerg // Parse the first declarator.
19597330f729Sjoerg ParsingDeclarator D(*this, DS, Context);
19607330f729Sjoerg ParseDeclarator(D);
19617330f729Sjoerg
19627330f729Sjoerg // Bail out if the first declarator didn't seem well-formed.
19637330f729Sjoerg if (!D.hasName() && !D.mayOmitIdentifier()) {
19647330f729Sjoerg SkipMalformedDecl();
19657330f729Sjoerg return nullptr;
19667330f729Sjoerg }
19677330f729Sjoerg
1968*e038c9c4Sjoerg if (Tok.is(tok::kw_requires))
1969*e038c9c4Sjoerg ParseTrailingRequiresClause(D);
1970*e038c9c4Sjoerg
19717330f729Sjoerg // Save late-parsed attributes for now; they need to be parsed in the
19727330f729Sjoerg // appropriate function scope after the function Decl has been constructed.
19737330f729Sjoerg // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList.
19747330f729Sjoerg LateParsedAttrList LateParsedAttrs(true);
19757330f729Sjoerg if (D.isFunctionDeclarator()) {
19767330f729Sjoerg MaybeParseGNUAttributes(D, &LateParsedAttrs);
19777330f729Sjoerg
19787330f729Sjoerg // The _Noreturn keyword can't appear here, unlike the GNU noreturn
19797330f729Sjoerg // attribute. If we find the keyword here, tell the user to put it
19807330f729Sjoerg // at the start instead.
19817330f729Sjoerg if (Tok.is(tok::kw__Noreturn)) {
19827330f729Sjoerg SourceLocation Loc = ConsumeToken();
19837330f729Sjoerg const char *PrevSpec;
19847330f729Sjoerg unsigned DiagID;
19857330f729Sjoerg
19867330f729Sjoerg // We can offer a fixit if it's valid to mark this function as _Noreturn
19877330f729Sjoerg // and we don't have any other declarators in this declaration.
19887330f729Sjoerg bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
19897330f729Sjoerg MaybeParseGNUAttributes(D, &LateParsedAttrs);
19907330f729Sjoerg Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try);
19917330f729Sjoerg
19927330f729Sjoerg Diag(Loc, diag::err_c11_noreturn_misplaced)
19937330f729Sjoerg << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())
19947330f729Sjoerg << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ")
19957330f729Sjoerg : FixItHint());
19967330f729Sjoerg }
19977330f729Sjoerg }
19987330f729Sjoerg
19997330f729Sjoerg // Check to see if we have a function *definition* which must have a body.
2000*e038c9c4Sjoerg if (D.isFunctionDeclarator()) {
2001*e038c9c4Sjoerg if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) {
2002*e038c9c4Sjoerg cutOffParsing();
2003*e038c9c4Sjoerg Actions.CodeCompleteAfterFunctionEquals(D);
2004*e038c9c4Sjoerg return nullptr;
2005*e038c9c4Sjoerg }
20067330f729Sjoerg // Look at the next token to make sure that this isn't a function
20077330f729Sjoerg // declaration. We have to check this because __attribute__ might be the
20087330f729Sjoerg // start of a function definition in GCC-extended K&R C.
2009*e038c9c4Sjoerg if (!isDeclarationAfterDeclarator()) {
20107330f729Sjoerg
20117330f729Sjoerg // Function definitions are only allowed at file scope and in C++ classes.
20127330f729Sjoerg // The C++ inline method definition case is handled elsewhere, so we only
20137330f729Sjoerg // need to handle the file scope definition case.
2014*e038c9c4Sjoerg if (Context == DeclaratorContext::File) {
20157330f729Sjoerg if (isStartOfFunctionDefinition(D)) {
20167330f729Sjoerg if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
20177330f729Sjoerg Diag(Tok, diag::err_function_declared_typedef);
20187330f729Sjoerg
20197330f729Sjoerg // Recover by treating the 'typedef' as spurious.
20207330f729Sjoerg DS.ClearStorageClassSpecs();
20217330f729Sjoerg }
20227330f729Sjoerg
2023*e038c9c4Sjoerg Decl *TheDecl = ParseFunctionDefinition(D, ParsedTemplateInfo(),
2024*e038c9c4Sjoerg &LateParsedAttrs);
20257330f729Sjoerg return Actions.ConvertDeclToDeclGroup(TheDecl);
20267330f729Sjoerg }
20277330f729Sjoerg
20287330f729Sjoerg if (isDeclarationSpecifier()) {
20297330f729Sjoerg // If there is an invalid declaration specifier right after the
20307330f729Sjoerg // function prototype, then we must be in a missing semicolon case
20317330f729Sjoerg // where this isn't actually a body. Just fall through into the code
20327330f729Sjoerg // that handles it as a prototype, and let the top-level code handle
20337330f729Sjoerg // the erroneous declspec where it would otherwise expect a comma or
20347330f729Sjoerg // semicolon.
20357330f729Sjoerg } else {
20367330f729Sjoerg Diag(Tok, diag::err_expected_fn_body);
20377330f729Sjoerg SkipUntil(tok::semi);
20387330f729Sjoerg return nullptr;
20397330f729Sjoerg }
20407330f729Sjoerg } else {
20417330f729Sjoerg if (Tok.is(tok::l_brace)) {
20427330f729Sjoerg Diag(Tok, diag::err_function_definition_not_allowed);
20437330f729Sjoerg SkipMalformedDecl();
20447330f729Sjoerg return nullptr;
20457330f729Sjoerg }
20467330f729Sjoerg }
20477330f729Sjoerg }
2048*e038c9c4Sjoerg }
20497330f729Sjoerg
20507330f729Sjoerg if (ParseAsmAttributesAfterDeclarator(D))
20517330f729Sjoerg return nullptr;
20527330f729Sjoerg
20537330f729Sjoerg // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we
20547330f729Sjoerg // must parse and analyze the for-range-initializer before the declaration is
20557330f729Sjoerg // analyzed.
20567330f729Sjoerg //
20577330f729Sjoerg // Handle the Objective-C for-in loop variable similarly, although we
20587330f729Sjoerg // don't need to parse the container in advance.
20597330f729Sjoerg if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {
20607330f729Sjoerg bool IsForRangeLoop = false;
20617330f729Sjoerg if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
20627330f729Sjoerg IsForRangeLoop = true;
20637330f729Sjoerg if (getLangOpts().OpenMP)
20647330f729Sjoerg Actions.startOpenMPCXXRangeFor();
20657330f729Sjoerg if (Tok.is(tok::l_brace))
20667330f729Sjoerg FRI->RangeExpr = ParseBraceInitializer();
20677330f729Sjoerg else
20687330f729Sjoerg FRI->RangeExpr = ParseExpression();
20697330f729Sjoerg }
20707330f729Sjoerg
20717330f729Sjoerg Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
20727330f729Sjoerg if (IsForRangeLoop) {
20737330f729Sjoerg Actions.ActOnCXXForRangeDecl(ThisDecl);
20747330f729Sjoerg } else {
20757330f729Sjoerg // Obj-C for loop
20767330f729Sjoerg if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl))
20777330f729Sjoerg VD->setObjCForDecl(true);
20787330f729Sjoerg }
20797330f729Sjoerg Actions.FinalizeDeclaration(ThisDecl);
20807330f729Sjoerg D.complete(ThisDecl);
20817330f729Sjoerg return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);
20827330f729Sjoerg }
20837330f729Sjoerg
20847330f729Sjoerg SmallVector<Decl *, 8> DeclsInGroup;
20857330f729Sjoerg Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(
20867330f729Sjoerg D, ParsedTemplateInfo(), FRI);
20877330f729Sjoerg if (LateParsedAttrs.size() > 0)
20887330f729Sjoerg ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);
20897330f729Sjoerg D.complete(FirstDecl);
20907330f729Sjoerg if (FirstDecl)
20917330f729Sjoerg DeclsInGroup.push_back(FirstDecl);
20927330f729Sjoerg
2093*e038c9c4Sjoerg bool ExpectSemi = Context != DeclaratorContext::ForInit;
20947330f729Sjoerg
20957330f729Sjoerg // If we don't have a comma, it is either the end of the list (a ';') or an
20967330f729Sjoerg // error, bail out.
20977330f729Sjoerg SourceLocation CommaLoc;
20987330f729Sjoerg while (TryConsumeToken(tok::comma, CommaLoc)) {
20997330f729Sjoerg if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) {
21007330f729Sjoerg // This comma was followed by a line-break and something which can't be
21017330f729Sjoerg // the start of a declarator. The comma was probably a typo for a
21027330f729Sjoerg // semicolon.
21037330f729Sjoerg Diag(CommaLoc, diag::err_expected_semi_declaration)
21047330f729Sjoerg << FixItHint::CreateReplacement(CommaLoc, ";");
21057330f729Sjoerg ExpectSemi = false;
21067330f729Sjoerg break;
21077330f729Sjoerg }
21087330f729Sjoerg
21097330f729Sjoerg // Parse the next declarator.
21107330f729Sjoerg D.clear();
21117330f729Sjoerg D.setCommaLoc(CommaLoc);
21127330f729Sjoerg
21137330f729Sjoerg // Accept attributes in an init-declarator. In the first declarator in a
21147330f729Sjoerg // declaration, these would be part of the declspec. In subsequent
21157330f729Sjoerg // declarators, they become part of the declarator itself, so that they
21167330f729Sjoerg // don't apply to declarators after *this* one. Examples:
21177330f729Sjoerg // short __attribute__((common)) var; -> declspec
21187330f729Sjoerg // short var __attribute__((common)); -> declarator
21197330f729Sjoerg // short x, __attribute__((common)) var; -> declarator
21207330f729Sjoerg MaybeParseGNUAttributes(D);
21217330f729Sjoerg
21227330f729Sjoerg // MSVC parses but ignores qualifiers after the comma as an extension.
21237330f729Sjoerg if (getLangOpts().MicrosoftExt)
21247330f729Sjoerg DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
21257330f729Sjoerg
21267330f729Sjoerg ParseDeclarator(D);
21277330f729Sjoerg if (!D.isInvalidType()) {
2128*e038c9c4Sjoerg // C++2a [dcl.decl]p1
2129*e038c9c4Sjoerg // init-declarator:
2130*e038c9c4Sjoerg // declarator initializer[opt]
2131*e038c9c4Sjoerg // declarator requires-clause
2132*e038c9c4Sjoerg if (Tok.is(tok::kw_requires))
2133*e038c9c4Sjoerg ParseTrailingRequiresClause(D);
21347330f729Sjoerg Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
21357330f729Sjoerg D.complete(ThisDecl);
21367330f729Sjoerg if (ThisDecl)
21377330f729Sjoerg DeclsInGroup.push_back(ThisDecl);
21387330f729Sjoerg }
21397330f729Sjoerg }
21407330f729Sjoerg
21417330f729Sjoerg if (DeclEnd)
21427330f729Sjoerg *DeclEnd = Tok.getLocation();
21437330f729Sjoerg
2144*e038c9c4Sjoerg if (ExpectSemi && ExpectAndConsumeSemi(
2145*e038c9c4Sjoerg Context == DeclaratorContext::File
21467330f729Sjoerg ? diag::err_invalid_token_after_toplevel_declarator
21477330f729Sjoerg : diag::err_expected_semi_declaration)) {
21487330f729Sjoerg // Okay, there was no semicolon and one was expected. If we see a
21497330f729Sjoerg // declaration specifier, just assume it was missing and continue parsing.
21507330f729Sjoerg // Otherwise things are very confused and we skip to recover.
21517330f729Sjoerg if (!isDeclarationSpecifier()) {
21527330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
21537330f729Sjoerg TryConsumeToken(tok::semi);
21547330f729Sjoerg }
21557330f729Sjoerg }
21567330f729Sjoerg
21577330f729Sjoerg return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
21587330f729Sjoerg }
21597330f729Sjoerg
21607330f729Sjoerg /// Parse an optional simple-asm-expr and attributes, and attach them to a
21617330f729Sjoerg /// declarator. Returns true on an error.
ParseAsmAttributesAfterDeclarator(Declarator & D)21627330f729Sjoerg bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
21637330f729Sjoerg // If a simple-asm-expr is present, parse it.
21647330f729Sjoerg if (Tok.is(tok::kw_asm)) {
21657330f729Sjoerg SourceLocation Loc;
2166*e038c9c4Sjoerg ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));
21677330f729Sjoerg if (AsmLabel.isInvalid()) {
21687330f729Sjoerg SkipUntil(tok::semi, StopBeforeMatch);
21697330f729Sjoerg return true;
21707330f729Sjoerg }
21717330f729Sjoerg
21727330f729Sjoerg D.setAsmLabel(AsmLabel.get());
21737330f729Sjoerg D.SetRangeEnd(Loc);
21747330f729Sjoerg }
21757330f729Sjoerg
21767330f729Sjoerg MaybeParseGNUAttributes(D);
21777330f729Sjoerg return false;
21787330f729Sjoerg }
21797330f729Sjoerg
21807330f729Sjoerg /// Parse 'declaration' after parsing 'declaration-specifiers
21817330f729Sjoerg /// declarator'. This method parses the remainder of the declaration
21827330f729Sjoerg /// (including any attributes or initializer, among other things) and
21837330f729Sjoerg /// finalizes the declaration.
21847330f729Sjoerg ///
21857330f729Sjoerg /// init-declarator: [C99 6.7]
21867330f729Sjoerg /// declarator
21877330f729Sjoerg /// declarator '=' initializer
21887330f729Sjoerg /// [GNU] declarator simple-asm-expr[opt] attributes[opt]
21897330f729Sjoerg /// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer
21907330f729Sjoerg /// [C++] declarator initializer[opt]
21917330f729Sjoerg ///
21927330f729Sjoerg /// [C++] initializer:
21937330f729Sjoerg /// [C++] '=' initializer-clause
21947330f729Sjoerg /// [C++] '(' expression-list ')'
21957330f729Sjoerg /// [C++0x] '=' 'default' [TODO]
21967330f729Sjoerg /// [C++0x] '=' 'delete'
21977330f729Sjoerg /// [C++0x] braced-init-list
21987330f729Sjoerg ///
21997330f729Sjoerg /// According to the standard grammar, =default and =delete are function
22007330f729Sjoerg /// definitions, but that definitely doesn't fit with the parser here.
22017330f729Sjoerg ///
ParseDeclarationAfterDeclarator(Declarator & D,const ParsedTemplateInfo & TemplateInfo)22027330f729Sjoerg Decl *Parser::ParseDeclarationAfterDeclarator(
22037330f729Sjoerg Declarator &D, const ParsedTemplateInfo &TemplateInfo) {
22047330f729Sjoerg if (ParseAsmAttributesAfterDeclarator(D))
22057330f729Sjoerg return nullptr;
22067330f729Sjoerg
22077330f729Sjoerg return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
22087330f729Sjoerg }
22097330f729Sjoerg
ParseDeclarationAfterDeclaratorAndAttributes(Declarator & D,const ParsedTemplateInfo & TemplateInfo,ForRangeInit * FRI)22107330f729Sjoerg Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
22117330f729Sjoerg Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {
22127330f729Sjoerg // RAII type used to track whether we're inside an initializer.
22137330f729Sjoerg struct InitializerScopeRAII {
22147330f729Sjoerg Parser &P;
22157330f729Sjoerg Declarator &D;
22167330f729Sjoerg Decl *ThisDecl;
22177330f729Sjoerg
22187330f729Sjoerg InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
22197330f729Sjoerg : P(P), D(D), ThisDecl(ThisDecl) {
22207330f729Sjoerg if (ThisDecl && P.getLangOpts().CPlusPlus) {
22217330f729Sjoerg Scope *S = nullptr;
22227330f729Sjoerg if (D.getCXXScopeSpec().isSet()) {
22237330f729Sjoerg P.EnterScope(0);
22247330f729Sjoerg S = P.getCurScope();
22257330f729Sjoerg }
22267330f729Sjoerg P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
22277330f729Sjoerg }
22287330f729Sjoerg }
22297330f729Sjoerg ~InitializerScopeRAII() { pop(); }
22307330f729Sjoerg void pop() {
22317330f729Sjoerg if (ThisDecl && P.getLangOpts().CPlusPlus) {
22327330f729Sjoerg Scope *S = nullptr;
22337330f729Sjoerg if (D.getCXXScopeSpec().isSet())
22347330f729Sjoerg S = P.getCurScope();
22357330f729Sjoerg P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
22367330f729Sjoerg if (S)
22377330f729Sjoerg P.ExitScope();
22387330f729Sjoerg }
22397330f729Sjoerg ThisDecl = nullptr;
22407330f729Sjoerg }
22417330f729Sjoerg };
22427330f729Sjoerg
2243*e038c9c4Sjoerg enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced };
2244*e038c9c4Sjoerg InitKind TheInitKind;
2245*e038c9c4Sjoerg // If a '==' or '+=' is found, suggest a fixit to '='.
2246*e038c9c4Sjoerg if (isTokenEqualOrEqualTypo())
2247*e038c9c4Sjoerg TheInitKind = InitKind::Equal;
2248*e038c9c4Sjoerg else if (Tok.is(tok::l_paren))
2249*e038c9c4Sjoerg TheInitKind = InitKind::CXXDirect;
2250*e038c9c4Sjoerg else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
2251*e038c9c4Sjoerg (!CurParsedObjCImpl || !D.isFunctionDeclarator()))
2252*e038c9c4Sjoerg TheInitKind = InitKind::CXXBraced;
2253*e038c9c4Sjoerg else
2254*e038c9c4Sjoerg TheInitKind = InitKind::Uninitialized;
2255*e038c9c4Sjoerg if (TheInitKind != InitKind::Uninitialized)
2256*e038c9c4Sjoerg D.setHasInitializer();
2257*e038c9c4Sjoerg
2258*e038c9c4Sjoerg // Inform Sema that we just parsed this declarator.
22597330f729Sjoerg Decl *ThisDecl = nullptr;
2260*e038c9c4Sjoerg Decl *OuterDecl = nullptr;
22617330f729Sjoerg switch (TemplateInfo.Kind) {
22627330f729Sjoerg case ParsedTemplateInfo::NonTemplate:
22637330f729Sjoerg ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
22647330f729Sjoerg break;
22657330f729Sjoerg
22667330f729Sjoerg case ParsedTemplateInfo::Template:
22677330f729Sjoerg case ParsedTemplateInfo::ExplicitSpecialization: {
22687330f729Sjoerg ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
22697330f729Sjoerg *TemplateInfo.TemplateParams,
22707330f729Sjoerg D);
2271*e038c9c4Sjoerg if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl)) {
22727330f729Sjoerg // Re-direct this decl to refer to the templated decl so that we can
22737330f729Sjoerg // initialize it.
22747330f729Sjoerg ThisDecl = VT->getTemplatedDecl();
2275*e038c9c4Sjoerg OuterDecl = VT;
2276*e038c9c4Sjoerg }
22777330f729Sjoerg break;
22787330f729Sjoerg }
22797330f729Sjoerg case ParsedTemplateInfo::ExplicitInstantiation: {
22807330f729Sjoerg if (Tok.is(tok::semi)) {
22817330f729Sjoerg DeclResult ThisRes = Actions.ActOnExplicitInstantiation(
22827330f729Sjoerg getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
22837330f729Sjoerg if (ThisRes.isInvalid()) {
22847330f729Sjoerg SkipUntil(tok::semi, StopBeforeMatch);
22857330f729Sjoerg return nullptr;
22867330f729Sjoerg }
22877330f729Sjoerg ThisDecl = ThisRes.get();
22887330f729Sjoerg } else {
22897330f729Sjoerg // FIXME: This check should be for a variable template instantiation only.
22907330f729Sjoerg
22917330f729Sjoerg // Check that this is a valid instantiation
22927330f729Sjoerg if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
22937330f729Sjoerg // If the declarator-id is not a template-id, issue a diagnostic and
22947330f729Sjoerg // recover by ignoring the 'template' keyword.
22957330f729Sjoerg Diag(Tok, diag::err_template_defn_explicit_instantiation)
22967330f729Sjoerg << 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
22977330f729Sjoerg ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
22987330f729Sjoerg } else {
22997330f729Sjoerg SourceLocation LAngleLoc =
23007330f729Sjoerg PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
23017330f729Sjoerg Diag(D.getIdentifierLoc(),
23027330f729Sjoerg diag::err_explicit_instantiation_with_definition)
23037330f729Sjoerg << SourceRange(TemplateInfo.TemplateLoc)
23047330f729Sjoerg << FixItHint::CreateInsertion(LAngleLoc, "<>");
23057330f729Sjoerg
23067330f729Sjoerg // Recover as if it were an explicit specialization.
23077330f729Sjoerg TemplateParameterLists FakedParamLists;
23087330f729Sjoerg FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
23097330f729Sjoerg 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None,
23107330f729Sjoerg LAngleLoc, nullptr));
23117330f729Sjoerg
23127330f729Sjoerg ThisDecl =
23137330f729Sjoerg Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
23147330f729Sjoerg }
23157330f729Sjoerg }
23167330f729Sjoerg break;
23177330f729Sjoerg }
23187330f729Sjoerg }
23197330f729Sjoerg
2320*e038c9c4Sjoerg switch (TheInitKind) {
23217330f729Sjoerg // Parse declarator '=' initializer.
2322*e038c9c4Sjoerg case InitKind::Equal: {
23237330f729Sjoerg SourceLocation EqualLoc = ConsumeToken();
23247330f729Sjoerg
23257330f729Sjoerg if (Tok.is(tok::kw_delete)) {
23267330f729Sjoerg if (D.isFunctionDeclarator())
23277330f729Sjoerg Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
23287330f729Sjoerg << 1 /* delete */;
23297330f729Sjoerg else
23307330f729Sjoerg Diag(ConsumeToken(), diag::err_deleted_non_function);
23317330f729Sjoerg } else if (Tok.is(tok::kw_default)) {
23327330f729Sjoerg if (D.isFunctionDeclarator())
23337330f729Sjoerg Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
23347330f729Sjoerg << 0 /* default */;
23357330f729Sjoerg else
23367330f729Sjoerg Diag(ConsumeToken(), diag::err_default_special_members)
2337*e038c9c4Sjoerg << getLangOpts().CPlusPlus20;
23387330f729Sjoerg } else {
23397330f729Sjoerg InitializerScopeRAII InitScope(*this, D, ThisDecl);
23407330f729Sjoerg
23417330f729Sjoerg if (Tok.is(tok::code_completion)) {
2342*e038c9c4Sjoerg cutOffParsing();
23437330f729Sjoerg Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
23447330f729Sjoerg Actions.FinalizeDeclaration(ThisDecl);
23457330f729Sjoerg return nullptr;
23467330f729Sjoerg }
23477330f729Sjoerg
23487330f729Sjoerg PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
23497330f729Sjoerg ExprResult Init = ParseInitializer();
23507330f729Sjoerg
23517330f729Sjoerg // If this is the only decl in (possibly) range based for statement,
23527330f729Sjoerg // our best guess is that the user meant ':' instead of '='.
23537330f729Sjoerg if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) {
23547330f729Sjoerg Diag(EqualLoc, diag::err_single_decl_assign_in_for_range)
23557330f729Sjoerg << FixItHint::CreateReplacement(EqualLoc, ":");
23567330f729Sjoerg // We are trying to stop parser from looking for ';' in this for
23577330f729Sjoerg // statement, therefore preventing spurious errors to be issued.
23587330f729Sjoerg FRI->ColonLoc = EqualLoc;
23597330f729Sjoerg Init = ExprError();
23607330f729Sjoerg FRI->RangeExpr = Init;
23617330f729Sjoerg }
23627330f729Sjoerg
23637330f729Sjoerg InitScope.pop();
23647330f729Sjoerg
23657330f729Sjoerg if (Init.isInvalid()) {
23667330f729Sjoerg SmallVector<tok::TokenKind, 2> StopTokens;
23677330f729Sjoerg StopTokens.push_back(tok::comma);
2368*e038c9c4Sjoerg if (D.getContext() == DeclaratorContext::ForInit ||
2369*e038c9c4Sjoerg D.getContext() == DeclaratorContext::SelectionInit)
23707330f729Sjoerg StopTokens.push_back(tok::r_paren);
23717330f729Sjoerg SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);
23727330f729Sjoerg Actions.ActOnInitializerError(ThisDecl);
23737330f729Sjoerg } else
23747330f729Sjoerg Actions.AddInitializerToDecl(ThisDecl, Init.get(),
23757330f729Sjoerg /*DirectInit=*/false);
23767330f729Sjoerg }
2377*e038c9c4Sjoerg break;
2378*e038c9c4Sjoerg }
2379*e038c9c4Sjoerg case InitKind::CXXDirect: {
23807330f729Sjoerg // Parse C++ direct initializer: '(' expression-list ')'
23817330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
23827330f729Sjoerg T.consumeOpen();
23837330f729Sjoerg
23847330f729Sjoerg ExprVector Exprs;
23857330f729Sjoerg CommaLocsTy CommaLocs;
23867330f729Sjoerg
23877330f729Sjoerg InitializerScopeRAII InitScope(*this, D, ThisDecl);
23887330f729Sjoerg
23897330f729Sjoerg auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
23907330f729Sjoerg auto RunSignatureHelp = [&]() {
23917330f729Sjoerg QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
23927330f729Sjoerg getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
23937330f729Sjoerg ThisDecl->getLocation(), Exprs, T.getOpenLocation());
23947330f729Sjoerg CalledSignatureHelp = true;
23957330f729Sjoerg return PreferredType;
23967330f729Sjoerg };
23977330f729Sjoerg auto SetPreferredType = [&] {
23987330f729Sjoerg PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
23997330f729Sjoerg };
24007330f729Sjoerg
24017330f729Sjoerg llvm::function_ref<void()> ExpressionStarts;
24027330f729Sjoerg if (ThisVarDecl) {
24037330f729Sjoerg // ParseExpressionList can sometimes succeed even when ThisDecl is not
24047330f729Sjoerg // VarDecl. This is an error and it is reported in a call to
24057330f729Sjoerg // Actions.ActOnInitializerError(). However, we call
24067330f729Sjoerg // ProduceConstructorSignatureHelp only on VarDecls.
24077330f729Sjoerg ExpressionStarts = SetPreferredType;
24087330f729Sjoerg }
24097330f729Sjoerg if (ParseExpressionList(Exprs, CommaLocs, ExpressionStarts)) {
24107330f729Sjoerg if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
24117330f729Sjoerg Actions.ProduceConstructorSignatureHelp(
24127330f729Sjoerg getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
24137330f729Sjoerg ThisDecl->getLocation(), Exprs, T.getOpenLocation());
24147330f729Sjoerg CalledSignatureHelp = true;
24157330f729Sjoerg }
24167330f729Sjoerg Actions.ActOnInitializerError(ThisDecl);
24177330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
24187330f729Sjoerg } else {
24197330f729Sjoerg // Match the ')'.
24207330f729Sjoerg T.consumeClose();
24217330f729Sjoerg
24227330f729Sjoerg assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
24237330f729Sjoerg "Unexpected number of commas!");
24247330f729Sjoerg
24257330f729Sjoerg InitScope.pop();
24267330f729Sjoerg
24277330f729Sjoerg ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
24287330f729Sjoerg T.getCloseLocation(),
24297330f729Sjoerg Exprs);
24307330f729Sjoerg Actions.AddInitializerToDecl(ThisDecl, Initializer.get(),
24317330f729Sjoerg /*DirectInit=*/true);
24327330f729Sjoerg }
2433*e038c9c4Sjoerg break;
2434*e038c9c4Sjoerg }
2435*e038c9c4Sjoerg case InitKind::CXXBraced: {
24367330f729Sjoerg // Parse C++0x braced-init-list.
24377330f729Sjoerg Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
24387330f729Sjoerg
24397330f729Sjoerg InitializerScopeRAII InitScope(*this, D, ThisDecl);
24407330f729Sjoerg
2441*e038c9c4Sjoerg PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);
24427330f729Sjoerg ExprResult Init(ParseBraceInitializer());
24437330f729Sjoerg
24447330f729Sjoerg InitScope.pop();
24457330f729Sjoerg
24467330f729Sjoerg if (Init.isInvalid()) {
24477330f729Sjoerg Actions.ActOnInitializerError(ThisDecl);
24487330f729Sjoerg } else
24497330f729Sjoerg Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true);
2450*e038c9c4Sjoerg break;
2451*e038c9c4Sjoerg }
2452*e038c9c4Sjoerg case InitKind::Uninitialized: {
24537330f729Sjoerg Actions.ActOnUninitializedDecl(ThisDecl);
2454*e038c9c4Sjoerg break;
2455*e038c9c4Sjoerg }
24567330f729Sjoerg }
24577330f729Sjoerg
24587330f729Sjoerg Actions.FinalizeDeclaration(ThisDecl);
2459*e038c9c4Sjoerg return OuterDecl ? OuterDecl : ThisDecl;
24607330f729Sjoerg }
24617330f729Sjoerg
24627330f729Sjoerg /// ParseSpecifierQualifierList
24637330f729Sjoerg /// specifier-qualifier-list:
24647330f729Sjoerg /// type-specifier specifier-qualifier-list[opt]
24657330f729Sjoerg /// type-qualifier specifier-qualifier-list[opt]
24667330f729Sjoerg /// [GNU] attributes specifier-qualifier-list[opt]
24677330f729Sjoerg ///
ParseSpecifierQualifierList(DeclSpec & DS,AccessSpecifier AS,DeclSpecContext DSC)24687330f729Sjoerg void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
24697330f729Sjoerg DeclSpecContext DSC) {
24707330f729Sjoerg /// specifier-qualifier-list is a subset of declaration-specifiers. Just
24717330f729Sjoerg /// parse declaration-specifiers and complain about extra stuff.
24727330f729Sjoerg /// TODO: diagnose attribute-specifiers and alignment-specifiers.
24737330f729Sjoerg ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC);
24747330f729Sjoerg
24757330f729Sjoerg // Validate declspec for type-name.
24767330f729Sjoerg unsigned Specs = DS.getParsedSpecifiers();
24777330f729Sjoerg if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {
24787330f729Sjoerg Diag(Tok, diag::err_expected_type);
24797330f729Sjoerg DS.SetTypeSpecError();
24807330f729Sjoerg } else if (Specs == DeclSpec::PQ_None && !DS.hasAttributes()) {
24817330f729Sjoerg Diag(Tok, diag::err_typename_requires_specqual);
24827330f729Sjoerg if (!DS.hasTypeSpecifier())
24837330f729Sjoerg DS.SetTypeSpecError();
24847330f729Sjoerg }
24857330f729Sjoerg
24867330f729Sjoerg // Issue diagnostic and remove storage class if present.
24877330f729Sjoerg if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
24887330f729Sjoerg if (DS.getStorageClassSpecLoc().isValid())
24897330f729Sjoerg Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);
24907330f729Sjoerg else
24917330f729Sjoerg Diag(DS.getThreadStorageClassSpecLoc(),
24927330f729Sjoerg diag::err_typename_invalid_storageclass);
24937330f729Sjoerg DS.ClearStorageClassSpecs();
24947330f729Sjoerg }
24957330f729Sjoerg
24967330f729Sjoerg // Issue diagnostic and remove function specifier if present.
24977330f729Sjoerg if (Specs & DeclSpec::PQ_FunctionSpecifier) {
24987330f729Sjoerg if (DS.isInlineSpecified())
24997330f729Sjoerg Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
25007330f729Sjoerg if (DS.isVirtualSpecified())
25017330f729Sjoerg Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
25027330f729Sjoerg if (DS.hasExplicitSpecifier())
25037330f729Sjoerg Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
25047330f729Sjoerg DS.ClearFunctionSpecs();
25057330f729Sjoerg }
25067330f729Sjoerg
25077330f729Sjoerg // Issue diagnostic and remove constexpr specifier if present.
25087330f729Sjoerg if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) {
25097330f729Sjoerg Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr)
2510*e038c9c4Sjoerg << static_cast<int>(DS.getConstexprSpecifier());
25117330f729Sjoerg DS.ClearConstexprSpec();
25127330f729Sjoerg }
25137330f729Sjoerg }
25147330f729Sjoerg
25157330f729Sjoerg /// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the
25167330f729Sjoerg /// specified token is valid after the identifier in a declarator which
25177330f729Sjoerg /// immediately follows the declspec. For example, these things are valid:
25187330f729Sjoerg ///
25197330f729Sjoerg /// int x [ 4]; // direct-declarator
25207330f729Sjoerg /// int x ( int y); // direct-declarator
25217330f729Sjoerg /// int(int x ) // direct-declarator
25227330f729Sjoerg /// int x ; // simple-declaration
25237330f729Sjoerg /// int x = 17; // init-declarator-list
25247330f729Sjoerg /// int x , y; // init-declarator-list
25257330f729Sjoerg /// int x __asm__ ("foo"); // init-declarator-list
25267330f729Sjoerg /// int x : 4; // struct-declarator
25277330f729Sjoerg /// int x { 5}; // C++'0x unified initializers
25287330f729Sjoerg ///
25297330f729Sjoerg /// This is not, because 'x' does not immediately follow the declspec (though
25307330f729Sjoerg /// ')' happens to be valid anyway).
25317330f729Sjoerg /// int (x)
25327330f729Sjoerg ///
isValidAfterIdentifierInDeclarator(const Token & T)25337330f729Sjoerg static bool isValidAfterIdentifierInDeclarator(const Token &T) {
25347330f729Sjoerg return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi,
25357330f729Sjoerg tok::comma, tok::equal, tok::kw_asm, tok::l_brace,
25367330f729Sjoerg tok::colon);
25377330f729Sjoerg }
25387330f729Sjoerg
25397330f729Sjoerg /// ParseImplicitInt - This method is called when we have an non-typename
25407330f729Sjoerg /// identifier in a declspec (which normally terminates the decl spec) when
25417330f729Sjoerg /// the declspec has no type specifier. In this case, the declspec is either
25427330f729Sjoerg /// malformed or is "implicit int" (in K&R and C89).
25437330f729Sjoerg ///
25447330f729Sjoerg /// This method handles diagnosing this prettily and returns false if the
25457330f729Sjoerg /// declspec is done being processed. If it recovers and thinks there may be
25467330f729Sjoerg /// other pieces of declspec after it, it returns true.
25477330f729Sjoerg ///
ParseImplicitInt(DeclSpec & DS,CXXScopeSpec * SS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSC,ParsedAttributesWithRange & Attrs)25487330f729Sjoerg bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
25497330f729Sjoerg const ParsedTemplateInfo &TemplateInfo,
25507330f729Sjoerg AccessSpecifier AS, DeclSpecContext DSC,
25517330f729Sjoerg ParsedAttributesWithRange &Attrs) {
25527330f729Sjoerg assert(Tok.is(tok::identifier) && "should have identifier");
25537330f729Sjoerg
25547330f729Sjoerg SourceLocation Loc = Tok.getLocation();
25557330f729Sjoerg // If we see an identifier that is not a type name, we normally would
25567330f729Sjoerg // parse it as the identifier being declared. However, when a typename
25577330f729Sjoerg // is typo'd or the definition is not included, this will incorrectly
25587330f729Sjoerg // parse the typename as the identifier name and fall over misparsing
25597330f729Sjoerg // later parts of the diagnostic.
25607330f729Sjoerg //
25617330f729Sjoerg // As such, we try to do some look-ahead in cases where this would
25627330f729Sjoerg // otherwise be an "implicit-int" case to see if this is invalid. For
25637330f729Sjoerg // example: "static foo_t x = 4;" In this case, if we parsed foo_t as
25647330f729Sjoerg // an identifier with implicit int, we'd get a parse error because the
25657330f729Sjoerg // next token is obviously invalid for a type. Parse these as a case
25667330f729Sjoerg // with an invalid type specifier.
25677330f729Sjoerg assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
25687330f729Sjoerg
25697330f729Sjoerg // Since we know that this either implicit int (which is rare) or an
25707330f729Sjoerg // error, do lookahead to try to do better recovery. This never applies
25717330f729Sjoerg // within a type specifier. Outside of C++, we allow this even if the
25727330f729Sjoerg // language doesn't "officially" support implicit int -- we support
25737330f729Sjoerg // implicit int as an extension in C99 and C11.
25747330f729Sjoerg if (!isTypeSpecifier(DSC) && !getLangOpts().CPlusPlus &&
25757330f729Sjoerg isValidAfterIdentifierInDeclarator(NextToken())) {
25767330f729Sjoerg // If this token is valid for implicit int, e.g. "static x = 4", then
25777330f729Sjoerg // we just avoid eating the identifier, so it will be parsed as the
25787330f729Sjoerg // identifier in the declarator.
25797330f729Sjoerg return false;
25807330f729Sjoerg }
25817330f729Sjoerg
25827330f729Sjoerg // Early exit as Sema has a dedicated missing_actual_pipe_type diagnostic
25837330f729Sjoerg // for incomplete declarations such as `pipe p`.
25847330f729Sjoerg if (getLangOpts().OpenCLCPlusPlus && DS.isTypeSpecPipe())
25857330f729Sjoerg return false;
25867330f729Sjoerg
25877330f729Sjoerg if (getLangOpts().CPlusPlus &&
25887330f729Sjoerg DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
25897330f729Sjoerg // Don't require a type specifier if we have the 'auto' storage class
25907330f729Sjoerg // specifier in C++98 -- we'll promote it to a type specifier.
25917330f729Sjoerg if (SS)
25927330f729Sjoerg AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
25937330f729Sjoerg return false;
25947330f729Sjoerg }
25957330f729Sjoerg
25967330f729Sjoerg if (getLangOpts().CPlusPlus && (!SS || SS->isEmpty()) &&
25977330f729Sjoerg getLangOpts().MSVCCompat) {
25987330f729Sjoerg // Lookup of an unqualified type name has failed in MSVC compatibility mode.
25997330f729Sjoerg // Give Sema a chance to recover if we are in a template with dependent base
26007330f729Sjoerg // classes.
26017330f729Sjoerg if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(
26027330f729Sjoerg *Tok.getIdentifierInfo(), Tok.getLocation(),
26037330f729Sjoerg DSC == DeclSpecContext::DSC_template_type_arg)) {
26047330f729Sjoerg const char *PrevSpec;
26057330f729Sjoerg unsigned DiagID;
26067330f729Sjoerg DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
26077330f729Sjoerg Actions.getASTContext().getPrintingPolicy());
26087330f729Sjoerg DS.SetRangeEnd(Tok.getLocation());
26097330f729Sjoerg ConsumeToken();
26107330f729Sjoerg return false;
26117330f729Sjoerg }
26127330f729Sjoerg }
26137330f729Sjoerg
26147330f729Sjoerg // Otherwise, if we don't consume this token, we are going to emit an
26157330f729Sjoerg // error anyway. Try to recover from various common problems. Check
26167330f729Sjoerg // to see if this was a reference to a tag name without a tag specified.
26177330f729Sjoerg // This is a common problem in C (saying 'foo' instead of 'struct foo').
26187330f729Sjoerg //
26197330f729Sjoerg // C++ doesn't need this, and isTagName doesn't take SS.
26207330f729Sjoerg if (SS == nullptr) {
26217330f729Sjoerg const char *TagName = nullptr, *FixitTagName = nullptr;
26227330f729Sjoerg tok::TokenKind TagKind = tok::unknown;
26237330f729Sjoerg
26247330f729Sjoerg switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {
26257330f729Sjoerg default: break;
26267330f729Sjoerg case DeclSpec::TST_enum:
26277330f729Sjoerg TagName="enum" ; FixitTagName = "enum " ; TagKind=tok::kw_enum ;break;
26287330f729Sjoerg case DeclSpec::TST_union:
26297330f729Sjoerg TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break;
26307330f729Sjoerg case DeclSpec::TST_struct:
26317330f729Sjoerg TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break;
26327330f729Sjoerg case DeclSpec::TST_interface:
26337330f729Sjoerg TagName="__interface"; FixitTagName = "__interface ";
26347330f729Sjoerg TagKind=tok::kw___interface;break;
26357330f729Sjoerg case DeclSpec::TST_class:
26367330f729Sjoerg TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break;
26377330f729Sjoerg }
26387330f729Sjoerg
26397330f729Sjoerg if (TagName) {
26407330f729Sjoerg IdentifierInfo *TokenName = Tok.getIdentifierInfo();
26417330f729Sjoerg LookupResult R(Actions, TokenName, SourceLocation(),
26427330f729Sjoerg Sema::LookupOrdinaryName);
26437330f729Sjoerg
26447330f729Sjoerg Diag(Loc, diag::err_use_of_tag_name_without_tag)
26457330f729Sjoerg << TokenName << TagName << getLangOpts().CPlusPlus
26467330f729Sjoerg << FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);
26477330f729Sjoerg
26487330f729Sjoerg if (Actions.LookupParsedName(R, getCurScope(), SS)) {
26497330f729Sjoerg for (LookupResult::iterator I = R.begin(), IEnd = R.end();
26507330f729Sjoerg I != IEnd; ++I)
26517330f729Sjoerg Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
26527330f729Sjoerg << TokenName << TagName;
26537330f729Sjoerg }
26547330f729Sjoerg
26557330f729Sjoerg // Parse this as a tag as if the missing tag were present.
26567330f729Sjoerg if (TagKind == tok::kw_enum)
26577330f729Sjoerg ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,
26587330f729Sjoerg DeclSpecContext::DSC_normal);
26597330f729Sjoerg else
26607330f729Sjoerg ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
26617330f729Sjoerg /*EnteringContext*/ false,
26627330f729Sjoerg DeclSpecContext::DSC_normal, Attrs);
26637330f729Sjoerg return true;
26647330f729Sjoerg }
26657330f729Sjoerg }
26667330f729Sjoerg
26677330f729Sjoerg // Determine whether this identifier could plausibly be the name of something
26687330f729Sjoerg // being declared (with a missing type).
26697330f729Sjoerg if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||
26707330f729Sjoerg DSC == DeclSpecContext::DSC_class)) {
26717330f729Sjoerg // Look ahead to the next token to try to figure out what this declaration
26727330f729Sjoerg // was supposed to be.
26737330f729Sjoerg switch (NextToken().getKind()) {
26747330f729Sjoerg case tok::l_paren: {
26757330f729Sjoerg // static x(4); // 'x' is not a type
26767330f729Sjoerg // x(int n); // 'x' is not a type
26777330f729Sjoerg // x (*p)[]; // 'x' is a type
26787330f729Sjoerg //
26797330f729Sjoerg // Since we're in an error case, we can afford to perform a tentative
26807330f729Sjoerg // parse to determine which case we're in.
26817330f729Sjoerg TentativeParsingAction PA(*this);
26827330f729Sjoerg ConsumeToken();
26837330f729Sjoerg TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
26847330f729Sjoerg PA.Revert();
26857330f729Sjoerg
26867330f729Sjoerg if (TPR != TPResult::False) {
26877330f729Sjoerg // The identifier is followed by a parenthesized declarator.
26887330f729Sjoerg // It's supposed to be a type.
26897330f729Sjoerg break;
26907330f729Sjoerg }
26917330f729Sjoerg
26927330f729Sjoerg // If we're in a context where we could be declaring a constructor,
26937330f729Sjoerg // check whether this is a constructor declaration with a bogus name.
26947330f729Sjoerg if (DSC == DeclSpecContext::DSC_class ||
26957330f729Sjoerg (DSC == DeclSpecContext::DSC_top_level && SS)) {
26967330f729Sjoerg IdentifierInfo *II = Tok.getIdentifierInfo();
26977330f729Sjoerg if (Actions.isCurrentClassNameTypo(II, SS)) {
26987330f729Sjoerg Diag(Loc, diag::err_constructor_bad_name)
26997330f729Sjoerg << Tok.getIdentifierInfo() << II
27007330f729Sjoerg << FixItHint::CreateReplacement(Tok.getLocation(), II->getName());
27017330f729Sjoerg Tok.setIdentifierInfo(II);
27027330f729Sjoerg }
27037330f729Sjoerg }
27047330f729Sjoerg // Fall through.
27057330f729Sjoerg LLVM_FALLTHROUGH;
27067330f729Sjoerg }
27077330f729Sjoerg case tok::comma:
27087330f729Sjoerg case tok::equal:
27097330f729Sjoerg case tok::kw_asm:
27107330f729Sjoerg case tok::l_brace:
27117330f729Sjoerg case tok::l_square:
27127330f729Sjoerg case tok::semi:
27137330f729Sjoerg // This looks like a variable or function declaration. The type is
27147330f729Sjoerg // probably missing. We're done parsing decl-specifiers.
27157330f729Sjoerg // But only if we are not in a function prototype scope.
27167330f729Sjoerg if (getCurScope()->isFunctionPrototypeScope())
27177330f729Sjoerg break;
27187330f729Sjoerg if (SS)
27197330f729Sjoerg AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);
27207330f729Sjoerg return false;
27217330f729Sjoerg
27227330f729Sjoerg default:
27237330f729Sjoerg // This is probably supposed to be a type. This includes cases like:
27247330f729Sjoerg // int f(itn);
2725*e038c9c4Sjoerg // struct S { unsigned : 4; };
27267330f729Sjoerg break;
27277330f729Sjoerg }
27287330f729Sjoerg }
27297330f729Sjoerg
27307330f729Sjoerg // This is almost certainly an invalid type name. Let Sema emit a diagnostic
27317330f729Sjoerg // and attempt to recover.
27327330f729Sjoerg ParsedType T;
27337330f729Sjoerg IdentifierInfo *II = Tok.getIdentifierInfo();
27347330f729Sjoerg bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less);
27357330f729Sjoerg Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,
27367330f729Sjoerg IsTemplateName);
27377330f729Sjoerg if (T) {
27387330f729Sjoerg // The action has suggested that the type T could be used. Set that as
27397330f729Sjoerg // the type in the declaration specifiers, consume the would-be type
27407330f729Sjoerg // name token, and we're done.
27417330f729Sjoerg const char *PrevSpec;
27427330f729Sjoerg unsigned DiagID;
27437330f729Sjoerg DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
27447330f729Sjoerg Actions.getASTContext().getPrintingPolicy());
27457330f729Sjoerg DS.SetRangeEnd(Tok.getLocation());
27467330f729Sjoerg ConsumeToken();
27477330f729Sjoerg // There may be other declaration specifiers after this.
27487330f729Sjoerg return true;
27497330f729Sjoerg } else if (II != Tok.getIdentifierInfo()) {
27507330f729Sjoerg // If no type was suggested, the correction is to a keyword
27517330f729Sjoerg Tok.setKind(II->getTokenID());
27527330f729Sjoerg // There may be other declaration specifiers after this.
27537330f729Sjoerg return true;
27547330f729Sjoerg }
27557330f729Sjoerg
27567330f729Sjoerg // Otherwise, the action had no suggestion for us. Mark this as an error.
27577330f729Sjoerg DS.SetTypeSpecError();
27587330f729Sjoerg DS.SetRangeEnd(Tok.getLocation());
27597330f729Sjoerg ConsumeToken();
27607330f729Sjoerg
27617330f729Sjoerg // Eat any following template arguments.
27627330f729Sjoerg if (IsTemplateName) {
27637330f729Sjoerg SourceLocation LAngle, RAngle;
27647330f729Sjoerg TemplateArgList Args;
27657330f729Sjoerg ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle);
27667330f729Sjoerg }
27677330f729Sjoerg
27687330f729Sjoerg // TODO: Could inject an invalid typedef decl in an enclosing scope to
27697330f729Sjoerg // avoid rippling error messages on subsequent uses of the same type,
27707330f729Sjoerg // could be useful if #include was forgotten.
27717330f729Sjoerg return true;
27727330f729Sjoerg }
27737330f729Sjoerg
27747330f729Sjoerg /// Determine the declaration specifier context from the declarator
27757330f729Sjoerg /// context.
27767330f729Sjoerg ///
27777330f729Sjoerg /// \param Context the declarator context, which is one of the
27787330f729Sjoerg /// DeclaratorContext enumerator values.
27797330f729Sjoerg Parser::DeclSpecContext
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context)27807330f729Sjoerg Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
2781*e038c9c4Sjoerg if (Context == DeclaratorContext::Member)
27827330f729Sjoerg return DeclSpecContext::DSC_class;
2783*e038c9c4Sjoerg if (Context == DeclaratorContext::File)
27847330f729Sjoerg return DeclSpecContext::DSC_top_level;
2785*e038c9c4Sjoerg if (Context == DeclaratorContext::TemplateParam)
27867330f729Sjoerg return DeclSpecContext::DSC_template_param;
2787*e038c9c4Sjoerg if (Context == DeclaratorContext::TemplateArg ||
2788*e038c9c4Sjoerg Context == DeclaratorContext::TemplateTypeArg)
27897330f729Sjoerg return DeclSpecContext::DSC_template_type_arg;
2790*e038c9c4Sjoerg if (Context == DeclaratorContext::TrailingReturn ||
2791*e038c9c4Sjoerg Context == DeclaratorContext::TrailingReturnVar)
27927330f729Sjoerg return DeclSpecContext::DSC_trailing;
2793*e038c9c4Sjoerg if (Context == DeclaratorContext::AliasDecl ||
2794*e038c9c4Sjoerg Context == DeclaratorContext::AliasTemplate)
27957330f729Sjoerg return DeclSpecContext::DSC_alias_declaration;
27967330f729Sjoerg return DeclSpecContext::DSC_normal;
27977330f729Sjoerg }
27987330f729Sjoerg
27997330f729Sjoerg /// ParseAlignArgument - Parse the argument to an alignment-specifier.
28007330f729Sjoerg ///
28017330f729Sjoerg /// FIXME: Simply returns an alignof() expression if the argument is a
28027330f729Sjoerg /// type. Ideally, the type should be propagated directly into Sema.
28037330f729Sjoerg ///
28047330f729Sjoerg /// [C11] type-id
28057330f729Sjoerg /// [C11] constant-expression
28067330f729Sjoerg /// [C++0x] type-id ...[opt]
28077330f729Sjoerg /// [C++0x] assignment-expression ...[opt]
ParseAlignArgument(SourceLocation Start,SourceLocation & EllipsisLoc)28087330f729Sjoerg ExprResult Parser::ParseAlignArgument(SourceLocation Start,
28097330f729Sjoerg SourceLocation &EllipsisLoc) {
28107330f729Sjoerg ExprResult ER;
28117330f729Sjoerg if (isTypeIdInParens()) {
28127330f729Sjoerg SourceLocation TypeLoc = Tok.getLocation();
28137330f729Sjoerg ParsedType Ty = ParseTypeName().get();
28147330f729Sjoerg SourceRange TypeRange(Start, Tok.getLocation());
28157330f729Sjoerg ER = Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true,
28167330f729Sjoerg Ty.getAsOpaquePtr(), TypeRange);
28177330f729Sjoerg } else
28187330f729Sjoerg ER = ParseConstantExpression();
28197330f729Sjoerg
28207330f729Sjoerg if (getLangOpts().CPlusPlus11)
28217330f729Sjoerg TryConsumeToken(tok::ellipsis, EllipsisLoc);
28227330f729Sjoerg
28237330f729Sjoerg return ER;
28247330f729Sjoerg }
28257330f729Sjoerg
28267330f729Sjoerg /// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the
28277330f729Sjoerg /// attribute to Attrs.
28287330f729Sjoerg ///
28297330f729Sjoerg /// alignment-specifier:
28307330f729Sjoerg /// [C11] '_Alignas' '(' type-id ')'
28317330f729Sjoerg /// [C11] '_Alignas' '(' constant-expression ')'
28327330f729Sjoerg /// [C++11] 'alignas' '(' type-id ...[opt] ')'
28337330f729Sjoerg /// [C++11] 'alignas' '(' assignment-expression ...[opt] ')'
ParseAlignmentSpecifier(ParsedAttributes & Attrs,SourceLocation * EndLoc)28347330f729Sjoerg void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
28357330f729Sjoerg SourceLocation *EndLoc) {
28367330f729Sjoerg assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) &&
28377330f729Sjoerg "Not an alignment-specifier!");
28387330f729Sjoerg
28397330f729Sjoerg IdentifierInfo *KWName = Tok.getIdentifierInfo();
28407330f729Sjoerg SourceLocation KWLoc = ConsumeToken();
28417330f729Sjoerg
28427330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
28437330f729Sjoerg if (T.expectAndConsume())
28447330f729Sjoerg return;
28457330f729Sjoerg
28467330f729Sjoerg SourceLocation EllipsisLoc;
28477330f729Sjoerg ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation(), EllipsisLoc);
28487330f729Sjoerg if (ArgExpr.isInvalid()) {
28497330f729Sjoerg T.skipToEnd();
28507330f729Sjoerg return;
28517330f729Sjoerg }
28527330f729Sjoerg
28537330f729Sjoerg T.consumeClose();
28547330f729Sjoerg if (EndLoc)
28557330f729Sjoerg *EndLoc = T.getCloseLocation();
28567330f729Sjoerg
28577330f729Sjoerg ArgsVector ArgExprs;
28587330f729Sjoerg ArgExprs.push_back(ArgExpr.get());
28597330f729Sjoerg Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1,
28607330f729Sjoerg ParsedAttr::AS_Keyword, EllipsisLoc);
28617330f729Sjoerg }
28627330f729Sjoerg
ParseExtIntegerArgument()2863*e038c9c4Sjoerg ExprResult Parser::ParseExtIntegerArgument() {
2864*e038c9c4Sjoerg assert(Tok.is(tok::kw__ExtInt) && "Not an extended int type");
2865*e038c9c4Sjoerg ConsumeToken();
2866*e038c9c4Sjoerg
2867*e038c9c4Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
2868*e038c9c4Sjoerg if (T.expectAndConsume())
2869*e038c9c4Sjoerg return ExprError();
2870*e038c9c4Sjoerg
2871*e038c9c4Sjoerg ExprResult ER = ParseConstantExpression();
2872*e038c9c4Sjoerg if (ER.isInvalid()) {
2873*e038c9c4Sjoerg T.skipToEnd();
2874*e038c9c4Sjoerg return ExprError();
2875*e038c9c4Sjoerg }
2876*e038c9c4Sjoerg
2877*e038c9c4Sjoerg if(T.consumeClose())
2878*e038c9c4Sjoerg return ExprError();
2879*e038c9c4Sjoerg return ER;
2880*e038c9c4Sjoerg }
2881*e038c9c4Sjoerg
28827330f729Sjoerg /// Determine whether we're looking at something that might be a declarator
28837330f729Sjoerg /// in a simple-declaration. If it can't possibly be a declarator, maybe
28847330f729Sjoerg /// diagnose a missing semicolon after a prior tag definition in the decl
28857330f729Sjoerg /// specifier.
28867330f729Sjoerg ///
28877330f729Sjoerg /// \return \c true if an error occurred and this can't be any kind of
28887330f729Sjoerg /// declaration.
28897330f729Sjoerg bool
DiagnoseMissingSemiAfterTagDefinition(DeclSpec & DS,AccessSpecifier AS,DeclSpecContext DSContext,LateParsedAttrList * LateAttrs)28907330f729Sjoerg Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
28917330f729Sjoerg DeclSpecContext DSContext,
28927330f729Sjoerg LateParsedAttrList *LateAttrs) {
28937330f729Sjoerg assert(DS.hasTagDefinition() && "shouldn't call this");
28947330f729Sjoerg
28957330f729Sjoerg bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
28967330f729Sjoerg DSContext == DeclSpecContext::DSC_top_level);
28977330f729Sjoerg
28987330f729Sjoerg if (getLangOpts().CPlusPlus &&
28997330f729Sjoerg Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,
29007330f729Sjoerg tok::annot_template_id) &&
29017330f729Sjoerg TryAnnotateCXXScopeToken(EnteringContext)) {
29027330f729Sjoerg SkipMalformedDecl();
29037330f729Sjoerg return true;
29047330f729Sjoerg }
29057330f729Sjoerg
29067330f729Sjoerg bool HasScope = Tok.is(tok::annot_cxxscope);
29077330f729Sjoerg // Make a copy in case GetLookAheadToken invalidates the result of NextToken.
29087330f729Sjoerg Token AfterScope = HasScope ? NextToken() : Tok;
29097330f729Sjoerg
29107330f729Sjoerg // Determine whether the following tokens could possibly be a
29117330f729Sjoerg // declarator.
29127330f729Sjoerg bool MightBeDeclarator = true;
29137330f729Sjoerg if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) {
29147330f729Sjoerg // A declarator-id can't start with 'typename'.
29157330f729Sjoerg MightBeDeclarator = false;
29167330f729Sjoerg } else if (AfterScope.is(tok::annot_template_id)) {
29177330f729Sjoerg // If we have a type expressed as a template-id, this cannot be a
29187330f729Sjoerg // declarator-id (such a type cannot be redeclared in a simple-declaration).
29197330f729Sjoerg TemplateIdAnnotation *Annot =
29207330f729Sjoerg static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());
29217330f729Sjoerg if (Annot->Kind == TNK_Type_template)
29227330f729Sjoerg MightBeDeclarator = false;
29237330f729Sjoerg } else if (AfterScope.is(tok::identifier)) {
29247330f729Sjoerg const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken();
29257330f729Sjoerg
29267330f729Sjoerg // These tokens cannot come after the declarator-id in a
29277330f729Sjoerg // simple-declaration, and are likely to come after a type-specifier.
29287330f729Sjoerg if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier,
29297330f729Sjoerg tok::annot_cxxscope, tok::coloncolon)) {
29307330f729Sjoerg // Missing a semicolon.
29317330f729Sjoerg MightBeDeclarator = false;
29327330f729Sjoerg } else if (HasScope) {
29337330f729Sjoerg // If the declarator-id has a scope specifier, it must redeclare a
29347330f729Sjoerg // previously-declared entity. If that's a type (and this is not a
29357330f729Sjoerg // typedef), that's an error.
29367330f729Sjoerg CXXScopeSpec SS;
29377330f729Sjoerg Actions.RestoreNestedNameSpecifierAnnotation(
29387330f729Sjoerg Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
29397330f729Sjoerg IdentifierInfo *Name = AfterScope.getIdentifierInfo();
29407330f729Sjoerg Sema::NameClassification Classification = Actions.ClassifyName(
29417330f729Sjoerg getCurScope(), SS, Name, AfterScope.getLocation(), Next,
29427330f729Sjoerg /*CCC=*/nullptr);
29437330f729Sjoerg switch (Classification.getKind()) {
29447330f729Sjoerg case Sema::NC_Error:
29457330f729Sjoerg SkipMalformedDecl();
29467330f729Sjoerg return true;
29477330f729Sjoerg
29487330f729Sjoerg case Sema::NC_Keyword:
29497330f729Sjoerg llvm_unreachable("typo correction is not possible here");
29507330f729Sjoerg
29517330f729Sjoerg case Sema::NC_Type:
29527330f729Sjoerg case Sema::NC_TypeTemplate:
29537330f729Sjoerg case Sema::NC_UndeclaredNonType:
29547330f729Sjoerg case Sema::NC_UndeclaredTemplate:
29557330f729Sjoerg // Not a previously-declared non-type entity.
29567330f729Sjoerg MightBeDeclarator = false;
29577330f729Sjoerg break;
29587330f729Sjoerg
29597330f729Sjoerg case Sema::NC_Unknown:
29607330f729Sjoerg case Sema::NC_NonType:
29617330f729Sjoerg case Sema::NC_DependentNonType:
2962*e038c9c4Sjoerg case Sema::NC_OverloadSet:
29637330f729Sjoerg case Sema::NC_VarTemplate:
29647330f729Sjoerg case Sema::NC_FunctionTemplate:
2965*e038c9c4Sjoerg case Sema::NC_Concept:
29667330f729Sjoerg // Might be a redeclaration of a prior entity.
29677330f729Sjoerg break;
29687330f729Sjoerg }
29697330f729Sjoerg }
29707330f729Sjoerg }
29717330f729Sjoerg
29727330f729Sjoerg if (MightBeDeclarator)
29737330f729Sjoerg return false;
29747330f729Sjoerg
29757330f729Sjoerg const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
29767330f729Sjoerg Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()),
29777330f729Sjoerg diag::err_expected_after)
29787330f729Sjoerg << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;
29797330f729Sjoerg
29807330f729Sjoerg // Try to recover from the typo, by dropping the tag definition and parsing
29817330f729Sjoerg // the problematic tokens as a type.
29827330f729Sjoerg //
29837330f729Sjoerg // FIXME: Split the DeclSpec into pieces for the standalone
29847330f729Sjoerg // declaration and pieces for the following declaration, instead
29857330f729Sjoerg // of assuming that all the other pieces attach to new declaration,
29867330f729Sjoerg // and call ParsedFreeStandingDeclSpec as appropriate.
29877330f729Sjoerg DS.ClearTypeSpecType();
29887330f729Sjoerg ParsedTemplateInfo NotATemplate;
29897330f729Sjoerg ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);
29907330f729Sjoerg return false;
29917330f729Sjoerg }
29927330f729Sjoerg
29937330f729Sjoerg // Choose the apprpriate diagnostic error for why fixed point types are
29947330f729Sjoerg // disabled, set the previous specifier, and mark as invalid.
SetupFixedPointError(const LangOptions & LangOpts,const char * & PrevSpec,unsigned & DiagID,bool & isInvalid)29957330f729Sjoerg static void SetupFixedPointError(const LangOptions &LangOpts,
29967330f729Sjoerg const char *&PrevSpec, unsigned &DiagID,
29977330f729Sjoerg bool &isInvalid) {
29987330f729Sjoerg assert(!LangOpts.FixedPoint);
29997330f729Sjoerg DiagID = diag::err_fixed_point_not_enabled;
30007330f729Sjoerg PrevSpec = ""; // Not used by diagnostic
30017330f729Sjoerg isInvalid = true;
30027330f729Sjoerg }
30037330f729Sjoerg
30047330f729Sjoerg /// ParseDeclarationSpecifiers
30057330f729Sjoerg /// declaration-specifiers: [C99 6.7]
30067330f729Sjoerg /// storage-class-specifier declaration-specifiers[opt]
30077330f729Sjoerg /// type-specifier declaration-specifiers[opt]
30087330f729Sjoerg /// [C99] function-specifier declaration-specifiers[opt]
30097330f729Sjoerg /// [C11] alignment-specifier declaration-specifiers[opt]
30107330f729Sjoerg /// [GNU] attributes declaration-specifiers[opt]
30117330f729Sjoerg /// [Clang] '__module_private__' declaration-specifiers[opt]
30127330f729Sjoerg /// [ObjC1] '__kindof' declaration-specifiers[opt]
30137330f729Sjoerg ///
30147330f729Sjoerg /// storage-class-specifier: [C99 6.7.1]
30157330f729Sjoerg /// 'typedef'
30167330f729Sjoerg /// 'extern'
30177330f729Sjoerg /// 'static'
30187330f729Sjoerg /// 'auto'
30197330f729Sjoerg /// 'register'
30207330f729Sjoerg /// [C++] 'mutable'
30217330f729Sjoerg /// [C++11] 'thread_local'
30227330f729Sjoerg /// [C11] '_Thread_local'
30237330f729Sjoerg /// [GNU] '__thread'
30247330f729Sjoerg /// function-specifier: [C99 6.7.4]
30257330f729Sjoerg /// [C99] 'inline'
30267330f729Sjoerg /// [C++] 'virtual'
30277330f729Sjoerg /// [C++] 'explicit'
30287330f729Sjoerg /// [OpenCL] '__kernel'
30297330f729Sjoerg /// 'friend': [C++ dcl.friend]
30307330f729Sjoerg /// 'constexpr': [C++0x dcl.constexpr]
ParseDeclarationSpecifiers(DeclSpec & DS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSContext,LateParsedAttrList * LateAttrs)30317330f729Sjoerg void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
30327330f729Sjoerg const ParsedTemplateInfo &TemplateInfo,
30337330f729Sjoerg AccessSpecifier AS,
30347330f729Sjoerg DeclSpecContext DSContext,
30357330f729Sjoerg LateParsedAttrList *LateAttrs) {
30367330f729Sjoerg if (DS.getSourceRange().isInvalid()) {
30377330f729Sjoerg // Start the range at the current token but make the end of the range
30387330f729Sjoerg // invalid. This will make the entire range invalid unless we successfully
30397330f729Sjoerg // consume a token.
30407330f729Sjoerg DS.SetRangeStart(Tok.getLocation());
30417330f729Sjoerg DS.SetRangeEnd(SourceLocation());
30427330f729Sjoerg }
30437330f729Sjoerg
30447330f729Sjoerg bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||
30457330f729Sjoerg DSContext == DeclSpecContext::DSC_top_level);
30467330f729Sjoerg bool AttrsLastTime = false;
30477330f729Sjoerg ParsedAttributesWithRange attrs(AttrFactory);
30487330f729Sjoerg // We use Sema's policy to get bool macros right.
30497330f729Sjoerg PrintingPolicy Policy = Actions.getPrintingPolicy();
30507330f729Sjoerg while (1) {
30517330f729Sjoerg bool isInvalid = false;
30527330f729Sjoerg bool isStorageClass = false;
30537330f729Sjoerg const char *PrevSpec = nullptr;
30547330f729Sjoerg unsigned DiagID = 0;
30557330f729Sjoerg
30567330f729Sjoerg // This value needs to be set to the location of the last token if the last
30577330f729Sjoerg // token of the specifier is already consumed.
30587330f729Sjoerg SourceLocation ConsumedEnd;
30597330f729Sjoerg
30607330f729Sjoerg // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
30617330f729Sjoerg // implementation for VS2013 uses _Atomic as an identifier for one of the
30627330f729Sjoerg // classes in <atomic>.
30637330f729Sjoerg //
30647330f729Sjoerg // A typedef declaration containing _Atomic<...> is among the places where
30657330f729Sjoerg // the class is used. If we are currently parsing such a declaration, treat
30667330f729Sjoerg // the token as an identifier.
30677330f729Sjoerg if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
30687330f729Sjoerg DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef &&
30697330f729Sjoerg !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less))
30707330f729Sjoerg Tok.setKind(tok::identifier);
30717330f729Sjoerg
30727330f729Sjoerg SourceLocation Loc = Tok.getLocation();
30737330f729Sjoerg
3074*e038c9c4Sjoerg // Helper for image types in OpenCL.
3075*e038c9c4Sjoerg auto handleOpenCLImageKW = [&] (StringRef Ext, TypeSpecifierType ImageTypeSpec) {
3076*e038c9c4Sjoerg // Check if the image type is supported and otherwise turn the keyword into an identifier
3077*e038c9c4Sjoerg // because image types from extensions are not reserved identifiers.
3078*e038c9c4Sjoerg if (!StringRef(Ext).empty() && !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) {
3079*e038c9c4Sjoerg Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
3080*e038c9c4Sjoerg Tok.setKind(tok::identifier);
3081*e038c9c4Sjoerg return false;
3082*e038c9c4Sjoerg }
3083*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy);
3084*e038c9c4Sjoerg return true;
3085*e038c9c4Sjoerg };
3086*e038c9c4Sjoerg
30877330f729Sjoerg switch (Tok.getKind()) {
30887330f729Sjoerg default:
30897330f729Sjoerg DoneWithDeclSpec:
30907330f729Sjoerg if (!AttrsLastTime)
30917330f729Sjoerg ProhibitAttributes(attrs);
30927330f729Sjoerg else {
30937330f729Sjoerg // Reject C++11 attributes that appertain to decl specifiers as
30947330f729Sjoerg // we don't support any C++11 attributes that appertain to decl
30957330f729Sjoerg // specifiers. This also conforms to what g++ 4.8 is doing.
30967330f729Sjoerg ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr);
30977330f729Sjoerg
30987330f729Sjoerg DS.takeAttributesFrom(attrs);
30997330f729Sjoerg }
31007330f729Sjoerg
31017330f729Sjoerg // If this is not a declaration specifier token, we're done reading decl
31027330f729Sjoerg // specifiers. First verify that DeclSpec's are consistent.
31037330f729Sjoerg DS.Finish(Actions, Policy);
31047330f729Sjoerg return;
31057330f729Sjoerg
31067330f729Sjoerg case tok::l_square:
31077330f729Sjoerg case tok::kw_alignas:
31087330f729Sjoerg if (!standardAttributesAllowed() || !isCXX11AttributeSpecifier())
31097330f729Sjoerg goto DoneWithDeclSpec;
31107330f729Sjoerg
31117330f729Sjoerg ProhibitAttributes(attrs);
31127330f729Sjoerg // FIXME: It would be good to recover by accepting the attributes,
31137330f729Sjoerg // but attempting to do that now would cause serious
31147330f729Sjoerg // madness in terms of diagnostics.
31157330f729Sjoerg attrs.clear();
31167330f729Sjoerg attrs.Range = SourceRange();
31177330f729Sjoerg
31187330f729Sjoerg ParseCXX11Attributes(attrs);
31197330f729Sjoerg AttrsLastTime = true;
31207330f729Sjoerg continue;
31217330f729Sjoerg
31227330f729Sjoerg case tok::code_completion: {
31237330f729Sjoerg Sema::ParserCompletionContext CCC = Sema::PCC_Namespace;
31247330f729Sjoerg if (DS.hasTypeSpecifier()) {
31257330f729Sjoerg bool AllowNonIdentifiers
31267330f729Sjoerg = (getCurScope()->getFlags() & (Scope::ControlScope |
31277330f729Sjoerg Scope::BlockScope |
31287330f729Sjoerg Scope::TemplateParamScope |
31297330f729Sjoerg Scope::FunctionPrototypeScope |
31307330f729Sjoerg Scope::AtCatchScope)) == 0;
31317330f729Sjoerg bool AllowNestedNameSpecifiers
31327330f729Sjoerg = DSContext == DeclSpecContext::DSC_top_level ||
31337330f729Sjoerg (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
31347330f729Sjoerg
3135*e038c9c4Sjoerg cutOffParsing();
31367330f729Sjoerg Actions.CodeCompleteDeclSpec(getCurScope(), DS,
31377330f729Sjoerg AllowNonIdentifiers,
31387330f729Sjoerg AllowNestedNameSpecifiers);
3139*e038c9c4Sjoerg return;
31407330f729Sjoerg }
31417330f729Sjoerg
31427330f729Sjoerg if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
31437330f729Sjoerg CCC = Sema::PCC_LocalDeclarationSpecifiers;
31447330f729Sjoerg else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
31457330f729Sjoerg CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate
31467330f729Sjoerg : Sema::PCC_Template;
31477330f729Sjoerg else if (DSContext == DeclSpecContext::DSC_class)
31487330f729Sjoerg CCC = Sema::PCC_Class;
31497330f729Sjoerg else if (CurParsedObjCImpl)
31507330f729Sjoerg CCC = Sema::PCC_ObjCImplementation;
31517330f729Sjoerg
3152*e038c9c4Sjoerg cutOffParsing();
31537330f729Sjoerg Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
3154*e038c9c4Sjoerg return;
31557330f729Sjoerg }
31567330f729Sjoerg
31577330f729Sjoerg case tok::coloncolon: // ::foo::bar
31587330f729Sjoerg // C++ scope specifier. Annotate and loop, or bail out on error.
31597330f729Sjoerg if (TryAnnotateCXXScopeToken(EnteringContext)) {
31607330f729Sjoerg if (!DS.hasTypeSpecifier())
31617330f729Sjoerg DS.SetTypeSpecError();
31627330f729Sjoerg goto DoneWithDeclSpec;
31637330f729Sjoerg }
31647330f729Sjoerg if (Tok.is(tok::coloncolon)) // ::new or ::delete
31657330f729Sjoerg goto DoneWithDeclSpec;
31667330f729Sjoerg continue;
31677330f729Sjoerg
31687330f729Sjoerg case tok::annot_cxxscope: {
31697330f729Sjoerg if (DS.hasTypeSpecifier() || DS.isTypeAltiVecVector())
31707330f729Sjoerg goto DoneWithDeclSpec;
31717330f729Sjoerg
31727330f729Sjoerg CXXScopeSpec SS;
31737330f729Sjoerg Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
31747330f729Sjoerg Tok.getAnnotationRange(),
31757330f729Sjoerg SS);
31767330f729Sjoerg
31777330f729Sjoerg // We are looking for a qualified typename.
31787330f729Sjoerg Token Next = NextToken();
3179*e038c9c4Sjoerg
3180*e038c9c4Sjoerg TemplateIdAnnotation *TemplateId = Next.is(tok::annot_template_id)
3181*e038c9c4Sjoerg ? takeTemplateIdAnnotation(Next)
3182*e038c9c4Sjoerg : nullptr;
3183*e038c9c4Sjoerg if (TemplateId && TemplateId->hasInvalidName()) {
3184*e038c9c4Sjoerg // We found something like 'T::U<Args> x', but U is not a template.
3185*e038c9c4Sjoerg // Assume it was supposed to be a type.
3186*e038c9c4Sjoerg DS.SetTypeSpecError();
3187*e038c9c4Sjoerg ConsumeAnnotationToken();
3188*e038c9c4Sjoerg break;
3189*e038c9c4Sjoerg }
3190*e038c9c4Sjoerg
3191*e038c9c4Sjoerg if (TemplateId && TemplateId->Kind == TNK_Type_template) {
31927330f729Sjoerg // We have a qualified template-id, e.g., N::A<int>
31937330f729Sjoerg
31947330f729Sjoerg // If this would be a valid constructor declaration with template
31957330f729Sjoerg // arguments, we will reject the attempt to form an invalid type-id
31967330f729Sjoerg // referring to the injected-class-name when we annotate the token,
31977330f729Sjoerg // per C++ [class.qual]p2.
31987330f729Sjoerg //
31997330f729Sjoerg // To improve diagnostics for this case, parse the declaration as a
32007330f729Sjoerg // constructor (and reject the extra template arguments later).
32017330f729Sjoerg if ((DSContext == DeclSpecContext::DSC_top_level ||
32027330f729Sjoerg DSContext == DeclSpecContext::DSC_class) &&
32037330f729Sjoerg TemplateId->Name &&
32047330f729Sjoerg Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&
3205*e038c9c4Sjoerg isConstructorDeclarator(/*Unqualified=*/false)) {
32067330f729Sjoerg // The user meant this to be an out-of-line constructor
32077330f729Sjoerg // definition, but template arguments are not allowed
32087330f729Sjoerg // there. Just allow this as a constructor; we'll
32097330f729Sjoerg // complain about it later.
32107330f729Sjoerg goto DoneWithDeclSpec;
32117330f729Sjoerg }
32127330f729Sjoerg
32137330f729Sjoerg DS.getTypeSpecScope() = SS;
32147330f729Sjoerg ConsumeAnnotationToken(); // The C++ scope.
32157330f729Sjoerg assert(Tok.is(tok::annot_template_id) &&
32167330f729Sjoerg "ParseOptionalCXXScopeSpecifier not working");
3217*e038c9c4Sjoerg AnnotateTemplateIdTokenAsType(SS);
3218*e038c9c4Sjoerg continue;
3219*e038c9c4Sjoerg }
3220*e038c9c4Sjoerg
3221*e038c9c4Sjoerg if (TemplateId && TemplateId->Kind == TNK_Concept_template &&
3222*e038c9c4Sjoerg GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype)) {
3223*e038c9c4Sjoerg DS.getTypeSpecScope() = SS;
3224*e038c9c4Sjoerg // This is a qualified placeholder-specifier, e.g., ::C<int> auto ...
3225*e038c9c4Sjoerg // Consume the scope annotation and continue to consume the template-id
3226*e038c9c4Sjoerg // as a placeholder-specifier.
3227*e038c9c4Sjoerg ConsumeAnnotationToken();
32287330f729Sjoerg continue;
32297330f729Sjoerg }
32307330f729Sjoerg
32317330f729Sjoerg if (Next.is(tok::annot_typename)) {
32327330f729Sjoerg DS.getTypeSpecScope() = SS;
32337330f729Sjoerg ConsumeAnnotationToken(); // The C++ scope.
3234*e038c9c4Sjoerg TypeResult T = getTypeAnnotation(Tok);
32357330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,
32367330f729Sjoerg Tok.getAnnotationEndLoc(),
32377330f729Sjoerg PrevSpec, DiagID, T, Policy);
32387330f729Sjoerg if (isInvalid)
32397330f729Sjoerg break;
32407330f729Sjoerg DS.SetRangeEnd(Tok.getAnnotationEndLoc());
32417330f729Sjoerg ConsumeAnnotationToken(); // The typename
32427330f729Sjoerg }
32437330f729Sjoerg
32447330f729Sjoerg if (Next.isNot(tok::identifier))
32457330f729Sjoerg goto DoneWithDeclSpec;
32467330f729Sjoerg
32477330f729Sjoerg // Check whether this is a constructor declaration. If we're in a
32487330f729Sjoerg // context where the identifier could be a class name, and it has the
32497330f729Sjoerg // shape of a constructor declaration, process it as one.
32507330f729Sjoerg if ((DSContext == DeclSpecContext::DSC_top_level ||
32517330f729Sjoerg DSContext == DeclSpecContext::DSC_class) &&
32527330f729Sjoerg Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),
32537330f729Sjoerg &SS) &&
32547330f729Sjoerg isConstructorDeclarator(/*Unqualified*/ false))
32557330f729Sjoerg goto DoneWithDeclSpec;
32567330f729Sjoerg
32577330f729Sjoerg ParsedType TypeRep =
32587330f729Sjoerg Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(),
32597330f729Sjoerg getCurScope(), &SS, false, false, nullptr,
32607330f729Sjoerg /*IsCtorOrDtorName=*/false,
32617330f729Sjoerg /*WantNontrivialTypeSourceInfo=*/true,
32627330f729Sjoerg isClassTemplateDeductionContext(DSContext));
32637330f729Sjoerg
32647330f729Sjoerg // If the referenced identifier is not a type, then this declspec is
32657330f729Sjoerg // erroneous: We already checked about that it has no type specifier, and
32667330f729Sjoerg // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
32677330f729Sjoerg // typename.
32687330f729Sjoerg if (!TypeRep) {
3269*e038c9c4Sjoerg if (TryAnnotateTypeConstraint())
3270*e038c9c4Sjoerg goto DoneWithDeclSpec;
3271*e038c9c4Sjoerg if (Tok.isNot(tok::annot_cxxscope) ||
3272*e038c9c4Sjoerg NextToken().isNot(tok::identifier))
3273*e038c9c4Sjoerg continue;
32747330f729Sjoerg // Eat the scope spec so the identifier is current.
32757330f729Sjoerg ConsumeAnnotationToken();
32767330f729Sjoerg ParsedAttributesWithRange Attrs(AttrFactory);
32777330f729Sjoerg if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {
32787330f729Sjoerg if (!Attrs.empty()) {
32797330f729Sjoerg AttrsLastTime = true;
32807330f729Sjoerg attrs.takeAllFrom(Attrs);
32817330f729Sjoerg }
32827330f729Sjoerg continue;
32837330f729Sjoerg }
32847330f729Sjoerg goto DoneWithDeclSpec;
32857330f729Sjoerg }
32867330f729Sjoerg
32877330f729Sjoerg DS.getTypeSpecScope() = SS;
32887330f729Sjoerg ConsumeAnnotationToken(); // The C++ scope.
32897330f729Sjoerg
32907330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
32917330f729Sjoerg DiagID, TypeRep, Policy);
32927330f729Sjoerg if (isInvalid)
32937330f729Sjoerg break;
32947330f729Sjoerg
32957330f729Sjoerg DS.SetRangeEnd(Tok.getLocation());
32967330f729Sjoerg ConsumeToken(); // The typename.
32977330f729Sjoerg
32987330f729Sjoerg continue;
32997330f729Sjoerg }
33007330f729Sjoerg
33017330f729Sjoerg case tok::annot_typename: {
33027330f729Sjoerg // If we've previously seen a tag definition, we were almost surely
33037330f729Sjoerg // missing a semicolon after it.
33047330f729Sjoerg if (DS.hasTypeSpecifier() && DS.hasTagDefinition())
33057330f729Sjoerg goto DoneWithDeclSpec;
33067330f729Sjoerg
3307*e038c9c4Sjoerg TypeResult T = getTypeAnnotation(Tok);
33087330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
33097330f729Sjoerg DiagID, T, Policy);
33107330f729Sjoerg if (isInvalid)
33117330f729Sjoerg break;
33127330f729Sjoerg
33137330f729Sjoerg DS.SetRangeEnd(Tok.getAnnotationEndLoc());
33147330f729Sjoerg ConsumeAnnotationToken(); // The typename
33157330f729Sjoerg
33167330f729Sjoerg continue;
33177330f729Sjoerg }
33187330f729Sjoerg
33197330f729Sjoerg case tok::kw___is_signed:
33207330f729Sjoerg // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang
33217330f729Sjoerg // typically treats it as a trait. If we see __is_signed as it appears
33227330f729Sjoerg // in libstdc++, e.g.,
33237330f729Sjoerg //
33247330f729Sjoerg // static const bool __is_signed;
33257330f729Sjoerg //
33267330f729Sjoerg // then treat __is_signed as an identifier rather than as a keyword.
33277330f729Sjoerg if (DS.getTypeSpecType() == TST_bool &&
33287330f729Sjoerg DS.getTypeQualifiers() == DeclSpec::TQ_const &&
33297330f729Sjoerg DS.getStorageClassSpec() == DeclSpec::SCS_static)
33307330f729Sjoerg TryKeywordIdentFallback(true);
33317330f729Sjoerg
33327330f729Sjoerg // We're done with the declaration-specifiers.
33337330f729Sjoerg goto DoneWithDeclSpec;
33347330f729Sjoerg
33357330f729Sjoerg // typedef-name
33367330f729Sjoerg case tok::kw___super:
33377330f729Sjoerg case tok::kw_decltype:
33387330f729Sjoerg case tok::identifier: {
33397330f729Sjoerg // This identifier can only be a typedef name if we haven't already seen
33407330f729Sjoerg // a type-specifier. Without this check we misparse:
33417330f729Sjoerg // typedef int X; struct Y { short X; }; as 'short int'.
33427330f729Sjoerg if (DS.hasTypeSpecifier())
33437330f729Sjoerg goto DoneWithDeclSpec;
33447330f729Sjoerg
33457330f729Sjoerg // If the token is an identifier named "__declspec" and Microsoft
33467330f729Sjoerg // extensions are not enabled, it is likely that there will be cascading
33477330f729Sjoerg // parse errors if this really is a __declspec attribute. Attempt to
33487330f729Sjoerg // recognize that scenario and recover gracefully.
33497330f729Sjoerg if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) &&
33507330f729Sjoerg Tok.getIdentifierInfo()->getName().equals("__declspec")) {
33517330f729Sjoerg Diag(Loc, diag::err_ms_attributes_not_enabled);
33527330f729Sjoerg
33537330f729Sjoerg // The next token should be an open paren. If it is, eat the entire
33547330f729Sjoerg // attribute declaration and continue.
33557330f729Sjoerg if (NextToken().is(tok::l_paren)) {
33567330f729Sjoerg // Consume the __declspec identifier.
33577330f729Sjoerg ConsumeToken();
33587330f729Sjoerg
33597330f729Sjoerg // Eat the parens and everything between them.
33607330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
33617330f729Sjoerg if (T.consumeOpen()) {
33627330f729Sjoerg assert(false && "Not a left paren?");
33637330f729Sjoerg return;
33647330f729Sjoerg }
33657330f729Sjoerg T.skipToEnd();
33667330f729Sjoerg continue;
33677330f729Sjoerg }
33687330f729Sjoerg }
33697330f729Sjoerg
33707330f729Sjoerg // In C++, check to see if this is a scope specifier like foo::bar::, if
33717330f729Sjoerg // so handle it as such. This is important for ctor parsing.
33727330f729Sjoerg if (getLangOpts().CPlusPlus) {
33737330f729Sjoerg if (TryAnnotateCXXScopeToken(EnteringContext)) {
33747330f729Sjoerg DS.SetTypeSpecError();
33757330f729Sjoerg goto DoneWithDeclSpec;
33767330f729Sjoerg }
33777330f729Sjoerg if (!Tok.is(tok::identifier))
33787330f729Sjoerg continue;
33797330f729Sjoerg }
33807330f729Sjoerg
33817330f729Sjoerg // Check for need to substitute AltiVec keyword tokens.
33827330f729Sjoerg if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
33837330f729Sjoerg break;
33847330f729Sjoerg
33857330f729Sjoerg // [AltiVec] 2.2: [If the 'vector' specifier is used] The syntax does not
33867330f729Sjoerg // allow the use of a typedef name as a type specifier.
33877330f729Sjoerg if (DS.isTypeAltiVecVector())
33887330f729Sjoerg goto DoneWithDeclSpec;
33897330f729Sjoerg
33907330f729Sjoerg if (DSContext == DeclSpecContext::DSC_objc_method_result &&
33917330f729Sjoerg isObjCInstancetype()) {
33927330f729Sjoerg ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc);
33937330f729Sjoerg assert(TypeRep);
33947330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
33957330f729Sjoerg DiagID, TypeRep, Policy);
33967330f729Sjoerg if (isInvalid)
33977330f729Sjoerg break;
33987330f729Sjoerg
33997330f729Sjoerg DS.SetRangeEnd(Loc);
34007330f729Sjoerg ConsumeToken();
34017330f729Sjoerg continue;
34027330f729Sjoerg }
34037330f729Sjoerg
34047330f729Sjoerg // If we're in a context where the identifier could be a class name,
34057330f729Sjoerg // check whether this is a constructor declaration.
34067330f729Sjoerg if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
34077330f729Sjoerg Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&
34087330f729Sjoerg isConstructorDeclarator(/*Unqualified*/true))
34097330f729Sjoerg goto DoneWithDeclSpec;
34107330f729Sjoerg
34117330f729Sjoerg ParsedType TypeRep = Actions.getTypeName(
34127330f729Sjoerg *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,
34137330f729Sjoerg false, false, nullptr, false, false,
34147330f729Sjoerg isClassTemplateDeductionContext(DSContext));
34157330f729Sjoerg
34167330f729Sjoerg // If this is not a typedef name, don't parse it as part of the declspec,
34177330f729Sjoerg // it must be an implicit int or an error.
34187330f729Sjoerg if (!TypeRep) {
3419*e038c9c4Sjoerg if (TryAnnotateTypeConstraint())
3420*e038c9c4Sjoerg goto DoneWithDeclSpec;
3421*e038c9c4Sjoerg if (Tok.isNot(tok::identifier))
3422*e038c9c4Sjoerg continue;
34237330f729Sjoerg ParsedAttributesWithRange Attrs(AttrFactory);
34247330f729Sjoerg if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) {
34257330f729Sjoerg if (!Attrs.empty()) {
34267330f729Sjoerg AttrsLastTime = true;
34277330f729Sjoerg attrs.takeAllFrom(Attrs);
34287330f729Sjoerg }
34297330f729Sjoerg continue;
34307330f729Sjoerg }
34317330f729Sjoerg goto DoneWithDeclSpec;
34327330f729Sjoerg }
34337330f729Sjoerg
34347330f729Sjoerg // Likewise, if this is a context where the identifier could be a template
34357330f729Sjoerg // name, check whether this is a deduction guide declaration.
34367330f729Sjoerg if (getLangOpts().CPlusPlus17 &&
34377330f729Sjoerg (DSContext == DeclSpecContext::DSC_class ||
34387330f729Sjoerg DSContext == DeclSpecContext::DSC_top_level) &&
34397330f729Sjoerg Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),
34407330f729Sjoerg Tok.getLocation()) &&
34417330f729Sjoerg isConstructorDeclarator(/*Unqualified*/ true,
34427330f729Sjoerg /*DeductionGuide*/ true))
34437330f729Sjoerg goto DoneWithDeclSpec;
34447330f729Sjoerg
34457330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
34467330f729Sjoerg DiagID, TypeRep, Policy);
34477330f729Sjoerg if (isInvalid)
34487330f729Sjoerg break;
34497330f729Sjoerg
34507330f729Sjoerg DS.SetRangeEnd(Tok.getLocation());
34517330f729Sjoerg ConsumeToken(); // The identifier
34527330f729Sjoerg
34537330f729Sjoerg // Objective-C supports type arguments and protocol references
34547330f729Sjoerg // following an Objective-C object or object pointer
34557330f729Sjoerg // type. Handle either one of them.
34567330f729Sjoerg if (Tok.is(tok::less) && getLangOpts().ObjC) {
34577330f729Sjoerg SourceLocation NewEndLoc;
34587330f729Sjoerg TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers(
34597330f729Sjoerg Loc, TypeRep, /*consumeLastToken=*/true,
34607330f729Sjoerg NewEndLoc);
34617330f729Sjoerg if (NewTypeRep.isUsable()) {
34627330f729Sjoerg DS.UpdateTypeRep(NewTypeRep.get());
34637330f729Sjoerg DS.SetRangeEnd(NewEndLoc);
34647330f729Sjoerg }
34657330f729Sjoerg }
34667330f729Sjoerg
34677330f729Sjoerg // Need to support trailing type qualifiers (e.g. "id<p> const").
34687330f729Sjoerg // If a type specifier follows, it will be diagnosed elsewhere.
34697330f729Sjoerg continue;
34707330f729Sjoerg }
34717330f729Sjoerg
3472*e038c9c4Sjoerg // type-name or placeholder-specifier
34737330f729Sjoerg case tok::annot_template_id: {
34747330f729Sjoerg TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
3475*e038c9c4Sjoerg
3476*e038c9c4Sjoerg if (TemplateId->hasInvalidName()) {
3477*e038c9c4Sjoerg DS.SetTypeSpecError();
3478*e038c9c4Sjoerg break;
3479*e038c9c4Sjoerg }
3480*e038c9c4Sjoerg
3481*e038c9c4Sjoerg if (TemplateId->Kind == TNK_Concept_template) {
3482*e038c9c4Sjoerg // If we've already diagnosed that this type-constraint has invalid
3483*e038c9c4Sjoerg // arguemnts, drop it and just form 'auto' or 'decltype(auto)'.
3484*e038c9c4Sjoerg if (TemplateId->hasInvalidArgs())
3485*e038c9c4Sjoerg TemplateId = nullptr;
3486*e038c9c4Sjoerg
3487*e038c9c4Sjoerg if (NextToken().is(tok::identifier)) {
3488*e038c9c4Sjoerg Diag(Loc, diag::err_placeholder_expected_auto_or_decltype_auto)
3489*e038c9c4Sjoerg << FixItHint::CreateInsertion(NextToken().getLocation(), "auto");
3490*e038c9c4Sjoerg // Attempt to continue as if 'auto' was placed here.
3491*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID,
3492*e038c9c4Sjoerg TemplateId, Policy);
3493*e038c9c4Sjoerg break;
3494*e038c9c4Sjoerg }
3495*e038c9c4Sjoerg if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))
3496*e038c9c4Sjoerg goto DoneWithDeclSpec;
3497*e038c9c4Sjoerg ConsumeAnnotationToken();
3498*e038c9c4Sjoerg SourceLocation AutoLoc = Tok.getLocation();
3499*e038c9c4Sjoerg if (TryConsumeToken(tok::kw_decltype)) {
3500*e038c9c4Sjoerg BalancedDelimiterTracker Tracker(*this, tok::l_paren);
3501*e038c9c4Sjoerg if (Tracker.consumeOpen()) {
3502*e038c9c4Sjoerg // Something like `void foo(Iterator decltype i)`
3503*e038c9c4Sjoerg Diag(Tok, diag::err_expected) << tok::l_paren;
3504*e038c9c4Sjoerg } else {
3505*e038c9c4Sjoerg if (!TryConsumeToken(tok::kw_auto)) {
3506*e038c9c4Sjoerg // Something like `void foo(Iterator decltype(int) i)`
3507*e038c9c4Sjoerg Tracker.skipToEnd();
3508*e038c9c4Sjoerg Diag(Tok, diag::err_placeholder_expected_auto_or_decltype_auto)
3509*e038c9c4Sjoerg << FixItHint::CreateReplacement(SourceRange(AutoLoc,
3510*e038c9c4Sjoerg Tok.getLocation()),
3511*e038c9c4Sjoerg "auto");
3512*e038c9c4Sjoerg } else {
3513*e038c9c4Sjoerg Tracker.consumeClose();
3514*e038c9c4Sjoerg }
3515*e038c9c4Sjoerg }
3516*e038c9c4Sjoerg ConsumedEnd = Tok.getLocation();
3517*e038c9c4Sjoerg // Even if something went wrong above, continue as if we've seen
3518*e038c9c4Sjoerg // `decltype(auto)`.
3519*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec,
3520*e038c9c4Sjoerg DiagID, TemplateId, Policy);
3521*e038c9c4Sjoerg } else {
3522*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID,
3523*e038c9c4Sjoerg TemplateId, Policy);
3524*e038c9c4Sjoerg }
3525*e038c9c4Sjoerg break;
3526*e038c9c4Sjoerg }
3527*e038c9c4Sjoerg
35287330f729Sjoerg if (TemplateId->Kind != TNK_Type_template &&
35297330f729Sjoerg TemplateId->Kind != TNK_Undeclared_template) {
35307330f729Sjoerg // This template-id does not refer to a type name, so we're
35317330f729Sjoerg // done with the type-specifiers.
35327330f729Sjoerg goto DoneWithDeclSpec;
35337330f729Sjoerg }
35347330f729Sjoerg
35357330f729Sjoerg // If we're in a context where the template-id could be a
35367330f729Sjoerg // constructor name or specialization, check whether this is a
35377330f729Sjoerg // constructor declaration.
35387330f729Sjoerg if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&
35397330f729Sjoerg Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&
3540*e038c9c4Sjoerg isConstructorDeclarator(/*Unqualified=*/true))
35417330f729Sjoerg goto DoneWithDeclSpec;
35427330f729Sjoerg
35437330f729Sjoerg // Turn the template-id annotation token into a type annotation
35447330f729Sjoerg // token, then try again to parse it as a type-specifier.
3545*e038c9c4Sjoerg CXXScopeSpec SS;
3546*e038c9c4Sjoerg AnnotateTemplateIdTokenAsType(SS);
35477330f729Sjoerg continue;
35487330f729Sjoerg }
35497330f729Sjoerg
3550*e038c9c4Sjoerg // Attributes support.
35517330f729Sjoerg case tok::kw___attribute:
35527330f729Sjoerg case tok::kw___declspec:
3553*e038c9c4Sjoerg ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), nullptr,
3554*e038c9c4Sjoerg LateAttrs);
35557330f729Sjoerg continue;
35567330f729Sjoerg
35577330f729Sjoerg // Microsoft single token adornments.
35587330f729Sjoerg case tok::kw___forceinline: {
35597330f729Sjoerg isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);
35607330f729Sjoerg IdentifierInfo *AttrName = Tok.getIdentifierInfo();
35617330f729Sjoerg SourceLocation AttrNameLoc = Tok.getLocation();
35627330f729Sjoerg DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,
35637330f729Sjoerg nullptr, 0, ParsedAttr::AS_Keyword);
35647330f729Sjoerg break;
35657330f729Sjoerg }
35667330f729Sjoerg
35677330f729Sjoerg case tok::kw___unaligned:
35687330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,
35697330f729Sjoerg getLangOpts());
35707330f729Sjoerg break;
35717330f729Sjoerg
35727330f729Sjoerg case tok::kw___sptr:
35737330f729Sjoerg case tok::kw___uptr:
35747330f729Sjoerg case tok::kw___ptr64:
35757330f729Sjoerg case tok::kw___ptr32:
35767330f729Sjoerg case tok::kw___w64:
35777330f729Sjoerg case tok::kw___cdecl:
35787330f729Sjoerg case tok::kw___stdcall:
35797330f729Sjoerg case tok::kw___fastcall:
35807330f729Sjoerg case tok::kw___thiscall:
35817330f729Sjoerg case tok::kw___regcall:
35827330f729Sjoerg case tok::kw___vectorcall:
35837330f729Sjoerg ParseMicrosoftTypeAttributes(DS.getAttributes());
35847330f729Sjoerg continue;
35857330f729Sjoerg
35867330f729Sjoerg // Borland single token adornments.
35877330f729Sjoerg case tok::kw___pascal:
35887330f729Sjoerg ParseBorlandTypeAttributes(DS.getAttributes());
35897330f729Sjoerg continue;
35907330f729Sjoerg
35917330f729Sjoerg // OpenCL single token adornments.
35927330f729Sjoerg case tok::kw___kernel:
35937330f729Sjoerg ParseOpenCLKernelAttributes(DS.getAttributes());
35947330f729Sjoerg continue;
35957330f729Sjoerg
35967330f729Sjoerg // Nullability type specifiers.
35977330f729Sjoerg case tok::kw__Nonnull:
35987330f729Sjoerg case tok::kw__Nullable:
3599*e038c9c4Sjoerg case tok::kw__Nullable_result:
36007330f729Sjoerg case tok::kw__Null_unspecified:
36017330f729Sjoerg ParseNullabilityTypeSpecifiers(DS.getAttributes());
36027330f729Sjoerg continue;
36037330f729Sjoerg
36047330f729Sjoerg // Objective-C 'kindof' types.
36057330f729Sjoerg case tok::kw___kindof:
36067330f729Sjoerg DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
36077330f729Sjoerg nullptr, 0, ParsedAttr::AS_Keyword);
36087330f729Sjoerg (void)ConsumeToken();
36097330f729Sjoerg continue;
36107330f729Sjoerg
36117330f729Sjoerg // storage-class-specifier
36127330f729Sjoerg case tok::kw_typedef:
36137330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
36147330f729Sjoerg PrevSpec, DiagID, Policy);
36157330f729Sjoerg isStorageClass = true;
36167330f729Sjoerg break;
36177330f729Sjoerg case tok::kw_extern:
36187330f729Sjoerg if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
36197330f729Sjoerg Diag(Tok, diag::ext_thread_before) << "extern";
36207330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
36217330f729Sjoerg PrevSpec, DiagID, Policy);
36227330f729Sjoerg isStorageClass = true;
36237330f729Sjoerg break;
36247330f729Sjoerg case tok::kw___private_extern__:
36257330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
36267330f729Sjoerg Loc, PrevSpec, DiagID, Policy);
36277330f729Sjoerg isStorageClass = true;
36287330f729Sjoerg break;
36297330f729Sjoerg case tok::kw_static:
36307330f729Sjoerg if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
36317330f729Sjoerg Diag(Tok, diag::ext_thread_before) << "static";
36327330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
36337330f729Sjoerg PrevSpec, DiagID, Policy);
36347330f729Sjoerg isStorageClass = true;
36357330f729Sjoerg break;
36367330f729Sjoerg case tok::kw_auto:
36377330f729Sjoerg if (getLangOpts().CPlusPlus11) {
36387330f729Sjoerg if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
36397330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
36407330f729Sjoerg PrevSpec, DiagID, Policy);
36417330f729Sjoerg if (!isInvalid)
36427330f729Sjoerg Diag(Tok, diag::ext_auto_storage_class)
36437330f729Sjoerg << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
36447330f729Sjoerg } else
36457330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
36467330f729Sjoerg DiagID, Policy);
36477330f729Sjoerg } else
36487330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
36497330f729Sjoerg PrevSpec, DiagID, Policy);
36507330f729Sjoerg isStorageClass = true;
36517330f729Sjoerg break;
36527330f729Sjoerg case tok::kw___auto_type:
36537330f729Sjoerg Diag(Tok, diag::ext_auto_type);
36547330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
36557330f729Sjoerg DiagID, Policy);
36567330f729Sjoerg break;
36577330f729Sjoerg case tok::kw_register:
36587330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
36597330f729Sjoerg PrevSpec, DiagID, Policy);
36607330f729Sjoerg isStorageClass = true;
36617330f729Sjoerg break;
36627330f729Sjoerg case tok::kw_mutable:
36637330f729Sjoerg isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
36647330f729Sjoerg PrevSpec, DiagID, Policy);
36657330f729Sjoerg isStorageClass = true;
36667330f729Sjoerg break;
36677330f729Sjoerg case tok::kw___thread:
36687330f729Sjoerg isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
36697330f729Sjoerg PrevSpec, DiagID);
36707330f729Sjoerg isStorageClass = true;
36717330f729Sjoerg break;
36727330f729Sjoerg case tok::kw_thread_local:
36737330f729Sjoerg isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc,
36747330f729Sjoerg PrevSpec, DiagID);
36757330f729Sjoerg isStorageClass = true;
36767330f729Sjoerg break;
36777330f729Sjoerg case tok::kw__Thread_local:
36787330f729Sjoerg if (!getLangOpts().C11)
36797330f729Sjoerg Diag(Tok, diag::ext_c11_feature) << Tok.getName();
36807330f729Sjoerg isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
36817330f729Sjoerg Loc, PrevSpec, DiagID);
36827330f729Sjoerg isStorageClass = true;
36837330f729Sjoerg break;
36847330f729Sjoerg
36857330f729Sjoerg // function-specifier
36867330f729Sjoerg case tok::kw_inline:
36877330f729Sjoerg isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);
36887330f729Sjoerg break;
36897330f729Sjoerg case tok::kw_virtual:
36907330f729Sjoerg // C++ for OpenCL does not allow virtual function qualifier, to avoid
36917330f729Sjoerg // function pointers restricted in OpenCL v2.0 s6.9.a.
3692*e038c9c4Sjoerg if (getLangOpts().OpenCLCPlusPlus &&
3693*e038c9c4Sjoerg !getActions().getOpenCLOptions().isAvailableOption(
3694*e038c9c4Sjoerg "__cl_clang_function_pointers", getLangOpts())) {
36957330f729Sjoerg DiagID = diag::err_openclcxx_virtual_function;
36967330f729Sjoerg PrevSpec = Tok.getIdentifierInfo()->getNameStart();
36977330f729Sjoerg isInvalid = true;
3698*e038c9c4Sjoerg } else {
36997330f729Sjoerg isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
37007330f729Sjoerg }
37017330f729Sjoerg break;
37027330f729Sjoerg case tok::kw_explicit: {
37037330f729Sjoerg SourceLocation ExplicitLoc = Loc;
37047330f729Sjoerg SourceLocation CloseParenLoc;
37057330f729Sjoerg ExplicitSpecifier ExplicitSpec(nullptr, ExplicitSpecKind::ResolvedTrue);
37067330f729Sjoerg ConsumedEnd = ExplicitLoc;
37077330f729Sjoerg ConsumeToken(); // kw_explicit
37087330f729Sjoerg if (Tok.is(tok::l_paren)) {
3709*e038c9c4Sjoerg if (getLangOpts().CPlusPlus20 || isExplicitBool() == TPResult::True) {
3710*e038c9c4Sjoerg Diag(Tok.getLocation(), getLangOpts().CPlusPlus20
3711*e038c9c4Sjoerg ? diag::warn_cxx17_compat_explicit_bool
3712*e038c9c4Sjoerg : diag::ext_explicit_bool);
3713*e038c9c4Sjoerg
37147330f729Sjoerg ExprResult ExplicitExpr(static_cast<Expr *>(nullptr));
37157330f729Sjoerg BalancedDelimiterTracker Tracker(*this, tok::l_paren);
37167330f729Sjoerg Tracker.consumeOpen();
37177330f729Sjoerg ExplicitExpr = ParseConstantExpression();
37187330f729Sjoerg ConsumedEnd = Tok.getLocation();
37197330f729Sjoerg if (ExplicitExpr.isUsable()) {
37207330f729Sjoerg CloseParenLoc = Tok.getLocation();
37217330f729Sjoerg Tracker.consumeClose();
37227330f729Sjoerg ExplicitSpec =
37237330f729Sjoerg Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get());
37247330f729Sjoerg } else
37257330f729Sjoerg Tracker.skipToEnd();
3726*e038c9c4Sjoerg } else {
3727*e038c9c4Sjoerg Diag(Tok.getLocation(), diag::warn_cxx20_compat_explicit_bool);
3728*e038c9c4Sjoerg }
37297330f729Sjoerg }
37307330f729Sjoerg isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID,
37317330f729Sjoerg ExplicitSpec, CloseParenLoc);
37327330f729Sjoerg break;
37337330f729Sjoerg }
37347330f729Sjoerg case tok::kw__Noreturn:
37357330f729Sjoerg if (!getLangOpts().C11)
37367330f729Sjoerg Diag(Tok, diag::ext_c11_feature) << Tok.getName();
37377330f729Sjoerg isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
37387330f729Sjoerg break;
37397330f729Sjoerg
37407330f729Sjoerg // alignment-specifier
37417330f729Sjoerg case tok::kw__Alignas:
37427330f729Sjoerg if (!getLangOpts().C11)
37437330f729Sjoerg Diag(Tok, diag::ext_c11_feature) << Tok.getName();
37447330f729Sjoerg ParseAlignmentSpecifier(DS.getAttributes());
37457330f729Sjoerg continue;
37467330f729Sjoerg
37477330f729Sjoerg // friend
37487330f729Sjoerg case tok::kw_friend:
37497330f729Sjoerg if (DSContext == DeclSpecContext::DSC_class)
37507330f729Sjoerg isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
37517330f729Sjoerg else {
37527330f729Sjoerg PrevSpec = ""; // not actually used by the diagnostic
37537330f729Sjoerg DiagID = diag::err_friend_invalid_in_context;
37547330f729Sjoerg isInvalid = true;
37557330f729Sjoerg }
37567330f729Sjoerg break;
37577330f729Sjoerg
37587330f729Sjoerg // Modules
37597330f729Sjoerg case tok::kw___module_private__:
37607330f729Sjoerg isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);
37617330f729Sjoerg break;
37627330f729Sjoerg
37637330f729Sjoerg // constexpr, consteval, constinit specifiers
37647330f729Sjoerg case tok::kw_constexpr:
3765*e038c9c4Sjoerg isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
3766*e038c9c4Sjoerg PrevSpec, DiagID);
37677330f729Sjoerg break;
37687330f729Sjoerg case tok::kw_consteval:
3769*e038c9c4Sjoerg isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Consteval, Loc,
3770*e038c9c4Sjoerg PrevSpec, DiagID);
37717330f729Sjoerg break;
37727330f729Sjoerg case tok::kw_constinit:
3773*e038c9c4Sjoerg isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constinit, Loc,
3774*e038c9c4Sjoerg PrevSpec, DiagID);
37757330f729Sjoerg break;
37767330f729Sjoerg
37777330f729Sjoerg // type-specifier
37787330f729Sjoerg case tok::kw_short:
3779*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Short, Loc, PrevSpec,
37807330f729Sjoerg DiagID, Policy);
37817330f729Sjoerg break;
37827330f729Sjoerg case tok::kw_long:
3783*e038c9c4Sjoerg if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Long)
3784*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Long, Loc, PrevSpec,
37857330f729Sjoerg DiagID, Policy);
37867330f729Sjoerg else
3787*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,
3788*e038c9c4Sjoerg PrevSpec, DiagID, Policy);
37897330f729Sjoerg break;
37907330f729Sjoerg case tok::kw___int64:
3791*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,
3792*e038c9c4Sjoerg PrevSpec, DiagID, Policy);
37937330f729Sjoerg break;
37947330f729Sjoerg case tok::kw_signed:
3795*e038c9c4Sjoerg isInvalid =
3796*e038c9c4Sjoerg DS.SetTypeSpecSign(TypeSpecifierSign::Signed, Loc, PrevSpec, DiagID);
37977330f729Sjoerg break;
37987330f729Sjoerg case tok::kw_unsigned:
3799*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecSign(TypeSpecifierSign::Unsigned, Loc, PrevSpec,
38007330f729Sjoerg DiagID);
38017330f729Sjoerg break;
38027330f729Sjoerg case tok::kw__Complex:
38037330f729Sjoerg if (!getLangOpts().C99)
38047330f729Sjoerg Diag(Tok, diag::ext_c99_feature) << Tok.getName();
38057330f729Sjoerg isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
38067330f729Sjoerg DiagID);
38077330f729Sjoerg break;
38087330f729Sjoerg case tok::kw__Imaginary:
38097330f729Sjoerg if (!getLangOpts().C99)
38107330f729Sjoerg Diag(Tok, diag::ext_c99_feature) << Tok.getName();
38117330f729Sjoerg isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
38127330f729Sjoerg DiagID);
38137330f729Sjoerg break;
38147330f729Sjoerg case tok::kw_void:
38157330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
38167330f729Sjoerg DiagID, Policy);
38177330f729Sjoerg break;
38187330f729Sjoerg case tok::kw_char:
38197330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
38207330f729Sjoerg DiagID, Policy);
38217330f729Sjoerg break;
38227330f729Sjoerg case tok::kw_int:
38237330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
38247330f729Sjoerg DiagID, Policy);
38257330f729Sjoerg break;
3826*e038c9c4Sjoerg case tok::kw__ExtInt: {
3827*e038c9c4Sjoerg ExprResult ER = ParseExtIntegerArgument();
3828*e038c9c4Sjoerg if (ER.isInvalid())
3829*e038c9c4Sjoerg continue;
3830*e038c9c4Sjoerg isInvalid = DS.SetExtIntType(Loc, ER.get(), PrevSpec, DiagID, Policy);
3831*e038c9c4Sjoerg ConsumedEnd = PrevTokLocation;
3832*e038c9c4Sjoerg break;
3833*e038c9c4Sjoerg }
38347330f729Sjoerg case tok::kw___int128:
38357330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,
38367330f729Sjoerg DiagID, Policy);
38377330f729Sjoerg break;
38387330f729Sjoerg case tok::kw_half:
38397330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,
38407330f729Sjoerg DiagID, Policy);
38417330f729Sjoerg break;
3842*e038c9c4Sjoerg case tok::kw___bf16:
3843*e038c9c4Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec,
3844*e038c9c4Sjoerg DiagID, Policy);
3845*e038c9c4Sjoerg break;
38467330f729Sjoerg case tok::kw_float:
38477330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
38487330f729Sjoerg DiagID, Policy);
38497330f729Sjoerg break;
38507330f729Sjoerg case tok::kw_double:
38517330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
38527330f729Sjoerg DiagID, Policy);
38537330f729Sjoerg break;
38547330f729Sjoerg case tok::kw__Float16:
38557330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,
38567330f729Sjoerg DiagID, Policy);
38577330f729Sjoerg break;
38587330f729Sjoerg case tok::kw__Accum:
38597330f729Sjoerg if (!getLangOpts().FixedPoint) {
38607330f729Sjoerg SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
38617330f729Sjoerg } else {
38627330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec,
38637330f729Sjoerg DiagID, Policy);
38647330f729Sjoerg }
38657330f729Sjoerg break;
38667330f729Sjoerg case tok::kw__Fract:
38677330f729Sjoerg if (!getLangOpts().FixedPoint) {
38687330f729Sjoerg SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
38697330f729Sjoerg } else {
38707330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec,
38717330f729Sjoerg DiagID, Policy);
38727330f729Sjoerg }
38737330f729Sjoerg break;
38747330f729Sjoerg case tok::kw__Sat:
38757330f729Sjoerg if (!getLangOpts().FixedPoint) {
38767330f729Sjoerg SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid);
38777330f729Sjoerg } else {
38787330f729Sjoerg isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID);
38797330f729Sjoerg }
38807330f729Sjoerg break;
38817330f729Sjoerg case tok::kw___float128:
38827330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
38837330f729Sjoerg DiagID, Policy);
38847330f729Sjoerg break;
38857330f729Sjoerg case tok::kw_wchar_t:
38867330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
38877330f729Sjoerg DiagID, Policy);
38887330f729Sjoerg break;
38897330f729Sjoerg case tok::kw_char8_t:
38907330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec,
38917330f729Sjoerg DiagID, Policy);
38927330f729Sjoerg break;
38937330f729Sjoerg case tok::kw_char16_t:
38947330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
38957330f729Sjoerg DiagID, Policy);
38967330f729Sjoerg break;
38977330f729Sjoerg case tok::kw_char32_t:
38987330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
38997330f729Sjoerg DiagID, Policy);
39007330f729Sjoerg break;
39017330f729Sjoerg case tok::kw_bool:
39027330f729Sjoerg case tok::kw__Bool:
39037330f729Sjoerg if (Tok.is(tok::kw__Bool) && !getLangOpts().C99)
39047330f729Sjoerg Diag(Tok, diag::ext_c99_feature) << Tok.getName();
39057330f729Sjoerg
39067330f729Sjoerg if (Tok.is(tok::kw_bool) &&
39077330f729Sjoerg DS.getTypeSpecType() != DeclSpec::TST_unspecified &&
39087330f729Sjoerg DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
39097330f729Sjoerg PrevSpec = ""; // Not used by the diagnostic.
39107330f729Sjoerg DiagID = diag::err_bool_redeclaration;
39117330f729Sjoerg // For better error recovery.
39127330f729Sjoerg Tok.setKind(tok::identifier);
39137330f729Sjoerg isInvalid = true;
39147330f729Sjoerg } else {
39157330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
39167330f729Sjoerg DiagID, Policy);
39177330f729Sjoerg }
39187330f729Sjoerg break;
39197330f729Sjoerg case tok::kw__Decimal32:
39207330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
39217330f729Sjoerg DiagID, Policy);
39227330f729Sjoerg break;
39237330f729Sjoerg case tok::kw__Decimal64:
39247330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
39257330f729Sjoerg DiagID, Policy);
39267330f729Sjoerg break;
39277330f729Sjoerg case tok::kw__Decimal128:
39287330f729Sjoerg isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
39297330f729Sjoerg DiagID, Policy);
39307330f729Sjoerg break;
39317330f729Sjoerg case tok::kw___vector:
39327330f729Sjoerg isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
39337330f729Sjoerg break;
39347330f729Sjoerg case tok::kw___pixel:
39357330f729Sjoerg isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
39367330f729Sjoerg break;
39377330f729Sjoerg case tok::kw___bool:
39387330f729Sjoerg isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
39397330f729Sjoerg break;
39407330f729Sjoerg case tok::kw_pipe:
39417330f729Sjoerg if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200 &&
39427330f729Sjoerg !getLangOpts().OpenCLCPlusPlus)) {
3943*e038c9c4Sjoerg // OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier
3944*e038c9c4Sjoerg // should support the "pipe" word as identifier.
39457330f729Sjoerg Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
3946*e038c9c4Sjoerg Tok.setKind(tok::identifier);
39477330f729Sjoerg goto DoneWithDeclSpec;
39487330f729Sjoerg }
39497330f729Sjoerg isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
39507330f729Sjoerg break;
3951*e038c9c4Sjoerg // We only need to enumerate each image type once.
3952*e038c9c4Sjoerg #define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
3953*e038c9c4Sjoerg #define IMAGE_WRITE_TYPE(Type, Id, Ext)
3954*e038c9c4Sjoerg #define IMAGE_READ_TYPE(ImgType, Id, Ext) \
39557330f729Sjoerg case tok::kw_##ImgType##_t: \
3956*e038c9c4Sjoerg if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \
3957*e038c9c4Sjoerg goto DoneWithDeclSpec; \
39587330f729Sjoerg break;
39597330f729Sjoerg #include "clang/Basic/OpenCLImageTypes.def"
39607330f729Sjoerg case tok::kw___unknown_anytype:
39617330f729Sjoerg isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
39627330f729Sjoerg PrevSpec, DiagID, Policy);
39637330f729Sjoerg break;
39647330f729Sjoerg
39657330f729Sjoerg // class-specifier:
39667330f729Sjoerg case tok::kw_class:
39677330f729Sjoerg case tok::kw_struct:
39687330f729Sjoerg case tok::kw___interface:
39697330f729Sjoerg case tok::kw_union: {
39707330f729Sjoerg tok::TokenKind Kind = Tok.getKind();
39717330f729Sjoerg ConsumeToken();
39727330f729Sjoerg
39737330f729Sjoerg // These are attributes following class specifiers.
39747330f729Sjoerg // To produce better diagnostic, we parse them when
39757330f729Sjoerg // parsing class specifier.
39767330f729Sjoerg ParsedAttributesWithRange Attributes(AttrFactory);
39777330f729Sjoerg ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS,
39787330f729Sjoerg EnteringContext, DSContext, Attributes);
39797330f729Sjoerg
39807330f729Sjoerg // If there are attributes following class specifier,
39817330f729Sjoerg // take them over and handle them here.
39827330f729Sjoerg if (!Attributes.empty()) {
39837330f729Sjoerg AttrsLastTime = true;
39847330f729Sjoerg attrs.takeAllFrom(Attributes);
39857330f729Sjoerg }
39867330f729Sjoerg continue;
39877330f729Sjoerg }
39887330f729Sjoerg
39897330f729Sjoerg // enum-specifier:
39907330f729Sjoerg case tok::kw_enum:
39917330f729Sjoerg ConsumeToken();
39927330f729Sjoerg ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext);
39937330f729Sjoerg continue;
39947330f729Sjoerg
39957330f729Sjoerg // cv-qualifier:
39967330f729Sjoerg case tok::kw_const:
39977330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
39987330f729Sjoerg getLangOpts());
39997330f729Sjoerg break;
40007330f729Sjoerg case tok::kw_volatile:
40017330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
40027330f729Sjoerg getLangOpts());
40037330f729Sjoerg break;
40047330f729Sjoerg case tok::kw_restrict:
40057330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
40067330f729Sjoerg getLangOpts());
40077330f729Sjoerg break;
40087330f729Sjoerg
40097330f729Sjoerg // C++ typename-specifier:
40107330f729Sjoerg case tok::kw_typename:
40117330f729Sjoerg if (TryAnnotateTypeOrScopeToken()) {
40127330f729Sjoerg DS.SetTypeSpecError();
40137330f729Sjoerg goto DoneWithDeclSpec;
40147330f729Sjoerg }
40157330f729Sjoerg if (!Tok.is(tok::kw_typename))
40167330f729Sjoerg continue;
40177330f729Sjoerg break;
40187330f729Sjoerg
40197330f729Sjoerg // GNU typeof support.
40207330f729Sjoerg case tok::kw_typeof:
40217330f729Sjoerg ParseTypeofSpecifier(DS);
40227330f729Sjoerg continue;
40237330f729Sjoerg
40247330f729Sjoerg case tok::annot_decltype:
40257330f729Sjoerg ParseDecltypeSpecifier(DS);
40267330f729Sjoerg continue;
40277330f729Sjoerg
40287330f729Sjoerg case tok::annot_pragma_pack:
40297330f729Sjoerg HandlePragmaPack();
40307330f729Sjoerg continue;
40317330f729Sjoerg
40327330f729Sjoerg case tok::annot_pragma_ms_pragma:
40337330f729Sjoerg HandlePragmaMSPragma();
40347330f729Sjoerg continue;
40357330f729Sjoerg
40367330f729Sjoerg case tok::annot_pragma_ms_vtordisp:
40377330f729Sjoerg HandlePragmaMSVtorDisp();
40387330f729Sjoerg continue;
40397330f729Sjoerg
40407330f729Sjoerg case tok::annot_pragma_ms_pointers_to_members:
40417330f729Sjoerg HandlePragmaMSPointersToMembers();
40427330f729Sjoerg continue;
40437330f729Sjoerg
40447330f729Sjoerg case tok::kw___underlying_type:
40457330f729Sjoerg ParseUnderlyingTypeSpecifier(DS);
40467330f729Sjoerg continue;
40477330f729Sjoerg
40487330f729Sjoerg case tok::kw__Atomic:
40497330f729Sjoerg // C11 6.7.2.4/4:
40507330f729Sjoerg // If the _Atomic keyword is immediately followed by a left parenthesis,
40517330f729Sjoerg // it is interpreted as a type specifier (with a type name), not as a
40527330f729Sjoerg // type qualifier.
40537330f729Sjoerg if (!getLangOpts().C11)
40547330f729Sjoerg Diag(Tok, diag::ext_c11_feature) << Tok.getName();
40557330f729Sjoerg
40567330f729Sjoerg if (NextToken().is(tok::l_paren)) {
40577330f729Sjoerg ParseAtomicSpecifier(DS);
40587330f729Sjoerg continue;
40597330f729Sjoerg }
40607330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
40617330f729Sjoerg getLangOpts());
40627330f729Sjoerg break;
40637330f729Sjoerg
40647330f729Sjoerg // OpenCL address space qualifiers:
40657330f729Sjoerg case tok::kw___generic:
40667330f729Sjoerg // generic address space is introduced only in OpenCL v2.0
40677330f729Sjoerg // see OpenCL C Spec v2.0 s6.5.5
4068*e038c9c4Sjoerg if (!Actions.getLangOpts().OpenCLGenericAddressSpace) {
40697330f729Sjoerg DiagID = diag::err_opencl_unknown_type_specifier;
40707330f729Sjoerg PrevSpec = Tok.getIdentifierInfo()->getNameStart();
40717330f729Sjoerg isInvalid = true;
40727330f729Sjoerg break;
4073*e038c9c4Sjoerg }
40747330f729Sjoerg LLVM_FALLTHROUGH;
40757330f729Sjoerg case tok::kw_private:
4076*e038c9c4Sjoerg // It's fine (but redundant) to check this for __generic on the
4077*e038c9c4Sjoerg // fallthrough path; we only form the __generic token in OpenCL mode.
4078*e038c9c4Sjoerg if (!getLangOpts().OpenCL)
4079*e038c9c4Sjoerg goto DoneWithDeclSpec;
4080*e038c9c4Sjoerg LLVM_FALLTHROUGH;
40817330f729Sjoerg case tok::kw___private:
40827330f729Sjoerg case tok::kw___global:
40837330f729Sjoerg case tok::kw___local:
40847330f729Sjoerg case tok::kw___constant:
40857330f729Sjoerg // OpenCL access qualifiers:
40867330f729Sjoerg case tok::kw___read_only:
40877330f729Sjoerg case tok::kw___write_only:
40887330f729Sjoerg case tok::kw___read_write:
40897330f729Sjoerg ParseOpenCLQualifiers(DS.getAttributes());
40907330f729Sjoerg break;
40917330f729Sjoerg
40927330f729Sjoerg case tok::less:
40937330f729Sjoerg // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
40947330f729Sjoerg // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
40957330f729Sjoerg // but we support it.
40967330f729Sjoerg if (DS.hasTypeSpecifier() || !getLangOpts().ObjC)
40977330f729Sjoerg goto DoneWithDeclSpec;
40987330f729Sjoerg
40997330f729Sjoerg SourceLocation StartLoc = Tok.getLocation();
41007330f729Sjoerg SourceLocation EndLoc;
41017330f729Sjoerg TypeResult Type = parseObjCProtocolQualifierType(EndLoc);
41027330f729Sjoerg if (Type.isUsable()) {
41037330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, StartLoc,
41047330f729Sjoerg PrevSpec, DiagID, Type.get(),
41057330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
41067330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
41077330f729Sjoerg
41087330f729Sjoerg DS.SetRangeEnd(EndLoc);
41097330f729Sjoerg } else {
41107330f729Sjoerg DS.SetTypeSpecError();
41117330f729Sjoerg }
41127330f729Sjoerg
41137330f729Sjoerg // Need to support trailing type qualifiers (e.g. "id<p> const").
41147330f729Sjoerg // If a type specifier follows, it will be diagnosed elsewhere.
41157330f729Sjoerg continue;
41167330f729Sjoerg }
41177330f729Sjoerg
41187330f729Sjoerg DS.SetRangeEnd(ConsumedEnd.isValid() ? ConsumedEnd : Tok.getLocation());
41197330f729Sjoerg
41207330f729Sjoerg // If the specifier wasn't legal, issue a diagnostic.
41217330f729Sjoerg if (isInvalid) {
41227330f729Sjoerg assert(PrevSpec && "Method did not return previous specifier!");
41237330f729Sjoerg assert(DiagID);
41247330f729Sjoerg
41257330f729Sjoerg if (DiagID == diag::ext_duplicate_declspec ||
41267330f729Sjoerg DiagID == diag::ext_warn_duplicate_declspec ||
41277330f729Sjoerg DiagID == diag::err_duplicate_declspec)
41287330f729Sjoerg Diag(Loc, DiagID) << PrevSpec
41297330f729Sjoerg << FixItHint::CreateRemoval(
41307330f729Sjoerg SourceRange(Loc, DS.getEndLoc()));
41317330f729Sjoerg else if (DiagID == diag::err_opencl_unknown_type_specifier) {
41327330f729Sjoerg Diag(Loc, DiagID) << getLangOpts().OpenCLCPlusPlus
41337330f729Sjoerg << getLangOpts().getOpenCLVersionTuple().getAsString()
41347330f729Sjoerg << PrevSpec << isStorageClass;
41357330f729Sjoerg } else
41367330f729Sjoerg Diag(Loc, DiagID) << PrevSpec;
41377330f729Sjoerg }
41387330f729Sjoerg
41397330f729Sjoerg if (DiagID != diag::err_bool_redeclaration && ConsumedEnd.isInvalid())
41407330f729Sjoerg // After an error the next token can be an annotation token.
41417330f729Sjoerg ConsumeAnyToken();
41427330f729Sjoerg
41437330f729Sjoerg AttrsLastTime = false;
41447330f729Sjoerg }
41457330f729Sjoerg }
41467330f729Sjoerg
41477330f729Sjoerg /// ParseStructDeclaration - Parse a struct declaration without the terminating
41487330f729Sjoerg /// semicolon.
41497330f729Sjoerg ///
41507330f729Sjoerg /// Note that a struct declaration refers to a declaration in a struct,
41517330f729Sjoerg /// not to the declaration of a struct.
41527330f729Sjoerg ///
41537330f729Sjoerg /// struct-declaration:
41547330f729Sjoerg /// [C2x] attributes-specifier-seq[opt]
41557330f729Sjoerg /// specifier-qualifier-list struct-declarator-list
41567330f729Sjoerg /// [GNU] __extension__ struct-declaration
41577330f729Sjoerg /// [GNU] specifier-qualifier-list
41587330f729Sjoerg /// struct-declarator-list:
41597330f729Sjoerg /// struct-declarator
41607330f729Sjoerg /// struct-declarator-list ',' struct-declarator
41617330f729Sjoerg /// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator
41627330f729Sjoerg /// struct-declarator:
41637330f729Sjoerg /// declarator
41647330f729Sjoerg /// [GNU] declarator attributes[opt]
41657330f729Sjoerg /// declarator[opt] ':' constant-expression
41667330f729Sjoerg /// [GNU] declarator[opt] ':' constant-expression attributes[opt]
41677330f729Sjoerg ///
ParseStructDeclaration(ParsingDeclSpec & DS,llvm::function_ref<void (ParsingFieldDeclarator &)> FieldsCallback)41687330f729Sjoerg void Parser::ParseStructDeclaration(
41697330f729Sjoerg ParsingDeclSpec &DS,
41707330f729Sjoerg llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback) {
41717330f729Sjoerg
41727330f729Sjoerg if (Tok.is(tok::kw___extension__)) {
41737330f729Sjoerg // __extension__ silences extension warnings in the subexpression.
41747330f729Sjoerg ExtensionRAIIObject O(Diags); // Use RAII to do this.
41757330f729Sjoerg ConsumeToken();
41767330f729Sjoerg return ParseStructDeclaration(DS, FieldsCallback);
41777330f729Sjoerg }
41787330f729Sjoerg
41797330f729Sjoerg // Parse leading attributes.
41807330f729Sjoerg ParsedAttributesWithRange Attrs(AttrFactory);
41817330f729Sjoerg MaybeParseCXX11Attributes(Attrs);
41827330f729Sjoerg DS.takeAttributesFrom(Attrs);
41837330f729Sjoerg
41847330f729Sjoerg // Parse the common specifier-qualifiers-list piece.
41857330f729Sjoerg ParseSpecifierQualifierList(DS);
41867330f729Sjoerg
41877330f729Sjoerg // If there are no declarators, this is a free-standing declaration
41887330f729Sjoerg // specifier. Let the actions module cope with it.
41897330f729Sjoerg if (Tok.is(tok::semi)) {
41907330f729Sjoerg RecordDecl *AnonRecord = nullptr;
41917330f729Sjoerg Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
41927330f729Sjoerg DS, AnonRecord);
41937330f729Sjoerg assert(!AnonRecord && "Did not expect anonymous struct or union here");
41947330f729Sjoerg DS.complete(TheDecl);
41957330f729Sjoerg return;
41967330f729Sjoerg }
41977330f729Sjoerg
41987330f729Sjoerg // Read struct-declarators until we find the semicolon.
41997330f729Sjoerg bool FirstDeclarator = true;
42007330f729Sjoerg SourceLocation CommaLoc;
42017330f729Sjoerg while (1) {
42027330f729Sjoerg ParsingFieldDeclarator DeclaratorInfo(*this, DS);
42037330f729Sjoerg DeclaratorInfo.D.setCommaLoc(CommaLoc);
42047330f729Sjoerg
42057330f729Sjoerg // Attributes are only allowed here on successive declarators.
4206*e038c9c4Sjoerg if (!FirstDeclarator) {
4207*e038c9c4Sjoerg // However, this does not apply for [[]] attributes (which could show up
4208*e038c9c4Sjoerg // before or after the __attribute__ attributes).
4209*e038c9c4Sjoerg DiagnoseAndSkipCXX11Attributes();
42107330f729Sjoerg MaybeParseGNUAttributes(DeclaratorInfo.D);
4211*e038c9c4Sjoerg DiagnoseAndSkipCXX11Attributes();
4212*e038c9c4Sjoerg }
42137330f729Sjoerg
42147330f729Sjoerg /// struct-declarator: declarator
42157330f729Sjoerg /// struct-declarator: declarator[opt] ':' constant-expression
42167330f729Sjoerg if (Tok.isNot(tok::colon)) {
42177330f729Sjoerg // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
42187330f729Sjoerg ColonProtectionRAIIObject X(*this);
42197330f729Sjoerg ParseDeclarator(DeclaratorInfo.D);
42207330f729Sjoerg } else
42217330f729Sjoerg DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation());
42227330f729Sjoerg
42237330f729Sjoerg if (TryConsumeToken(tok::colon)) {
42247330f729Sjoerg ExprResult Res(ParseConstantExpression());
42257330f729Sjoerg if (Res.isInvalid())
42267330f729Sjoerg SkipUntil(tok::semi, StopBeforeMatch);
42277330f729Sjoerg else
42287330f729Sjoerg DeclaratorInfo.BitfieldSize = Res.get();
42297330f729Sjoerg }
42307330f729Sjoerg
42317330f729Sjoerg // If attributes exist after the declarator, parse them.
42327330f729Sjoerg MaybeParseGNUAttributes(DeclaratorInfo.D);
42337330f729Sjoerg
42347330f729Sjoerg // We're done with this declarator; invoke the callback.
42357330f729Sjoerg FieldsCallback(DeclaratorInfo);
42367330f729Sjoerg
42377330f729Sjoerg // If we don't have a comma, it is either the end of the list (a ';')
42387330f729Sjoerg // or an error, bail out.
42397330f729Sjoerg if (!TryConsumeToken(tok::comma, CommaLoc))
42407330f729Sjoerg return;
42417330f729Sjoerg
42427330f729Sjoerg FirstDeclarator = false;
42437330f729Sjoerg }
42447330f729Sjoerg }
42457330f729Sjoerg
42467330f729Sjoerg /// ParseStructUnionBody
42477330f729Sjoerg /// struct-contents:
42487330f729Sjoerg /// struct-declaration-list
42497330f729Sjoerg /// [EXT] empty
4250*e038c9c4Sjoerg /// [GNU] "struct-declaration-list" without terminating ';'
42517330f729Sjoerg /// struct-declaration-list:
42527330f729Sjoerg /// struct-declaration
42537330f729Sjoerg /// struct-declaration-list struct-declaration
42547330f729Sjoerg /// [OBC] '@' 'defs' '(' class-name ')'
42557330f729Sjoerg ///
ParseStructUnionBody(SourceLocation RecordLoc,DeclSpec::TST TagType,RecordDecl * TagDecl)42567330f729Sjoerg void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
4257*e038c9c4Sjoerg DeclSpec::TST TagType, RecordDecl *TagDecl) {
42587330f729Sjoerg PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
42597330f729Sjoerg "parsing struct/union body");
42607330f729Sjoerg assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
42617330f729Sjoerg
42627330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_brace);
42637330f729Sjoerg if (T.consumeOpen())
42647330f729Sjoerg return;
42657330f729Sjoerg
42667330f729Sjoerg ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
42677330f729Sjoerg Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
42687330f729Sjoerg
42697330f729Sjoerg // While we still have something to read, read the declarations in the struct.
42707330f729Sjoerg while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
42717330f729Sjoerg Tok.isNot(tok::eof)) {
42727330f729Sjoerg // Each iteration of this loop reads one struct-declaration.
42737330f729Sjoerg
42747330f729Sjoerg // Check for extraneous top-level semicolon.
42757330f729Sjoerg if (Tok.is(tok::semi)) {
42767330f729Sjoerg ConsumeExtraSemi(InsideStruct, TagType);
42777330f729Sjoerg continue;
42787330f729Sjoerg }
42797330f729Sjoerg
42807330f729Sjoerg // Parse _Static_assert declaration.
4281*e038c9c4Sjoerg if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) {
42827330f729Sjoerg SourceLocation DeclEnd;
42837330f729Sjoerg ParseStaticAssertDeclaration(DeclEnd);
42847330f729Sjoerg continue;
42857330f729Sjoerg }
42867330f729Sjoerg
42877330f729Sjoerg if (Tok.is(tok::annot_pragma_pack)) {
42887330f729Sjoerg HandlePragmaPack();
42897330f729Sjoerg continue;
42907330f729Sjoerg }
42917330f729Sjoerg
42927330f729Sjoerg if (Tok.is(tok::annot_pragma_align)) {
42937330f729Sjoerg HandlePragmaAlign();
42947330f729Sjoerg continue;
42957330f729Sjoerg }
42967330f729Sjoerg
42977330f729Sjoerg if (Tok.is(tok::annot_pragma_openmp)) {
42987330f729Sjoerg // Result can be ignored, because it must be always empty.
42997330f729Sjoerg AccessSpecifier AS = AS_none;
43007330f729Sjoerg ParsedAttributesWithRange Attrs(AttrFactory);
43017330f729Sjoerg (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
43027330f729Sjoerg continue;
43037330f729Sjoerg }
43047330f729Sjoerg
43057330f729Sjoerg if (tok::isPragmaAnnotation(Tok.getKind())) {
43067330f729Sjoerg Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)
43077330f729Sjoerg << DeclSpec::getSpecifierName(
43087330f729Sjoerg TagType, Actions.getASTContext().getPrintingPolicy());
43097330f729Sjoerg ConsumeAnnotationToken();
43107330f729Sjoerg continue;
43117330f729Sjoerg }
43127330f729Sjoerg
43137330f729Sjoerg if (!Tok.is(tok::at)) {
43147330f729Sjoerg auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
43157330f729Sjoerg // Install the declarator into the current TagDecl.
43167330f729Sjoerg Decl *Field =
43177330f729Sjoerg Actions.ActOnField(getCurScope(), TagDecl,
43187330f729Sjoerg FD.D.getDeclSpec().getSourceRange().getBegin(),
43197330f729Sjoerg FD.D, FD.BitfieldSize);
43207330f729Sjoerg FD.complete(Field);
43217330f729Sjoerg };
43227330f729Sjoerg
43237330f729Sjoerg // Parse all the comma separated declarators.
43247330f729Sjoerg ParsingDeclSpec DS(*this);
43257330f729Sjoerg ParseStructDeclaration(DS, CFieldCallback);
43267330f729Sjoerg } else { // Handle @defs
43277330f729Sjoerg ConsumeToken();
43287330f729Sjoerg if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
43297330f729Sjoerg Diag(Tok, diag::err_unexpected_at);
43307330f729Sjoerg SkipUntil(tok::semi);
43317330f729Sjoerg continue;
43327330f729Sjoerg }
43337330f729Sjoerg ConsumeToken();
43347330f729Sjoerg ExpectAndConsume(tok::l_paren);
43357330f729Sjoerg if (!Tok.is(tok::identifier)) {
43367330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
43377330f729Sjoerg SkipUntil(tok::semi);
43387330f729Sjoerg continue;
43397330f729Sjoerg }
43407330f729Sjoerg SmallVector<Decl *, 16> Fields;
43417330f729Sjoerg Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),
43427330f729Sjoerg Tok.getIdentifierInfo(), Fields);
43437330f729Sjoerg ConsumeToken();
43447330f729Sjoerg ExpectAndConsume(tok::r_paren);
43457330f729Sjoerg }
43467330f729Sjoerg
43477330f729Sjoerg if (TryConsumeToken(tok::semi))
43487330f729Sjoerg continue;
43497330f729Sjoerg
43507330f729Sjoerg if (Tok.is(tok::r_brace)) {
43517330f729Sjoerg ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
43527330f729Sjoerg break;
43537330f729Sjoerg }
43547330f729Sjoerg
43557330f729Sjoerg ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
43567330f729Sjoerg // Skip to end of block or statement to avoid ext-warning on extra ';'.
43577330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
43587330f729Sjoerg // If we stopped at a ';', eat it.
43597330f729Sjoerg TryConsumeToken(tok::semi);
43607330f729Sjoerg }
43617330f729Sjoerg
43627330f729Sjoerg T.consumeClose();
43637330f729Sjoerg
43647330f729Sjoerg ParsedAttributes attrs(AttrFactory);
43657330f729Sjoerg // If attributes exist after struct contents, parse them.
43667330f729Sjoerg MaybeParseGNUAttributes(attrs);
43677330f729Sjoerg
4368*e038c9c4Sjoerg SmallVector<Decl *, 32> FieldDecls(TagDecl->field_begin(),
4369*e038c9c4Sjoerg TagDecl->field_end());
4370*e038c9c4Sjoerg
43717330f729Sjoerg Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls,
43727330f729Sjoerg T.getOpenLocation(), T.getCloseLocation(), attrs);
43737330f729Sjoerg StructScope.Exit();
43747330f729Sjoerg Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());
43757330f729Sjoerg }
43767330f729Sjoerg
43777330f729Sjoerg /// ParseEnumSpecifier
43787330f729Sjoerg /// enum-specifier: [C99 6.7.2.2]
43797330f729Sjoerg /// 'enum' identifier[opt] '{' enumerator-list '}'
43807330f729Sjoerg ///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'
43817330f729Sjoerg /// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
43827330f729Sjoerg /// '}' attributes[opt]
43837330f729Sjoerg /// [MS] 'enum' __declspec[opt] identifier[opt] '{' enumerator-list ',' [opt]
43847330f729Sjoerg /// '}'
43857330f729Sjoerg /// 'enum' identifier
43867330f729Sjoerg /// [GNU] 'enum' attributes[opt] identifier
43877330f729Sjoerg ///
43887330f729Sjoerg /// [C++11] enum-head '{' enumerator-list[opt] '}'
43897330f729Sjoerg /// [C++11] enum-head '{' enumerator-list ',' '}'
43907330f729Sjoerg ///
43917330f729Sjoerg /// enum-head: [C++11]
43927330f729Sjoerg /// enum-key attribute-specifier-seq[opt] identifier[opt] enum-base[opt]
43937330f729Sjoerg /// enum-key attribute-specifier-seq[opt] nested-name-specifier
43947330f729Sjoerg /// identifier enum-base[opt]
43957330f729Sjoerg ///
43967330f729Sjoerg /// enum-key: [C++11]
43977330f729Sjoerg /// 'enum'
43987330f729Sjoerg /// 'enum' 'class'
43997330f729Sjoerg /// 'enum' 'struct'
44007330f729Sjoerg ///
44017330f729Sjoerg /// enum-base: [C++11]
44027330f729Sjoerg /// ':' type-specifier-seq
44037330f729Sjoerg ///
44047330f729Sjoerg /// [C++] elaborated-type-specifier:
4405*e038c9c4Sjoerg /// [C++] 'enum' nested-name-specifier[opt] identifier
44067330f729Sjoerg ///
ParseEnumSpecifier(SourceLocation StartLoc,DeclSpec & DS,const ParsedTemplateInfo & TemplateInfo,AccessSpecifier AS,DeclSpecContext DSC)44077330f729Sjoerg void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
44087330f729Sjoerg const ParsedTemplateInfo &TemplateInfo,
44097330f729Sjoerg AccessSpecifier AS, DeclSpecContext DSC) {
44107330f729Sjoerg // Parse the tag portion of this.
44117330f729Sjoerg if (Tok.is(tok::code_completion)) {
44127330f729Sjoerg // Code completion for an enum name.
4413*e038c9c4Sjoerg cutOffParsing();
44147330f729Sjoerg Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);
4415*e038c9c4Sjoerg return;
44167330f729Sjoerg }
44177330f729Sjoerg
44187330f729Sjoerg // If attributes exist after tag, parse them.
44197330f729Sjoerg ParsedAttributesWithRange attrs(AttrFactory);
4420*e038c9c4Sjoerg MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
44217330f729Sjoerg
44227330f729Sjoerg SourceLocation ScopedEnumKWLoc;
44237330f729Sjoerg bool IsScopedUsingClassTag = false;
44247330f729Sjoerg
44257330f729Sjoerg // In C++11, recognize 'enum class' and 'enum struct'.
44267330f729Sjoerg if (Tok.isOneOf(tok::kw_class, tok::kw_struct)) {
44277330f729Sjoerg Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum
44287330f729Sjoerg : diag::ext_scoped_enum);
44297330f729Sjoerg IsScopedUsingClassTag = Tok.is(tok::kw_class);
44307330f729Sjoerg ScopedEnumKWLoc = ConsumeToken();
44317330f729Sjoerg
44327330f729Sjoerg // Attributes are not allowed between these keywords. Diagnose,
44337330f729Sjoerg // but then just treat them like they appeared in the right place.
44347330f729Sjoerg ProhibitAttributes(attrs);
44357330f729Sjoerg
44367330f729Sjoerg // They are allowed afterwards, though.
4437*e038c9c4Sjoerg MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
44387330f729Sjoerg }
44397330f729Sjoerg
44407330f729Sjoerg // C++11 [temp.explicit]p12:
44417330f729Sjoerg // The usual access controls do not apply to names used to specify
44427330f729Sjoerg // explicit instantiations.
44437330f729Sjoerg // We extend this to also cover explicit specializations. Note that
44447330f729Sjoerg // we don't suppress if this turns out to be an elaborated type
44457330f729Sjoerg // specifier.
44467330f729Sjoerg bool shouldDelayDiagsInTag =
44477330f729Sjoerg (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
44487330f729Sjoerg TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
44497330f729Sjoerg SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
44507330f729Sjoerg
4451*e038c9c4Sjoerg // Determine whether this declaration is permitted to have an enum-base.
4452*e038c9c4Sjoerg AllowDefiningTypeSpec AllowEnumSpecifier =
4453*e038c9c4Sjoerg isDefiningTypeSpecifierContext(DSC);
4454*e038c9c4Sjoerg bool CanBeOpaqueEnumDeclaration =
4455*e038c9c4Sjoerg DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC);
4456*e038c9c4Sjoerg bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC ||
4457*e038c9c4Sjoerg getLangOpts().MicrosoftExt) &&
4458*e038c9c4Sjoerg (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes ||
4459*e038c9c4Sjoerg CanBeOpaqueEnumDeclaration);
44607330f729Sjoerg
44617330f729Sjoerg CXXScopeSpec &SS = DS.getTypeSpecScope();
44627330f729Sjoerg if (getLangOpts().CPlusPlus) {
4463*e038c9c4Sjoerg // "enum foo : bar;" is not a potential typo for "enum foo::bar;".
4464*e038c9c4Sjoerg ColonProtectionRAIIObject X(*this);
44657330f729Sjoerg
44667330f729Sjoerg CXXScopeSpec Spec;
4467*e038c9c4Sjoerg if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,
4468*e038c9c4Sjoerg /*ObjectHadErrors=*/false,
44697330f729Sjoerg /*EnteringContext=*/true))
44707330f729Sjoerg return;
44717330f729Sjoerg
44727330f729Sjoerg if (Spec.isSet() && Tok.isNot(tok::identifier)) {
44737330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
44747330f729Sjoerg if (Tok.isNot(tok::l_brace)) {
44757330f729Sjoerg // Has no name and is not a definition.
44767330f729Sjoerg // Skip the rest of this declarator, up until the comma or semicolon.
44777330f729Sjoerg SkipUntil(tok::comma, StopAtSemi);
44787330f729Sjoerg return;
44797330f729Sjoerg }
44807330f729Sjoerg }
44817330f729Sjoerg
44827330f729Sjoerg SS = Spec;
44837330f729Sjoerg }
44847330f729Sjoerg
4485*e038c9c4Sjoerg // Must have either 'enum name' or 'enum {...}' or (rarely) 'enum : T { ... }'.
44867330f729Sjoerg if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
4487*e038c9c4Sjoerg Tok.isNot(tok::colon)) {
44887330f729Sjoerg Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
44897330f729Sjoerg
44907330f729Sjoerg // Skip the rest of this declarator, up until the comma or semicolon.
44917330f729Sjoerg SkipUntil(tok::comma, StopAtSemi);
44927330f729Sjoerg return;
44937330f729Sjoerg }
44947330f729Sjoerg
44957330f729Sjoerg // If an identifier is present, consume and remember it.
44967330f729Sjoerg IdentifierInfo *Name = nullptr;
44977330f729Sjoerg SourceLocation NameLoc;
44987330f729Sjoerg if (Tok.is(tok::identifier)) {
44997330f729Sjoerg Name = Tok.getIdentifierInfo();
45007330f729Sjoerg NameLoc = ConsumeToken();
45017330f729Sjoerg }
45027330f729Sjoerg
45037330f729Sjoerg if (!Name && ScopedEnumKWLoc.isValid()) {
45047330f729Sjoerg // C++0x 7.2p2: The optional identifier shall not be omitted in the
45057330f729Sjoerg // declaration of a scoped enumeration.
45067330f729Sjoerg Diag(Tok, diag::err_scoped_enum_missing_identifier);
45077330f729Sjoerg ScopedEnumKWLoc = SourceLocation();
45087330f729Sjoerg IsScopedUsingClassTag = false;
45097330f729Sjoerg }
45107330f729Sjoerg
45117330f729Sjoerg // Okay, end the suppression area. We'll decide whether to emit the
45127330f729Sjoerg // diagnostics in a second.
45137330f729Sjoerg if (shouldDelayDiagsInTag)
45147330f729Sjoerg diagsFromTag.done();
45157330f729Sjoerg
45167330f729Sjoerg TypeResult BaseType;
4517*e038c9c4Sjoerg SourceRange BaseRange;
4518*e038c9c4Sjoerg
4519*e038c9c4Sjoerg bool CanBeBitfield = (getCurScope()->getFlags() & Scope::ClassScope) &&
4520*e038c9c4Sjoerg ScopedEnumKWLoc.isInvalid() && Name;
45217330f729Sjoerg
45227330f729Sjoerg // Parse the fixed underlying type.
4523*e038c9c4Sjoerg if (Tok.is(tok::colon)) {
4524*e038c9c4Sjoerg // This might be an enum-base or part of some unrelated enclosing context.
4525*e038c9c4Sjoerg //
4526*e038c9c4Sjoerg // 'enum E : base' is permitted in two circumstances:
4527*e038c9c4Sjoerg //
4528*e038c9c4Sjoerg // 1) As a defining-type-specifier, when followed by '{'.
4529*e038c9c4Sjoerg // 2) As the sole constituent of a complete declaration -- when DS is empty
4530*e038c9c4Sjoerg // and the next token is ';'.
4531*e038c9c4Sjoerg //
4532*e038c9c4Sjoerg // The restriction to defining-type-specifiers is important to allow parsing
4533*e038c9c4Sjoerg // a ? new enum E : int{}
4534*e038c9c4Sjoerg // _Generic(a, enum E : int{})
4535*e038c9c4Sjoerg // properly.
4536*e038c9c4Sjoerg //
4537*e038c9c4Sjoerg // One additional consideration applies:
4538*e038c9c4Sjoerg //
4539*e038c9c4Sjoerg // C++ [dcl.enum]p1:
4540*e038c9c4Sjoerg // A ':' following "enum nested-name-specifier[opt] identifier" within
4541*e038c9c4Sjoerg // the decl-specifier-seq of a member-declaration is parsed as part of
4542*e038c9c4Sjoerg // an enum-base.
4543*e038c9c4Sjoerg //
4544*e038c9c4Sjoerg // Other language modes supporting enumerations with fixed underlying types
4545*e038c9c4Sjoerg // do not have clear rules on this, so we disambiguate to determine whether
4546*e038c9c4Sjoerg // the tokens form a bit-field width or an enum-base.
45477330f729Sjoerg
4548*e038c9c4Sjoerg if (CanBeBitfield && !isEnumBase(CanBeOpaqueEnumDeclaration)) {
4549*e038c9c4Sjoerg // Outside C++11, do not interpret the tokens as an enum-base if they do
4550*e038c9c4Sjoerg // not make sense as one. In C++11, it's an error if this happens.
4551*e038c9c4Sjoerg if (getLangOpts().CPlusPlus11)
4552*e038c9c4Sjoerg Diag(Tok.getLocation(), diag::err_anonymous_enum_bitfield);
4553*e038c9c4Sjoerg } else if (CanHaveEnumBase || !ColonIsSacred) {
4554*e038c9c4Sjoerg SourceLocation ColonLoc = ConsumeToken();
45557330f729Sjoerg
4556*e038c9c4Sjoerg // Parse a type-specifier-seq as a type. We can't just ParseTypeName here,
4557*e038c9c4Sjoerg // because under -fms-extensions,
4558*e038c9c4Sjoerg // enum E : int *p;
4559*e038c9c4Sjoerg // declares 'enum E : int; E *p;' not 'enum E : int*; E p;'.
4560*e038c9c4Sjoerg DeclSpec DS(AttrFactory);
4561*e038c9c4Sjoerg ParseSpecifierQualifierList(DS, AS, DeclSpecContext::DSC_type_specifier);
4562*e038c9c4Sjoerg Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName);
4563*e038c9c4Sjoerg BaseType = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
45647330f729Sjoerg
4565*e038c9c4Sjoerg BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());
45667330f729Sjoerg
45677330f729Sjoerg if (!getLangOpts().ObjC) {
45687330f729Sjoerg if (getLangOpts().CPlusPlus11)
4569*e038c9c4Sjoerg Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)
4570*e038c9c4Sjoerg << BaseRange;
45717330f729Sjoerg else if (getLangOpts().CPlusPlus)
4572*e038c9c4Sjoerg Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)
4573*e038c9c4Sjoerg << BaseRange;
45747330f729Sjoerg else if (getLangOpts().MicrosoftExt)
4575*e038c9c4Sjoerg Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)
4576*e038c9c4Sjoerg << BaseRange;
45777330f729Sjoerg else
4578*e038c9c4Sjoerg Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)
4579*e038c9c4Sjoerg << BaseRange;
45807330f729Sjoerg }
45817330f729Sjoerg }
45827330f729Sjoerg }
45837330f729Sjoerg
45847330f729Sjoerg // There are four options here. If we have 'friend enum foo;' then this is a
45857330f729Sjoerg // friend declaration, and cannot have an accompanying definition. If we have
45867330f729Sjoerg // 'enum foo;', then this is a forward declaration. If we have
45877330f729Sjoerg // 'enum foo {...' then this is a definition. Otherwise we have something
45887330f729Sjoerg // like 'enum foo xyz', a reference.
45897330f729Sjoerg //
45907330f729Sjoerg // This is needed to handle stuff like this right (C99 6.7.2.3p11):
45917330f729Sjoerg // enum foo {..}; void bar() { enum foo; } <- new foo in bar.
45927330f729Sjoerg // enum foo {..}; void bar() { enum foo x; } <- use of old foo.
45937330f729Sjoerg //
45947330f729Sjoerg Sema::TagUseKind TUK;
4595*e038c9c4Sjoerg if (AllowEnumSpecifier == AllowDefiningTypeSpec::No)
45967330f729Sjoerg TUK = Sema::TUK_Reference;
4597*e038c9c4Sjoerg else if (Tok.is(tok::l_brace)) {
45987330f729Sjoerg if (DS.isFriendSpecified()) {
45997330f729Sjoerg Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
46007330f729Sjoerg << SourceRange(DS.getFriendSpecLoc());
46017330f729Sjoerg ConsumeBrace();
46027330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi);
4603*e038c9c4Sjoerg // Discard any other definition-only pieces.
4604*e038c9c4Sjoerg attrs.clear();
4605*e038c9c4Sjoerg ScopedEnumKWLoc = SourceLocation();
4606*e038c9c4Sjoerg IsScopedUsingClassTag = false;
4607*e038c9c4Sjoerg BaseType = TypeResult();
46087330f729Sjoerg TUK = Sema::TUK_Friend;
46097330f729Sjoerg } else {
46107330f729Sjoerg TUK = Sema::TUK_Definition;
46117330f729Sjoerg }
46127330f729Sjoerg } else if (!isTypeSpecifier(DSC) &&
46137330f729Sjoerg (Tok.is(tok::semi) ||
46147330f729Sjoerg (Tok.isAtStartOfLine() &&
46157330f729Sjoerg !isValidAfterTypeSpecifier(CanBeBitfield)))) {
4616*e038c9c4Sjoerg // An opaque-enum-declaration is required to be standalone (no preceding or
4617*e038c9c4Sjoerg // following tokens in the declaration). Sema enforces this separately by
4618*e038c9c4Sjoerg // diagnosing anything else in the DeclSpec.
46197330f729Sjoerg TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
46207330f729Sjoerg if (Tok.isNot(tok::semi)) {
46217330f729Sjoerg // A semicolon was missing after this declaration. Diagnose and recover.
46227330f729Sjoerg ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
46237330f729Sjoerg PP.EnterToken(Tok, /*IsReinject=*/true);
46247330f729Sjoerg Tok.setKind(tok::semi);
46257330f729Sjoerg }
46267330f729Sjoerg } else {
46277330f729Sjoerg TUK = Sema::TUK_Reference;
46287330f729Sjoerg }
46297330f729Sjoerg
4630*e038c9c4Sjoerg bool IsElaboratedTypeSpecifier =
4631*e038c9c4Sjoerg TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend;
4632*e038c9c4Sjoerg
4633*e038c9c4Sjoerg // If this is an elaborated type specifier nested in a larger declaration,
4634*e038c9c4Sjoerg // and we delayed diagnostics before, just merge them into the current pool.
46357330f729Sjoerg if (TUK == Sema::TUK_Reference && shouldDelayDiagsInTag) {
46367330f729Sjoerg diagsFromTag.redelay();
46377330f729Sjoerg }
46387330f729Sjoerg
46397330f729Sjoerg MultiTemplateParamsArg TParams;
46407330f729Sjoerg if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
46417330f729Sjoerg TUK != Sema::TUK_Reference) {
46427330f729Sjoerg if (!getLangOpts().CPlusPlus11 || !SS.isSet()) {
46437330f729Sjoerg // Skip the rest of this declarator, up until the comma or semicolon.
46447330f729Sjoerg Diag(Tok, diag::err_enum_template);
46457330f729Sjoerg SkipUntil(tok::comma, StopAtSemi);
46467330f729Sjoerg return;
46477330f729Sjoerg }
46487330f729Sjoerg
46497330f729Sjoerg if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
46507330f729Sjoerg // Enumerations can't be explicitly instantiated.
46517330f729Sjoerg DS.SetTypeSpecError();
46527330f729Sjoerg Diag(StartLoc, diag::err_explicit_instantiation_enum);
46537330f729Sjoerg return;
46547330f729Sjoerg }
46557330f729Sjoerg
46567330f729Sjoerg assert(TemplateInfo.TemplateParams && "no template parameters");
46577330f729Sjoerg TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(),
46587330f729Sjoerg TemplateInfo.TemplateParams->size());
46597330f729Sjoerg }
46607330f729Sjoerg
46617330f729Sjoerg if (!Name && TUK != Sema::TUK_Definition) {
46627330f729Sjoerg Diag(Tok, diag::err_enumerator_unnamed_no_def);
46637330f729Sjoerg
46647330f729Sjoerg // Skip the rest of this declarator, up until the comma or semicolon.
46657330f729Sjoerg SkipUntil(tok::comma, StopAtSemi);
46667330f729Sjoerg return;
46677330f729Sjoerg }
46687330f729Sjoerg
4669*e038c9c4Sjoerg // An elaborated-type-specifier has a much more constrained grammar:
4670*e038c9c4Sjoerg //
4671*e038c9c4Sjoerg // 'enum' nested-name-specifier[opt] identifier
4672*e038c9c4Sjoerg //
4673*e038c9c4Sjoerg // If we parsed any other bits, reject them now.
4674*e038c9c4Sjoerg //
4675*e038c9c4Sjoerg // MSVC and (for now at least) Objective-C permit a full enum-specifier
4676*e038c9c4Sjoerg // or opaque-enum-declaration anywhere.
4677*e038c9c4Sjoerg if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt &&
4678*e038c9c4Sjoerg !getLangOpts().ObjC) {
4679*e038c9c4Sjoerg ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
4680*e038c9c4Sjoerg /*DiagnoseEmptyAttrs=*/true);
4681*e038c9c4Sjoerg if (BaseType.isUsable())
4682*e038c9c4Sjoerg Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier)
4683*e038c9c4Sjoerg << (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange;
4684*e038c9c4Sjoerg else if (ScopedEnumKWLoc.isValid())
4685*e038c9c4Sjoerg Diag(ScopedEnumKWLoc, diag::ext_elaborated_enum_class)
4686*e038c9c4Sjoerg << FixItHint::CreateRemoval(ScopedEnumKWLoc) << IsScopedUsingClassTag;
4687*e038c9c4Sjoerg }
4688*e038c9c4Sjoerg
46897330f729Sjoerg stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
46907330f729Sjoerg
46917330f729Sjoerg Sema::SkipBodyInfo SkipBody;
46927330f729Sjoerg if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) &&
46937330f729Sjoerg NextToken().is(tok::identifier))
46947330f729Sjoerg SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(),
46957330f729Sjoerg NextToken().getIdentifierInfo(),
46967330f729Sjoerg NextToken().getLocation());
46977330f729Sjoerg
46987330f729Sjoerg bool Owned = false;
46997330f729Sjoerg bool IsDependent = false;
47007330f729Sjoerg const char *PrevSpec = nullptr;
47017330f729Sjoerg unsigned DiagID;
47027330f729Sjoerg Decl *TagDecl = Actions.ActOnTag(
47037330f729Sjoerg getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc,
47047330f729Sjoerg attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,
47057330f729Sjoerg ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType,
47067330f729Sjoerg DSC == DeclSpecContext::DSC_type_specifier,
47077330f729Sjoerg DSC == DeclSpecContext::DSC_template_param ||
47087330f729Sjoerg DSC == DeclSpecContext::DSC_template_type_arg,
47097330f729Sjoerg &SkipBody);
47107330f729Sjoerg
47117330f729Sjoerg if (SkipBody.ShouldSkip) {
47127330f729Sjoerg assert(TUK == Sema::TUK_Definition && "can only skip a definition");
47137330f729Sjoerg
47147330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_brace);
47157330f729Sjoerg T.consumeOpen();
47167330f729Sjoerg T.skipToEnd();
47177330f729Sjoerg
47187330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
47197330f729Sjoerg NameLoc.isValid() ? NameLoc : StartLoc,
47207330f729Sjoerg PrevSpec, DiagID, TagDecl, Owned,
47217330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
47227330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
47237330f729Sjoerg return;
47247330f729Sjoerg }
47257330f729Sjoerg
47267330f729Sjoerg if (IsDependent) {
47277330f729Sjoerg // This enum has a dependent nested-name-specifier. Handle it as a
47287330f729Sjoerg // dependent tag.
47297330f729Sjoerg if (!Name) {
47307330f729Sjoerg DS.SetTypeSpecError();
47317330f729Sjoerg Diag(Tok, diag::err_expected_type_name_after_typename);
47327330f729Sjoerg return;
47337330f729Sjoerg }
47347330f729Sjoerg
47357330f729Sjoerg TypeResult Type = Actions.ActOnDependentTag(
47367330f729Sjoerg getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc);
47377330f729Sjoerg if (Type.isInvalid()) {
47387330f729Sjoerg DS.SetTypeSpecError();
47397330f729Sjoerg return;
47407330f729Sjoerg }
47417330f729Sjoerg
47427330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
47437330f729Sjoerg NameLoc.isValid() ? NameLoc : StartLoc,
47447330f729Sjoerg PrevSpec, DiagID, Type.get(),
47457330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
47467330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
47477330f729Sjoerg
47487330f729Sjoerg return;
47497330f729Sjoerg }
47507330f729Sjoerg
47517330f729Sjoerg if (!TagDecl) {
47527330f729Sjoerg // The action failed to produce an enumeration tag. If this is a
47537330f729Sjoerg // definition, consume the entire definition.
47547330f729Sjoerg if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
47557330f729Sjoerg ConsumeBrace();
47567330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi);
47577330f729Sjoerg }
47587330f729Sjoerg
47597330f729Sjoerg DS.SetTypeSpecError();
47607330f729Sjoerg return;
47617330f729Sjoerg }
47627330f729Sjoerg
4763*e038c9c4Sjoerg if (Tok.is(tok::l_brace) && TUK == Sema::TUK_Definition) {
47647330f729Sjoerg Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl;
47657330f729Sjoerg ParseEnumBody(StartLoc, D);
47667330f729Sjoerg if (SkipBody.CheckSameAsPrevious &&
47677330f729Sjoerg !Actions.ActOnDuplicateDefinition(DS, TagDecl, SkipBody)) {
47687330f729Sjoerg DS.SetTypeSpecError();
47697330f729Sjoerg return;
47707330f729Sjoerg }
47717330f729Sjoerg }
47727330f729Sjoerg
47737330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
47747330f729Sjoerg NameLoc.isValid() ? NameLoc : StartLoc,
47757330f729Sjoerg PrevSpec, DiagID, TagDecl, Owned,
47767330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
47777330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
47787330f729Sjoerg }
47797330f729Sjoerg
47807330f729Sjoerg /// ParseEnumBody - Parse a {} enclosed enumerator-list.
47817330f729Sjoerg /// enumerator-list:
47827330f729Sjoerg /// enumerator
47837330f729Sjoerg /// enumerator-list ',' enumerator
47847330f729Sjoerg /// enumerator:
47857330f729Sjoerg /// enumeration-constant attributes[opt]
47867330f729Sjoerg /// enumeration-constant attributes[opt] '=' constant-expression
47877330f729Sjoerg /// enumeration-constant:
47887330f729Sjoerg /// identifier
47897330f729Sjoerg ///
ParseEnumBody(SourceLocation StartLoc,Decl * EnumDecl)47907330f729Sjoerg void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
47917330f729Sjoerg // Enter the scope of the enum body and start the definition.
47927330f729Sjoerg ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope);
47937330f729Sjoerg Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
47947330f729Sjoerg
47957330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_brace);
47967330f729Sjoerg T.consumeOpen();
47977330f729Sjoerg
47987330f729Sjoerg // C does not allow an empty enumerator-list, C++ does [dcl.enum].
47997330f729Sjoerg if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)
48007330f729Sjoerg Diag(Tok, diag::err_empty_enum);
48017330f729Sjoerg
48027330f729Sjoerg SmallVector<Decl *, 32> EnumConstantDecls;
48037330f729Sjoerg SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
48047330f729Sjoerg
48057330f729Sjoerg Decl *LastEnumConstDecl = nullptr;
48067330f729Sjoerg
48077330f729Sjoerg // Parse the enumerator-list.
48087330f729Sjoerg while (Tok.isNot(tok::r_brace)) {
48097330f729Sjoerg // Parse enumerator. If failed, try skipping till the start of the next
48107330f729Sjoerg // enumerator definition.
48117330f729Sjoerg if (Tok.isNot(tok::identifier)) {
48127330f729Sjoerg Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
48137330f729Sjoerg if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&
48147330f729Sjoerg TryConsumeToken(tok::comma))
48157330f729Sjoerg continue;
48167330f729Sjoerg break;
48177330f729Sjoerg }
48187330f729Sjoerg IdentifierInfo *Ident = Tok.getIdentifierInfo();
48197330f729Sjoerg SourceLocation IdentLoc = ConsumeToken();
48207330f729Sjoerg
48217330f729Sjoerg // If attributes exist after the enumerator, parse them.
48227330f729Sjoerg ParsedAttributesWithRange attrs(AttrFactory);
48237330f729Sjoerg MaybeParseGNUAttributes(attrs);
48247330f729Sjoerg if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
48257330f729Sjoerg if (getLangOpts().CPlusPlus)
48267330f729Sjoerg Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
48277330f729Sjoerg ? diag::warn_cxx14_compat_ns_enum_attribute
48287330f729Sjoerg : diag::ext_ns_enum_attribute)
48297330f729Sjoerg << 1 /*enumerator*/;
48307330f729Sjoerg ParseCXX11Attributes(attrs);
48317330f729Sjoerg }
48327330f729Sjoerg
48337330f729Sjoerg SourceLocation EqualLoc;
48347330f729Sjoerg ExprResult AssignedVal;
48357330f729Sjoerg EnumAvailabilityDiags.emplace_back(*this);
48367330f729Sjoerg
48377330f729Sjoerg EnterExpressionEvaluationContext ConstantEvaluated(
48387330f729Sjoerg Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
48397330f729Sjoerg if (TryConsumeToken(tok::equal, EqualLoc)) {
48407330f729Sjoerg AssignedVal = ParseConstantExpressionInExprEvalContext();
48417330f729Sjoerg if (AssignedVal.isInvalid())
48427330f729Sjoerg SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
48437330f729Sjoerg }
48447330f729Sjoerg
48457330f729Sjoerg // Install the enumerator constant into EnumDecl.
48467330f729Sjoerg Decl *EnumConstDecl = Actions.ActOnEnumConstant(
48477330f729Sjoerg getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs,
48487330f729Sjoerg EqualLoc, AssignedVal.get());
48497330f729Sjoerg EnumAvailabilityDiags.back().done();
48507330f729Sjoerg
48517330f729Sjoerg EnumConstantDecls.push_back(EnumConstDecl);
48527330f729Sjoerg LastEnumConstDecl = EnumConstDecl;
48537330f729Sjoerg
48547330f729Sjoerg if (Tok.is(tok::identifier)) {
48557330f729Sjoerg // We're missing a comma between enumerators.
48567330f729Sjoerg SourceLocation Loc = getEndOfPreviousToken();
48577330f729Sjoerg Diag(Loc, diag::err_enumerator_list_missing_comma)
48587330f729Sjoerg << FixItHint::CreateInsertion(Loc, ", ");
48597330f729Sjoerg continue;
48607330f729Sjoerg }
48617330f729Sjoerg
48627330f729Sjoerg // Emumerator definition must be finished, only comma or r_brace are
48637330f729Sjoerg // allowed here.
48647330f729Sjoerg SourceLocation CommaLoc;
48657330f729Sjoerg if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {
48667330f729Sjoerg if (EqualLoc.isValid())
48677330f729Sjoerg Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace
48687330f729Sjoerg << tok::comma;
48697330f729Sjoerg else
48707330f729Sjoerg Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);
48717330f729Sjoerg if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {
48727330f729Sjoerg if (TryConsumeToken(tok::comma, CommaLoc))
48737330f729Sjoerg continue;
48747330f729Sjoerg } else {
48757330f729Sjoerg break;
48767330f729Sjoerg }
48777330f729Sjoerg }
48787330f729Sjoerg
48797330f729Sjoerg // If comma is followed by r_brace, emit appropriate warning.
48807330f729Sjoerg if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {
48817330f729Sjoerg if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
48827330f729Sjoerg Diag(CommaLoc, getLangOpts().CPlusPlus ?
48837330f729Sjoerg diag::ext_enumerator_list_comma_cxx :
48847330f729Sjoerg diag::ext_enumerator_list_comma_c)
48857330f729Sjoerg << FixItHint::CreateRemoval(CommaLoc);
48867330f729Sjoerg else if (getLangOpts().CPlusPlus11)
48877330f729Sjoerg Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
48887330f729Sjoerg << FixItHint::CreateRemoval(CommaLoc);
48897330f729Sjoerg break;
48907330f729Sjoerg }
48917330f729Sjoerg }
48927330f729Sjoerg
48937330f729Sjoerg // Eat the }.
48947330f729Sjoerg T.consumeClose();
48957330f729Sjoerg
48967330f729Sjoerg // If attributes exist after the identifier list, parse them.
48977330f729Sjoerg ParsedAttributes attrs(AttrFactory);
48987330f729Sjoerg MaybeParseGNUAttributes(attrs);
48997330f729Sjoerg
49007330f729Sjoerg Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls,
49017330f729Sjoerg getCurScope(), attrs);
49027330f729Sjoerg
49037330f729Sjoerg // Now handle enum constant availability diagnostics.
49047330f729Sjoerg assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());
49057330f729Sjoerg for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) {
49067330f729Sjoerg ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
49077330f729Sjoerg EnumAvailabilityDiags[i].redelay();
49087330f729Sjoerg PD.complete(EnumConstantDecls[i]);
49097330f729Sjoerg }
49107330f729Sjoerg
49117330f729Sjoerg EnumScope.Exit();
49127330f729Sjoerg Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getRange());
49137330f729Sjoerg
49147330f729Sjoerg // The next token must be valid after an enum definition. If not, a ';'
49157330f729Sjoerg // was probably forgotten.
49167330f729Sjoerg bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
49177330f729Sjoerg if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
49187330f729Sjoerg ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
49197330f729Sjoerg // Push this token back into the preprocessor and change our current token
49207330f729Sjoerg // to ';' so that the rest of the code recovers as though there were an
49217330f729Sjoerg // ';' after the definition.
49227330f729Sjoerg PP.EnterToken(Tok, /*IsReinject=*/true);
49237330f729Sjoerg Tok.setKind(tok::semi);
49247330f729Sjoerg }
49257330f729Sjoerg }
49267330f729Sjoerg
49277330f729Sjoerg /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
49287330f729Sjoerg /// is definitely a type-specifier. Return false if it isn't part of a type
49297330f729Sjoerg /// specifier or if we're not sure.
isKnownToBeTypeSpecifier(const Token & Tok) const49307330f729Sjoerg bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
49317330f729Sjoerg switch (Tok.getKind()) {
49327330f729Sjoerg default: return false;
49337330f729Sjoerg // type-specifiers
49347330f729Sjoerg case tok::kw_short:
49357330f729Sjoerg case tok::kw_long:
49367330f729Sjoerg case tok::kw___int64:
49377330f729Sjoerg case tok::kw___int128:
49387330f729Sjoerg case tok::kw_signed:
49397330f729Sjoerg case tok::kw_unsigned:
49407330f729Sjoerg case tok::kw__Complex:
49417330f729Sjoerg case tok::kw__Imaginary:
49427330f729Sjoerg case tok::kw_void:
49437330f729Sjoerg case tok::kw_char:
49447330f729Sjoerg case tok::kw_wchar_t:
49457330f729Sjoerg case tok::kw_char8_t:
49467330f729Sjoerg case tok::kw_char16_t:
49477330f729Sjoerg case tok::kw_char32_t:
49487330f729Sjoerg case tok::kw_int:
4949*e038c9c4Sjoerg case tok::kw__ExtInt:
4950*e038c9c4Sjoerg case tok::kw___bf16:
49517330f729Sjoerg case tok::kw_half:
49527330f729Sjoerg case tok::kw_float:
49537330f729Sjoerg case tok::kw_double:
49547330f729Sjoerg case tok::kw__Accum:
49557330f729Sjoerg case tok::kw__Fract:
49567330f729Sjoerg case tok::kw__Float16:
49577330f729Sjoerg case tok::kw___float128:
49587330f729Sjoerg case tok::kw_bool:
49597330f729Sjoerg case tok::kw__Bool:
49607330f729Sjoerg case tok::kw__Decimal32:
49617330f729Sjoerg case tok::kw__Decimal64:
49627330f729Sjoerg case tok::kw__Decimal128:
49637330f729Sjoerg case tok::kw___vector:
49647330f729Sjoerg #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
49657330f729Sjoerg #include "clang/Basic/OpenCLImageTypes.def"
49667330f729Sjoerg
49677330f729Sjoerg // struct-or-union-specifier (C99) or class-specifier (C++)
49687330f729Sjoerg case tok::kw_class:
49697330f729Sjoerg case tok::kw_struct:
49707330f729Sjoerg case tok::kw___interface:
49717330f729Sjoerg case tok::kw_union:
49727330f729Sjoerg // enum-specifier
49737330f729Sjoerg case tok::kw_enum:
49747330f729Sjoerg
49757330f729Sjoerg // typedef-name
49767330f729Sjoerg case tok::annot_typename:
49777330f729Sjoerg return true;
49787330f729Sjoerg }
49797330f729Sjoerg }
49807330f729Sjoerg
49817330f729Sjoerg /// isTypeSpecifierQualifier - Return true if the current token could be the
49827330f729Sjoerg /// start of a specifier-qualifier-list.
isTypeSpecifierQualifier()49837330f729Sjoerg bool Parser::isTypeSpecifierQualifier() {
49847330f729Sjoerg switch (Tok.getKind()) {
49857330f729Sjoerg default: return false;
49867330f729Sjoerg
49877330f729Sjoerg case tok::identifier: // foo::bar
49887330f729Sjoerg if (TryAltiVecVectorToken())
49897330f729Sjoerg return true;
49907330f729Sjoerg LLVM_FALLTHROUGH;
49917330f729Sjoerg case tok::kw_typename: // typename T::type
49927330f729Sjoerg // Annotate typenames and C++ scope specifiers. If we get one, just
49937330f729Sjoerg // recurse to handle whatever we get.
49947330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
49957330f729Sjoerg return true;
49967330f729Sjoerg if (Tok.is(tok::identifier))
49977330f729Sjoerg return false;
49987330f729Sjoerg return isTypeSpecifierQualifier();
49997330f729Sjoerg
50007330f729Sjoerg case tok::coloncolon: // ::foo::bar
50017330f729Sjoerg if (NextToken().is(tok::kw_new) || // ::new
50027330f729Sjoerg NextToken().is(tok::kw_delete)) // ::delete
50037330f729Sjoerg return false;
50047330f729Sjoerg
50057330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
50067330f729Sjoerg return true;
50077330f729Sjoerg return isTypeSpecifierQualifier();
50087330f729Sjoerg
50097330f729Sjoerg // GNU attributes support.
50107330f729Sjoerg case tok::kw___attribute:
50117330f729Sjoerg // GNU typeof support.
50127330f729Sjoerg case tok::kw_typeof:
50137330f729Sjoerg
50147330f729Sjoerg // type-specifiers
50157330f729Sjoerg case tok::kw_short:
50167330f729Sjoerg case tok::kw_long:
50177330f729Sjoerg case tok::kw___int64:
50187330f729Sjoerg case tok::kw___int128:
50197330f729Sjoerg case tok::kw_signed:
50207330f729Sjoerg case tok::kw_unsigned:
50217330f729Sjoerg case tok::kw__Complex:
50227330f729Sjoerg case tok::kw__Imaginary:
50237330f729Sjoerg case tok::kw_void:
50247330f729Sjoerg case tok::kw_char:
50257330f729Sjoerg case tok::kw_wchar_t:
50267330f729Sjoerg case tok::kw_char8_t:
50277330f729Sjoerg case tok::kw_char16_t:
50287330f729Sjoerg case tok::kw_char32_t:
50297330f729Sjoerg case tok::kw_int:
5030*e038c9c4Sjoerg case tok::kw__ExtInt:
50317330f729Sjoerg case tok::kw_half:
5032*e038c9c4Sjoerg case tok::kw___bf16:
50337330f729Sjoerg case tok::kw_float:
50347330f729Sjoerg case tok::kw_double:
50357330f729Sjoerg case tok::kw__Accum:
50367330f729Sjoerg case tok::kw__Fract:
50377330f729Sjoerg case tok::kw__Float16:
50387330f729Sjoerg case tok::kw___float128:
50397330f729Sjoerg case tok::kw_bool:
50407330f729Sjoerg case tok::kw__Bool:
50417330f729Sjoerg case tok::kw__Decimal32:
50427330f729Sjoerg case tok::kw__Decimal64:
50437330f729Sjoerg case tok::kw__Decimal128:
50447330f729Sjoerg case tok::kw___vector:
50457330f729Sjoerg #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
50467330f729Sjoerg #include "clang/Basic/OpenCLImageTypes.def"
50477330f729Sjoerg
50487330f729Sjoerg // struct-or-union-specifier (C99) or class-specifier (C++)
50497330f729Sjoerg case tok::kw_class:
50507330f729Sjoerg case tok::kw_struct:
50517330f729Sjoerg case tok::kw___interface:
50527330f729Sjoerg case tok::kw_union:
50537330f729Sjoerg // enum-specifier
50547330f729Sjoerg case tok::kw_enum:
50557330f729Sjoerg
50567330f729Sjoerg // type-qualifier
50577330f729Sjoerg case tok::kw_const:
50587330f729Sjoerg case tok::kw_volatile:
50597330f729Sjoerg case tok::kw_restrict:
50607330f729Sjoerg case tok::kw__Sat:
50617330f729Sjoerg
50627330f729Sjoerg // Debugger support.
50637330f729Sjoerg case tok::kw___unknown_anytype:
50647330f729Sjoerg
50657330f729Sjoerg // typedef-name
50667330f729Sjoerg case tok::annot_typename:
50677330f729Sjoerg return true;
50687330f729Sjoerg
50697330f729Sjoerg // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
50707330f729Sjoerg case tok::less:
50717330f729Sjoerg return getLangOpts().ObjC;
50727330f729Sjoerg
50737330f729Sjoerg case tok::kw___cdecl:
50747330f729Sjoerg case tok::kw___stdcall:
50757330f729Sjoerg case tok::kw___fastcall:
50767330f729Sjoerg case tok::kw___thiscall:
50777330f729Sjoerg case tok::kw___regcall:
50787330f729Sjoerg case tok::kw___vectorcall:
50797330f729Sjoerg case tok::kw___w64:
50807330f729Sjoerg case tok::kw___ptr64:
50817330f729Sjoerg case tok::kw___ptr32:
50827330f729Sjoerg case tok::kw___pascal:
50837330f729Sjoerg case tok::kw___unaligned:
50847330f729Sjoerg
50857330f729Sjoerg case tok::kw__Nonnull:
50867330f729Sjoerg case tok::kw__Nullable:
5087*e038c9c4Sjoerg case tok::kw__Nullable_result:
50887330f729Sjoerg case tok::kw__Null_unspecified:
50897330f729Sjoerg
50907330f729Sjoerg case tok::kw___kindof:
50917330f729Sjoerg
50927330f729Sjoerg case tok::kw___private:
50937330f729Sjoerg case tok::kw___local:
50947330f729Sjoerg case tok::kw___global:
50957330f729Sjoerg case tok::kw___constant:
50967330f729Sjoerg case tok::kw___generic:
50977330f729Sjoerg case tok::kw___read_only:
50987330f729Sjoerg case tok::kw___read_write:
50997330f729Sjoerg case tok::kw___write_only:
51007330f729Sjoerg return true;
51017330f729Sjoerg
51027330f729Sjoerg case tok::kw_private:
51037330f729Sjoerg return getLangOpts().OpenCL;
51047330f729Sjoerg
51057330f729Sjoerg // C11 _Atomic
51067330f729Sjoerg case tok::kw__Atomic:
51077330f729Sjoerg return true;
51087330f729Sjoerg }
51097330f729Sjoerg }
51107330f729Sjoerg
51117330f729Sjoerg /// isDeclarationSpecifier() - Return true if the current token is part of a
51127330f729Sjoerg /// declaration specifier.
51137330f729Sjoerg ///
51147330f729Sjoerg /// \param DisambiguatingWithExpression True to indicate that the purpose of
51157330f729Sjoerg /// this check is to disambiguate between an expression and a declaration.
isDeclarationSpecifier(bool DisambiguatingWithExpression)51167330f729Sjoerg bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
51177330f729Sjoerg switch (Tok.getKind()) {
51187330f729Sjoerg default: return false;
51197330f729Sjoerg
51207330f729Sjoerg case tok::kw_pipe:
5121*e038c9c4Sjoerg return getLangOpts().OpenCLPipe;
51227330f729Sjoerg
51237330f729Sjoerg case tok::identifier: // foo::bar
51247330f729Sjoerg // Unfortunate hack to support "Class.factoryMethod" notation.
51257330f729Sjoerg if (getLangOpts().ObjC && NextToken().is(tok::period))
51267330f729Sjoerg return false;
51277330f729Sjoerg if (TryAltiVecVectorToken())
51287330f729Sjoerg return true;
51297330f729Sjoerg LLVM_FALLTHROUGH;
51307330f729Sjoerg case tok::kw_decltype: // decltype(T())::type
51317330f729Sjoerg case tok::kw_typename: // typename T::type
51327330f729Sjoerg // Annotate typenames and C++ scope specifiers. If we get one, just
51337330f729Sjoerg // recurse to handle whatever we get.
51347330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
51357330f729Sjoerg return true;
5136*e038c9c4Sjoerg if (TryAnnotateTypeConstraint())
5137*e038c9c4Sjoerg return true;
51387330f729Sjoerg if (Tok.is(tok::identifier))
51397330f729Sjoerg return false;
51407330f729Sjoerg
51417330f729Sjoerg // If we're in Objective-C and we have an Objective-C class type followed
51427330f729Sjoerg // by an identifier and then either ':' or ']', in a place where an
51437330f729Sjoerg // expression is permitted, then this is probably a class message send
51447330f729Sjoerg // missing the initial '['. In this case, we won't consider this to be
51457330f729Sjoerg // the start of a declaration.
51467330f729Sjoerg if (DisambiguatingWithExpression &&
51477330f729Sjoerg isStartOfObjCClassMessageMissingOpenBracket())
51487330f729Sjoerg return false;
51497330f729Sjoerg
51507330f729Sjoerg return isDeclarationSpecifier();
51517330f729Sjoerg
51527330f729Sjoerg case tok::coloncolon: // ::foo::bar
51537330f729Sjoerg if (NextToken().is(tok::kw_new) || // ::new
51547330f729Sjoerg NextToken().is(tok::kw_delete)) // ::delete
51557330f729Sjoerg return false;
51567330f729Sjoerg
51577330f729Sjoerg // Annotate typenames and C++ scope specifiers. If we get one, just
51587330f729Sjoerg // recurse to handle whatever we get.
51597330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
51607330f729Sjoerg return true;
51617330f729Sjoerg return isDeclarationSpecifier();
51627330f729Sjoerg
51637330f729Sjoerg // storage-class-specifier
51647330f729Sjoerg case tok::kw_typedef:
51657330f729Sjoerg case tok::kw_extern:
51667330f729Sjoerg case tok::kw___private_extern__:
51677330f729Sjoerg case tok::kw_static:
51687330f729Sjoerg case tok::kw_auto:
51697330f729Sjoerg case tok::kw___auto_type:
51707330f729Sjoerg case tok::kw_register:
51717330f729Sjoerg case tok::kw___thread:
51727330f729Sjoerg case tok::kw_thread_local:
51737330f729Sjoerg case tok::kw__Thread_local:
51747330f729Sjoerg
51757330f729Sjoerg // Modules
51767330f729Sjoerg case tok::kw___module_private__:
51777330f729Sjoerg
51787330f729Sjoerg // Debugger support
51797330f729Sjoerg case tok::kw___unknown_anytype:
51807330f729Sjoerg
51817330f729Sjoerg // type-specifiers
51827330f729Sjoerg case tok::kw_short:
51837330f729Sjoerg case tok::kw_long:
51847330f729Sjoerg case tok::kw___int64:
51857330f729Sjoerg case tok::kw___int128:
51867330f729Sjoerg case tok::kw_signed:
51877330f729Sjoerg case tok::kw_unsigned:
51887330f729Sjoerg case tok::kw__Complex:
51897330f729Sjoerg case tok::kw__Imaginary:
51907330f729Sjoerg case tok::kw_void:
51917330f729Sjoerg case tok::kw_char:
51927330f729Sjoerg case tok::kw_wchar_t:
51937330f729Sjoerg case tok::kw_char8_t:
51947330f729Sjoerg case tok::kw_char16_t:
51957330f729Sjoerg case tok::kw_char32_t:
51967330f729Sjoerg
51977330f729Sjoerg case tok::kw_int:
5198*e038c9c4Sjoerg case tok::kw__ExtInt:
51997330f729Sjoerg case tok::kw_half:
5200*e038c9c4Sjoerg case tok::kw___bf16:
52017330f729Sjoerg case tok::kw_float:
52027330f729Sjoerg case tok::kw_double:
52037330f729Sjoerg case tok::kw__Accum:
52047330f729Sjoerg case tok::kw__Fract:
52057330f729Sjoerg case tok::kw__Float16:
52067330f729Sjoerg case tok::kw___float128:
52077330f729Sjoerg case tok::kw_bool:
52087330f729Sjoerg case tok::kw__Bool:
52097330f729Sjoerg case tok::kw__Decimal32:
52107330f729Sjoerg case tok::kw__Decimal64:
52117330f729Sjoerg case tok::kw__Decimal128:
52127330f729Sjoerg case tok::kw___vector:
52137330f729Sjoerg
52147330f729Sjoerg // struct-or-union-specifier (C99) or class-specifier (C++)
52157330f729Sjoerg case tok::kw_class:
52167330f729Sjoerg case tok::kw_struct:
52177330f729Sjoerg case tok::kw_union:
52187330f729Sjoerg case tok::kw___interface:
52197330f729Sjoerg // enum-specifier
52207330f729Sjoerg case tok::kw_enum:
52217330f729Sjoerg
52227330f729Sjoerg // type-qualifier
52237330f729Sjoerg case tok::kw_const:
52247330f729Sjoerg case tok::kw_volatile:
52257330f729Sjoerg case tok::kw_restrict:
52267330f729Sjoerg case tok::kw__Sat:
52277330f729Sjoerg
52287330f729Sjoerg // function-specifier
52297330f729Sjoerg case tok::kw_inline:
52307330f729Sjoerg case tok::kw_virtual:
52317330f729Sjoerg case tok::kw_explicit:
52327330f729Sjoerg case tok::kw__Noreturn:
52337330f729Sjoerg
52347330f729Sjoerg // alignment-specifier
52357330f729Sjoerg case tok::kw__Alignas:
52367330f729Sjoerg
52377330f729Sjoerg // friend keyword.
52387330f729Sjoerg case tok::kw_friend:
52397330f729Sjoerg
52407330f729Sjoerg // static_assert-declaration
5241*e038c9c4Sjoerg case tok::kw_static_assert:
52427330f729Sjoerg case tok::kw__Static_assert:
52437330f729Sjoerg
52447330f729Sjoerg // GNU typeof support.
52457330f729Sjoerg case tok::kw_typeof:
52467330f729Sjoerg
52477330f729Sjoerg // GNU attributes.
52487330f729Sjoerg case tok::kw___attribute:
52497330f729Sjoerg
52507330f729Sjoerg // C++11 decltype and constexpr.
52517330f729Sjoerg case tok::annot_decltype:
52527330f729Sjoerg case tok::kw_constexpr:
52537330f729Sjoerg
52547330f729Sjoerg // C++20 consteval and constinit.
52557330f729Sjoerg case tok::kw_consteval:
52567330f729Sjoerg case tok::kw_constinit:
52577330f729Sjoerg
52587330f729Sjoerg // C11 _Atomic
52597330f729Sjoerg case tok::kw__Atomic:
52607330f729Sjoerg return true;
52617330f729Sjoerg
52627330f729Sjoerg // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
52637330f729Sjoerg case tok::less:
52647330f729Sjoerg return getLangOpts().ObjC;
52657330f729Sjoerg
52667330f729Sjoerg // typedef-name
52677330f729Sjoerg case tok::annot_typename:
52687330f729Sjoerg return !DisambiguatingWithExpression ||
52697330f729Sjoerg !isStartOfObjCClassMessageMissingOpenBracket();
52707330f729Sjoerg
5271*e038c9c4Sjoerg // placeholder-type-specifier
5272*e038c9c4Sjoerg case tok::annot_template_id: {
5273*e038c9c4Sjoerg TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
5274*e038c9c4Sjoerg if (TemplateId->hasInvalidName())
5275*e038c9c4Sjoerg return true;
5276*e038c9c4Sjoerg // FIXME: What about type templates that have only been annotated as
5277*e038c9c4Sjoerg // annot_template_id, not as annot_typename?
5278*e038c9c4Sjoerg return isTypeConstraintAnnotation() &&
5279*e038c9c4Sjoerg (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));
5280*e038c9c4Sjoerg }
5281*e038c9c4Sjoerg
5282*e038c9c4Sjoerg case tok::annot_cxxscope: {
5283*e038c9c4Sjoerg TemplateIdAnnotation *TemplateId =
5284*e038c9c4Sjoerg NextToken().is(tok::annot_template_id)
5285*e038c9c4Sjoerg ? takeTemplateIdAnnotation(NextToken())
5286*e038c9c4Sjoerg : nullptr;
5287*e038c9c4Sjoerg if (TemplateId && TemplateId->hasInvalidName())
5288*e038c9c4Sjoerg return true;
5289*e038c9c4Sjoerg // FIXME: What about type templates that have only been annotated as
5290*e038c9c4Sjoerg // annot_template_id, not as annot_typename?
5291*e038c9c4Sjoerg if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())
5292*e038c9c4Sjoerg return true;
5293*e038c9c4Sjoerg return isTypeConstraintAnnotation() &&
5294*e038c9c4Sjoerg GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);
5295*e038c9c4Sjoerg }
5296*e038c9c4Sjoerg
52977330f729Sjoerg case tok::kw___declspec:
52987330f729Sjoerg case tok::kw___cdecl:
52997330f729Sjoerg case tok::kw___stdcall:
53007330f729Sjoerg case tok::kw___fastcall:
53017330f729Sjoerg case tok::kw___thiscall:
53027330f729Sjoerg case tok::kw___regcall:
53037330f729Sjoerg case tok::kw___vectorcall:
53047330f729Sjoerg case tok::kw___w64:
53057330f729Sjoerg case tok::kw___sptr:
53067330f729Sjoerg case tok::kw___uptr:
53077330f729Sjoerg case tok::kw___ptr64:
53087330f729Sjoerg case tok::kw___ptr32:
53097330f729Sjoerg case tok::kw___forceinline:
53107330f729Sjoerg case tok::kw___pascal:
53117330f729Sjoerg case tok::kw___unaligned:
53127330f729Sjoerg
53137330f729Sjoerg case tok::kw__Nonnull:
53147330f729Sjoerg case tok::kw__Nullable:
5315*e038c9c4Sjoerg case tok::kw__Nullable_result:
53167330f729Sjoerg case tok::kw__Null_unspecified:
53177330f729Sjoerg
53187330f729Sjoerg case tok::kw___kindof:
53197330f729Sjoerg
53207330f729Sjoerg case tok::kw___private:
53217330f729Sjoerg case tok::kw___local:
53227330f729Sjoerg case tok::kw___global:
53237330f729Sjoerg case tok::kw___constant:
53247330f729Sjoerg case tok::kw___generic:
53257330f729Sjoerg case tok::kw___read_only:
53267330f729Sjoerg case tok::kw___read_write:
53277330f729Sjoerg case tok::kw___write_only:
53287330f729Sjoerg #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
53297330f729Sjoerg #include "clang/Basic/OpenCLImageTypes.def"
53307330f729Sjoerg
53317330f729Sjoerg return true;
53327330f729Sjoerg
53337330f729Sjoerg case tok::kw_private:
53347330f729Sjoerg return getLangOpts().OpenCL;
53357330f729Sjoerg }
53367330f729Sjoerg }
53377330f729Sjoerg
isConstructorDeclarator(bool IsUnqualified,bool DeductionGuide)53387330f729Sjoerg bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) {
53397330f729Sjoerg TentativeParsingAction TPA(*this);
53407330f729Sjoerg
53417330f729Sjoerg // Parse the C++ scope specifier.
53427330f729Sjoerg CXXScopeSpec SS;
5343*e038c9c4Sjoerg if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
5344*e038c9c4Sjoerg /*ObjectHadErrors=*/false,
53457330f729Sjoerg /*EnteringContext=*/true)) {
53467330f729Sjoerg TPA.Revert();
53477330f729Sjoerg return false;
53487330f729Sjoerg }
53497330f729Sjoerg
53507330f729Sjoerg // Parse the constructor name.
53517330f729Sjoerg if (Tok.is(tok::identifier)) {
53527330f729Sjoerg // We already know that we have a constructor name; just consume
53537330f729Sjoerg // the token.
53547330f729Sjoerg ConsumeToken();
53557330f729Sjoerg } else if (Tok.is(tok::annot_template_id)) {
53567330f729Sjoerg ConsumeAnnotationToken();
53577330f729Sjoerg } else {
53587330f729Sjoerg TPA.Revert();
53597330f729Sjoerg return false;
53607330f729Sjoerg }
53617330f729Sjoerg
53627330f729Sjoerg // There may be attributes here, appertaining to the constructor name or type
53637330f729Sjoerg // we just stepped past.
53647330f729Sjoerg SkipCXX11Attributes();
53657330f729Sjoerg
53667330f729Sjoerg // Current class name must be followed by a left parenthesis.
53677330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
53687330f729Sjoerg TPA.Revert();
53697330f729Sjoerg return false;
53707330f729Sjoerg }
53717330f729Sjoerg ConsumeParen();
53727330f729Sjoerg
53737330f729Sjoerg // A right parenthesis, or ellipsis followed by a right parenthesis signals
53747330f729Sjoerg // that we have a constructor.
53757330f729Sjoerg if (Tok.is(tok::r_paren) ||
53767330f729Sjoerg (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) {
53777330f729Sjoerg TPA.Revert();
53787330f729Sjoerg return true;
53797330f729Sjoerg }
53807330f729Sjoerg
53817330f729Sjoerg // A C++11 attribute here signals that we have a constructor, and is an
53827330f729Sjoerg // attribute on the first constructor parameter.
53837330f729Sjoerg if (getLangOpts().CPlusPlus11 &&
53847330f729Sjoerg isCXX11AttributeSpecifier(/*Disambiguate*/ false,
53857330f729Sjoerg /*OuterMightBeMessageSend*/ true)) {
53867330f729Sjoerg TPA.Revert();
53877330f729Sjoerg return true;
53887330f729Sjoerg }
53897330f729Sjoerg
53907330f729Sjoerg // If we need to, enter the specified scope.
53917330f729Sjoerg DeclaratorScopeObj DeclScopeObj(*this, SS);
53927330f729Sjoerg if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))
53937330f729Sjoerg DeclScopeObj.EnterDeclaratorScope();
53947330f729Sjoerg
53957330f729Sjoerg // Optionally skip Microsoft attributes.
53967330f729Sjoerg ParsedAttributes Attrs(AttrFactory);
53977330f729Sjoerg MaybeParseMicrosoftAttributes(Attrs);
53987330f729Sjoerg
53997330f729Sjoerg // Check whether the next token(s) are part of a declaration
54007330f729Sjoerg // specifier, in which case we have the start of a parameter and,
54017330f729Sjoerg // therefore, we know that this is a constructor.
54027330f729Sjoerg bool IsConstructor = false;
54037330f729Sjoerg if (isDeclarationSpecifier())
54047330f729Sjoerg IsConstructor = true;
54057330f729Sjoerg else if (Tok.is(tok::identifier) ||
54067330f729Sjoerg (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) {
54077330f729Sjoerg // We've seen "C ( X" or "C ( X::Y", but "X" / "X::Y" is not a type.
54087330f729Sjoerg // This might be a parenthesized member name, but is more likely to
54097330f729Sjoerg // be a constructor declaration with an invalid argument type. Keep
54107330f729Sjoerg // looking.
54117330f729Sjoerg if (Tok.is(tok::annot_cxxscope))
54127330f729Sjoerg ConsumeAnnotationToken();
54137330f729Sjoerg ConsumeToken();
54147330f729Sjoerg
54157330f729Sjoerg // If this is not a constructor, we must be parsing a declarator,
54167330f729Sjoerg // which must have one of the following syntactic forms (see the
54177330f729Sjoerg // grammar extract at the start of ParseDirectDeclarator):
54187330f729Sjoerg switch (Tok.getKind()) {
54197330f729Sjoerg case tok::l_paren:
54207330f729Sjoerg // C(X ( int));
54217330f729Sjoerg case tok::l_square:
54227330f729Sjoerg // C(X [ 5]);
54237330f729Sjoerg // C(X [ [attribute]]);
54247330f729Sjoerg case tok::coloncolon:
54257330f729Sjoerg // C(X :: Y);
54267330f729Sjoerg // C(X :: *p);
54277330f729Sjoerg // Assume this isn't a constructor, rather than assuming it's a
54287330f729Sjoerg // constructor with an unnamed parameter of an ill-formed type.
54297330f729Sjoerg break;
54307330f729Sjoerg
54317330f729Sjoerg case tok::r_paren:
54327330f729Sjoerg // C(X )
54337330f729Sjoerg
54347330f729Sjoerg // Skip past the right-paren and any following attributes to get to
54357330f729Sjoerg // the function body or trailing-return-type.
54367330f729Sjoerg ConsumeParen();
54377330f729Sjoerg SkipCXX11Attributes();
54387330f729Sjoerg
54397330f729Sjoerg if (DeductionGuide) {
54407330f729Sjoerg // C(X) -> ... is a deduction guide.
54417330f729Sjoerg IsConstructor = Tok.is(tok::arrow);
54427330f729Sjoerg break;
54437330f729Sjoerg }
54447330f729Sjoerg if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {
54457330f729Sjoerg // Assume these were meant to be constructors:
54467330f729Sjoerg // C(X) : (the name of a bit-field cannot be parenthesized).
54477330f729Sjoerg // C(X) try (this is otherwise ill-formed).
54487330f729Sjoerg IsConstructor = true;
54497330f729Sjoerg }
54507330f729Sjoerg if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) {
54517330f729Sjoerg // If we have a constructor name within the class definition,
54527330f729Sjoerg // assume these were meant to be constructors:
54537330f729Sjoerg // C(X) {
54547330f729Sjoerg // C(X) ;
54557330f729Sjoerg // ... because otherwise we would be declaring a non-static data
54567330f729Sjoerg // member that is ill-formed because it's of the same type as its
54577330f729Sjoerg // surrounding class.
54587330f729Sjoerg //
54597330f729Sjoerg // FIXME: We can actually do this whether or not the name is qualified,
54607330f729Sjoerg // because if it is qualified in this context it must be being used as
54617330f729Sjoerg // a constructor name.
54627330f729Sjoerg // currently, so we're somewhat conservative here.
54637330f729Sjoerg IsConstructor = IsUnqualified;
54647330f729Sjoerg }
54657330f729Sjoerg break;
54667330f729Sjoerg
54677330f729Sjoerg default:
54687330f729Sjoerg IsConstructor = true;
54697330f729Sjoerg break;
54707330f729Sjoerg }
54717330f729Sjoerg }
54727330f729Sjoerg
54737330f729Sjoerg TPA.Revert();
54747330f729Sjoerg return IsConstructor;
54757330f729Sjoerg }
54767330f729Sjoerg
54777330f729Sjoerg /// ParseTypeQualifierListOpt
54787330f729Sjoerg /// type-qualifier-list: [C99 6.7.5]
54797330f729Sjoerg /// type-qualifier
54807330f729Sjoerg /// [vendor] attributes
54817330f729Sjoerg /// [ only if AttrReqs & AR_VendorAttributesParsed ]
54827330f729Sjoerg /// type-qualifier-list type-qualifier
54837330f729Sjoerg /// [vendor] type-qualifier-list attributes
54847330f729Sjoerg /// [ only if AttrReqs & AR_VendorAttributesParsed ]
54857330f729Sjoerg /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
54867330f729Sjoerg /// [ only if AttReqs & AR_CXX11AttributesParsed ]
54877330f729Sjoerg /// Note: vendor can be GNU, MS, etc and can be explicitly controlled via
54887330f729Sjoerg /// AttrRequirements bitmask values.
ParseTypeQualifierListOpt(DeclSpec & DS,unsigned AttrReqs,bool AtomicAllowed,bool IdentifierRequired,Optional<llvm::function_ref<void ()>> CodeCompletionHandler)54897330f729Sjoerg void Parser::ParseTypeQualifierListOpt(
54907330f729Sjoerg DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,
54917330f729Sjoerg bool IdentifierRequired,
54927330f729Sjoerg Optional<llvm::function_ref<void()>> CodeCompletionHandler) {
54937330f729Sjoerg if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) &&
54947330f729Sjoerg isCXX11AttributeSpecifier()) {
54957330f729Sjoerg ParsedAttributesWithRange attrs(AttrFactory);
54967330f729Sjoerg ParseCXX11Attributes(attrs);
54977330f729Sjoerg DS.takeAttributesFrom(attrs);
54987330f729Sjoerg }
54997330f729Sjoerg
55007330f729Sjoerg SourceLocation EndLoc;
55017330f729Sjoerg
55027330f729Sjoerg while (1) {
55037330f729Sjoerg bool isInvalid = false;
55047330f729Sjoerg const char *PrevSpec = nullptr;
55057330f729Sjoerg unsigned DiagID = 0;
55067330f729Sjoerg SourceLocation Loc = Tok.getLocation();
55077330f729Sjoerg
55087330f729Sjoerg switch (Tok.getKind()) {
55097330f729Sjoerg case tok::code_completion:
5510*e038c9c4Sjoerg cutOffParsing();
55117330f729Sjoerg if (CodeCompletionHandler)
55127330f729Sjoerg (*CodeCompletionHandler)();
55137330f729Sjoerg else
55147330f729Sjoerg Actions.CodeCompleteTypeQualifiers(DS);
5515*e038c9c4Sjoerg return;
55167330f729Sjoerg
55177330f729Sjoerg case tok::kw_const:
55187330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
55197330f729Sjoerg getLangOpts());
55207330f729Sjoerg break;
55217330f729Sjoerg case tok::kw_volatile:
55227330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
55237330f729Sjoerg getLangOpts());
55247330f729Sjoerg break;
55257330f729Sjoerg case tok::kw_restrict:
55267330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
55277330f729Sjoerg getLangOpts());
55287330f729Sjoerg break;
55297330f729Sjoerg case tok::kw__Atomic:
55307330f729Sjoerg if (!AtomicAllowed)
55317330f729Sjoerg goto DoneWithTypeQuals;
55327330f729Sjoerg if (!getLangOpts().C11)
55337330f729Sjoerg Diag(Tok, diag::ext_c11_feature) << Tok.getName();
55347330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
55357330f729Sjoerg getLangOpts());
55367330f729Sjoerg break;
55377330f729Sjoerg
55387330f729Sjoerg // OpenCL qualifiers:
55397330f729Sjoerg case tok::kw_private:
55407330f729Sjoerg if (!getLangOpts().OpenCL)
55417330f729Sjoerg goto DoneWithTypeQuals;
55427330f729Sjoerg LLVM_FALLTHROUGH;
55437330f729Sjoerg case tok::kw___private:
55447330f729Sjoerg case tok::kw___global:
55457330f729Sjoerg case tok::kw___local:
55467330f729Sjoerg case tok::kw___constant:
55477330f729Sjoerg case tok::kw___generic:
55487330f729Sjoerg case tok::kw___read_only:
55497330f729Sjoerg case tok::kw___write_only:
55507330f729Sjoerg case tok::kw___read_write:
55517330f729Sjoerg ParseOpenCLQualifiers(DS.getAttributes());
55527330f729Sjoerg break;
55537330f729Sjoerg
55547330f729Sjoerg case tok::kw___unaligned:
55557330f729Sjoerg isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,
55567330f729Sjoerg getLangOpts());
55577330f729Sjoerg break;
55587330f729Sjoerg case tok::kw___uptr:
55597330f729Sjoerg // GNU libc headers in C mode use '__uptr' as an identifier which conflicts
55607330f729Sjoerg // with the MS modifier keyword.
55617330f729Sjoerg if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus &&
55627330f729Sjoerg IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) {
55637330f729Sjoerg if (TryKeywordIdentFallback(false))
55647330f729Sjoerg continue;
55657330f729Sjoerg }
55667330f729Sjoerg LLVM_FALLTHROUGH;
55677330f729Sjoerg case tok::kw___sptr:
55687330f729Sjoerg case tok::kw___w64:
55697330f729Sjoerg case tok::kw___ptr64:
55707330f729Sjoerg case tok::kw___ptr32:
55717330f729Sjoerg case tok::kw___cdecl:
55727330f729Sjoerg case tok::kw___stdcall:
55737330f729Sjoerg case tok::kw___fastcall:
55747330f729Sjoerg case tok::kw___thiscall:
55757330f729Sjoerg case tok::kw___regcall:
55767330f729Sjoerg case tok::kw___vectorcall:
55777330f729Sjoerg if (AttrReqs & AR_DeclspecAttributesParsed) {
55787330f729Sjoerg ParseMicrosoftTypeAttributes(DS.getAttributes());
55797330f729Sjoerg continue;
55807330f729Sjoerg }
55817330f729Sjoerg goto DoneWithTypeQuals;
55827330f729Sjoerg case tok::kw___pascal:
55837330f729Sjoerg if (AttrReqs & AR_VendorAttributesParsed) {
55847330f729Sjoerg ParseBorlandTypeAttributes(DS.getAttributes());
55857330f729Sjoerg continue;
55867330f729Sjoerg }
55877330f729Sjoerg goto DoneWithTypeQuals;
55887330f729Sjoerg
55897330f729Sjoerg // Nullability type specifiers.
55907330f729Sjoerg case tok::kw__Nonnull:
55917330f729Sjoerg case tok::kw__Nullable:
5592*e038c9c4Sjoerg case tok::kw__Nullable_result:
55937330f729Sjoerg case tok::kw__Null_unspecified:
55947330f729Sjoerg ParseNullabilityTypeSpecifiers(DS.getAttributes());
55957330f729Sjoerg continue;
55967330f729Sjoerg
55977330f729Sjoerg // Objective-C 'kindof' types.
55987330f729Sjoerg case tok::kw___kindof:
55997330f729Sjoerg DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,
56007330f729Sjoerg nullptr, 0, ParsedAttr::AS_Keyword);
56017330f729Sjoerg (void)ConsumeToken();
56027330f729Sjoerg continue;
56037330f729Sjoerg
56047330f729Sjoerg case tok::kw___attribute:
56057330f729Sjoerg if (AttrReqs & AR_GNUAttributesParsedAndRejected)
56067330f729Sjoerg // When GNU attributes are expressly forbidden, diagnose their usage.
56077330f729Sjoerg Diag(Tok, diag::err_attributes_not_allowed);
56087330f729Sjoerg
56097330f729Sjoerg // Parse the attributes even if they are rejected to ensure that error
56107330f729Sjoerg // recovery is graceful.
56117330f729Sjoerg if (AttrReqs & AR_GNUAttributesParsed ||
56127330f729Sjoerg AttrReqs & AR_GNUAttributesParsedAndRejected) {
56137330f729Sjoerg ParseGNUAttributes(DS.getAttributes());
56147330f729Sjoerg continue; // do *not* consume the next token!
56157330f729Sjoerg }
56167330f729Sjoerg // otherwise, FALL THROUGH!
56177330f729Sjoerg LLVM_FALLTHROUGH;
56187330f729Sjoerg default:
56197330f729Sjoerg DoneWithTypeQuals:
56207330f729Sjoerg // If this is not a type-qualifier token, we're done reading type
56217330f729Sjoerg // qualifiers. First verify that DeclSpec's are consistent.
56227330f729Sjoerg DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
56237330f729Sjoerg if (EndLoc.isValid())
56247330f729Sjoerg DS.SetRangeEnd(EndLoc);
56257330f729Sjoerg return;
56267330f729Sjoerg }
56277330f729Sjoerg
56287330f729Sjoerg // If the specifier combination wasn't legal, issue a diagnostic.
56297330f729Sjoerg if (isInvalid) {
56307330f729Sjoerg assert(PrevSpec && "Method did not return previous specifier!");
56317330f729Sjoerg Diag(Tok, DiagID) << PrevSpec;
56327330f729Sjoerg }
56337330f729Sjoerg EndLoc = ConsumeToken();
56347330f729Sjoerg }
56357330f729Sjoerg }
56367330f729Sjoerg
56377330f729Sjoerg /// ParseDeclarator - Parse and verify a newly-initialized declarator.
56387330f729Sjoerg ///
ParseDeclarator(Declarator & D)56397330f729Sjoerg void Parser::ParseDeclarator(Declarator &D) {
56407330f729Sjoerg /// This implements the 'declarator' production in the C grammar, then checks
56417330f729Sjoerg /// for well-formedness and issues diagnostics.
56427330f729Sjoerg ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
56437330f729Sjoerg }
56447330f729Sjoerg
isPtrOperatorToken(tok::TokenKind Kind,const LangOptions & Lang,DeclaratorContext TheContext)56457330f729Sjoerg static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
56467330f729Sjoerg DeclaratorContext TheContext) {
56477330f729Sjoerg if (Kind == tok::star || Kind == tok::caret)
56487330f729Sjoerg return true;
56497330f729Sjoerg
5650*e038c9c4Sjoerg if (Kind == tok::kw_pipe && Lang.OpenCLPipe)
56517330f729Sjoerg return true;
56527330f729Sjoerg
56537330f729Sjoerg if (!Lang.CPlusPlus)
56547330f729Sjoerg return false;
56557330f729Sjoerg
56567330f729Sjoerg if (Kind == tok::amp)
56577330f729Sjoerg return true;
56587330f729Sjoerg
56597330f729Sjoerg // We parse rvalue refs in C++03, because otherwise the errors are scary.
56607330f729Sjoerg // But we must not parse them in conversion-type-ids and new-type-ids, since
56617330f729Sjoerg // those can be legitimately followed by a && operator.
56627330f729Sjoerg // (The same thing can in theory happen after a trailing-return-type, but
56637330f729Sjoerg // since those are a C++11 feature, there is no rejects-valid issue there.)
56647330f729Sjoerg if (Kind == tok::ampamp)
5665*e038c9c4Sjoerg return Lang.CPlusPlus11 || (TheContext != DeclaratorContext::ConversionId &&
5666*e038c9c4Sjoerg TheContext != DeclaratorContext::CXXNew);
56677330f729Sjoerg
56687330f729Sjoerg return false;
56697330f729Sjoerg }
56707330f729Sjoerg
56717330f729Sjoerg // Indicates whether the given declarator is a pipe declarator.
isPipeDeclerator(const Declarator & D)56727330f729Sjoerg static bool isPipeDeclerator(const Declarator &D) {
56737330f729Sjoerg const unsigned NumTypes = D.getNumTypeObjects();
56747330f729Sjoerg
56757330f729Sjoerg for (unsigned Idx = 0; Idx != NumTypes; ++Idx)
56767330f729Sjoerg if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)
56777330f729Sjoerg return true;
56787330f729Sjoerg
56797330f729Sjoerg return false;
56807330f729Sjoerg }
56817330f729Sjoerg
56827330f729Sjoerg /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
56837330f729Sjoerg /// is parsed by the function passed to it. Pass null, and the direct-declarator
56847330f729Sjoerg /// isn't parsed at all, making this function effectively parse the C++
56857330f729Sjoerg /// ptr-operator production.
56867330f729Sjoerg ///
56877330f729Sjoerg /// If the grammar of this construct is extended, matching changes must also be
56887330f729Sjoerg /// made to TryParseDeclarator and MightBeDeclarator, and possibly to
56897330f729Sjoerg /// isConstructorDeclarator.
56907330f729Sjoerg ///
56917330f729Sjoerg /// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]
56927330f729Sjoerg /// [C] pointer[opt] direct-declarator
56937330f729Sjoerg /// [C++] direct-declarator
56947330f729Sjoerg /// [C++] ptr-operator declarator
56957330f729Sjoerg ///
56967330f729Sjoerg /// pointer: [C99 6.7.5]
56977330f729Sjoerg /// '*' type-qualifier-list[opt]
56987330f729Sjoerg /// '*' type-qualifier-list[opt] pointer
56997330f729Sjoerg ///
57007330f729Sjoerg /// ptr-operator:
57017330f729Sjoerg /// '*' cv-qualifier-seq[opt]
57027330f729Sjoerg /// '&'
57037330f729Sjoerg /// [C++0x] '&&'
57047330f729Sjoerg /// [GNU] '&' restrict[opt] attributes[opt]
57057330f729Sjoerg /// [GNU?] '&&' restrict[opt] attributes[opt]
57067330f729Sjoerg /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
ParseDeclaratorInternal(Declarator & D,DirectDeclParseFunction DirectDeclParser)57077330f729Sjoerg void Parser::ParseDeclaratorInternal(Declarator &D,
57087330f729Sjoerg DirectDeclParseFunction DirectDeclParser) {
57097330f729Sjoerg if (Diags.hasAllExtensionsSilenced())
57107330f729Sjoerg D.setExtension();
57117330f729Sjoerg
57127330f729Sjoerg // C++ member pointers start with a '::' or a nested-name.
57137330f729Sjoerg // Member pointers get special handling, since there's no place for the
57147330f729Sjoerg // scope spec in the generic path below.
57157330f729Sjoerg if (getLangOpts().CPlusPlus &&
57167330f729Sjoerg (Tok.is(tok::coloncolon) || Tok.is(tok::kw_decltype) ||
57177330f729Sjoerg (Tok.is(tok::identifier) &&
57187330f729Sjoerg (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||
57197330f729Sjoerg Tok.is(tok::annot_cxxscope))) {
5720*e038c9c4Sjoerg bool EnteringContext = D.getContext() == DeclaratorContext::File ||
5721*e038c9c4Sjoerg D.getContext() == DeclaratorContext::Member;
57227330f729Sjoerg CXXScopeSpec SS;
5723*e038c9c4Sjoerg ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
5724*e038c9c4Sjoerg /*ObjectHadErrors=*/false, EnteringContext);
57257330f729Sjoerg
57267330f729Sjoerg if (SS.isNotEmpty()) {
57277330f729Sjoerg if (Tok.isNot(tok::star)) {
57287330f729Sjoerg // The scope spec really belongs to the direct-declarator.
57297330f729Sjoerg if (D.mayHaveIdentifier())
57307330f729Sjoerg D.getCXXScopeSpec() = SS;
57317330f729Sjoerg else
57327330f729Sjoerg AnnotateScopeToken(SS, true);
57337330f729Sjoerg
57347330f729Sjoerg if (DirectDeclParser)
57357330f729Sjoerg (this->*DirectDeclParser)(D);
57367330f729Sjoerg return;
57377330f729Sjoerg }
57387330f729Sjoerg
5739*e038c9c4Sjoerg if (SS.isValid()) {
5740*e038c9c4Sjoerg checkCompoundToken(SS.getEndLoc(), tok::coloncolon,
5741*e038c9c4Sjoerg CompoundToken::MemberPtr);
5742*e038c9c4Sjoerg }
5743*e038c9c4Sjoerg
5744*e038c9c4Sjoerg SourceLocation StarLoc = ConsumeToken();
5745*e038c9c4Sjoerg D.SetRangeEnd(StarLoc);
57467330f729Sjoerg DeclSpec DS(AttrFactory);
57477330f729Sjoerg ParseTypeQualifierListOpt(DS);
57487330f729Sjoerg D.ExtendWithDeclSpec(DS);
57497330f729Sjoerg
57507330f729Sjoerg // Recurse to parse whatever is left.
57517330f729Sjoerg ParseDeclaratorInternal(D, DirectDeclParser);
57527330f729Sjoerg
57537330f729Sjoerg // Sema will have to catch (syntactically invalid) pointers into global
57547330f729Sjoerg // scope. It has to catch pointers into namespace scope anyway.
57557330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
5756*e038c9c4Sjoerg SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()),
57577330f729Sjoerg std::move(DS.getAttributes()),
57587330f729Sjoerg /* Don't replace range end. */ SourceLocation());
57597330f729Sjoerg return;
57607330f729Sjoerg }
57617330f729Sjoerg }
57627330f729Sjoerg
57637330f729Sjoerg tok::TokenKind Kind = Tok.getKind();
57647330f729Sjoerg
57657330f729Sjoerg if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclerator(D)) {
57667330f729Sjoerg DeclSpec DS(AttrFactory);
57677330f729Sjoerg ParseTypeQualifierListOpt(DS);
57687330f729Sjoerg
57697330f729Sjoerg D.AddTypeInfo(
57707330f729Sjoerg DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
57717330f729Sjoerg std::move(DS.getAttributes()), SourceLocation());
57727330f729Sjoerg }
57737330f729Sjoerg
57747330f729Sjoerg // Not a pointer, C++ reference, or block.
57757330f729Sjoerg if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {
57767330f729Sjoerg if (DirectDeclParser)
57777330f729Sjoerg (this->*DirectDeclParser)(D);
57787330f729Sjoerg return;
57797330f729Sjoerg }
57807330f729Sjoerg
57817330f729Sjoerg // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,
57827330f729Sjoerg // '&&' -> rvalue reference
57837330f729Sjoerg SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&.
57847330f729Sjoerg D.SetRangeEnd(Loc);
57857330f729Sjoerg
57867330f729Sjoerg if (Kind == tok::star || Kind == tok::caret) {
57877330f729Sjoerg // Is a pointer.
57887330f729Sjoerg DeclSpec DS(AttrFactory);
57897330f729Sjoerg
57907330f729Sjoerg // GNU attributes are not allowed here in a new-type-id, but Declspec and
57917330f729Sjoerg // C++11 attributes are allowed.
57927330f729Sjoerg unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |
5793*e038c9c4Sjoerg ((D.getContext() != DeclaratorContext::CXXNew)
57947330f729Sjoerg ? AR_GNUAttributesParsed
57957330f729Sjoerg : AR_GNUAttributesParsedAndRejected);
57967330f729Sjoerg ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());
57977330f729Sjoerg D.ExtendWithDeclSpec(DS);
57987330f729Sjoerg
57997330f729Sjoerg // Recursively parse the declarator.
58007330f729Sjoerg ParseDeclaratorInternal(D, DirectDeclParser);
58017330f729Sjoerg if (Kind == tok::star)
58027330f729Sjoerg // Remember that we parsed a pointer type, and remember the type-quals.
58037330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getPointer(
58047330f729Sjoerg DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(),
58057330f729Sjoerg DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(),
58067330f729Sjoerg DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()),
58077330f729Sjoerg std::move(DS.getAttributes()), SourceLocation());
58087330f729Sjoerg else
58097330f729Sjoerg // Remember that we parsed a Block type, and remember the type-quals.
58107330f729Sjoerg D.AddTypeInfo(
58117330f729Sjoerg DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc),
58127330f729Sjoerg std::move(DS.getAttributes()), SourceLocation());
58137330f729Sjoerg } else {
58147330f729Sjoerg // Is a reference
58157330f729Sjoerg DeclSpec DS(AttrFactory);
58167330f729Sjoerg
58177330f729Sjoerg // Complain about rvalue references in C++03, but then go on and build
58187330f729Sjoerg // the declarator.
58197330f729Sjoerg if (Kind == tok::ampamp)
58207330f729Sjoerg Diag(Loc, getLangOpts().CPlusPlus11 ?
58217330f729Sjoerg diag::warn_cxx98_compat_rvalue_reference :
58227330f729Sjoerg diag::ext_rvalue_reference);
58237330f729Sjoerg
58247330f729Sjoerg // GNU-style and C++11 attributes are allowed here, as is restrict.
58257330f729Sjoerg ParseTypeQualifierListOpt(DS);
58267330f729Sjoerg D.ExtendWithDeclSpec(DS);
58277330f729Sjoerg
58287330f729Sjoerg // C++ 8.3.2p1: cv-qualified references are ill-formed except when the
58297330f729Sjoerg // cv-qualifiers are introduced through the use of a typedef or of a
58307330f729Sjoerg // template type argument, in which case the cv-qualifiers are ignored.
58317330f729Sjoerg if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
58327330f729Sjoerg if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
58337330f729Sjoerg Diag(DS.getConstSpecLoc(),
58347330f729Sjoerg diag::err_invalid_reference_qualifier_application) << "const";
58357330f729Sjoerg if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
58367330f729Sjoerg Diag(DS.getVolatileSpecLoc(),
58377330f729Sjoerg diag::err_invalid_reference_qualifier_application) << "volatile";
58387330f729Sjoerg // 'restrict' is permitted as an extension.
58397330f729Sjoerg if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
58407330f729Sjoerg Diag(DS.getAtomicSpecLoc(),
58417330f729Sjoerg diag::err_invalid_reference_qualifier_application) << "_Atomic";
58427330f729Sjoerg }
58437330f729Sjoerg
58447330f729Sjoerg // Recursively parse the declarator.
58457330f729Sjoerg ParseDeclaratorInternal(D, DirectDeclParser);
58467330f729Sjoerg
58477330f729Sjoerg if (D.getNumTypeObjects() > 0) {
58487330f729Sjoerg // C++ [dcl.ref]p4: There shall be no references to references.
58497330f729Sjoerg DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);
58507330f729Sjoerg if (InnerChunk.Kind == DeclaratorChunk::Reference) {
58517330f729Sjoerg if (const IdentifierInfo *II = D.getIdentifier())
58527330f729Sjoerg Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
58537330f729Sjoerg << II;
58547330f729Sjoerg else
58557330f729Sjoerg Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
58567330f729Sjoerg << "type name";
58577330f729Sjoerg
58587330f729Sjoerg // Once we've complained about the reference-to-reference, we
58597330f729Sjoerg // can go ahead and build the (technically ill-formed)
58607330f729Sjoerg // declarator: reference collapsing will take care of it.
58617330f729Sjoerg }
58627330f729Sjoerg }
58637330f729Sjoerg
58647330f729Sjoerg // Remember that we parsed a reference type.
58657330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
58667330f729Sjoerg Kind == tok::amp),
58677330f729Sjoerg std::move(DS.getAttributes()), SourceLocation());
58687330f729Sjoerg }
58697330f729Sjoerg }
58707330f729Sjoerg
58717330f729Sjoerg // When correcting from misplaced brackets before the identifier, the location
58727330f729Sjoerg // is saved inside the declarator so that other diagnostic messages can use
58737330f729Sjoerg // them. This extracts and returns that location, or returns the provided
58747330f729Sjoerg // location if a stored location does not exist.
getMissingDeclaratorIdLoc(Declarator & D,SourceLocation Loc)58757330f729Sjoerg static SourceLocation getMissingDeclaratorIdLoc(Declarator &D,
58767330f729Sjoerg SourceLocation Loc) {
58777330f729Sjoerg if (D.getName().StartLocation.isInvalid() &&
58787330f729Sjoerg D.getName().EndLocation.isValid())
58797330f729Sjoerg return D.getName().EndLocation;
58807330f729Sjoerg
58817330f729Sjoerg return Loc;
58827330f729Sjoerg }
58837330f729Sjoerg
58847330f729Sjoerg /// ParseDirectDeclarator
58857330f729Sjoerg /// direct-declarator: [C99 6.7.5]
58867330f729Sjoerg /// [C99] identifier
58877330f729Sjoerg /// '(' declarator ')'
58887330f729Sjoerg /// [GNU] '(' attributes declarator ')'
58897330f729Sjoerg /// [C90] direct-declarator '[' constant-expression[opt] ']'
58907330f729Sjoerg /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
58917330f729Sjoerg /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
58927330f729Sjoerg /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
58937330f729Sjoerg /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
58947330f729Sjoerg /// [C++11] direct-declarator '[' constant-expression[opt] ']'
58957330f729Sjoerg /// attribute-specifier-seq[opt]
58967330f729Sjoerg /// direct-declarator '(' parameter-type-list ')'
58977330f729Sjoerg /// direct-declarator '(' identifier-list[opt] ')'
58987330f729Sjoerg /// [GNU] direct-declarator '(' parameter-forward-declarations
58997330f729Sjoerg /// parameter-type-list[opt] ')'
59007330f729Sjoerg /// [C++] direct-declarator '(' parameter-declaration-clause ')'
59017330f729Sjoerg /// cv-qualifier-seq[opt] exception-specification[opt]
59027330f729Sjoerg /// [C++11] direct-declarator '(' parameter-declaration-clause ')'
59037330f729Sjoerg /// attribute-specifier-seq[opt] cv-qualifier-seq[opt]
59047330f729Sjoerg /// ref-qualifier[opt] exception-specification[opt]
59057330f729Sjoerg /// [C++] declarator-id
59067330f729Sjoerg /// [C++11] declarator-id attribute-specifier-seq[opt]
59077330f729Sjoerg ///
59087330f729Sjoerg /// declarator-id: [C++ 8]
59097330f729Sjoerg /// '...'[opt] id-expression
59107330f729Sjoerg /// '::'[opt] nested-name-specifier[opt] type-name
59117330f729Sjoerg ///
59127330f729Sjoerg /// id-expression: [C++ 5.1]
59137330f729Sjoerg /// unqualified-id
59147330f729Sjoerg /// qualified-id
59157330f729Sjoerg ///
59167330f729Sjoerg /// unqualified-id: [C++ 5.1]
59177330f729Sjoerg /// identifier
59187330f729Sjoerg /// operator-function-id
59197330f729Sjoerg /// conversion-function-id
59207330f729Sjoerg /// '~' class-name
59217330f729Sjoerg /// template-id
59227330f729Sjoerg ///
59237330f729Sjoerg /// C++17 adds the following, which we also handle here:
59247330f729Sjoerg ///
59257330f729Sjoerg /// simple-declaration:
59267330f729Sjoerg /// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';'
59277330f729Sjoerg ///
59287330f729Sjoerg /// Note, any additional constructs added here may need corresponding changes
59297330f729Sjoerg /// in isConstructorDeclarator.
ParseDirectDeclarator(Declarator & D)59307330f729Sjoerg void Parser::ParseDirectDeclarator(Declarator &D) {
59317330f729Sjoerg DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
59327330f729Sjoerg
59337330f729Sjoerg if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
59347330f729Sjoerg // This might be a C++17 structured binding.
59357330f729Sjoerg if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() &&
59367330f729Sjoerg D.getCXXScopeSpec().isEmpty())
59377330f729Sjoerg return ParseDecompositionDeclarator(D);
59387330f729Sjoerg
59397330f729Sjoerg // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in
59407330f729Sjoerg // this context it is a bitfield. Also in range-based for statement colon
59417330f729Sjoerg // may delimit for-range-declaration.
59427330f729Sjoerg ColonProtectionRAIIObject X(
5943*e038c9c4Sjoerg *this, D.getContext() == DeclaratorContext::Member ||
5944*e038c9c4Sjoerg (D.getContext() == DeclaratorContext::ForInit &&
59457330f729Sjoerg getLangOpts().CPlusPlus11));
59467330f729Sjoerg
59477330f729Sjoerg // ParseDeclaratorInternal might already have parsed the scope.
59487330f729Sjoerg if (D.getCXXScopeSpec().isEmpty()) {
5949*e038c9c4Sjoerg bool EnteringContext = D.getContext() == DeclaratorContext::File ||
5950*e038c9c4Sjoerg D.getContext() == DeclaratorContext::Member;
5951*e038c9c4Sjoerg ParseOptionalCXXScopeSpecifier(
5952*e038c9c4Sjoerg D.getCXXScopeSpec(), /*ObjectType=*/nullptr,
5953*e038c9c4Sjoerg /*ObjectHadErrors=*/false, EnteringContext);
59547330f729Sjoerg }
59557330f729Sjoerg
59567330f729Sjoerg if (D.getCXXScopeSpec().isValid()) {
59577330f729Sjoerg if (Actions.ShouldEnterDeclaratorScope(getCurScope(),
59587330f729Sjoerg D.getCXXScopeSpec()))
59597330f729Sjoerg // Change the declaration context for name lookup, until this function
59607330f729Sjoerg // is exited (and the declarator has been parsed).
59617330f729Sjoerg DeclScopeObj.EnterDeclaratorScope();
59627330f729Sjoerg else if (getObjCDeclContext()) {
59637330f729Sjoerg // Ensure that we don't interpret the next token as an identifier when
59647330f729Sjoerg // dealing with declarations in an Objective-C container.
59657330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
59667330f729Sjoerg D.setInvalidType(true);
59677330f729Sjoerg ConsumeToken();
59687330f729Sjoerg goto PastIdentifier;
59697330f729Sjoerg }
59707330f729Sjoerg }
59717330f729Sjoerg
59727330f729Sjoerg // C++0x [dcl.fct]p14:
59737330f729Sjoerg // There is a syntactic ambiguity when an ellipsis occurs at the end of a
59747330f729Sjoerg // parameter-declaration-clause without a preceding comma. In this case,
59757330f729Sjoerg // the ellipsis is parsed as part of the abstract-declarator if the type
59767330f729Sjoerg // of the parameter either names a template parameter pack that has not
59777330f729Sjoerg // been expanded or contains auto; otherwise, it is parsed as part of the
59787330f729Sjoerg // parameter-declaration-clause.
59797330f729Sjoerg if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
5980*e038c9c4Sjoerg !((D.getContext() == DeclaratorContext::Prototype ||
5981*e038c9c4Sjoerg D.getContext() == DeclaratorContext::LambdaExprParameter ||
5982*e038c9c4Sjoerg D.getContext() == DeclaratorContext::BlockLiteral) &&
5983*e038c9c4Sjoerg NextToken().is(tok::r_paren) && !D.hasGroupingParens() &&
59847330f729Sjoerg !Actions.containsUnexpandedParameterPacks(D) &&
59857330f729Sjoerg D.getDeclSpec().getTypeSpecType() != TST_auto)) {
59867330f729Sjoerg SourceLocation EllipsisLoc = ConsumeToken();
59877330f729Sjoerg if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) {
59887330f729Sjoerg // The ellipsis was put in the wrong place. Recover, and explain to
59897330f729Sjoerg // the user what they should have done.
59907330f729Sjoerg ParseDeclarator(D);
59917330f729Sjoerg if (EllipsisLoc.isValid())
59927330f729Sjoerg DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
59937330f729Sjoerg return;
59947330f729Sjoerg } else
59957330f729Sjoerg D.setEllipsisLoc(EllipsisLoc);
59967330f729Sjoerg
59977330f729Sjoerg // The ellipsis can't be followed by a parenthesized declarator. We
59987330f729Sjoerg // check for that in ParseParenDeclarator, after we have disambiguated
59997330f729Sjoerg // the l_paren token.
60007330f729Sjoerg }
60017330f729Sjoerg
60027330f729Sjoerg if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
60037330f729Sjoerg tok::tilde)) {
60047330f729Sjoerg // We found something that indicates the start of an unqualified-id.
60057330f729Sjoerg // Parse that unqualified-id.
60067330f729Sjoerg bool AllowConstructorName;
60077330f729Sjoerg bool AllowDeductionGuide;
60087330f729Sjoerg if (D.getDeclSpec().hasTypeSpecifier()) {
60097330f729Sjoerg AllowConstructorName = false;
60107330f729Sjoerg AllowDeductionGuide = false;
60117330f729Sjoerg } else if (D.getCXXScopeSpec().isSet()) {
6012*e038c9c4Sjoerg AllowConstructorName = (D.getContext() == DeclaratorContext::File ||
6013*e038c9c4Sjoerg D.getContext() == DeclaratorContext::Member);
60147330f729Sjoerg AllowDeductionGuide = false;
60157330f729Sjoerg } else {
6016*e038c9c4Sjoerg AllowConstructorName = (D.getContext() == DeclaratorContext::Member);
6017*e038c9c4Sjoerg AllowDeductionGuide = (D.getContext() == DeclaratorContext::File ||
6018*e038c9c4Sjoerg D.getContext() == DeclaratorContext::Member);
60197330f729Sjoerg }
60207330f729Sjoerg
60217330f729Sjoerg bool HadScope = D.getCXXScopeSpec().isValid();
60227330f729Sjoerg if (ParseUnqualifiedId(D.getCXXScopeSpec(),
6023*e038c9c4Sjoerg /*ObjectType=*/nullptr,
6024*e038c9c4Sjoerg /*ObjectHadErrors=*/false,
60257330f729Sjoerg /*EnteringContext=*/true,
60267330f729Sjoerg /*AllowDestructorName=*/true, AllowConstructorName,
6027*e038c9c4Sjoerg AllowDeductionGuide, nullptr, D.getName()) ||
60287330f729Sjoerg // Once we're past the identifier, if the scope was bad, mark the
60297330f729Sjoerg // whole declarator bad.
60307330f729Sjoerg D.getCXXScopeSpec().isInvalid()) {
60317330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
60327330f729Sjoerg D.setInvalidType(true);
60337330f729Sjoerg } else {
60347330f729Sjoerg // ParseUnqualifiedId might have parsed a scope specifier during error
60357330f729Sjoerg // recovery. If it did so, enter that scope.
60367330f729Sjoerg if (!HadScope && D.getCXXScopeSpec().isValid() &&
60377330f729Sjoerg Actions.ShouldEnterDeclaratorScope(getCurScope(),
60387330f729Sjoerg D.getCXXScopeSpec()))
60397330f729Sjoerg DeclScopeObj.EnterDeclaratorScope();
60407330f729Sjoerg
60417330f729Sjoerg // Parsed the unqualified-id; update range information and move along.
60427330f729Sjoerg if (D.getSourceRange().getBegin().isInvalid())
60437330f729Sjoerg D.SetRangeBegin(D.getName().getSourceRange().getBegin());
60447330f729Sjoerg D.SetRangeEnd(D.getName().getSourceRange().getEnd());
60457330f729Sjoerg }
60467330f729Sjoerg goto PastIdentifier;
60477330f729Sjoerg }
60487330f729Sjoerg
60497330f729Sjoerg if (D.getCXXScopeSpec().isNotEmpty()) {
60507330f729Sjoerg // We have a scope specifier but no following unqualified-id.
60517330f729Sjoerg Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()),
60527330f729Sjoerg diag::err_expected_unqualified_id)
60537330f729Sjoerg << /*C++*/1;
60547330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
60557330f729Sjoerg goto PastIdentifier;
60567330f729Sjoerg }
60577330f729Sjoerg } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
60587330f729Sjoerg assert(!getLangOpts().CPlusPlus &&
60597330f729Sjoerg "There's a C++-specific check for tok::identifier above");
60607330f729Sjoerg assert(Tok.getIdentifierInfo() && "Not an identifier?");
60617330f729Sjoerg D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
60627330f729Sjoerg D.SetRangeEnd(Tok.getLocation());
60637330f729Sjoerg ConsumeToken();
60647330f729Sjoerg goto PastIdentifier;
60657330f729Sjoerg } else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) {
60667330f729Sjoerg // We're not allowed an identifier here, but we got one. Try to figure out
60677330f729Sjoerg // if the user was trying to attach a name to the type, or whether the name
60687330f729Sjoerg // is some unrelated trailing syntax.
60697330f729Sjoerg bool DiagnoseIdentifier = false;
60707330f729Sjoerg if (D.hasGroupingParens())
60717330f729Sjoerg // An identifier within parens is unlikely to be intended to be anything
60727330f729Sjoerg // other than a name being "declared".
60737330f729Sjoerg DiagnoseIdentifier = true;
6074*e038c9c4Sjoerg else if (D.getContext() == DeclaratorContext::TemplateArg)
60757330f729Sjoerg // T<int N> is an accidental identifier; T<int N indicates a missing '>'.
60767330f729Sjoerg DiagnoseIdentifier =
60777330f729Sjoerg NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);
6078*e038c9c4Sjoerg else if (D.getContext() == DeclaratorContext::AliasDecl ||
6079*e038c9c4Sjoerg D.getContext() == DeclaratorContext::AliasTemplate)
60807330f729Sjoerg // The most likely error is that the ';' was forgotten.
60817330f729Sjoerg DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);
6082*e038c9c4Sjoerg else if ((D.getContext() == DeclaratorContext::TrailingReturn ||
6083*e038c9c4Sjoerg D.getContext() == DeclaratorContext::TrailingReturnVar) &&
60847330f729Sjoerg !isCXX11VirtSpecifier(Tok))
60857330f729Sjoerg DiagnoseIdentifier = NextToken().isOneOf(
60867330f729Sjoerg tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);
60877330f729Sjoerg if (DiagnoseIdentifier) {
60887330f729Sjoerg Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)
60897330f729Sjoerg << FixItHint::CreateRemoval(Tok.getLocation());
60907330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
60917330f729Sjoerg ConsumeToken();
60927330f729Sjoerg goto PastIdentifier;
60937330f729Sjoerg }
60947330f729Sjoerg }
60957330f729Sjoerg
60967330f729Sjoerg if (Tok.is(tok::l_paren)) {
60977330f729Sjoerg // If this might be an abstract-declarator followed by a direct-initializer,
60987330f729Sjoerg // check whether this is a valid declarator chunk. If it can't be, assume
60997330f729Sjoerg // that it's an initializer instead.
61007330f729Sjoerg if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
61017330f729Sjoerg RevertingTentativeParsingAction PA(*this);
61027330f729Sjoerg if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) ==
61037330f729Sjoerg TPResult::False) {
61047330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
61057330f729Sjoerg goto PastIdentifier;
61067330f729Sjoerg }
61077330f729Sjoerg }
61087330f729Sjoerg
61097330f729Sjoerg // direct-declarator: '(' declarator ')'
61107330f729Sjoerg // direct-declarator: '(' attributes declarator ')'
61117330f729Sjoerg // Example: 'char (*X)' or 'int (*XX)(void)'
61127330f729Sjoerg ParseParenDeclarator(D);
61137330f729Sjoerg
61147330f729Sjoerg // If the declarator was parenthesized, we entered the declarator
61157330f729Sjoerg // scope when parsing the parenthesized declarator, then exited
61167330f729Sjoerg // the scope already. Re-enter the scope, if we need to.
61177330f729Sjoerg if (D.getCXXScopeSpec().isSet()) {
61187330f729Sjoerg // If there was an error parsing parenthesized declarator, declarator
61197330f729Sjoerg // scope may have been entered before. Don't do it again.
61207330f729Sjoerg if (!D.isInvalidType() &&
61217330f729Sjoerg Actions.ShouldEnterDeclaratorScope(getCurScope(),
61227330f729Sjoerg D.getCXXScopeSpec()))
61237330f729Sjoerg // Change the declaration context for name lookup, until this function
61247330f729Sjoerg // is exited (and the declarator has been parsed).
61257330f729Sjoerg DeclScopeObj.EnterDeclaratorScope();
61267330f729Sjoerg }
61277330f729Sjoerg } else if (D.mayOmitIdentifier()) {
61287330f729Sjoerg // This could be something simple like "int" (in which case the declarator
61297330f729Sjoerg // portion is empty), if an abstract-declarator is allowed.
61307330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
61317330f729Sjoerg
61327330f729Sjoerg // The grammar for abstract-pack-declarator does not allow grouping parens.
61337330f729Sjoerg // FIXME: Revisit this once core issue 1488 is resolved.
61347330f729Sjoerg if (D.hasEllipsis() && D.hasGroupingParens())
61357330f729Sjoerg Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()),
61367330f729Sjoerg diag::ext_abstract_pack_declarator_parens);
61377330f729Sjoerg } else {
61387330f729Sjoerg if (Tok.getKind() == tok::annot_pragma_parser_crash)
61397330f729Sjoerg LLVM_BUILTIN_TRAP;
61407330f729Sjoerg if (Tok.is(tok::l_square))
61417330f729Sjoerg return ParseMisplacedBracketDeclarator(D);
6142*e038c9c4Sjoerg if (D.getContext() == DeclaratorContext::Member) {
61437330f729Sjoerg // Objective-C++: Detect C++ keywords and try to prevent further errors by
61447330f729Sjoerg // treating these keyword as valid member names.
61457330f729Sjoerg if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&
61467330f729Sjoerg Tok.getIdentifierInfo() &&
61477330f729Sjoerg Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) {
61487330f729Sjoerg Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
61497330f729Sjoerg diag::err_expected_member_name_or_semi_objcxx_keyword)
61507330f729Sjoerg << Tok.getIdentifierInfo()
61517330f729Sjoerg << (D.getDeclSpec().isEmpty() ? SourceRange()
61527330f729Sjoerg : D.getDeclSpec().getSourceRange());
61537330f729Sjoerg D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
61547330f729Sjoerg D.SetRangeEnd(Tok.getLocation());
61557330f729Sjoerg ConsumeToken();
61567330f729Sjoerg goto PastIdentifier;
61577330f729Sjoerg }
61587330f729Sjoerg Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
61597330f729Sjoerg diag::err_expected_member_name_or_semi)
61607330f729Sjoerg << (D.getDeclSpec().isEmpty() ? SourceRange()
61617330f729Sjoerg : D.getDeclSpec().getSourceRange());
61627330f729Sjoerg } else if (getLangOpts().CPlusPlus) {
61637330f729Sjoerg if (Tok.isOneOf(tok::period, tok::arrow))
61647330f729Sjoerg Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
61657330f729Sjoerg else {
61667330f729Sjoerg SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
61677330f729Sjoerg if (Tok.isAtStartOfLine() && Loc.isValid())
61687330f729Sjoerg Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
61697330f729Sjoerg << getLangOpts().CPlusPlus;
61707330f729Sjoerg else
61717330f729Sjoerg Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
61727330f729Sjoerg diag::err_expected_unqualified_id)
61737330f729Sjoerg << getLangOpts().CPlusPlus;
61747330f729Sjoerg }
61757330f729Sjoerg } else {
61767330f729Sjoerg Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
61777330f729Sjoerg diag::err_expected_either)
61787330f729Sjoerg << tok::identifier << tok::l_paren;
61797330f729Sjoerg }
61807330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
61817330f729Sjoerg D.setInvalidType(true);
61827330f729Sjoerg }
61837330f729Sjoerg
61847330f729Sjoerg PastIdentifier:
61857330f729Sjoerg assert(D.isPastIdentifier() &&
61867330f729Sjoerg "Haven't past the location of the identifier yet?");
61877330f729Sjoerg
61887330f729Sjoerg // Don't parse attributes unless we have parsed an unparenthesized name.
61897330f729Sjoerg if (D.hasName() && !D.getNumTypeObjects())
61907330f729Sjoerg MaybeParseCXX11Attributes(D);
61917330f729Sjoerg
61927330f729Sjoerg while (1) {
61937330f729Sjoerg if (Tok.is(tok::l_paren)) {
6194*e038c9c4Sjoerg bool IsFunctionDeclaration = D.isFunctionDeclaratorAFunctionDeclaration();
61957330f729Sjoerg // Enter function-declaration scope, limiting any declarators to the
61967330f729Sjoerg // function prototype scope, including parameter declarators.
61977330f729Sjoerg ParseScope PrototypeScope(this,
61987330f729Sjoerg Scope::FunctionPrototypeScope|Scope::DeclScope|
6199*e038c9c4Sjoerg (IsFunctionDeclaration
62007330f729Sjoerg ? Scope::FunctionDeclarationScope : 0));
62017330f729Sjoerg
62027330f729Sjoerg // The paren may be part of a C++ direct initializer, eg. "int x(1);".
62037330f729Sjoerg // In such a case, check if we actually have a function declarator; if it
62047330f729Sjoerg // is not, the declarator has been fully parsed.
62057330f729Sjoerg bool IsAmbiguous = false;
62067330f729Sjoerg if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
62077330f729Sjoerg // The name of the declarator, if any, is tentatively declared within
62087330f729Sjoerg // a possible direct initializer.
62097330f729Sjoerg TentativelyDeclaredIdentifiers.push_back(D.getIdentifier());
62107330f729Sjoerg bool IsFunctionDecl = isCXXFunctionDeclarator(&IsAmbiguous);
62117330f729Sjoerg TentativelyDeclaredIdentifiers.pop_back();
62127330f729Sjoerg if (!IsFunctionDecl)
62137330f729Sjoerg break;
62147330f729Sjoerg }
62157330f729Sjoerg ParsedAttributes attrs(AttrFactory);
62167330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
62177330f729Sjoerg T.consumeOpen();
6218*e038c9c4Sjoerg if (IsFunctionDeclaration)
6219*e038c9c4Sjoerg Actions.ActOnStartFunctionDeclarationDeclarator(D,
6220*e038c9c4Sjoerg TemplateParameterDepth);
62217330f729Sjoerg ParseFunctionDeclarator(D, attrs, T, IsAmbiguous);
6222*e038c9c4Sjoerg if (IsFunctionDeclaration)
6223*e038c9c4Sjoerg Actions.ActOnFinishFunctionDeclarationDeclarator(D);
62247330f729Sjoerg PrototypeScope.Exit();
62257330f729Sjoerg } else if (Tok.is(tok::l_square)) {
62267330f729Sjoerg ParseBracketDeclarator(D);
6227*e038c9c4Sjoerg } else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) {
6228*e038c9c4Sjoerg // This declarator is declaring a function, but the requires clause is
6229*e038c9c4Sjoerg // in the wrong place:
6230*e038c9c4Sjoerg // void (f() requires true);
6231*e038c9c4Sjoerg // instead of
6232*e038c9c4Sjoerg // void f() requires true;
6233*e038c9c4Sjoerg // or
6234*e038c9c4Sjoerg // void (f()) requires true;
6235*e038c9c4Sjoerg Diag(Tok, diag::err_requires_clause_inside_parens);
6236*e038c9c4Sjoerg ConsumeToken();
6237*e038c9c4Sjoerg ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr(
6238*e038c9c4Sjoerg ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
6239*e038c9c4Sjoerg if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() &&
6240*e038c9c4Sjoerg !D.hasTrailingRequiresClause())
6241*e038c9c4Sjoerg // We're already ill-formed if we got here but we'll accept it anyway.
6242*e038c9c4Sjoerg D.setTrailingRequiresClause(TrailingRequiresClause.get());
62437330f729Sjoerg } else {
62447330f729Sjoerg break;
62457330f729Sjoerg }
62467330f729Sjoerg }
62477330f729Sjoerg }
62487330f729Sjoerg
ParseDecompositionDeclarator(Declarator & D)62497330f729Sjoerg void Parser::ParseDecompositionDeclarator(Declarator &D) {
62507330f729Sjoerg assert(Tok.is(tok::l_square));
62517330f729Sjoerg
62527330f729Sjoerg // If this doesn't look like a structured binding, maybe it's a misplaced
62537330f729Sjoerg // array declarator.
62547330f729Sjoerg // FIXME: Consume the l_square first so we don't need extra lookahead for
62557330f729Sjoerg // this.
62567330f729Sjoerg if (!(NextToken().is(tok::identifier) &&
62577330f729Sjoerg GetLookAheadToken(2).isOneOf(tok::comma, tok::r_square)) &&
62587330f729Sjoerg !(NextToken().is(tok::r_square) &&
62597330f729Sjoerg GetLookAheadToken(2).isOneOf(tok::equal, tok::l_brace)))
62607330f729Sjoerg return ParseMisplacedBracketDeclarator(D);
62617330f729Sjoerg
62627330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_square);
62637330f729Sjoerg T.consumeOpen();
62647330f729Sjoerg
62657330f729Sjoerg SmallVector<DecompositionDeclarator::Binding, 32> Bindings;
62667330f729Sjoerg while (Tok.isNot(tok::r_square)) {
62677330f729Sjoerg if (!Bindings.empty()) {
62687330f729Sjoerg if (Tok.is(tok::comma))
62697330f729Sjoerg ConsumeToken();
62707330f729Sjoerg else {
62717330f729Sjoerg if (Tok.is(tok::identifier)) {
62727330f729Sjoerg SourceLocation EndLoc = getEndOfPreviousToken();
62737330f729Sjoerg Diag(EndLoc, diag::err_expected)
62747330f729Sjoerg << tok::comma << FixItHint::CreateInsertion(EndLoc, ",");
62757330f729Sjoerg } else {
62767330f729Sjoerg Diag(Tok, diag::err_expected_comma_or_rsquare);
62777330f729Sjoerg }
62787330f729Sjoerg
62797330f729Sjoerg SkipUntil(tok::r_square, tok::comma, tok::identifier,
62807330f729Sjoerg StopAtSemi | StopBeforeMatch);
62817330f729Sjoerg if (Tok.is(tok::comma))
62827330f729Sjoerg ConsumeToken();
62837330f729Sjoerg else if (Tok.isNot(tok::identifier))
62847330f729Sjoerg break;
62857330f729Sjoerg }
62867330f729Sjoerg }
62877330f729Sjoerg
62887330f729Sjoerg if (Tok.isNot(tok::identifier)) {
62897330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
62907330f729Sjoerg break;
62917330f729Sjoerg }
62927330f729Sjoerg
62937330f729Sjoerg Bindings.push_back({Tok.getIdentifierInfo(), Tok.getLocation()});
62947330f729Sjoerg ConsumeToken();
62957330f729Sjoerg }
62967330f729Sjoerg
62977330f729Sjoerg if (Tok.isNot(tok::r_square))
62987330f729Sjoerg // We've already diagnosed a problem here.
62997330f729Sjoerg T.skipToEnd();
63007330f729Sjoerg else {
63017330f729Sjoerg // C++17 does not allow the identifier-list in a structured binding
63027330f729Sjoerg // to be empty.
63037330f729Sjoerg if (Bindings.empty())
63047330f729Sjoerg Diag(Tok.getLocation(), diag::ext_decomp_decl_empty);
63057330f729Sjoerg
63067330f729Sjoerg T.consumeClose();
63077330f729Sjoerg }
63087330f729Sjoerg
63097330f729Sjoerg return D.setDecompositionBindings(T.getOpenLocation(), Bindings,
63107330f729Sjoerg T.getCloseLocation());
63117330f729Sjoerg }
63127330f729Sjoerg
63137330f729Sjoerg /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
63147330f729Sjoerg /// only called before the identifier, so these are most likely just grouping
63157330f729Sjoerg /// parens for precedence. If we find that these are actually function
63167330f729Sjoerg /// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
63177330f729Sjoerg ///
63187330f729Sjoerg /// direct-declarator:
63197330f729Sjoerg /// '(' declarator ')'
63207330f729Sjoerg /// [GNU] '(' attributes declarator ')'
63217330f729Sjoerg /// direct-declarator '(' parameter-type-list ')'
63227330f729Sjoerg /// direct-declarator '(' identifier-list[opt] ')'
63237330f729Sjoerg /// [GNU] direct-declarator '(' parameter-forward-declarations
63247330f729Sjoerg /// parameter-type-list[opt] ')'
63257330f729Sjoerg ///
ParseParenDeclarator(Declarator & D)63267330f729Sjoerg void Parser::ParseParenDeclarator(Declarator &D) {
63277330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
63287330f729Sjoerg T.consumeOpen();
63297330f729Sjoerg
63307330f729Sjoerg assert(!D.isPastIdentifier() && "Should be called before passing identifier");
63317330f729Sjoerg
63327330f729Sjoerg // Eat any attributes before we look at whether this is a grouping or function
63337330f729Sjoerg // declarator paren. If this is a grouping paren, the attribute applies to
63347330f729Sjoerg // the type being built up, for example:
63357330f729Sjoerg // int (__attribute__(()) *x)(long y)
63367330f729Sjoerg // If this ends up not being a grouping paren, the attribute applies to the
63377330f729Sjoerg // first argument, for example:
63387330f729Sjoerg // int (__attribute__(()) int x)
63397330f729Sjoerg // In either case, we need to eat any attributes to be able to determine what
63407330f729Sjoerg // sort of paren this is.
63417330f729Sjoerg //
63427330f729Sjoerg ParsedAttributes attrs(AttrFactory);
63437330f729Sjoerg bool RequiresArg = false;
63447330f729Sjoerg if (Tok.is(tok::kw___attribute)) {
63457330f729Sjoerg ParseGNUAttributes(attrs);
63467330f729Sjoerg
63477330f729Sjoerg // We require that the argument list (if this is a non-grouping paren) be
63487330f729Sjoerg // present even if the attribute list was empty.
63497330f729Sjoerg RequiresArg = true;
63507330f729Sjoerg }
63517330f729Sjoerg
63527330f729Sjoerg // Eat any Microsoft extensions.
63537330f729Sjoerg ParseMicrosoftTypeAttributes(attrs);
63547330f729Sjoerg
63557330f729Sjoerg // Eat any Borland extensions.
63567330f729Sjoerg if (Tok.is(tok::kw___pascal))
63577330f729Sjoerg ParseBorlandTypeAttributes(attrs);
63587330f729Sjoerg
63597330f729Sjoerg // If we haven't past the identifier yet (or where the identifier would be
63607330f729Sjoerg // stored, if this is an abstract declarator), then this is probably just
63617330f729Sjoerg // grouping parens. However, if this could be an abstract-declarator, then
63627330f729Sjoerg // this could also be the start of function arguments (consider 'void()').
63637330f729Sjoerg bool isGrouping;
63647330f729Sjoerg
63657330f729Sjoerg if (!D.mayOmitIdentifier()) {
63667330f729Sjoerg // If this can't be an abstract-declarator, this *must* be a grouping
63677330f729Sjoerg // paren, because we haven't seen the identifier yet.
63687330f729Sjoerg isGrouping = true;
63697330f729Sjoerg } else if (Tok.is(tok::r_paren) || // 'int()' is a function.
63707330f729Sjoerg (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) &&
63717330f729Sjoerg NextToken().is(tok::r_paren)) || // C++ int(...)
63727330f729Sjoerg isDeclarationSpecifier() || // 'int(int)' is a function.
63737330f729Sjoerg isCXX11AttributeSpecifier()) { // 'int([[]]int)' is a function.
63747330f729Sjoerg // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
63757330f729Sjoerg // considered to be a type, not a K&R identifier-list.
63767330f729Sjoerg isGrouping = false;
63777330f729Sjoerg } else {
63787330f729Sjoerg // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
63797330f729Sjoerg isGrouping = true;
63807330f729Sjoerg }
63817330f729Sjoerg
63827330f729Sjoerg // If this is a grouping paren, handle:
63837330f729Sjoerg // direct-declarator: '(' declarator ')'
63847330f729Sjoerg // direct-declarator: '(' attributes declarator ')'
63857330f729Sjoerg if (isGrouping) {
63867330f729Sjoerg SourceLocation EllipsisLoc = D.getEllipsisLoc();
63877330f729Sjoerg D.setEllipsisLoc(SourceLocation());
63887330f729Sjoerg
63897330f729Sjoerg bool hadGroupingParens = D.hasGroupingParens();
63907330f729Sjoerg D.setGroupingParens(true);
63917330f729Sjoerg ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
63927330f729Sjoerg // Match the ')'.
63937330f729Sjoerg T.consumeClose();
63947330f729Sjoerg D.AddTypeInfo(
63957330f729Sjoerg DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()),
63967330f729Sjoerg std::move(attrs), T.getCloseLocation());
63977330f729Sjoerg
63987330f729Sjoerg D.setGroupingParens(hadGroupingParens);
63997330f729Sjoerg
64007330f729Sjoerg // An ellipsis cannot be placed outside parentheses.
64017330f729Sjoerg if (EllipsisLoc.isValid())
64027330f729Sjoerg DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);
64037330f729Sjoerg
64047330f729Sjoerg return;
64057330f729Sjoerg }
64067330f729Sjoerg
64077330f729Sjoerg // Okay, if this wasn't a grouping paren, it must be the start of a function
64087330f729Sjoerg // argument list. Recognize that this declarator will never have an
64097330f729Sjoerg // identifier (and remember where it would have been), then call into
64107330f729Sjoerg // ParseFunctionDeclarator to handle of argument list.
64117330f729Sjoerg D.SetIdentifier(nullptr, Tok.getLocation());
64127330f729Sjoerg
64137330f729Sjoerg // Enter function-declaration scope, limiting any declarators to the
64147330f729Sjoerg // function prototype scope, including parameter declarators.
64157330f729Sjoerg ParseScope PrototypeScope(this,
64167330f729Sjoerg Scope::FunctionPrototypeScope | Scope::DeclScope |
64177330f729Sjoerg (D.isFunctionDeclaratorAFunctionDeclaration()
64187330f729Sjoerg ? Scope::FunctionDeclarationScope : 0));
64197330f729Sjoerg ParseFunctionDeclarator(D, attrs, T, false, RequiresArg);
64207330f729Sjoerg PrototypeScope.Exit();
64217330f729Sjoerg }
64227330f729Sjoerg
InitCXXThisScopeForDeclaratorIfRelevant(const Declarator & D,const DeclSpec & DS,llvm::Optional<Sema::CXXThisScopeRAII> & ThisScope)6423*e038c9c4Sjoerg void Parser::InitCXXThisScopeForDeclaratorIfRelevant(
6424*e038c9c4Sjoerg const Declarator &D, const DeclSpec &DS,
6425*e038c9c4Sjoerg llvm::Optional<Sema::CXXThisScopeRAII> &ThisScope) {
6426*e038c9c4Sjoerg // C++11 [expr.prim.general]p3:
6427*e038c9c4Sjoerg // If a declaration declares a member function or member function
6428*e038c9c4Sjoerg // template of a class X, the expression this is a prvalue of type
6429*e038c9c4Sjoerg // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
6430*e038c9c4Sjoerg // and the end of the function-definition, member-declarator, or
6431*e038c9c4Sjoerg // declarator.
6432*e038c9c4Sjoerg // FIXME: currently, "static" case isn't handled correctly.
6433*e038c9c4Sjoerg bool IsCXX11MemberFunction =
6434*e038c9c4Sjoerg getLangOpts().CPlusPlus11 &&
6435*e038c9c4Sjoerg D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
6436*e038c9c4Sjoerg (D.getContext() == DeclaratorContext::Member
6437*e038c9c4Sjoerg ? !D.getDeclSpec().isFriendSpecified()
6438*e038c9c4Sjoerg : D.getContext() == DeclaratorContext::File &&
6439*e038c9c4Sjoerg D.getCXXScopeSpec().isValid() &&
6440*e038c9c4Sjoerg Actions.CurContext->isRecord());
6441*e038c9c4Sjoerg if (!IsCXX11MemberFunction)
6442*e038c9c4Sjoerg return;
6443*e038c9c4Sjoerg
6444*e038c9c4Sjoerg Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());
6445*e038c9c4Sjoerg if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)
6446*e038c9c4Sjoerg Q.addConst();
6447*e038c9c4Sjoerg // FIXME: Collect C++ address spaces.
6448*e038c9c4Sjoerg // If there are multiple different address spaces, the source is invalid.
6449*e038c9c4Sjoerg // Carry on using the first addr space for the qualifiers of 'this'.
6450*e038c9c4Sjoerg // The diagnostic will be given later while creating the function
6451*e038c9c4Sjoerg // prototype for the method.
6452*e038c9c4Sjoerg if (getLangOpts().OpenCLCPlusPlus) {
6453*e038c9c4Sjoerg for (ParsedAttr &attr : DS.getAttributes()) {
6454*e038c9c4Sjoerg LangAS ASIdx = attr.asOpenCLLangAS();
6455*e038c9c4Sjoerg if (ASIdx != LangAS::Default) {
6456*e038c9c4Sjoerg Q.addAddressSpace(ASIdx);
6457*e038c9c4Sjoerg break;
6458*e038c9c4Sjoerg }
6459*e038c9c4Sjoerg }
6460*e038c9c4Sjoerg }
6461*e038c9c4Sjoerg ThisScope.emplace(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,
6462*e038c9c4Sjoerg IsCXX11MemberFunction);
6463*e038c9c4Sjoerg }
6464*e038c9c4Sjoerg
64657330f729Sjoerg /// ParseFunctionDeclarator - We are after the identifier and have parsed the
64667330f729Sjoerg /// declarator D up to a paren, which indicates that we are parsing function
64677330f729Sjoerg /// arguments.
64687330f729Sjoerg ///
64697330f729Sjoerg /// If FirstArgAttrs is non-null, then the caller parsed those arguments
64707330f729Sjoerg /// immediately after the open paren - they should be considered to be the
64717330f729Sjoerg /// first argument of a parameter.
64727330f729Sjoerg ///
64737330f729Sjoerg /// If RequiresArg is true, then the first argument of the function is required
64747330f729Sjoerg /// to be present and required to not be an identifier list.
64757330f729Sjoerg ///
64767330f729Sjoerg /// For C++, after the parameter-list, it also parses the cv-qualifier-seq[opt],
64777330f729Sjoerg /// (C++11) ref-qualifier[opt], exception-specification[opt],
6478*e038c9c4Sjoerg /// (C++11) attribute-specifier-seq[opt], (C++11) trailing-return-type[opt] and
6479*e038c9c4Sjoerg /// (C++2a) the trailing requires-clause.
64807330f729Sjoerg ///
64817330f729Sjoerg /// [C++11] exception-specification:
64827330f729Sjoerg /// dynamic-exception-specification
64837330f729Sjoerg /// noexcept-specification
64847330f729Sjoerg ///
ParseFunctionDeclarator(Declarator & D,ParsedAttributes & FirstArgAttrs,BalancedDelimiterTracker & Tracker,bool IsAmbiguous,bool RequiresArg)64857330f729Sjoerg void Parser::ParseFunctionDeclarator(Declarator &D,
64867330f729Sjoerg ParsedAttributes &FirstArgAttrs,
64877330f729Sjoerg BalancedDelimiterTracker &Tracker,
64887330f729Sjoerg bool IsAmbiguous,
64897330f729Sjoerg bool RequiresArg) {
64907330f729Sjoerg assert(getCurScope()->isFunctionPrototypeScope() &&
64917330f729Sjoerg "Should call from a Function scope");
64927330f729Sjoerg // lparen is already consumed!
64937330f729Sjoerg assert(D.isPastIdentifier() && "Should not call before identifier!");
64947330f729Sjoerg
64957330f729Sjoerg // This should be true when the function has typed arguments.
64967330f729Sjoerg // Otherwise, it is treated as a K&R-style function.
64977330f729Sjoerg bool HasProto = false;
64987330f729Sjoerg // Build up an array of information about the parsed arguments.
64997330f729Sjoerg SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
65007330f729Sjoerg // Remember where we see an ellipsis, if any.
65017330f729Sjoerg SourceLocation EllipsisLoc;
65027330f729Sjoerg
65037330f729Sjoerg DeclSpec DS(AttrFactory);
65047330f729Sjoerg bool RefQualifierIsLValueRef = true;
65057330f729Sjoerg SourceLocation RefQualifierLoc;
65067330f729Sjoerg ExceptionSpecificationType ESpecType = EST_None;
65077330f729Sjoerg SourceRange ESpecRange;
65087330f729Sjoerg SmallVector<ParsedType, 2> DynamicExceptions;
65097330f729Sjoerg SmallVector<SourceRange, 2> DynamicExceptionRanges;
65107330f729Sjoerg ExprResult NoexceptExpr;
65117330f729Sjoerg CachedTokens *ExceptionSpecTokens = nullptr;
65127330f729Sjoerg ParsedAttributesWithRange FnAttrs(AttrFactory);
65137330f729Sjoerg TypeResult TrailingReturnType;
6514*e038c9c4Sjoerg SourceLocation TrailingReturnTypeLoc;
65157330f729Sjoerg
65167330f729Sjoerg /* LocalEndLoc is the end location for the local FunctionTypeLoc.
65177330f729Sjoerg EndLoc is the end location for the function declarator.
65187330f729Sjoerg They differ for trailing return types. */
65197330f729Sjoerg SourceLocation StartLoc, LocalEndLoc, EndLoc;
65207330f729Sjoerg SourceLocation LParenLoc, RParenLoc;
65217330f729Sjoerg LParenLoc = Tracker.getOpenLocation();
65227330f729Sjoerg StartLoc = LParenLoc;
65237330f729Sjoerg
65247330f729Sjoerg if (isFunctionDeclaratorIdentifierList()) {
65257330f729Sjoerg if (RequiresArg)
65267330f729Sjoerg Diag(Tok, diag::err_argument_required_after_attribute);
65277330f729Sjoerg
65287330f729Sjoerg ParseFunctionDeclaratorIdentifierList(D, ParamInfo);
65297330f729Sjoerg
65307330f729Sjoerg Tracker.consumeClose();
65317330f729Sjoerg RParenLoc = Tracker.getCloseLocation();
65327330f729Sjoerg LocalEndLoc = RParenLoc;
65337330f729Sjoerg EndLoc = RParenLoc;
65347330f729Sjoerg
65357330f729Sjoerg // If there are attributes following the identifier list, parse them and
65367330f729Sjoerg // prohibit them.
65377330f729Sjoerg MaybeParseCXX11Attributes(FnAttrs);
65387330f729Sjoerg ProhibitAttributes(FnAttrs);
65397330f729Sjoerg } else {
65407330f729Sjoerg if (Tok.isNot(tok::r_paren))
6541*e038c9c4Sjoerg ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo,
65427330f729Sjoerg EllipsisLoc);
65437330f729Sjoerg else if (RequiresArg)
65447330f729Sjoerg Diag(Tok, diag::err_argument_required_after_attribute);
65457330f729Sjoerg
65467330f729Sjoerg HasProto = ParamInfo.size() || getLangOpts().CPlusPlus
65477330f729Sjoerg || getLangOpts().OpenCL;
65487330f729Sjoerg
65497330f729Sjoerg // If we have the closing ')', eat it.
65507330f729Sjoerg Tracker.consumeClose();
65517330f729Sjoerg RParenLoc = Tracker.getCloseLocation();
65527330f729Sjoerg LocalEndLoc = RParenLoc;
65537330f729Sjoerg EndLoc = RParenLoc;
65547330f729Sjoerg
65557330f729Sjoerg if (getLangOpts().CPlusPlus) {
65567330f729Sjoerg // FIXME: Accept these components in any order, and produce fixits to
65577330f729Sjoerg // correct the order if the user gets it wrong. Ideally we should deal
65587330f729Sjoerg // with the pure-specifier in the same way.
65597330f729Sjoerg
65607330f729Sjoerg // Parse cv-qualifier-seq[opt].
65617330f729Sjoerg ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed,
65627330f729Sjoerg /*AtomicAllowed*/ false,
65637330f729Sjoerg /*IdentifierRequired=*/false,
65647330f729Sjoerg llvm::function_ref<void()>([&]() {
65657330f729Sjoerg Actions.CodeCompleteFunctionQualifiers(DS, D);
65667330f729Sjoerg }));
65677330f729Sjoerg if (!DS.getSourceRange().getEnd().isInvalid()) {
65687330f729Sjoerg EndLoc = DS.getSourceRange().getEnd();
65697330f729Sjoerg }
65707330f729Sjoerg
65717330f729Sjoerg // Parse ref-qualifier[opt].
65727330f729Sjoerg if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))
65737330f729Sjoerg EndLoc = RefQualifierLoc;
65747330f729Sjoerg
6575*e038c9c4Sjoerg llvm::Optional<Sema::CXXThisScopeRAII> ThisScope;
6576*e038c9c4Sjoerg InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);
65777330f729Sjoerg
65787330f729Sjoerg // Parse exception-specification[opt].
6579*e038c9c4Sjoerg // FIXME: Per [class.mem]p6, all exception-specifications at class scope
6580*e038c9c4Sjoerg // should be delayed, including those for non-members (eg, friend
6581*e038c9c4Sjoerg // declarations). But only applying this to member declarations is
6582*e038c9c4Sjoerg // consistent with what other implementations do.
65837330f729Sjoerg bool Delayed = D.isFirstDeclarationOfMember() &&
65847330f729Sjoerg D.isFunctionDeclaratorAFunctionDeclaration();
65857330f729Sjoerg if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) &&
65867330f729Sjoerg GetLookAheadToken(0).is(tok::kw_noexcept) &&
65877330f729Sjoerg GetLookAheadToken(1).is(tok::l_paren) &&
65887330f729Sjoerg GetLookAheadToken(2).is(tok::kw_noexcept) &&
65897330f729Sjoerg GetLookAheadToken(3).is(tok::l_paren) &&
65907330f729Sjoerg GetLookAheadToken(4).is(tok::identifier) &&
65917330f729Sjoerg GetLookAheadToken(4).getIdentifierInfo()->isStr("swap")) {
65927330f729Sjoerg // HACK: We've got an exception-specification
65937330f729Sjoerg // noexcept(noexcept(swap(...)))
65947330f729Sjoerg // or
65957330f729Sjoerg // noexcept(noexcept(swap(...)) && noexcept(swap(...)))
65967330f729Sjoerg // on a 'swap' member function. This is a libstdc++ bug; the lookup
65977330f729Sjoerg // for 'swap' will only find the function we're currently declaring,
65987330f729Sjoerg // whereas it expects to find a non-member swap through ADL. Turn off
65997330f729Sjoerg // delayed parsing to give it a chance to find what it expects.
66007330f729Sjoerg Delayed = false;
66017330f729Sjoerg }
66027330f729Sjoerg ESpecType = tryParseExceptionSpecification(Delayed,
66037330f729Sjoerg ESpecRange,
66047330f729Sjoerg DynamicExceptions,
66057330f729Sjoerg DynamicExceptionRanges,
66067330f729Sjoerg NoexceptExpr,
66077330f729Sjoerg ExceptionSpecTokens);
66087330f729Sjoerg if (ESpecType != EST_None)
66097330f729Sjoerg EndLoc = ESpecRange.getEnd();
66107330f729Sjoerg
66117330f729Sjoerg // Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes
66127330f729Sjoerg // after the exception-specification.
66137330f729Sjoerg MaybeParseCXX11Attributes(FnAttrs);
66147330f729Sjoerg
66157330f729Sjoerg // Parse trailing-return-type[opt].
66167330f729Sjoerg LocalEndLoc = EndLoc;
66177330f729Sjoerg if (getLangOpts().CPlusPlus11 && Tok.is(tok::arrow)) {
66187330f729Sjoerg Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);
66197330f729Sjoerg if (D.getDeclSpec().getTypeSpecType() == TST_auto)
66207330f729Sjoerg StartLoc = D.getDeclSpec().getTypeSpecTypeLoc();
66217330f729Sjoerg LocalEndLoc = Tok.getLocation();
66227330f729Sjoerg SourceRange Range;
66237330f729Sjoerg TrailingReturnType =
66247330f729Sjoerg ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit());
6625*e038c9c4Sjoerg TrailingReturnTypeLoc = Range.getBegin();
66267330f729Sjoerg EndLoc = Range.getEnd();
66277330f729Sjoerg }
66287330f729Sjoerg } else if (standardAttributesAllowed()) {
66297330f729Sjoerg MaybeParseCXX11Attributes(FnAttrs);
66307330f729Sjoerg }
66317330f729Sjoerg }
66327330f729Sjoerg
66337330f729Sjoerg // Collect non-parameter declarations from the prototype if this is a function
66347330f729Sjoerg // declaration. They will be moved into the scope of the function. Only do
66357330f729Sjoerg // this in C and not C++, where the decls will continue to live in the
66367330f729Sjoerg // surrounding context.
66377330f729Sjoerg SmallVector<NamedDecl *, 0> DeclsInPrototype;
66387330f729Sjoerg if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope &&
66397330f729Sjoerg !getLangOpts().CPlusPlus) {
66407330f729Sjoerg for (Decl *D : getCurScope()->decls()) {
66417330f729Sjoerg NamedDecl *ND = dyn_cast<NamedDecl>(D);
66427330f729Sjoerg if (!ND || isa<ParmVarDecl>(ND))
66437330f729Sjoerg continue;
66447330f729Sjoerg DeclsInPrototype.push_back(ND);
66457330f729Sjoerg }
66467330f729Sjoerg }
66477330f729Sjoerg
66487330f729Sjoerg // Remember that we parsed a function type, and remember the attributes.
66497330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getFunction(
66507330f729Sjoerg HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(),
66517330f729Sjoerg ParamInfo.size(), EllipsisLoc, RParenLoc,
66527330f729Sjoerg RefQualifierIsLValueRef, RefQualifierLoc,
66537330f729Sjoerg /*MutableLoc=*/SourceLocation(),
66547330f729Sjoerg ESpecType, ESpecRange, DynamicExceptions.data(),
66557330f729Sjoerg DynamicExceptionRanges.data(), DynamicExceptions.size(),
66567330f729Sjoerg NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
66577330f729Sjoerg ExceptionSpecTokens, DeclsInPrototype, StartLoc,
6658*e038c9c4Sjoerg LocalEndLoc, D, TrailingReturnType, TrailingReturnTypeLoc,
6659*e038c9c4Sjoerg &DS),
66607330f729Sjoerg std::move(FnAttrs), EndLoc);
66617330f729Sjoerg }
66627330f729Sjoerg
66637330f729Sjoerg /// ParseRefQualifier - Parses a member function ref-qualifier. Returns
66647330f729Sjoerg /// true if a ref-qualifier is found.
ParseRefQualifier(bool & RefQualifierIsLValueRef,SourceLocation & RefQualifierLoc)66657330f729Sjoerg bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,
66667330f729Sjoerg SourceLocation &RefQualifierLoc) {
66677330f729Sjoerg if (Tok.isOneOf(tok::amp, tok::ampamp)) {
66687330f729Sjoerg Diag(Tok, getLangOpts().CPlusPlus11 ?
66697330f729Sjoerg diag::warn_cxx98_compat_ref_qualifier :
66707330f729Sjoerg diag::ext_ref_qualifier);
66717330f729Sjoerg
66727330f729Sjoerg RefQualifierIsLValueRef = Tok.is(tok::amp);
66737330f729Sjoerg RefQualifierLoc = ConsumeToken();
66747330f729Sjoerg return true;
66757330f729Sjoerg }
66767330f729Sjoerg return false;
66777330f729Sjoerg }
66787330f729Sjoerg
66797330f729Sjoerg /// isFunctionDeclaratorIdentifierList - This parameter list may have an
66807330f729Sjoerg /// identifier list form for a K&R-style function: void foo(a,b,c)
66817330f729Sjoerg ///
66827330f729Sjoerg /// Note that identifier-lists are only allowed for normal declarators, not for
66837330f729Sjoerg /// abstract-declarators.
isFunctionDeclaratorIdentifierList()66847330f729Sjoerg bool Parser::isFunctionDeclaratorIdentifierList() {
66857330f729Sjoerg return !getLangOpts().CPlusPlus
66867330f729Sjoerg && Tok.is(tok::identifier)
66877330f729Sjoerg && !TryAltiVecVectorToken()
66887330f729Sjoerg // K&R identifier lists can't have typedefs as identifiers, per C99
66897330f729Sjoerg // 6.7.5.3p11.
66907330f729Sjoerg && (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename))
66917330f729Sjoerg // Identifier lists follow a really simple grammar: the identifiers can
66927330f729Sjoerg // be followed *only* by a ", identifier" or ")". However, K&R
66937330f729Sjoerg // identifier lists are really rare in the brave new modern world, and
66947330f729Sjoerg // it is very common for someone to typo a type in a non-K&R style
66957330f729Sjoerg // list. If we are presented with something like: "void foo(intptr x,
66967330f729Sjoerg // float y)", we don't want to start parsing the function declarator as
66977330f729Sjoerg // though it is a K&R style declarator just because intptr is an
66987330f729Sjoerg // invalid type.
66997330f729Sjoerg //
67007330f729Sjoerg // To handle this, we check to see if the token after the first
67017330f729Sjoerg // identifier is a "," or ")". Only then do we parse it as an
67027330f729Sjoerg // identifier list.
67037330f729Sjoerg && (!Tok.is(tok::eof) &&
67047330f729Sjoerg (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));
67057330f729Sjoerg }
67067330f729Sjoerg
67077330f729Sjoerg /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
67087330f729Sjoerg /// we found a K&R-style identifier list instead of a typed parameter list.
67097330f729Sjoerg ///
67107330f729Sjoerg /// After returning, ParamInfo will hold the parsed parameters.
67117330f729Sjoerg ///
67127330f729Sjoerg /// identifier-list: [C99 6.7.5]
67137330f729Sjoerg /// identifier
67147330f729Sjoerg /// identifier-list ',' identifier
67157330f729Sjoerg ///
ParseFunctionDeclaratorIdentifierList(Declarator & D,SmallVectorImpl<DeclaratorChunk::ParamInfo> & ParamInfo)67167330f729Sjoerg void Parser::ParseFunctionDeclaratorIdentifierList(
67177330f729Sjoerg Declarator &D,
67187330f729Sjoerg SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) {
67197330f729Sjoerg // If there was no identifier specified for the declarator, either we are in
67207330f729Sjoerg // an abstract-declarator, or we are in a parameter declarator which was found
67217330f729Sjoerg // to be abstract. In abstract-declarators, identifier lists are not valid:
67227330f729Sjoerg // diagnose this.
67237330f729Sjoerg if (!D.getIdentifier())
67247330f729Sjoerg Diag(Tok, diag::ext_ident_list_in_param);
67257330f729Sjoerg
67267330f729Sjoerg // Maintain an efficient lookup of params we have seen so far.
67277330f729Sjoerg llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
67287330f729Sjoerg
67297330f729Sjoerg do {
67307330f729Sjoerg // If this isn't an identifier, report the error and skip until ')'.
67317330f729Sjoerg if (Tok.isNot(tok::identifier)) {
67327330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
67337330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
67347330f729Sjoerg // Forget we parsed anything.
67357330f729Sjoerg ParamInfo.clear();
67367330f729Sjoerg return;
67377330f729Sjoerg }
67387330f729Sjoerg
67397330f729Sjoerg IdentifierInfo *ParmII = Tok.getIdentifierInfo();
67407330f729Sjoerg
67417330f729Sjoerg // Reject 'typedef int y; int test(x, y)', but continue parsing.
67427330f729Sjoerg if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope()))
67437330f729Sjoerg Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
67447330f729Sjoerg
67457330f729Sjoerg // Verify that the argument identifier has not already been mentioned.
67467330f729Sjoerg if (!ParamsSoFar.insert(ParmII).second) {
67477330f729Sjoerg Diag(Tok, diag::err_param_redefinition) << ParmII;
67487330f729Sjoerg } else {
67497330f729Sjoerg // Remember this identifier in ParamInfo.
67507330f729Sjoerg ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
67517330f729Sjoerg Tok.getLocation(),
67527330f729Sjoerg nullptr));
67537330f729Sjoerg }
67547330f729Sjoerg
67557330f729Sjoerg // Eat the identifier.
67567330f729Sjoerg ConsumeToken();
67577330f729Sjoerg // The list continues if we see a comma.
67587330f729Sjoerg } while (TryConsumeToken(tok::comma));
67597330f729Sjoerg }
67607330f729Sjoerg
67617330f729Sjoerg /// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
67627330f729Sjoerg /// after the opening parenthesis. This function will not parse a K&R-style
67637330f729Sjoerg /// identifier list.
67647330f729Sjoerg ///
6765*e038c9c4Sjoerg /// DeclContext is the context of the declarator being parsed. If FirstArgAttrs
6766*e038c9c4Sjoerg /// is non-null, then the caller parsed those attributes immediately after the
6767*e038c9c4Sjoerg /// open paren - they should be considered to be part of the first parameter.
67687330f729Sjoerg ///
67697330f729Sjoerg /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will
67707330f729Sjoerg /// be the location of the ellipsis, if any was parsed.
67717330f729Sjoerg ///
67727330f729Sjoerg /// parameter-type-list: [C99 6.7.5]
67737330f729Sjoerg /// parameter-list
67747330f729Sjoerg /// parameter-list ',' '...'
67757330f729Sjoerg /// [C++] parameter-list '...'
67767330f729Sjoerg ///
67777330f729Sjoerg /// parameter-list: [C99 6.7.5]
67787330f729Sjoerg /// parameter-declaration
67797330f729Sjoerg /// parameter-list ',' parameter-declaration
67807330f729Sjoerg ///
67817330f729Sjoerg /// parameter-declaration: [C99 6.7.5]
67827330f729Sjoerg /// declaration-specifiers declarator
67837330f729Sjoerg /// [C++] declaration-specifiers declarator '=' assignment-expression
67847330f729Sjoerg /// [C++11] initializer-clause
67857330f729Sjoerg /// [GNU] declaration-specifiers declarator attributes
67867330f729Sjoerg /// declaration-specifiers abstract-declarator[opt]
67877330f729Sjoerg /// [C++] declaration-specifiers abstract-declarator[opt]
67887330f729Sjoerg /// '=' assignment-expression
67897330f729Sjoerg /// [GNU] declaration-specifiers abstract-declarator[opt] attributes
67907330f729Sjoerg /// [C++11] attribute-specifier-seq parameter-declaration
67917330f729Sjoerg ///
ParseParameterDeclarationClause(DeclaratorContext DeclaratorCtx,ParsedAttributes & FirstArgAttrs,SmallVectorImpl<DeclaratorChunk::ParamInfo> & ParamInfo,SourceLocation & EllipsisLoc)67927330f729Sjoerg void Parser::ParseParameterDeclarationClause(
6793*e038c9c4Sjoerg DeclaratorContext DeclaratorCtx,
67947330f729Sjoerg ParsedAttributes &FirstArgAttrs,
67957330f729Sjoerg SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
67967330f729Sjoerg SourceLocation &EllipsisLoc) {
6797*e038c9c4Sjoerg
6798*e038c9c4Sjoerg // Avoid exceeding the maximum function scope depth.
6799*e038c9c4Sjoerg // See https://bugs.llvm.org/show_bug.cgi?id=19607
6800*e038c9c4Sjoerg // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with
6801*e038c9c4Sjoerg // getFunctionPrototypeDepth() - 1.
6802*e038c9c4Sjoerg if (getCurScope()->getFunctionPrototypeDepth() - 1 >
6803*e038c9c4Sjoerg ParmVarDecl::getMaxFunctionScopeDepth()) {
6804*e038c9c4Sjoerg Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded)
6805*e038c9c4Sjoerg << ParmVarDecl::getMaxFunctionScopeDepth();
6806*e038c9c4Sjoerg cutOffParsing();
6807*e038c9c4Sjoerg return;
6808*e038c9c4Sjoerg }
6809*e038c9c4Sjoerg
68107330f729Sjoerg do {
68117330f729Sjoerg // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
68127330f729Sjoerg // before deciding this was a parameter-declaration-clause.
68137330f729Sjoerg if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
68147330f729Sjoerg break;
68157330f729Sjoerg
68167330f729Sjoerg // Parse the declaration-specifiers.
68177330f729Sjoerg // Just use the ParsingDeclaration "scope" of the declarator.
68187330f729Sjoerg DeclSpec DS(AttrFactory);
68197330f729Sjoerg
68207330f729Sjoerg // Parse any C++11 attributes.
68217330f729Sjoerg MaybeParseCXX11Attributes(DS.getAttributes());
68227330f729Sjoerg
68237330f729Sjoerg // Skip any Microsoft attributes before a param.
68247330f729Sjoerg MaybeParseMicrosoftAttributes(DS.getAttributes());
68257330f729Sjoerg
68267330f729Sjoerg SourceLocation DSStart = Tok.getLocation();
68277330f729Sjoerg
68287330f729Sjoerg // If the caller parsed attributes for the first argument, add them now.
68297330f729Sjoerg // Take them so that we only apply the attributes to the first parameter.
68307330f729Sjoerg // FIXME: If we can leave the attributes in the token stream somehow, we can
68317330f729Sjoerg // get rid of a parameter (FirstArgAttrs) and this statement. It might be
68327330f729Sjoerg // too much hassle.
68337330f729Sjoerg DS.takeAttributesFrom(FirstArgAttrs);
68347330f729Sjoerg
68357330f729Sjoerg ParseDeclarationSpecifiers(DS);
68367330f729Sjoerg
68377330f729Sjoerg
68387330f729Sjoerg // Parse the declarator. This is "PrototypeContext" or
68397330f729Sjoerg // "LambdaExprParameterContext", because we must accept either
68407330f729Sjoerg // 'declarator' or 'abstract-declarator' here.
68417330f729Sjoerg Declarator ParmDeclarator(
6842*e038c9c4Sjoerg DS, DeclaratorCtx == DeclaratorContext::RequiresExpr
6843*e038c9c4Sjoerg ? DeclaratorContext::RequiresExpr
6844*e038c9c4Sjoerg : DeclaratorCtx == DeclaratorContext::LambdaExpr
6845*e038c9c4Sjoerg ? DeclaratorContext::LambdaExprParameter
6846*e038c9c4Sjoerg : DeclaratorContext::Prototype);
68477330f729Sjoerg ParseDeclarator(ParmDeclarator);
68487330f729Sjoerg
68497330f729Sjoerg // Parse GNU attributes, if present.
68507330f729Sjoerg MaybeParseGNUAttributes(ParmDeclarator);
68517330f729Sjoerg
6852*e038c9c4Sjoerg if (Tok.is(tok::kw_requires)) {
6853*e038c9c4Sjoerg // User tried to define a requires clause in a parameter declaration,
6854*e038c9c4Sjoerg // which is surely not a function declaration.
6855*e038c9c4Sjoerg // void f(int (*g)(int, int) requires true);
6856*e038c9c4Sjoerg Diag(Tok,
6857*e038c9c4Sjoerg diag::err_requires_clause_on_declarator_not_declaring_a_function);
6858*e038c9c4Sjoerg ConsumeToken();
6859*e038c9c4Sjoerg Actions.CorrectDelayedTyposInExpr(
6860*e038c9c4Sjoerg ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
6861*e038c9c4Sjoerg }
6862*e038c9c4Sjoerg
68637330f729Sjoerg // Remember this parsed parameter in ParamInfo.
68647330f729Sjoerg IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
68657330f729Sjoerg
68667330f729Sjoerg // DefArgToks is used when the parsing of default arguments needs
68677330f729Sjoerg // to be delayed.
68687330f729Sjoerg std::unique_ptr<CachedTokens> DefArgToks;
68697330f729Sjoerg
68707330f729Sjoerg // If no parameter was specified, verify that *something* was specified,
68717330f729Sjoerg // otherwise we have a missing type and identifier.
68727330f729Sjoerg if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr &&
68737330f729Sjoerg ParmDeclarator.getNumTypeObjects() == 0) {
68747330f729Sjoerg // Completely missing, emit error.
68757330f729Sjoerg Diag(DSStart, diag::err_missing_param);
68767330f729Sjoerg } else {
68777330f729Sjoerg // Otherwise, we have something. Add it and let semantic analysis try
68787330f729Sjoerg // to grok it and add the result to the ParamInfo we are building.
68797330f729Sjoerg
68807330f729Sjoerg // Last chance to recover from a misplaced ellipsis in an attempted
68817330f729Sjoerg // parameter pack declaration.
68827330f729Sjoerg if (Tok.is(tok::ellipsis) &&
68837330f729Sjoerg (NextToken().isNot(tok::r_paren) ||
68847330f729Sjoerg (!ParmDeclarator.getEllipsisLoc().isValid() &&
68857330f729Sjoerg !Actions.isUnexpandedParameterPackPermitted())) &&
68867330f729Sjoerg Actions.containsUnexpandedParameterPacks(ParmDeclarator))
68877330f729Sjoerg DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator);
68887330f729Sjoerg
6889*e038c9c4Sjoerg // Now we are at the point where declarator parsing is finished.
6890*e038c9c4Sjoerg //
6891*e038c9c4Sjoerg // Try to catch keywords in place of the identifier in a declarator, and
6892*e038c9c4Sjoerg // in particular the common case where:
6893*e038c9c4Sjoerg // 1 identifier comes at the end of the declarator
6894*e038c9c4Sjoerg // 2 if the identifier is dropped, the declarator is valid but anonymous
6895*e038c9c4Sjoerg // (no identifier)
6896*e038c9c4Sjoerg // 3 declarator parsing succeeds, and then we have a trailing keyword,
6897*e038c9c4Sjoerg // which is never valid in a param list (e.g. missing a ',')
6898*e038c9c4Sjoerg // And we can't handle this in ParseDeclarator because in general keywords
6899*e038c9c4Sjoerg // may be allowed to follow the declarator. (And in some cases there'd be
6900*e038c9c4Sjoerg // better recovery like inserting punctuation). ParseDeclarator is just
6901*e038c9c4Sjoerg // treating this as an anonymous parameter, and fortunately at this point
6902*e038c9c4Sjoerg // we've already almost done that.
6903*e038c9c4Sjoerg //
6904*e038c9c4Sjoerg // We care about case 1) where the declarator type should be known, and
6905*e038c9c4Sjoerg // the identifier should be null.
6906*e038c9c4Sjoerg if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName()) {
6907*e038c9c4Sjoerg if (Tok.getIdentifierInfo() &&
6908*e038c9c4Sjoerg Tok.getIdentifierInfo()->isKeyword(getLangOpts())) {
6909*e038c9c4Sjoerg Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok);
6910*e038c9c4Sjoerg // Consume the keyword.
6911*e038c9c4Sjoerg ConsumeToken();
6912*e038c9c4Sjoerg }
6913*e038c9c4Sjoerg }
69147330f729Sjoerg // Inform the actions module about the parameter declarator, so it gets
69157330f729Sjoerg // added to the current scope.
69167330f729Sjoerg Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);
69177330f729Sjoerg // Parse the default argument, if any. We parse the default
69187330f729Sjoerg // arguments in all dialects; the semantic analysis in
69197330f729Sjoerg // ActOnParamDefaultArgument will reject the default argument in
69207330f729Sjoerg // C.
69217330f729Sjoerg if (Tok.is(tok::equal)) {
69227330f729Sjoerg SourceLocation EqualLoc = Tok.getLocation();
69237330f729Sjoerg
69247330f729Sjoerg // Parse the default argument
6925*e038c9c4Sjoerg if (DeclaratorCtx == DeclaratorContext::Member) {
69267330f729Sjoerg // If we're inside a class definition, cache the tokens
69277330f729Sjoerg // corresponding to the default argument. We'll actually parse
69287330f729Sjoerg // them when we see the end of the class definition.
69297330f729Sjoerg DefArgToks.reset(new CachedTokens);
69307330f729Sjoerg
69317330f729Sjoerg SourceLocation ArgStartLoc = NextToken().getLocation();
69327330f729Sjoerg if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
69337330f729Sjoerg DefArgToks.reset();
69347330f729Sjoerg Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
69357330f729Sjoerg } else {
69367330f729Sjoerg Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
69377330f729Sjoerg ArgStartLoc);
69387330f729Sjoerg }
69397330f729Sjoerg } else {
69407330f729Sjoerg // Consume the '='.
69417330f729Sjoerg ConsumeToken();
69427330f729Sjoerg
69437330f729Sjoerg // The argument isn't actually potentially evaluated unless it is
69447330f729Sjoerg // used.
69457330f729Sjoerg EnterExpressionEvaluationContext Eval(
69467330f729Sjoerg Actions,
69477330f729Sjoerg Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed,
69487330f729Sjoerg Param);
69497330f729Sjoerg
69507330f729Sjoerg ExprResult DefArgResult;
69517330f729Sjoerg if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
69527330f729Sjoerg Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
69537330f729Sjoerg DefArgResult = ParseBraceInitializer();
69547330f729Sjoerg } else
69557330f729Sjoerg DefArgResult = ParseAssignmentExpression();
69567330f729Sjoerg DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
69577330f729Sjoerg if (DefArgResult.isInvalid()) {
69587330f729Sjoerg Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
69597330f729Sjoerg SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);
69607330f729Sjoerg } else {
69617330f729Sjoerg // Inform the actions module about the default argument
69627330f729Sjoerg Actions.ActOnParamDefaultArgument(Param, EqualLoc,
69637330f729Sjoerg DefArgResult.get());
69647330f729Sjoerg }
69657330f729Sjoerg }
69667330f729Sjoerg }
69677330f729Sjoerg
69687330f729Sjoerg ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
69697330f729Sjoerg ParmDeclarator.getIdentifierLoc(),
69707330f729Sjoerg Param, std::move(DefArgToks)));
69717330f729Sjoerg }
69727330f729Sjoerg
69737330f729Sjoerg if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
69747330f729Sjoerg if (!getLangOpts().CPlusPlus) {
69757330f729Sjoerg // We have ellipsis without a preceding ',', which is ill-formed
69767330f729Sjoerg // in C. Complain and provide the fix.
69777330f729Sjoerg Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
69787330f729Sjoerg << FixItHint::CreateInsertion(EllipsisLoc, ", ");
69797330f729Sjoerg } else if (ParmDeclarator.getEllipsisLoc().isValid() ||
69807330f729Sjoerg Actions.containsUnexpandedParameterPacks(ParmDeclarator)) {
69817330f729Sjoerg // It looks like this was supposed to be a parameter pack. Warn and
69827330f729Sjoerg // point out where the ellipsis should have gone.
69837330f729Sjoerg SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc();
69847330f729Sjoerg Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg)
69857330f729Sjoerg << ParmEllipsis.isValid() << ParmEllipsis;
69867330f729Sjoerg if (ParmEllipsis.isValid()) {
69877330f729Sjoerg Diag(ParmEllipsis,
69887330f729Sjoerg diag::note_misplaced_ellipsis_vararg_existing_ellipsis);
69897330f729Sjoerg } else {
69907330f729Sjoerg Diag(ParmDeclarator.getIdentifierLoc(),
69917330f729Sjoerg diag::note_misplaced_ellipsis_vararg_add_ellipsis)
69927330f729Sjoerg << FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(),
69937330f729Sjoerg "...")
69947330f729Sjoerg << !ParmDeclarator.hasName();
69957330f729Sjoerg }
69967330f729Sjoerg Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma)
69977330f729Sjoerg << FixItHint::CreateInsertion(EllipsisLoc, ", ");
69987330f729Sjoerg }
69997330f729Sjoerg
70007330f729Sjoerg // We can't have any more parameters after an ellipsis.
70017330f729Sjoerg break;
70027330f729Sjoerg }
70037330f729Sjoerg
70047330f729Sjoerg // If the next token is a comma, consume it and keep reading arguments.
70057330f729Sjoerg } while (TryConsumeToken(tok::comma));
70067330f729Sjoerg }
70077330f729Sjoerg
70087330f729Sjoerg /// [C90] direct-declarator '[' constant-expression[opt] ']'
70097330f729Sjoerg /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
70107330f729Sjoerg /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
70117330f729Sjoerg /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
70127330f729Sjoerg /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
70137330f729Sjoerg /// [C++11] direct-declarator '[' constant-expression[opt] ']'
70147330f729Sjoerg /// attribute-specifier-seq[opt]
ParseBracketDeclarator(Declarator & D)70157330f729Sjoerg void Parser::ParseBracketDeclarator(Declarator &D) {
70167330f729Sjoerg if (CheckProhibitedCXX11Attribute())
70177330f729Sjoerg return;
70187330f729Sjoerg
70197330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_square);
70207330f729Sjoerg T.consumeOpen();
70217330f729Sjoerg
70227330f729Sjoerg // C array syntax has many features, but by-far the most common is [] and [4].
70237330f729Sjoerg // This code does a fast path to handle some of the most obvious cases.
70247330f729Sjoerg if (Tok.getKind() == tok::r_square) {
70257330f729Sjoerg T.consumeClose();
70267330f729Sjoerg ParsedAttributes attrs(AttrFactory);
70277330f729Sjoerg MaybeParseCXX11Attributes(attrs);
70287330f729Sjoerg
70297330f729Sjoerg // Remember that we parsed the empty array type.
70307330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
70317330f729Sjoerg T.getOpenLocation(),
70327330f729Sjoerg T.getCloseLocation()),
70337330f729Sjoerg std::move(attrs), T.getCloseLocation());
70347330f729Sjoerg return;
70357330f729Sjoerg } else if (Tok.getKind() == tok::numeric_constant &&
70367330f729Sjoerg GetLookAheadToken(1).is(tok::r_square)) {
70377330f729Sjoerg // [4] is very common. Parse the numeric constant expression.
70387330f729Sjoerg ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope()));
70397330f729Sjoerg ConsumeToken();
70407330f729Sjoerg
70417330f729Sjoerg T.consumeClose();
70427330f729Sjoerg ParsedAttributes attrs(AttrFactory);
70437330f729Sjoerg MaybeParseCXX11Attributes(attrs);
70447330f729Sjoerg
70457330f729Sjoerg // Remember that we parsed a array type, and remember its features.
70467330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(),
70477330f729Sjoerg T.getOpenLocation(),
70487330f729Sjoerg T.getCloseLocation()),
70497330f729Sjoerg std::move(attrs), T.getCloseLocation());
70507330f729Sjoerg return;
70517330f729Sjoerg } else if (Tok.getKind() == tok::code_completion) {
7052*e038c9c4Sjoerg cutOffParsing();
70537330f729Sjoerg Actions.CodeCompleteBracketDeclarator(getCurScope());
7054*e038c9c4Sjoerg return;
70557330f729Sjoerg }
70567330f729Sjoerg
70577330f729Sjoerg // If valid, this location is the position where we read the 'static' keyword.
70587330f729Sjoerg SourceLocation StaticLoc;
70597330f729Sjoerg TryConsumeToken(tok::kw_static, StaticLoc);
70607330f729Sjoerg
70617330f729Sjoerg // If there is a type-qualifier-list, read it now.
70627330f729Sjoerg // Type qualifiers in an array subscript are a C99 feature.
70637330f729Sjoerg DeclSpec DS(AttrFactory);
70647330f729Sjoerg ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed);
70657330f729Sjoerg
70667330f729Sjoerg // If we haven't already read 'static', check to see if there is one after the
70677330f729Sjoerg // type-qualifier-list.
70687330f729Sjoerg if (!StaticLoc.isValid())
70697330f729Sjoerg TryConsumeToken(tok::kw_static, StaticLoc);
70707330f729Sjoerg
70717330f729Sjoerg // Handle "direct-declarator [ type-qual-list[opt] * ]".
70727330f729Sjoerg bool isStar = false;
70737330f729Sjoerg ExprResult NumElements;
70747330f729Sjoerg
70757330f729Sjoerg // Handle the case where we have '[*]' as the array size. However, a leading
70767330f729Sjoerg // star could be the start of an expression, for example 'X[*p + 4]'. Verify
70777330f729Sjoerg // the token after the star is a ']'. Since stars in arrays are
70787330f729Sjoerg // infrequent, use of lookahead is not costly here.
70797330f729Sjoerg if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) {
70807330f729Sjoerg ConsumeToken(); // Eat the '*'.
70817330f729Sjoerg
70827330f729Sjoerg if (StaticLoc.isValid()) {
70837330f729Sjoerg Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);
70847330f729Sjoerg StaticLoc = SourceLocation(); // Drop the static.
70857330f729Sjoerg }
70867330f729Sjoerg isStar = true;
70877330f729Sjoerg } else if (Tok.isNot(tok::r_square)) {
70887330f729Sjoerg // Note, in C89, this production uses the constant-expr production instead
70897330f729Sjoerg // of assignment-expr. The only difference is that assignment-expr allows
70907330f729Sjoerg // things like '=' and '*='. Sema rejects these in C89 mode because they
70917330f729Sjoerg // are not i-c-e's, so we don't need to distinguish between the two here.
70927330f729Sjoerg
70937330f729Sjoerg // Parse the constant-expression or assignment-expression now (depending
70947330f729Sjoerg // on dialect).
70957330f729Sjoerg if (getLangOpts().CPlusPlus) {
70967330f729Sjoerg NumElements = ParseConstantExpression();
70977330f729Sjoerg } else {
70987330f729Sjoerg EnterExpressionEvaluationContext Unevaluated(
70997330f729Sjoerg Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
71007330f729Sjoerg NumElements =
71017330f729Sjoerg Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
71027330f729Sjoerg }
71037330f729Sjoerg } else {
71047330f729Sjoerg if (StaticLoc.isValid()) {
71057330f729Sjoerg Diag(StaticLoc, diag::err_unspecified_size_with_static);
71067330f729Sjoerg StaticLoc = SourceLocation(); // Drop the static.
71077330f729Sjoerg }
71087330f729Sjoerg }
71097330f729Sjoerg
71107330f729Sjoerg // If there was an error parsing the assignment-expression, recover.
71117330f729Sjoerg if (NumElements.isInvalid()) {
71127330f729Sjoerg D.setInvalidType(true);
71137330f729Sjoerg // If the expression was invalid, skip it.
71147330f729Sjoerg SkipUntil(tok::r_square, StopAtSemi);
71157330f729Sjoerg return;
71167330f729Sjoerg }
71177330f729Sjoerg
71187330f729Sjoerg T.consumeClose();
71197330f729Sjoerg
71207330f729Sjoerg MaybeParseCXX11Attributes(DS.getAttributes());
71217330f729Sjoerg
71227330f729Sjoerg // Remember that we parsed a array type, and remember its features.
71237330f729Sjoerg D.AddTypeInfo(
71247330f729Sjoerg DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(),
71257330f729Sjoerg isStar, NumElements.get(), T.getOpenLocation(),
71267330f729Sjoerg T.getCloseLocation()),
71277330f729Sjoerg std::move(DS.getAttributes()), T.getCloseLocation());
71287330f729Sjoerg }
71297330f729Sjoerg
71307330f729Sjoerg /// Diagnose brackets before an identifier.
ParseMisplacedBracketDeclarator(Declarator & D)71317330f729Sjoerg void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
71327330f729Sjoerg assert(Tok.is(tok::l_square) && "Missing opening bracket");
71337330f729Sjoerg assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier");
71347330f729Sjoerg
71357330f729Sjoerg SourceLocation StartBracketLoc = Tok.getLocation();
71367330f729Sjoerg Declarator TempDeclarator(D.getDeclSpec(), D.getContext());
71377330f729Sjoerg
71387330f729Sjoerg while (Tok.is(tok::l_square)) {
71397330f729Sjoerg ParseBracketDeclarator(TempDeclarator);
71407330f729Sjoerg }
71417330f729Sjoerg
71427330f729Sjoerg // Stuff the location of the start of the brackets into the Declarator.
71437330f729Sjoerg // The diagnostics from ParseDirectDeclarator will make more sense if
71447330f729Sjoerg // they use this location instead.
71457330f729Sjoerg if (Tok.is(tok::semi))
71467330f729Sjoerg D.getName().EndLocation = StartBracketLoc;
71477330f729Sjoerg
71487330f729Sjoerg SourceLocation SuggestParenLoc = Tok.getLocation();
71497330f729Sjoerg
71507330f729Sjoerg // Now that the brackets are removed, try parsing the declarator again.
71517330f729Sjoerg ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
71527330f729Sjoerg
71537330f729Sjoerg // Something went wrong parsing the brackets, in which case,
71547330f729Sjoerg // ParseBracketDeclarator has emitted an error, and we don't need to emit
71557330f729Sjoerg // one here.
71567330f729Sjoerg if (TempDeclarator.getNumTypeObjects() == 0)
71577330f729Sjoerg return;
71587330f729Sjoerg
71597330f729Sjoerg // Determine if parens will need to be suggested in the diagnostic.
71607330f729Sjoerg bool NeedParens = false;
71617330f729Sjoerg if (D.getNumTypeObjects() != 0) {
71627330f729Sjoerg switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) {
71637330f729Sjoerg case DeclaratorChunk::Pointer:
71647330f729Sjoerg case DeclaratorChunk::Reference:
71657330f729Sjoerg case DeclaratorChunk::BlockPointer:
71667330f729Sjoerg case DeclaratorChunk::MemberPointer:
71677330f729Sjoerg case DeclaratorChunk::Pipe:
71687330f729Sjoerg NeedParens = true;
71697330f729Sjoerg break;
71707330f729Sjoerg case DeclaratorChunk::Array:
71717330f729Sjoerg case DeclaratorChunk::Function:
71727330f729Sjoerg case DeclaratorChunk::Paren:
71737330f729Sjoerg break;
71747330f729Sjoerg }
71757330f729Sjoerg }
71767330f729Sjoerg
71777330f729Sjoerg if (NeedParens) {
71787330f729Sjoerg // Create a DeclaratorChunk for the inserted parens.
71797330f729Sjoerg SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
71807330f729Sjoerg D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc),
71817330f729Sjoerg SourceLocation());
71827330f729Sjoerg }
71837330f729Sjoerg
71847330f729Sjoerg // Adding back the bracket info to the end of the Declarator.
71857330f729Sjoerg for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {
71867330f729Sjoerg const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);
71877330f729Sjoerg D.AddTypeInfo(Chunk, SourceLocation());
71887330f729Sjoerg }
71897330f729Sjoerg
71907330f729Sjoerg // The missing identifier would have been diagnosed in ParseDirectDeclarator.
71917330f729Sjoerg // If parentheses are required, always suggest them.
71927330f729Sjoerg if (!D.getIdentifier() && !NeedParens)
71937330f729Sjoerg return;
71947330f729Sjoerg
71957330f729Sjoerg SourceLocation EndBracketLoc = TempDeclarator.getEndLoc();
71967330f729Sjoerg
71977330f729Sjoerg // Generate the move bracket error message.
71987330f729Sjoerg SourceRange BracketRange(StartBracketLoc, EndBracketLoc);
71997330f729Sjoerg SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());
72007330f729Sjoerg
72017330f729Sjoerg if (NeedParens) {
72027330f729Sjoerg Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
72037330f729Sjoerg << getLangOpts().CPlusPlus
72047330f729Sjoerg << FixItHint::CreateInsertion(SuggestParenLoc, "(")
72057330f729Sjoerg << FixItHint::CreateInsertion(EndLoc, ")")
72067330f729Sjoerg << FixItHint::CreateInsertionFromRange(
72077330f729Sjoerg EndLoc, CharSourceRange(BracketRange, true))
72087330f729Sjoerg << FixItHint::CreateRemoval(BracketRange);
72097330f729Sjoerg } else {
72107330f729Sjoerg Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)
72117330f729Sjoerg << getLangOpts().CPlusPlus
72127330f729Sjoerg << FixItHint::CreateInsertionFromRange(
72137330f729Sjoerg EndLoc, CharSourceRange(BracketRange, true))
72147330f729Sjoerg << FixItHint::CreateRemoval(BracketRange);
72157330f729Sjoerg }
72167330f729Sjoerg }
72177330f729Sjoerg
72187330f729Sjoerg /// [GNU] typeof-specifier:
72197330f729Sjoerg /// typeof ( expressions )
72207330f729Sjoerg /// typeof ( type-name )
72217330f729Sjoerg /// [GNU/C++] typeof unary-expression
72227330f729Sjoerg ///
ParseTypeofSpecifier(DeclSpec & DS)72237330f729Sjoerg void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
72247330f729Sjoerg assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier");
72257330f729Sjoerg Token OpTok = Tok;
72267330f729Sjoerg SourceLocation StartLoc = ConsumeToken();
72277330f729Sjoerg
72287330f729Sjoerg const bool hasParens = Tok.is(tok::l_paren);
72297330f729Sjoerg
72307330f729Sjoerg EnterExpressionEvaluationContext Unevaluated(
72317330f729Sjoerg Actions, Sema::ExpressionEvaluationContext::Unevaluated,
72327330f729Sjoerg Sema::ReuseLambdaContextDecl);
72337330f729Sjoerg
72347330f729Sjoerg bool isCastExpr;
72357330f729Sjoerg ParsedType CastTy;
72367330f729Sjoerg SourceRange CastRange;
72377330f729Sjoerg ExprResult Operand = Actions.CorrectDelayedTyposInExpr(
72387330f729Sjoerg ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));
72397330f729Sjoerg if (hasParens)
72407330f729Sjoerg DS.setTypeofParensRange(CastRange);
72417330f729Sjoerg
72427330f729Sjoerg if (CastRange.getEnd().isInvalid())
72437330f729Sjoerg // FIXME: Not accurate, the range gets one token more than it should.
72447330f729Sjoerg DS.SetRangeEnd(Tok.getLocation());
72457330f729Sjoerg else
72467330f729Sjoerg DS.SetRangeEnd(CastRange.getEnd());
72477330f729Sjoerg
72487330f729Sjoerg if (isCastExpr) {
72497330f729Sjoerg if (!CastTy) {
72507330f729Sjoerg DS.SetTypeSpecError();
72517330f729Sjoerg return;
72527330f729Sjoerg }
72537330f729Sjoerg
72547330f729Sjoerg const char *PrevSpec = nullptr;
72557330f729Sjoerg unsigned DiagID;
72567330f729Sjoerg // Check for duplicate type specifiers (e.g. "int typeof(int)").
72577330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
72587330f729Sjoerg DiagID, CastTy,
72597330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
72607330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
72617330f729Sjoerg return;
72627330f729Sjoerg }
72637330f729Sjoerg
72647330f729Sjoerg // If we get here, the operand to the typeof was an expression.
72657330f729Sjoerg if (Operand.isInvalid()) {
72667330f729Sjoerg DS.SetTypeSpecError();
72677330f729Sjoerg return;
72687330f729Sjoerg }
72697330f729Sjoerg
72707330f729Sjoerg // We might need to transform the operand if it is potentially evaluated.
72717330f729Sjoerg Operand = Actions.HandleExprEvaluationContextForTypeof(Operand.get());
72727330f729Sjoerg if (Operand.isInvalid()) {
72737330f729Sjoerg DS.SetTypeSpecError();
72747330f729Sjoerg return;
72757330f729Sjoerg }
72767330f729Sjoerg
72777330f729Sjoerg const char *PrevSpec = nullptr;
72787330f729Sjoerg unsigned DiagID;
72797330f729Sjoerg // Check for duplicate type specifiers (e.g. "int typeof(int)").
72807330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
72817330f729Sjoerg DiagID, Operand.get(),
72827330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
72837330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
72847330f729Sjoerg }
72857330f729Sjoerg
72867330f729Sjoerg /// [C11] atomic-specifier:
72877330f729Sjoerg /// _Atomic ( type-name )
72887330f729Sjoerg ///
ParseAtomicSpecifier(DeclSpec & DS)72897330f729Sjoerg void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
72907330f729Sjoerg assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) &&
72917330f729Sjoerg "Not an atomic specifier");
72927330f729Sjoerg
72937330f729Sjoerg SourceLocation StartLoc = ConsumeToken();
72947330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
72957330f729Sjoerg if (T.consumeOpen())
72967330f729Sjoerg return;
72977330f729Sjoerg
72987330f729Sjoerg TypeResult Result = ParseTypeName();
72997330f729Sjoerg if (Result.isInvalid()) {
73007330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
73017330f729Sjoerg return;
73027330f729Sjoerg }
73037330f729Sjoerg
73047330f729Sjoerg // Match the ')'
73057330f729Sjoerg T.consumeClose();
73067330f729Sjoerg
73077330f729Sjoerg if (T.getCloseLocation().isInvalid())
73087330f729Sjoerg return;
73097330f729Sjoerg
73107330f729Sjoerg DS.setTypeofParensRange(T.getRange());
73117330f729Sjoerg DS.SetRangeEnd(T.getCloseLocation());
73127330f729Sjoerg
73137330f729Sjoerg const char *PrevSpec = nullptr;
73147330f729Sjoerg unsigned DiagID;
73157330f729Sjoerg if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,
73167330f729Sjoerg DiagID, Result.get(),
73177330f729Sjoerg Actions.getASTContext().getPrintingPolicy()))
73187330f729Sjoerg Diag(StartLoc, DiagID) << PrevSpec;
73197330f729Sjoerg }
73207330f729Sjoerg
73217330f729Sjoerg /// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
73227330f729Sjoerg /// from TryAltiVecVectorToken.
TryAltiVecVectorTokenOutOfLine()73237330f729Sjoerg bool Parser::TryAltiVecVectorTokenOutOfLine() {
73247330f729Sjoerg Token Next = NextToken();
73257330f729Sjoerg switch (Next.getKind()) {
73267330f729Sjoerg default: return false;
73277330f729Sjoerg case tok::kw_short:
73287330f729Sjoerg case tok::kw_long:
73297330f729Sjoerg case tok::kw_signed:
73307330f729Sjoerg case tok::kw_unsigned:
73317330f729Sjoerg case tok::kw_void:
73327330f729Sjoerg case tok::kw_char:
73337330f729Sjoerg case tok::kw_int:
73347330f729Sjoerg case tok::kw_float:
73357330f729Sjoerg case tok::kw_double:
73367330f729Sjoerg case tok::kw_bool:
7337*e038c9c4Sjoerg case tok::kw__Bool:
73387330f729Sjoerg case tok::kw___bool:
73397330f729Sjoerg case tok::kw___pixel:
73407330f729Sjoerg Tok.setKind(tok::kw___vector);
73417330f729Sjoerg return true;
73427330f729Sjoerg case tok::identifier:
73437330f729Sjoerg if (Next.getIdentifierInfo() == Ident_pixel) {
73447330f729Sjoerg Tok.setKind(tok::kw___vector);
73457330f729Sjoerg return true;
73467330f729Sjoerg }
7347*e038c9c4Sjoerg if (Next.getIdentifierInfo() == Ident_bool ||
7348*e038c9c4Sjoerg Next.getIdentifierInfo() == Ident_Bool) {
73497330f729Sjoerg Tok.setKind(tok::kw___vector);
73507330f729Sjoerg return true;
73517330f729Sjoerg }
73527330f729Sjoerg return false;
73537330f729Sjoerg }
73547330f729Sjoerg }
73557330f729Sjoerg
TryAltiVecTokenOutOfLine(DeclSpec & DS,SourceLocation Loc,const char * & PrevSpec,unsigned & DiagID,bool & isInvalid)73567330f729Sjoerg bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
73577330f729Sjoerg const char *&PrevSpec, unsigned &DiagID,
73587330f729Sjoerg bool &isInvalid) {
73597330f729Sjoerg const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
73607330f729Sjoerg if (Tok.getIdentifierInfo() == Ident_vector) {
73617330f729Sjoerg Token Next = NextToken();
73627330f729Sjoerg switch (Next.getKind()) {
73637330f729Sjoerg case tok::kw_short:
73647330f729Sjoerg case tok::kw_long:
73657330f729Sjoerg case tok::kw_signed:
73667330f729Sjoerg case tok::kw_unsigned:
73677330f729Sjoerg case tok::kw_void:
73687330f729Sjoerg case tok::kw_char:
73697330f729Sjoerg case tok::kw_int:
73707330f729Sjoerg case tok::kw_float:
73717330f729Sjoerg case tok::kw_double:
73727330f729Sjoerg case tok::kw_bool:
7373*e038c9c4Sjoerg case tok::kw__Bool:
73747330f729Sjoerg case tok::kw___bool:
73757330f729Sjoerg case tok::kw___pixel:
73767330f729Sjoerg isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
73777330f729Sjoerg return true;
73787330f729Sjoerg case tok::identifier:
73797330f729Sjoerg if (Next.getIdentifierInfo() == Ident_pixel) {
73807330f729Sjoerg isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
73817330f729Sjoerg return true;
73827330f729Sjoerg }
7383*e038c9c4Sjoerg if (Next.getIdentifierInfo() == Ident_bool ||
7384*e038c9c4Sjoerg Next.getIdentifierInfo() == Ident_Bool) {
7385*e038c9c4Sjoerg isInvalid =
7386*e038c9c4Sjoerg DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
73877330f729Sjoerg return true;
73887330f729Sjoerg }
73897330f729Sjoerg break;
73907330f729Sjoerg default:
73917330f729Sjoerg break;
73927330f729Sjoerg }
73937330f729Sjoerg } else if ((Tok.getIdentifierInfo() == Ident_pixel) &&
73947330f729Sjoerg DS.isTypeAltiVecVector()) {
73957330f729Sjoerg isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);
73967330f729Sjoerg return true;
73977330f729Sjoerg } else if ((Tok.getIdentifierInfo() == Ident_bool) &&
73987330f729Sjoerg DS.isTypeAltiVecVector()) {
73997330f729Sjoerg isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
74007330f729Sjoerg return true;
74017330f729Sjoerg }
74027330f729Sjoerg return false;
74037330f729Sjoerg }
7404