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