ParseTentative.cpp revision 245431
1193326Sed//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements the tentative parsing portions of the Parser 11193326Sed// interfaces, for ambiguity resolution. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed 15193326Sed#include "clang/Parse/Parser.h" 16193326Sed#include "clang/Parse/ParseDiagnostic.h" 17212904Sdim#include "clang/Sema/ParsedTemplate.h" 18193326Sedusing namespace clang; 19193326Sed 20193326Sed/// isCXXDeclarationStatement - C++-specialized function that disambiguates 21193326Sed/// between a declaration or an expression statement, when parsing function 22193326Sed/// bodies. Returns true for declaration, false for expression. 23193326Sed/// 24193326Sed/// declaration-statement: 25193326Sed/// block-declaration 26193326Sed/// 27193326Sed/// block-declaration: 28193326Sed/// simple-declaration 29193326Sed/// asm-definition 30193326Sed/// namespace-alias-definition 31193326Sed/// using-declaration 32193326Sed/// using-directive 33193326Sed/// [C++0x] static_assert-declaration 34193326Sed/// 35193326Sed/// asm-definition: 36193326Sed/// 'asm' '(' string-literal ')' ';' 37193326Sed/// 38193326Sed/// namespace-alias-definition: 39193326Sed/// 'namespace' identifier = qualified-namespace-specifier ';' 40193326Sed/// 41193326Sed/// using-declaration: 42193326Sed/// 'using' typename[opt] '::'[opt] nested-name-specifier 43193326Sed/// unqualified-id ';' 44193326Sed/// 'using' '::' unqualified-id ; 45193326Sed/// 46193326Sed/// using-directive: 47193326Sed/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt] 48193326Sed/// namespace-name ';' 49193326Sed/// 50193326Sedbool Parser::isCXXDeclarationStatement() { 51193326Sed switch (Tok.getKind()) { 52193326Sed // asm-definition 53193326Sed case tok::kw_asm: 54193326Sed // namespace-alias-definition 55193326Sed case tok::kw_namespace: 56193326Sed // using-declaration 57193326Sed // using-directive 58193326Sed case tok::kw_using: 59199990Srdivacky // static_assert-declaration 60193326Sed case tok::kw_static_assert: 61221345Sdim case tok::kw__Static_assert: 62193326Sed return true; 63199990Srdivacky // simple-declaration 64193326Sed default: 65235633Sdim return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false); 66193326Sed } 67193326Sed} 68193326Sed 69193326Sed/// isCXXSimpleDeclaration - C++-specialized function that disambiguates 70193326Sed/// between a simple-declaration or an expression-statement. 71193326Sed/// If during the disambiguation process a parsing error is encountered, 72193326Sed/// the function returns true to let the declaration parsing code handle it. 73193326Sed/// Returns false if the statement is disambiguated as expression. 74193326Sed/// 75193326Sed/// simple-declaration: 76193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 77193326Sed/// 78235633Sdim/// (if AllowForRangeDecl specified) 79235633Sdim/// for ( for-range-declaration : for-range-initializer ) statement 80235633Sdim/// for-range-declaration: 81235633Sdim/// attribute-specifier-seqopt type-specifier-seq declarator 82235633Sdimbool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) { 83193326Sed // C++ 6.8p1: 84193326Sed // There is an ambiguity in the grammar involving expression-statements and 85193326Sed // declarations: An expression-statement with a function-style explicit type 86193326Sed // conversion (5.2.3) as its leftmost subexpression can be indistinguishable 87193326Sed // from a declaration where the first declarator starts with a '('. In those 88193326Sed // cases the statement is a declaration. [Note: To disambiguate, the whole 89193326Sed // statement might have to be examined to determine if it is an 90193326Sed // expression-statement or a declaration]. 91193326Sed 92193326Sed // C++ 6.8p3: 93193326Sed // The disambiguation is purely syntactic; that is, the meaning of the names 94193326Sed // occurring in such a statement, beyond whether they are type-names or not, 95193326Sed // is not generally used in or changed by the disambiguation. Class 96193326Sed // templates are instantiated as necessary to determine if a qualified name 97193326Sed // is a type-name. Disambiguation precedes parsing, and a statement 98193326Sed // disambiguated as a declaration may be an ill-formed declaration. 99193326Sed 100193326Sed // We don't have to parse all of the decl-specifier-seq part. There's only 101193326Sed // an ambiguity if the first decl-specifier is 102193326Sed // simple-type-specifier/typename-specifier followed by a '(', which may 103193326Sed // indicate a function-style cast expression. 104193326Sed // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such 105193326Sed // a case. 106193326Sed 107245431Sdim bool InvalidAsDeclaration = false; 108245431Sdim TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), 109245431Sdim &InvalidAsDeclaration); 110193326Sed if (TPR != TPResult::Ambiguous()) 111193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 112193326Sed // TPResult::Error(). 113193326Sed 114245431Sdim // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer, 115245431Sdim // and so gets some cases wrong. We can't carry on if we've already seen 116245431Sdim // something which makes this statement invalid as a declaration in this case, 117245431Sdim // since it can cause us to misparse valid code. Revisit this once 118245431Sdim // TryParseInitDeclaratorList is fixed. 119245431Sdim if (InvalidAsDeclaration) 120245431Sdim return false; 121245431Sdim 122193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 123193326Sed // and how they were resolved (number of declarations+number of expressions). 124193326Sed 125245431Sdim // Ok, we have a simple-type-specifier/typename-specifier followed by a '(', 126245431Sdim // or an identifier which doesn't resolve as anything. We need tentative 127245431Sdim // parsing... 128193326Sed 129193326Sed TentativeParsingAction PA(*this); 130235633Sdim TPR = TryParseSimpleDeclaration(AllowForRangeDecl); 131193326Sed PA.Revert(); 132193326Sed 133193326Sed // In case of an error, let the declaration parsing code handle it. 134193326Sed if (TPR == TPResult::Error()) 135193326Sed return true; 136193326Sed 137193326Sed // Declarations take precedence over expressions. 138193326Sed if (TPR == TPResult::Ambiguous()) 139193326Sed TPR = TPResult::True(); 140193326Sed 141193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 142193326Sed return TPR == TPResult::True(); 143193326Sed} 144193326Sed 145193326Sed/// simple-declaration: 146193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 147193326Sed/// 148235633Sdim/// (if AllowForRangeDecl specified) 149235633Sdim/// for ( for-range-declaration : for-range-initializer ) statement 150235633Sdim/// for-range-declaration: 151235633Sdim/// attribute-specifier-seqopt type-specifier-seq declarator 152235633Sdim/// 153235633SdimParser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) { 154193326Sed if (Tok.is(tok::kw_typeof)) 155193326Sed TryParseTypeofSpecifier(); 156218893Sdim else { 157245431Sdim if (Tok.is(tok::annot_cxxscope)) 158245431Sdim ConsumeToken(); 159193326Sed ConsumeToken(); 160245431Sdim 161235633Sdim if (getLangOpts().ObjC1 && Tok.is(tok::less)) 162218893Sdim TryParseProtocolQualifiers(); 163218893Sdim } 164193326Sed 165245431Sdim // Two decl-specifiers in a row conclusively disambiguate this as being a 166245431Sdim // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the 167245431Sdim // overwhelmingly common case that the next token is a '('. 168245431Sdim if (Tok.isNot(tok::l_paren)) { 169245431Sdim TPResult TPR = isCXXDeclarationSpecifier(); 170245431Sdim if (TPR == TPResult::Ambiguous()) 171245431Sdim return TPResult::True(); 172245431Sdim if (TPR == TPResult::True() || TPR == TPResult::Error()) 173245431Sdim return TPR; 174245431Sdim assert(TPR == TPResult::False()); 175245431Sdim } 176245431Sdim 177193326Sed TPResult TPR = TryParseInitDeclaratorList(); 178193326Sed if (TPR != TPResult::Ambiguous()) 179193326Sed return TPR; 180193326Sed 181235633Sdim if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon))) 182193326Sed return TPResult::False(); 183193326Sed 184193326Sed return TPResult::Ambiguous(); 185193326Sed} 186193326Sed 187193326Sed/// init-declarator-list: 188193326Sed/// init-declarator 189193326Sed/// init-declarator-list ',' init-declarator 190193326Sed/// 191193326Sed/// init-declarator: 192193326Sed/// declarator initializer[opt] 193193326Sed/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt] 194193326Sed/// 195193326Sed/// initializer: 196193326Sed/// '=' initializer-clause 197193326Sed/// '(' expression-list ')' 198193326Sed/// 199193326Sed/// initializer-clause: 200193326Sed/// assignment-expression 201193326Sed/// '{' initializer-list ','[opt] '}' 202193326Sed/// '{' '}' 203193326Sed/// 204193326SedParser::TPResult Parser::TryParseInitDeclaratorList() { 205193326Sed while (1) { 206193326Sed // declarator 207193326Sed TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); 208193326Sed if (TPR != TPResult::Ambiguous()) 209193326Sed return TPR; 210193326Sed 211193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 212193326Sed if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 213193326Sed return TPResult::True(); 214193326Sed 215193326Sed // initializer[opt] 216193326Sed if (Tok.is(tok::l_paren)) { 217193326Sed // Parse through the parens. 218193326Sed ConsumeParen(); 219193326Sed if (!SkipUntil(tok::r_paren)) 220193326Sed return TPResult::Error(); 221212904Sdim } else if (Tok.is(tok::equal) || isTokIdentifier_in()) { 222212904Sdim // MSVC and g++ won't examine the rest of declarators if '=' is 223212904Sdim // encountered; they just conclude that we have a declaration. 224212904Sdim // EDG parses the initializer completely, which is the proper behavior 225212904Sdim // for this case. 226193326Sed // 227212904Sdim // At present, Clang follows MSVC and g++, since the parser does not have 228212904Sdim // the ability to parse an expression fully without recording the 229212904Sdim // results of that parse. 230212904Sdim // Also allow 'in' after on objective-c declaration as in: 231212904Sdim // for (int (^b)(void) in array). Ideally this should be done in the 232212904Sdim // context of parsing for-init-statement of a foreach statement only. But, 233212904Sdim // in any other context 'in' is invalid after a declaration and parser 234212904Sdim // issues the error regardless of outcome of this decision. 235212904Sdim // FIXME. Change if above assumption does not hold. 236212904Sdim return TPResult::True(); 237193326Sed } 238193326Sed 239193326Sed if (Tok.isNot(tok::comma)) 240193326Sed break; 241193326Sed ConsumeToken(); // the comma. 242193326Sed } 243193326Sed 244193326Sed return TPResult::Ambiguous(); 245193326Sed} 246193326Sed 247193326Sed/// isCXXConditionDeclaration - Disambiguates between a declaration or an 248193326Sed/// expression for a condition of a if/switch/while/for statement. 249193326Sed/// If during the disambiguation process a parsing error is encountered, 250193326Sed/// the function returns true to let the declaration parsing code handle it. 251193326Sed/// 252193326Sed/// condition: 253193326Sed/// expression 254193326Sed/// type-specifier-seq declarator '=' assignment-expression 255235633Sdim/// [C++11] type-specifier-seq declarator '=' initializer-clause 256235633Sdim/// [C++11] type-specifier-seq declarator braced-init-list 257193326Sed/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 258193326Sed/// '=' assignment-expression 259193326Sed/// 260193326Sedbool Parser::isCXXConditionDeclaration() { 261193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 262193326Sed if (TPR != TPResult::Ambiguous()) 263193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 264193326Sed // TPResult::Error(). 265193326Sed 266193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 267193326Sed // and how they were resolved (number of declarations+number of expressions). 268193326Sed 269193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 270193326Sed // We need tentative parsing... 271193326Sed 272193326Sed TentativeParsingAction PA(*this); 273193326Sed 274193326Sed // type-specifier-seq 275193326Sed if (Tok.is(tok::kw_typeof)) 276193326Sed TryParseTypeofSpecifier(); 277218893Sdim else { 278193326Sed ConsumeToken(); 279218893Sdim 280235633Sdim if (getLangOpts().ObjC1 && Tok.is(tok::less)) 281218893Sdim TryParseProtocolQualifiers(); 282218893Sdim } 283193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 284193326Sed 285193326Sed // declarator 286193326Sed TPR = TryParseDeclarator(false/*mayBeAbstract*/); 287193326Sed 288193326Sed // In case of an error, let the declaration parsing code handle it. 289193326Sed if (TPR == TPResult::Error()) 290193326Sed TPR = TPResult::True(); 291193326Sed 292193326Sed if (TPR == TPResult::Ambiguous()) { 293193326Sed // '=' 294193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 295193326Sed if (Tok.is(tok::equal) || 296193326Sed Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 297193326Sed TPR = TPResult::True(); 298235633Sdim else if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) 299235633Sdim TPR = TPResult::True(); 300193326Sed else 301193326Sed TPR = TPResult::False(); 302193326Sed } 303193326Sed 304193326Sed PA.Revert(); 305193326Sed 306193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 307193326Sed return TPR == TPResult::True(); 308193326Sed} 309193326Sed 310198092Srdivacky /// \brief Determine whether the next set of tokens contains a type-id. 311193326Sed /// 312193326Sed /// The context parameter states what context we're parsing right 313193326Sed /// now, which affects how this routine copes with the token 314193326Sed /// following the type-id. If the context is TypeIdInParens, we have 315193326Sed /// already parsed the '(' and we will cease lookahead when we hit 316193326Sed /// the corresponding ')'. If the context is 317193326Sed /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' 318193326Sed /// before this template argument, and will cease lookahead when we 319193326Sed /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id 320193326Sed /// and false for an expression. If during the disambiguation 321193326Sed /// process a parsing error is encountered, the function returns 322193326Sed /// true to let the declaration parsing code handle it. 323193326Sed /// 324193326Sed /// type-id: 325193326Sed /// type-specifier-seq abstract-declarator[opt] 326193326Sed /// 327193326Sedbool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { 328198092Srdivacky 329193326Sed isAmbiguous = false; 330193326Sed 331193326Sed // C++ 8.2p2: 332193326Sed // The ambiguity arising from the similarity between a function-style cast and 333193326Sed // a type-id can occur in different contexts. The ambiguity appears as a 334193326Sed // choice between a function-style cast expression and a declaration of a 335193326Sed // type. The resolution is that any construct that could possibly be a type-id 336193326Sed // in its syntactic context shall be considered a type-id. 337193326Sed 338193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 339193326Sed if (TPR != TPResult::Ambiguous()) 340193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 341193326Sed // TPResult::Error(). 342193326Sed 343193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 344193326Sed // and how they were resolved (number of declarations+number of expressions). 345193326Sed 346193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 347193326Sed // We need tentative parsing... 348193326Sed 349193326Sed TentativeParsingAction PA(*this); 350193326Sed 351193326Sed // type-specifier-seq 352193326Sed if (Tok.is(tok::kw_typeof)) 353193326Sed TryParseTypeofSpecifier(); 354218893Sdim else { 355193326Sed ConsumeToken(); 356218893Sdim 357235633Sdim if (getLangOpts().ObjC1 && Tok.is(tok::less)) 358218893Sdim TryParseProtocolQualifiers(); 359218893Sdim } 360218893Sdim 361193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 362193326Sed 363193326Sed // declarator 364193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); 365193326Sed 366193326Sed // In case of an error, let the declaration parsing code handle it. 367193326Sed if (TPR == TPResult::Error()) 368193326Sed TPR = TPResult::True(); 369193326Sed 370193326Sed if (TPR == TPResult::Ambiguous()) { 371193326Sed // We are supposed to be inside parens, so if after the abstract declarator 372193326Sed // we encounter a ')' this is a type-id, otherwise it's an expression. 373193326Sed if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { 374193326Sed TPR = TPResult::True(); 375193326Sed isAmbiguous = true; 376193326Sed 377193326Sed // We are supposed to be inside a template argument, so if after 378193326Sed // the abstract declarator we encounter a '>', '>>' (in C++0x), or 379193326Sed // ',', this is a type-id. Otherwise, it's an expression. 380193326Sed } else if (Context == TypeIdAsTemplateArgument && 381193326Sed (Tok.is(tok::greater) || Tok.is(tok::comma) || 382235633Sdim (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)))) { 383193326Sed TPR = TPResult::True(); 384193326Sed isAmbiguous = true; 385193326Sed 386193326Sed } else 387193326Sed TPR = TPResult::False(); 388193326Sed } 389193326Sed 390193326Sed PA.Revert(); 391193326Sed 392193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 393193326Sed return TPR == TPResult::True(); 394193326Sed} 395193326Sed 396235633Sdim/// \brief Returns true if this is a C++11 attribute-specifier. Per 397235633Sdim/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens 398235633Sdim/// always introduce an attribute. In Objective-C++11, this rule does not 399235633Sdim/// apply if either '[' begins a message-send. 400199990Srdivacky/// 401235633Sdim/// If Disambiguate is true, we try harder to determine whether a '[[' starts 402235633Sdim/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not. 403199990Srdivacky/// 404235633Sdim/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an 405235633Sdim/// Obj-C message send or the start of an attribute. Otherwise, we assume it 406235633Sdim/// is not an Obj-C message send. 407199990Srdivacky/// 408235633Sdim/// C++11 [dcl.attr.grammar]: 409235633Sdim/// 410235633Sdim/// attribute-specifier: 411199990Srdivacky/// '[' '[' attribute-list ']' ']' 412226890Sdim/// alignment-specifier 413199990Srdivacky/// 414235633Sdim/// attribute-list: 415199990Srdivacky/// attribute[opt] 416199990Srdivacky/// attribute-list ',' attribute[opt] 417235633Sdim/// attribute '...' 418235633Sdim/// attribute-list ',' attribute '...' 419199990Srdivacky/// 420235633Sdim/// attribute: 421199990Srdivacky/// attribute-token attribute-argument-clause[opt] 422199990Srdivacky/// 423235633Sdim/// attribute-token: 424199990Srdivacky/// identifier 425235633Sdim/// identifier '::' identifier 426199990Srdivacky/// 427235633Sdim/// attribute-argument-clause: 428199990Srdivacky/// '(' balanced-token-seq ')' 429235633SdimParser::CXX11AttributeKind 430235633SdimParser::isCXX11AttributeSpecifier(bool Disambiguate, 431235633Sdim bool OuterMightBeMessageSend) { 432226890Sdim if (Tok.is(tok::kw_alignas)) 433235633Sdim return CAK_AttributeSpecifier; 434226890Sdim 435199990Srdivacky if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) 436235633Sdim return CAK_NotAttributeSpecifier; 437199990Srdivacky 438235633Sdim // No tentative parsing if we don't need to look for ']]' or a lambda. 439235633Sdim if (!Disambiguate && !getLangOpts().ObjC1) 440235633Sdim return CAK_AttributeSpecifier; 441199990Srdivacky 442235633Sdim TentativeParsingAction PA(*this); 443235633Sdim 444199990Srdivacky // Opening brackets were checked for above. 445199990Srdivacky ConsumeBracket(); 446199990Srdivacky 447235633Sdim // Outside Obj-C++11, treat anything with a matching ']]' as an attribute. 448235633Sdim if (!getLangOpts().ObjC1) { 449235633Sdim ConsumeBracket(); 450199990Srdivacky 451235633Sdim bool IsAttribute = SkipUntil(tok::r_square, false); 452235633Sdim IsAttribute &= Tok.is(tok::r_square); 453235633Sdim 454235633Sdim PA.Revert(); 455235633Sdim 456235633Sdim return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier; 457235633Sdim } 458235633Sdim 459235633Sdim // In Obj-C++11, we need to distinguish four situations: 460235633Sdim // 1a) int x[[attr]]; C++11 attribute. 461235633Sdim // 1b) [[attr]]; C++11 statement attribute. 462235633Sdim // 2) int x[[obj](){ return 1; }()]; Lambda in array size/index. 463235633Sdim // 3a) int x[[obj get]]; Message send in array size/index. 464235633Sdim // 3b) [[Class alloc] init]; Message send in message send. 465235633Sdim // 4) [[obj]{ return self; }() doStuff]; Lambda in message send. 466235633Sdim // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted. 467235633Sdim 468235633Sdim // If we have a lambda-introducer, then this is definitely not a message send. 469235633Sdim // FIXME: If this disambiguation is too slow, fold the tentative lambda parse 470235633Sdim // into the tentative attribute parse below. 471235633Sdim LambdaIntroducer Intro; 472235633Sdim if (!TryParseLambdaIntroducer(Intro)) { 473235633Sdim // A lambda cannot end with ']]', and an attribute must. 474235633Sdim bool IsAttribute = Tok.is(tok::r_square); 475235633Sdim 476235633Sdim PA.Revert(); 477235633Sdim 478235633Sdim if (IsAttribute) 479235633Sdim // Case 1: C++11 attribute. 480235633Sdim return CAK_AttributeSpecifier; 481235633Sdim 482235633Sdim if (OuterMightBeMessageSend) 483235633Sdim // Case 4: Lambda in message send. 484235633Sdim return CAK_NotAttributeSpecifier; 485235633Sdim 486235633Sdim // Case 2: Lambda in array size / index. 487235633Sdim return CAK_InvalidAttributeSpecifier; 488235633Sdim } 489235633Sdim 490199990Srdivacky ConsumeBracket(); 491199990Srdivacky 492235633Sdim // If we don't have a lambda-introducer, then we have an attribute or a 493235633Sdim // message-send. 494235633Sdim bool IsAttribute = true; 495235633Sdim while (Tok.isNot(tok::r_square)) { 496235633Sdim if (Tok.is(tok::comma)) { 497235633Sdim // Case 1: Stray commas can only occur in attributes. 498235633Sdim PA.Revert(); 499235633Sdim return CAK_AttributeSpecifier; 500235633Sdim } 501199990Srdivacky 502235633Sdim // Parse the attribute-token, if present. 503235633Sdim // C++11 [dcl.attr.grammar]: 504235633Sdim // If a keyword or an alternative token that satisfies the syntactic 505235633Sdim // requirements of an identifier is contained in an attribute-token, 506235633Sdim // it is considered an identifier. 507235633Sdim SourceLocation Loc; 508235633Sdim if (!TryParseCXX11AttributeIdentifier(Loc)) { 509235633Sdim IsAttribute = false; 510235633Sdim break; 511235633Sdim } 512235633Sdim if (Tok.is(tok::coloncolon)) { 513235633Sdim ConsumeToken(); 514235633Sdim if (!TryParseCXX11AttributeIdentifier(Loc)) { 515235633Sdim IsAttribute = false; 516235633Sdim break; 517235633Sdim } 518235633Sdim } 519235633Sdim 520235633Sdim // Parse the attribute-argument-clause, if present. 521235633Sdim if (Tok.is(tok::l_paren)) { 522235633Sdim ConsumeParen(); 523235633Sdim if (!SkipUntil(tok::r_paren, false)) { 524235633Sdim IsAttribute = false; 525235633Sdim break; 526235633Sdim } 527235633Sdim } 528235633Sdim 529235633Sdim if (Tok.is(tok::ellipsis)) 530235633Sdim ConsumeToken(); 531235633Sdim 532235633Sdim if (Tok.isNot(tok::comma)) 533235633Sdim break; 534235633Sdim 535235633Sdim ConsumeToken(); 536235633Sdim } 537235633Sdim 538235633Sdim // An attribute must end ']]'. 539235633Sdim if (IsAttribute) { 540235633Sdim if (Tok.is(tok::r_square)) { 541235633Sdim ConsumeBracket(); 542235633Sdim IsAttribute = Tok.is(tok::r_square); 543235633Sdim } else { 544235633Sdim IsAttribute = false; 545235633Sdim } 546235633Sdim } 547235633Sdim 548235633Sdim PA.Revert(); 549235633Sdim 550235633Sdim if (IsAttribute) 551235633Sdim // Case 1: C++11 statement attribute. 552235633Sdim return CAK_AttributeSpecifier; 553235633Sdim 554235633Sdim // Case 3: Message send. 555235633Sdim return CAK_NotAttributeSpecifier; 556199990Srdivacky} 557199990Srdivacky 558193326Sed/// declarator: 559193326Sed/// direct-declarator 560193326Sed/// ptr-operator declarator 561193326Sed/// 562193326Sed/// direct-declarator: 563193326Sed/// declarator-id 564193326Sed/// direct-declarator '(' parameter-declaration-clause ')' 565193326Sed/// cv-qualifier-seq[opt] exception-specification[opt] 566193326Sed/// direct-declarator '[' constant-expression[opt] ']' 567193326Sed/// '(' declarator ')' 568193326Sed/// [GNU] '(' attributes declarator ')' 569193326Sed/// 570193326Sed/// abstract-declarator: 571193326Sed/// ptr-operator abstract-declarator[opt] 572193326Sed/// direct-abstract-declarator 573218893Sdim/// ... 574193326Sed/// 575193326Sed/// direct-abstract-declarator: 576193326Sed/// direct-abstract-declarator[opt] 577193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 578193326Sed/// exception-specification[opt] 579193326Sed/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 580193326Sed/// '(' abstract-declarator ')' 581193326Sed/// 582193326Sed/// ptr-operator: 583193326Sed/// '*' cv-qualifier-seq[opt] 584193326Sed/// '&' 585193326Sed/// [C++0x] '&&' [TODO] 586193326Sed/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] 587193326Sed/// 588193326Sed/// cv-qualifier-seq: 589193326Sed/// cv-qualifier cv-qualifier-seq[opt] 590193326Sed/// 591193326Sed/// cv-qualifier: 592193326Sed/// 'const' 593193326Sed/// 'volatile' 594193326Sed/// 595193326Sed/// declarator-id: 596218893Sdim/// '...'[opt] id-expression 597193326Sed/// 598193326Sed/// id-expression: 599193326Sed/// unqualified-id 600193326Sed/// qualified-id [TODO] 601193326Sed/// 602193326Sed/// unqualified-id: 603193326Sed/// identifier 604193326Sed/// operator-function-id [TODO] 605193326Sed/// conversion-function-id [TODO] 606193326Sed/// '~' class-name [TODO] 607193326Sed/// template-id [TODO] 608193326Sed/// 609193326SedParser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, 610193326Sed bool mayHaveIdentifier) { 611193326Sed // declarator: 612193326Sed // direct-declarator 613193326Sed // ptr-operator declarator 614193326Sed 615193326Sed while (1) { 616193326Sed if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) 617204643Srdivacky if (TryAnnotateCXXScopeToken(true)) 618204643Srdivacky return TPResult::Error(); 619193326Sed 620193326Sed if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || 621218893Sdim Tok.is(tok::ampamp) || 622193326Sed (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { 623193326Sed // ptr-operator 624193326Sed ConsumeToken(); 625193326Sed while (Tok.is(tok::kw_const) || 626193326Sed Tok.is(tok::kw_volatile) || 627193326Sed Tok.is(tok::kw_restrict)) 628193326Sed ConsumeToken(); 629193326Sed } else { 630193326Sed break; 631193326Sed } 632193326Sed } 633193326Sed 634193326Sed // direct-declarator: 635193326Sed // direct-abstract-declarator: 636218893Sdim if (Tok.is(tok::ellipsis)) 637218893Sdim ConsumeToken(); 638218893Sdim 639198092Srdivacky if ((Tok.is(tok::identifier) || 640198092Srdivacky (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) && 641198092Srdivacky mayHaveIdentifier) { 642193326Sed // declarator-id 643198092Srdivacky if (Tok.is(tok::annot_cxxscope)) 644198092Srdivacky ConsumeToken(); 645245431Sdim else 646245431Sdim TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); 647193326Sed ConsumeToken(); 648193326Sed } else if (Tok.is(tok::l_paren)) { 649193326Sed ConsumeParen(); 650193326Sed if (mayBeAbstract && 651193326Sed (Tok.is(tok::r_paren) || // 'int()' is a function. 652235633Sdim // 'int(...)' is a function. 653235633Sdim (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) || 654193326Sed isDeclarationSpecifier())) { // 'int(int)' is a function. 655193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 656193326Sed // exception-specification[opt] 657193326Sed TPResult TPR = TryParseFunctionDeclarator(); 658193326Sed if (TPR != TPResult::Ambiguous()) 659193326Sed return TPR; 660193326Sed } else { 661193326Sed // '(' declarator ')' 662193326Sed // '(' attributes declarator ')' 663193326Sed // '(' abstract-declarator ')' 664218893Sdim if (Tok.is(tok::kw___attribute) || 665218893Sdim Tok.is(tok::kw___declspec) || 666218893Sdim Tok.is(tok::kw___cdecl) || 667218893Sdim Tok.is(tok::kw___stdcall) || 668218893Sdim Tok.is(tok::kw___fastcall) || 669226890Sdim Tok.is(tok::kw___thiscall) || 670226890Sdim Tok.is(tok::kw___unaligned)) 671193326Sed return TPResult::True(); // attributes indicate declaration 672193326Sed TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); 673193326Sed if (TPR != TPResult::Ambiguous()) 674193326Sed return TPR; 675193326Sed if (Tok.isNot(tok::r_paren)) 676193326Sed return TPResult::False(); 677193326Sed ConsumeParen(); 678193326Sed } 679193326Sed } else if (!mayBeAbstract) { 680193326Sed return TPResult::False(); 681193326Sed } 682193326Sed 683193326Sed while (1) { 684193326Sed TPResult TPR(TPResult::Ambiguous()); 685193326Sed 686218893Sdim // abstract-declarator: ... 687218893Sdim if (Tok.is(tok::ellipsis)) 688218893Sdim ConsumeToken(); 689218893Sdim 690193326Sed if (Tok.is(tok::l_paren)) { 691193326Sed // Check whether we have a function declarator or a possible ctor-style 692193326Sed // initializer that follows the declarator. Note that ctor-style 693193326Sed // initializers are not possible in contexts where abstract declarators 694193326Sed // are allowed. 695245431Sdim if (!mayBeAbstract && !isCXXFunctionDeclarator()) 696193326Sed break; 697193326Sed 698193326Sed // direct-declarator '(' parameter-declaration-clause ')' 699193326Sed // cv-qualifier-seq[opt] exception-specification[opt] 700193326Sed ConsumeParen(); 701193326Sed TPR = TryParseFunctionDeclarator(); 702193326Sed } else if (Tok.is(tok::l_square)) { 703193326Sed // direct-declarator '[' constant-expression[opt] ']' 704193326Sed // direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 705193326Sed TPR = TryParseBracketDeclarator(); 706193326Sed } else { 707193326Sed break; 708193326Sed } 709193326Sed 710193326Sed if (TPR != TPResult::Ambiguous()) 711193326Sed return TPR; 712193326Sed } 713193326Sed 714193326Sed return TPResult::Ambiguous(); 715193326Sed} 716193326Sed 717218893SdimParser::TPResult 718218893SdimParser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { 719218893Sdim switch (Kind) { 720218893Sdim // Obviously starts an expression. 721218893Sdim case tok::numeric_constant: 722218893Sdim case tok::char_constant: 723226890Sdim case tok::wide_char_constant: 724226890Sdim case tok::utf16_char_constant: 725226890Sdim case tok::utf32_char_constant: 726218893Sdim case tok::string_literal: 727218893Sdim case tok::wide_string_literal: 728226890Sdim case tok::utf8_string_literal: 729226890Sdim case tok::utf16_string_literal: 730226890Sdim case tok::utf32_string_literal: 731218893Sdim case tok::l_square: 732218893Sdim case tok::l_paren: 733218893Sdim case tok::amp: 734218893Sdim case tok::ampamp: 735218893Sdim case tok::star: 736218893Sdim case tok::plus: 737218893Sdim case tok::plusplus: 738218893Sdim case tok::minus: 739218893Sdim case tok::minusminus: 740218893Sdim case tok::tilde: 741218893Sdim case tok::exclaim: 742218893Sdim case tok::kw_sizeof: 743218893Sdim case tok::kw___func__: 744218893Sdim case tok::kw_const_cast: 745218893Sdim case tok::kw_delete: 746218893Sdim case tok::kw_dynamic_cast: 747218893Sdim case tok::kw_false: 748218893Sdim case tok::kw_new: 749218893Sdim case tok::kw_operator: 750218893Sdim case tok::kw_reinterpret_cast: 751218893Sdim case tok::kw_static_cast: 752218893Sdim case tok::kw_this: 753218893Sdim case tok::kw_throw: 754218893Sdim case tok::kw_true: 755218893Sdim case tok::kw_typeid: 756218893Sdim case tok::kw_alignof: 757218893Sdim case tok::kw_noexcept: 758218893Sdim case tok::kw_nullptr: 759245431Sdim case tok::kw__Alignof: 760218893Sdim case tok::kw___null: 761218893Sdim case tok::kw___alignof: 762218893Sdim case tok::kw___builtin_choose_expr: 763218893Sdim case tok::kw___builtin_offsetof: 764218893Sdim case tok::kw___builtin_types_compatible_p: 765218893Sdim case tok::kw___builtin_va_arg: 766218893Sdim case tok::kw___imag: 767218893Sdim case tok::kw___real: 768218893Sdim case tok::kw___FUNCTION__: 769245431Sdim case tok::kw_L__FUNCTION__: 770218893Sdim case tok::kw___PRETTY_FUNCTION__: 771218893Sdim case tok::kw___has_nothrow_assign: 772218893Sdim case tok::kw___has_nothrow_copy: 773218893Sdim case tok::kw___has_nothrow_constructor: 774218893Sdim case tok::kw___has_trivial_assign: 775218893Sdim case tok::kw___has_trivial_copy: 776218893Sdim case tok::kw___has_trivial_constructor: 777218893Sdim case tok::kw___has_trivial_destructor: 778218893Sdim case tok::kw___has_virtual_destructor: 779218893Sdim case tok::kw___is_abstract: 780218893Sdim case tok::kw___is_base_of: 781218893Sdim case tok::kw___is_class: 782218893Sdim case tok::kw___is_convertible_to: 783218893Sdim case tok::kw___is_empty: 784218893Sdim case tok::kw___is_enum: 785245431Sdim case tok::kw___is_interface_class: 786235633Sdim case tok::kw___is_final: 787221345Sdim case tok::kw___is_literal: 788221345Sdim case tok::kw___is_literal_type: 789218893Sdim case tok::kw___is_pod: 790218893Sdim case tok::kw___is_polymorphic: 791221345Sdim case tok::kw___is_trivial: 792235633Sdim case tok::kw___is_trivially_assignable: 793235633Sdim case tok::kw___is_trivially_constructible: 794223017Sdim case tok::kw___is_trivially_copyable: 795218893Sdim case tok::kw___is_union: 796218893Sdim case tok::kw___uuidof: 797218893Sdim return TPResult::True(); 798218893Sdim 799218893Sdim // Obviously starts a type-specifier-seq: 800218893Sdim case tok::kw_char: 801218893Sdim case tok::kw_const: 802218893Sdim case tok::kw_double: 803218893Sdim case tok::kw_enum: 804226890Sdim case tok::kw_half: 805218893Sdim case tok::kw_float: 806218893Sdim case tok::kw_int: 807218893Sdim case tok::kw_long: 808221345Sdim case tok::kw___int64: 809235633Sdim case tok::kw___int128: 810218893Sdim case tok::kw_restrict: 811218893Sdim case tok::kw_short: 812218893Sdim case tok::kw_signed: 813218893Sdim case tok::kw_struct: 814218893Sdim case tok::kw_union: 815218893Sdim case tok::kw_unsigned: 816218893Sdim case tok::kw_void: 817218893Sdim case tok::kw_volatile: 818218893Sdim case tok::kw__Bool: 819218893Sdim case tok::kw__Complex: 820218893Sdim case tok::kw_class: 821218893Sdim case tok::kw_typename: 822218893Sdim case tok::kw_wchar_t: 823218893Sdim case tok::kw_char16_t: 824218893Sdim case tok::kw_char32_t: 825223017Sdim case tok::kw___underlying_type: 826218893Sdim case tok::kw_thread_local: 827218893Sdim case tok::kw__Decimal32: 828218893Sdim case tok::kw__Decimal64: 829218893Sdim case tok::kw__Decimal128: 830218893Sdim case tok::kw___thread: 831218893Sdim case tok::kw_typeof: 832218893Sdim case tok::kw___cdecl: 833218893Sdim case tok::kw___stdcall: 834218893Sdim case tok::kw___fastcall: 835218893Sdim case tok::kw___thiscall: 836226890Sdim case tok::kw___unaligned: 837218893Sdim case tok::kw___vector: 838218893Sdim case tok::kw___pixel: 839226890Sdim case tok::kw__Atomic: 840218893Sdim return TPResult::False(); 841218893Sdim 842218893Sdim default: 843218893Sdim break; 844218893Sdim } 845218893Sdim 846218893Sdim return TPResult::Ambiguous(); 847218893Sdim} 848218893Sdim 849245431Sdimbool Parser::isTentativelyDeclared(IdentifierInfo *II) { 850245431Sdim return std::find(TentativelyDeclaredIdentifiers.begin(), 851245431Sdim TentativelyDeclaredIdentifiers.end(), II) 852245431Sdim != TentativelyDeclaredIdentifiers.end(); 853245431Sdim} 854245431Sdim 855193326Sed/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration 856193326Sed/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could 857193326Sed/// be either a decl-specifier or a function-style cast, and TPResult::Error() 858193326Sed/// if a parsing error was found and reported. 859193326Sed/// 860245431Sdim/// If HasMissingTypename is provided, a name with a dependent scope specifier 861245431Sdim/// will be treated as ambiguous if the 'typename' keyword is missing. If this 862245431Sdim/// happens, *HasMissingTypename will be set to 'true'. This will also be used 863245431Sdim/// as an indicator that undeclared identifiers (which will trigger a later 864245431Sdim/// parse error) should be treated as types. Returns TPResult::Ambiguous() in 865245431Sdim/// such cases. 866245431Sdim/// 867193326Sed/// decl-specifier: 868193326Sed/// storage-class-specifier 869193326Sed/// type-specifier 870193326Sed/// function-specifier 871193326Sed/// 'friend' 872193326Sed/// 'typedef' 873198954Srdivacky/// [C++0x] 'constexpr' 874193326Sed/// [GNU] attributes declaration-specifiers[opt] 875193326Sed/// 876193326Sed/// storage-class-specifier: 877193326Sed/// 'register' 878193326Sed/// 'static' 879193326Sed/// 'extern' 880193326Sed/// 'mutable' 881193326Sed/// 'auto' 882193326Sed/// [GNU] '__thread' 883193326Sed/// 884193326Sed/// function-specifier: 885193326Sed/// 'inline' 886193326Sed/// 'virtual' 887193326Sed/// 'explicit' 888193326Sed/// 889193326Sed/// typedef-name: 890193326Sed/// identifier 891193326Sed/// 892193326Sed/// type-specifier: 893193326Sed/// simple-type-specifier 894193326Sed/// class-specifier 895193326Sed/// enum-specifier 896193326Sed/// elaborated-type-specifier 897193326Sed/// typename-specifier 898193326Sed/// cv-qualifier 899193326Sed/// 900193326Sed/// simple-type-specifier: 901193326Sed/// '::'[opt] nested-name-specifier[opt] type-name 902193326Sed/// '::'[opt] nested-name-specifier 'template' 903193326Sed/// simple-template-id [TODO] 904193326Sed/// 'char' 905193326Sed/// 'wchar_t' 906193326Sed/// 'bool' 907193326Sed/// 'short' 908193326Sed/// 'int' 909193326Sed/// 'long' 910193326Sed/// 'signed' 911193326Sed/// 'unsigned' 912193326Sed/// 'float' 913193326Sed/// 'double' 914193326Sed/// 'void' 915193326Sed/// [GNU] typeof-specifier 916193326Sed/// [GNU] '_Complex' 917193326Sed/// [C++0x] 'auto' [TODO] 918195099Sed/// [C++0x] 'decltype' ( expression ) 919193326Sed/// 920193326Sed/// type-name: 921193326Sed/// class-name 922193326Sed/// enum-name 923193326Sed/// typedef-name 924193326Sed/// 925193326Sed/// elaborated-type-specifier: 926193326Sed/// class-key '::'[opt] nested-name-specifier[opt] identifier 927193326Sed/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt] 928193326Sed/// simple-template-id 929193326Sed/// 'enum' '::'[opt] nested-name-specifier[opt] identifier 930193326Sed/// 931193326Sed/// enum-name: 932193326Sed/// identifier 933193326Sed/// 934193326Sed/// enum-specifier: 935193326Sed/// 'enum' identifier[opt] '{' enumerator-list[opt] '}' 936193326Sed/// 'enum' identifier[opt] '{' enumerator-list ',' '}' 937193326Sed/// 938193326Sed/// class-specifier: 939193326Sed/// class-head '{' member-specification[opt] '}' 940193326Sed/// 941193326Sed/// class-head: 942193326Sed/// class-key identifier[opt] base-clause[opt] 943193326Sed/// class-key nested-name-specifier identifier base-clause[opt] 944193326Sed/// class-key nested-name-specifier[opt] simple-template-id 945193326Sed/// base-clause[opt] 946193326Sed/// 947193326Sed/// class-key: 948193326Sed/// 'class' 949193326Sed/// 'struct' 950193326Sed/// 'union' 951193326Sed/// 952193326Sed/// cv-qualifier: 953193326Sed/// 'const' 954193326Sed/// 'volatile' 955193326Sed/// [GNU] restrict 956193326Sed/// 957235633SdimParser::TPResult 958245431SdimParser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, 959245431Sdim bool *HasMissingTypename) { 960193326Sed switch (Tok.getKind()) { 961245431Sdim case tok::identifier: { 962203955Srdivacky // Check for need to substitute AltiVec __vector keyword 963203955Srdivacky // for "vector" identifier. 964203955Srdivacky if (TryAltiVecVectorToken()) 965203955Srdivacky return TPResult::True(); 966245431Sdim 967245431Sdim const Token &Next = NextToken(); 968245431Sdim // In 'foo bar', 'foo' is always a type name outside of Objective-C. 969245431Sdim if (!getLangOpts().ObjC1 && Next.is(tok::identifier)) 970245431Sdim return TPResult::True(); 971245431Sdim 972245431Sdim if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { 973245431Sdim // Determine whether this is a valid expression. If not, we will hit 974245431Sdim // a parse error one way or another. In that case, tell the caller that 975245431Sdim // this is ambiguous. Typo-correct to type and expression keywords and 976245431Sdim // to types and identifiers, in order to try to recover from errors. 977245431Sdim CorrectionCandidateCallback TypoCorrection; 978245431Sdim TypoCorrection.WantRemainingKeywords = false; 979245431Sdim switch (TryAnnotateName(false /* no nested name specifier */, 980245431Sdim &TypoCorrection)) { 981245431Sdim case ANK_Error: 982245431Sdim return TPResult::Error(); 983245431Sdim case ANK_TentativeDecl: 984245431Sdim return TPResult::False(); 985245431Sdim case ANK_TemplateName: 986245431Sdim // A bare type template-name which can't be a template template 987245431Sdim // argument is an error, and was probably intended to be a type. 988245431Sdim return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); 989245431Sdim case ANK_Unresolved: 990245431Sdim return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False(); 991245431Sdim case ANK_Success: 992245431Sdim break; 993245431Sdim } 994245431Sdim assert(Tok.isNot(tok::identifier) && 995245431Sdim "TryAnnotateName succeeded without producing an annotation"); 996245431Sdim } else { 997245431Sdim // This might possibly be a type with a dependent scope specifier and 998245431Sdim // a missing 'typename' keyword. Don't use TryAnnotateName in this case, 999245431Sdim // since it will annotate as a primary expression, and we want to use the 1000245431Sdim // "missing 'typename'" logic. 1001245431Sdim if (TryAnnotateTypeOrScopeToken()) 1002245431Sdim return TPResult::Error(); 1003245431Sdim // If annotation failed, assume it's a non-type. 1004245431Sdim // FIXME: If this happens due to an undeclared identifier, treat it as 1005245431Sdim // ambiguous. 1006245431Sdim if (Tok.is(tok::identifier)) 1007245431Sdim return TPResult::False(); 1008245431Sdim } 1009245431Sdim 1010245431Sdim // We annotated this token as something. Recurse to handle whatever we got. 1011245431Sdim return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); 1012245431Sdim } 1013245431Sdim 1014193326Sed case tok::kw_typename: // typename T::type 1015193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 1016193326Sed // recurse to handle whatever we get. 1017193326Sed if (TryAnnotateTypeOrScopeToken()) 1018204643Srdivacky return TPResult::Error(); 1019245431Sdim return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); 1020193326Sed 1021201361Srdivacky case tok::coloncolon: { // ::foo::bar 1022201361Srdivacky const Token &Next = NextToken(); 1023201361Srdivacky if (Next.is(tok::kw_new) || // ::new 1024201361Srdivacky Next.is(tok::kw_delete)) // ::delete 1025201361Srdivacky return TPResult::False(); 1026235633Sdim } 1027235633Sdim // Fall through. 1028235633Sdim case tok::kw_decltype: 1029193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 1030193326Sed // recurse to handle whatever we get. 1031193326Sed if (TryAnnotateTypeOrScopeToken()) 1032204643Srdivacky return TPResult::Error(); 1033245431Sdim return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); 1034235633Sdim 1035193326Sed // decl-specifier: 1036193326Sed // storage-class-specifier 1037193326Sed // type-specifier 1038193326Sed // function-specifier 1039193326Sed // 'friend' 1040193326Sed // 'typedef' 1041198954Srdivacky // 'constexpr' 1042193326Sed case tok::kw_friend: 1043193326Sed case tok::kw_typedef: 1044198954Srdivacky case tok::kw_constexpr: 1045193326Sed // storage-class-specifier 1046193326Sed case tok::kw_register: 1047193326Sed case tok::kw_static: 1048193326Sed case tok::kw_extern: 1049193326Sed case tok::kw_mutable: 1050193326Sed case tok::kw_auto: 1051193326Sed case tok::kw___thread: 1052193326Sed // function-specifier 1053193326Sed case tok::kw_inline: 1054193326Sed case tok::kw_virtual: 1055193326Sed case tok::kw_explicit: 1056193326Sed 1057226890Sdim // Modules 1058226890Sdim case tok::kw___module_private__: 1059226890Sdim 1060193326Sed // type-specifier: 1061193326Sed // simple-type-specifier 1062193326Sed // class-specifier 1063193326Sed // enum-specifier 1064193326Sed // elaborated-type-specifier 1065193326Sed // typename-specifier 1066193326Sed // cv-qualifier 1067193326Sed 1068193326Sed // class-specifier 1069193326Sed // elaborated-type-specifier 1070193326Sed case tok::kw_class: 1071193326Sed case tok::kw_struct: 1072193326Sed case tok::kw_union: 1073193326Sed // enum-specifier 1074193326Sed case tok::kw_enum: 1075193326Sed // cv-qualifier 1076193326Sed case tok::kw_const: 1077193326Sed case tok::kw_volatile: 1078193326Sed 1079193326Sed // GNU 1080193326Sed case tok::kw_restrict: 1081193326Sed case tok::kw__Complex: 1082193326Sed case tok::kw___attribute: 1083193326Sed return TPResult::True(); 1084198092Srdivacky 1085193326Sed // Microsoft 1086193326Sed case tok::kw___declspec: 1087193326Sed case tok::kw___cdecl: 1088193326Sed case tok::kw___stdcall: 1089193326Sed case tok::kw___fastcall: 1090208600Srdivacky case tok::kw___thiscall: 1091194179Sed case tok::kw___w64: 1092194179Sed case tok::kw___ptr64: 1093226890Sdim case tok::kw___ptr32: 1094194179Sed case tok::kw___forceinline: 1095226890Sdim case tok::kw___unaligned: 1096194179Sed return TPResult::True(); 1097212904Sdim 1098212904Sdim // Borland 1099212904Sdim case tok::kw___pascal: 1100212904Sdim return TPResult::True(); 1101203955Srdivacky 1102203955Srdivacky // AltiVec 1103203955Srdivacky case tok::kw___vector: 1104203955Srdivacky return TPResult::True(); 1105193326Sed 1106207619Srdivacky case tok::annot_template_id: { 1107224145Sdim TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); 1108207619Srdivacky if (TemplateId->Kind != TNK_Type_template) 1109207619Srdivacky return TPResult::False(); 1110207619Srdivacky CXXScopeSpec SS; 1111221345Sdim AnnotateTemplateIdTokenAsType(); 1112207619Srdivacky assert(Tok.is(tok::annot_typename)); 1113207619Srdivacky goto case_typename; 1114207619Srdivacky } 1115207619Srdivacky 1116201361Srdivacky case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed 1117201361Srdivacky // We've already annotated a scope; try to annotate a type. 1118204643Srdivacky if (TryAnnotateTypeOrScopeToken()) 1119204643Srdivacky return TPResult::Error(); 1120235633Sdim if (!Tok.is(tok::annot_typename)) { 1121235633Sdim // If the next token is an identifier or a type qualifier, then this 1122235633Sdim // can't possibly be a valid expression either. 1123235633Sdim if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) { 1124235633Sdim CXXScopeSpec SS; 1125235633Sdim Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), 1126235633Sdim Tok.getAnnotationRange(), 1127235633Sdim SS); 1128235633Sdim if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) { 1129235633Sdim TentativeParsingAction PA(*this); 1130235633Sdim ConsumeToken(); 1131235633Sdim ConsumeToken(); 1132235633Sdim bool isIdentifier = Tok.is(tok::identifier); 1133235633Sdim TPResult TPR = TPResult::False(); 1134235633Sdim if (!isIdentifier) 1135245431Sdim TPR = isCXXDeclarationSpecifier(BracedCastResult, 1136245431Sdim HasMissingTypename); 1137235633Sdim PA.Revert(); 1138235633Sdim 1139235633Sdim if (isIdentifier || 1140235633Sdim TPR == TPResult::True() || TPR == TPResult::Error()) 1141235633Sdim return TPResult::Error(); 1142245431Sdim 1143245431Sdim if (HasMissingTypename) { 1144245431Sdim // We can't tell whether this is a missing 'typename' or a valid 1145245431Sdim // expression. 1146245431Sdim *HasMissingTypename = true; 1147245431Sdim return TPResult::Ambiguous(); 1148245431Sdim } 1149245431Sdim } else { 1150245431Sdim // Try to resolve the name. If it doesn't exist, assume it was 1151245431Sdim // intended to name a type and keep disambiguating. 1152245431Sdim switch (TryAnnotateName(false /* SS is not dependent */)) { 1153245431Sdim case ANK_Error: 1154245431Sdim return TPResult::Error(); 1155245431Sdim case ANK_TentativeDecl: 1156245431Sdim return TPResult::False(); 1157245431Sdim case ANK_TemplateName: 1158245431Sdim // A bare type template-name which can't be a template template 1159245431Sdim // argument is an error, and was probably intended to be a type. 1160245431Sdim return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); 1161245431Sdim case ANK_Unresolved: 1162245431Sdim return HasMissingTypename ? TPResult::Ambiguous() 1163245431Sdim : TPResult::False(); 1164245431Sdim case ANK_Success: 1165245431Sdim // Annotated it, check again. 1166245431Sdim assert(Tok.isNot(tok::annot_cxxscope) || 1167245431Sdim NextToken().isNot(tok::identifier)); 1168245431Sdim return isCXXDeclarationSpecifier(BracedCastResult, 1169245431Sdim HasMissingTypename); 1170245431Sdim } 1171235633Sdim } 1172235633Sdim } 1173201361Srdivacky return TPResult::False(); 1174235633Sdim } 1175201361Srdivacky // If that succeeded, fallthrough into the generic simple-type-id case. 1176201361Srdivacky 1177193326Sed // The ambiguity resides in a simple-type-specifier/typename-specifier 1178193326Sed // followed by a '('. The '(' could either be the start of: 1179193326Sed // 1180193326Sed // direct-declarator: 1181193326Sed // '(' declarator ')' 1182193326Sed // 1183193326Sed // direct-abstract-declarator: 1184193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 1185193326Sed // exception-specification[opt] 1186193326Sed // '(' abstract-declarator ')' 1187193326Sed // 1188193326Sed // or part of a function-style cast expression: 1189193326Sed // 1190193326Sed // simple-type-specifier '(' expression-list[opt] ')' 1191193326Sed // 1192193326Sed 1193193326Sed // simple-type-specifier: 1194193326Sed 1195218893Sdim case tok::annot_typename: 1196218893Sdim case_typename: 1197218893Sdim // In Objective-C, we might have a protocol-qualified type. 1198235633Sdim if (getLangOpts().ObjC1 && NextToken().is(tok::less)) { 1199218893Sdim // Tentatively parse the 1200218893Sdim TentativeParsingAction PA(*this); 1201218893Sdim ConsumeToken(); // The type token 1202218893Sdim 1203218893Sdim TPResult TPR = TryParseProtocolQualifiers(); 1204218893Sdim bool isFollowedByParen = Tok.is(tok::l_paren); 1205235633Sdim bool isFollowedByBrace = Tok.is(tok::l_brace); 1206218893Sdim 1207218893Sdim PA.Revert(); 1208218893Sdim 1209218893Sdim if (TPR == TPResult::Error()) 1210218893Sdim return TPResult::Error(); 1211218893Sdim 1212218893Sdim if (isFollowedByParen) 1213218893Sdim return TPResult::Ambiguous(); 1214235633Sdim 1215235633Sdim if (getLangOpts().CPlusPlus0x && isFollowedByBrace) 1216235633Sdim return BracedCastResult; 1217218893Sdim 1218218893Sdim return TPResult::True(); 1219218893Sdim } 1220218893Sdim 1221193326Sed case tok::kw_char: 1222193326Sed case tok::kw_wchar_t: 1223198092Srdivacky case tok::kw_char16_t: 1224198092Srdivacky case tok::kw_char32_t: 1225193326Sed case tok::kw_bool: 1226193326Sed case tok::kw_short: 1227193326Sed case tok::kw_int: 1228193326Sed case tok::kw_long: 1229221345Sdim case tok::kw___int64: 1230235633Sdim case tok::kw___int128: 1231193326Sed case tok::kw_signed: 1232193326Sed case tok::kw_unsigned: 1233226890Sdim case tok::kw_half: 1234193326Sed case tok::kw_float: 1235193326Sed case tok::kw_double: 1236193326Sed case tok::kw_void: 1237235633Sdim case tok::annot_decltype: 1238193326Sed if (NextToken().is(tok::l_paren)) 1239193326Sed return TPResult::Ambiguous(); 1240193326Sed 1241235633Sdim // This is a function-style cast in all cases we disambiguate other than 1242235633Sdim // one: 1243235633Sdim // struct S { 1244235633Sdim // enum E : int { a = 4 }; // enum 1245235633Sdim // enum E : int { 4 }; // bit-field 1246235633Sdim // }; 1247235633Sdim if (getLangOpts().CPlusPlus0x && NextToken().is(tok::l_brace)) 1248235633Sdim return BracedCastResult; 1249235633Sdim 1250218893Sdim if (isStartOfObjCClassMessageMissingOpenBracket()) 1251218893Sdim return TPResult::False(); 1252218893Sdim 1253193326Sed return TPResult::True(); 1254193326Sed 1255195099Sed // GNU typeof support. 1256193326Sed case tok::kw_typeof: { 1257193326Sed if (NextToken().isNot(tok::l_paren)) 1258193326Sed return TPResult::True(); 1259193326Sed 1260193326Sed TentativeParsingAction PA(*this); 1261193326Sed 1262193326Sed TPResult TPR = TryParseTypeofSpecifier(); 1263193326Sed bool isFollowedByParen = Tok.is(tok::l_paren); 1264235633Sdim bool isFollowedByBrace = Tok.is(tok::l_brace); 1265193326Sed 1266193326Sed PA.Revert(); 1267193326Sed 1268193326Sed if (TPR == TPResult::Error()) 1269193326Sed return TPResult::Error(); 1270193326Sed 1271193326Sed if (isFollowedByParen) 1272193326Sed return TPResult::Ambiguous(); 1273193326Sed 1274235633Sdim if (getLangOpts().CPlusPlus0x && isFollowedByBrace) 1275235633Sdim return BracedCastResult; 1276235633Sdim 1277193326Sed return TPResult::True(); 1278193326Sed } 1279193326Sed 1280223017Sdim // C++0x type traits support 1281223017Sdim case tok::kw___underlying_type: 1282223017Sdim return TPResult::True(); 1283223017Sdim 1284235633Sdim // C11 _Atomic 1285226890Sdim case tok::kw__Atomic: 1286226890Sdim return TPResult::True(); 1287226890Sdim 1288193326Sed default: 1289193326Sed return TPResult::False(); 1290193326Sed } 1291193326Sed} 1292193326Sed 1293193326Sed/// [GNU] typeof-specifier: 1294193326Sed/// 'typeof' '(' expressions ')' 1295193326Sed/// 'typeof' '(' type-name ')' 1296193326Sed/// 1297193326SedParser::TPResult Parser::TryParseTypeofSpecifier() { 1298193326Sed assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 1299193326Sed ConsumeToken(); 1300193326Sed 1301193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 1302193326Sed // Parse through the parens after 'typeof'. 1303193326Sed ConsumeParen(); 1304193326Sed if (!SkipUntil(tok::r_paren)) 1305193326Sed return TPResult::Error(); 1306193326Sed 1307193326Sed return TPResult::Ambiguous(); 1308193326Sed} 1309193326Sed 1310218893Sdim/// [ObjC] protocol-qualifiers: 1311218893Sdim//// '<' identifier-list '>' 1312218893SdimParser::TPResult Parser::TryParseProtocolQualifiers() { 1313218893Sdim assert(Tok.is(tok::less) && "Expected '<' for qualifier list"); 1314218893Sdim ConsumeToken(); 1315218893Sdim do { 1316218893Sdim if (Tok.isNot(tok::identifier)) 1317218893Sdim return TPResult::Error(); 1318218893Sdim ConsumeToken(); 1319218893Sdim 1320218893Sdim if (Tok.is(tok::comma)) { 1321218893Sdim ConsumeToken(); 1322218893Sdim continue; 1323218893Sdim } 1324218893Sdim 1325218893Sdim if (Tok.is(tok::greater)) { 1326218893Sdim ConsumeToken(); 1327218893Sdim return TPResult::Ambiguous(); 1328218893Sdim } 1329218893Sdim } while (false); 1330218893Sdim 1331218893Sdim return TPResult::Error(); 1332218893Sdim} 1333218893Sdim 1334245431SdimParser::TPResult 1335245431SdimParser::TryParseDeclarationSpecifier(bool *HasMissingTypename) { 1336245431Sdim TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), 1337245431Sdim HasMissingTypename); 1338193326Sed if (TPR != TPResult::Ambiguous()) 1339193326Sed return TPR; 1340193326Sed 1341193326Sed if (Tok.is(tok::kw_typeof)) 1342193326Sed TryParseTypeofSpecifier(); 1343218893Sdim else { 1344245431Sdim if (Tok.is(tok::annot_cxxscope)) 1345245431Sdim ConsumeToken(); 1346193326Sed ConsumeToken(); 1347218893Sdim 1348235633Sdim if (getLangOpts().ObjC1 && Tok.is(tok::less)) 1349218893Sdim TryParseProtocolQualifiers(); 1350218893Sdim } 1351198092Srdivacky 1352193326Sed return TPResult::Ambiguous(); 1353193326Sed} 1354193326Sed 1355193326Sed/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 1356193326Sed/// a constructor-style initializer, when parsing declaration statements. 1357193326Sed/// Returns true for function declarator and false for constructor-style 1358193326Sed/// initializer. 1359193326Sed/// If during the disambiguation process a parsing error is encountered, 1360193326Sed/// the function returns true to let the declaration parsing code handle it. 1361193326Sed/// 1362193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 1363193326Sed/// exception-specification[opt] 1364193326Sed/// 1365245431Sdimbool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) { 1366193326Sed 1367193326Sed // C++ 8.2p1: 1368193326Sed // The ambiguity arising from the similarity between a function-style cast and 1369193326Sed // a declaration mentioned in 6.8 can also occur in the context of a 1370193326Sed // declaration. In that context, the choice is between a function declaration 1371193326Sed // with a redundant set of parentheses around a parameter name and an object 1372193326Sed // declaration with a function-style cast as the initializer. Just as for the 1373193326Sed // ambiguities mentioned in 6.8, the resolution is to consider any construct 1374193326Sed // that could possibly be a declaration a declaration. 1375193326Sed 1376193326Sed TentativeParsingAction PA(*this); 1377193326Sed 1378193326Sed ConsumeParen(); 1379245431Sdim bool InvalidAsDeclaration = false; 1380245431Sdim TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration); 1381245431Sdim if (TPR == TPResult::Ambiguous()) { 1382245431Sdim if (Tok.isNot(tok::r_paren)) 1383245431Sdim TPR = TPResult::False(); 1384245431Sdim else { 1385245431Sdim const Token &Next = NextToken(); 1386245431Sdim if (Next.is(tok::amp) || Next.is(tok::ampamp) || 1387245431Sdim Next.is(tok::kw_const) || Next.is(tok::kw_volatile) || 1388245431Sdim Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) || 1389245431Sdim Next.is(tok::l_square) || isCXX0XVirtSpecifier(Next) || 1390245431Sdim Next.is(tok::l_brace) || Next.is(tok::kw_try) || 1391245431Sdim Next.is(tok::equal) || Next.is(tok::arrow)) 1392245431Sdim // The next token cannot appear after a constructor-style initializer, 1393245431Sdim // and can appear next in a function definition. This must be a function 1394245431Sdim // declarator. 1395245431Sdim TPR = TPResult::True(); 1396245431Sdim else if (InvalidAsDeclaration) 1397245431Sdim // Use the absence of 'typename' as a tie-breaker. 1398245431Sdim TPR = TPResult::False(); 1399245431Sdim } 1400245431Sdim } 1401193326Sed 1402193326Sed PA.Revert(); 1403193326Sed 1404245431Sdim if (IsAmbiguous && TPR == TPResult::Ambiguous()) 1405245431Sdim *IsAmbiguous = true; 1406245431Sdim 1407193326Sed // In case of an error, let the declaration parsing code handle it. 1408245431Sdim return TPR != TPResult::False(); 1409193326Sed} 1410193326Sed 1411193326Sed/// parameter-declaration-clause: 1412193326Sed/// parameter-declaration-list[opt] '...'[opt] 1413193326Sed/// parameter-declaration-list ',' '...' 1414193326Sed/// 1415193326Sed/// parameter-declaration-list: 1416193326Sed/// parameter-declaration 1417193326Sed/// parameter-declaration-list ',' parameter-declaration 1418193326Sed/// 1419193326Sed/// parameter-declaration: 1420235633Sdim/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt] 1421235633Sdim/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt] 1422218893Sdim/// '=' assignment-expression 1423235633Sdim/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt] 1424235633Sdim/// attributes[opt] 1425235633Sdim/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt] 1426235633Sdim/// attributes[opt] '=' assignment-expression 1427193326Sed/// 1428245431SdimParser::TPResult 1429245431SdimParser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration) { 1430193326Sed 1431193326Sed if (Tok.is(tok::r_paren)) 1432245431Sdim return TPResult::Ambiguous(); 1433193326Sed 1434193326Sed // parameter-declaration-list[opt] '...'[opt] 1435193326Sed // parameter-declaration-list ',' '...' 1436193326Sed // 1437193326Sed // parameter-declaration-list: 1438193326Sed // parameter-declaration 1439193326Sed // parameter-declaration-list ',' parameter-declaration 1440193326Sed // 1441193326Sed while (1) { 1442193326Sed // '...'[opt] 1443193326Sed if (Tok.is(tok::ellipsis)) { 1444193326Sed ConsumeToken(); 1445235633Sdim if (Tok.is(tok::r_paren)) 1446235633Sdim return TPResult::True(); // '...)' is a sign of a function declarator. 1447235633Sdim else 1448235633Sdim return TPResult::False(); 1449193326Sed } 1450193326Sed 1451235633Sdim // An attribute-specifier-seq here is a sign of a function declarator. 1452235633Sdim if (isCXX11AttributeSpecifier(/*Disambiguate*/false, 1453235633Sdim /*OuterMightBeMessageSend*/true)) 1454235633Sdim return TPResult::True(); 1455235633Sdim 1456221345Sdim ParsedAttributes attrs(AttrFactory); 1457218893Sdim MaybeParseMicrosoftAttributes(attrs); 1458218893Sdim 1459193326Sed // decl-specifier-seq 1460235633Sdim // A parameter-declaration's initializer must be preceded by an '=', so 1461235633Sdim // decl-specifier-seq '{' is not a parameter in C++11. 1462245431Sdim TPResult TPR = TryParseDeclarationSpecifier(InvalidAsDeclaration); 1463193326Sed if (TPR != TPResult::Ambiguous()) 1464193326Sed return TPR; 1465193326Sed 1466193326Sed // declarator 1467193326Sed // abstract-declarator[opt] 1468193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/); 1469193326Sed if (TPR != TPResult::Ambiguous()) 1470193326Sed return TPR; 1471193326Sed 1472218893Sdim // [GNU] attributes[opt] 1473218893Sdim if (Tok.is(tok::kw___attribute)) 1474218893Sdim return TPResult::True(); 1475218893Sdim 1476193326Sed if (Tok.is(tok::equal)) { 1477193326Sed // '=' assignment-expression 1478193326Sed // Parse through assignment-expression. 1479235633Sdim if (!SkipUntil(tok::comma, tok::r_paren, true/*StopAtSemi*/, 1480235633Sdim true/*DontConsume*/)) 1481193326Sed return TPResult::Error(); 1482193326Sed } 1483193326Sed 1484193326Sed if (Tok.is(tok::ellipsis)) { 1485193326Sed ConsumeToken(); 1486235633Sdim if (Tok.is(tok::r_paren)) 1487235633Sdim return TPResult::True(); // '...)' is a sign of a function declarator. 1488235633Sdim else 1489235633Sdim return TPResult::False(); 1490193326Sed } 1491193326Sed 1492193326Sed if (Tok.isNot(tok::comma)) 1493193326Sed break; 1494193326Sed ConsumeToken(); // the comma. 1495193326Sed } 1496193326Sed 1497193326Sed return TPResult::Ambiguous(); 1498193326Sed} 1499193326Sed 1500193326Sed/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 1501193326Sed/// parsing as a function declarator. 1502193326Sed/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 1503193326Sed/// return TPResult::Ambiguous(), otherwise it will return either False() or 1504193326Sed/// Error(). 1505198092Srdivacky/// 1506193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 1507193326Sed/// exception-specification[opt] 1508193326Sed/// 1509193326Sed/// exception-specification: 1510193326Sed/// 'throw' '(' type-id-list[opt] ')' 1511193326Sed/// 1512193326SedParser::TPResult Parser::TryParseFunctionDeclarator() { 1513193326Sed 1514193326Sed // The '(' is already parsed. 1515193326Sed 1516193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 1517193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 1518193326Sed TPR = TPResult::False(); 1519193326Sed 1520193326Sed if (TPR == TPResult::False() || TPR == TPResult::Error()) 1521193326Sed return TPR; 1522193326Sed 1523193326Sed // Parse through the parens. 1524193326Sed if (!SkipUntil(tok::r_paren)) 1525193326Sed return TPResult::Error(); 1526193326Sed 1527193326Sed // cv-qualifier-seq 1528193326Sed while (Tok.is(tok::kw_const) || 1529193326Sed Tok.is(tok::kw_volatile) || 1530193326Sed Tok.is(tok::kw_restrict) ) 1531193326Sed ConsumeToken(); 1532193326Sed 1533218893Sdim // ref-qualifier[opt] 1534218893Sdim if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) 1535218893Sdim ConsumeToken(); 1536218893Sdim 1537193326Sed // exception-specification 1538193326Sed if (Tok.is(tok::kw_throw)) { 1539193326Sed ConsumeToken(); 1540193326Sed if (Tok.isNot(tok::l_paren)) 1541193326Sed return TPResult::Error(); 1542193326Sed 1543193326Sed // Parse through the parens after 'throw'. 1544193326Sed ConsumeParen(); 1545193326Sed if (!SkipUntil(tok::r_paren)) 1546193326Sed return TPResult::Error(); 1547193326Sed } 1548221345Sdim if (Tok.is(tok::kw_noexcept)) { 1549221345Sdim ConsumeToken(); 1550221345Sdim // Possibly an expression as well. 1551221345Sdim if (Tok.is(tok::l_paren)) { 1552221345Sdim // Find the matching rparen. 1553221345Sdim ConsumeParen(); 1554221345Sdim if (!SkipUntil(tok::r_paren)) 1555221345Sdim return TPResult::Error(); 1556221345Sdim } 1557221345Sdim } 1558193326Sed 1559193326Sed return TPResult::Ambiguous(); 1560193326Sed} 1561193326Sed 1562193326Sed/// '[' constant-expression[opt] ']' 1563193326Sed/// 1564193326SedParser::TPResult Parser::TryParseBracketDeclarator() { 1565193326Sed ConsumeBracket(); 1566193326Sed if (!SkipUntil(tok::r_square)) 1567193326Sed return TPResult::Error(); 1568193326Sed 1569193326Sed return TPResult::Ambiguous(); 1570193326Sed} 1571