10b57cec5SDimitry Andric //===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the C++ Declaration portions of the Parser interfaces. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 140b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 150b57cec5SDimitry Andric #include "clang/AST/PrettyDeclStackTrace.h" 1681ad6265SDimitry Andric #include "clang/Basic/AttributeCommonInfo.h" 170b57cec5SDimitry Andric #include "clang/Basic/Attributes.h" 180b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 190b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.h" 200b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 21bdd1243dSDimitry Andric #include "clang/Basic/TokenKinds.h" 225f757f3fSDimitry Andric #include "clang/Lex/LiteralSupport.h" 230b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h" 2481ad6265SDimitry Andric #include "clang/Parse/Parser.h" 250b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h" 260b57cec5SDimitry Andric #include "clang/Sema/DeclSpec.h" 2706c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h" 280b57cec5SDimitry Andric #include "clang/Sema/ParsedTemplate.h" 290b57cec5SDimitry Andric #include "clang/Sema/Scope.h" 30*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h" 310b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 320b57cec5SDimitry Andric #include "llvm/Support/TimeProfiler.h" 33bdd1243dSDimitry Andric #include <optional> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace clang; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric /// ParseNamespace - We know that the current token is a namespace keyword. This 380b57cec5SDimitry Andric /// may either be a top level namespace or a block-level namespace alias. If 390b57cec5SDimitry Andric /// there was an inline keyword, it has already been parsed. 400b57cec5SDimitry Andric /// 410b57cec5SDimitry Andric /// namespace-definition: [C++: namespace.def] 420b57cec5SDimitry Andric /// named-namespace-definition 430b57cec5SDimitry Andric /// unnamed-namespace-definition 440b57cec5SDimitry Andric /// nested-namespace-definition 450b57cec5SDimitry Andric /// 460b57cec5SDimitry Andric /// named-namespace-definition: 470b57cec5SDimitry Andric /// 'inline'[opt] 'namespace' attributes[opt] identifier '{' 480b57cec5SDimitry Andric /// namespace-body '}' 490b57cec5SDimitry Andric /// 500b57cec5SDimitry Andric /// unnamed-namespace-definition: 510b57cec5SDimitry Andric /// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}' 520b57cec5SDimitry Andric /// 530b57cec5SDimitry Andric /// nested-namespace-definition: 540b57cec5SDimitry Andric /// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt] 550b57cec5SDimitry Andric /// identifier '{' namespace-body '}' 560b57cec5SDimitry Andric /// 570b57cec5SDimitry Andric /// enclosing-namespace-specifier: 580b57cec5SDimitry Andric /// identifier 590b57cec5SDimitry Andric /// enclosing-namespace-specifier '::' 'inline'[opt] identifier 600b57cec5SDimitry Andric /// 610b57cec5SDimitry Andric /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] 620b57cec5SDimitry Andric /// 'namespace' identifier '=' qualified-namespace-specifier ';' 630b57cec5SDimitry Andric /// 640b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, 650b57cec5SDimitry Andric SourceLocation &DeclEnd, 660b57cec5SDimitry Andric SourceLocation InlineLoc) { 670b57cec5SDimitry Andric assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); 680b57cec5SDimitry Andric SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. 690b57cec5SDimitry Andric ObjCDeclContextSwitch ObjCDC(*this); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 720b57cec5SDimitry Andric cutOffParsing(); 73*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteNamespaceDecl(getCurScope()); 740b57cec5SDimitry Andric return nullptr; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric SourceLocation IdentLoc; 780b57cec5SDimitry Andric IdentifierInfo *Ident = nullptr; 790b57cec5SDimitry Andric InnerNamespaceInfoList ExtraNSs; 800b57cec5SDimitry Andric SourceLocation FirstNestedInlineLoc; 810b57cec5SDimitry Andric 8281ad6265SDimitry Andric ParsedAttributes attrs(AttrFactory); 8381ad6265SDimitry Andric 8481ad6265SDimitry Andric auto ReadAttributes = [&] { 8581ad6265SDimitry Andric bool MoreToParse; 8681ad6265SDimitry Andric do { 8781ad6265SDimitry Andric MoreToParse = false; 8881ad6265SDimitry Andric if (Tok.is(tok::kw___attribute)) { 8981ad6265SDimitry Andric ParseGNUAttributes(attrs); 9081ad6265SDimitry Andric MoreToParse = true; 9181ad6265SDimitry Andric } 920b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { 930b57cec5SDimitry Andric Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 940b57cec5SDimitry Andric ? diag::warn_cxx14_compat_ns_enum_attribute 950b57cec5SDimitry Andric : diag::ext_ns_enum_attribute) 960b57cec5SDimitry Andric << 0 /*namespace*/; 970b57cec5SDimitry Andric ParseCXX11Attributes(attrs); 9881ad6265SDimitry Andric MoreToParse = true; 990b57cec5SDimitry Andric } 10081ad6265SDimitry Andric } while (MoreToParse); 10181ad6265SDimitry Andric }; 10281ad6265SDimitry Andric 10381ad6265SDimitry Andric ReadAttributes(); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 1060b57cec5SDimitry Andric Ident = Tok.getIdentifierInfo(); 1070b57cec5SDimitry Andric IdentLoc = ConsumeToken(); // eat the identifier. 1080b57cec5SDimitry Andric while (Tok.is(tok::coloncolon) && 1090b57cec5SDimitry Andric (NextToken().is(tok::identifier) || 1100b57cec5SDimitry Andric (NextToken().is(tok::kw_inline) && 1110b57cec5SDimitry Andric GetLookAheadToken(2).is(tok::identifier)))) { 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric InnerNamespaceInfo Info; 1140b57cec5SDimitry Andric Info.NamespaceLoc = ConsumeToken(); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric if (Tok.is(tok::kw_inline)) { 1170b57cec5SDimitry Andric Info.InlineLoc = ConsumeToken(); 1180b57cec5SDimitry Andric if (FirstNestedInlineLoc.isInvalid()) 1190b57cec5SDimitry Andric FirstNestedInlineLoc = Info.InlineLoc; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric Info.Ident = Tok.getIdentifierInfo(); 1230b57cec5SDimitry Andric Info.IdentLoc = ConsumeToken(); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric ExtraNSs.push_back(Info); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 12981ad6265SDimitry Andric ReadAttributes(); 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric SourceLocation attrLoc = attrs.Range.getBegin(); 13281ad6265SDimitry Andric 1330b57cec5SDimitry Andric // A nested namespace definition cannot have attributes. 1340b57cec5SDimitry Andric if (!ExtraNSs.empty() && attrLoc.isValid()) 1350b57cec5SDimitry Andric Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric if (Tok.is(tok::equal)) { 1380b57cec5SDimitry Andric if (!Ident) { 1390b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; 1400b57cec5SDimitry Andric // Skip to end of the definition and eat the ';'. 1410b57cec5SDimitry Andric SkipUntil(tok::semi); 1420b57cec5SDimitry Andric return nullptr; 1430b57cec5SDimitry Andric } 144*0fca6ea1SDimitry Andric if (!ExtraNSs.empty()) { 145*0fca6ea1SDimitry Andric Diag(ExtraNSs.front().NamespaceLoc, 146*0fca6ea1SDimitry Andric diag::err_unexpected_qualified_namespace_alias) 147*0fca6ea1SDimitry Andric << SourceRange(ExtraNSs.front().NamespaceLoc, 148*0fca6ea1SDimitry Andric ExtraNSs.back().IdentLoc); 149*0fca6ea1SDimitry Andric SkipUntil(tok::semi); 150*0fca6ea1SDimitry Andric return nullptr; 151*0fca6ea1SDimitry Andric } 1520b57cec5SDimitry Andric if (attrLoc.isValid()) 1530b57cec5SDimitry Andric Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); 1540b57cec5SDimitry Andric if (InlineLoc.isValid()) 1550b57cec5SDimitry Andric Diag(InlineLoc, diag::err_inline_namespace_alias) 1560b57cec5SDimitry Andric << FixItHint::CreateRemoval(InlineLoc); 1570b57cec5SDimitry Andric Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); 1580b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(NSAlias); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace); 1620b57cec5SDimitry Andric if (T.consumeOpen()) { 1630b57cec5SDimitry Andric if (Ident) 1640b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 1650b57cec5SDimitry Andric else 1660b57cec5SDimitry Andric Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; 1670b57cec5SDimitry Andric return nullptr; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || 1710b57cec5SDimitry Andric getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || 1720b57cec5SDimitry Andric getCurScope()->getFnParent()) { 1730b57cec5SDimitry Andric Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); 1740b57cec5SDimitry Andric SkipUntil(tok::r_brace); 1750b57cec5SDimitry Andric return nullptr; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric if (ExtraNSs.empty()) { 1790b57cec5SDimitry Andric // Normal namespace definition, not a nested-namespace-definition. 1800b57cec5SDimitry Andric } else if (InlineLoc.isValid()) { 1810b57cec5SDimitry Andric Diag(InlineLoc, diag::err_inline_nested_namespace_definition); 1825ffd83dbSDimitry Andric } else if (getLangOpts().CPlusPlus20) { 1830b57cec5SDimitry Andric Diag(ExtraNSs[0].NamespaceLoc, 1840b57cec5SDimitry Andric diag::warn_cxx14_compat_nested_namespace_definition); 1850b57cec5SDimitry Andric if (FirstNestedInlineLoc.isValid()) 1860b57cec5SDimitry Andric Diag(FirstNestedInlineLoc, 1870b57cec5SDimitry Andric diag::warn_cxx17_compat_inline_nested_namespace_definition); 1880b57cec5SDimitry Andric } else if (getLangOpts().CPlusPlus17) { 1890b57cec5SDimitry Andric Diag(ExtraNSs[0].NamespaceLoc, 1900b57cec5SDimitry Andric diag::warn_cxx14_compat_nested_namespace_definition); 1910b57cec5SDimitry Andric if (FirstNestedInlineLoc.isValid()) 1920b57cec5SDimitry Andric Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition); 1930b57cec5SDimitry Andric } else { 1940b57cec5SDimitry Andric TentativeParsingAction TPA(*this); 1950b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopBeforeMatch); 1960b57cec5SDimitry Andric Token rBraceToken = Tok; 1970b57cec5SDimitry Andric TPA.Revert(); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric if (!rBraceToken.is(tok::r_brace)) { 2000b57cec5SDimitry Andric Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition) 2010b57cec5SDimitry Andric << SourceRange(ExtraNSs.front().NamespaceLoc, 2020b57cec5SDimitry Andric ExtraNSs.back().IdentLoc); 2030b57cec5SDimitry Andric } else { 2040b57cec5SDimitry Andric std::string NamespaceFix; 2050b57cec5SDimitry Andric for (const auto &ExtraNS : ExtraNSs) { 2060b57cec5SDimitry Andric NamespaceFix += " { "; 2070b57cec5SDimitry Andric if (ExtraNS.InlineLoc.isValid()) 2080b57cec5SDimitry Andric NamespaceFix += "inline "; 2090b57cec5SDimitry Andric NamespaceFix += "namespace "; 2100b57cec5SDimitry Andric NamespaceFix += ExtraNS.Ident->getName(); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric std::string RBraces; 2140b57cec5SDimitry Andric for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i) 2150b57cec5SDimitry Andric RBraces += "} "; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition) 2180b57cec5SDimitry Andric << FixItHint::CreateReplacement( 2190b57cec5SDimitry Andric SourceRange(ExtraNSs.front().NamespaceLoc, 2200b57cec5SDimitry Andric ExtraNSs.back().IdentLoc), 2210b57cec5SDimitry Andric NamespaceFix) 2220b57cec5SDimitry Andric << FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric // Warn about nested inline namespaces. 2260b57cec5SDimitry Andric if (FirstNestedInlineLoc.isValid()) 2270b57cec5SDimitry Andric Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // If we're still good, complain about inline namespaces in non-C++0x now. 2310b57cec5SDimitry Andric if (InlineLoc.isValid()) 232972a253aSDimitry Andric Diag(InlineLoc, getLangOpts().CPlusPlus11 233972a253aSDimitry Andric ? diag::warn_cxx98_compat_inline_namespace 234972a253aSDimitry Andric : diag::ext_inline_namespace); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Enter a scope for the namespace. 2370b57cec5SDimitry Andric ParseScope NamespaceScope(this, Scope::DeclScope); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; 2400b57cec5SDimitry Andric Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( 2410b57cec5SDimitry Andric getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, 242bdd1243dSDimitry Andric T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, false); 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, 2450b57cec5SDimitry Andric NamespaceLoc, "parsing namespace"); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // Parse the contents of the namespace. This includes parsing recovery on 2480b57cec5SDimitry Andric // any improperly nested namespaces. 2490b57cec5SDimitry Andric ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // Leave the namespace scope. 2520b57cec5SDimitry Andric NamespaceScope.Exit(); 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric DeclEnd = T.getCloseLocation(); 2550b57cec5SDimitry Andric Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(NamespcDecl, 2580b57cec5SDimitry Andric ImplicitUsingDirectiveDecl); 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric /// ParseInnerNamespace - Parse the contents of a namespace. 2620b57cec5SDimitry Andric void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs, 2630b57cec5SDimitry Andric unsigned int index, SourceLocation &InlineLoc, 2640b57cec5SDimitry Andric ParsedAttributes &attrs, 2650b57cec5SDimitry Andric BalancedDelimiterTracker &Tracker) { 2660b57cec5SDimitry Andric if (index == InnerNSs.size()) { 2670b57cec5SDimitry Andric while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && 2680b57cec5SDimitry Andric Tok.isNot(tok::eof)) { 269bdd1243dSDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 270bdd1243dSDimitry Andric MaybeParseCXX11Attributes(DeclAttrs); 271bdd1243dSDimitry Andric ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 272bdd1243dSDimitry Andric ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // The caller is what called check -- we are simply calling 2760b57cec5SDimitry Andric // the close for it. 2770b57cec5SDimitry Andric Tracker.consumeClose(); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric return; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // Handle a nested namespace definition. 2830b57cec5SDimitry Andric // FIXME: Preserve the source information through to the AST rather than 2840b57cec5SDimitry Andric // desugaring it here. 2850b57cec5SDimitry Andric ParseScope NamespaceScope(this, Scope::DeclScope); 2860b57cec5SDimitry Andric UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; 2870b57cec5SDimitry Andric Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( 2880b57cec5SDimitry Andric getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc, 2890b57cec5SDimitry Andric InnerNSs[index].IdentLoc, InnerNSs[index].Ident, 290bdd1243dSDimitry Andric Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, true); 2910b57cec5SDimitry Andric assert(!ImplicitUsingDirectiveDecl && 2920b57cec5SDimitry Andric "nested namespace definition cannot define anonymous namespace"); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric NamespaceScope.Exit(); 2970b57cec5SDimitry Andric Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation()); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric /// ParseNamespaceAlias - Parse the part after the '=' in a namespace 3010b57cec5SDimitry Andric /// alias definition. 3020b57cec5SDimitry Andric /// 3030b57cec5SDimitry Andric Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, 3040b57cec5SDimitry Andric SourceLocation AliasLoc, 3050b57cec5SDimitry Andric IdentifierInfo *Alias, 3060b57cec5SDimitry Andric SourceLocation &DeclEnd) { 3070b57cec5SDimitry Andric assert(Tok.is(tok::equal) && "Not equal token"); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric ConsumeToken(); // eat the '='. 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 3120b57cec5SDimitry Andric cutOffParsing(); 313*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteNamespaceAliasDecl(getCurScope()); 3140b57cec5SDimitry Andric return nullptr; 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric CXXScopeSpec SS; 3180b57cec5SDimitry Andric // Parse (optional) nested-name-specifier. 3195ffd83dbSDimitry Andric ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 32004eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 3215ffd83dbSDimitry Andric /*EnteringContext=*/false, 3220b57cec5SDimitry Andric /*MayBePseudoDestructor=*/nullptr, 3230b57cec5SDimitry Andric /*IsTypename=*/false, 3240b57cec5SDimitry Andric /*LastII=*/nullptr, 3250b57cec5SDimitry Andric /*OnlyNamespace=*/true); 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) { 3280b57cec5SDimitry Andric Diag(Tok, diag::err_expected_namespace_name); 3290b57cec5SDimitry Andric // Skip to end of the definition and eat the ';'. 3300b57cec5SDimitry Andric SkipUntil(tok::semi); 3310b57cec5SDimitry Andric return nullptr; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric if (SS.isInvalid()) { 3350b57cec5SDimitry Andric // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier. 3360b57cec5SDimitry Andric // Skip to end of the definition and eat the ';'. 3370b57cec5SDimitry Andric SkipUntil(tok::semi); 3380b57cec5SDimitry Andric return nullptr; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // Parse identifier. 3420b57cec5SDimitry Andric IdentifierInfo *Ident = Tok.getIdentifierInfo(); 3430b57cec5SDimitry Andric SourceLocation IdentLoc = ConsumeToken(); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // Eat the ';'. 3460b57cec5SDimitry Andric DeclEnd = Tok.getLocation(); 3470b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name)) 3480b57cec5SDimitry Andric SkipUntil(tok::semi); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, 3510b57cec5SDimitry Andric Alias, SS, IdentLoc, Ident); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric /// ParseLinkage - We know that the current token is a string_literal 3550b57cec5SDimitry Andric /// and just before that, that extern was seen. 3560b57cec5SDimitry Andric /// 3570b57cec5SDimitry Andric /// linkage-specification: [C++ 7.5p2: dcl.link] 3580b57cec5SDimitry Andric /// 'extern' string-literal '{' declaration-seq[opt] '}' 3590b57cec5SDimitry Andric /// 'extern' string-literal declaration 3600b57cec5SDimitry Andric /// 3610b57cec5SDimitry Andric Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { 3620b57cec5SDimitry Andric assert(isTokenStringLiteral() && "Not a string literal!"); 36306c3fb27SDimitry Andric ExprResult Lang = ParseUnevaluatedStringLiteralExpression(); 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric ParseScope LinkageScope(this, Scope::DeclScope); 3660b57cec5SDimitry Andric Decl *LinkageSpec = 3670b57cec5SDimitry Andric Lang.isInvalid() 3680b57cec5SDimitry Andric ? nullptr 3690b57cec5SDimitry Andric : Actions.ActOnStartLinkageSpecification( 3700b57cec5SDimitry Andric getCurScope(), DS.getSourceRange().getBegin(), Lang.get(), 3710b57cec5SDimitry Andric Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); 3720b57cec5SDimitry Andric 37381ad6265SDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 374bdd1243dSDimitry Andric ParsedAttributes DeclSpecAttrs(AttrFactory); 375bdd1243dSDimitry Andric 376bdd1243dSDimitry Andric while (MaybeParseCXX11Attributes(DeclAttrs) || 377bdd1243dSDimitry Andric MaybeParseGNUAttributes(DeclSpecAttrs)) 378bdd1243dSDimitry Andric ; 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) { 3810b57cec5SDimitry Andric // Reset the source range in DS, as the leading "extern" 3820b57cec5SDimitry Andric // does not really belong to the inner declaration ... 3830b57cec5SDimitry Andric DS.SetRangeStart(SourceLocation()); 3840b57cec5SDimitry Andric DS.SetRangeEnd(SourceLocation()); 3850b57cec5SDimitry Andric // ... but anyway remember that such an "extern" was seen. 3860b57cec5SDimitry Andric DS.setExternInLinkageSpec(true); 387bdd1243dSDimitry Andric ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs, &DS); 3880b57cec5SDimitry Andric return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( 3890b57cec5SDimitry Andric getCurScope(), LinkageSpec, SourceLocation()) 3900b57cec5SDimitry Andric : nullptr; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric DS.abort(); 3940b57cec5SDimitry Andric 39581ad6265SDimitry Andric ProhibitAttributes(DeclAttrs); 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace); 3980b57cec5SDimitry Andric T.consumeOpen(); 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric unsigned NestedModules = 0; 4010b57cec5SDimitry Andric while (true) { 4020b57cec5SDimitry Andric switch (Tok.getKind()) { 4030b57cec5SDimitry Andric case tok::annot_module_begin: 4040b57cec5SDimitry Andric ++NestedModules; 4050b57cec5SDimitry Andric ParseTopLevelDecl(); 4060b57cec5SDimitry Andric continue; 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric case tok::annot_module_end: 4090b57cec5SDimitry Andric if (!NestedModules) 4100b57cec5SDimitry Andric break; 4110b57cec5SDimitry Andric --NestedModules; 4120b57cec5SDimitry Andric ParseTopLevelDecl(); 4130b57cec5SDimitry Andric continue; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric case tok::annot_module_include: 4160b57cec5SDimitry Andric ParseTopLevelDecl(); 4170b57cec5SDimitry Andric continue; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric case tok::eof: 4200b57cec5SDimitry Andric break; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric case tok::r_brace: 4230b57cec5SDimitry Andric if (!NestedModules) 4240b57cec5SDimitry Andric break; 425bdd1243dSDimitry Andric [[fallthrough]]; 4260b57cec5SDimitry Andric default: 427bdd1243dSDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 428bdd1243dSDimitry Andric MaybeParseCXX11Attributes(DeclAttrs); 429bdd1243dSDimitry Andric ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs); 4300b57cec5SDimitry Andric continue; 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric T.consumeClose(); 4370b57cec5SDimitry Andric return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( 4380b57cec5SDimitry Andric getCurScope(), LinkageSpec, T.getCloseLocation()) 4390b57cec5SDimitry Andric : nullptr; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 44206c3fb27SDimitry Andric /// Parse a standard C++ Modules export-declaration. 4430b57cec5SDimitry Andric /// 4440b57cec5SDimitry Andric /// export-declaration: 4450b57cec5SDimitry Andric /// 'export' declaration 4460b57cec5SDimitry Andric /// 'export' '{' declaration-seq[opt] '}' 4470b57cec5SDimitry Andric /// 448*0fca6ea1SDimitry Andric /// HLSL: Parse export function declaration. 449*0fca6ea1SDimitry Andric /// 450*0fca6ea1SDimitry Andric /// export-function-declaration: 451*0fca6ea1SDimitry Andric /// 'export' function-declaration 452*0fca6ea1SDimitry Andric /// 453*0fca6ea1SDimitry Andric /// export-declaration-group: 454*0fca6ea1SDimitry Andric /// 'export' '{' function-declaration-seq[opt] '}' 455*0fca6ea1SDimitry Andric /// 4560b57cec5SDimitry Andric Decl *Parser::ParseExportDeclaration() { 4570b57cec5SDimitry Andric assert(Tok.is(tok::kw_export)); 4580b57cec5SDimitry Andric SourceLocation ExportLoc = ConsumeToken(); 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric ParseScope ExportScope(this, Scope::DeclScope); 4610b57cec5SDimitry Andric Decl *ExportDecl = Actions.ActOnStartExportDecl( 4620b57cec5SDimitry Andric getCurScope(), ExportLoc, 4630b57cec5SDimitry Andric Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric if (Tok.isNot(tok::l_brace)) { 4660b57cec5SDimitry Andric // FIXME: Factor out a ParseExternalDeclarationWithAttrs. 467bdd1243dSDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 468bdd1243dSDimitry Andric MaybeParseCXX11Attributes(DeclAttrs); 469bdd1243dSDimitry Andric ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 470bdd1243dSDimitry Andric ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); 4710b57cec5SDimitry Andric return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl, 4720b57cec5SDimitry Andric SourceLocation()); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace); 4760b57cec5SDimitry Andric T.consumeOpen(); 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && 4790b57cec5SDimitry Andric Tok.isNot(tok::eof)) { 480bdd1243dSDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 481bdd1243dSDimitry Andric MaybeParseCXX11Attributes(DeclAttrs); 482bdd1243dSDimitry Andric ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 483bdd1243dSDimitry Andric ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric T.consumeClose(); 4870b57cec5SDimitry Andric return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl, 4880b57cec5SDimitry Andric T.getCloseLocation()); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or 4920b57cec5SDimitry Andric /// using-directive. Assumes that current token is 'using'. 49381ad6265SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseUsingDirectiveOrDeclaration( 49481ad6265SDimitry Andric DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, 49581ad6265SDimitry Andric SourceLocation &DeclEnd, ParsedAttributes &Attrs) { 4960b57cec5SDimitry Andric assert(Tok.is(tok::kw_using) && "Not using token"); 4970b57cec5SDimitry Andric ObjCDeclContextSwitch ObjCDC(*this); 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // Eat 'using'. 5000b57cec5SDimitry Andric SourceLocation UsingLoc = ConsumeToken(); 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 5030b57cec5SDimitry Andric cutOffParsing(); 504*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteUsing(getCurScope()); 5050b57cec5SDimitry Andric return nullptr; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // Consume unexpected 'template' keywords. 5090b57cec5SDimitry Andric while (Tok.is(tok::kw_template)) { 5100b57cec5SDimitry Andric SourceLocation TemplateLoc = ConsumeToken(); 5110b57cec5SDimitry Andric Diag(TemplateLoc, diag::err_unexpected_template_after_using) 5120b57cec5SDimitry Andric << FixItHint::CreateRemoval(TemplateLoc); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric // 'using namespace' means this is a using-directive. 5160b57cec5SDimitry Andric if (Tok.is(tok::kw_namespace)) { 5170b57cec5SDimitry Andric // Template parameters are always an error here. 5180b57cec5SDimitry Andric if (TemplateInfo.Kind) { 5190b57cec5SDimitry Andric SourceRange R = TemplateInfo.getSourceRange(); 5200b57cec5SDimitry Andric Diag(UsingLoc, diag::err_templated_using_directive_declaration) 5210b57cec5SDimitry Andric << 0 /* directive */ << R << FixItHint::CreateRemoval(R); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 52481ad6265SDimitry Andric Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, Attrs); 5250b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(UsingDir); 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric // Otherwise, it must be a using-declaration or an alias-declaration. 52981ad6265SDimitry Andric return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, Attrs, 5300b57cec5SDimitry Andric AS_none); 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric /// ParseUsingDirective - Parse C++ using-directive, assumes 5340b57cec5SDimitry Andric /// that current token is 'namespace' and 'using' was already parsed. 5350b57cec5SDimitry Andric /// 5360b57cec5SDimitry Andric /// using-directive: [C++ 7.3.p4: namespace.udir] 5370b57cec5SDimitry Andric /// 'using' 'namespace' ::[opt] nested-name-specifier[opt] 5380b57cec5SDimitry Andric /// namespace-name ; 5390b57cec5SDimitry Andric /// [GNU] using-directive: 5400b57cec5SDimitry Andric /// 'using' 'namespace' ::[opt] nested-name-specifier[opt] 5410b57cec5SDimitry Andric /// namespace-name attributes[opt] ; 5420b57cec5SDimitry Andric /// 5430b57cec5SDimitry Andric Decl *Parser::ParseUsingDirective(DeclaratorContext Context, 5440b57cec5SDimitry Andric SourceLocation UsingLoc, 5450b57cec5SDimitry Andric SourceLocation &DeclEnd, 5460b57cec5SDimitry Andric ParsedAttributes &attrs) { 5470b57cec5SDimitry Andric assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token"); 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric // Eat 'namespace'. 5500b57cec5SDimitry Andric SourceLocation NamespcLoc = ConsumeToken(); 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 5530b57cec5SDimitry Andric cutOffParsing(); 554*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteUsingDirective(getCurScope()); 5550b57cec5SDimitry Andric return nullptr; 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric CXXScopeSpec SS; 5590b57cec5SDimitry Andric // Parse (optional) nested-name-specifier. 5605ffd83dbSDimitry Andric ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 56104eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 5625ffd83dbSDimitry Andric /*EnteringContext=*/false, 5630b57cec5SDimitry Andric /*MayBePseudoDestructor=*/nullptr, 5640b57cec5SDimitry Andric /*IsTypename=*/false, 5650b57cec5SDimitry Andric /*LastII=*/nullptr, 5660b57cec5SDimitry Andric /*OnlyNamespace=*/true); 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric IdentifierInfo *NamespcName = nullptr; 5690b57cec5SDimitry Andric SourceLocation IdentLoc = SourceLocation(); 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric // Parse namespace-name. 5720b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) { 5730b57cec5SDimitry Andric Diag(Tok, diag::err_expected_namespace_name); 5740b57cec5SDimitry Andric // If there was invalid namespace name, skip to end of decl, and eat ';'. 5750b57cec5SDimitry Andric SkipUntil(tok::semi); 5760b57cec5SDimitry Andric // FIXME: Are there cases, when we would like to call ActOnUsingDirective? 5770b57cec5SDimitry Andric return nullptr; 5780b57cec5SDimitry Andric } 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric if (SS.isInvalid()) { 5810b57cec5SDimitry Andric // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier. 5820b57cec5SDimitry Andric // Skip to end of the definition and eat the ';'. 5830b57cec5SDimitry Andric SkipUntil(tok::semi); 5840b57cec5SDimitry Andric return nullptr; 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric // Parse identifier. 5880b57cec5SDimitry Andric NamespcName = Tok.getIdentifierInfo(); 5890b57cec5SDimitry Andric IdentLoc = ConsumeToken(); 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric // Parse (optional) attributes (most likely GNU strong-using extension). 5920b57cec5SDimitry Andric bool GNUAttr = false; 5930b57cec5SDimitry Andric if (Tok.is(tok::kw___attribute)) { 5940b57cec5SDimitry Andric GNUAttr = true; 5950b57cec5SDimitry Andric ParseGNUAttributes(attrs); 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric // Eat ';'. 5990b57cec5SDimitry Andric DeclEnd = Tok.getLocation(); 6000b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, 6010b57cec5SDimitry Andric GNUAttr ? diag::err_expected_semi_after_attribute_list 6020b57cec5SDimitry Andric : diag::err_expected_semi_after_namespace_name)) 6030b57cec5SDimitry Andric SkipUntil(tok::semi); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS, 6060b57cec5SDimitry Andric IdentLoc, NamespcName, attrs); 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric /// Parse a using-declarator (or the identifier in a C++11 alias-declaration). 6100b57cec5SDimitry Andric /// 6110b57cec5SDimitry Andric /// using-declarator: 6120b57cec5SDimitry Andric /// 'typename'[opt] nested-name-specifier unqualified-id 6130b57cec5SDimitry Andric /// 6140b57cec5SDimitry Andric bool Parser::ParseUsingDeclarator(DeclaratorContext Context, 6150b57cec5SDimitry Andric UsingDeclarator &D) { 6160b57cec5SDimitry Andric D.clear(); 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric // Ignore optional 'typename'. 6190b57cec5SDimitry Andric // FIXME: This is wrong; we should parse this as a typename-specifier. 6200b57cec5SDimitry Andric TryConsumeToken(tok::kw_typename, D.TypenameLoc); 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric if (Tok.is(tok::kw___super)) { 6230b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_super_in_using_declaration); 6240b57cec5SDimitry Andric return true; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric // Parse nested-name-specifier. 628*0fca6ea1SDimitry Andric const IdentifierInfo *LastII = nullptr; 6295ffd83dbSDimitry Andric if (ParseOptionalCXXScopeSpecifier(D.SS, /*ObjectType=*/nullptr, 63004eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 6315ffd83dbSDimitry Andric /*EnteringContext=*/false, 6320b57cec5SDimitry Andric /*MayBePseudoDtor=*/nullptr, 6330b57cec5SDimitry Andric /*IsTypename=*/false, 634480093f4SDimitry Andric /*LastII=*/&LastII, 635480093f4SDimitry Andric /*OnlyNamespace=*/false, 636480093f4SDimitry Andric /*InUsingDeclaration=*/true)) 637480093f4SDimitry Andric 6380b57cec5SDimitry Andric return true; 6390b57cec5SDimitry Andric if (D.SS.isInvalid()) 6400b57cec5SDimitry Andric return true; 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric // Parse the unqualified-id. We allow parsing of both constructor and 6430b57cec5SDimitry Andric // destructor names and allow the action module to diagnose any semantic 6440b57cec5SDimitry Andric // errors. 6450b57cec5SDimitry Andric // 6460b57cec5SDimitry Andric // C++11 [class.qual]p2: 6470b57cec5SDimitry Andric // [...] in a using-declaration that is a member-declaration, if the name 6480b57cec5SDimitry Andric // specified after the nested-name-specifier is the same as the identifier 6490b57cec5SDimitry Andric // or the simple-template-id's template-name in the last component of the 6500b57cec5SDimitry Andric // nested-name-specifier, the name is [...] considered to name the 6510b57cec5SDimitry Andric // constructor. 652e8d8bef9SDimitry Andric if (getLangOpts().CPlusPlus11 && Context == DeclaratorContext::Member && 6530b57cec5SDimitry Andric Tok.is(tok::identifier) && 6540b57cec5SDimitry Andric (NextToken().is(tok::semi) || NextToken().is(tok::comma) || 655fe6060f1SDimitry Andric NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) || 65606c3fb27SDimitry Andric NextToken().isRegularKeywordAttribute() || 657fe6060f1SDimitry Andric NextToken().is(tok::kw___attribute)) && 6580b57cec5SDimitry Andric D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && 6590b57cec5SDimitry Andric !D.SS.getScopeRep()->getAsNamespace() && 6600b57cec5SDimitry Andric !D.SS.getScopeRep()->getAsNamespaceAlias()) { 6610b57cec5SDimitry Andric SourceLocation IdLoc = ConsumeToken(); 6620b57cec5SDimitry Andric ParsedType Type = 6630b57cec5SDimitry Andric Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII); 6640b57cec5SDimitry Andric D.Name.setConstructorName(Type, IdLoc, IdLoc); 6650b57cec5SDimitry Andric } else { 6660b57cec5SDimitry Andric if (ParseUnqualifiedId( 6675ffd83dbSDimitry Andric D.SS, /*ObjectType=*/nullptr, 6685ffd83dbSDimitry Andric /*ObjectHadErrors=*/false, /*EnteringContext=*/false, 6690b57cec5SDimitry Andric /*AllowDestructorName=*/true, 6705ffd83dbSDimitry Andric /*AllowConstructorName=*/ 6715ffd83dbSDimitry Andric !(Tok.is(tok::identifier) && NextToken().is(tok::equal)), 6725ffd83dbSDimitry Andric /*AllowDeductionGuide=*/false, nullptr, D.Name)) 6730b57cec5SDimitry Andric return true; 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc)) 677972a253aSDimitry Andric Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 678972a253aSDimitry Andric ? diag::warn_cxx17_compat_using_declaration_pack 679972a253aSDimitry Andric : diag::ext_using_declaration_pack); 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric return false; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric /// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration. 6850b57cec5SDimitry Andric /// Assumes that 'using' was already seen. 6860b57cec5SDimitry Andric /// 6870b57cec5SDimitry Andric /// using-declaration: [C++ 7.3.p3: namespace.udecl] 6880b57cec5SDimitry Andric /// 'using' using-declarator-list[opt] ; 6890b57cec5SDimitry Andric /// 6900b57cec5SDimitry Andric /// using-declarator-list: [C++1z] 6910b57cec5SDimitry Andric /// using-declarator '...'[opt] 6920b57cec5SDimitry Andric /// using-declarator-list ',' using-declarator '...'[opt] 6930b57cec5SDimitry Andric /// 6940b57cec5SDimitry Andric /// using-declarator-list: [C++98-14] 6950b57cec5SDimitry Andric /// using-declarator 6960b57cec5SDimitry Andric /// 6970b57cec5SDimitry Andric /// alias-declaration: C++11 [dcl.dcl]p1 6980b57cec5SDimitry Andric /// 'using' identifier attribute-specifier-seq[opt] = type-id ; 6990b57cec5SDimitry Andric /// 700fe6060f1SDimitry Andric /// using-enum-declaration: [C++20, dcl.enum] 701fe6060f1SDimitry Andric /// 'using' elaborated-enum-specifier ; 702bdd1243dSDimitry Andric /// The terminal name of the elaborated-enum-specifier undergoes 703*0fca6ea1SDimitry Andric /// type-only lookup 704fe6060f1SDimitry Andric /// 705fe6060f1SDimitry Andric /// elaborated-enum-specifier: 706fe6060f1SDimitry Andric /// 'enum' nested-name-specifier[opt] identifier 70781ad6265SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( 708fe6060f1SDimitry Andric DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, 7090b57cec5SDimitry Andric SourceLocation UsingLoc, SourceLocation &DeclEnd, 71081ad6265SDimitry Andric ParsedAttributes &PrefixAttrs, AccessSpecifier AS) { 711fe6060f1SDimitry Andric SourceLocation UELoc; 712349cc55cSDimitry Andric bool InInitStatement = Context == DeclaratorContext::SelectionInit || 713349cc55cSDimitry Andric Context == DeclaratorContext::ForInit; 714349cc55cSDimitry Andric 715349cc55cSDimitry Andric if (TryConsumeToken(tok::kw_enum, UELoc) && !InInitStatement) { 716fe6060f1SDimitry Andric // C++20 using-enum 717fe6060f1SDimitry Andric Diag(UELoc, getLangOpts().CPlusPlus20 718fe6060f1SDimitry Andric ? diag::warn_cxx17_compat_using_enum_declaration 719fe6060f1SDimitry Andric : diag::ext_using_enum_declaration); 720fe6060f1SDimitry Andric 721fe6060f1SDimitry Andric DiagnoseCXX11AttributeExtension(PrefixAttrs); 722fe6060f1SDimitry Andric 723fe6060f1SDimitry Andric if (TemplateInfo.Kind) { 724fe6060f1SDimitry Andric SourceRange R = TemplateInfo.getSourceRange(); 725fe6060f1SDimitry Andric Diag(UsingLoc, diag::err_templated_using_directive_declaration) 726fe6060f1SDimitry Andric << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); 727bdd1243dSDimitry Andric SkipUntil(tok::semi); 728bdd1243dSDimitry Andric return nullptr; 729bdd1243dSDimitry Andric } 730bdd1243dSDimitry Andric CXXScopeSpec SS; 731bdd1243dSDimitry Andric if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr, 732bdd1243dSDimitry Andric /*ObectHasErrors=*/false, 733bdd1243dSDimitry Andric /*EnteringConttext=*/false, 734bdd1243dSDimitry Andric /*MayBePseudoDestructor=*/nullptr, 735*0fca6ea1SDimitry Andric /*IsTypename=*/true, 736bdd1243dSDimitry Andric /*IdentifierInfo=*/nullptr, 737bdd1243dSDimitry Andric /*OnlyNamespace=*/false, 738bdd1243dSDimitry Andric /*InUsingDeclaration=*/true)) { 739bdd1243dSDimitry Andric SkipUntil(tok::semi); 740fe6060f1SDimitry Andric return nullptr; 741fe6060f1SDimitry Andric } 742fe6060f1SDimitry Andric 743bdd1243dSDimitry Andric if (Tok.is(tok::code_completion)) { 744bdd1243dSDimitry Andric cutOffParsing(); 745*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteUsing(getCurScope()); 746bdd1243dSDimitry Andric return nullptr; 747bdd1243dSDimitry Andric } 748bdd1243dSDimitry Andric 749*0fca6ea1SDimitry Andric Decl *UED = nullptr; 750*0fca6ea1SDimitry Andric 751*0fca6ea1SDimitry Andric // FIXME: identifier and annot_template_id handling is very similar to 752*0fca6ea1SDimitry Andric // ParseBaseTypeSpecifier. It should be factored out into a function. 753*0fca6ea1SDimitry Andric if (Tok.is(tok::identifier)) { 754*0fca6ea1SDimitry Andric IdentifierInfo *IdentInfo = Tok.getIdentifierInfo(); 755*0fca6ea1SDimitry Andric SourceLocation IdentLoc = ConsumeToken(); 756*0fca6ea1SDimitry Andric 757*0fca6ea1SDimitry Andric ParsedType Type = Actions.getTypeName( 758*0fca6ea1SDimitry Andric *IdentInfo, IdentLoc, getCurScope(), &SS, /*isClassName=*/true, 759*0fca6ea1SDimitry Andric /*HasTrailingDot=*/false, 760*0fca6ea1SDimitry Andric /*ObjectType=*/nullptr, /*IsCtorOrDtorName=*/false, 761*0fca6ea1SDimitry Andric /*WantNontrivialTypeSourceInfo=*/true); 762*0fca6ea1SDimitry Andric 763*0fca6ea1SDimitry Andric UED = Actions.ActOnUsingEnumDeclaration( 764*0fca6ea1SDimitry Andric getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, Type, &SS); 765*0fca6ea1SDimitry Andric } else if (Tok.is(tok::annot_template_id)) { 766*0fca6ea1SDimitry Andric TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); 767*0fca6ea1SDimitry Andric 768*0fca6ea1SDimitry Andric if (TemplateId->mightBeType()) { 769*0fca6ea1SDimitry Andric AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, 770*0fca6ea1SDimitry Andric /*IsClassName=*/true); 771*0fca6ea1SDimitry Andric 772*0fca6ea1SDimitry Andric assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); 773*0fca6ea1SDimitry Andric TypeResult Type = getTypeAnnotation(Tok); 774*0fca6ea1SDimitry Andric SourceRange Loc = Tok.getAnnotationRange(); 775*0fca6ea1SDimitry Andric ConsumeAnnotationToken(); 776*0fca6ea1SDimitry Andric 777*0fca6ea1SDimitry Andric UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc, 778*0fca6ea1SDimitry Andric UELoc, Loc, *TemplateId->Name, 779*0fca6ea1SDimitry Andric Type.get(), &SS); 780*0fca6ea1SDimitry Andric } else { 781*0fca6ea1SDimitry Andric Diag(Tok.getLocation(), diag::err_using_enum_not_enum) 782*0fca6ea1SDimitry Andric << TemplateId->Name->getName() 783*0fca6ea1SDimitry Andric << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); 784*0fca6ea1SDimitry Andric } 785*0fca6ea1SDimitry Andric } else { 786bdd1243dSDimitry Andric Diag(Tok.getLocation(), diag::err_using_enum_expect_identifier) 787bdd1243dSDimitry Andric << Tok.is(tok::kw_enum); 788bdd1243dSDimitry Andric SkipUntil(tok::semi); 789bdd1243dSDimitry Andric return nullptr; 790bdd1243dSDimitry Andric } 791*0fca6ea1SDimitry Andric 792bdd1243dSDimitry Andric if (!UED) { 793bdd1243dSDimitry Andric SkipUntil(tok::semi); 794bdd1243dSDimitry Andric return nullptr; 795bdd1243dSDimitry Andric } 796bdd1243dSDimitry Andric 797fe6060f1SDimitry Andric DeclEnd = Tok.getLocation(); 798fe6060f1SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_after, 799fe6060f1SDimitry Andric "using-enum declaration")) 800fe6060f1SDimitry Andric SkipUntil(tok::semi); 801fe6060f1SDimitry Andric 802fe6060f1SDimitry Andric return Actions.ConvertDeclToDeclGroup(UED); 803fe6060f1SDimitry Andric } 804fe6060f1SDimitry Andric 8050b57cec5SDimitry Andric // Check for misplaced attributes before the identifier in an 8060b57cec5SDimitry Andric // alias-declaration. 80781ad6265SDimitry Andric ParsedAttributes MisplacedAttrs(AttrFactory); 8080b57cec5SDimitry Andric MaybeParseCXX11Attributes(MisplacedAttrs); 8090b57cec5SDimitry Andric 810349cc55cSDimitry Andric if (InInitStatement && Tok.isNot(tok::identifier)) 811349cc55cSDimitry Andric return nullptr; 812349cc55cSDimitry Andric 8130b57cec5SDimitry Andric UsingDeclarator D; 8140b57cec5SDimitry Andric bool InvalidDeclarator = ParseUsingDeclarator(Context, D); 8150b57cec5SDimitry Andric 81681ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory); 817fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric // If we had any misplaced attributes from earlier, this is where they 8200b57cec5SDimitry Andric // should have been written. 8210b57cec5SDimitry Andric if (MisplacedAttrs.Range.isValid()) { 82206c3fb27SDimitry Andric auto *FirstAttr = 82306c3fb27SDimitry Andric MisplacedAttrs.empty() ? nullptr : &MisplacedAttrs.front(); 82406c3fb27SDimitry Andric auto &Range = MisplacedAttrs.Range; 82506c3fb27SDimitry Andric (FirstAttr && FirstAttr->isRegularKeywordAttribute() 82606c3fb27SDimitry Andric ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr 82706c3fb27SDimitry Andric : Diag(Range.getBegin(), diag::err_attributes_not_allowed)) 8280b57cec5SDimitry Andric << FixItHint::CreateInsertionFromRange( 82906c3fb27SDimitry Andric Tok.getLocation(), CharSourceRange::getTokenRange(Range)) 83006c3fb27SDimitry Andric << FixItHint::CreateRemoval(Range); 8310b57cec5SDimitry Andric Attrs.takeAllFrom(MisplacedAttrs); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 834fe6060f1SDimitry Andric // Maybe this is an alias-declaration. 835349cc55cSDimitry Andric if (Tok.is(tok::equal) || InInitStatement) { 836fe6060f1SDimitry Andric if (InvalidDeclarator) { 837fe6060f1SDimitry Andric SkipUntil(tok::semi); 838fe6060f1SDimitry Andric return nullptr; 839fe6060f1SDimitry Andric } 840fe6060f1SDimitry Andric 841fe6060f1SDimitry Andric ProhibitAttributes(PrefixAttrs); 842fe6060f1SDimitry Andric 8430b57cec5SDimitry Andric Decl *DeclFromDeclSpec = nullptr; 844*0fca6ea1SDimitry Andric Scope *CurScope = getCurScope(); 845*0fca6ea1SDimitry Andric if (CurScope) 846*0fca6ea1SDimitry Andric CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope | 847*0fca6ea1SDimitry Andric CurScope->getFlags()); 848*0fca6ea1SDimitry Andric 8490b57cec5SDimitry Andric Decl *AD = ParseAliasDeclarationAfterDeclarator( 8500b57cec5SDimitry Andric TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec); 8510b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec); 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 854fe6060f1SDimitry Andric DiagnoseCXX11AttributeExtension(PrefixAttrs); 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric // Diagnose an attempt to declare a templated using-declaration. 8570b57cec5SDimitry Andric // In C++11, alias-declarations can be templates: 8580b57cec5SDimitry Andric // template <...> using id = type; 8590b57cec5SDimitry Andric if (TemplateInfo.Kind) { 8600b57cec5SDimitry Andric SourceRange R = TemplateInfo.getSourceRange(); 8610b57cec5SDimitry Andric Diag(UsingLoc, diag::err_templated_using_directive_declaration) 8620b57cec5SDimitry Andric << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric // Unfortunately, we have to bail out instead of recovering by 8650b57cec5SDimitry Andric // ignoring the parameters, just in case the nested name specifier 8660b57cec5SDimitry Andric // depends on the parameters. 8670b57cec5SDimitry Andric return nullptr; 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric SmallVector<Decl *, 8> DeclsInGroup; 8710b57cec5SDimitry Andric while (true) { 872fe6060f1SDimitry Andric // Parse (optional) attributes. 873fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); 874fe6060f1SDimitry Andric DiagnoseCXX11AttributeExtension(Attrs); 875fe6060f1SDimitry Andric Attrs.addAll(PrefixAttrs.begin(), PrefixAttrs.end()); 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric if (InvalidDeclarator) 8780b57cec5SDimitry Andric SkipUntil(tok::comma, tok::semi, StopBeforeMatch); 8790b57cec5SDimitry Andric else { 8800b57cec5SDimitry Andric // "typename" keyword is allowed for identifiers only, 8810b57cec5SDimitry Andric // because it may be a type definition. 8820b57cec5SDimitry Andric if (D.TypenameLoc.isValid() && 8830b57cec5SDimitry Andric D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) { 8840b57cec5SDimitry Andric Diag(D.Name.getSourceRange().getBegin(), 8850b57cec5SDimitry Andric diag::err_typename_identifiers_only) 8860b57cec5SDimitry Andric << FixItHint::CreateRemoval(SourceRange(D.TypenameLoc)); 8870b57cec5SDimitry Andric // Proceed parsing, but discard the typename keyword. 8880b57cec5SDimitry Andric D.TypenameLoc = SourceLocation(); 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, 8920b57cec5SDimitry Andric D.TypenameLoc, D.SS, D.Name, 8930b57cec5SDimitry Andric D.EllipsisLoc, Attrs); 8940b57cec5SDimitry Andric if (UD) 8950b57cec5SDimitry Andric DeclsInGroup.push_back(UD); 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma)) 8990b57cec5SDimitry Andric break; 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric // Parse another using-declarator. 9020b57cec5SDimitry Andric Attrs.clear(); 9030b57cec5SDimitry Andric InvalidDeclarator = ParseUsingDeclarator(Context, D); 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric if (DeclsInGroup.size() > 1) 907972a253aSDimitry Andric Diag(Tok.getLocation(), 908972a253aSDimitry Andric getLangOpts().CPlusPlus17 909972a253aSDimitry Andric ? diag::warn_cxx17_compat_multi_using_declaration 910972a253aSDimitry Andric : diag::ext_multi_using_declaration); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric // Eat ';'. 9130b57cec5SDimitry Andric DeclEnd = Tok.getLocation(); 9140b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_after, 9150b57cec5SDimitry Andric !Attrs.empty() ? "attributes list" 916fe6060f1SDimitry Andric : UELoc.isValid() ? "using-enum declaration" 9170b57cec5SDimitry Andric : "using declaration")) 9180b57cec5SDimitry Andric SkipUntil(tok::semi); 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric return Actions.BuildDeclaratorGroup(DeclsInGroup); 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric Decl *Parser::ParseAliasDeclarationAfterDeclarator( 9240b57cec5SDimitry Andric const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, 9250b57cec5SDimitry Andric UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS, 9260b57cec5SDimitry Andric ParsedAttributes &Attrs, Decl **OwnedType) { 9270b57cec5SDimitry Andric if (ExpectAndConsume(tok::equal)) { 9280b57cec5SDimitry Andric SkipUntil(tok::semi); 9290b57cec5SDimitry Andric return nullptr; 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 932972a253aSDimitry Andric Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 933972a253aSDimitry Andric ? diag::warn_cxx98_compat_alias_declaration 934972a253aSDimitry Andric : diag::ext_alias_declaration); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric // Type alias templates cannot be specialized. 9370b57cec5SDimitry Andric int SpecKind = -1; 9380b57cec5SDimitry Andric if (TemplateInfo.Kind == ParsedTemplateInfo::Template && 9390b57cec5SDimitry Andric D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId) 9400b57cec5SDimitry Andric SpecKind = 0; 9410b57cec5SDimitry Andric if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) 9420b57cec5SDimitry Andric SpecKind = 1; 9430b57cec5SDimitry Andric if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) 9440b57cec5SDimitry Andric SpecKind = 2; 9450b57cec5SDimitry Andric if (SpecKind != -1) { 9460b57cec5SDimitry Andric SourceRange Range; 9470b57cec5SDimitry Andric if (SpecKind == 0) 9480b57cec5SDimitry Andric Range = SourceRange(D.Name.TemplateId->LAngleLoc, 9490b57cec5SDimitry Andric D.Name.TemplateId->RAngleLoc); 9500b57cec5SDimitry Andric else 9510b57cec5SDimitry Andric Range = TemplateInfo.getSourceRange(); 9520b57cec5SDimitry Andric Diag(Range.getBegin(), diag::err_alias_declaration_specialization) 9530b57cec5SDimitry Andric << SpecKind << Range; 9540b57cec5SDimitry Andric SkipUntil(tok::semi); 9550b57cec5SDimitry Andric return nullptr; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric // Name must be an identifier. 9590b57cec5SDimitry Andric if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) { 9600b57cec5SDimitry Andric Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier); 9610b57cec5SDimitry Andric // No removal fixit: can't recover from this. 9620b57cec5SDimitry Andric SkipUntil(tok::semi); 9630b57cec5SDimitry Andric return nullptr; 9640b57cec5SDimitry Andric } else if (D.TypenameLoc.isValid()) 9650b57cec5SDimitry Andric Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier) 966972a253aSDimitry Andric << FixItHint::CreateRemoval( 967972a253aSDimitry Andric SourceRange(D.TypenameLoc, D.SS.isNotEmpty() ? D.SS.getEndLoc() 968972a253aSDimitry Andric : D.TypenameLoc)); 9690b57cec5SDimitry Andric else if (D.SS.isNotEmpty()) 9700b57cec5SDimitry Andric Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) 9710b57cec5SDimitry Andric << FixItHint::CreateRemoval(D.SS.getRange()); 9720b57cec5SDimitry Andric if (D.EllipsisLoc.isValid()) 9730b57cec5SDimitry Andric Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion) 9740b57cec5SDimitry Andric << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric Decl *DeclFromDeclSpec = nullptr; 977e8d8bef9SDimitry Andric TypeResult TypeAlias = 978e8d8bef9SDimitry Andric ParseTypeName(nullptr, 979e8d8bef9SDimitry Andric TemplateInfo.Kind ? DeclaratorContext::AliasTemplate 980e8d8bef9SDimitry Andric : DeclaratorContext::AliasDecl, 9810b57cec5SDimitry Andric AS, &DeclFromDeclSpec, &Attrs); 9820b57cec5SDimitry Andric if (OwnedType) 9830b57cec5SDimitry Andric *OwnedType = DeclFromDeclSpec; 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric // Eat ';'. 9860b57cec5SDimitry Andric DeclEnd = Tok.getLocation(); 9870b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_after, 9880b57cec5SDimitry Andric !Attrs.empty() ? "attributes list" 9890b57cec5SDimitry Andric : "alias declaration")) 9900b57cec5SDimitry Andric SkipUntil(tok::semi); 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; 9930b57cec5SDimitry Andric MultiTemplateParamsArg TemplateParamsArg( 9940b57cec5SDimitry Andric TemplateParams ? TemplateParams->data() : nullptr, 9950b57cec5SDimitry Andric TemplateParams ? TemplateParams->size() : 0); 9960b57cec5SDimitry Andric return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, 9970b57cec5SDimitry Andric UsingLoc, D.Name, Attrs, TypeAlias, 9980b57cec5SDimitry Andric DeclFromDeclSpec); 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric 1001fe6060f1SDimitry Andric static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr, 1002fe6060f1SDimitry Andric SourceLocation EndExprLoc) { 1003fe6060f1SDimitry Andric if (const auto *BO = dyn_cast_or_null<BinaryOperator>(AssertExpr)) { 1004fe6060f1SDimitry Andric if (BO->getOpcode() == BO_LAnd && 1005fe6060f1SDimitry Andric isa<StringLiteral>(BO->getRHS()->IgnoreImpCasts())) 1006fe6060f1SDimitry Andric return FixItHint::CreateReplacement(BO->getOperatorLoc(), ","); 1007fe6060f1SDimitry Andric } 1008fe6060f1SDimitry Andric return FixItHint::CreateInsertion(EndExprLoc, ", \"\""); 1009fe6060f1SDimitry Andric } 1010fe6060f1SDimitry Andric 10110b57cec5SDimitry Andric /// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration. 10120b57cec5SDimitry Andric /// 10130b57cec5SDimitry Andric /// [C++0x] static_assert-declaration: 10140b57cec5SDimitry Andric /// static_assert ( constant-expression , string-literal ) ; 10150b57cec5SDimitry Andric /// 10160b57cec5SDimitry Andric /// [C11] static_assert-declaration: 10170b57cec5SDimitry Andric /// _Static_assert ( constant-expression , string-literal ) ; 10180b57cec5SDimitry Andric /// 10190b57cec5SDimitry Andric Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) { 10200b57cec5SDimitry Andric assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) && 10210b57cec5SDimitry Andric "Not a static_assert declaration"); 10220b57cec5SDimitry Andric 102306c3fb27SDimitry Andric // Save the token name used for static assertion. 102406c3fb27SDimitry Andric const char *TokName = Tok.getName(); 1025972a253aSDimitry Andric 1026*0fca6ea1SDimitry Andric if (Tok.is(tok::kw__Static_assert)) 1027*0fca6ea1SDimitry Andric diagnoseUseOfC11Keyword(Tok); 1028*0fca6ea1SDimitry Andric else if (Tok.is(tok::kw_static_assert)) { 1029bdd1243dSDimitry Andric if (!getLangOpts().CPlusPlus) { 10305f757f3fSDimitry Andric if (getLangOpts().C23) 10315f757f3fSDimitry Andric Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName(); 103206c3fb27SDimitry Andric else 1033bdd1243dSDimitry Andric Diag(Tok, diag::ext_ms_static_assert) << FixItHint::CreateReplacement( 1034bdd1243dSDimitry Andric Tok.getLocation(), "_Static_assert"); 1035bdd1243dSDimitry Andric } else 10360b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_static_assert); 1037fe6060f1SDimitry Andric } 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric SourceLocation StaticAssertLoc = ConsumeToken(); 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 10420b57cec5SDimitry Andric if (T.consumeOpen()) { 10430b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren; 10440b57cec5SDimitry Andric SkipMalformedDecl(); 10450b57cec5SDimitry Andric return nullptr; 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 10490b57cec5SDimitry Andric Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); 10500b57cec5SDimitry Andric ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext()); 10510b57cec5SDimitry Andric if (AssertExpr.isInvalid()) { 10520b57cec5SDimitry Andric SkipMalformedDecl(); 10530b57cec5SDimitry Andric return nullptr; 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric ExprResult AssertMessage; 10570b57cec5SDimitry Andric if (Tok.is(tok::r_paren)) { 1058fe6060f1SDimitry Andric unsigned DiagVal; 1059fe6060f1SDimitry Andric if (getLangOpts().CPlusPlus17) 1060fe6060f1SDimitry Andric DiagVal = diag::warn_cxx14_compat_static_assert_no_message; 1061fe6060f1SDimitry Andric else if (getLangOpts().CPlusPlus) 1062fe6060f1SDimitry Andric DiagVal = diag::ext_cxx_static_assert_no_message; 10635f757f3fSDimitry Andric else if (getLangOpts().C23) 1064fe6060f1SDimitry Andric DiagVal = diag::warn_c17_compat_static_assert_no_message; 1065fe6060f1SDimitry Andric else 1066fe6060f1SDimitry Andric DiagVal = diag::ext_c_static_assert_no_message; 1067fe6060f1SDimitry Andric Diag(Tok, DiagVal) << getStaticAssertNoMessageFixIt(AssertExpr.get(), 1068fe6060f1SDimitry Andric Tok.getLocation()); 10690b57cec5SDimitry Andric } else { 10700b57cec5SDimitry Andric if (ExpectAndConsume(tok::comma)) { 10710b57cec5SDimitry Andric SkipUntil(tok::semi); 10720b57cec5SDimitry Andric return nullptr; 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric 10758a4dda33SDimitry Andric bool ParseAsExpression = false; 10768a4dda33SDimitry Andric if (getLangOpts().CPlusPlus26) { 10778a4dda33SDimitry Andric for (unsigned I = 0;; ++I) { 10788a4dda33SDimitry Andric const Token &T = GetLookAheadToken(I); 10798a4dda33SDimitry Andric if (T.is(tok::r_paren)) 10808a4dda33SDimitry Andric break; 10815f757f3fSDimitry Andric if (!tokenIsLikeStringLiteral(T, getLangOpts()) || T.hasUDSuffix()) { 10828a4dda33SDimitry Andric ParseAsExpression = true; 10838a4dda33SDimitry Andric break; 10848a4dda33SDimitry Andric } 10858a4dda33SDimitry Andric } 10868a4dda33SDimitry Andric } 10878a4dda33SDimitry Andric 10888a4dda33SDimitry Andric if (ParseAsExpression) 108906c3fb27SDimitry Andric AssertMessage = ParseConstantExpressionInExprEvalContext(); 10905f757f3fSDimitry Andric else if (tokenIsLikeStringLiteral(Tok, getLangOpts())) 10918a4dda33SDimitry Andric AssertMessage = ParseUnevaluatedStringLiteralExpression(); 109206c3fb27SDimitry Andric else { 10930b57cec5SDimitry Andric Diag(Tok, diag::err_expected_string_literal) 10940b57cec5SDimitry Andric << /*Source='static_assert'*/ 1; 10950b57cec5SDimitry Andric SkipMalformedDecl(); 10960b57cec5SDimitry Andric return nullptr; 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric if (AssertMessage.isInvalid()) { 11000b57cec5SDimitry Andric SkipMalformedDecl(); 11010b57cec5SDimitry Andric return nullptr; 11020b57cec5SDimitry Andric } 11030b57cec5SDimitry Andric } 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric T.consumeClose(); 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric DeclEnd = Tok.getLocation(); 110806c3fb27SDimitry Andric ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert, TokName); 11090b57cec5SDimitry Andric 1110972a253aSDimitry Andric return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.get(), 11110b57cec5SDimitry Andric AssertMessage.get(), 11120b57cec5SDimitry Andric T.getCloseLocation()); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric /// ParseDecltypeSpecifier - Parse a C++11 decltype specifier. 11160b57cec5SDimitry Andric /// 11170b57cec5SDimitry Andric /// 'decltype' ( expression ) 11180b57cec5SDimitry Andric /// 'decltype' ( 'auto' ) [C++1y] 11190b57cec5SDimitry Andric /// 11200b57cec5SDimitry Andric SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { 1121972a253aSDimitry Andric assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) && 1122972a253aSDimitry Andric "Not a decltype specifier"); 11230b57cec5SDimitry Andric 11240b57cec5SDimitry Andric ExprResult Result; 11250b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 11260b57cec5SDimitry Andric SourceLocation EndLoc; 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric if (Tok.is(tok::annot_decltype)) { 11290b57cec5SDimitry Andric Result = getExprAnnotation(Tok); 11300b57cec5SDimitry Andric EndLoc = Tok.getAnnotationEndLoc(); 113104eeddc0SDimitry Andric // Unfortunately, we don't know the LParen source location as the annotated 113204eeddc0SDimitry Andric // token doesn't have it. 1133bdd1243dSDimitry Andric DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc)); 11340b57cec5SDimitry Andric ConsumeAnnotationToken(); 11350b57cec5SDimitry Andric if (Result.isInvalid()) { 11360b57cec5SDimitry Andric DS.SetTypeSpecError(); 11370b57cec5SDimitry Andric return EndLoc; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric } else { 11400b57cec5SDimitry Andric if (Tok.getIdentifierInfo()->isStr("decltype")) 11410b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_decltype); 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric ConsumeToken(); 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 1146972a253aSDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, "decltype", 1147972a253aSDimitry Andric tok::r_paren)) { 11480b57cec5SDimitry Andric DS.SetTypeSpecError(); 1149972a253aSDimitry Andric return T.getOpenLocation() == Tok.getLocation() ? StartLoc 1150972a253aSDimitry Andric : T.getOpenLocation(); 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric // Check for C++1y 'decltype(auto)'. 115481ad6265SDimitry Andric if (Tok.is(tok::kw_auto) && NextToken().is(tok::r_paren)) { 115581ad6265SDimitry Andric // the typename-specifier in a function-style cast expression may 115606c3fb27SDimitry Andric // be 'auto' since C++23. 11570b57cec5SDimitry Andric Diag(Tok.getLocation(), 11580b57cec5SDimitry Andric getLangOpts().CPlusPlus14 11590b57cec5SDimitry Andric ? diag::warn_cxx11_compat_decltype_auto_type_specifier 11600b57cec5SDimitry Andric : diag::ext_decltype_auto_type_specifier); 11610b57cec5SDimitry Andric ConsumeToken(); 11620b57cec5SDimitry Andric } else { 11630b57cec5SDimitry Andric // Parse the expression 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric // C++11 [dcl.type.simple]p4: 11660b57cec5SDimitry Andric // The operand of the decltype specifier is an unevaluated operand. 11670b57cec5SDimitry Andric EnterExpressionEvaluationContext Unevaluated( 11680b57cec5SDimitry Andric Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, 11690b57cec5SDimitry Andric Sema::ExpressionEvaluationContextRecord::EK_Decltype); 11705ffd83dbSDimitry Andric Result = Actions.CorrectDelayedTyposInExpr( 11715ffd83dbSDimitry Andric ParseExpression(), /*InitDecl=*/nullptr, 11725ffd83dbSDimitry Andric /*RecoverUncorrectedTypos=*/false, 11735ffd83dbSDimitry Andric [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; }); 11740b57cec5SDimitry Andric if (Result.isInvalid()) { 11750b57cec5SDimitry Andric DS.SetTypeSpecError(); 11760b57cec5SDimitry Andric if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { 11770b57cec5SDimitry Andric EndLoc = ConsumeParen(); 11780b57cec5SDimitry Andric } else { 11790b57cec5SDimitry Andric if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) { 11800b57cec5SDimitry Andric // Backtrack to get the location of the last token before the semi. 11810b57cec5SDimitry Andric PP.RevertCachedTokens(2); 11820b57cec5SDimitry Andric ConsumeToken(); // the semi. 11830b57cec5SDimitry Andric EndLoc = ConsumeAnyToken(); 11840b57cec5SDimitry Andric assert(Tok.is(tok::semi)); 11850b57cec5SDimitry Andric } else { 11860b57cec5SDimitry Andric EndLoc = Tok.getLocation(); 11870b57cec5SDimitry Andric } 11880b57cec5SDimitry Andric } 11890b57cec5SDimitry Andric return EndLoc; 11900b57cec5SDimitry Andric } 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric Result = Actions.ActOnDecltypeExpression(Result.get()); 11930b57cec5SDimitry Andric } 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric // Match the ')' 11960b57cec5SDimitry Andric T.consumeClose(); 1197bdd1243dSDimitry Andric DS.setTypeArgumentRange(T.getRange()); 11980b57cec5SDimitry Andric if (T.getCloseLocation().isInvalid()) { 11990b57cec5SDimitry Andric DS.SetTypeSpecError(); 12000b57cec5SDimitry Andric // FIXME: this should return the location of the last token 12010b57cec5SDimitry Andric // that was consumed (by "consumeClose()") 12020b57cec5SDimitry Andric return T.getCloseLocation(); 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric if (Result.isInvalid()) { 12060b57cec5SDimitry Andric DS.SetTypeSpecError(); 12070b57cec5SDimitry Andric return T.getCloseLocation(); 12080b57cec5SDimitry Andric } 12090b57cec5SDimitry Andric 12100b57cec5SDimitry Andric EndLoc = T.getCloseLocation(); 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric assert(!Result.isInvalid()); 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric const char *PrevSpec = nullptr; 12150b57cec5SDimitry Andric unsigned DiagID; 12160b57cec5SDimitry Andric const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); 12170b57cec5SDimitry Andric // Check for duplicate type specifiers (e.g. "int decltype(a)"). 1218972a253aSDimitry Andric if (Result.get() ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, 1219972a253aSDimitry Andric PrevSpec, DiagID, Result.get(), Policy) 1220972a253aSDimitry Andric : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, 1221972a253aSDimitry Andric PrevSpec, DiagID, Policy)) { 12220b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec; 12230b57cec5SDimitry Andric DS.SetTypeSpecError(); 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric return EndLoc; 12260b57cec5SDimitry Andric } 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, 12290b57cec5SDimitry Andric SourceLocation StartLoc, 12300b57cec5SDimitry Andric SourceLocation EndLoc) { 12310b57cec5SDimitry Andric // make sure we have a token we can turn into an annotation token 1232e8d8bef9SDimitry Andric if (PP.isBacktrackEnabled()) { 12330b57cec5SDimitry Andric PP.RevertCachedTokens(1); 1234e8d8bef9SDimitry Andric if (DS.getTypeSpecType() == TST_error) { 1235e8d8bef9SDimitry Andric // We encountered an error in parsing 'decltype(...)' so lets annotate all 1236e8d8bef9SDimitry Andric // the tokens in the backtracking cache - that we likely had to skip over 1237e8d8bef9SDimitry Andric // to get to a token that allows us to resume parsing, such as a 1238e8d8bef9SDimitry Andric // semi-colon. 1239e8d8bef9SDimitry Andric EndLoc = PP.getLastCachedTokenLocation(); 1240e8d8bef9SDimitry Andric } 1241972a253aSDimitry Andric } else 12420b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric Tok.setKind(tok::annot_decltype); 12450b57cec5SDimitry Andric setExprAnnotation(Tok, 1246972a253aSDimitry Andric DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr() 1247972a253aSDimitry Andric : DS.getTypeSpecType() == TST_decltype_auto ? ExprResult() 1248972a253aSDimitry Andric : ExprError()); 12490b57cec5SDimitry Andric Tok.setAnnotationEndLoc(EndLoc); 12500b57cec5SDimitry Andric Tok.setLocation(StartLoc); 12510b57cec5SDimitry Andric PP.AnnotateCachedTokens(Tok); 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric 1254*0fca6ea1SDimitry Andric SourceLocation Parser::ParsePackIndexingType(DeclSpec &DS) { 1255*0fca6ea1SDimitry Andric assert(Tok.isOneOf(tok::annot_pack_indexing_type, tok::identifier) && 1256*0fca6ea1SDimitry Andric "Expected an identifier"); 1257*0fca6ea1SDimitry Andric 1258*0fca6ea1SDimitry Andric TypeResult Type; 1259*0fca6ea1SDimitry Andric SourceLocation StartLoc; 1260*0fca6ea1SDimitry Andric SourceLocation EllipsisLoc; 1261*0fca6ea1SDimitry Andric const char *PrevSpec; 1262*0fca6ea1SDimitry Andric unsigned DiagID; 1263*0fca6ea1SDimitry Andric const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); 1264*0fca6ea1SDimitry Andric 1265*0fca6ea1SDimitry Andric if (Tok.is(tok::annot_pack_indexing_type)) { 1266*0fca6ea1SDimitry Andric StartLoc = Tok.getLocation(); 1267*0fca6ea1SDimitry Andric SourceLocation EndLoc; 1268*0fca6ea1SDimitry Andric Type = getTypeAnnotation(Tok); 1269*0fca6ea1SDimitry Andric EndLoc = Tok.getAnnotationEndLoc(); 1270*0fca6ea1SDimitry Andric // Unfortunately, we don't know the LParen source location as the annotated 1271*0fca6ea1SDimitry Andric // token doesn't have it. 1272*0fca6ea1SDimitry Andric DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc)); 1273*0fca6ea1SDimitry Andric ConsumeAnnotationToken(); 1274*0fca6ea1SDimitry Andric if (Type.isInvalid()) { 1275*0fca6ea1SDimitry Andric DS.SetTypeSpecError(); 1276*0fca6ea1SDimitry Andric return EndLoc; 1277*0fca6ea1SDimitry Andric } 1278*0fca6ea1SDimitry Andric DS.SetTypeSpecType(DeclSpec::TST_typename_pack_indexing, StartLoc, PrevSpec, 1279*0fca6ea1SDimitry Andric DiagID, Type, Policy); 1280*0fca6ea1SDimitry Andric return EndLoc; 1281*0fca6ea1SDimitry Andric } 1282*0fca6ea1SDimitry Andric if (!NextToken().is(tok::ellipsis) || 1283*0fca6ea1SDimitry Andric !GetLookAheadToken(2).is(tok::l_square)) { 1284*0fca6ea1SDimitry Andric DS.SetTypeSpecError(); 1285*0fca6ea1SDimitry Andric return Tok.getEndLoc(); 1286*0fca6ea1SDimitry Andric } 1287*0fca6ea1SDimitry Andric 1288*0fca6ea1SDimitry Andric ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), 1289*0fca6ea1SDimitry Andric Tok.getLocation(), getCurScope()); 1290*0fca6ea1SDimitry Andric if (!Ty) { 1291*0fca6ea1SDimitry Andric DS.SetTypeSpecError(); 1292*0fca6ea1SDimitry Andric return Tok.getEndLoc(); 1293*0fca6ea1SDimitry Andric } 1294*0fca6ea1SDimitry Andric Type = Ty; 1295*0fca6ea1SDimitry Andric 1296*0fca6ea1SDimitry Andric StartLoc = ConsumeToken(); 1297*0fca6ea1SDimitry Andric EllipsisLoc = ConsumeToken(); 1298*0fca6ea1SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_square); 1299*0fca6ea1SDimitry Andric T.consumeOpen(); 1300*0fca6ea1SDimitry Andric ExprResult IndexExpr = ParseConstantExpression(); 1301*0fca6ea1SDimitry Andric T.consumeClose(); 1302*0fca6ea1SDimitry Andric 1303*0fca6ea1SDimitry Andric DS.SetRangeStart(StartLoc); 1304*0fca6ea1SDimitry Andric DS.SetRangeEnd(T.getCloseLocation()); 1305*0fca6ea1SDimitry Andric 1306*0fca6ea1SDimitry Andric if (!IndexExpr.isUsable()) { 1307*0fca6ea1SDimitry Andric ASTContext &C = Actions.getASTContext(); 1308*0fca6ea1SDimitry Andric IndexExpr = IntegerLiteral::Create(C, C.MakeIntValue(0, C.getSizeType()), 1309*0fca6ea1SDimitry Andric C.getSizeType(), SourceLocation()); 1310*0fca6ea1SDimitry Andric } 1311*0fca6ea1SDimitry Andric 1312*0fca6ea1SDimitry Andric DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, PrevSpec, DiagID, Type, 1313*0fca6ea1SDimitry Andric Policy); 1314*0fca6ea1SDimitry Andric DS.SetPackIndexingExpr(EllipsisLoc, IndexExpr.get()); 1315*0fca6ea1SDimitry Andric return T.getCloseLocation(); 1316*0fca6ea1SDimitry Andric } 1317*0fca6ea1SDimitry Andric 1318*0fca6ea1SDimitry Andric void Parser::AnnotateExistingIndexedTypeNamePack(ParsedType T, 1319*0fca6ea1SDimitry Andric SourceLocation StartLoc, 1320*0fca6ea1SDimitry Andric SourceLocation EndLoc) { 1321*0fca6ea1SDimitry Andric // make sure we have a token we can turn into an annotation token 1322*0fca6ea1SDimitry Andric if (PP.isBacktrackEnabled()) { 1323*0fca6ea1SDimitry Andric PP.RevertCachedTokens(1); 1324*0fca6ea1SDimitry Andric if (!T) { 1325*0fca6ea1SDimitry Andric // We encountered an error in parsing 'decltype(...)' so lets annotate all 1326*0fca6ea1SDimitry Andric // the tokens in the backtracking cache - that we likely had to skip over 1327*0fca6ea1SDimitry Andric // to get to a token that allows us to resume parsing, such as a 1328*0fca6ea1SDimitry Andric // semi-colon. 1329*0fca6ea1SDimitry Andric EndLoc = PP.getLastCachedTokenLocation(); 1330*0fca6ea1SDimitry Andric } 1331*0fca6ea1SDimitry Andric } else 1332*0fca6ea1SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 1333*0fca6ea1SDimitry Andric 1334*0fca6ea1SDimitry Andric Tok.setKind(tok::annot_pack_indexing_type); 1335*0fca6ea1SDimitry Andric setTypeAnnotation(Tok, T); 1336*0fca6ea1SDimitry Andric Tok.setAnnotationEndLoc(EndLoc); 1337*0fca6ea1SDimitry Andric Tok.setLocation(StartLoc); 1338*0fca6ea1SDimitry Andric PP.AnnotateCachedTokens(Tok); 1339*0fca6ea1SDimitry Andric } 1340*0fca6ea1SDimitry Andric 1341bdd1243dSDimitry Andric DeclSpec::TST Parser::TypeTransformTokToDeclSpec() { 1342bdd1243dSDimitry Andric switch (Tok.getKind()) { 1343bdd1243dSDimitry Andric #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ 1344bdd1243dSDimitry Andric case tok::kw___##Trait: \ 1345bdd1243dSDimitry Andric return DeclSpec::TST_##Trait; 1346bdd1243dSDimitry Andric #include "clang/Basic/TransformTypeTraits.def" 1347bdd1243dSDimitry Andric default: 1348bdd1243dSDimitry Andric llvm_unreachable("passed in an unhandled type transformation built-in"); 13490b57cec5SDimitry Andric } 1350bdd1243dSDimitry Andric } 1351bdd1243dSDimitry Andric 1352bdd1243dSDimitry Andric bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) { 1353bdd1243dSDimitry Andric if (!NextToken().is(tok::l_paren)) { 1354bdd1243dSDimitry Andric Tok.setKind(tok::identifier); 1355bdd1243dSDimitry Andric return false; 1356bdd1243dSDimitry Andric } 1357bdd1243dSDimitry Andric DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec(); 1358bdd1243dSDimitry Andric SourceLocation StartLoc = ConsumeToken(); 1359bdd1243dSDimitry Andric 1360bdd1243dSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 1361bdd1243dSDimitry Andric if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(), 1362bdd1243dSDimitry Andric tok::r_paren)) 1363bdd1243dSDimitry Andric return true; 13640b57cec5SDimitry Andric 13650b57cec5SDimitry Andric TypeResult Result = ParseTypeName(); 13660b57cec5SDimitry Andric if (Result.isInvalid()) { 13670b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 1368bdd1243dSDimitry Andric return true; 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric T.consumeClose(); 13720b57cec5SDimitry Andric if (T.getCloseLocation().isInvalid()) 1373bdd1243dSDimitry Andric return true; 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric const char *PrevSpec = nullptr; 13760b57cec5SDimitry Andric unsigned DiagID; 1377bdd1243dSDimitry Andric if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID, 1378bdd1243dSDimitry Andric Result.get(), 13790b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy())) 13800b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec; 1381bdd1243dSDimitry Andric DS.setTypeArgumentRange(T.getRange()); 1382bdd1243dSDimitry Andric return true; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric /// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a 13860b57cec5SDimitry Andric /// class name or decltype-specifier. Note that we only check that the result 13870b57cec5SDimitry Andric /// names a type; semantic analysis will need to verify that the type names a 13880b57cec5SDimitry Andric /// class. The result is either a type or null, depending on whether a type 13890b57cec5SDimitry Andric /// name was found. 13900b57cec5SDimitry Andric /// 13910b57cec5SDimitry Andric /// base-type-specifier: [C++11 class.derived] 13920b57cec5SDimitry Andric /// class-or-decltype 13930b57cec5SDimitry Andric /// class-or-decltype: [C++11 class.derived] 13940b57cec5SDimitry Andric /// nested-name-specifier[opt] class-name 13950b57cec5SDimitry Andric /// decltype-specifier 13960b57cec5SDimitry Andric /// class-name: [C++ class.name] 13970b57cec5SDimitry Andric /// identifier 13980b57cec5SDimitry Andric /// simple-template-id 13990b57cec5SDimitry Andric /// 14000b57cec5SDimitry Andric /// In C++98, instead of base-type-specifier, we have: 14010b57cec5SDimitry Andric /// 14020b57cec5SDimitry Andric /// ::[opt] nested-name-specifier[opt] class-name 14030b57cec5SDimitry Andric TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, 14040b57cec5SDimitry Andric SourceLocation &EndLocation) { 14050b57cec5SDimitry Andric // Ignore attempts to use typename 14060b57cec5SDimitry Andric if (Tok.is(tok::kw_typename)) { 14070b57cec5SDimitry Andric Diag(Tok, diag::err_expected_class_name_not_template) 14080b57cec5SDimitry Andric << FixItHint::CreateRemoval(Tok.getLocation()); 14090b57cec5SDimitry Andric ConsumeToken(); 14100b57cec5SDimitry Andric } 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric // Parse optional nested-name-specifier 14130b57cec5SDimitry Andric CXXScopeSpec SS; 14145ffd83dbSDimitry Andric if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 141504eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 14165ffd83dbSDimitry Andric /*EnteringContext=*/false)) 14170b57cec5SDimitry Andric return true; 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric BaseLoc = Tok.getLocation(); 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric // Parse decltype-specifier 14220b57cec5SDimitry Andric // tok == kw_decltype is just error recovery, it can only happen when SS 14230b57cec5SDimitry Andric // isn't empty 14240b57cec5SDimitry Andric if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) { 14250b57cec5SDimitry Andric if (SS.isNotEmpty()) 14260b57cec5SDimitry Andric Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype) 14270b57cec5SDimitry Andric << FixItHint::CreateRemoval(SS.getRange()); 14280b57cec5SDimitry Andric // Fake up a Declarator to use with ActOnTypeName. 14290b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric EndLocation = ParseDecltypeSpecifier(DS); 14320b57cec5SDimitry Andric 143381ad6265SDimitry Andric Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), 143481ad6265SDimitry Andric DeclaratorContext::TypeName); 14357a6dacacSDimitry Andric return Actions.ActOnTypeName(DeclaratorInfo); 14360b57cec5SDimitry Andric } 14370b57cec5SDimitry Andric 1438*0fca6ea1SDimitry Andric if (Tok.is(tok::annot_pack_indexing_type)) { 1439*0fca6ea1SDimitry Andric DeclSpec DS(AttrFactory); 1440*0fca6ea1SDimitry Andric ParsePackIndexingType(DS); 1441*0fca6ea1SDimitry Andric Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), 1442*0fca6ea1SDimitry Andric DeclaratorContext::TypeName); 1443*0fca6ea1SDimitry Andric return Actions.ActOnTypeName(DeclaratorInfo); 1444*0fca6ea1SDimitry Andric } 1445*0fca6ea1SDimitry Andric 14460b57cec5SDimitry Andric // Check whether we have a template-id that names a type. 1447*0fca6ea1SDimitry Andric // FIXME: identifier and annot_template_id handling in ParseUsingDeclaration 1448*0fca6ea1SDimitry Andric // work very similarly. It should be refactored into a separate function. 14490b57cec5SDimitry Andric if (Tok.is(tok::annot_template_id)) { 14500b57cec5SDimitry Andric TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); 14515ffd83dbSDimitry Andric if (TemplateId->mightBeType()) { 1452bdd1243dSDimitry Andric AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, 1453bdd1243dSDimitry Andric /*IsClassName=*/true); 14540b57cec5SDimitry Andric 14550b57cec5SDimitry Andric assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); 14565ffd83dbSDimitry Andric TypeResult Type = getTypeAnnotation(Tok); 14570b57cec5SDimitry Andric EndLocation = Tok.getAnnotationEndLoc(); 14580b57cec5SDimitry Andric ConsumeAnnotationToken(); 14590b57cec5SDimitry Andric return Type; 14600b57cec5SDimitry Andric } 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric // Fall through to produce an error below. 14630b57cec5SDimitry Andric } 14640b57cec5SDimitry Andric 14650b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) { 14660b57cec5SDimitry Andric Diag(Tok, diag::err_expected_class_name); 14670b57cec5SDimitry Andric return true; 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric IdentifierInfo *Id = Tok.getIdentifierInfo(); 14710b57cec5SDimitry Andric SourceLocation IdLoc = ConsumeToken(); 14720b57cec5SDimitry Andric 14730b57cec5SDimitry Andric if (Tok.is(tok::less)) { 14740b57cec5SDimitry Andric // It looks the user intended to write a template-id here, but the 14750b57cec5SDimitry Andric // template-name was wrong. Try to fix that. 14765ffd83dbSDimitry Andric // FIXME: Invoke ParseOptionalCXXScopeSpecifier in a "'template' is neither 14775ffd83dbSDimitry Andric // required nor permitted" mode, and do this there. 14785ffd83dbSDimitry Andric TemplateNameKind TNK = TNK_Non_template; 14790b57cec5SDimitry Andric TemplateTy Template; 1480972a253aSDimitry Andric if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), &SS, 1481972a253aSDimitry Andric Template, TNK)) { 1482972a253aSDimitry Andric Diag(IdLoc, diag::err_unknown_template_name) << Id; 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric // Form the template name 14860b57cec5SDimitry Andric UnqualifiedId TemplateName; 14870b57cec5SDimitry Andric TemplateName.setIdentifier(Id, IdLoc); 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric // Parse the full template-id, then turn it into a type. 14900b57cec5SDimitry Andric if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), 14910b57cec5SDimitry Andric TemplateName)) 14920b57cec5SDimitry Andric return true; 14935ffd83dbSDimitry Andric if (Tok.is(tok::annot_template_id) && 14945ffd83dbSDimitry Andric takeTemplateIdAnnotation(Tok)->mightBeType()) 1495bdd1243dSDimitry Andric AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, 1496bdd1243dSDimitry Andric /*IsClassName=*/true); 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric // If we didn't end up with a typename token, there's nothing more we 14990b57cec5SDimitry Andric // can do. 15000b57cec5SDimitry Andric if (Tok.isNot(tok::annot_typename)) 15010b57cec5SDimitry Andric return true; 15020b57cec5SDimitry Andric 15030b57cec5SDimitry Andric // Retrieve the type from the annotation token, consume that token, and 15040b57cec5SDimitry Andric // return. 15050b57cec5SDimitry Andric EndLocation = Tok.getAnnotationEndLoc(); 15065ffd83dbSDimitry Andric TypeResult Type = getTypeAnnotation(Tok); 15070b57cec5SDimitry Andric ConsumeAnnotationToken(); 15080b57cec5SDimitry Andric return Type; 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric // We have an identifier; check whether it is actually a type. 15120b57cec5SDimitry Andric IdentifierInfo *CorrectedII = nullptr; 15130b57cec5SDimitry Andric ParsedType Type = Actions.getTypeName( 15140b57cec5SDimitry Andric *Id, IdLoc, getCurScope(), &SS, /*isClassName=*/true, false, nullptr, 15150b57cec5SDimitry Andric /*IsCtorOrDtorName=*/false, 15160b57cec5SDimitry Andric /*WantNontrivialTypeSourceInfo=*/true, 1517bdd1243dSDimitry Andric /*IsClassTemplateDeductionContext=*/false, ImplicitTypenameContext::No, 1518bdd1243dSDimitry Andric &CorrectedII); 15190b57cec5SDimitry Andric if (!Type) { 15200b57cec5SDimitry Andric Diag(IdLoc, diag::err_expected_class_name); 15210b57cec5SDimitry Andric return true; 15220b57cec5SDimitry Andric } 15230b57cec5SDimitry Andric 15240b57cec5SDimitry Andric // Consume the identifier. 15250b57cec5SDimitry Andric EndLocation = IdLoc; 15260b57cec5SDimitry Andric 15270b57cec5SDimitry Andric // Fake up a Declarator to use with ActOnTypeName. 15280b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 15290b57cec5SDimitry Andric DS.SetRangeStart(IdLoc); 15300b57cec5SDimitry Andric DS.SetRangeEnd(EndLocation); 15310b57cec5SDimitry Andric DS.getTypeSpecScope() = SS; 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric const char *PrevSpec = nullptr; 15340b57cec5SDimitry Andric unsigned DiagID; 15350b57cec5SDimitry Andric DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type, 15360b57cec5SDimitry Andric Actions.getASTContext().getPrintingPolicy()); 15370b57cec5SDimitry Andric 153881ad6265SDimitry Andric Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), 153981ad6265SDimitry Andric DeclaratorContext::TypeName); 15407a6dacacSDimitry Andric return Actions.ActOnTypeName(DeclaratorInfo); 15410b57cec5SDimitry Andric } 15420b57cec5SDimitry Andric 15430b57cec5SDimitry Andric void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { 15440b57cec5SDimitry Andric while (Tok.isOneOf(tok::kw___single_inheritance, 15450b57cec5SDimitry Andric tok::kw___multiple_inheritance, 15460b57cec5SDimitry Andric tok::kw___virtual_inheritance)) { 15470b57cec5SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo(); 154806c3fb27SDimitry Andric auto Kind = Tok.getKind(); 15490b57cec5SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken(); 155006c3fb27SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); 15510b57cec5SDimitry Andric } 15520b57cec5SDimitry Andric } 15530b57cec5SDimitry Andric 1554*0fca6ea1SDimitry Andric void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) { 1555*0fca6ea1SDimitry Andric while (Tok.is(tok::kw__Nullable)) { 1556*0fca6ea1SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo(); 1557*0fca6ea1SDimitry Andric auto Kind = Tok.getKind(); 1558*0fca6ea1SDimitry Andric SourceLocation AttrNameLoc = ConsumeToken(); 1559*0fca6ea1SDimitry Andric attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); 1560*0fca6ea1SDimitry Andric } 1561*0fca6ea1SDimitry Andric } 1562*0fca6ea1SDimitry Andric 15630b57cec5SDimitry Andric /// Determine whether the following tokens are valid after a type-specifier 15640b57cec5SDimitry Andric /// which could be a standalone declaration. This will conservatively return 15650b57cec5SDimitry Andric /// true if there's any doubt, and is appropriate for insert-';' fixits. 15660b57cec5SDimitry Andric bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { 15670b57cec5SDimitry Andric // This switch enumerates the valid "follow" set for type-specifiers. 15680b57cec5SDimitry Andric switch (Tok.getKind()) { 1569972a253aSDimitry Andric default: 157006c3fb27SDimitry Andric if (Tok.isRegularKeywordAttribute()) 157106c3fb27SDimitry Andric return true; 1572972a253aSDimitry Andric break; 15730b57cec5SDimitry Andric case tok::semi: // struct foo {...} ; 15740b57cec5SDimitry Andric case tok::star: // struct foo {...} * P; 15750b57cec5SDimitry Andric case tok::amp: // struct foo {...} & R = ... 15760b57cec5SDimitry Andric case tok::ampamp: // struct foo {...} && R = ... 15770b57cec5SDimitry Andric case tok::identifier: // struct foo {...} V ; 15780b57cec5SDimitry Andric case tok::r_paren: //(struct foo {...} ) {4} 15790b57cec5SDimitry Andric case tok::coloncolon: // struct foo {...} :: a::b; 15800b57cec5SDimitry Andric case tok::annot_cxxscope: // struct foo {...} a:: b; 15810b57cec5SDimitry Andric case tok::annot_typename: // struct foo {...} a ::b; 15820b57cec5SDimitry Andric case tok::annot_template_id: // struct foo {...} a<int> ::b; 15830b57cec5SDimitry Andric case tok::kw_decltype: // struct foo {...} decltype (a)::b; 15840b57cec5SDimitry Andric case tok::l_paren: // struct foo {...} ( x); 15850b57cec5SDimitry Andric case tok::comma: // __builtin_offsetof(struct foo{...} , 15860b57cec5SDimitry Andric case tok::kw_operator: // struct foo operator ++() {...} 15870b57cec5SDimitry Andric case tok::kw___declspec: // struct foo {...} __declspec(...) 15880b57cec5SDimitry Andric case tok::l_square: // void f(struct f [ 3]) 15890b57cec5SDimitry Andric case tok::ellipsis: // void f(struct f ... [Ns]) 15900b57cec5SDimitry Andric // FIXME: we should emit semantic diagnostic when declaration 15910b57cec5SDimitry Andric // attribute is in type attribute position. 15920b57cec5SDimitry Andric case tok::kw___attribute: // struct foo __attribute__((used)) x; 15930b57cec5SDimitry Andric case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop)); 15940b57cec5SDimitry Andric // struct foo {...} _Pragma(section(...)); 15950b57cec5SDimitry Andric case tok::annot_pragma_ms_pragma: 15960b57cec5SDimitry Andric // struct foo {...} _Pragma(vtordisp(pop)); 15970b57cec5SDimitry Andric case tok::annot_pragma_ms_vtordisp: 15980b57cec5SDimitry Andric // struct foo {...} _Pragma(pointers_to_members(...)); 15990b57cec5SDimitry Andric case tok::annot_pragma_ms_pointers_to_members: 16000b57cec5SDimitry Andric return true; 16010b57cec5SDimitry Andric case tok::colon: 16025ffd83dbSDimitry Andric return CouldBeBitfield || // enum E { ... } : 2; 16035ffd83dbSDimitry Andric ColonIsSacred; // _Generic(..., enum E : 2); 16040b57cec5SDimitry Andric // Microsoft compatibility 16050b57cec5SDimitry Andric case tok::kw___cdecl: // struct foo {...} __cdecl x; 16060b57cec5SDimitry Andric case tok::kw___fastcall: // struct foo {...} __fastcall x; 16070b57cec5SDimitry Andric case tok::kw___stdcall: // struct foo {...} __stdcall x; 16080b57cec5SDimitry Andric case tok::kw___thiscall: // struct foo {...} __thiscall x; 16090b57cec5SDimitry Andric case tok::kw___vectorcall: // struct foo {...} __vectorcall x; 16100b57cec5SDimitry Andric // We will diagnose these calling-convention specifiers on non-function 16110b57cec5SDimitry Andric // declarations later, so claim they are valid after a type specifier. 16120b57cec5SDimitry Andric return getLangOpts().MicrosoftExt; 16130b57cec5SDimitry Andric // Type qualifiers 16140b57cec5SDimitry Andric case tok::kw_const: // struct foo {...} const x; 16150b57cec5SDimitry Andric case tok::kw_volatile: // struct foo {...} volatile x; 16160b57cec5SDimitry Andric case tok::kw_restrict: // struct foo {...} restrict x; 16170b57cec5SDimitry Andric case tok::kw__Atomic: // struct foo {...} _Atomic x; 16180b57cec5SDimitry Andric case tok::kw___unaligned: // struct foo {...} __unaligned *x; 16190b57cec5SDimitry Andric // Function specifiers 16200b57cec5SDimitry Andric // Note, no 'explicit'. An explicit function must be either a conversion 16210b57cec5SDimitry Andric // operator or a constructor. Either way, it can't have a return type. 16220b57cec5SDimitry Andric case tok::kw_inline: // struct foo inline f(); 16230b57cec5SDimitry Andric case tok::kw_virtual: // struct foo virtual f(); 16240b57cec5SDimitry Andric case tok::kw_friend: // struct foo friend f(); 16250b57cec5SDimitry Andric // Storage-class specifiers 16260b57cec5SDimitry Andric case tok::kw_static: // struct foo {...} static x; 16270b57cec5SDimitry Andric case tok::kw_extern: // struct foo {...} extern x; 16280b57cec5SDimitry Andric case tok::kw_typedef: // struct foo {...} typedef x; 16290b57cec5SDimitry Andric case tok::kw_register: // struct foo {...} register x; 16300b57cec5SDimitry Andric case tok::kw_auto: // struct foo {...} auto x; 16310b57cec5SDimitry Andric case tok::kw_mutable: // struct foo {...} mutable x; 16320b57cec5SDimitry Andric case tok::kw_thread_local: // struct foo {...} thread_local x; 16330b57cec5SDimitry Andric case tok::kw_constexpr: // struct foo {...} constexpr x; 1634a7dea167SDimitry Andric case tok::kw_consteval: // struct foo {...} consteval x; 1635a7dea167SDimitry Andric case tok::kw_constinit: // struct foo {...} constinit x; 16360b57cec5SDimitry Andric // As shown above, type qualifiers and storage class specifiers absolutely 16370b57cec5SDimitry Andric // can occur after class specifiers according to the grammar. However, 16380b57cec5SDimitry Andric // almost no one actually writes code like this. If we see one of these, 16390b57cec5SDimitry Andric // it is much more likely that someone missed a semi colon and the 16400b57cec5SDimitry Andric // type/storage class specifier we're seeing is part of the *next* 16410b57cec5SDimitry Andric // intended declaration, as in: 16420b57cec5SDimitry Andric // 16430b57cec5SDimitry Andric // struct foo { ... } 16440b57cec5SDimitry Andric // typedef int X; 16450b57cec5SDimitry Andric // 16460b57cec5SDimitry Andric // We'd really like to emit a missing semicolon error instead of emitting 16470b57cec5SDimitry Andric // an error on the 'int' saying that you can't have two type specifiers in 16480b57cec5SDimitry Andric // the same declaration of X. Because of this, we look ahead past this 16490b57cec5SDimitry Andric // token to see if it's a type specifier. If so, we know the code is 16500b57cec5SDimitry Andric // otherwise invalid, so we can produce the expected semi error. 16510b57cec5SDimitry Andric if (!isKnownToBeTypeSpecifier(NextToken())) 16520b57cec5SDimitry Andric return true; 16530b57cec5SDimitry Andric break; 16540b57cec5SDimitry Andric case tok::r_brace: // struct bar { struct foo {...} } 16550b57cec5SDimitry Andric // Missing ';' at end of struct is accepted as an extension in C mode. 16560b57cec5SDimitry Andric if (!getLangOpts().CPlusPlus) 16570b57cec5SDimitry Andric return true; 16580b57cec5SDimitry Andric break; 16590b57cec5SDimitry Andric case tok::greater: 16600b57cec5SDimitry Andric // template<class T = class X> 16610b57cec5SDimitry Andric return getLangOpts().CPlusPlus; 16620b57cec5SDimitry Andric } 16630b57cec5SDimitry Andric return false; 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric /// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or 16670b57cec5SDimitry Andric /// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which 16680b57cec5SDimitry Andric /// until we reach the start of a definition or see a token that 16690b57cec5SDimitry Andric /// cannot start a definition. 16700b57cec5SDimitry Andric /// 16710b57cec5SDimitry Andric /// class-specifier: [C++ class] 16720b57cec5SDimitry Andric /// class-head '{' member-specification[opt] '}' 16730b57cec5SDimitry Andric /// class-head '{' member-specification[opt] '}' attributes[opt] 16740b57cec5SDimitry Andric /// class-head: 16750b57cec5SDimitry Andric /// class-key identifier[opt] base-clause[opt] 16760b57cec5SDimitry Andric /// class-key nested-name-specifier identifier base-clause[opt] 16770b57cec5SDimitry Andric /// class-key nested-name-specifier[opt] simple-template-id 16780b57cec5SDimitry Andric /// base-clause[opt] 16790b57cec5SDimitry Andric /// [GNU] class-key attributes[opt] identifier[opt] base-clause[opt] 16800b57cec5SDimitry Andric /// [GNU] class-key attributes[opt] nested-name-specifier 16810b57cec5SDimitry Andric /// identifier base-clause[opt] 16820b57cec5SDimitry Andric /// [GNU] class-key attributes[opt] nested-name-specifier[opt] 16830b57cec5SDimitry Andric /// simple-template-id base-clause[opt] 16840b57cec5SDimitry Andric /// class-key: 16850b57cec5SDimitry Andric /// 'class' 16860b57cec5SDimitry Andric /// 'struct' 16870b57cec5SDimitry Andric /// 'union' 16880b57cec5SDimitry Andric /// 16890b57cec5SDimitry Andric /// elaborated-type-specifier: [C++ dcl.type.elab] 16900b57cec5SDimitry Andric /// class-key ::[opt] nested-name-specifier[opt] identifier 16910b57cec5SDimitry Andric /// class-key ::[opt] nested-name-specifier[opt] 'template'[opt] 16920b57cec5SDimitry Andric /// simple-template-id 16930b57cec5SDimitry Andric /// 16940b57cec5SDimitry Andric /// Note that the C++ class-specifier and elaborated-type-specifier, 16950b57cec5SDimitry Andric /// together, subsume the C99 struct-or-union-specifier: 16960b57cec5SDimitry Andric /// 16970b57cec5SDimitry Andric /// struct-or-union-specifier: [C99 6.7.2.1] 16980b57cec5SDimitry Andric /// struct-or-union identifier[opt] '{' struct-contents '}' 16990b57cec5SDimitry Andric /// struct-or-union identifier 17000b57cec5SDimitry Andric /// [GNU] struct-or-union attributes[opt] identifier[opt] '{' struct-contents 17010b57cec5SDimitry Andric /// '}' attributes[opt] 17020b57cec5SDimitry Andric /// [GNU] struct-or-union attributes[opt] identifier 17030b57cec5SDimitry Andric /// struct-or-union: 17040b57cec5SDimitry Andric /// 'struct' 17050b57cec5SDimitry Andric /// 'union' 17060b57cec5SDimitry Andric void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, 17070b57cec5SDimitry Andric SourceLocation StartLoc, DeclSpec &DS, 1708*0fca6ea1SDimitry Andric ParsedTemplateInfo &TemplateInfo, 170981ad6265SDimitry Andric AccessSpecifier AS, bool EnteringContext, 171081ad6265SDimitry Andric DeclSpecContext DSC, 171181ad6265SDimitry Andric ParsedAttributes &Attributes) { 17120b57cec5SDimitry Andric DeclSpec::TST TagType; 17130b57cec5SDimitry Andric if (TagTokKind == tok::kw_struct) 17140b57cec5SDimitry Andric TagType = DeclSpec::TST_struct; 17150b57cec5SDimitry Andric else if (TagTokKind == tok::kw___interface) 17160b57cec5SDimitry Andric TagType = DeclSpec::TST_interface; 17170b57cec5SDimitry Andric else if (TagTokKind == tok::kw_class) 17180b57cec5SDimitry Andric TagType = DeclSpec::TST_class; 17190b57cec5SDimitry Andric else { 17200b57cec5SDimitry Andric assert(TagTokKind == tok::kw_union && "Not a class specifier"); 17210b57cec5SDimitry Andric TagType = DeclSpec::TST_union; 17220b57cec5SDimitry Andric } 17230b57cec5SDimitry Andric 17240b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 17250b57cec5SDimitry Andric // Code completion for a struct, class, or union name. 1726fe6060f1SDimitry Andric cutOffParsing(); 1727*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteTag(getCurScope(), TagType); 1728fe6060f1SDimitry Andric return; 17290b57cec5SDimitry Andric } 17300b57cec5SDimitry Andric 1731349cc55cSDimitry Andric // C++20 [temp.class.spec] 13.7.5/10 1732349cc55cSDimitry Andric // The usual access checking rules do not apply to non-dependent names 1733349cc55cSDimitry Andric // used to specify template arguments of the simple-template-id of the 1734349cc55cSDimitry Andric // partial specialization. 1735349cc55cSDimitry Andric // C++20 [temp.spec] 13.9/6: 1736349cc55cSDimitry Andric // The usual access checking rules do not apply to names in a declaration 1737349cc55cSDimitry Andric // of an explicit instantiation or explicit specialization... 1738349cc55cSDimitry Andric const bool shouldDelayDiagsInTag = 1739349cc55cSDimitry Andric (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate); 17400b57cec5SDimitry Andric SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); 17410b57cec5SDimitry Andric 174281ad6265SDimitry Andric ParsedAttributes attrs(AttrFactory); 17430b57cec5SDimitry Andric // If attributes exist after tag, parse them. 1744*0fca6ea1SDimitry Andric for (;;) { 1745fe6060f1SDimitry Andric MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); 17460b57cec5SDimitry Andric // Parse inheritance specifiers. 1747*0fca6ea1SDimitry Andric if (Tok.isOneOf(tok::kw___single_inheritance, 1748*0fca6ea1SDimitry Andric tok::kw___multiple_inheritance, 1749*0fca6ea1SDimitry Andric tok::kw___virtual_inheritance)) { 17500b57cec5SDimitry Andric ParseMicrosoftInheritanceClassAttributes(attrs); 1751*0fca6ea1SDimitry Andric continue; 1752*0fca6ea1SDimitry Andric } 1753*0fca6ea1SDimitry Andric if (Tok.is(tok::kw__Nullable)) { 1754*0fca6ea1SDimitry Andric ParseNullabilityClassAttributes(attrs); 1755*0fca6ea1SDimitry Andric continue; 1756*0fca6ea1SDimitry Andric } 1757*0fca6ea1SDimitry Andric break; 1758*0fca6ea1SDimitry Andric } 17590b57cec5SDimitry Andric 17600b57cec5SDimitry Andric // Source location used by FIXIT to insert misplaced 17610b57cec5SDimitry Andric // C++11 attributes 17620b57cec5SDimitry Andric SourceLocation AttrFixitLoc = Tok.getLocation(); 17630b57cec5SDimitry Andric 1764972a253aSDimitry Andric if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) && 1765972a253aSDimitry Andric !Tok.isAnnotation() && Tok.getIdentifierInfo() && 1766972a253aSDimitry Andric Tok.isOneOf( 1767bdd1243dSDimitry Andric #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, 1768bdd1243dSDimitry Andric #include "clang/Basic/TransformTypeTraits.def" 1769bdd1243dSDimitry Andric tok::kw___is_abstract, 1770bdd1243dSDimitry Andric tok::kw___is_aggregate, 1771bdd1243dSDimitry Andric tok::kw___is_arithmetic, 1772bdd1243dSDimitry Andric tok::kw___is_array, 1773bdd1243dSDimitry Andric tok::kw___is_assignable, 1774bdd1243dSDimitry Andric tok::kw___is_base_of, 1775bdd1243dSDimitry Andric tok::kw___is_bounded_array, 1776bdd1243dSDimitry Andric tok::kw___is_class, 1777bdd1243dSDimitry Andric tok::kw___is_complete_type, 1778bdd1243dSDimitry Andric tok::kw___is_compound, 1779bdd1243dSDimitry Andric tok::kw___is_const, 1780bdd1243dSDimitry Andric tok::kw___is_constructible, 1781bdd1243dSDimitry Andric tok::kw___is_convertible, 1782bdd1243dSDimitry Andric tok::kw___is_convertible_to, 1783bdd1243dSDimitry Andric tok::kw___is_destructible, 1784bdd1243dSDimitry Andric tok::kw___is_empty, 1785bdd1243dSDimitry Andric tok::kw___is_enum, 1786bdd1243dSDimitry Andric tok::kw___is_floating_point, 1787bdd1243dSDimitry Andric tok::kw___is_final, 1788bdd1243dSDimitry Andric tok::kw___is_function, 1789bdd1243dSDimitry Andric tok::kw___is_fundamental, 1790bdd1243dSDimitry Andric tok::kw___is_integral, 1791bdd1243dSDimitry Andric tok::kw___is_interface_class, 1792bdd1243dSDimitry Andric tok::kw___is_literal, 1793bdd1243dSDimitry Andric tok::kw___is_lvalue_expr, 1794bdd1243dSDimitry Andric tok::kw___is_lvalue_reference, 1795bdd1243dSDimitry Andric tok::kw___is_member_function_pointer, 1796bdd1243dSDimitry Andric tok::kw___is_member_object_pointer, 1797bdd1243dSDimitry Andric tok::kw___is_member_pointer, 1798bdd1243dSDimitry Andric tok::kw___is_nothrow_assignable, 1799bdd1243dSDimitry Andric tok::kw___is_nothrow_constructible, 1800*0fca6ea1SDimitry Andric tok::kw___is_nothrow_convertible, 1801bdd1243dSDimitry Andric tok::kw___is_nothrow_destructible, 1802bdd1243dSDimitry Andric tok::kw___is_nullptr, 1803bdd1243dSDimitry Andric tok::kw___is_object, 1804bdd1243dSDimitry Andric tok::kw___is_pod, 1805bdd1243dSDimitry Andric tok::kw___is_pointer, 1806bdd1243dSDimitry Andric tok::kw___is_polymorphic, 1807bdd1243dSDimitry Andric tok::kw___is_reference, 1808bdd1243dSDimitry Andric tok::kw___is_referenceable, 1809bdd1243dSDimitry Andric tok::kw___is_rvalue_expr, 1810bdd1243dSDimitry Andric tok::kw___is_rvalue_reference, 1811bdd1243dSDimitry Andric tok::kw___is_same, 1812bdd1243dSDimitry Andric tok::kw___is_scalar, 1813bdd1243dSDimitry Andric tok::kw___is_scoped_enum, 1814bdd1243dSDimitry Andric tok::kw___is_sealed, 1815bdd1243dSDimitry Andric tok::kw___is_signed, 1816bdd1243dSDimitry Andric tok::kw___is_standard_layout, 1817bdd1243dSDimitry Andric tok::kw___is_trivial, 181806c3fb27SDimitry Andric tok::kw___is_trivially_equality_comparable, 18190b57cec5SDimitry Andric tok::kw___is_trivially_assignable, 1820bdd1243dSDimitry Andric tok::kw___is_trivially_constructible, 1821bdd1243dSDimitry Andric tok::kw___is_trivially_copyable, 1822bdd1243dSDimitry Andric tok::kw___is_unbounded_array, 1823bdd1243dSDimitry Andric tok::kw___is_union, 1824bdd1243dSDimitry Andric tok::kw___is_unsigned, 1825bdd1243dSDimitry Andric tok::kw___is_void, 1826*0fca6ea1SDimitry Andric tok::kw___is_volatile 1827*0fca6ea1SDimitry Andric )) 18280b57cec5SDimitry Andric // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the 18290b57cec5SDimitry Andric // name of struct templates, but some are keywords in GCC >= 4.3 18300b57cec5SDimitry Andric // and Clang. Therefore, when we see the token sequence "struct 18310b57cec5SDimitry Andric // X", make X into a normal identifier rather than a keyword, to 18320b57cec5SDimitry Andric // allow libstdc++ 4.2 and libc++ to work properly. 18330b57cec5SDimitry Andric TryKeywordIdentFallback(true); 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric struct PreserveAtomicIdentifierInfoRAII { 18360b57cec5SDimitry Andric PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled) 18370b57cec5SDimitry Andric : AtomicII(nullptr) { 18380b57cec5SDimitry Andric if (!Enabled) 18390b57cec5SDimitry Andric return; 18400b57cec5SDimitry Andric assert(Tok.is(tok::kw__Atomic)); 18410b57cec5SDimitry Andric AtomicII = Tok.getIdentifierInfo(); 18420b57cec5SDimitry Andric AtomicII->revertTokenIDToIdentifier(); 18430b57cec5SDimitry Andric Tok.setKind(tok::identifier); 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric ~PreserveAtomicIdentifierInfoRAII() { 18460b57cec5SDimitry Andric if (!AtomicII) 18470b57cec5SDimitry Andric return; 18480b57cec5SDimitry Andric AtomicII->revertIdentifierToTokenID(tok::kw__Atomic); 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric IdentifierInfo *AtomicII; 18510b57cec5SDimitry Andric }; 18520b57cec5SDimitry Andric 18530b57cec5SDimitry Andric // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL 18540b57cec5SDimitry Andric // implementation for VS2013 uses _Atomic as an identifier for one of the 18550b57cec5SDimitry Andric // classes in <atomic>. When we are parsing 'struct _Atomic', don't consider 18560b57cec5SDimitry Andric // '_Atomic' to be a keyword. We are careful to undo this so that clang can 18570b57cec5SDimitry Andric // use '_Atomic' in its own header files. 18580b57cec5SDimitry Andric bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat && 18590b57cec5SDimitry Andric Tok.is(tok::kw__Atomic) && 18600b57cec5SDimitry Andric TagType == DeclSpec::TST_struct; 18610b57cec5SDimitry Andric PreserveAtomicIdentifierInfoRAII AtomicTokenGuard( 18620b57cec5SDimitry Andric Tok, ShouldChangeAtomicToIdentifier); 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric // Parse the (optional) nested-name-specifier. 18650b57cec5SDimitry Andric CXXScopeSpec &SS = DS.getTypeSpecScope(); 18660b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) { 18670b57cec5SDimitry Andric // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it 18680b57cec5SDimitry Andric // is a base-specifier-list. 18690b57cec5SDimitry Andric ColonProtectionRAIIObject X(*this); 18700b57cec5SDimitry Andric 18710b57cec5SDimitry Andric CXXScopeSpec Spec; 187206c3fb27SDimitry Andric if (TemplateInfo.TemplateParams) 187306c3fb27SDimitry Andric Spec.setTemplateParamLists(*TemplateInfo.TemplateParams); 187406c3fb27SDimitry Andric 18750b57cec5SDimitry Andric bool HasValidSpec = true; 18765ffd83dbSDimitry Andric if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr, 187704eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 18785ffd83dbSDimitry Andric EnteringContext)) { 18790b57cec5SDimitry Andric DS.SetTypeSpecError(); 18800b57cec5SDimitry Andric HasValidSpec = false; 18810b57cec5SDimitry Andric } 18820b57cec5SDimitry Andric if (Spec.isSet()) 18830b57cec5SDimitry Andric if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) { 18840b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; 18850b57cec5SDimitry Andric HasValidSpec = false; 18860b57cec5SDimitry Andric } 18870b57cec5SDimitry Andric if (HasValidSpec) 18880b57cec5SDimitry Andric SS = Spec; 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; 18920b57cec5SDimitry Andric 18930b57cec5SDimitry Andric auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name, 18940b57cec5SDimitry Andric SourceLocation NameLoc, 18950b57cec5SDimitry Andric SourceRange TemplateArgRange, 18960b57cec5SDimitry Andric bool KnownUndeclared) { 18970b57cec5SDimitry Andric Diag(NameLoc, diag::err_explicit_spec_non_template) 18980b57cec5SDimitry Andric << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) 18990b57cec5SDimitry Andric << TagTokKind << Name << TemplateArgRange << KnownUndeclared; 19000b57cec5SDimitry Andric 19010b57cec5SDimitry Andric // Strip off the last template parameter list if it was empty, since 19020b57cec5SDimitry Andric // we've removed its template argument list. 19030b57cec5SDimitry Andric if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) { 19040b57cec5SDimitry Andric if (TemplateParams->size() > 1) { 19050b57cec5SDimitry Andric TemplateParams->pop_back(); 19060b57cec5SDimitry Andric } else { 19070b57cec5SDimitry Andric TemplateParams = nullptr; 1908*0fca6ea1SDimitry Andric TemplateInfo.Kind = ParsedTemplateInfo::NonTemplate; 19090b57cec5SDimitry Andric } 19100b57cec5SDimitry Andric } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { 19110b57cec5SDimitry Andric // Pretend this is just a forward declaration. 19120b57cec5SDimitry Andric TemplateParams = nullptr; 1913*0fca6ea1SDimitry Andric TemplateInfo.Kind = ParsedTemplateInfo::NonTemplate; 1914*0fca6ea1SDimitry Andric TemplateInfo.TemplateLoc = SourceLocation(); 1915*0fca6ea1SDimitry Andric TemplateInfo.ExternLoc = SourceLocation(); 19160b57cec5SDimitry Andric } 19170b57cec5SDimitry Andric }; 19180b57cec5SDimitry Andric 19190b57cec5SDimitry Andric // Parse the (optional) class name or simple-template-id. 19200b57cec5SDimitry Andric IdentifierInfo *Name = nullptr; 19210b57cec5SDimitry Andric SourceLocation NameLoc; 19220b57cec5SDimitry Andric TemplateIdAnnotation *TemplateId = nullptr; 19230b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 19240b57cec5SDimitry Andric Name = Tok.getIdentifierInfo(); 19250b57cec5SDimitry Andric NameLoc = ConsumeToken(); 1926*0fca6ea1SDimitry Andric DS.SetRangeEnd(NameLoc); 19270b57cec5SDimitry Andric 19280b57cec5SDimitry Andric if (Tok.is(tok::less) && getLangOpts().CPlusPlus) { 19290b57cec5SDimitry Andric // The name was supposed to refer to a template, but didn't. 19300b57cec5SDimitry Andric // Eat the template argument list and try to continue parsing this as 19310b57cec5SDimitry Andric // a class (or template thereof). 19320b57cec5SDimitry Andric TemplateArgList TemplateArgs; 19330b57cec5SDimitry Andric SourceLocation LAngleLoc, RAngleLoc; 19340b57cec5SDimitry Andric if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, 19350b57cec5SDimitry Andric RAngleLoc)) { 19360b57cec5SDimitry Andric // We couldn't parse the template argument list at all, so don't 19370b57cec5SDimitry Andric // try to give any location information for the list. 19380b57cec5SDimitry Andric LAngleLoc = RAngleLoc = SourceLocation(); 19390b57cec5SDimitry Andric } 19400b57cec5SDimitry Andric RecoverFromUndeclaredTemplateName( 19410b57cec5SDimitry Andric Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false); 19420b57cec5SDimitry Andric } 19430b57cec5SDimitry Andric } else if (Tok.is(tok::annot_template_id)) { 19440b57cec5SDimitry Andric TemplateId = takeTemplateIdAnnotation(Tok); 19450b57cec5SDimitry Andric NameLoc = ConsumeAnnotationToken(); 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric if (TemplateId->Kind == TNK_Undeclared_template) { 19485ffd83dbSDimitry Andric // Try to resolve the template name to a type template. May update Kind. 19495ffd83dbSDimitry Andric Actions.ActOnUndeclaredTypeTemplateName( 19505ffd83dbSDimitry Andric getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name); 19510b57cec5SDimitry Andric if (TemplateId->Kind == TNK_Undeclared_template) { 19520b57cec5SDimitry Andric RecoverFromUndeclaredTemplateName( 19530b57cec5SDimitry Andric Name, NameLoc, 19540b57cec5SDimitry Andric SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true); 19550b57cec5SDimitry Andric TemplateId = nullptr; 19560b57cec5SDimitry Andric } 19570b57cec5SDimitry Andric } 19580b57cec5SDimitry Andric 19595ffd83dbSDimitry Andric if (TemplateId && !TemplateId->mightBeType()) { 19600b57cec5SDimitry Andric // The template-name in the simple-template-id refers to 19615ffd83dbSDimitry Andric // something other than a type template. Give an appropriate 19620b57cec5SDimitry Andric // error message and skip to the ';'. 19630b57cec5SDimitry Andric SourceRange Range(NameLoc); 19640b57cec5SDimitry Andric if (SS.isNotEmpty()) 19650b57cec5SDimitry Andric Range.setBegin(SS.getBeginLoc()); 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric // FIXME: Name may be null here. 19680b57cec5SDimitry Andric Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template) 19690b57cec5SDimitry Andric << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range; 19700b57cec5SDimitry Andric 19710b57cec5SDimitry Andric DS.SetTypeSpecError(); 19720b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch); 19730b57cec5SDimitry Andric return; 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 19770b57cec5SDimitry Andric // There are four options here. 19780b57cec5SDimitry Andric // - If we are in a trailing return type, this is always just a reference, 19790b57cec5SDimitry Andric // and we must not try to parse a definition. For instance, 19800b57cec5SDimitry Andric // [] () -> struct S { }; 19810b57cec5SDimitry Andric // does not define a type. 19820b57cec5SDimitry Andric // - If we have 'struct foo {...', 'struct foo :...', 19830b57cec5SDimitry Andric // 'struct foo final :' or 'struct foo final {', then this is a definition. 19840b57cec5SDimitry Andric // - If we have 'struct foo;', then this is either a forward declaration 19850b57cec5SDimitry Andric // or a friend declaration, which have to be treated differently. 19860b57cec5SDimitry Andric // - Otherwise we have something like 'struct foo xyz', a reference. 19870b57cec5SDimitry Andric // 19880b57cec5SDimitry Andric // We also detect these erroneous cases to provide better diagnostic for 19890b57cec5SDimitry Andric // C++11 attributes parsing. 19900b57cec5SDimitry Andric // - attributes follow class name: 19910b57cec5SDimitry Andric // struct foo [[]] {}; 19920b57cec5SDimitry Andric // - attributes appear before or after 'final': 19930b57cec5SDimitry Andric // struct foo [[]] final [[]] {}; 19940b57cec5SDimitry Andric // 19950b57cec5SDimitry Andric // However, in type-specifier-seq's, things look like declarations but are 19960b57cec5SDimitry Andric // just references, e.g. 19970b57cec5SDimitry Andric // new struct s; 19980b57cec5SDimitry Andric // or 19990b57cec5SDimitry Andric // &T::operator struct s; 20000b57cec5SDimitry Andric // For these, DSC is DeclSpecContext::DSC_type_specifier or 20010b57cec5SDimitry Andric // DeclSpecContext::DSC_alias_declaration. 20020b57cec5SDimitry Andric 20030b57cec5SDimitry Andric // If there are attributes after class name, parse them. 20040b57cec5SDimitry Andric MaybeParseCXX11Attributes(Attributes); 20050b57cec5SDimitry Andric 20060b57cec5SDimitry Andric const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); 2007*0fca6ea1SDimitry Andric TagUseKind TUK; 200881ad6265SDimitry Andric if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) == 200981ad6265SDimitry Andric AllowDefiningTypeSpec::No || 20105ffd83dbSDimitry Andric (getLangOpts().OpenMP && OpenMPDirectiveParsing)) 2011*0fca6ea1SDimitry Andric TUK = TagUseKind::Reference; 20120b57cec5SDimitry Andric else if (Tok.is(tok::l_brace) || 201381ad6265SDimitry Andric (DSC != DeclSpecContext::DSC_association && 201481ad6265SDimitry Andric getLangOpts().CPlusPlus && Tok.is(tok::colon)) || 2015fe6060f1SDimitry Andric (isClassCompatibleKeyword() && 20160b57cec5SDimitry Andric (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) { 20170b57cec5SDimitry Andric if (DS.isFriendSpecified()) { 20180b57cec5SDimitry Andric // C++ [class.friend]p2: 20190b57cec5SDimitry Andric // A class shall not be defined in a friend declaration. 20200b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_friend_decl_defines_type) 20210b57cec5SDimitry Andric << SourceRange(DS.getFriendSpecLoc()); 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric // Skip everything up to the semicolon, so that this looks like a proper 20240b57cec5SDimitry Andric // friend class (or template thereof) declaration. 20250b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch); 2026*0fca6ea1SDimitry Andric TUK = TagUseKind::Friend; 20270b57cec5SDimitry Andric } else { 20280b57cec5SDimitry Andric // Okay, this is a class definition. 2029*0fca6ea1SDimitry Andric TUK = TagUseKind::Definition; 20300b57cec5SDimitry Andric } 2031fe6060f1SDimitry Andric } else if (isClassCompatibleKeyword() && 2032fe6060f1SDimitry Andric (NextToken().is(tok::l_square) || 2033fe6060f1SDimitry Andric NextToken().is(tok::kw_alignas) || 203406c3fb27SDimitry Andric NextToken().isRegularKeywordAttribute() || 2035fe6060f1SDimitry Andric isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None)) { 20360b57cec5SDimitry Andric // We can't tell if this is a definition or reference 20370b57cec5SDimitry Andric // until we skipped the 'final' and C++11 attribute specifiers. 20380b57cec5SDimitry Andric TentativeParsingAction PA(*this); 20390b57cec5SDimitry Andric 2040fe6060f1SDimitry Andric // Skip the 'final', abstract'... keywords. 2041fe6060f1SDimitry Andric while (isClassCompatibleKeyword()) { 20420b57cec5SDimitry Andric ConsumeToken(); 2043fe6060f1SDimitry Andric } 20440b57cec5SDimitry Andric 20450b57cec5SDimitry Andric // Skip C++11 attribute specifiers. 20460b57cec5SDimitry Andric while (true) { 20470b57cec5SDimitry Andric if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { 20480b57cec5SDimitry Andric ConsumeBracket(); 20490b57cec5SDimitry Andric if (!SkipUntil(tok::r_square, StopAtSemi)) 20500b57cec5SDimitry Andric break; 20510b57cec5SDimitry Andric } else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) { 20520b57cec5SDimitry Andric ConsumeToken(); 20530b57cec5SDimitry Andric ConsumeParen(); 20540b57cec5SDimitry Andric if (!SkipUntil(tok::r_paren, StopAtSemi)) 20550b57cec5SDimitry Andric break; 205606c3fb27SDimitry Andric } else if (Tok.isRegularKeywordAttribute()) { 20577a6dacacSDimitry Andric bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind()); 205806c3fb27SDimitry Andric ConsumeToken(); 20597a6dacacSDimitry Andric if (TakesArgs) { 20607a6dacacSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 20617a6dacacSDimitry Andric if (!T.consumeOpen()) 20627a6dacacSDimitry Andric T.skipToEnd(); 20637a6dacacSDimitry Andric } 20640b57cec5SDimitry Andric } else { 20650b57cec5SDimitry Andric break; 20660b57cec5SDimitry Andric } 20670b57cec5SDimitry Andric } 20680b57cec5SDimitry Andric 20690b57cec5SDimitry Andric if (Tok.isOneOf(tok::l_brace, tok::colon)) 2070*0fca6ea1SDimitry Andric TUK = TagUseKind::Definition; 20710b57cec5SDimitry Andric else 2072*0fca6ea1SDimitry Andric TUK = TagUseKind::Reference; 20730b57cec5SDimitry Andric 20740b57cec5SDimitry Andric PA.Revert(); 20750b57cec5SDimitry Andric } else if (!isTypeSpecifier(DSC) && 20760b57cec5SDimitry Andric (Tok.is(tok::semi) || 20770b57cec5SDimitry Andric (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { 2078*0fca6ea1SDimitry Andric TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration; 20790b57cec5SDimitry Andric if (Tok.isNot(tok::semi)) { 20800b57cec5SDimitry Andric const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); 20810b57cec5SDimitry Andric // A semicolon was missing after this declaration. Diagnose and recover. 20820b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, 20830b57cec5SDimitry Andric DeclSpec::getSpecifierName(TagType, PPol)); 20840b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 20850b57cec5SDimitry Andric Tok.setKind(tok::semi); 20860b57cec5SDimitry Andric } 20870b57cec5SDimitry Andric } else 2088*0fca6ea1SDimitry Andric TUK = TagUseKind::Reference; 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric // Forbid misplaced attributes. In cases of a reference, we pass attributes 20910b57cec5SDimitry Andric // to caller to handle. 2092*0fca6ea1SDimitry Andric if (TUK != TagUseKind::Reference) { 20930b57cec5SDimitry Andric // If this is not a reference, then the only possible 20940b57cec5SDimitry Andric // valid place for C++11 attributes to appear here 20950b57cec5SDimitry Andric // is between class-key and class-name. If there are 20960b57cec5SDimitry Andric // any attributes after class-name, we try a fixit to move 20970b57cec5SDimitry Andric // them to the right place. 20980b57cec5SDimitry Andric SourceRange AttrRange = Attributes.Range; 20990b57cec5SDimitry Andric if (AttrRange.isValid()) { 210006c3fb27SDimitry Andric auto *FirstAttr = Attributes.empty() ? nullptr : &Attributes.front(); 210106c3fb27SDimitry Andric auto Loc = AttrRange.getBegin(); 210206c3fb27SDimitry Andric (FirstAttr && FirstAttr->isRegularKeywordAttribute() 210306c3fb27SDimitry Andric ? Diag(Loc, diag::err_keyword_not_allowed) << FirstAttr 210406c3fb27SDimitry Andric : Diag(Loc, diag::err_attributes_not_allowed)) 21050b57cec5SDimitry Andric << AttrRange 2106972a253aSDimitry Andric << FixItHint::CreateInsertionFromRange( 2107972a253aSDimitry Andric AttrFixitLoc, CharSourceRange(AttrRange, true)) 21080b57cec5SDimitry Andric << FixItHint::CreateRemoval(AttrRange); 21090b57cec5SDimitry Andric 21100b57cec5SDimitry Andric // Recover by adding misplaced attributes to the attribute list 21110b57cec5SDimitry Andric // of the class so they can be applied on the class later. 21120b57cec5SDimitry Andric attrs.takeAllFrom(Attributes); 21130b57cec5SDimitry Andric } 21140b57cec5SDimitry Andric } 21150b57cec5SDimitry Andric 2116972a253aSDimitry Andric if (!Name && !TemplateId && 2117972a253aSDimitry Andric (DS.getTypeSpecType() == DeclSpec::TST_error || 2118*0fca6ea1SDimitry Andric TUK != TagUseKind::Definition)) { 21190b57cec5SDimitry Andric if (DS.getTypeSpecType() != DeclSpec::TST_error) { 21200b57cec5SDimitry Andric // We have a declaration or reference to an anonymous class. 21210b57cec5SDimitry Andric Diag(StartLoc, diag::err_anon_type_definition) 21220b57cec5SDimitry Andric << DeclSpec::getSpecifierName(TagType, Policy); 21230b57cec5SDimitry Andric } 21240b57cec5SDimitry Andric 21250b57cec5SDimitry Andric // If we are parsing a definition and stop at a base-clause, continue on 21260b57cec5SDimitry Andric // until the semicolon. Continuing from the comma will just trick us into 21270b57cec5SDimitry Andric // thinking we are seeing a variable declaration. 2128*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Definition && Tok.is(tok::colon)) 21290b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch); 21300b57cec5SDimitry Andric else 21310b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi); 21320b57cec5SDimitry Andric return; 21330b57cec5SDimitry Andric } 21340b57cec5SDimitry Andric 21350b57cec5SDimitry Andric // Create the tag portion of the class or class template. 21360b57cec5SDimitry Andric DeclResult TagOrTempResult = true; // invalid 21370b57cec5SDimitry Andric TypeResult TypeResult = true; // invalid 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric bool Owned = false; 2140*0fca6ea1SDimitry Andric SkipBodyInfo SkipBody; 21410b57cec5SDimitry Andric if (TemplateId) { 21420b57cec5SDimitry Andric // Explicit specialization, class template partial specialization, 21430b57cec5SDimitry Andric // or explicit instantiation. 21440b57cec5SDimitry Andric ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), 21450b57cec5SDimitry Andric TemplateId->NumArgs); 21465ffd83dbSDimitry Andric if (TemplateId->isInvalid()) { 21475ffd83dbSDimitry Andric // Can't build the declaration. 21485ffd83dbSDimitry Andric } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && 2149*0fca6ea1SDimitry Andric TUK == TagUseKind::Declaration) { 21500b57cec5SDimitry Andric // This is an explicit instantiation of a class template. 2151fe6060f1SDimitry Andric ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, 215206c3fb27SDimitry Andric diag::err_keyword_not_allowed, 2153fe6060f1SDimitry Andric /*DiagnoseEmptyAttrs=*/true); 21540b57cec5SDimitry Andric 21550b57cec5SDimitry Andric TagOrTempResult = Actions.ActOnExplicitInstantiation( 21560b57cec5SDimitry Andric getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, 21570b57cec5SDimitry Andric TagType, StartLoc, SS, TemplateId->Template, 21580b57cec5SDimitry Andric TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, 21590b57cec5SDimitry Andric TemplateId->RAngleLoc, attrs); 21600b57cec5SDimitry Andric 21610b57cec5SDimitry Andric // Friend template-ids are treated as references unless 21620b57cec5SDimitry Andric // they have template headers, in which case they're ill-formed 21630b57cec5SDimitry Andric // (FIXME: "template <class T> friend class A<T>::B<int>;"). 21640b57cec5SDimitry Andric // We diagnose this error in ActOnClassTemplateSpecialization. 2165*0fca6ea1SDimitry Andric } else if (TUK == TagUseKind::Reference || 2166*0fca6ea1SDimitry Andric (TUK == TagUseKind::Friend && 21670b57cec5SDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { 2168fe6060f1SDimitry Andric ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, 216906c3fb27SDimitry Andric diag::err_keyword_not_allowed, 2170fe6060f1SDimitry Andric /*DiagnoseEmptyAttrs=*/true); 2171972a253aSDimitry Andric TypeResult = Actions.ActOnTagTemplateIdType( 2172972a253aSDimitry Andric TUK, TagType, StartLoc, SS, TemplateId->TemplateKWLoc, 2173972a253aSDimitry Andric TemplateId->Template, TemplateId->TemplateNameLoc, 2174972a253aSDimitry Andric TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc); 21750b57cec5SDimitry Andric } else { 21760b57cec5SDimitry Andric // This is an explicit specialization or a class template 21770b57cec5SDimitry Andric // partial specialization. 21780b57cec5SDimitry Andric TemplateParameterLists FakedParamLists; 21790b57cec5SDimitry Andric if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { 21800b57cec5SDimitry Andric // This looks like an explicit instantiation, because we have 21810b57cec5SDimitry Andric // something like 21820b57cec5SDimitry Andric // 21830b57cec5SDimitry Andric // template class Foo<X> 21840b57cec5SDimitry Andric // 21850b57cec5SDimitry Andric // but it actually has a definition. Most likely, this was 21860b57cec5SDimitry Andric // meant to be an explicit specialization, but the user forgot 21870b57cec5SDimitry Andric // the '<>' after 'template'. 21880b57cec5SDimitry Andric // It this is friend declaration however, since it cannot have a 21890b57cec5SDimitry Andric // template header, it is most likely that the user meant to 21900b57cec5SDimitry Andric // remove the 'template' keyword. 2191*0fca6ea1SDimitry Andric assert((TUK == TagUseKind::Definition || TUK == TagUseKind::Friend) && 21920b57cec5SDimitry Andric "Expected a definition here"); 21930b57cec5SDimitry Andric 2194*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Friend) { 21950b57cec5SDimitry Andric Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation); 21960b57cec5SDimitry Andric TemplateParams = nullptr; 21970b57cec5SDimitry Andric } else { 21980b57cec5SDimitry Andric SourceLocation LAngleLoc = 21990b57cec5SDimitry Andric PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); 22000b57cec5SDimitry Andric Diag(TemplateId->TemplateNameLoc, 22010b57cec5SDimitry Andric diag::err_explicit_instantiation_with_definition) 22020b57cec5SDimitry Andric << SourceRange(TemplateInfo.TemplateLoc) 22030b57cec5SDimitry Andric << FixItHint::CreateInsertion(LAngleLoc, "<>"); 22040b57cec5SDimitry Andric 22050b57cec5SDimitry Andric // Create a fake template parameter list that contains only 22060b57cec5SDimitry Andric // "template<>", so that we treat this construct as a class 22070b57cec5SDimitry Andric // template specialization. 22080b57cec5SDimitry Andric FakedParamLists.push_back(Actions.ActOnTemplateParameterList( 2209bdd1243dSDimitry Andric 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 2210bdd1243dSDimitry Andric std::nullopt, LAngleLoc, nullptr)); 22110b57cec5SDimitry Andric TemplateParams = &FakedParamLists; 22120b57cec5SDimitry Andric } 22130b57cec5SDimitry Andric } 22140b57cec5SDimitry Andric 22150b57cec5SDimitry Andric // Build the class template specialization. 22160b57cec5SDimitry Andric TagOrTempResult = Actions.ActOnClassTemplateSpecialization( 22170b57cec5SDimitry Andric getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), 221855e4f9d5SDimitry Andric SS, *TemplateId, attrs, 22190b57cec5SDimitry Andric MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] 22200b57cec5SDimitry Andric : nullptr, 22210b57cec5SDimitry Andric TemplateParams ? TemplateParams->size() : 0), 22220b57cec5SDimitry Andric &SkipBody); 22230b57cec5SDimitry Andric } 22240b57cec5SDimitry Andric } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && 2225*0fca6ea1SDimitry Andric TUK == TagUseKind::Declaration) { 22260b57cec5SDimitry Andric // Explicit instantiation of a member of a class template 22270b57cec5SDimitry Andric // specialization, e.g., 22280b57cec5SDimitry Andric // 22290b57cec5SDimitry Andric // template struct Outer<int>::Inner; 22300b57cec5SDimitry Andric // 22310b57cec5SDimitry Andric ProhibitAttributes(attrs); 22320b57cec5SDimitry Andric 22330b57cec5SDimitry Andric TagOrTempResult = Actions.ActOnExplicitInstantiation( 22340b57cec5SDimitry Andric getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, 22350b57cec5SDimitry Andric TagType, StartLoc, SS, Name, NameLoc, attrs); 2236*0fca6ea1SDimitry Andric } else if (TUK == TagUseKind::Friend && 22370b57cec5SDimitry Andric TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { 2238fe6060f1SDimitry Andric ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, 223906c3fb27SDimitry Andric diag::err_keyword_not_allowed, 2240fe6060f1SDimitry Andric /*DiagnoseEmptyAttrs=*/true); 22410b57cec5SDimitry Andric 22420b57cec5SDimitry Andric TagOrTempResult = Actions.ActOnTemplatedFriendTag( 22430b57cec5SDimitry Andric getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, 22440b57cec5SDimitry Andric NameLoc, attrs, 22450b57cec5SDimitry Andric MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, 22460b57cec5SDimitry Andric TemplateParams ? TemplateParams->size() : 0)); 22470b57cec5SDimitry Andric } else { 2248*0fca6ea1SDimitry Andric if (TUK != TagUseKind::Declaration && TUK != TagUseKind::Definition) 2249fe6060f1SDimitry Andric ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, 225006c3fb27SDimitry Andric diag::err_keyword_not_allowed, 2251fe6060f1SDimitry Andric /* DiagnoseEmptyAttrs=*/true); 22520b57cec5SDimitry Andric 2253*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Definition && 22540b57cec5SDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { 22550b57cec5SDimitry Andric // If the declarator-id is not a template-id, issue a diagnostic and 22560b57cec5SDimitry Andric // recover by ignoring the 'template' keyword. 22570b57cec5SDimitry Andric Diag(Tok, diag::err_template_defn_explicit_instantiation) 22580b57cec5SDimitry Andric << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); 22590b57cec5SDimitry Andric TemplateParams = nullptr; 22600b57cec5SDimitry Andric } 22610b57cec5SDimitry Andric 22620b57cec5SDimitry Andric bool IsDependent = false; 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric // Don't pass down template parameter lists if this is just a tag 22650b57cec5SDimitry Andric // reference. For example, we don't need the template parameters here: 22660b57cec5SDimitry Andric // template <class T> class A *makeA(T t); 22670b57cec5SDimitry Andric MultiTemplateParamsArg TParams; 2268*0fca6ea1SDimitry Andric if (TUK != TagUseKind::Reference && TemplateParams) 22690b57cec5SDimitry Andric TParams = 22700b57cec5SDimitry Andric MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); 22710b57cec5SDimitry Andric 22720b57cec5SDimitry Andric stripTypeAttributesOffDeclSpec(attrs, DS, TUK); 22730b57cec5SDimitry Andric 22740b57cec5SDimitry Andric // Declaration or definition of a class type 22750b57cec5SDimitry Andric TagOrTempResult = Actions.ActOnTag( 22760b57cec5SDimitry Andric getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS, 22770b57cec5SDimitry Andric DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, 22780b57cec5SDimitry Andric SourceLocation(), false, clang::TypeResult(), 22790b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_type_specifier, 22800b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_template_param || 22810b57cec5SDimitry Andric DSC == DeclSpecContext::DSC_template_type_arg, 22821ac55f4cSDimitry Andric OffsetOfState, &SkipBody); 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric // If ActOnTag said the type was dependent, try again with the 22850b57cec5SDimitry Andric // less common call. 22860b57cec5SDimitry Andric if (IsDependent) { 2287*0fca6ea1SDimitry Andric assert(TUK == TagUseKind::Reference || TUK == TagUseKind::Friend); 2288972a253aSDimitry Andric TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, SS, 2289972a253aSDimitry Andric Name, StartLoc, NameLoc); 22900b57cec5SDimitry Andric } 22910b57cec5SDimitry Andric } 22920b57cec5SDimitry Andric 2293349cc55cSDimitry Andric // If this is an elaborated type specifier in function template, 2294349cc55cSDimitry Andric // and we delayed diagnostics before, 2295349cc55cSDimitry Andric // just merge them into the current pool. 2296349cc55cSDimitry Andric if (shouldDelayDiagsInTag) { 2297349cc55cSDimitry Andric diagsFromTag.done(); 2298*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Reference && 2299349cc55cSDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::Template) 2300349cc55cSDimitry Andric diagsFromTag.redelay(); 2301349cc55cSDimitry Andric } 2302349cc55cSDimitry Andric 23030b57cec5SDimitry Andric // If there is a body, parse it and inform the actions module. 2304*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Definition) { 23050b57cec5SDimitry Andric assert(Tok.is(tok::l_brace) || 23060b57cec5SDimitry Andric (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || 2307fe6060f1SDimitry Andric isClassCompatibleKeyword()); 23080b57cec5SDimitry Andric if (SkipBody.ShouldSkip) 23090b57cec5SDimitry Andric SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, 23100b57cec5SDimitry Andric TagOrTempResult.get()); 23110b57cec5SDimitry Andric else if (getLangOpts().CPlusPlus) 23120b57cec5SDimitry Andric ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, 23130b57cec5SDimitry Andric TagOrTempResult.get()); 23140b57cec5SDimitry Andric else { 23150b57cec5SDimitry Andric Decl *D = 23160b57cec5SDimitry Andric SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get(); 23170b57cec5SDimitry Andric // Parse the definition body. 23185ffd83dbSDimitry Andric ParseStructUnionBody(StartLoc, TagType, cast<RecordDecl>(D)); 23190b57cec5SDimitry Andric if (SkipBody.CheckSameAsPrevious && 232081ad6265SDimitry Andric !Actions.ActOnDuplicateDefinition(TagOrTempResult.get(), SkipBody)) { 23210b57cec5SDimitry Andric DS.SetTypeSpecError(); 23220b57cec5SDimitry Andric return; 23230b57cec5SDimitry Andric } 23240b57cec5SDimitry Andric } 23250b57cec5SDimitry Andric } 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric if (!TagOrTempResult.isInvalid()) 23280b57cec5SDimitry Andric // Delayed processing of attributes. 23290b57cec5SDimitry Andric Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs); 23300b57cec5SDimitry Andric 23310b57cec5SDimitry Andric const char *PrevSpec = nullptr; 23320b57cec5SDimitry Andric unsigned DiagID; 23330b57cec5SDimitry Andric bool Result; 23340b57cec5SDimitry Andric if (!TypeResult.isInvalid()) { 23350b57cec5SDimitry Andric Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, 23360b57cec5SDimitry Andric NameLoc.isValid() ? NameLoc : StartLoc, 23370b57cec5SDimitry Andric PrevSpec, DiagID, TypeResult.get(), Policy); 23380b57cec5SDimitry Andric } else if (!TagOrTempResult.isInvalid()) { 2339972a253aSDimitry Andric Result = DS.SetTypeSpecType( 2340972a253aSDimitry Andric TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec, 23411ac55f4cSDimitry Andric DiagID, TagOrTempResult.get(), Owned, Policy); 23420b57cec5SDimitry Andric } else { 23430b57cec5SDimitry Andric DS.SetTypeSpecError(); 23440b57cec5SDimitry Andric return; 23450b57cec5SDimitry Andric } 23460b57cec5SDimitry Andric 23470b57cec5SDimitry Andric if (Result) 23480b57cec5SDimitry Andric Diag(StartLoc, DiagID) << PrevSpec; 23490b57cec5SDimitry Andric 23500b57cec5SDimitry Andric // At this point, we've successfully parsed a class-specifier in 'definition' 23510b57cec5SDimitry Andric // form (e.g. "struct foo { int x; }". While we could just return here, we're 23520b57cec5SDimitry Andric // going to look at what comes after it to improve error recovery. If an 23530b57cec5SDimitry Andric // impossible token occurs next, we assume that the programmer forgot a ; at 23540b57cec5SDimitry Andric // the end of the declaration and recover that way. 23550b57cec5SDimitry Andric // 23560b57cec5SDimitry Andric // Also enforce C++ [temp]p3: 23570b57cec5SDimitry Andric // In a template-declaration which defines a class, no declarator 23580b57cec5SDimitry Andric // is permitted. 23590b57cec5SDimitry Andric // 23600b57cec5SDimitry Andric // After a type-specifier, we don't expect a semicolon. This only happens in 23610b57cec5SDimitry Andric // C, since definitions are not permitted in this context in C++. 2362*0fca6ea1SDimitry Andric if (TUK == TagUseKind::Definition && 23630b57cec5SDimitry Andric (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) && 23640b57cec5SDimitry Andric (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { 23650b57cec5SDimitry Andric if (Tok.isNot(tok::semi)) { 23660b57cec5SDimitry Andric const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); 23670b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_after, 23680b57cec5SDimitry Andric DeclSpec::getSpecifierName(TagType, PPol)); 23690b57cec5SDimitry Andric // Push this token back into the preprocessor and change our current token 23700b57cec5SDimitry Andric // to ';' so that the rest of the code recovers as though there were an 23710b57cec5SDimitry Andric // ';' after the definition. 23720b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject=*/true); 23730b57cec5SDimitry Andric Tok.setKind(tok::semi); 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric } 23760b57cec5SDimitry Andric } 23770b57cec5SDimitry Andric 23780b57cec5SDimitry Andric /// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived]. 23790b57cec5SDimitry Andric /// 23800b57cec5SDimitry Andric /// base-clause : [C++ class.derived] 23810b57cec5SDimitry Andric /// ':' base-specifier-list 23820b57cec5SDimitry Andric /// base-specifier-list: 23830b57cec5SDimitry Andric /// base-specifier '...'[opt] 23840b57cec5SDimitry Andric /// base-specifier-list ',' base-specifier '...'[opt] 23850b57cec5SDimitry Andric void Parser::ParseBaseClause(Decl *ClassDecl) { 23860b57cec5SDimitry Andric assert(Tok.is(tok::colon) && "Not a base clause"); 23870b57cec5SDimitry Andric ConsumeToken(); 23880b57cec5SDimitry Andric 23890b57cec5SDimitry Andric // Build up an array of parsed base specifiers. 23900b57cec5SDimitry Andric SmallVector<CXXBaseSpecifier *, 8> BaseInfo; 23910b57cec5SDimitry Andric 23920b57cec5SDimitry Andric while (true) { 23930b57cec5SDimitry Andric // Parse a base-specifier. 23940b57cec5SDimitry Andric BaseResult Result = ParseBaseSpecifier(ClassDecl); 23950b57cec5SDimitry Andric if (Result.isInvalid()) { 23960b57cec5SDimitry Andric // Skip the rest of this base specifier, up until the comma or 23970b57cec5SDimitry Andric // opening brace. 23980b57cec5SDimitry Andric SkipUntil(tok::comma, tok::l_brace, StopAtSemi | StopBeforeMatch); 23990b57cec5SDimitry Andric } else { 24000b57cec5SDimitry Andric // Add this to our array of base specifiers. 24010b57cec5SDimitry Andric BaseInfo.push_back(Result.get()); 24020b57cec5SDimitry Andric } 24030b57cec5SDimitry Andric 24040b57cec5SDimitry Andric // If the next token is a comma, consume it and keep reading 24050b57cec5SDimitry Andric // base-specifiers. 24060b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma)) 24070b57cec5SDimitry Andric break; 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric 24100b57cec5SDimitry Andric // Attach the base specifiers 24110b57cec5SDimitry Andric Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo); 24120b57cec5SDimitry Andric } 24130b57cec5SDimitry Andric 24140b57cec5SDimitry Andric /// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is 24150b57cec5SDimitry Andric /// one entry in the base class list of a class specifier, for example: 24160b57cec5SDimitry Andric /// class foo : public bar, virtual private baz { 24170b57cec5SDimitry Andric /// 'public bar' and 'virtual private baz' are each base-specifiers. 24180b57cec5SDimitry Andric /// 24190b57cec5SDimitry Andric /// base-specifier: [C++ class.derived] 24200b57cec5SDimitry Andric /// attribute-specifier-seq[opt] base-type-specifier 24210b57cec5SDimitry Andric /// attribute-specifier-seq[opt] 'virtual' access-specifier[opt] 24220b57cec5SDimitry Andric /// base-type-specifier 24230b57cec5SDimitry Andric /// attribute-specifier-seq[opt] access-specifier 'virtual'[opt] 24240b57cec5SDimitry Andric /// base-type-specifier 24250b57cec5SDimitry Andric BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { 24260b57cec5SDimitry Andric bool IsVirtual = false; 24270b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 24280b57cec5SDimitry Andric 242981ad6265SDimitry Andric ParsedAttributes Attributes(AttrFactory); 24300b57cec5SDimitry Andric MaybeParseCXX11Attributes(Attributes); 24310b57cec5SDimitry Andric 24320b57cec5SDimitry Andric // Parse the 'virtual' keyword. 24330b57cec5SDimitry Andric if (TryConsumeToken(tok::kw_virtual)) 24340b57cec5SDimitry Andric IsVirtual = true; 24350b57cec5SDimitry Andric 24360b57cec5SDimitry Andric CheckMisplacedCXX11Attribute(Attributes, StartLoc); 24370b57cec5SDimitry Andric 24380b57cec5SDimitry Andric // Parse an (optional) access specifier. 24390b57cec5SDimitry Andric AccessSpecifier Access = getAccessSpecifierIfPresent(); 244081ad6265SDimitry Andric if (Access != AS_none) { 24410b57cec5SDimitry Andric ConsumeToken(); 244281ad6265SDimitry Andric if (getLangOpts().HLSL) 244381ad6265SDimitry Andric Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers); 244481ad6265SDimitry Andric } 24450b57cec5SDimitry Andric 24460b57cec5SDimitry Andric CheckMisplacedCXX11Attribute(Attributes, StartLoc); 24470b57cec5SDimitry Andric 24480b57cec5SDimitry Andric // Parse the 'virtual' keyword (again!), in case it came after the 24490b57cec5SDimitry Andric // access specifier. 24500b57cec5SDimitry Andric if (Tok.is(tok::kw_virtual)) { 24510b57cec5SDimitry Andric SourceLocation VirtualLoc = ConsumeToken(); 24520b57cec5SDimitry Andric if (IsVirtual) { 24530b57cec5SDimitry Andric // Complain about duplicate 'virtual' 24540b57cec5SDimitry Andric Diag(VirtualLoc, diag::err_dup_virtual) 24550b57cec5SDimitry Andric << FixItHint::CreateRemoval(VirtualLoc); 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric 24580b57cec5SDimitry Andric IsVirtual = true; 24590b57cec5SDimitry Andric } 24600b57cec5SDimitry Andric 24610b57cec5SDimitry Andric CheckMisplacedCXX11Attribute(Attributes, StartLoc); 24620b57cec5SDimitry Andric 24630b57cec5SDimitry Andric // Parse the class-name. 24640b57cec5SDimitry Andric 24650b57cec5SDimitry Andric // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL 24660b57cec5SDimitry Andric // implementation for VS2013 uses _Atomic as an identifier for one of the 24670b57cec5SDimitry Andric // classes in <atomic>. Treat '_Atomic' to be an identifier when we are 24680b57cec5SDimitry Andric // parsing the class-name for a base specifier. 24690b57cec5SDimitry Andric if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) && 24700b57cec5SDimitry Andric NextToken().is(tok::less)) 24710b57cec5SDimitry Andric Tok.setKind(tok::identifier); 24720b57cec5SDimitry Andric 24730b57cec5SDimitry Andric SourceLocation EndLocation; 24740b57cec5SDimitry Andric SourceLocation BaseLoc; 24750b57cec5SDimitry Andric TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation); 24760b57cec5SDimitry Andric if (BaseType.isInvalid()) 24770b57cec5SDimitry Andric return true; 24780b57cec5SDimitry Andric 24790b57cec5SDimitry Andric // Parse the optional ellipsis (for a pack expansion). The ellipsis is 24800b57cec5SDimitry Andric // actually part of the base-specifier-list grammar productions, but we 24810b57cec5SDimitry Andric // parse it here for convenience. 24820b57cec5SDimitry Andric SourceLocation EllipsisLoc; 24830b57cec5SDimitry Andric TryConsumeToken(tok::ellipsis, EllipsisLoc); 24840b57cec5SDimitry Andric 24850b57cec5SDimitry Andric // Find the complete source range for the base-specifier. 24860b57cec5SDimitry Andric SourceRange Range(StartLoc, EndLocation); 24870b57cec5SDimitry Andric 24880b57cec5SDimitry Andric // Notify semantic analysis that we have parsed a complete 24890b57cec5SDimitry Andric // base-specifier. 24900b57cec5SDimitry Andric return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual, 24910b57cec5SDimitry Andric Access, BaseType.get(), BaseLoc, 24920b57cec5SDimitry Andric EllipsisLoc); 24930b57cec5SDimitry Andric } 24940b57cec5SDimitry Andric 24950b57cec5SDimitry Andric /// getAccessSpecifierIfPresent - Determine whether the next token is 24960b57cec5SDimitry Andric /// a C++ access-specifier. 24970b57cec5SDimitry Andric /// 24980b57cec5SDimitry Andric /// access-specifier: [C++ class.derived] 24990b57cec5SDimitry Andric /// 'private' 25000b57cec5SDimitry Andric /// 'protected' 25010b57cec5SDimitry Andric /// 'public' 25020b57cec5SDimitry Andric AccessSpecifier Parser::getAccessSpecifierIfPresent() const { 25030b57cec5SDimitry Andric switch (Tok.getKind()) { 2504972a253aSDimitry Andric default: 2505972a253aSDimitry Andric return AS_none; 2506972a253aSDimitry Andric case tok::kw_private: 2507972a253aSDimitry Andric return AS_private; 2508972a253aSDimitry Andric case tok::kw_protected: 2509972a253aSDimitry Andric return AS_protected; 2510972a253aSDimitry Andric case tok::kw_public: 2511972a253aSDimitry Andric return AS_public; 25120b57cec5SDimitry Andric } 25130b57cec5SDimitry Andric } 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric /// If the given declarator has any parts for which parsing has to be 25160b57cec5SDimitry Andric /// delayed, e.g., default arguments or an exception-specification, create a 25170b57cec5SDimitry Andric /// late-parsed method declaration record to handle the parsing at the end of 25180b57cec5SDimitry Andric /// the class definition. 25190b57cec5SDimitry Andric void Parser::HandleMemberFunctionDeclDelays(Declarator &DeclaratorInfo, 25200b57cec5SDimitry Andric Decl *ThisDecl) { 2521972a253aSDimitry Andric DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo(); 25220b57cec5SDimitry Andric // If there was a late-parsed exception-specification, we'll need a 25230b57cec5SDimitry Andric // late parse 25240b57cec5SDimitry Andric bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed; 25250b57cec5SDimitry Andric 25260b57cec5SDimitry Andric if (!NeedLateParse) { 25270b57cec5SDimitry Andric // Look ahead to see if there are any default args 25280b57cec5SDimitry Andric for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { 2529*0fca6ea1SDimitry Andric const auto *Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param); 25300b57cec5SDimitry Andric if (Param->hasUnparsedDefaultArg()) { 25310b57cec5SDimitry Andric NeedLateParse = true; 25320b57cec5SDimitry Andric break; 25330b57cec5SDimitry Andric } 25340b57cec5SDimitry Andric } 25350b57cec5SDimitry Andric } 25360b57cec5SDimitry Andric 25370b57cec5SDimitry Andric if (NeedLateParse) { 25380b57cec5SDimitry Andric // Push this method onto the stack of late-parsed method 25390b57cec5SDimitry Andric // declarations. 25400b57cec5SDimitry Andric auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); 25410b57cec5SDimitry Andric getCurrentClass().LateParsedDeclarations.push_back(LateMethod); 25420b57cec5SDimitry Andric 2543e8d8bef9SDimitry Andric // Push tokens for each parameter. Those that do not have defaults will be 2544e8d8bef9SDimitry Andric // NULL. We need to track all the parameters so that we can push them into 2545e8d8bef9SDimitry Andric // scope for later parameters and perhaps for the exception specification. 25460b57cec5SDimitry Andric LateMethod->DefaultArgs.reserve(FTI.NumParams); 25470b57cec5SDimitry Andric for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) 25480b57cec5SDimitry Andric LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument( 25490b57cec5SDimitry Andric FTI.Params[ParamIdx].Param, 25500b57cec5SDimitry Andric std::move(FTI.Params[ParamIdx].DefaultArgTokens))); 2551e8d8bef9SDimitry Andric 2552e8d8bef9SDimitry Andric // Stash the exception-specification tokens in the late-pased method. 2553e8d8bef9SDimitry Andric if (FTI.getExceptionSpecType() == EST_Unparsed) { 2554e8d8bef9SDimitry Andric LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; 2555e8d8bef9SDimitry Andric FTI.ExceptionSpecTokens = nullptr; 2556e8d8bef9SDimitry Andric } 25570b57cec5SDimitry Andric } 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric 25600b57cec5SDimitry Andric /// isCXX11VirtSpecifier - Determine whether the given token is a C++11 25610b57cec5SDimitry Andric /// virt-specifier. 25620b57cec5SDimitry Andric /// 25630b57cec5SDimitry Andric /// virt-specifier: 25640b57cec5SDimitry Andric /// override 25650b57cec5SDimitry Andric /// final 25660b57cec5SDimitry Andric /// __final 25670b57cec5SDimitry Andric VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { 25680b57cec5SDimitry Andric if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier)) 25690b57cec5SDimitry Andric return VirtSpecifiers::VS_None; 25700b57cec5SDimitry Andric 2571*0fca6ea1SDimitry Andric const IdentifierInfo *II = Tok.getIdentifierInfo(); 25720b57cec5SDimitry Andric 25730b57cec5SDimitry Andric // Initialize the contextual keywords. 25740b57cec5SDimitry Andric if (!Ident_final) { 25750b57cec5SDimitry Andric Ident_final = &PP.getIdentifierTable().get("final"); 25760b57cec5SDimitry Andric if (getLangOpts().GNUKeywords) 25770b57cec5SDimitry Andric Ident_GNU_final = &PP.getIdentifierTable().get("__final"); 2578fe6060f1SDimitry Andric if (getLangOpts().MicrosoftExt) { 25790b57cec5SDimitry Andric Ident_sealed = &PP.getIdentifierTable().get("sealed"); 2580fe6060f1SDimitry Andric Ident_abstract = &PP.getIdentifierTable().get("abstract"); 2581fe6060f1SDimitry Andric } 25820b57cec5SDimitry Andric Ident_override = &PP.getIdentifierTable().get("override"); 25830b57cec5SDimitry Andric } 25840b57cec5SDimitry Andric 25850b57cec5SDimitry Andric if (II == Ident_override) 25860b57cec5SDimitry Andric return VirtSpecifiers::VS_Override; 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric if (II == Ident_sealed) 25890b57cec5SDimitry Andric return VirtSpecifiers::VS_Sealed; 25900b57cec5SDimitry Andric 2591fe6060f1SDimitry Andric if (II == Ident_abstract) 2592fe6060f1SDimitry Andric return VirtSpecifiers::VS_Abstract; 2593fe6060f1SDimitry Andric 25940b57cec5SDimitry Andric if (II == Ident_final) 25950b57cec5SDimitry Andric return VirtSpecifiers::VS_Final; 25960b57cec5SDimitry Andric 25970b57cec5SDimitry Andric if (II == Ident_GNU_final) 25980b57cec5SDimitry Andric return VirtSpecifiers::VS_GNU_Final; 25990b57cec5SDimitry Andric 26000b57cec5SDimitry Andric return VirtSpecifiers::VS_None; 26010b57cec5SDimitry Andric } 26020b57cec5SDimitry Andric 26030b57cec5SDimitry Andric /// ParseOptionalCXX11VirtSpecifierSeq - Parse a virt-specifier-seq. 26040b57cec5SDimitry Andric /// 26050b57cec5SDimitry Andric /// virt-specifier-seq: 26060b57cec5SDimitry Andric /// virt-specifier 26070b57cec5SDimitry Andric /// virt-specifier-seq virt-specifier 26080b57cec5SDimitry Andric void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, 26090b57cec5SDimitry Andric bool IsInterface, 26100b57cec5SDimitry Andric SourceLocation FriendLoc) { 26110b57cec5SDimitry Andric while (true) { 26120b57cec5SDimitry Andric VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); 26130b57cec5SDimitry Andric if (Specifier == VirtSpecifiers::VS_None) 26140b57cec5SDimitry Andric return; 26150b57cec5SDimitry Andric 26160b57cec5SDimitry Andric if (FriendLoc.isValid()) { 26170b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_friend_decl_spec) 26180b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier) 26190b57cec5SDimitry Andric << FixItHint::CreateRemoval(Tok.getLocation()) 26200b57cec5SDimitry Andric << SourceRange(FriendLoc, FriendLoc); 26210b57cec5SDimitry Andric ConsumeToken(); 26220b57cec5SDimitry Andric continue; 26230b57cec5SDimitry Andric } 26240b57cec5SDimitry Andric 26250b57cec5SDimitry Andric // C++ [class.mem]p8: 26260b57cec5SDimitry Andric // A virt-specifier-seq shall contain at most one of each virt-specifier. 26270b57cec5SDimitry Andric const char *PrevSpec = nullptr; 26280b57cec5SDimitry Andric if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec)) 26290b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier) 2630972a253aSDimitry Andric << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); 26310b57cec5SDimitry Andric 26320b57cec5SDimitry Andric if (IsInterface && (Specifier == VirtSpecifiers::VS_Final || 26330b57cec5SDimitry Andric Specifier == VirtSpecifiers::VS_Sealed)) { 26340b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_override_control_interface) 26350b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier); 26360b57cec5SDimitry Andric } else if (Specifier == VirtSpecifiers::VS_Sealed) { 26370b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword); 2638fe6060f1SDimitry Andric } else if (Specifier == VirtSpecifiers::VS_Abstract) { 2639fe6060f1SDimitry Andric Diag(Tok.getLocation(), diag::ext_ms_abstract_keyword); 26400b57cec5SDimitry Andric } else if (Specifier == VirtSpecifiers::VS_GNU_Final) { 26410b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::ext_warn_gnu_final); 26420b57cec5SDimitry Andric } else { 26430b57cec5SDimitry Andric Diag(Tok.getLocation(), 26440b57cec5SDimitry Andric getLangOpts().CPlusPlus11 26450b57cec5SDimitry Andric ? diag::warn_cxx98_compat_override_control_keyword 26460b57cec5SDimitry Andric : diag::ext_override_control_keyword) 26470b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier); 26480b57cec5SDimitry Andric } 26490b57cec5SDimitry Andric ConsumeToken(); 26500b57cec5SDimitry Andric } 26510b57cec5SDimitry Andric } 26520b57cec5SDimitry Andric 26530b57cec5SDimitry Andric /// isCXX11FinalKeyword - Determine whether the next token is a C++11 26540b57cec5SDimitry Andric /// 'final' or Microsoft 'sealed' contextual keyword. 26550b57cec5SDimitry Andric bool Parser::isCXX11FinalKeyword() const { 26560b57cec5SDimitry Andric VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); 26570b57cec5SDimitry Andric return Specifier == VirtSpecifiers::VS_Final || 26580b57cec5SDimitry Andric Specifier == VirtSpecifiers::VS_GNU_Final || 26590b57cec5SDimitry Andric Specifier == VirtSpecifiers::VS_Sealed; 26600b57cec5SDimitry Andric } 26610b57cec5SDimitry Andric 2662fe6060f1SDimitry Andric /// isClassCompatibleKeyword - Determine whether the next token is a C++11 2663fe6060f1SDimitry Andric /// 'final' or Microsoft 'sealed' or 'abstract' contextual keywords. 2664fe6060f1SDimitry Andric bool Parser::isClassCompatibleKeyword() const { 2665fe6060f1SDimitry Andric VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); 2666fe6060f1SDimitry Andric return Specifier == VirtSpecifiers::VS_Final || 2667fe6060f1SDimitry Andric Specifier == VirtSpecifiers::VS_GNU_Final || 2668fe6060f1SDimitry Andric Specifier == VirtSpecifiers::VS_Sealed || 2669fe6060f1SDimitry Andric Specifier == VirtSpecifiers::VS_Abstract; 2670fe6060f1SDimitry Andric } 2671fe6060f1SDimitry Andric 26720b57cec5SDimitry Andric /// Parse a C++ member-declarator up to, but not including, the optional 26730b57cec5SDimitry Andric /// brace-or-equal-initializer or pure-specifier. 26740b57cec5SDimitry Andric bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( 26750b57cec5SDimitry Andric Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize, 26760b57cec5SDimitry Andric LateParsedAttrList &LateParsedAttrs) { 26770b57cec5SDimitry Andric // member-declarator: 2678e8d8bef9SDimitry Andric // declarator virt-specifier-seq[opt] pure-specifier[opt] 2679480093f4SDimitry Andric // declarator requires-clause 26800b57cec5SDimitry Andric // declarator brace-or-equal-initializer[opt] 2681e8d8bef9SDimitry Andric // identifier attribute-specifier-seq[opt] ':' constant-expression 2682e8d8bef9SDimitry Andric // brace-or-equal-initializer[opt] 2683e8d8bef9SDimitry Andric // ':' constant-expression 2684e8d8bef9SDimitry Andric // 2685e8d8bef9SDimitry Andric // NOTE: the latter two productions are a proposed bugfix rather than the 2686e8d8bef9SDimitry Andric // current grammar rules as of C++20. 26870b57cec5SDimitry Andric if (Tok.isNot(tok::colon)) 26880b57cec5SDimitry Andric ParseDeclarator(DeclaratorInfo); 26890b57cec5SDimitry Andric else 26900b57cec5SDimitry Andric DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation()); 26910b57cec5SDimitry Andric 2692*0fca6ea1SDimitry Andric if (getLangOpts().HLSL) 2693*0fca6ea1SDimitry Andric MaybeParseHLSLAnnotations(DeclaratorInfo, nullptr, 2694*0fca6ea1SDimitry Andric /*CouldBeBitField*/ true); 2695*0fca6ea1SDimitry Andric 26960b57cec5SDimitry Andric if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) { 26970b57cec5SDimitry Andric assert(DeclaratorInfo.isPastIdentifier() && 26980b57cec5SDimitry Andric "don't know where identifier would go yet?"); 26990b57cec5SDimitry Andric BitfieldSize = ParseConstantExpression(); 27000b57cec5SDimitry Andric if (BitfieldSize.isInvalid()) 27010b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); 2702480093f4SDimitry Andric } else if (Tok.is(tok::kw_requires)) { 2703480093f4SDimitry Andric ParseTrailingRequiresClause(DeclaratorInfo); 27040b57cec5SDimitry Andric } else { 27050b57cec5SDimitry Andric ParseOptionalCXX11VirtSpecifierSeq( 27060b57cec5SDimitry Andric VS, getCurrentClass().IsInterface, 27070b57cec5SDimitry Andric DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); 27080b57cec5SDimitry Andric if (!VS.isUnset()) 2709972a253aSDimitry Andric MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, 2710972a253aSDimitry Andric VS); 27110b57cec5SDimitry Andric } 27120b57cec5SDimitry Andric 27130b57cec5SDimitry Andric // If a simple-asm-expr is present, parse it. 27140b57cec5SDimitry Andric if (Tok.is(tok::kw_asm)) { 27150b57cec5SDimitry Andric SourceLocation Loc; 2716480093f4SDimitry Andric ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc)); 27170b57cec5SDimitry Andric if (AsmLabel.isInvalid()) 27180b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); 27190b57cec5SDimitry Andric 27200b57cec5SDimitry Andric DeclaratorInfo.setAsmLabel(AsmLabel.get()); 27210b57cec5SDimitry Andric DeclaratorInfo.SetRangeEnd(Loc); 27220b57cec5SDimitry Andric } 27230b57cec5SDimitry Andric 27240b57cec5SDimitry Andric // If attributes exist after the declarator, but before an '{', parse them. 2725e8d8bef9SDimitry Andric // However, this does not apply for [[]] attributes (which could show up 2726e8d8bef9SDimitry Andric // before or after the __attribute__ attributes). 2727e8d8bef9SDimitry Andric DiagnoseAndSkipCXX11Attributes(); 27280b57cec5SDimitry Andric MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); 2729e8d8bef9SDimitry Andric DiagnoseAndSkipCXX11Attributes(); 27300b57cec5SDimitry Andric 27310b57cec5SDimitry Andric // For compatibility with code written to older Clang, also accept a 27320b57cec5SDimitry Andric // virt-specifier *after* the GNU attributes. 27330b57cec5SDimitry Andric if (BitfieldSize.isUnset() && VS.isUnset()) { 27340b57cec5SDimitry Andric ParseOptionalCXX11VirtSpecifierSeq( 27350b57cec5SDimitry Andric VS, getCurrentClass().IsInterface, 27360b57cec5SDimitry Andric DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); 27370b57cec5SDimitry Andric if (!VS.isUnset()) { 27380b57cec5SDimitry Andric // If we saw any GNU-style attributes that are known to GCC followed by a 27390b57cec5SDimitry Andric // virt-specifier, issue a GCC-compat warning. 27400b57cec5SDimitry Andric for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) 27410b57cec5SDimitry Andric if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) 27420b57cec5SDimitry Andric Diag(AL.getLoc(), diag::warn_gcc_attribute_location); 27430b57cec5SDimitry Andric 2744972a253aSDimitry Andric MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, 2745972a253aSDimitry Andric VS); 27460b57cec5SDimitry Andric } 27470b57cec5SDimitry Andric } 27480b57cec5SDimitry Andric 27490b57cec5SDimitry Andric // If this has neither a name nor a bit width, something has gone seriously 27500b57cec5SDimitry Andric // wrong. Skip until the semi-colon or }. 27510b57cec5SDimitry Andric if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) { 27520b57cec5SDimitry Andric // If so, skip until the semi-colon or a }. 27530b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); 27540b57cec5SDimitry Andric return true; 27550b57cec5SDimitry Andric } 27560b57cec5SDimitry Andric return false; 27570b57cec5SDimitry Andric } 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric /// Look for declaration specifiers possibly occurring after C++11 27600b57cec5SDimitry Andric /// virt-specifier-seq and diagnose them. 27610b57cec5SDimitry Andric void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( 2762972a253aSDimitry Andric Declarator &D, VirtSpecifiers &VS) { 27630b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 27640b57cec5SDimitry Andric 27650b57cec5SDimitry Andric // GNU-style and C++11 attributes are not allowed here, but they will be 27660b57cec5SDimitry Andric // handled by the caller. Diagnose everything else. 27670b57cec5SDimitry Andric ParseTypeQualifierListOpt( 27680b57cec5SDimitry Andric DS, AR_NoAttributesParsed, false, 27690b57cec5SDimitry Andric /*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() { 2770*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D, &VS); 27710b57cec5SDimitry Andric })); 27720b57cec5SDimitry Andric D.ExtendWithDeclSpec(DS); 27730b57cec5SDimitry Andric 27740b57cec5SDimitry Andric if (D.isFunctionDeclarator()) { 27750b57cec5SDimitry Andric auto &Function = D.getFunctionTypeInfo(); 27760b57cec5SDimitry Andric if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) { 27770b57cec5SDimitry Andric auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName, 27780b57cec5SDimitry Andric SourceLocation SpecLoc) { 27790b57cec5SDimitry Andric FixItHint Insertion; 27800b57cec5SDimitry Andric auto &MQ = Function.getOrCreateMethodQualifiers(); 27810b57cec5SDimitry Andric if (!(MQ.getTypeQualifiers() & TypeQual)) { 27820b57cec5SDimitry Andric std::string Name(FixItName.data()); 27830b57cec5SDimitry Andric Name += " "; 27840b57cec5SDimitry Andric Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name); 27850b57cec5SDimitry Andric MQ.SetTypeQual(TypeQual, SpecLoc); 27860b57cec5SDimitry Andric } 27870b57cec5SDimitry Andric Diag(SpecLoc, diag::err_declspec_after_virtspec) 27880b57cec5SDimitry Andric << FixItName 27890b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) 27900b57cec5SDimitry Andric << FixItHint::CreateRemoval(SpecLoc) << Insertion; 27910b57cec5SDimitry Andric }; 27920b57cec5SDimitry Andric DS.forEachQualifier(DeclSpecCheck); 27930b57cec5SDimitry Andric } 27940b57cec5SDimitry Andric 27950b57cec5SDimitry Andric // Parse ref-qualifiers. 27960b57cec5SDimitry Andric bool RefQualifierIsLValueRef = true; 27970b57cec5SDimitry Andric SourceLocation RefQualifierLoc; 27980b57cec5SDimitry Andric if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) { 27990b57cec5SDimitry Andric const char *Name = (RefQualifierIsLValueRef ? "& " : "&& "); 2800972a253aSDimitry Andric FixItHint Insertion = 2801972a253aSDimitry Andric FixItHint::CreateInsertion(VS.getFirstLocation(), Name); 28020b57cec5SDimitry Andric Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef; 2803e8d8bef9SDimitry Andric Function.RefQualifierLoc = RefQualifierLoc; 28040b57cec5SDimitry Andric 28050b57cec5SDimitry Andric Diag(RefQualifierLoc, diag::err_declspec_after_virtspec) 28060b57cec5SDimitry Andric << (RefQualifierIsLValueRef ? "&" : "&&") 28070b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) 2808972a253aSDimitry Andric << FixItHint::CreateRemoval(RefQualifierLoc) << Insertion; 28090b57cec5SDimitry Andric D.SetRangeEnd(RefQualifierLoc); 28100b57cec5SDimitry Andric } 28110b57cec5SDimitry Andric } 28120b57cec5SDimitry Andric } 28130b57cec5SDimitry Andric 28140b57cec5SDimitry Andric /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. 28150b57cec5SDimitry Andric /// 28160b57cec5SDimitry Andric /// member-declaration: 28170b57cec5SDimitry Andric /// decl-specifier-seq[opt] member-declarator-list[opt] ';' 28180b57cec5SDimitry Andric /// function-definition ';'[opt] 28190b57cec5SDimitry Andric /// ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO] 28200b57cec5SDimitry Andric /// using-declaration [TODO] 28210b57cec5SDimitry Andric /// [C++0x] static_assert-declaration 28220b57cec5SDimitry Andric /// template-declaration 28230b57cec5SDimitry Andric /// [GNU] '__extension__' member-declaration 28240b57cec5SDimitry Andric /// 28250b57cec5SDimitry Andric /// member-declarator-list: 28260b57cec5SDimitry Andric /// member-declarator 28270b57cec5SDimitry Andric /// member-declarator-list ',' member-declarator 28280b57cec5SDimitry Andric /// 28290b57cec5SDimitry Andric /// member-declarator: 28300b57cec5SDimitry Andric /// declarator virt-specifier-seq[opt] pure-specifier[opt] 2831480093f4SDimitry Andric /// [C++2a] declarator requires-clause 28320b57cec5SDimitry Andric /// declarator constant-initializer[opt] 28330b57cec5SDimitry Andric /// [C++11] declarator brace-or-equal-initializer[opt] 28340b57cec5SDimitry Andric /// identifier[opt] ':' constant-expression 28350b57cec5SDimitry Andric /// 28360b57cec5SDimitry Andric /// virt-specifier-seq: 28370b57cec5SDimitry Andric /// virt-specifier 28380b57cec5SDimitry Andric /// virt-specifier-seq virt-specifier 28390b57cec5SDimitry Andric /// 28400b57cec5SDimitry Andric /// virt-specifier: 28410b57cec5SDimitry Andric /// override 28420b57cec5SDimitry Andric /// final 28430b57cec5SDimitry Andric /// [MS] sealed 28440b57cec5SDimitry Andric /// 28450b57cec5SDimitry Andric /// pure-specifier: 28460b57cec5SDimitry Andric /// '= 0' 28470b57cec5SDimitry Andric /// 28480b57cec5SDimitry Andric /// constant-initializer: 28490b57cec5SDimitry Andric /// '=' constant-expression 28500b57cec5SDimitry Andric /// 2851*0fca6ea1SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( 2852*0fca6ea1SDimitry Andric AccessSpecifier AS, ParsedAttributes &AccessAttrs, 2853*0fca6ea1SDimitry Andric ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { 28541db9f3b2SDimitry Andric assert(getLangOpts().CPlusPlus && 28551db9f3b2SDimitry Andric "ParseCXXClassMemberDeclaration should only be called in C++ mode"); 28560b57cec5SDimitry Andric if (Tok.is(tok::at)) { 28570b57cec5SDimitry Andric if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(tok::objc_defs)) 28580b57cec5SDimitry Andric Diag(Tok, diag::err_at_defs_cxx); 28590b57cec5SDimitry Andric else 28600b57cec5SDimitry Andric Diag(Tok, diag::err_at_in_class); 28610b57cec5SDimitry Andric 28620b57cec5SDimitry Andric ConsumeToken(); 28630b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi); 28640b57cec5SDimitry Andric return nullptr; 28650b57cec5SDimitry Andric } 28660b57cec5SDimitry Andric 28670b57cec5SDimitry Andric // Turn on colon protection early, while parsing declspec, although there is 28680b57cec5SDimitry Andric // nothing to protect there. It prevents from false errors if error recovery 28690b57cec5SDimitry Andric // incorrectly determines where the declspec ends, as in the example: 28700b57cec5SDimitry Andric // struct A { enum class B { C }; }; 28710b57cec5SDimitry Andric // const int C = 4; 28720b57cec5SDimitry Andric // struct D { A::B : C; }; 28730b57cec5SDimitry Andric ColonProtectionRAIIObject X(*this); 28740b57cec5SDimitry Andric 28750b57cec5SDimitry Andric // Access declarations. 28760b57cec5SDimitry Andric bool MalformedTypeSpec = false; 28770b57cec5SDimitry Andric if (!TemplateInfo.Kind && 28780b57cec5SDimitry Andric Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) { 28790b57cec5SDimitry Andric if (TryAnnotateCXXScopeToken()) 28800b57cec5SDimitry Andric MalformedTypeSpec = true; 28810b57cec5SDimitry Andric 28820b57cec5SDimitry Andric bool isAccessDecl; 28830b57cec5SDimitry Andric if (Tok.isNot(tok::annot_cxxscope)) 28840b57cec5SDimitry Andric isAccessDecl = false; 28850b57cec5SDimitry Andric else if (NextToken().is(tok::identifier)) 28860b57cec5SDimitry Andric isAccessDecl = GetLookAheadToken(2).is(tok::semi); 28870b57cec5SDimitry Andric else 28880b57cec5SDimitry Andric isAccessDecl = NextToken().is(tok::kw_operator); 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric if (isAccessDecl) { 28910b57cec5SDimitry Andric // Collect the scope specifier token we annotated earlier. 28920b57cec5SDimitry Andric CXXScopeSpec SS; 28935ffd83dbSDimitry Andric ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 289404eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 28950b57cec5SDimitry Andric /*EnteringContext=*/false); 28960b57cec5SDimitry Andric 28970b57cec5SDimitry Andric if (SS.isInvalid()) { 28980b57cec5SDimitry Andric SkipUntil(tok::semi); 28990b57cec5SDimitry Andric return nullptr; 29000b57cec5SDimitry Andric } 29010b57cec5SDimitry Andric 29020b57cec5SDimitry Andric // Try to parse an unqualified-id. 29030b57cec5SDimitry Andric SourceLocation TemplateKWLoc; 29040b57cec5SDimitry Andric UnqualifiedId Name; 29055ffd83dbSDimitry Andric if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 29065ffd83dbSDimitry Andric /*ObjectHadErrors=*/false, false, true, true, 29075ffd83dbSDimitry Andric false, &TemplateKWLoc, Name)) { 29080b57cec5SDimitry Andric SkipUntil(tok::semi); 29090b57cec5SDimitry Andric return nullptr; 29100b57cec5SDimitry Andric } 29110b57cec5SDimitry Andric 29120b57cec5SDimitry Andric // TODO: recover from mistakenly-qualified operator declarations. 29130b57cec5SDimitry Andric if (ExpectAndConsume(tok::semi, diag::err_expected_after, 29140b57cec5SDimitry Andric "access declaration")) { 29150b57cec5SDimitry Andric SkipUntil(tok::semi); 29160b57cec5SDimitry Andric return nullptr; 29170b57cec5SDimitry Andric } 29180b57cec5SDimitry Andric 29190b57cec5SDimitry Andric // FIXME: We should do something with the 'template' keyword here. 29200b57cec5SDimitry Andric return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( 29210b57cec5SDimitry Andric getCurScope(), AS, /*UsingLoc*/ SourceLocation(), 29220b57cec5SDimitry Andric /*TypenameLoc*/ SourceLocation(), SS, Name, 29230b57cec5SDimitry Andric /*EllipsisLoc*/ SourceLocation(), 29240b57cec5SDimitry Andric /*AttrList*/ ParsedAttributesView()))); 29250b57cec5SDimitry Andric } 29260b57cec5SDimitry Andric } 29270b57cec5SDimitry Andric 29280b57cec5SDimitry Andric // static_assert-declaration. A templated static_assert declaration is 2929*0fca6ea1SDimitry Andric // diagnosed in Parser::ParseDeclarationAfterTemplate. 29300b57cec5SDimitry Andric if (!TemplateInfo.Kind && 29310b57cec5SDimitry Andric Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { 29320b57cec5SDimitry Andric SourceLocation DeclEnd; 29330b57cec5SDimitry Andric return DeclGroupPtrTy::make( 29340b57cec5SDimitry Andric DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd))); 29350b57cec5SDimitry Andric } 29360b57cec5SDimitry Andric 29370b57cec5SDimitry Andric if (Tok.is(tok::kw_template)) { 29380b57cec5SDimitry Andric assert(!TemplateInfo.TemplateParams && 29390b57cec5SDimitry Andric "Nested template improperly parsed?"); 29400b57cec5SDimitry Andric ObjCDeclContextSwitch ObjCDC(*this); 29410b57cec5SDimitry Andric SourceLocation DeclEnd; 2942*0fca6ea1SDimitry Andric return ParseTemplateDeclarationOrSpecialization(DeclaratorContext::Member, 2943*0fca6ea1SDimitry Andric DeclEnd, AccessAttrs, AS); 29440b57cec5SDimitry Andric } 29450b57cec5SDimitry Andric 29460b57cec5SDimitry Andric // Handle: member-declaration ::= '__extension__' member-declaration 29470b57cec5SDimitry Andric if (Tok.is(tok::kw___extension__)) { 29480b57cec5SDimitry Andric // __extension__ silences extension warnings in the subexpression. 29490b57cec5SDimitry Andric ExtensionRAIIObject O(Diags); // Use RAII to do this. 29500b57cec5SDimitry Andric ConsumeToken(); 2951972a253aSDimitry Andric return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, 2952972a253aSDimitry Andric TemplateDiags); 29530b57cec5SDimitry Andric } 29540b57cec5SDimitry Andric 295581ad6265SDimitry Andric ParsedAttributes DeclAttrs(AttrFactory); 29560b57cec5SDimitry Andric // Optional C++11 attribute-specifier 295781ad6265SDimitry Andric MaybeParseCXX11Attributes(DeclAttrs); 2958fe6060f1SDimitry Andric 2959fe6060f1SDimitry Andric // The next token may be an OpenMP pragma annotation token. That would 2960fe6060f1SDimitry Andric // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in 2961fe6060f1SDimitry Andric // this case, it came from an *attribute* rather than a pragma. Handle it now. 2962fe6060f1SDimitry Andric if (Tok.is(tok::annot_attr_openmp)) 296381ad6265SDimitry Andric return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, DeclAttrs); 29640b57cec5SDimitry Andric 29650b57cec5SDimitry Andric if (Tok.is(tok::kw_using)) { 29660b57cec5SDimitry Andric // Eat 'using'. 29670b57cec5SDimitry Andric SourceLocation UsingLoc = ConsumeToken(); 29680b57cec5SDimitry Andric 29690b57cec5SDimitry Andric // Consume unexpected 'template' keywords. 29700b57cec5SDimitry Andric while (Tok.is(tok::kw_template)) { 29710b57cec5SDimitry Andric SourceLocation TemplateLoc = ConsumeToken(); 29720b57cec5SDimitry Andric Diag(TemplateLoc, diag::err_unexpected_template_after_using) 29730b57cec5SDimitry Andric << FixItHint::CreateRemoval(TemplateLoc); 29740b57cec5SDimitry Andric } 29750b57cec5SDimitry Andric 29760b57cec5SDimitry Andric if (Tok.is(tok::kw_namespace)) { 29770b57cec5SDimitry Andric Diag(UsingLoc, diag::err_using_namespace_in_class); 29780b57cec5SDimitry Andric SkipUntil(tok::semi, StopBeforeMatch); 29790b57cec5SDimitry Andric return nullptr; 29800b57cec5SDimitry Andric } 29810b57cec5SDimitry Andric SourceLocation DeclEnd; 29820b57cec5SDimitry Andric // Otherwise, it must be a using-declaration or an alias-declaration. 2983e8d8bef9SDimitry Andric return ParseUsingDeclaration(DeclaratorContext::Member, TemplateInfo, 298481ad6265SDimitry Andric UsingLoc, DeclEnd, DeclAttrs, AS); 29850b57cec5SDimitry Andric } 29860b57cec5SDimitry Andric 298781ad6265SDimitry Andric ParsedAttributes DeclSpecAttrs(AttrFactory); 298881ad6265SDimitry Andric MaybeParseMicrosoftAttributes(DeclSpecAttrs); 298981ad6265SDimitry Andric 29900b57cec5SDimitry Andric // Hold late-parsed attributes so we can attach a Decl to them later. 29910b57cec5SDimitry Andric LateParsedAttrList CommonLateParsedAttrs; 29920b57cec5SDimitry Andric 29930b57cec5SDimitry Andric // decl-specifier-seq: 29940b57cec5SDimitry Andric // Parse the common declaration-specifiers piece. 29950b57cec5SDimitry Andric ParsingDeclSpec DS(*this, TemplateDiags); 299681ad6265SDimitry Andric DS.takeAttributesFrom(DeclSpecAttrs); 299781ad6265SDimitry Andric 29980b57cec5SDimitry Andric if (MalformedTypeSpec) 29990b57cec5SDimitry Andric DS.SetTypeSpecError(); 30000b57cec5SDimitry Andric 3001349cc55cSDimitry Andric // Turn off usual access checking for templates explicit specialization 3002349cc55cSDimitry Andric // and instantiation. 3003349cc55cSDimitry Andric // C++20 [temp.spec] 13.9/6. 3004349cc55cSDimitry Andric // This disables the access checking rules for member function template 3005349cc55cSDimitry Andric // explicit instantiation and explicit specialization. 3006349cc55cSDimitry Andric bool IsTemplateSpecOrInst = 3007349cc55cSDimitry Andric (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || 3008349cc55cSDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); 3009349cc55cSDimitry Andric SuppressAccessChecks diagsFromTag(*this, IsTemplateSpecOrInst); 3010349cc55cSDimitry Andric 30110b57cec5SDimitry Andric ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class, 30120b57cec5SDimitry Andric &CommonLateParsedAttrs); 30130b57cec5SDimitry Andric 3014349cc55cSDimitry Andric if (IsTemplateSpecOrInst) 3015349cc55cSDimitry Andric diagsFromTag.done(); 3016349cc55cSDimitry Andric 30170b57cec5SDimitry Andric // Turn off colon protection that was set for declspec. 30180b57cec5SDimitry Andric X.restore(); 30190b57cec5SDimitry Andric 30200b57cec5SDimitry Andric // If we had a free-standing type definition with a missing semicolon, we 30210b57cec5SDimitry Andric // may get this far before the problem becomes obvious. 30220b57cec5SDimitry Andric if (DS.hasTagDefinition() && 30230b57cec5SDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate && 30240b57cec5SDimitry Andric DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class, 30250b57cec5SDimitry Andric &CommonLateParsedAttrs)) 30260b57cec5SDimitry Andric return nullptr; 30270b57cec5SDimitry Andric 30280b57cec5SDimitry Andric MultiTemplateParamsArg TemplateParams( 30290b57cec5SDimitry Andric TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() 30300b57cec5SDimitry Andric : nullptr, 30310b57cec5SDimitry Andric TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); 30320b57cec5SDimitry Andric 30330b57cec5SDimitry Andric if (TryConsumeToken(tok::semi)) { 30340b57cec5SDimitry Andric if (DS.isFriendSpecified()) 303581ad6265SDimitry Andric ProhibitAttributes(DeclAttrs); 30360b57cec5SDimitry Andric 30370b57cec5SDimitry Andric RecordDecl *AnonRecord = nullptr; 30380b57cec5SDimitry Andric Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( 303981ad6265SDimitry Andric getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord); 30405f757f3fSDimitry Andric Actions.ActOnDefinedDeclarationSpecifier(TheDecl); 30410b57cec5SDimitry Andric DS.complete(TheDecl); 30420b57cec5SDimitry Andric if (AnonRecord) { 30430b57cec5SDimitry Andric Decl *decls[] = {AnonRecord, TheDecl}; 30440b57cec5SDimitry Andric return Actions.BuildDeclaratorGroup(decls); 30450b57cec5SDimitry Andric } 30460b57cec5SDimitry Andric return Actions.ConvertDeclToDeclGroup(TheDecl); 30470b57cec5SDimitry Andric } 30480b57cec5SDimitry Andric 30495f757f3fSDimitry Andric if (DS.hasTagDefinition()) 30505f757f3fSDimitry Andric Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl()); 30515f757f3fSDimitry Andric 305281ad6265SDimitry Andric ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs, 305381ad6265SDimitry Andric DeclaratorContext::Member); 305455e4f9d5SDimitry Andric if (TemplateInfo.TemplateParams) 305555e4f9d5SDimitry Andric DeclaratorInfo.setTemplateParameterLists(TemplateParams); 30560b57cec5SDimitry Andric VirtSpecifiers VS; 30570b57cec5SDimitry Andric 30580b57cec5SDimitry Andric // Hold late-parsed attributes so we can attach a Decl to them later. 30590b57cec5SDimitry Andric LateParsedAttrList LateParsedAttrs; 30600b57cec5SDimitry Andric 30610b57cec5SDimitry Andric SourceLocation EqualLoc; 30620b57cec5SDimitry Andric SourceLocation PureSpecLoc; 30630b57cec5SDimitry Andric 30640b57cec5SDimitry Andric auto TryConsumePureSpecifier = [&](bool AllowDefinition) { 30650b57cec5SDimitry Andric if (Tok.isNot(tok::equal)) 30660b57cec5SDimitry Andric return false; 30670b57cec5SDimitry Andric 30680b57cec5SDimitry Andric auto &Zero = NextToken(); 30690b57cec5SDimitry Andric SmallString<8> Buffer; 30705ffd83dbSDimitry Andric if (Zero.isNot(tok::numeric_constant) || 30710b57cec5SDimitry Andric PP.getSpelling(Zero, Buffer) != "0") 30720b57cec5SDimitry Andric return false; 30730b57cec5SDimitry Andric 30740b57cec5SDimitry Andric auto &After = GetLookAheadToken(2); 30750b57cec5SDimitry Andric if (!After.isOneOf(tok::semi, tok::comma) && 30760b57cec5SDimitry Andric !(AllowDefinition && 30770b57cec5SDimitry Andric After.isOneOf(tok::l_brace, tok::colon, tok::kw_try))) 30780b57cec5SDimitry Andric return false; 30790b57cec5SDimitry Andric 30800b57cec5SDimitry Andric EqualLoc = ConsumeToken(); 30810b57cec5SDimitry Andric PureSpecLoc = ConsumeToken(); 30820b57cec5SDimitry Andric return true; 30830b57cec5SDimitry Andric }; 30840b57cec5SDimitry Andric 30850b57cec5SDimitry Andric SmallVector<Decl *, 8> DeclsInGroup; 30860b57cec5SDimitry Andric ExprResult BitfieldSize; 3087480093f4SDimitry Andric ExprResult TrailingRequiresClause; 30880b57cec5SDimitry Andric bool ExpectSemi = true; 30890b57cec5SDimitry Andric 3090349cc55cSDimitry Andric // C++20 [temp.spec] 13.9/6. 3091349cc55cSDimitry Andric // This disables the access checking rules for member function template 3092349cc55cSDimitry Andric // explicit instantiation and explicit specialization. 3093349cc55cSDimitry Andric SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst); 3094349cc55cSDimitry Andric 30950b57cec5SDimitry Andric // Parse the first declarator. 30960b57cec5SDimitry Andric if (ParseCXXMemberDeclaratorBeforeInitializer( 30970b57cec5SDimitry Andric DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) { 30980b57cec5SDimitry Andric TryConsumeToken(tok::semi); 30990b57cec5SDimitry Andric return nullptr; 31000b57cec5SDimitry Andric } 31010b57cec5SDimitry Andric 3102349cc55cSDimitry Andric if (IsTemplateSpecOrInst) 3103349cc55cSDimitry Andric SAC.done(); 3104349cc55cSDimitry Andric 31050b57cec5SDimitry Andric // Check for a member function definition. 31060b57cec5SDimitry Andric if (BitfieldSize.isUnset()) { 31070b57cec5SDimitry Andric // MSVC permits pure specifier on inline functions defined at class scope. 31080b57cec5SDimitry Andric // Hence check for =0 before checking for function definition. 31090b57cec5SDimitry Andric if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction()) 31100b57cec5SDimitry Andric TryConsumePureSpecifier(/*AllowDefinition*/ true); 31110b57cec5SDimitry Andric 3112e8d8bef9SDimitry Andric FunctionDefinitionKind DefinitionKind = FunctionDefinitionKind::Declaration; 31130b57cec5SDimitry Andric // function-definition: 31140b57cec5SDimitry Andric // 31150b57cec5SDimitry Andric // In C++11, a non-function declarator followed by an open brace is a 31160b57cec5SDimitry Andric // braced-init-list for an in-class member initialization, not an 31170b57cec5SDimitry Andric // erroneous function definition. 31180b57cec5SDimitry Andric if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) { 3119e8d8bef9SDimitry Andric DefinitionKind = FunctionDefinitionKind::Definition; 31200b57cec5SDimitry Andric } else if (DeclaratorInfo.isFunctionDeclarator()) { 31210b57cec5SDimitry Andric if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) { 3122e8d8bef9SDimitry Andric DefinitionKind = FunctionDefinitionKind::Definition; 31230b57cec5SDimitry Andric } else if (Tok.is(tok::equal)) { 31240b57cec5SDimitry Andric const Token &KW = NextToken(); 31250b57cec5SDimitry Andric if (KW.is(tok::kw_default)) 3126e8d8bef9SDimitry Andric DefinitionKind = FunctionDefinitionKind::Defaulted; 31270b57cec5SDimitry Andric else if (KW.is(tok::kw_delete)) 3128e8d8bef9SDimitry Andric DefinitionKind = FunctionDefinitionKind::Deleted; 31295ffd83dbSDimitry Andric else if (KW.is(tok::code_completion)) { 31305ffd83dbSDimitry Andric cutOffParsing(); 3131*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteAfterFunctionEquals( 3132*0fca6ea1SDimitry Andric DeclaratorInfo); 31335ffd83dbSDimitry Andric return nullptr; 31345ffd83dbSDimitry Andric } 31350b57cec5SDimitry Andric } 31360b57cec5SDimitry Andric } 31370b57cec5SDimitry Andric DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind); 31380b57cec5SDimitry Andric 31390b57cec5SDimitry Andric // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains 31400b57cec5SDimitry Andric // to a friend declaration, that declaration shall be a definition. 31410b57cec5SDimitry Andric if (DeclaratorInfo.isFunctionDeclarator() && 3142e8d8bef9SDimitry Andric DefinitionKind == FunctionDefinitionKind::Declaration && 3143e8d8bef9SDimitry Andric DS.isFriendSpecified()) { 31440b57cec5SDimitry Andric // Diagnose attributes that appear before decl specifier: 31450b57cec5SDimitry Andric // [[]] friend int foo(); 314681ad6265SDimitry Andric ProhibitAttributes(DeclAttrs); 31470b57cec5SDimitry Andric } 31480b57cec5SDimitry Andric 3149e8d8bef9SDimitry Andric if (DefinitionKind != FunctionDefinitionKind::Declaration) { 31500b57cec5SDimitry Andric if (!DeclaratorInfo.isFunctionDeclarator()) { 31510b57cec5SDimitry Andric Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params); 31520b57cec5SDimitry Andric ConsumeBrace(); 31530b57cec5SDimitry Andric SkipUntil(tok::r_brace); 31540b57cec5SDimitry Andric 31550b57cec5SDimitry Andric // Consume the optional ';' 31560b57cec5SDimitry Andric TryConsumeToken(tok::semi); 31570b57cec5SDimitry Andric 31580b57cec5SDimitry Andric return nullptr; 31590b57cec5SDimitry Andric } 31600b57cec5SDimitry Andric 31610b57cec5SDimitry Andric if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { 31620b57cec5SDimitry Andric Diag(DeclaratorInfo.getIdentifierLoc(), 31630b57cec5SDimitry Andric diag::err_function_declared_typedef); 31640b57cec5SDimitry Andric 31650b57cec5SDimitry Andric // Recover by treating the 'typedef' as spurious. 31660b57cec5SDimitry Andric DS.ClearStorageClassSpecs(); 31670b57cec5SDimitry Andric } 31680b57cec5SDimitry Andric 3169972a253aSDimitry Andric Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, 3170972a253aSDimitry Andric TemplateInfo, VS, PureSpecLoc); 31710b57cec5SDimitry Andric 31720b57cec5SDimitry Andric if (FunDecl) { 31730b57cec5SDimitry Andric for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { 31740b57cec5SDimitry Andric CommonLateParsedAttrs[i]->addDecl(FunDecl); 31750b57cec5SDimitry Andric } 31760b57cec5SDimitry Andric for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { 31770b57cec5SDimitry Andric LateParsedAttrs[i]->addDecl(FunDecl); 31780b57cec5SDimitry Andric } 31790b57cec5SDimitry Andric } 31800b57cec5SDimitry Andric LateParsedAttrs.clear(); 31810b57cec5SDimitry Andric 31820b57cec5SDimitry Andric // Consume the ';' - it's optional unless we have a delete or default 31830b57cec5SDimitry Andric if (Tok.is(tok::semi)) 31840b57cec5SDimitry Andric ConsumeExtraSemi(AfterMemberFunctionDefinition); 31850b57cec5SDimitry Andric 31860b57cec5SDimitry Andric return DeclGroupPtrTy::make(DeclGroupRef(FunDecl)); 31870b57cec5SDimitry Andric } 31880b57cec5SDimitry Andric } 31890b57cec5SDimitry Andric 31900b57cec5SDimitry Andric // member-declarator-list: 31910b57cec5SDimitry Andric // member-declarator 31920b57cec5SDimitry Andric // member-declarator-list ',' member-declarator 31930b57cec5SDimitry Andric 319404eeddc0SDimitry Andric while (true) { 31950b57cec5SDimitry Andric InClassInitStyle HasInClassInit = ICIS_NoInit; 31960b57cec5SDimitry Andric bool HasStaticInitializer = false; 31970b57cec5SDimitry Andric if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) { 3198e8d8bef9SDimitry Andric // DRXXXX: Anonymous bit-fields cannot have a brace-or-equal-initializer. 3199e8d8bef9SDimitry Andric if (BitfieldSize.isUsable() && !DeclaratorInfo.hasName()) { 3200e8d8bef9SDimitry Andric // Diagnose the error and pretend there is no in-class initializer. 3201e8d8bef9SDimitry Andric Diag(Tok, diag::err_anon_bitfield_member_init); 3202e8d8bef9SDimitry Andric SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); 3203e8d8bef9SDimitry Andric } else if (DeclaratorInfo.isDeclarationOfFunction()) { 32040b57cec5SDimitry Andric // It's a pure-specifier. 32050b57cec5SDimitry Andric if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false)) 32060b57cec5SDimitry Andric // Parse it as an expression so that Sema can diagnose it. 32070b57cec5SDimitry Andric HasStaticInitializer = true; 32080b57cec5SDimitry Andric } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() != 32090b57cec5SDimitry Andric DeclSpec::SCS_static && 32100b57cec5SDimitry Andric DeclaratorInfo.getDeclSpec().getStorageClassSpec() != 32110b57cec5SDimitry Andric DeclSpec::SCS_typedef && 3212*0fca6ea1SDimitry Andric !DS.isFriendSpecified() && 3213*0fca6ea1SDimitry Andric TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate) { 32140b57cec5SDimitry Andric // It's a default member initializer. 32150b57cec5SDimitry Andric if (BitfieldSize.get()) 32165ffd83dbSDimitry Andric Diag(Tok, getLangOpts().CPlusPlus20 32170b57cec5SDimitry Andric ? diag::warn_cxx17_compat_bitfield_member_init 32180b57cec5SDimitry Andric : diag::ext_bitfield_member_init); 32190b57cec5SDimitry Andric HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; 32200b57cec5SDimitry Andric } else { 32210b57cec5SDimitry Andric HasStaticInitializer = true; 32220b57cec5SDimitry Andric } 32230b57cec5SDimitry Andric } 32240b57cec5SDimitry Andric 32250b57cec5SDimitry Andric // NOTE: If Sema is the Action module and declarator is an instance field, 32260b57cec5SDimitry Andric // this call will *not* return the created decl; It will return null. 32270b57cec5SDimitry Andric // See Sema::ActOnCXXMemberDeclarator for details. 32280b57cec5SDimitry Andric 32290b57cec5SDimitry Andric NamedDecl *ThisDecl = nullptr; 32300b57cec5SDimitry Andric if (DS.isFriendSpecified()) { 32310b57cec5SDimitry Andric // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains 32320b57cec5SDimitry Andric // to a friend declaration, that declaration shall be a definition. 32330b57cec5SDimitry Andric // 32340b57cec5SDimitry Andric // Diagnose attributes that appear in a friend member function declarator: 32350b57cec5SDimitry Andric // friend int foo [[]] (); 323606c3fb27SDimitry Andric for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) 323706c3fb27SDimitry Andric if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) { 323806c3fb27SDimitry Andric auto Loc = AL.getRange().getBegin(); 323906c3fb27SDimitry Andric (AL.isRegularKeywordAttribute() 324006c3fb27SDimitry Andric ? Diag(Loc, diag::err_keyword_not_allowed) << AL 324106c3fb27SDimitry Andric : Diag(Loc, diag::err_attributes_not_allowed)) 324206c3fb27SDimitry Andric << AL.getRange(); 324306c3fb27SDimitry Andric } 32440b57cec5SDimitry Andric 32450b57cec5SDimitry Andric ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, 32460b57cec5SDimitry Andric TemplateParams); 32470b57cec5SDimitry Andric } else { 3248972a253aSDimitry Andric ThisDecl = Actions.ActOnCXXMemberDeclarator( 3249972a253aSDimitry Andric getCurScope(), AS, DeclaratorInfo, TemplateParams, BitfieldSize.get(), 32500b57cec5SDimitry Andric VS, HasInClassInit); 32510b57cec5SDimitry Andric 32520b57cec5SDimitry Andric if (VarTemplateDecl *VT = 32530b57cec5SDimitry Andric ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr) 32540b57cec5SDimitry Andric // Re-direct this decl to refer to the templated decl so that we can 32550b57cec5SDimitry Andric // initialize it. 32560b57cec5SDimitry Andric ThisDecl = VT->getTemplatedDecl(); 32570b57cec5SDimitry Andric 32580b57cec5SDimitry Andric if (ThisDecl) 32590b57cec5SDimitry Andric Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); 32600b57cec5SDimitry Andric } 32610b57cec5SDimitry Andric 32620b57cec5SDimitry Andric // Error recovery might have converted a non-static member into a static 32630b57cec5SDimitry Andric // member. 32640b57cec5SDimitry Andric if (HasInClassInit != ICIS_NoInit && 32650b57cec5SDimitry Andric DeclaratorInfo.getDeclSpec().getStorageClassSpec() == 32660b57cec5SDimitry Andric DeclSpec::SCS_static) { 32670b57cec5SDimitry Andric HasInClassInit = ICIS_NoInit; 32680b57cec5SDimitry Andric HasStaticInitializer = true; 32690b57cec5SDimitry Andric } 32700b57cec5SDimitry Andric 3271fe6060f1SDimitry Andric if (PureSpecLoc.isValid() && VS.getAbstractLoc().isValid()) { 3272fe6060f1SDimitry Andric Diag(PureSpecLoc, diag::err_duplicate_virt_specifier) << "abstract"; 3273fe6060f1SDimitry Andric } 32740b57cec5SDimitry Andric if (ThisDecl && PureSpecLoc.isValid()) 32750b57cec5SDimitry Andric Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc); 3276fe6060f1SDimitry Andric else if (ThisDecl && VS.getAbstractLoc().isValid()) 3277fe6060f1SDimitry Andric Actions.ActOnPureSpecifier(ThisDecl, VS.getAbstractLoc()); 32780b57cec5SDimitry Andric 32790b57cec5SDimitry Andric // Handle the initializer. 32800b57cec5SDimitry Andric if (HasInClassInit != ICIS_NoInit) { 32810b57cec5SDimitry Andric // The initializer was deferred; parse it and cache the tokens. 32820b57cec5SDimitry Andric Diag(Tok, getLangOpts().CPlusPlus11 32830b57cec5SDimitry Andric ? diag::warn_cxx98_compat_nonstatic_member_init 32840b57cec5SDimitry Andric : diag::ext_nonstatic_member_init); 32850b57cec5SDimitry Andric 32860b57cec5SDimitry Andric if (DeclaratorInfo.isArrayOfUnknownBound()) { 32870b57cec5SDimitry Andric // C++11 [dcl.array]p3: An array bound may also be omitted when the 32880b57cec5SDimitry Andric // declarator is followed by an initializer. 32890b57cec5SDimitry Andric // 32900b57cec5SDimitry Andric // A brace-or-equal-initializer for a member-declarator is not an 32910b57cec5SDimitry Andric // initializer in the grammar, so this is ill-formed. 32920b57cec5SDimitry Andric Diag(Tok, diag::err_incomplete_array_member_init); 32930b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); 32940b57cec5SDimitry Andric 32950b57cec5SDimitry Andric // Avoid later warnings about a class member of incomplete type. 32960b57cec5SDimitry Andric if (ThisDecl) 32970b57cec5SDimitry Andric ThisDecl->setInvalidDecl(); 32980b57cec5SDimitry Andric } else 32990b57cec5SDimitry Andric ParseCXXNonStaticMemberInitializer(ThisDecl); 33000b57cec5SDimitry Andric } else if (HasStaticInitializer) { 33010b57cec5SDimitry Andric // Normal initializer. 33020b57cec5SDimitry Andric ExprResult Init = ParseCXXMemberInitializer( 33030b57cec5SDimitry Andric ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); 33040b57cec5SDimitry Andric 3305349cc55cSDimitry Andric if (Init.isInvalid()) { 3306349cc55cSDimitry Andric if (ThisDecl) 3307349cc55cSDimitry Andric Actions.ActOnUninitializedDecl(ThisDecl); 33080b57cec5SDimitry Andric SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); 3309349cc55cSDimitry Andric } else if (ThisDecl) 3310972a253aSDimitry Andric Actions.AddInitializerToDecl(ThisDecl, Init.get(), 3311972a253aSDimitry Andric EqualLoc.isInvalid()); 3312*0fca6ea1SDimitry Andric } else if (ThisDecl && DeclaratorInfo.isStaticMember()) 33130b57cec5SDimitry Andric // No initializer. 33140b57cec5SDimitry Andric Actions.ActOnUninitializedDecl(ThisDecl); 33150b57cec5SDimitry Andric 33160b57cec5SDimitry Andric if (ThisDecl) { 33170b57cec5SDimitry Andric if (!ThisDecl->isInvalidDecl()) { 33180b57cec5SDimitry Andric // Set the Decl for any late parsed attributes 33190b57cec5SDimitry Andric for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) 33200b57cec5SDimitry Andric CommonLateParsedAttrs[i]->addDecl(ThisDecl); 33210b57cec5SDimitry Andric 33220b57cec5SDimitry Andric for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) 33230b57cec5SDimitry Andric LateParsedAttrs[i]->addDecl(ThisDecl); 33240b57cec5SDimitry Andric } 33250b57cec5SDimitry Andric Actions.FinalizeDeclaration(ThisDecl); 33260b57cec5SDimitry Andric DeclsInGroup.push_back(ThisDecl); 33270b57cec5SDimitry Andric 33280b57cec5SDimitry Andric if (DeclaratorInfo.isFunctionDeclarator() && 33290b57cec5SDimitry Andric DeclaratorInfo.getDeclSpec().getStorageClassSpec() != 33300b57cec5SDimitry Andric DeclSpec::SCS_typedef) 33310b57cec5SDimitry Andric HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl); 33320b57cec5SDimitry Andric } 33330b57cec5SDimitry Andric LateParsedAttrs.clear(); 33340b57cec5SDimitry Andric 33350b57cec5SDimitry Andric DeclaratorInfo.complete(ThisDecl); 33360b57cec5SDimitry Andric 33370b57cec5SDimitry Andric // If we don't have a comma, it is either the end of the list (a ';') 33380b57cec5SDimitry Andric // or an error, bail out. 33390b57cec5SDimitry Andric SourceLocation CommaLoc; 33400b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma, CommaLoc)) 33410b57cec5SDimitry Andric break; 33420b57cec5SDimitry Andric 33430b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && 3344e8d8bef9SDimitry Andric !MightBeDeclarator(DeclaratorContext::Member)) { 33450b57cec5SDimitry Andric // This comma was followed by a line-break and something which can't be 33460b57cec5SDimitry Andric // the start of a declarator. The comma was probably a typo for a 33470b57cec5SDimitry Andric // semicolon. 33480b57cec5SDimitry Andric Diag(CommaLoc, diag::err_expected_semi_declaration) 33490b57cec5SDimitry Andric << FixItHint::CreateReplacement(CommaLoc, ";"); 33500b57cec5SDimitry Andric ExpectSemi = false; 33510b57cec5SDimitry Andric break; 33520b57cec5SDimitry Andric } 33530b57cec5SDimitry Andric 3354*0fca6ea1SDimitry Andric // C++23 [temp.pre]p5: 3355*0fca6ea1SDimitry Andric // In a template-declaration, explicit specialization, or explicit 3356*0fca6ea1SDimitry Andric // instantiation the init-declarator-list in the declaration shall 3357*0fca6ea1SDimitry Andric // contain at most one declarator. 3358*0fca6ea1SDimitry Andric if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && 3359*0fca6ea1SDimitry Andric DeclaratorInfo.isFirstDeclarator()) { 3360*0fca6ea1SDimitry Andric Diag(CommaLoc, diag::err_multiple_template_declarators) 3361*0fca6ea1SDimitry Andric << TemplateInfo.Kind; 3362*0fca6ea1SDimitry Andric } 3363*0fca6ea1SDimitry Andric 33640b57cec5SDimitry Andric // Parse the next declarator. 33650b57cec5SDimitry Andric DeclaratorInfo.clear(); 33660b57cec5SDimitry Andric VS.clear(); 33670b57cec5SDimitry Andric BitfieldSize = ExprResult(/*Invalid=*/false); 33680b57cec5SDimitry Andric EqualLoc = PureSpecLoc = SourceLocation(); 33690b57cec5SDimitry Andric DeclaratorInfo.setCommaLoc(CommaLoc); 33700b57cec5SDimitry Andric 33710b57cec5SDimitry Andric // GNU attributes are allowed before the second and subsequent declarator. 3372e8d8bef9SDimitry Andric // However, this does not apply for [[]] attributes (which could show up 3373e8d8bef9SDimitry Andric // before or after the __attribute__ attributes). 3374e8d8bef9SDimitry Andric DiagnoseAndSkipCXX11Attributes(); 33750b57cec5SDimitry Andric MaybeParseGNUAttributes(DeclaratorInfo); 3376e8d8bef9SDimitry Andric DiagnoseAndSkipCXX11Attributes(); 33770b57cec5SDimitry Andric 33780b57cec5SDimitry Andric if (ParseCXXMemberDeclaratorBeforeInitializer( 33790b57cec5SDimitry Andric DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) 33800b57cec5SDimitry Andric break; 33810b57cec5SDimitry Andric } 33820b57cec5SDimitry Andric 33830b57cec5SDimitry Andric if (ExpectSemi && 33840b57cec5SDimitry Andric ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) { 33850b57cec5SDimitry Andric // Skip to end of block or statement. 33860b57cec5SDimitry Andric SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); 33870b57cec5SDimitry Andric // If we stopped at a ';', eat it. 33880b57cec5SDimitry Andric TryConsumeToken(tok::semi); 33890b57cec5SDimitry Andric return nullptr; 33900b57cec5SDimitry Andric } 33910b57cec5SDimitry Andric 33920b57cec5SDimitry Andric return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); 33930b57cec5SDimitry Andric } 33940b57cec5SDimitry Andric 33950b57cec5SDimitry Andric /// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer. 33960b57cec5SDimitry Andric /// Also detect and reject any attempted defaulted/deleted function definition. 33970b57cec5SDimitry Andric /// The location of the '=', if any, will be placed in EqualLoc. 33980b57cec5SDimitry Andric /// 33990b57cec5SDimitry Andric /// This does not check for a pure-specifier; that's handled elsewhere. 34000b57cec5SDimitry Andric /// 34010b57cec5SDimitry Andric /// brace-or-equal-initializer: 34020b57cec5SDimitry Andric /// '=' initializer-expression 34030b57cec5SDimitry Andric /// braced-init-list 34040b57cec5SDimitry Andric /// 34050b57cec5SDimitry Andric /// initializer-clause: 34060b57cec5SDimitry Andric /// assignment-expression 34070b57cec5SDimitry Andric /// braced-init-list 34080b57cec5SDimitry Andric /// 34090b57cec5SDimitry Andric /// defaulted/deleted function-definition: 34100b57cec5SDimitry Andric /// '=' 'default' 34110b57cec5SDimitry Andric /// '=' 'delete' 34120b57cec5SDimitry Andric /// 34130b57cec5SDimitry Andric /// Prior to C++0x, the assignment-expression in an initializer-clause must 34140b57cec5SDimitry Andric /// be a constant-expression. 34150b57cec5SDimitry Andric ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, 34160b57cec5SDimitry Andric SourceLocation &EqualLoc) { 3417972a253aSDimitry Andric assert(Tok.isOneOf(tok::equal, tok::l_brace) && 3418972a253aSDimitry Andric "Data member initializer not starting with '=' or '{'"); 34190b57cec5SDimitry Andric 34205f757f3fSDimitry Andric bool IsFieldInitialization = isa_and_present<FieldDecl>(D); 34215f757f3fSDimitry Andric 34220b57cec5SDimitry Andric EnterExpressionEvaluationContext Context( 3423bdd1243dSDimitry Andric Actions, 34245f757f3fSDimitry Andric IsFieldInitialization 3425bdd1243dSDimitry Andric ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed 3426bdd1243dSDimitry Andric : Sema::ExpressionEvaluationContext::PotentiallyEvaluated, 3427bdd1243dSDimitry Andric D); 34285f757f3fSDimitry Andric 34295f757f3fSDimitry Andric // CWG2760 34305f757f3fSDimitry Andric // Default member initializers used to initialize a base or member subobject 34315f757f3fSDimitry Andric // [...] are considered to be part of the function body 34325f757f3fSDimitry Andric Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext = 34335f757f3fSDimitry Andric IsFieldInitialization; 34345f757f3fSDimitry Andric 34350b57cec5SDimitry Andric if (TryConsumeToken(tok::equal, EqualLoc)) { 34360b57cec5SDimitry Andric if (Tok.is(tok::kw_delete)) { 34370b57cec5SDimitry Andric // In principle, an initializer of '= delete p;' is legal, but it will 3438972a253aSDimitry Andric // never type-check. It's better to diagnose it as an ill-formed 3439972a253aSDimitry Andric // expression than as an ill-formed deleted non-function member. An 3440972a253aSDimitry Andric // initializer of '= delete p, foo' will never be parsed, because a 3441972a253aSDimitry Andric // top-level comma always ends the initializer expression. 34420b57cec5SDimitry Andric const Token &Next = NextToken(); 34430b57cec5SDimitry Andric if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) { 34440b57cec5SDimitry Andric if (IsFunction) 34450b57cec5SDimitry Andric Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) 34460b57cec5SDimitry Andric << 1 /* delete */; 34470b57cec5SDimitry Andric else 34480b57cec5SDimitry Andric Diag(ConsumeToken(), diag::err_deleted_non_function); 3449*0fca6ea1SDimitry Andric SkipDeletedFunctionBody(); 34500b57cec5SDimitry Andric return ExprError(); 34510b57cec5SDimitry Andric } 34520b57cec5SDimitry Andric } else if (Tok.is(tok::kw_default)) { 34530b57cec5SDimitry Andric if (IsFunction) 34540b57cec5SDimitry Andric Diag(Tok, diag::err_default_delete_in_multiple_declaration) 34550b57cec5SDimitry Andric << 0 /* default */; 34560b57cec5SDimitry Andric else 3457480093f4SDimitry Andric Diag(ConsumeToken(), diag::err_default_special_members) 34585ffd83dbSDimitry Andric << getLangOpts().CPlusPlus20; 34590b57cec5SDimitry Andric return ExprError(); 34600b57cec5SDimitry Andric } 34610b57cec5SDimitry Andric } 34620b57cec5SDimitry Andric if (const auto *PD = dyn_cast_or_null<MSPropertyDecl>(D)) { 34630b57cec5SDimitry Andric Diag(Tok, diag::err_ms_property_initializer) << PD; 34640b57cec5SDimitry Andric return ExprError(); 34650b57cec5SDimitry Andric } 34660b57cec5SDimitry Andric return ParseInitializer(); 34670b57cec5SDimitry Andric } 34680b57cec5SDimitry Andric 34690b57cec5SDimitry Andric void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, 34700b57cec5SDimitry Andric SourceLocation AttrFixitLoc, 34710b57cec5SDimitry Andric unsigned TagType, Decl *TagDecl) { 34720b57cec5SDimitry Andric // Skip the optional 'final' keyword. 34730b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { 34740b57cec5SDimitry Andric assert(isCXX11FinalKeyword() && "not a class definition"); 34750b57cec5SDimitry Andric ConsumeToken(); 34760b57cec5SDimitry Andric 34770b57cec5SDimitry Andric // Diagnose any C++11 attributes after 'final' keyword. 34780b57cec5SDimitry Andric // We deliberately discard these attributes. 347981ad6265SDimitry Andric ParsedAttributes Attrs(AttrFactory); 34800b57cec5SDimitry Andric CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc); 34810b57cec5SDimitry Andric 34820b57cec5SDimitry Andric // This can only happen if we had malformed misplaced attributes; 34830b57cec5SDimitry Andric // we only get called if there is a colon or left-brace after the 34840b57cec5SDimitry Andric // attributes. 34850b57cec5SDimitry Andric if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace)) 34860b57cec5SDimitry Andric return; 34870b57cec5SDimitry Andric } 34880b57cec5SDimitry Andric 34890b57cec5SDimitry Andric // Skip the base clauses. This requires actually parsing them, because 34900b57cec5SDimitry Andric // otherwise we can't be sure where they end (a left brace may appear 34910b57cec5SDimitry Andric // within a template argument). 34920b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 34930b57cec5SDimitry Andric // Enter the scope of the class so that we can correctly parse its bases. 34940b57cec5SDimitry Andric ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); 34950b57cec5SDimitry Andric ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true, 34960b57cec5SDimitry Andric TagType == DeclSpec::TST_interface); 34970b57cec5SDimitry Andric auto OldContext = 34980b57cec5SDimitry Andric Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl); 34990b57cec5SDimitry Andric 35000b57cec5SDimitry Andric // Parse the bases but don't attach them to the class. 35010b57cec5SDimitry Andric ParseBaseClause(nullptr); 35020b57cec5SDimitry Andric 35030b57cec5SDimitry Andric Actions.ActOnTagFinishSkippedDefinition(OldContext); 35040b57cec5SDimitry Andric 35050b57cec5SDimitry Andric if (!Tok.is(tok::l_brace)) { 35060b57cec5SDimitry Andric Diag(PP.getLocForEndOfToken(PrevTokLocation), 35070b57cec5SDimitry Andric diag::err_expected_lbrace_after_base_specifiers); 35080b57cec5SDimitry Andric return; 35090b57cec5SDimitry Andric } 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric // Skip the body. 35130b57cec5SDimitry Andric assert(Tok.is(tok::l_brace)); 35140b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace); 35150b57cec5SDimitry Andric T.consumeOpen(); 35160b57cec5SDimitry Andric T.skipToEnd(); 35170b57cec5SDimitry Andric 35180b57cec5SDimitry Andric // Parse and discard any trailing attributes. 351981ad6265SDimitry Andric if (Tok.is(tok::kw___attribute)) { 35200b57cec5SDimitry Andric ParsedAttributes Attrs(AttrFactory); 35210b57cec5SDimitry Andric MaybeParseGNUAttributes(Attrs); 35220b57cec5SDimitry Andric } 352381ad6265SDimitry Andric } 35240b57cec5SDimitry Andric 35250b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( 352681ad6265SDimitry Andric AccessSpecifier &AS, ParsedAttributes &AccessAttrs, DeclSpec::TST TagType, 352781ad6265SDimitry Andric Decl *TagDecl) { 35280b57cec5SDimitry Andric ParenBraceBracketBalancer BalancerRAIIObj(*this); 35290b57cec5SDimitry Andric 35300b57cec5SDimitry Andric switch (Tok.getKind()) { 35310b57cec5SDimitry Andric case tok::kw___if_exists: 35320b57cec5SDimitry Andric case tok::kw___if_not_exists: 35330b57cec5SDimitry Andric ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS); 35340b57cec5SDimitry Andric return nullptr; 35350b57cec5SDimitry Andric 35360b57cec5SDimitry Andric case tok::semi: 35370b57cec5SDimitry Andric // Check for extraneous top-level semicolon. 35380b57cec5SDimitry Andric ConsumeExtraSemi(InsideStruct, TagType); 35390b57cec5SDimitry Andric return nullptr; 35400b57cec5SDimitry Andric 35410b57cec5SDimitry Andric // Handle pragmas that can appear as member declarations. 35420b57cec5SDimitry Andric case tok::annot_pragma_vis: 35430b57cec5SDimitry Andric HandlePragmaVisibility(); 35440b57cec5SDimitry Andric return nullptr; 35450b57cec5SDimitry Andric case tok::annot_pragma_pack: 35460b57cec5SDimitry Andric HandlePragmaPack(); 35470b57cec5SDimitry Andric return nullptr; 35480b57cec5SDimitry Andric case tok::annot_pragma_align: 35490b57cec5SDimitry Andric HandlePragmaAlign(); 35500b57cec5SDimitry Andric return nullptr; 35510b57cec5SDimitry Andric case tok::annot_pragma_ms_pointers_to_members: 35520b57cec5SDimitry Andric HandlePragmaMSPointersToMembers(); 35530b57cec5SDimitry Andric return nullptr; 35540b57cec5SDimitry Andric case tok::annot_pragma_ms_pragma: 35550b57cec5SDimitry Andric HandlePragmaMSPragma(); 35560b57cec5SDimitry Andric return nullptr; 35570b57cec5SDimitry Andric case tok::annot_pragma_ms_vtordisp: 35580b57cec5SDimitry Andric HandlePragmaMSVtorDisp(); 35590b57cec5SDimitry Andric return nullptr; 35600b57cec5SDimitry Andric case tok::annot_pragma_dump: 35610b57cec5SDimitry Andric HandlePragmaDump(); 35620b57cec5SDimitry Andric return nullptr; 35630b57cec5SDimitry Andric 35640b57cec5SDimitry Andric case tok::kw_namespace: 35650b57cec5SDimitry Andric // If we see a namespace here, a close brace was missing somewhere. 35660b57cec5SDimitry Andric DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); 35670b57cec5SDimitry Andric return nullptr; 35680b57cec5SDimitry Andric 35690b57cec5SDimitry Andric case tok::kw_private: 35700b57cec5SDimitry Andric // FIXME: We don't accept GNU attributes on access specifiers in OpenCL mode 35710b57cec5SDimitry Andric // yet. 3572*0fca6ea1SDimitry Andric if (getLangOpts().OpenCL && !NextToken().is(tok::colon)) { 3573*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo; 3574*0fca6ea1SDimitry Andric return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo); 3575*0fca6ea1SDimitry Andric } 3576bdd1243dSDimitry Andric [[fallthrough]]; 35770b57cec5SDimitry Andric case tok::kw_public: 35780b57cec5SDimitry Andric case tok::kw_protected: { 357981ad6265SDimitry Andric if (getLangOpts().HLSL) 358081ad6265SDimitry Andric Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers); 35810b57cec5SDimitry Andric AccessSpecifier NewAS = getAccessSpecifierIfPresent(); 35820b57cec5SDimitry Andric assert(NewAS != AS_none); 35830b57cec5SDimitry Andric // Current token is a C++ access specifier. 35840b57cec5SDimitry Andric AS = NewAS; 35850b57cec5SDimitry Andric SourceLocation ASLoc = Tok.getLocation(); 35860b57cec5SDimitry Andric unsigned TokLength = Tok.getLength(); 35870b57cec5SDimitry Andric ConsumeToken(); 35880b57cec5SDimitry Andric AccessAttrs.clear(); 35890b57cec5SDimitry Andric MaybeParseGNUAttributes(AccessAttrs); 35900b57cec5SDimitry Andric 35910b57cec5SDimitry Andric SourceLocation EndLoc; 35920b57cec5SDimitry Andric if (TryConsumeToken(tok::colon, EndLoc)) { 35930b57cec5SDimitry Andric } else if (TryConsumeToken(tok::semi, EndLoc)) { 35940b57cec5SDimitry Andric Diag(EndLoc, diag::err_expected) 35950b57cec5SDimitry Andric << tok::colon << FixItHint::CreateReplacement(EndLoc, ":"); 35960b57cec5SDimitry Andric } else { 35970b57cec5SDimitry Andric EndLoc = ASLoc.getLocWithOffset(TokLength); 35980b57cec5SDimitry Andric Diag(EndLoc, diag::err_expected) 35990b57cec5SDimitry Andric << tok::colon << FixItHint::CreateInsertion(EndLoc, ":"); 36000b57cec5SDimitry Andric } 36010b57cec5SDimitry Andric 36020b57cec5SDimitry Andric // The Microsoft extension __interface does not permit non-public 36030b57cec5SDimitry Andric // access specifiers. 36040b57cec5SDimitry Andric if (TagType == DeclSpec::TST_interface && AS != AS_public) { 36050b57cec5SDimitry Andric Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected); 36060b57cec5SDimitry Andric } 36070b57cec5SDimitry Andric 36080b57cec5SDimitry Andric if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) { 36090b57cec5SDimitry Andric // found another attribute than only annotations 36100b57cec5SDimitry Andric AccessAttrs.clear(); 36110b57cec5SDimitry Andric } 36120b57cec5SDimitry Andric 36130b57cec5SDimitry Andric return nullptr; 36140b57cec5SDimitry Andric } 36150b57cec5SDimitry Andric 3616fe6060f1SDimitry Andric case tok::annot_attr_openmp: 36170b57cec5SDimitry Andric case tok::annot_pragma_openmp: 3618480093f4SDimitry Andric return ParseOpenMPDeclarativeDirectiveWithExtDecl( 3619480093f4SDimitry Andric AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl); 36205f757f3fSDimitry Andric case tok::annot_pragma_openacc: 36215f757f3fSDimitry Andric return ParseOpenACCDirectiveDecl(); 36220b57cec5SDimitry Andric 36230b57cec5SDimitry Andric default: 3624a7dea167SDimitry Andric if (tok::isPragmaAnnotation(Tok.getKind())) { 3625a7dea167SDimitry Andric Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) 3626972a253aSDimitry Andric << DeclSpec::getSpecifierName( 3627972a253aSDimitry Andric TagType, Actions.getASTContext().getPrintingPolicy()); 3628a7dea167SDimitry Andric ConsumeAnnotationToken(); 3629a7dea167SDimitry Andric return nullptr; 3630a7dea167SDimitry Andric } 3631*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo; 3632*0fca6ea1SDimitry Andric return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo); 36330b57cec5SDimitry Andric } 36340b57cec5SDimitry Andric } 36350b57cec5SDimitry Andric 36360b57cec5SDimitry Andric /// ParseCXXMemberSpecification - Parse the class definition. 36370b57cec5SDimitry Andric /// 36380b57cec5SDimitry Andric /// member-specification: 36390b57cec5SDimitry Andric /// member-declaration member-specification[opt] 36400b57cec5SDimitry Andric /// access-specifier ':' member-specification[opt] 36410b57cec5SDimitry Andric /// 36420b57cec5SDimitry Andric void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, 36430b57cec5SDimitry Andric SourceLocation AttrFixitLoc, 364481ad6265SDimitry Andric ParsedAttributes &Attrs, 36450b57cec5SDimitry Andric unsigned TagType, Decl *TagDecl) { 36460b57cec5SDimitry Andric assert((TagType == DeclSpec::TST_struct || 36470b57cec5SDimitry Andric TagType == DeclSpec::TST_interface || 3648972a253aSDimitry Andric TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) && 3649972a253aSDimitry Andric "Invalid TagType!"); 36500b57cec5SDimitry Andric 36510b57cec5SDimitry Andric llvm::TimeTraceScope TimeScope("ParseClass", [&]() { 36520b57cec5SDimitry Andric if (auto *TD = dyn_cast_or_null<NamedDecl>(TagDecl)) 36530b57cec5SDimitry Andric return TD->getQualifiedNameAsString(); 36540b57cec5SDimitry Andric return std::string("<anonymous>"); 36550b57cec5SDimitry Andric }); 36560b57cec5SDimitry Andric 36570b57cec5SDimitry Andric PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, 36580b57cec5SDimitry Andric "parsing struct/union/class body"); 36590b57cec5SDimitry Andric 36600b57cec5SDimitry Andric // Determine whether this is a non-nested class. Note that local 36610b57cec5SDimitry Andric // classes are *not* considered to be nested classes. 36620b57cec5SDimitry Andric bool NonNestedClass = true; 36630b57cec5SDimitry Andric if (!ClassStack.empty()) { 36640b57cec5SDimitry Andric for (const Scope *S = getCurScope(); S; S = S->getParent()) { 36650b57cec5SDimitry Andric if (S->isClassScope()) { 36660b57cec5SDimitry Andric // We're inside a class scope, so this is a nested class. 36670b57cec5SDimitry Andric NonNestedClass = false; 36680b57cec5SDimitry Andric 36690b57cec5SDimitry Andric // The Microsoft extension __interface does not permit nested classes. 36700b57cec5SDimitry Andric if (getCurrentClass().IsInterface) { 36710b57cec5SDimitry Andric Diag(RecordLoc, diag::err_invalid_member_in_interface) 36720b57cec5SDimitry Andric << /*ErrorType=*/6 36730b57cec5SDimitry Andric << (isa<NamedDecl>(TagDecl) 36740b57cec5SDimitry Andric ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString() 36750b57cec5SDimitry Andric : "(anonymous)"); 36760b57cec5SDimitry Andric } 36770b57cec5SDimitry Andric break; 36780b57cec5SDimitry Andric } 36790b57cec5SDimitry Andric 368081ad6265SDimitry Andric if (S->isFunctionScope()) 36810b57cec5SDimitry Andric // If we're in a function or function template then this is a local 36820b57cec5SDimitry Andric // class rather than a nested class. 36830b57cec5SDimitry Andric break; 36840b57cec5SDimitry Andric } 36850b57cec5SDimitry Andric } 36860b57cec5SDimitry Andric 36870b57cec5SDimitry Andric // Enter a scope for the class. 36880b57cec5SDimitry Andric ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); 36890b57cec5SDimitry Andric 36900b57cec5SDimitry Andric // Note that we are parsing a new (potentially-nested) class definition. 36910b57cec5SDimitry Andric ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass, 36920b57cec5SDimitry Andric TagType == DeclSpec::TST_interface); 36930b57cec5SDimitry Andric 36940b57cec5SDimitry Andric if (TagDecl) 36950b57cec5SDimitry Andric Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); 36960b57cec5SDimitry Andric 36970b57cec5SDimitry Andric SourceLocation FinalLoc; 3698fe6060f1SDimitry Andric SourceLocation AbstractLoc; 36990b57cec5SDimitry Andric bool IsFinalSpelledSealed = false; 3700fe6060f1SDimitry Andric bool IsAbstract = false; 37010b57cec5SDimitry Andric 37020b57cec5SDimitry Andric // Parse the optional 'final' keyword. 37030b57cec5SDimitry Andric if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { 3704fe6060f1SDimitry Andric while (true) { 37050b57cec5SDimitry Andric VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok); 3706fe6060f1SDimitry Andric if (Specifier == VirtSpecifiers::VS_None) 3707fe6060f1SDimitry Andric break; 3708fe6060f1SDimitry Andric if (isCXX11FinalKeyword()) { 3709fe6060f1SDimitry Andric if (FinalLoc.isValid()) { 3710fe6060f1SDimitry Andric auto Skipped = ConsumeToken(); 3711fe6060f1SDimitry Andric Diag(Skipped, diag::err_duplicate_class_virt_specifier) 3712fe6060f1SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier); 3713fe6060f1SDimitry Andric } else { 37140b57cec5SDimitry Andric FinalLoc = ConsumeToken(); 3715fe6060f1SDimitry Andric if (Specifier == VirtSpecifiers::VS_Sealed) 3716fe6060f1SDimitry Andric IsFinalSpelledSealed = true; 3717fe6060f1SDimitry Andric } 3718fe6060f1SDimitry Andric } else { 3719fe6060f1SDimitry Andric if (AbstractLoc.isValid()) { 3720fe6060f1SDimitry Andric auto Skipped = ConsumeToken(); 3721fe6060f1SDimitry Andric Diag(Skipped, diag::err_duplicate_class_virt_specifier) 3722fe6060f1SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier); 3723fe6060f1SDimitry Andric } else { 3724fe6060f1SDimitry Andric AbstractLoc = ConsumeToken(); 3725fe6060f1SDimitry Andric IsAbstract = true; 3726fe6060f1SDimitry Andric } 3727fe6060f1SDimitry Andric } 37280b57cec5SDimitry Andric if (TagType == DeclSpec::TST_interface) 37290b57cec5SDimitry Andric Diag(FinalLoc, diag::err_override_control_interface) 37300b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier); 37310b57cec5SDimitry Andric else if (Specifier == VirtSpecifiers::VS_Final) 37320b57cec5SDimitry Andric Diag(FinalLoc, getLangOpts().CPlusPlus11 37330b57cec5SDimitry Andric ? diag::warn_cxx98_compat_override_control_keyword 37340b57cec5SDimitry Andric : diag::ext_override_control_keyword) 37350b57cec5SDimitry Andric << VirtSpecifiers::getSpecifierName(Specifier); 37360b57cec5SDimitry Andric else if (Specifier == VirtSpecifiers::VS_Sealed) 37370b57cec5SDimitry Andric Diag(FinalLoc, diag::ext_ms_sealed_keyword); 3738fe6060f1SDimitry Andric else if (Specifier == VirtSpecifiers::VS_Abstract) 3739fe6060f1SDimitry Andric Diag(AbstractLoc, diag::ext_ms_abstract_keyword); 37400b57cec5SDimitry Andric else if (Specifier == VirtSpecifiers::VS_GNU_Final) 37410b57cec5SDimitry Andric Diag(FinalLoc, diag::ext_warn_gnu_final); 3742fe6060f1SDimitry Andric } 3743fe6060f1SDimitry Andric assert((FinalLoc.isValid() || AbstractLoc.isValid()) && 3744fe6060f1SDimitry Andric "not a class definition"); 37450b57cec5SDimitry Andric 37460b57cec5SDimitry Andric // Parse any C++11 attributes after 'final' keyword. 37470b57cec5SDimitry Andric // These attributes are not allowed to appear here, 37480b57cec5SDimitry Andric // and the only possible place for them to appertain 37490b57cec5SDimitry Andric // to the class would be between class-key and class-name. 37500b57cec5SDimitry Andric CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc); 37510b57cec5SDimitry Andric 37520b57cec5SDimitry Andric // ParseClassSpecifier() does only a superficial check for attributes before 37530b57cec5SDimitry Andric // deciding to call this method. For example, for 37540b57cec5SDimitry Andric // `class C final alignas ([l) {` it will decide that this looks like a 37550b57cec5SDimitry Andric // misplaced attribute since it sees `alignas '(' ')'`. But the actual 37560b57cec5SDimitry Andric // attribute parsing code will try to parse the '[' as a constexpr lambda 37570b57cec5SDimitry Andric // and consume enough tokens that the alignas parsing code will eat the 37580b57cec5SDimitry Andric // opening '{'. So bail out if the next token isn't one we expect. 37590b57cec5SDimitry Andric if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace)) { 37600b57cec5SDimitry Andric if (TagDecl) 37610b57cec5SDimitry Andric Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); 37620b57cec5SDimitry Andric return; 37630b57cec5SDimitry Andric } 37640b57cec5SDimitry Andric } 37650b57cec5SDimitry Andric 37660b57cec5SDimitry Andric if (Tok.is(tok::colon)) { 37670b57cec5SDimitry Andric ParseScope InheritanceScope(this, getCurScope()->getFlags() | 37680b57cec5SDimitry Andric Scope::ClassInheritanceScope); 37690b57cec5SDimitry Andric 37700b57cec5SDimitry Andric ParseBaseClause(TagDecl); 37710b57cec5SDimitry Andric if (!Tok.is(tok::l_brace)) { 37720b57cec5SDimitry Andric bool SuggestFixIt = false; 37730b57cec5SDimitry Andric SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation); 37740b57cec5SDimitry Andric if (Tok.isAtStartOfLine()) { 37750b57cec5SDimitry Andric switch (Tok.getKind()) { 37760b57cec5SDimitry Andric case tok::kw_private: 37770b57cec5SDimitry Andric case tok::kw_protected: 37780b57cec5SDimitry Andric case tok::kw_public: 37790b57cec5SDimitry Andric SuggestFixIt = NextToken().getKind() == tok::colon; 37800b57cec5SDimitry Andric break; 37810b57cec5SDimitry Andric case tok::kw_static_assert: 37820b57cec5SDimitry Andric case tok::r_brace: 37830b57cec5SDimitry Andric case tok::kw_using: 37840b57cec5SDimitry Andric // base-clause can have simple-template-id; 'template' can't be there 37850b57cec5SDimitry Andric case tok::kw_template: 37860b57cec5SDimitry Andric SuggestFixIt = true; 37870b57cec5SDimitry Andric break; 37880b57cec5SDimitry Andric case tok::identifier: 37890b57cec5SDimitry Andric SuggestFixIt = isConstructorDeclarator(true); 37900b57cec5SDimitry Andric break; 37910b57cec5SDimitry Andric default: 37920b57cec5SDimitry Andric SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false); 37930b57cec5SDimitry Andric break; 37940b57cec5SDimitry Andric } 37950b57cec5SDimitry Andric } 37960b57cec5SDimitry Andric DiagnosticBuilder LBraceDiag = 37970b57cec5SDimitry Andric Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers); 37980b57cec5SDimitry Andric if (SuggestFixIt) { 37990b57cec5SDimitry Andric LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {"); 38000b57cec5SDimitry Andric // Try recovering from missing { after base-clause. 38010b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 38020b57cec5SDimitry Andric Tok.setKind(tok::l_brace); 38030b57cec5SDimitry Andric } else { 38040b57cec5SDimitry Andric if (TagDecl) 38050b57cec5SDimitry Andric Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); 38060b57cec5SDimitry Andric return; 38070b57cec5SDimitry Andric } 38080b57cec5SDimitry Andric } 38090b57cec5SDimitry Andric } 38100b57cec5SDimitry Andric 38110b57cec5SDimitry Andric assert(Tok.is(tok::l_brace)); 38120b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_brace); 38130b57cec5SDimitry Andric T.consumeOpen(); 38140b57cec5SDimitry Andric 38150b57cec5SDimitry Andric if (TagDecl) 38160b57cec5SDimitry Andric Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc, 3817fe6060f1SDimitry Andric IsFinalSpelledSealed, IsAbstract, 38180b57cec5SDimitry Andric T.getOpenLocation()); 38190b57cec5SDimitry Andric 38200b57cec5SDimitry Andric // C++ 11p3: Members of a class defined with the keyword class are private 38210b57cec5SDimitry Andric // by default. Members of a class defined with the keywords struct or union 38220b57cec5SDimitry Andric // are public by default. 382381ad6265SDimitry Andric // HLSL: In HLSL members of a class are public by default. 38240b57cec5SDimitry Andric AccessSpecifier CurAS; 382581ad6265SDimitry Andric if (TagType == DeclSpec::TST_class && !getLangOpts().HLSL) 38260b57cec5SDimitry Andric CurAS = AS_private; 38270b57cec5SDimitry Andric else 38280b57cec5SDimitry Andric CurAS = AS_public; 382981ad6265SDimitry Andric ParsedAttributes AccessAttrs(AttrFactory); 38300b57cec5SDimitry Andric 38310b57cec5SDimitry Andric if (TagDecl) { 38320b57cec5SDimitry Andric // While we still have something to read, read the member-declarations. 38330b57cec5SDimitry Andric while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && 38340b57cec5SDimitry Andric Tok.isNot(tok::eof)) { 38350b57cec5SDimitry Andric // Each iteration of this loop reads one member-declaration. 38360b57cec5SDimitry Andric ParseCXXClassMemberDeclarationWithPragmas( 38370b57cec5SDimitry Andric CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl); 38385ffd83dbSDimitry Andric MaybeDestroyTemplateIds(); 38390b57cec5SDimitry Andric } 38400b57cec5SDimitry Andric T.consumeClose(); 38410b57cec5SDimitry Andric } else { 38420b57cec5SDimitry Andric SkipUntil(tok::r_brace); 38430b57cec5SDimitry Andric } 38440b57cec5SDimitry Andric 38450b57cec5SDimitry Andric // If attributes exist after class contents, parse them. 38460b57cec5SDimitry Andric ParsedAttributes attrs(AttrFactory); 38470b57cec5SDimitry Andric MaybeParseGNUAttributes(attrs); 38480b57cec5SDimitry Andric 38490b57cec5SDimitry Andric if (TagDecl) 38500b57cec5SDimitry Andric Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl, 38510b57cec5SDimitry Andric T.getOpenLocation(), 38520b57cec5SDimitry Andric T.getCloseLocation(), attrs); 38530b57cec5SDimitry Andric 38540b57cec5SDimitry Andric // C++11 [class.mem]p2: 38550b57cec5SDimitry Andric // Within the class member-specification, the class is regarded as complete 38560b57cec5SDimitry Andric // within function bodies, default arguments, exception-specifications, and 38570b57cec5SDimitry Andric // brace-or-equal-initializers for non-static data members (including such 38580b57cec5SDimitry Andric // things in nested classes). 38590b57cec5SDimitry Andric if (TagDecl && NonNestedClass) { 38600b57cec5SDimitry Andric // We are not inside a nested class. This class and its nested classes 38610b57cec5SDimitry Andric // are complete and we can parse the delayed portions of method 38620b57cec5SDimitry Andric // declarations and the lexed inline method definitions, along with any 38630b57cec5SDimitry Andric // delayed attributes. 38645ffd83dbSDimitry Andric 38650b57cec5SDimitry Andric SourceLocation SavedPrevTokLocation = PrevTokLocation; 3866480093f4SDimitry Andric ParseLexedPragmas(getCurrentClass()); 38670b57cec5SDimitry Andric ParseLexedAttributes(getCurrentClass()); 38680b57cec5SDimitry Andric ParseLexedMethodDeclarations(getCurrentClass()); 38690b57cec5SDimitry Andric 38700b57cec5SDimitry Andric // We've finished with all pending member declarations. 38710b57cec5SDimitry Andric Actions.ActOnFinishCXXMemberDecls(); 38720b57cec5SDimitry Andric 38730b57cec5SDimitry Andric ParseLexedMemberInitializers(getCurrentClass()); 38740b57cec5SDimitry Andric ParseLexedMethodDefs(getCurrentClass()); 38750b57cec5SDimitry Andric PrevTokLocation = SavedPrevTokLocation; 38760b57cec5SDimitry Andric 38770b57cec5SDimitry Andric // We've finished parsing everything, including default argument 38780b57cec5SDimitry Andric // initializers. 3879480093f4SDimitry Andric Actions.ActOnFinishCXXNonNestedClass(); 38800b57cec5SDimitry Andric } 38810b57cec5SDimitry Andric 38820b57cec5SDimitry Andric if (TagDecl) 38830b57cec5SDimitry Andric Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); 38840b57cec5SDimitry Andric 38850b57cec5SDimitry Andric // Leave the class scope. 38860b57cec5SDimitry Andric ParsingDef.Pop(); 38870b57cec5SDimitry Andric ClassScope.Exit(); 38880b57cec5SDimitry Andric } 38890b57cec5SDimitry Andric 38900b57cec5SDimitry Andric void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) { 38910b57cec5SDimitry Andric assert(Tok.is(tok::kw_namespace)); 38920b57cec5SDimitry Andric 38930b57cec5SDimitry Andric // FIXME: Suggest where the close brace should have gone by looking 38940b57cec5SDimitry Andric // at indentation changes within the definition body. 3895972a253aSDimitry Andric Diag(D->getLocation(), diag::err_missing_end_of_definition) << D; 3896972a253aSDimitry Andric Diag(Tok.getLocation(), diag::note_missing_end_of_definition_before) << D; 38970b57cec5SDimitry Andric 38980b57cec5SDimitry Andric // Push '};' onto the token stream to recover. 38990b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 39000b57cec5SDimitry Andric 39010b57cec5SDimitry Andric Tok.startToken(); 39020b57cec5SDimitry Andric Tok.setLocation(PP.getLocForEndOfToken(PrevTokLocation)); 39030b57cec5SDimitry Andric Tok.setKind(tok::semi); 39040b57cec5SDimitry Andric PP.EnterToken(Tok, /*IsReinject*/ true); 39050b57cec5SDimitry Andric 39060b57cec5SDimitry Andric Tok.setKind(tok::r_brace); 39070b57cec5SDimitry Andric } 39080b57cec5SDimitry Andric 39090b57cec5SDimitry Andric /// ParseConstructorInitializer - Parse a C++ constructor initializer, 39100b57cec5SDimitry Andric /// which explicitly initializes the members or base classes of a 39110b57cec5SDimitry Andric /// class (C++ [class.base.init]). For example, the three initializers 39120b57cec5SDimitry Andric /// after the ':' in the Derived constructor below: 39130b57cec5SDimitry Andric /// 39140b57cec5SDimitry Andric /// @code 39150b57cec5SDimitry Andric /// class Base { }; 39160b57cec5SDimitry Andric /// class Derived : Base { 39170b57cec5SDimitry Andric /// int x; 39180b57cec5SDimitry Andric /// float f; 39190b57cec5SDimitry Andric /// public: 39200b57cec5SDimitry Andric /// Derived(float f) : Base(), x(17), f(f) { } 39210b57cec5SDimitry Andric /// }; 39220b57cec5SDimitry Andric /// @endcode 39230b57cec5SDimitry Andric /// 39240b57cec5SDimitry Andric /// [C++] ctor-initializer: 39250b57cec5SDimitry Andric /// ':' mem-initializer-list 39260b57cec5SDimitry Andric /// 39270b57cec5SDimitry Andric /// [C++] mem-initializer-list: 39280b57cec5SDimitry Andric /// mem-initializer ...[opt] 39290b57cec5SDimitry Andric /// mem-initializer ...[opt] , mem-initializer-list 39300b57cec5SDimitry Andric void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { 39310b57cec5SDimitry Andric assert(Tok.is(tok::colon) && 39320b57cec5SDimitry Andric "Constructor initializer always starts with ':'"); 39330b57cec5SDimitry Andric 39340b57cec5SDimitry Andric // Poison the SEH identifiers so they are flagged as illegal in constructor 39350b57cec5SDimitry Andric // initializers. 39360b57cec5SDimitry Andric PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); 39370b57cec5SDimitry Andric SourceLocation ColonLoc = ConsumeToken(); 39380b57cec5SDimitry Andric 39390b57cec5SDimitry Andric SmallVector<CXXCtorInitializer *, 4> MemInitializers; 39400b57cec5SDimitry Andric bool AnyErrors = false; 39410b57cec5SDimitry Andric 39420b57cec5SDimitry Andric do { 39430b57cec5SDimitry Andric if (Tok.is(tok::code_completion)) { 3944fe6060f1SDimitry Andric cutOffParsing(); 3945*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteConstructorInitializer( 3946*0fca6ea1SDimitry Andric ConstructorDecl, MemInitializers); 3947fe6060f1SDimitry Andric return; 39480b57cec5SDimitry Andric } 39490b57cec5SDimitry Andric 39500b57cec5SDimitry Andric MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); 39510b57cec5SDimitry Andric if (!MemInit.isInvalid()) 39520b57cec5SDimitry Andric MemInitializers.push_back(MemInit.get()); 39530b57cec5SDimitry Andric else 39540b57cec5SDimitry Andric AnyErrors = true; 39550b57cec5SDimitry Andric 39560b57cec5SDimitry Andric if (Tok.is(tok::comma)) 39570b57cec5SDimitry Andric ConsumeToken(); 39580b57cec5SDimitry Andric else if (Tok.is(tok::l_brace)) 39590b57cec5SDimitry Andric break; 39600b57cec5SDimitry Andric // If the previous initializer was valid and the next token looks like a 39610b57cec5SDimitry Andric // base or member initializer, assume that we're just missing a comma. 39620b57cec5SDimitry Andric else if (!MemInit.isInvalid() && 39630b57cec5SDimitry Andric Tok.isOneOf(tok::identifier, tok::coloncolon)) { 39640b57cec5SDimitry Andric SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); 39650b57cec5SDimitry Andric Diag(Loc, diag::err_ctor_init_missing_comma) 39660b57cec5SDimitry Andric << FixItHint::CreateInsertion(Loc, ", "); 39670b57cec5SDimitry Andric } else { 39680b57cec5SDimitry Andric // Skip over garbage, until we get to '{'. Don't eat the '{'. 39690b57cec5SDimitry Andric if (!MemInit.isInvalid()) 3970972a253aSDimitry Andric Diag(Tok.getLocation(), diag::err_expected_either) 3971972a253aSDimitry Andric << tok::l_brace << tok::comma; 39720b57cec5SDimitry Andric SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); 39730b57cec5SDimitry Andric break; 39740b57cec5SDimitry Andric } 39750b57cec5SDimitry Andric } while (true); 39760b57cec5SDimitry Andric 39770b57cec5SDimitry Andric Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, MemInitializers, 39780b57cec5SDimitry Andric AnyErrors); 39790b57cec5SDimitry Andric } 39800b57cec5SDimitry Andric 39810b57cec5SDimitry Andric /// ParseMemInitializer - Parse a C++ member initializer, which is 39820b57cec5SDimitry Andric /// part of a constructor initializer that explicitly initializes one 39830b57cec5SDimitry Andric /// member or base class (C++ [class.base.init]). See 39840b57cec5SDimitry Andric /// ParseConstructorInitializer for an example. 39850b57cec5SDimitry Andric /// 39860b57cec5SDimitry Andric /// [C++] mem-initializer: 39870b57cec5SDimitry Andric /// mem-initializer-id '(' expression-list[opt] ')' 39880b57cec5SDimitry Andric /// [C++0x] mem-initializer-id braced-init-list 39890b57cec5SDimitry Andric /// 39900b57cec5SDimitry Andric /// [C++] mem-initializer-id: 39910b57cec5SDimitry Andric /// '::'[opt] nested-name-specifier[opt] class-name 39920b57cec5SDimitry Andric /// identifier 39930b57cec5SDimitry Andric MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { 39940b57cec5SDimitry Andric // parse '::'[opt] nested-name-specifier[opt] 39950b57cec5SDimitry Andric CXXScopeSpec SS; 39965ffd83dbSDimitry Andric if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 399704eeddc0SDimitry Andric /*ObjectHasErrors=*/false, 39985ffd83dbSDimitry Andric /*EnteringContext=*/false)) 39990b57cec5SDimitry Andric return true; 40000b57cec5SDimitry Andric 40010b57cec5SDimitry Andric // : identifier 40020b57cec5SDimitry Andric IdentifierInfo *II = nullptr; 40030b57cec5SDimitry Andric SourceLocation IdLoc = Tok.getLocation(); 40040b57cec5SDimitry Andric // : declype(...) 40050b57cec5SDimitry Andric DeclSpec DS(AttrFactory); 40060b57cec5SDimitry Andric // : template_name<...> 40075ffd83dbSDimitry Andric TypeResult TemplateTypeTy; 40080b57cec5SDimitry Andric 40090b57cec5SDimitry Andric if (Tok.is(tok::identifier)) { 40100b57cec5SDimitry Andric // Get the identifier. This may be a member name or a class name, 40110b57cec5SDimitry Andric // but we'll let the semantic analysis determine which it is. 40120b57cec5SDimitry Andric II = Tok.getIdentifierInfo(); 40130b57cec5SDimitry Andric ConsumeToken(); 40140b57cec5SDimitry Andric } else if (Tok.is(tok::annot_decltype)) { 40150b57cec5SDimitry Andric // Get the decltype expression, if there is one. 40160b57cec5SDimitry Andric // Uses of decltype will already have been converted to annot_decltype by 40170b57cec5SDimitry Andric // ParseOptionalCXXScopeSpecifier at this point. 40180b57cec5SDimitry Andric // FIXME: Can we get here with a scope specifier? 40190b57cec5SDimitry Andric ParseDecltypeSpecifier(DS); 4020*0fca6ea1SDimitry Andric } else if (Tok.is(tok::annot_pack_indexing_type)) { 4021*0fca6ea1SDimitry Andric // Uses of T...[N] will already have been converted to 4022*0fca6ea1SDimitry Andric // annot_pack_indexing_type by ParseOptionalCXXScopeSpecifier at this point. 4023*0fca6ea1SDimitry Andric ParsePackIndexingType(DS); 40240b57cec5SDimitry Andric } else { 40250b57cec5SDimitry Andric TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id) 40260b57cec5SDimitry Andric ? takeTemplateIdAnnotation(Tok) 40270b57cec5SDimitry Andric : nullptr; 40285ffd83dbSDimitry Andric if (TemplateId && TemplateId->mightBeType()) { 4029bdd1243dSDimitry Andric AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, 4030bdd1243dSDimitry Andric /*IsClassName=*/true); 40310b57cec5SDimitry Andric assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); 40320b57cec5SDimitry Andric TemplateTypeTy = getTypeAnnotation(Tok); 40330b57cec5SDimitry Andric ConsumeAnnotationToken(); 40340b57cec5SDimitry Andric } else { 40350b57cec5SDimitry Andric Diag(Tok, diag::err_expected_member_or_base_name); 40360b57cec5SDimitry Andric return true; 40370b57cec5SDimitry Andric } 40380b57cec5SDimitry Andric } 40390b57cec5SDimitry Andric 40400b57cec5SDimitry Andric // Parse the '('. 40410b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 40420b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 40430b57cec5SDimitry Andric 40440b57cec5SDimitry Andric // FIXME: Add support for signature help inside initializer lists. 40450b57cec5SDimitry Andric ExprResult InitList = ParseBraceInitializer(); 40460b57cec5SDimitry Andric if (InitList.isInvalid()) 40470b57cec5SDimitry Andric return true; 40480b57cec5SDimitry Andric 40490b57cec5SDimitry Andric SourceLocation EllipsisLoc; 40500b57cec5SDimitry Andric TryConsumeToken(tok::ellipsis, EllipsisLoc); 40510b57cec5SDimitry Andric 40525ffd83dbSDimitry Andric if (TemplateTypeTy.isInvalid()) 40535ffd83dbSDimitry Andric return true; 40540b57cec5SDimitry Andric return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, 40555ffd83dbSDimitry Andric TemplateTypeTy.get(), DS, IdLoc, 40560b57cec5SDimitry Andric InitList.get(), EllipsisLoc); 40570b57cec5SDimitry Andric } else if (Tok.is(tok::l_paren)) { 40580b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 40590b57cec5SDimitry Andric T.consumeOpen(); 40600b57cec5SDimitry Andric 40610b57cec5SDimitry Andric // Parse the optional expression-list. 40620b57cec5SDimitry Andric ExprVector ArgExprs; 40630b57cec5SDimitry Andric auto RunSignatureHelp = [&] { 40645ffd83dbSDimitry Andric if (TemplateTypeTy.isInvalid()) 40655ffd83dbSDimitry Andric return QualType(); 4066*0fca6ea1SDimitry Andric QualType PreferredType = 4067*0fca6ea1SDimitry Andric Actions.CodeCompletion().ProduceCtorInitMemberSignatureHelp( 406804eeddc0SDimitry Andric ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II, 406904eeddc0SDimitry Andric T.getOpenLocation(), /*Braced=*/false); 40700b57cec5SDimitry Andric CalledSignatureHelp = true; 40710b57cec5SDimitry Andric return PreferredType; 40720b57cec5SDimitry Andric }; 4073bdd1243dSDimitry Andric if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, [&] { 40740b57cec5SDimitry Andric PreferredType.enterFunctionArgument(Tok.getLocation(), 40750b57cec5SDimitry Andric RunSignatureHelp); 40760b57cec5SDimitry Andric })) { 40770b57cec5SDimitry Andric if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 40780b57cec5SDimitry Andric RunSignatureHelp(); 40790b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 40800b57cec5SDimitry Andric return true; 40810b57cec5SDimitry Andric } 40820b57cec5SDimitry Andric 40830b57cec5SDimitry Andric T.consumeClose(); 40840b57cec5SDimitry Andric 40850b57cec5SDimitry Andric SourceLocation EllipsisLoc; 40860b57cec5SDimitry Andric TryConsumeToken(tok::ellipsis, EllipsisLoc); 40870b57cec5SDimitry Andric 40885ffd83dbSDimitry Andric if (TemplateTypeTy.isInvalid()) 40895ffd83dbSDimitry Andric return true; 4090972a253aSDimitry Andric return Actions.ActOnMemInitializer( 4091972a253aSDimitry Andric ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy.get(), DS, IdLoc, 4092972a253aSDimitry Andric T.getOpenLocation(), ArgExprs, T.getCloseLocation(), EllipsisLoc); 40930b57cec5SDimitry Andric } 40940b57cec5SDimitry Andric 40955ffd83dbSDimitry Andric if (TemplateTypeTy.isInvalid()) 40965ffd83dbSDimitry Andric return true; 40975ffd83dbSDimitry Andric 40980b57cec5SDimitry Andric if (getLangOpts().CPlusPlus11) 40990b57cec5SDimitry Andric return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace; 41000b57cec5SDimitry Andric else 41010b57cec5SDimitry Andric return Diag(Tok, diag::err_expected) << tok::l_paren; 41020b57cec5SDimitry Andric } 41030b57cec5SDimitry Andric 41040b57cec5SDimitry Andric /// Parse a C++ exception-specification if present (C++0x [except.spec]). 41050b57cec5SDimitry Andric /// 41060b57cec5SDimitry Andric /// exception-specification: 41070b57cec5SDimitry Andric /// dynamic-exception-specification 41080b57cec5SDimitry Andric /// noexcept-specification 41090b57cec5SDimitry Andric /// 41100b57cec5SDimitry Andric /// noexcept-specification: 41110b57cec5SDimitry Andric /// 'noexcept' 41120b57cec5SDimitry Andric /// 'noexcept' '(' constant-expression ')' 4113972a253aSDimitry Andric ExceptionSpecificationType Parser::tryParseExceptionSpecification( 4114972a253aSDimitry Andric bool Delayed, SourceRange &SpecificationRange, 41150b57cec5SDimitry Andric SmallVectorImpl<ParsedType> &DynamicExceptions, 41160b57cec5SDimitry Andric SmallVectorImpl<SourceRange> &DynamicExceptionRanges, 4117972a253aSDimitry Andric ExprResult &NoexceptExpr, CachedTokens *&ExceptionSpecTokens) { 41180b57cec5SDimitry Andric ExceptionSpecificationType Result = EST_None; 41190b57cec5SDimitry Andric ExceptionSpecTokens = nullptr; 41200b57cec5SDimitry Andric 41210b57cec5SDimitry Andric // Handle delayed parsing of exception-specifications. 41220b57cec5SDimitry Andric if (Delayed) { 41230b57cec5SDimitry Andric if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept)) 41240b57cec5SDimitry Andric return EST_None; 41250b57cec5SDimitry Andric 41260b57cec5SDimitry Andric // Consume and cache the starting token. 41270b57cec5SDimitry Andric bool IsNoexcept = Tok.is(tok::kw_noexcept); 41280b57cec5SDimitry Andric Token StartTok = Tok; 41290b57cec5SDimitry Andric SpecificationRange = SourceRange(ConsumeToken()); 41300b57cec5SDimitry Andric 41310b57cec5SDimitry Andric // Check for a '('. 41320b57cec5SDimitry Andric if (!Tok.is(tok::l_paren)) { 41330b57cec5SDimitry Andric // If this is a bare 'noexcept', we're done. 41340b57cec5SDimitry Andric if (IsNoexcept) { 41350b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); 41360b57cec5SDimitry Andric NoexceptExpr = nullptr; 41370b57cec5SDimitry Andric return EST_BasicNoexcept; 41380b57cec5SDimitry Andric } 41390b57cec5SDimitry Andric 41400b57cec5SDimitry Andric Diag(Tok, diag::err_expected_lparen_after) << "throw"; 41410b57cec5SDimitry Andric return EST_DynamicNone; 41420b57cec5SDimitry Andric } 41430b57cec5SDimitry Andric 41440b57cec5SDimitry Andric // Cache the tokens for the exception-specification. 41450b57cec5SDimitry Andric ExceptionSpecTokens = new CachedTokens; 41460b57cec5SDimitry Andric ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept' 41470b57cec5SDimitry Andric ExceptionSpecTokens->push_back(Tok); // '(' 41480b57cec5SDimitry Andric SpecificationRange.setEnd(ConsumeParen()); // '(' 41490b57cec5SDimitry Andric 41500b57cec5SDimitry Andric ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens, 41510b57cec5SDimitry Andric /*StopAtSemi=*/true, 41520b57cec5SDimitry Andric /*ConsumeFinalToken=*/true); 41530b57cec5SDimitry Andric SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation()); 41540b57cec5SDimitry Andric 41550b57cec5SDimitry Andric return EST_Unparsed; 41560b57cec5SDimitry Andric } 41570b57cec5SDimitry Andric 41580b57cec5SDimitry Andric // See if there's a dynamic specification. 41590b57cec5SDimitry Andric if (Tok.is(tok::kw_throw)) { 4160972a253aSDimitry Andric Result = ParseDynamicExceptionSpecification( 4161972a253aSDimitry Andric SpecificationRange, DynamicExceptions, DynamicExceptionRanges); 41620b57cec5SDimitry Andric assert(DynamicExceptions.size() == DynamicExceptionRanges.size() && 41630b57cec5SDimitry Andric "Produced different number of exception types and ranges."); 41640b57cec5SDimitry Andric } 41650b57cec5SDimitry Andric 41660b57cec5SDimitry Andric // If there's no noexcept specification, we're done. 41670b57cec5SDimitry Andric if (Tok.isNot(tok::kw_noexcept)) 41680b57cec5SDimitry Andric return Result; 41690b57cec5SDimitry Andric 41700b57cec5SDimitry Andric Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); 41710b57cec5SDimitry Andric 41720b57cec5SDimitry Andric // If we already had a dynamic specification, parse the noexcept for, 41730b57cec5SDimitry Andric // recovery, but emit a diagnostic and don't store the results. 41740b57cec5SDimitry Andric SourceRange NoexceptRange; 41750b57cec5SDimitry Andric ExceptionSpecificationType NoexceptType = EST_None; 41760b57cec5SDimitry Andric 41770b57cec5SDimitry Andric SourceLocation KeywordLoc = ConsumeToken(); 41780b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) { 41790b57cec5SDimitry Andric // There is an argument. 41800b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 41810b57cec5SDimitry Andric T.consumeOpen(); 41825f757f3fSDimitry Andric 41835f757f3fSDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 41845f757f3fSDimitry Andric Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); 41855f757f3fSDimitry Andric NoexceptExpr = ParseConstantExpressionInExprEvalContext(); 41865f757f3fSDimitry Andric 41870b57cec5SDimitry Andric T.consumeClose(); 41880b57cec5SDimitry Andric if (!NoexceptExpr.isInvalid()) { 4189972a253aSDimitry Andric NoexceptExpr = 4190972a253aSDimitry Andric Actions.ActOnNoexceptSpec(NoexceptExpr.get(), NoexceptType); 41910b57cec5SDimitry Andric NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); 41920b57cec5SDimitry Andric } else { 41930b57cec5SDimitry Andric NoexceptType = EST_BasicNoexcept; 41940b57cec5SDimitry Andric } 41950b57cec5SDimitry Andric } else { 41960b57cec5SDimitry Andric // There is no argument. 41970b57cec5SDimitry Andric NoexceptType = EST_BasicNoexcept; 41980b57cec5SDimitry Andric NoexceptRange = SourceRange(KeywordLoc, KeywordLoc); 41990b57cec5SDimitry Andric } 42000b57cec5SDimitry Andric 42010b57cec5SDimitry Andric if (Result == EST_None) { 42020b57cec5SDimitry Andric SpecificationRange = NoexceptRange; 42030b57cec5SDimitry Andric Result = NoexceptType; 42040b57cec5SDimitry Andric 42050b57cec5SDimitry Andric // If there's a dynamic specification after a noexcept specification, 42060b57cec5SDimitry Andric // parse that and ignore the results. 42070b57cec5SDimitry Andric if (Tok.is(tok::kw_throw)) { 42080b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification); 42090b57cec5SDimitry Andric ParseDynamicExceptionSpecification(NoexceptRange, DynamicExceptions, 42100b57cec5SDimitry Andric DynamicExceptionRanges); 42110b57cec5SDimitry Andric } 42120b57cec5SDimitry Andric } else { 42130b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification); 42140b57cec5SDimitry Andric } 42150b57cec5SDimitry Andric 42160b57cec5SDimitry Andric return Result; 42170b57cec5SDimitry Andric } 42180b57cec5SDimitry Andric 4219972a253aSDimitry Andric static void diagnoseDynamicExceptionSpecification(Parser &P, SourceRange Range, 4220972a253aSDimitry Andric bool IsNoexcept) { 42210b57cec5SDimitry Andric if (P.getLangOpts().CPlusPlus11) { 42220b57cec5SDimitry Andric const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)"; 4223972a253aSDimitry Andric P.Diag(Range.getBegin(), P.getLangOpts().CPlusPlus17 && !IsNoexcept 42240b57cec5SDimitry Andric ? diag::ext_dynamic_exception_spec 42250b57cec5SDimitry Andric : diag::warn_exception_spec_deprecated) 42260b57cec5SDimitry Andric << Range; 42270b57cec5SDimitry Andric P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated) 42280b57cec5SDimitry Andric << Replacement << FixItHint::CreateReplacement(Range, Replacement); 42290b57cec5SDimitry Andric } 42300b57cec5SDimitry Andric } 42310b57cec5SDimitry Andric 42320b57cec5SDimitry Andric /// ParseDynamicExceptionSpecification - Parse a C++ 42330b57cec5SDimitry Andric /// dynamic-exception-specification (C++ [except.spec]). 42340b57cec5SDimitry Andric /// 42350b57cec5SDimitry Andric /// dynamic-exception-specification: 42360b57cec5SDimitry Andric /// 'throw' '(' type-id-list [opt] ')' 42370b57cec5SDimitry Andric /// [MS] 'throw' '(' '...' ')' 42380b57cec5SDimitry Andric /// 42390b57cec5SDimitry Andric /// type-id-list: 42400b57cec5SDimitry Andric /// type-id ... [opt] 42410b57cec5SDimitry Andric /// type-id-list ',' type-id ... [opt] 42420b57cec5SDimitry Andric /// 42430b57cec5SDimitry Andric ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( 4244972a253aSDimitry Andric SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &Exceptions, 42450b57cec5SDimitry Andric SmallVectorImpl<SourceRange> &Ranges) { 42460b57cec5SDimitry Andric assert(Tok.is(tok::kw_throw) && "expected throw"); 42470b57cec5SDimitry Andric 42480b57cec5SDimitry Andric SpecificationRange.setBegin(ConsumeToken()); 42490b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 42500b57cec5SDimitry Andric if (T.consumeOpen()) { 42510b57cec5SDimitry Andric Diag(Tok, diag::err_expected_lparen_after) << "throw"; 42520b57cec5SDimitry Andric SpecificationRange.setEnd(SpecificationRange.getBegin()); 42530b57cec5SDimitry Andric return EST_DynamicNone; 42540b57cec5SDimitry Andric } 42550b57cec5SDimitry Andric 42560b57cec5SDimitry Andric // Parse throw(...), a Microsoft extension that means "this function 42570b57cec5SDimitry Andric // can throw anything". 42580b57cec5SDimitry Andric if (Tok.is(tok::ellipsis)) { 42590b57cec5SDimitry Andric SourceLocation EllipsisLoc = ConsumeToken(); 42600b57cec5SDimitry Andric if (!getLangOpts().MicrosoftExt) 42610b57cec5SDimitry Andric Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec); 42620b57cec5SDimitry Andric T.consumeClose(); 42630b57cec5SDimitry Andric SpecificationRange.setEnd(T.getCloseLocation()); 42640b57cec5SDimitry Andric diagnoseDynamicExceptionSpecification(*this, SpecificationRange, false); 42650b57cec5SDimitry Andric return EST_MSAny; 42660b57cec5SDimitry Andric } 42670b57cec5SDimitry Andric 42680b57cec5SDimitry Andric // Parse the sequence of type-ids. 42690b57cec5SDimitry Andric SourceRange Range; 42700b57cec5SDimitry Andric while (Tok.isNot(tok::r_paren)) { 42710b57cec5SDimitry Andric TypeResult Res(ParseTypeName(&Range)); 42720b57cec5SDimitry Andric 42730b57cec5SDimitry Andric if (Tok.is(tok::ellipsis)) { 42740b57cec5SDimitry Andric // C++0x [temp.variadic]p5: 42750b57cec5SDimitry Andric // - In a dynamic-exception-specification (15.4); the pattern is a 42760b57cec5SDimitry Andric // type-id. 42770b57cec5SDimitry Andric SourceLocation Ellipsis = ConsumeToken(); 42780b57cec5SDimitry Andric Range.setEnd(Ellipsis); 42790b57cec5SDimitry Andric if (!Res.isInvalid()) 42800b57cec5SDimitry Andric Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis); 42810b57cec5SDimitry Andric } 42820b57cec5SDimitry Andric 42830b57cec5SDimitry Andric if (!Res.isInvalid()) { 42840b57cec5SDimitry Andric Exceptions.push_back(Res.get()); 42850b57cec5SDimitry Andric Ranges.push_back(Range); 42860b57cec5SDimitry Andric } 42870b57cec5SDimitry Andric 42880b57cec5SDimitry Andric if (!TryConsumeToken(tok::comma)) 42890b57cec5SDimitry Andric break; 42900b57cec5SDimitry Andric } 42910b57cec5SDimitry Andric 42920b57cec5SDimitry Andric T.consumeClose(); 42930b57cec5SDimitry Andric SpecificationRange.setEnd(T.getCloseLocation()); 42940b57cec5SDimitry Andric diagnoseDynamicExceptionSpecification(*this, SpecificationRange, 42950b57cec5SDimitry Andric Exceptions.empty()); 42960b57cec5SDimitry Andric return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic; 42970b57cec5SDimitry Andric } 42980b57cec5SDimitry Andric 42990b57cec5SDimitry Andric /// ParseTrailingReturnType - Parse a trailing return type on a new-style 43000b57cec5SDimitry Andric /// function declaration. 43010b57cec5SDimitry Andric TypeResult Parser::ParseTrailingReturnType(SourceRange &Range, 43020b57cec5SDimitry Andric bool MayBeFollowedByDirectInit) { 43030b57cec5SDimitry Andric assert(Tok.is(tok::arrow) && "expected arrow"); 43040b57cec5SDimitry Andric 43050b57cec5SDimitry Andric ConsumeToken(); 43060b57cec5SDimitry Andric 43070b57cec5SDimitry Andric return ParseTypeName(&Range, MayBeFollowedByDirectInit 4308e8d8bef9SDimitry Andric ? DeclaratorContext::TrailingReturnVar 4309e8d8bef9SDimitry Andric : DeclaratorContext::TrailingReturn); 43100b57cec5SDimitry Andric } 43110b57cec5SDimitry Andric 4312480093f4SDimitry Andric /// Parse a requires-clause as part of a function declaration. 4313480093f4SDimitry Andric void Parser::ParseTrailingRequiresClause(Declarator &D) { 4314480093f4SDimitry Andric assert(Tok.is(tok::kw_requires) && "expected requires"); 4315480093f4SDimitry Andric 4316480093f4SDimitry Andric SourceLocation RequiresKWLoc = ConsumeToken(); 4317480093f4SDimitry Andric 4318*0fca6ea1SDimitry Andric // C++23 [basic.scope.namespace]p1: 4319*0fca6ea1SDimitry Andric // For each non-friend redeclaration or specialization whose target scope 4320*0fca6ea1SDimitry Andric // is or is contained by the scope, the portion after the declarator-id, 4321*0fca6ea1SDimitry Andric // class-head-name, or enum-head-name is also included in the scope. 4322*0fca6ea1SDimitry Andric // C++23 [basic.scope.class]p1: 4323*0fca6ea1SDimitry Andric // For each non-friend redeclaration or specialization whose target scope 4324*0fca6ea1SDimitry Andric // is or is contained by the scope, the portion after the declarator-id, 4325*0fca6ea1SDimitry Andric // class-head-name, or enum-head-name is also included in the scope. 4326*0fca6ea1SDimitry Andric // 4327*0fca6ea1SDimitry Andric // FIXME: We should really be calling ParseTrailingRequiresClause in 4328*0fca6ea1SDimitry Andric // ParseDirectDeclarator, when we are already in the declarator scope. 4329*0fca6ea1SDimitry Andric // This would also correctly suppress access checks for specializations 4330*0fca6ea1SDimitry Andric // and explicit instantiations, which we currently do not do. 4331*0fca6ea1SDimitry Andric CXXScopeSpec &SS = D.getCXXScopeSpec(); 4332*0fca6ea1SDimitry Andric DeclaratorScopeObj DeclScopeObj(*this, SS); 4333*0fca6ea1SDimitry Andric if (SS.isValid() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS)) 4334*0fca6ea1SDimitry Andric DeclScopeObj.EnterDeclaratorScope(); 4335*0fca6ea1SDimitry Andric 4336480093f4SDimitry Andric ExprResult TrailingRequiresClause; 4337972a253aSDimitry Andric ParseScope ParamScope(this, Scope::DeclScope | 4338480093f4SDimitry Andric Scope::FunctionDeclarationScope | 4339480093f4SDimitry Andric Scope::FunctionPrototypeScope); 4340480093f4SDimitry Andric 4341480093f4SDimitry Andric Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); 4342480093f4SDimitry Andric 4343bdd1243dSDimitry Andric std::optional<Sema::CXXThisScopeRAII> ThisScope; 4344480093f4SDimitry Andric InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope); 4345480093f4SDimitry Andric 4346480093f4SDimitry Andric TrailingRequiresClause = 4347480093f4SDimitry Andric ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true); 4348480093f4SDimitry Andric 4349480093f4SDimitry Andric TrailingRequiresClause = 4350480093f4SDimitry Andric Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause); 4351480093f4SDimitry Andric 4352480093f4SDimitry Andric if (!D.isDeclarationOfFunction()) { 4353480093f4SDimitry Andric Diag(RequiresKWLoc, 4354480093f4SDimitry Andric diag::err_requires_clause_on_declarator_not_declaring_a_function); 4355480093f4SDimitry Andric return; 4356480093f4SDimitry Andric } 4357480093f4SDimitry Andric 4358480093f4SDimitry Andric if (TrailingRequiresClause.isInvalid()) 4359480093f4SDimitry Andric SkipUntil({tok::l_brace, tok::arrow, tok::kw_try, tok::comma, tok::colon}, 4360480093f4SDimitry Andric StopAtSemi | StopBeforeMatch); 4361480093f4SDimitry Andric else 4362480093f4SDimitry Andric D.setTrailingRequiresClause(TrailingRequiresClause.get()); 4363480093f4SDimitry Andric 4364480093f4SDimitry Andric // Did the user swap the trailing return type and requires clause? 4365480093f4SDimitry Andric if (D.isFunctionDeclarator() && Tok.is(tok::arrow) && 4366480093f4SDimitry Andric D.getDeclSpec().getTypeSpecType() == TST_auto) { 4367480093f4SDimitry Andric SourceLocation ArrowLoc = Tok.getLocation(); 4368480093f4SDimitry Andric SourceRange Range; 4369480093f4SDimitry Andric TypeResult TrailingReturnType = 4370480093f4SDimitry Andric ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false); 4371480093f4SDimitry Andric 4372480093f4SDimitry Andric if (!TrailingReturnType.isInvalid()) { 4373480093f4SDimitry Andric Diag(ArrowLoc, 4374480093f4SDimitry Andric diag::err_requires_clause_must_appear_after_trailing_return) 4375480093f4SDimitry Andric << Range; 4376480093f4SDimitry Andric auto &FunctionChunk = D.getFunctionTypeInfo(); 4377480093f4SDimitry Andric FunctionChunk.HasTrailingReturnType = TrailingReturnType.isUsable(); 4378480093f4SDimitry Andric FunctionChunk.TrailingReturnType = TrailingReturnType.get(); 4379e8d8bef9SDimitry Andric FunctionChunk.TrailingReturnTypeLoc = Range.getBegin(); 4380480093f4SDimitry Andric } else 4381480093f4SDimitry Andric SkipUntil({tok::equal, tok::l_brace, tok::arrow, tok::kw_try, tok::comma}, 4382480093f4SDimitry Andric StopAtSemi | StopBeforeMatch); 4383480093f4SDimitry Andric } 4384480093f4SDimitry Andric } 4385480093f4SDimitry Andric 43860b57cec5SDimitry Andric /// We have just started parsing the definition of a new class, 43870b57cec5SDimitry Andric /// so push that class onto our stack of classes that is currently 43880b57cec5SDimitry Andric /// being parsed. 4389972a253aSDimitry Andric Sema::ParsingClassState Parser::PushParsingClass(Decl *ClassDecl, 4390972a253aSDimitry Andric bool NonNestedClass, 43910b57cec5SDimitry Andric bool IsInterface) { 43920b57cec5SDimitry Andric assert((NonNestedClass || !ClassStack.empty()) && 43930b57cec5SDimitry Andric "Nested class without outer class"); 43940b57cec5SDimitry Andric ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass, IsInterface)); 43950b57cec5SDimitry Andric return Actions.PushParsingClass(); 43960b57cec5SDimitry Andric } 43970b57cec5SDimitry Andric 43980b57cec5SDimitry Andric /// Deallocate the given parsed class and all of its nested 43990b57cec5SDimitry Andric /// classes. 44000b57cec5SDimitry Andric void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) { 44010b57cec5SDimitry Andric for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I) 44020b57cec5SDimitry Andric delete Class->LateParsedDeclarations[I]; 44030b57cec5SDimitry Andric delete Class; 44040b57cec5SDimitry Andric } 44050b57cec5SDimitry Andric 44060b57cec5SDimitry Andric /// Pop the top class of the stack of classes that are 44070b57cec5SDimitry Andric /// currently being parsed. 44080b57cec5SDimitry Andric /// 44090b57cec5SDimitry Andric /// This routine should be called when we have finished parsing the 44100b57cec5SDimitry Andric /// definition of a class, but have not yet popped the Scope 44110b57cec5SDimitry Andric /// associated with the class's definition. 44120b57cec5SDimitry Andric void Parser::PopParsingClass(Sema::ParsingClassState state) { 44130b57cec5SDimitry Andric assert(!ClassStack.empty() && "Mismatched push/pop for class parsing"); 44140b57cec5SDimitry Andric 44150b57cec5SDimitry Andric Actions.PopParsingClass(state); 44160b57cec5SDimitry Andric 44170b57cec5SDimitry Andric ParsingClass *Victim = ClassStack.top(); 44180b57cec5SDimitry Andric ClassStack.pop(); 44190b57cec5SDimitry Andric if (Victim->TopLevelClass) { 44200b57cec5SDimitry Andric // Deallocate all of the nested classes of this class, 44210b57cec5SDimitry Andric // recursively: we don't need to keep any of this information. 44220b57cec5SDimitry Andric DeallocateParsedClasses(Victim); 44230b57cec5SDimitry Andric return; 44240b57cec5SDimitry Andric } 44250b57cec5SDimitry Andric assert(!ClassStack.empty() && "Missing top-level class?"); 44260b57cec5SDimitry Andric 44270b57cec5SDimitry Andric if (Victim->LateParsedDeclarations.empty()) { 44280b57cec5SDimitry Andric // The victim is a nested class, but we will not need to perform 44290b57cec5SDimitry Andric // any processing after the definition of this class since it has 44300b57cec5SDimitry Andric // no members whose handling was delayed. Therefore, we can just 44310b57cec5SDimitry Andric // remove this nested class. 44320b57cec5SDimitry Andric DeallocateParsedClasses(Victim); 44330b57cec5SDimitry Andric return; 44340b57cec5SDimitry Andric } 44350b57cec5SDimitry Andric 44360b57cec5SDimitry Andric // This nested class has some members that will need to be processed 44370b57cec5SDimitry Andric // after the top-level class is completely defined. Therefore, add 44380b57cec5SDimitry Andric // it to the list of nested classes within its parent. 4439972a253aSDimitry Andric assert(getCurScope()->isClassScope() && 4440972a253aSDimitry Andric "Nested class outside of class scope?"); 44415ffd83dbSDimitry Andric ClassStack.top()->LateParsedDeclarations.push_back( 44425ffd83dbSDimitry Andric new LateParsedClass(this, Victim)); 44430b57cec5SDimitry Andric } 44440b57cec5SDimitry Andric 44450b57cec5SDimitry Andric /// Try to parse an 'identifier' which appears within an attribute-token. 44460b57cec5SDimitry Andric /// 44470b57cec5SDimitry Andric /// \return the parsed identifier on success, and 0 if the next token is not an 44480b57cec5SDimitry Andric /// attribute-token. 44490b57cec5SDimitry Andric /// 44500b57cec5SDimitry Andric /// C++11 [dcl.attr.grammar]p3: 44510b57cec5SDimitry Andric /// If a keyword or an alternative token that satisfies the syntactic 44520b57cec5SDimitry Andric /// requirements of an identifier is contained in an attribute-token, 44530b57cec5SDimitry Andric /// it is considered an identifier. 4454*0fca6ea1SDimitry Andric IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier( 4455*0fca6ea1SDimitry Andric SourceLocation &Loc, SemaCodeCompletion::AttributeCompletion Completion, 4456349cc55cSDimitry Andric const IdentifierInfo *Scope) { 44570b57cec5SDimitry Andric switch (Tok.getKind()) { 44580b57cec5SDimitry Andric default: 44590b57cec5SDimitry Andric // Identifiers and keywords have identifier info attached. 44600b57cec5SDimitry Andric if (!Tok.isAnnotation()) { 44610b57cec5SDimitry Andric if (IdentifierInfo *II = Tok.getIdentifierInfo()) { 44620b57cec5SDimitry Andric Loc = ConsumeToken(); 44630b57cec5SDimitry Andric return II; 44640b57cec5SDimitry Andric } 44650b57cec5SDimitry Andric } 44660b57cec5SDimitry Andric return nullptr; 44670b57cec5SDimitry Andric 4468349cc55cSDimitry Andric case tok::code_completion: 4469349cc55cSDimitry Andric cutOffParsing(); 4470*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteAttribute( 4471*0fca6ea1SDimitry Andric getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C23, 4472349cc55cSDimitry Andric Completion, Scope); 4473349cc55cSDimitry Andric return nullptr; 4474349cc55cSDimitry Andric 44750b57cec5SDimitry Andric case tok::numeric_constant: { 44760b57cec5SDimitry Andric // If we got a numeric constant, check to see if it comes from a macro that 44770b57cec5SDimitry Andric // corresponds to the predefined __clang__ macro. If it does, warn the user 44780b57cec5SDimitry Andric // and recover by pretending they said _Clang instead. 44790b57cec5SDimitry Andric if (Tok.getLocation().isMacroID()) { 44800b57cec5SDimitry Andric SmallString<8> ExpansionBuf; 44810b57cec5SDimitry Andric SourceLocation ExpansionLoc = 44820b57cec5SDimitry Andric PP.getSourceManager().getExpansionLoc(Tok.getLocation()); 44830b57cec5SDimitry Andric StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf); 44840b57cec5SDimitry Andric if (Spelling == "__clang__") { 44850b57cec5SDimitry Andric SourceRange TokRange( 44860b57cec5SDimitry Andric ExpansionLoc, 44870b57cec5SDimitry Andric PP.getSourceManager().getExpansionLoc(Tok.getEndLoc())); 44880b57cec5SDimitry Andric Diag(Tok, diag::warn_wrong_clang_attr_namespace) 44890b57cec5SDimitry Andric << FixItHint::CreateReplacement(TokRange, "_Clang"); 44900b57cec5SDimitry Andric Loc = ConsumeToken(); 44910b57cec5SDimitry Andric return &PP.getIdentifierTable().get("_Clang"); 44920b57cec5SDimitry Andric } 44930b57cec5SDimitry Andric } 44940b57cec5SDimitry Andric return nullptr; 44950b57cec5SDimitry Andric } 44960b57cec5SDimitry Andric 44970b57cec5SDimitry Andric case tok::ampamp: // 'and' 44980b57cec5SDimitry Andric case tok::pipe: // 'bitor' 44990b57cec5SDimitry Andric case tok::pipepipe: // 'or' 45000b57cec5SDimitry Andric case tok::caret: // 'xor' 45010b57cec5SDimitry Andric case tok::tilde: // 'compl' 45020b57cec5SDimitry Andric case tok::amp: // 'bitand' 45030b57cec5SDimitry Andric case tok::ampequal: // 'and_eq' 45040b57cec5SDimitry Andric case tok::pipeequal: // 'or_eq' 45050b57cec5SDimitry Andric case tok::caretequal: // 'xor_eq' 45060b57cec5SDimitry Andric case tok::exclaim: // 'not' 45070b57cec5SDimitry Andric case tok::exclaimequal: // 'not_eq' 45080b57cec5SDimitry Andric // Alternative tokens do not have identifier info, but their spelling 45090b57cec5SDimitry Andric // starts with an alphabetical character. 45100b57cec5SDimitry Andric SmallString<8> SpellingBuf; 45110b57cec5SDimitry Andric SourceLocation SpellingLoc = 45120b57cec5SDimitry Andric PP.getSourceManager().getSpellingLoc(Tok.getLocation()); 45130b57cec5SDimitry Andric StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf); 45140b57cec5SDimitry Andric if (isLetter(Spelling[0])) { 45150b57cec5SDimitry Andric Loc = ConsumeToken(); 45160b57cec5SDimitry Andric return &PP.getIdentifierTable().get(Spelling); 45170b57cec5SDimitry Andric } 45180b57cec5SDimitry Andric return nullptr; 45190b57cec5SDimitry Andric } 45200b57cec5SDimitry Andric } 45210b57cec5SDimitry Andric 45225f757f3fSDimitry Andric void Parser::ParseOpenMPAttributeArgs(const IdentifierInfo *AttrName, 4523fe6060f1SDimitry Andric CachedTokens &OpenMPTokens) { 4524fe6060f1SDimitry Andric // Both 'sequence' and 'directive' attributes require arguments, so parse the 4525fe6060f1SDimitry Andric // open paren for the argument list. 4526fe6060f1SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 4527fe6060f1SDimitry Andric if (T.consumeOpen()) { 4528fe6060f1SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren; 4529fe6060f1SDimitry Andric return; 4530fe6060f1SDimitry Andric } 4531fe6060f1SDimitry Andric 4532fe6060f1SDimitry Andric if (AttrName->isStr("directive")) { 4533fe6060f1SDimitry Andric // If the attribute is named `directive`, we can consume its argument list 4534fe6060f1SDimitry Andric // and push the tokens from it into the cached token stream for a new OpenMP 4535fe6060f1SDimitry Andric // pragma directive. 4536fe6060f1SDimitry Andric Token OMPBeginTok; 4537fe6060f1SDimitry Andric OMPBeginTok.startToken(); 4538fe6060f1SDimitry Andric OMPBeginTok.setKind(tok::annot_attr_openmp); 4539fe6060f1SDimitry Andric OMPBeginTok.setLocation(Tok.getLocation()); 4540fe6060f1SDimitry Andric OpenMPTokens.push_back(OMPBeginTok); 4541fe6060f1SDimitry Andric 4542fe6060f1SDimitry Andric ConsumeAndStoreUntil(tok::r_paren, OpenMPTokens, /*StopAtSemi=*/false, 4543fe6060f1SDimitry Andric /*ConsumeFinalToken*/ false); 4544fe6060f1SDimitry Andric Token OMPEndTok; 4545fe6060f1SDimitry Andric OMPEndTok.startToken(); 4546fe6060f1SDimitry Andric OMPEndTok.setKind(tok::annot_pragma_openmp_end); 4547fe6060f1SDimitry Andric OMPEndTok.setLocation(Tok.getLocation()); 4548fe6060f1SDimitry Andric OpenMPTokens.push_back(OMPEndTok); 4549fe6060f1SDimitry Andric } else { 4550fe6060f1SDimitry Andric assert(AttrName->isStr("sequence") && 4551fe6060f1SDimitry Andric "Expected either 'directive' or 'sequence'"); 4552fe6060f1SDimitry Andric // If the attribute is named 'sequence', its argument is a list of one or 4553fe6060f1SDimitry Andric // more OpenMP attributes (either 'omp::directive' or 'omp::sequence', 4554fe6060f1SDimitry Andric // where the 'omp::' is optional). 4555fe6060f1SDimitry Andric do { 4556fe6060f1SDimitry Andric // We expect to see one of the following: 4557fe6060f1SDimitry Andric // * An identifier (omp) for the attribute namespace followed by :: 4558fe6060f1SDimitry Andric // * An identifier (directive) or an identifier (sequence). 4559fe6060f1SDimitry Andric SourceLocation IdentLoc; 45605f757f3fSDimitry Andric const IdentifierInfo *Ident = TryParseCXX11AttributeIdentifier(IdentLoc); 4561fe6060f1SDimitry Andric 4562fe6060f1SDimitry Andric // If there is an identifier and it is 'omp', a double colon is required 4563fe6060f1SDimitry Andric // followed by the actual identifier we're after. 4564fe6060f1SDimitry Andric if (Ident && Ident->isStr("omp") && !ExpectAndConsume(tok::coloncolon)) 4565fe6060f1SDimitry Andric Ident = TryParseCXX11AttributeIdentifier(IdentLoc); 4566fe6060f1SDimitry Andric 4567fe6060f1SDimitry Andric // If we failed to find an identifier (scoped or otherwise), or we found 4568fe6060f1SDimitry Andric // an unexpected identifier, diagnose. 4569fe6060f1SDimitry Andric if (!Ident || (!Ident->isStr("directive") && !Ident->isStr("sequence"))) { 4570fe6060f1SDimitry Andric Diag(Tok.getLocation(), diag::err_expected_sequence_or_directive); 4571fe6060f1SDimitry Andric SkipUntil(tok::r_paren, StopBeforeMatch); 4572fe6060f1SDimitry Andric continue; 4573fe6060f1SDimitry Andric } 4574fe6060f1SDimitry Andric // We read an identifier. If the identifier is one of the ones we 4575fe6060f1SDimitry Andric // expected, we can recurse to parse the args. 4576fe6060f1SDimitry Andric ParseOpenMPAttributeArgs(Ident, OpenMPTokens); 4577fe6060f1SDimitry Andric 4578fe6060f1SDimitry Andric // There may be a comma to signal that we expect another directive in the 4579fe6060f1SDimitry Andric // sequence. 4580fe6060f1SDimitry Andric } while (TryConsumeToken(tok::comma)); 4581fe6060f1SDimitry Andric } 4582fe6060f1SDimitry Andric // Parse the closing paren for the argument list. 4583fe6060f1SDimitry Andric T.consumeClose(); 4584fe6060f1SDimitry Andric } 4585fe6060f1SDimitry Andric 45860b57cec5SDimitry Andric static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, 45870b57cec5SDimitry Andric IdentifierInfo *ScopeName) { 4588a7dea167SDimitry Andric switch ( 4589a7dea167SDimitry Andric ParsedAttr::getParsedKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { 45900b57cec5SDimitry Andric case ParsedAttr::AT_CarriesDependency: 45910b57cec5SDimitry Andric case ParsedAttr::AT_Deprecated: 45920b57cec5SDimitry Andric case ParsedAttr::AT_FallThrough: 45930b57cec5SDimitry Andric case ParsedAttr::AT_CXX11NoReturn: 45940b57cec5SDimitry Andric case ParsedAttr::AT_NoUniqueAddress: 4595e8d8bef9SDimitry Andric case ParsedAttr::AT_Likely: 4596e8d8bef9SDimitry Andric case ParsedAttr::AT_Unlikely: 45970b57cec5SDimitry Andric return true; 45980b57cec5SDimitry Andric case ParsedAttr::AT_WarnUnusedResult: 4599*0fca6ea1SDimitry Andric return !ScopeName && AttrName->getName() == "nodiscard"; 46000b57cec5SDimitry Andric case ParsedAttr::AT_Unused: 4601*0fca6ea1SDimitry Andric return !ScopeName && AttrName->getName() == "maybe_unused"; 46020b57cec5SDimitry Andric default: 46030b57cec5SDimitry Andric return false; 46040b57cec5SDimitry Andric } 46050b57cec5SDimitry Andric } 46060b57cec5SDimitry Andric 4607*0fca6ea1SDimitry Andric /// Parse the argument to C++23's [[assume()]] attribute. 4608*0fca6ea1SDimitry Andric bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, 4609*0fca6ea1SDimitry Andric IdentifierInfo *AttrName, 4610*0fca6ea1SDimitry Andric SourceLocation AttrNameLoc, 4611*0fca6ea1SDimitry Andric SourceLocation *EndLoc, 4612*0fca6ea1SDimitry Andric ParsedAttr::Form Form) { 4613*0fca6ea1SDimitry Andric assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); 4614*0fca6ea1SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 4615*0fca6ea1SDimitry Andric T.consumeOpen(); 4616*0fca6ea1SDimitry Andric 4617*0fca6ea1SDimitry Andric // [dcl.attr.assume]: The expression is potentially evaluated. 4618*0fca6ea1SDimitry Andric EnterExpressionEvaluationContext Unevaluated( 4619*0fca6ea1SDimitry Andric Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 4620*0fca6ea1SDimitry Andric 4621*0fca6ea1SDimitry Andric TentativeParsingAction TPA(*this); 4622*0fca6ea1SDimitry Andric ExprResult Res( 4623*0fca6ea1SDimitry Andric Actions.CorrectDelayedTyposInExpr(ParseConditionalExpression())); 4624*0fca6ea1SDimitry Andric if (Res.isInvalid()) { 4625*0fca6ea1SDimitry Andric TPA.Commit(); 4626*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::r_square, StopAtSemi | StopBeforeMatch); 4627*0fca6ea1SDimitry Andric if (Tok.is(tok::r_paren)) 4628*0fca6ea1SDimitry Andric T.consumeClose(); 4629*0fca6ea1SDimitry Andric return true; 4630*0fca6ea1SDimitry Andric } 4631*0fca6ea1SDimitry Andric 4632*0fca6ea1SDimitry Andric if (!Tok.isOneOf(tok::r_paren, tok::r_square)) { 4633*0fca6ea1SDimitry Andric // Emit a better diagnostic if this is an otherwise valid expression that 4634*0fca6ea1SDimitry Andric // is not allowed here. 4635*0fca6ea1SDimitry Andric TPA.Revert(); 4636*0fca6ea1SDimitry Andric Res = ParseExpression(); 4637*0fca6ea1SDimitry Andric if (!Res.isInvalid()) { 4638*0fca6ea1SDimitry Andric auto *E = Res.get(); 4639*0fca6ea1SDimitry Andric Diag(E->getExprLoc(), diag::err_assume_attr_expects_cond_expr) 4640*0fca6ea1SDimitry Andric << AttrName << FixItHint::CreateInsertion(E->getBeginLoc(), "(") 4641*0fca6ea1SDimitry Andric << FixItHint::CreateInsertion(PP.getLocForEndOfToken(E->getEndLoc()), 4642*0fca6ea1SDimitry Andric ")") 4643*0fca6ea1SDimitry Andric << E->getSourceRange(); 4644*0fca6ea1SDimitry Andric } 4645*0fca6ea1SDimitry Andric 4646*0fca6ea1SDimitry Andric T.consumeClose(); 4647*0fca6ea1SDimitry Andric return true; 4648*0fca6ea1SDimitry Andric } 4649*0fca6ea1SDimitry Andric 4650*0fca6ea1SDimitry Andric TPA.Commit(); 4651*0fca6ea1SDimitry Andric ArgsUnion Assumption = Res.get(); 4652*0fca6ea1SDimitry Andric auto RParen = Tok.getLocation(); 4653*0fca6ea1SDimitry Andric T.consumeClose(); 4654*0fca6ea1SDimitry Andric Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr, 4655*0fca6ea1SDimitry Andric SourceLocation(), &Assumption, 1, Form); 4656*0fca6ea1SDimitry Andric 4657*0fca6ea1SDimitry Andric if (EndLoc) 4658*0fca6ea1SDimitry Andric *EndLoc = RParen; 4659*0fca6ea1SDimitry Andric 4660*0fca6ea1SDimitry Andric return false; 4661*0fca6ea1SDimitry Andric } 4662*0fca6ea1SDimitry Andric 46630b57cec5SDimitry Andric /// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause. 46640b57cec5SDimitry Andric /// 46650b57cec5SDimitry Andric /// [C++11] attribute-argument-clause: 46660b57cec5SDimitry Andric /// '(' balanced-token-seq ')' 46670b57cec5SDimitry Andric /// 46680b57cec5SDimitry Andric /// [C++11] balanced-token-seq: 46690b57cec5SDimitry Andric /// balanced-token 46700b57cec5SDimitry Andric /// balanced-token-seq balanced-token 46710b57cec5SDimitry Andric /// 46720b57cec5SDimitry Andric /// [C++11] balanced-token: 46730b57cec5SDimitry Andric /// '(' balanced-token-seq ')' 46740b57cec5SDimitry Andric /// '[' balanced-token-seq ']' 46750b57cec5SDimitry Andric /// '{' balanced-token-seq '}' 46760b57cec5SDimitry Andric /// any token but '(', ')', '[', ']', '{', or '}' 4677972a253aSDimitry Andric bool Parser::ParseCXX11AttributeArgs( 4678972a253aSDimitry Andric IdentifierInfo *AttrName, SourceLocation AttrNameLoc, 4679972a253aSDimitry Andric ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, 4680972a253aSDimitry Andric SourceLocation ScopeLoc, CachedTokens &OpenMPTokens) { 46810b57cec5SDimitry Andric assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); 46820b57cec5SDimitry Andric SourceLocation LParenLoc = Tok.getLocation(); 46830b57cec5SDimitry Andric const LangOptions &LO = getLangOpts(); 468406c3fb27SDimitry Andric ParsedAttr::Form Form = 46855f757f3fSDimitry Andric LO.CPlusPlus ? ParsedAttr::Form::CXX11() : ParsedAttr::Form::C23(); 46860b57cec5SDimitry Andric 468781ad6265SDimitry Andric // Try parsing microsoft attributes 468881ad6265SDimitry Andric if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) { 468981ad6265SDimitry Andric if (hasAttribute(AttributeCommonInfo::Syntax::AS_Microsoft, ScopeName, 469081ad6265SDimitry Andric AttrName, getTargetInfo(), getLangOpts())) 469106c3fb27SDimitry Andric Form = ParsedAttr::Form::Microsoft(); 469281ad6265SDimitry Andric } 469381ad6265SDimitry Andric 46940b57cec5SDimitry Andric // If the attribute isn't known, we will not attempt to parse any 46950b57cec5SDimitry Andric // arguments. 469606c3fb27SDimitry Andric if (Form.getSyntax() != ParsedAttr::AS_Microsoft && 469781ad6265SDimitry Andric !hasAttribute(LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX11 46985f757f3fSDimitry Andric : AttributeCommonInfo::Syntax::AS_C23, 469981ad6265SDimitry Andric ScopeName, AttrName, getTargetInfo(), getLangOpts())) { 47000b57cec5SDimitry Andric // Eat the left paren, then skip to the ending right paren. 47010b57cec5SDimitry Andric ConsumeParen(); 47020b57cec5SDimitry Andric SkipUntil(tok::r_paren); 47030b57cec5SDimitry Andric return false; 47040b57cec5SDimitry Andric } 47050b57cec5SDimitry Andric 47060b57cec5SDimitry Andric if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) { 47070b57cec5SDimitry Andric // GNU-scoped attributes have some special cases to handle GNU-specific 47080b57cec5SDimitry Andric // behaviors. 47090b57cec5SDimitry Andric ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, 471006c3fb27SDimitry Andric ScopeLoc, Form, nullptr); 47110b57cec5SDimitry Andric return true; 47120b57cec5SDimitry Andric } 47130b57cec5SDimitry Andric 4714*0fca6ea1SDimitry Andric // [[omp::directive]] and [[omp::sequence]] need special handling. 4715*0fca6ea1SDimitry Andric if (ScopeName && ScopeName->isStr("omp") && 4716*0fca6ea1SDimitry Andric (AttrName->isStr("directive") || AttrName->isStr("sequence"))) { 4717fe6060f1SDimitry Andric Diag(AttrNameLoc, getLangOpts().OpenMP >= 51 4718fe6060f1SDimitry Andric ? diag::warn_omp51_compat_attributes 4719fe6060f1SDimitry Andric : diag::ext_omp_attributes); 4720fe6060f1SDimitry Andric 4721fe6060f1SDimitry Andric ParseOpenMPAttributeArgs(AttrName, OpenMPTokens); 4722fe6060f1SDimitry Andric 4723fe6060f1SDimitry Andric // We claim that an attribute was parsed and added so that one is not 4724fe6060f1SDimitry Andric // created for us by the caller. 4725fe6060f1SDimitry Andric return true; 4726fe6060f1SDimitry Andric } 4727fe6060f1SDimitry Andric 47280b57cec5SDimitry Andric unsigned NumArgs; 47290b57cec5SDimitry Andric // Some Clang-scoped attributes have some special parsing behavior. 47300b57cec5SDimitry Andric if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"))) 47310b57cec5SDimitry Andric NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, 473206c3fb27SDimitry Andric ScopeName, ScopeLoc, Form); 4733*0fca6ea1SDimitry Andric // So does C++23's assume() attribute. 4734*0fca6ea1SDimitry Andric else if (!ScopeName && AttrName->isStr("assume")) { 4735*0fca6ea1SDimitry Andric if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form)) 4736*0fca6ea1SDimitry Andric return true; 4737*0fca6ea1SDimitry Andric NumArgs = 1; 4738*0fca6ea1SDimitry Andric } else 4739972a253aSDimitry Andric NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, 474006c3fb27SDimitry Andric ScopeName, ScopeLoc, Form); 47410b57cec5SDimitry Andric 47420b57cec5SDimitry Andric if (!Attrs.empty() && 47430b57cec5SDimitry Andric IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { 47440b57cec5SDimitry Andric ParsedAttr &Attr = Attrs.back(); 47455f757f3fSDimitry Andric 47465f757f3fSDimitry Andric // Ignore attributes that don't exist for the target. 47475f757f3fSDimitry Andric if (!Attr.existsInTarget(getTargetInfo())) { 47485f757f3fSDimitry Andric Diag(LParenLoc, diag::warn_unknown_attribute_ignored) << AttrName; 47495f757f3fSDimitry Andric Attr.setInvalid(true); 47505f757f3fSDimitry Andric return true; 47515f757f3fSDimitry Andric } 47525f757f3fSDimitry Andric 47530b57cec5SDimitry Andric // If the attribute is a standard or built-in attribute and we are 47540b57cec5SDimitry Andric // parsing an argument list, we need to determine whether this attribute 47550b57cec5SDimitry Andric // was allowed to have an argument list (such as [[deprecated]]), and how 47560b57cec5SDimitry Andric // many arguments were parsed (so we can diagnose on [[deprecated()]]). 47570b57cec5SDimitry Andric if (Attr.getMaxArgs() && !NumArgs) { 47580b57cec5SDimitry Andric // The attribute was allowed to have arguments, but none were provided 47590b57cec5SDimitry Andric // even though the attribute parsed successfully. This is an error. 47600b57cec5SDimitry Andric Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; 47610b57cec5SDimitry Andric Attr.setInvalid(true); 47620b57cec5SDimitry Andric } else if (!Attr.getMaxArgs()) { 47630b57cec5SDimitry Andric // The attribute parsed successfully, but was not allowed to have any 47640b57cec5SDimitry Andric // arguments. It doesn't matter whether any were provided -- the 47650b57cec5SDimitry Andric // presence of the argument list (even if empty) is diagnosed. 47660b57cec5SDimitry Andric Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) 47670b57cec5SDimitry Andric << AttrName 47680b57cec5SDimitry Andric << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); 47690b57cec5SDimitry Andric Attr.setInvalid(true); 47700b57cec5SDimitry Andric } 47710b57cec5SDimitry Andric } 47720b57cec5SDimitry Andric return true; 47730b57cec5SDimitry Andric } 47740b57cec5SDimitry Andric 47755f757f3fSDimitry Andric /// Parse a C++11 or C23 attribute-specifier. 47760b57cec5SDimitry Andric /// 47770b57cec5SDimitry Andric /// [C++11] attribute-specifier: 47780b57cec5SDimitry Andric /// '[' '[' attribute-list ']' ']' 47790b57cec5SDimitry Andric /// alignment-specifier 47800b57cec5SDimitry Andric /// 47810b57cec5SDimitry Andric /// [C++11] attribute-list: 47820b57cec5SDimitry Andric /// attribute[opt] 47830b57cec5SDimitry Andric /// attribute-list ',' attribute[opt] 47840b57cec5SDimitry Andric /// attribute '...' 47850b57cec5SDimitry Andric /// attribute-list ',' attribute '...' 47860b57cec5SDimitry Andric /// 47870b57cec5SDimitry Andric /// [C++11] attribute: 47880b57cec5SDimitry Andric /// attribute-token attribute-argument-clause[opt] 47890b57cec5SDimitry Andric /// 47900b57cec5SDimitry Andric /// [C++11] attribute-token: 47910b57cec5SDimitry Andric /// identifier 47920b57cec5SDimitry Andric /// attribute-scoped-token 47930b57cec5SDimitry Andric /// 47940b57cec5SDimitry Andric /// [C++11] attribute-scoped-token: 47950b57cec5SDimitry Andric /// attribute-namespace '::' identifier 47960b57cec5SDimitry Andric /// 47970b57cec5SDimitry Andric /// [C++11] attribute-namespace: 47980b57cec5SDimitry Andric /// identifier 4799fe6060f1SDimitry Andric void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, 4800fe6060f1SDimitry Andric CachedTokens &OpenMPTokens, 4801fe6060f1SDimitry Andric SourceLocation *EndLoc) { 48020b57cec5SDimitry Andric if (Tok.is(tok::kw_alignas)) { 4803*0fca6ea1SDimitry Andric // alignas is a valid token in C23 but it is not an attribute, it's a type- 4804*0fca6ea1SDimitry Andric // specifier-qualifier, which means it has different parsing behavior. We 4805*0fca6ea1SDimitry Andric // handle this in ParseDeclarationSpecifiers() instead of here in C. We 4806*0fca6ea1SDimitry Andric // should not get here for C any longer. 4807*0fca6ea1SDimitry Andric assert(getLangOpts().CPlusPlus && "'alignas' is not an attribute in C"); 48080b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas); 4809fe6060f1SDimitry Andric ParseAlignmentSpecifier(Attrs, EndLoc); 48100b57cec5SDimitry Andric return; 48110b57cec5SDimitry Andric } 48120b57cec5SDimitry Andric 481306c3fb27SDimitry Andric if (Tok.isRegularKeywordAttribute()) { 481406c3fb27SDimitry Andric SourceLocation Loc = Tok.getLocation(); 481506c3fb27SDimitry Andric IdentifierInfo *AttrName = Tok.getIdentifierInfo(); 48167a6dacacSDimitry Andric ParsedAttr::Form Form = ParsedAttr::Form(Tok.getKind()); 48177a6dacacSDimitry Andric bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind()); 481806c3fb27SDimitry Andric ConsumeToken(); 48197a6dacacSDimitry Andric if (TakesArgs) { 48207a6dacacSDimitry Andric if (!Tok.is(tok::l_paren)) 48217a6dacacSDimitry Andric Diag(Tok.getLocation(), diag::err_expected_lparen_after) << AttrName; 48227a6dacacSDimitry Andric else 48237a6dacacSDimitry Andric ParseAttributeArgsCommon(AttrName, Loc, Attrs, EndLoc, 48247a6dacacSDimitry Andric /*ScopeName*/ nullptr, 48257a6dacacSDimitry Andric /*ScopeLoc*/ Loc, Form); 48267a6dacacSDimitry Andric } else 48277a6dacacSDimitry Andric Attrs.addNew(AttrName, Loc, nullptr, Loc, nullptr, 0, Form); 482806c3fb27SDimitry Andric return; 482906c3fb27SDimitry Andric } 483006c3fb27SDimitry Andric 48310b57cec5SDimitry Andric assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) && 48320b57cec5SDimitry Andric "Not a double square bracket attribute list"); 48330b57cec5SDimitry Andric 4834e8d8bef9SDimitry Andric SourceLocation OpenLoc = Tok.getLocation(); 483506c3fb27SDimitry Andric if (getLangOpts().CPlusPlus) { 483606c3fb27SDimitry Andric Diag(OpenLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_attribute 483706c3fb27SDimitry Andric : diag::warn_ext_cxx11_attributes); 483806c3fb27SDimitry Andric } else { 48395f757f3fSDimitry Andric Diag(OpenLoc, getLangOpts().C23 ? diag::warn_pre_c23_compat_attributes 48405f757f3fSDimitry Andric : diag::warn_ext_c23_attributes); 484106c3fb27SDimitry Andric } 48420b57cec5SDimitry Andric 48430b57cec5SDimitry Andric ConsumeBracket(); 4844e8d8bef9SDimitry Andric checkCompoundToken(OpenLoc, tok::l_square, CompoundToken::AttrBegin); 48450b57cec5SDimitry Andric ConsumeBracket(); 48460b57cec5SDimitry Andric 48470b57cec5SDimitry Andric SourceLocation CommonScopeLoc; 48480b57cec5SDimitry Andric IdentifierInfo *CommonScopeName = nullptr; 48490b57cec5SDimitry Andric if (Tok.is(tok::kw_using)) { 48500b57cec5SDimitry Andric Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 48510b57cec5SDimitry Andric ? diag::warn_cxx14_compat_using_attribute_ns 48520b57cec5SDimitry Andric : diag::ext_using_attribute_ns); 48530b57cec5SDimitry Andric ConsumeToken(); 48540b57cec5SDimitry Andric 4855349cc55cSDimitry Andric CommonScopeName = TryParseCXX11AttributeIdentifier( 4856*0fca6ea1SDimitry Andric CommonScopeLoc, SemaCodeCompletion::AttributeCompletion::Scope); 48570b57cec5SDimitry Andric if (!CommonScopeName) { 48580b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; 48590b57cec5SDimitry Andric SkipUntil(tok::r_square, tok::colon, StopBeforeMatch); 48600b57cec5SDimitry Andric } 48610b57cec5SDimitry Andric if (!TryConsumeToken(tok::colon) && CommonScopeName) 48620b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected) << tok::colon; 48630b57cec5SDimitry Andric } 48640b57cec5SDimitry Andric 4865fe6060f1SDimitry Andric bool AttrParsed = false; 4866349cc55cSDimitry Andric while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) { 4867fe6060f1SDimitry Andric if (AttrParsed) { 4868fe6060f1SDimitry Andric // If we parsed an attribute, a comma is required before parsing any 4869fe6060f1SDimitry Andric // additional attributes. 4870fe6060f1SDimitry Andric if (ExpectAndConsume(tok::comma)) { 4871fe6060f1SDimitry Andric SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch); 48720b57cec5SDimitry Andric continue; 4873fe6060f1SDimitry Andric } 4874fe6060f1SDimitry Andric AttrParsed = false; 4875fe6060f1SDimitry Andric } 4876fe6060f1SDimitry Andric 4877fe6060f1SDimitry Andric // Eat all remaining superfluous commas before parsing the next attribute. 4878fe6060f1SDimitry Andric while (TryConsumeToken(tok::comma)) 4879fe6060f1SDimitry Andric ; 48800b57cec5SDimitry Andric 48810b57cec5SDimitry Andric SourceLocation ScopeLoc, AttrLoc; 48820b57cec5SDimitry Andric IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr; 48830b57cec5SDimitry Andric 4884349cc55cSDimitry Andric AttrName = TryParseCXX11AttributeIdentifier( 4885*0fca6ea1SDimitry Andric AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute, 4886*0fca6ea1SDimitry Andric CommonScopeName); 48870b57cec5SDimitry Andric if (!AttrName) 48880b57cec5SDimitry Andric // Break out to the "expected ']'" diagnostic. 48890b57cec5SDimitry Andric break; 48900b57cec5SDimitry Andric 48910b57cec5SDimitry Andric // scoped attribute 48920b57cec5SDimitry Andric if (TryConsumeToken(tok::coloncolon)) { 48930b57cec5SDimitry Andric ScopeName = AttrName; 48940b57cec5SDimitry Andric ScopeLoc = AttrLoc; 48950b57cec5SDimitry Andric 4896349cc55cSDimitry Andric AttrName = TryParseCXX11AttributeIdentifier( 4897*0fca6ea1SDimitry Andric AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute, 4898*0fca6ea1SDimitry Andric ScopeName); 48990b57cec5SDimitry Andric if (!AttrName) { 49000b57cec5SDimitry Andric Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; 49010b57cec5SDimitry Andric SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch); 49020b57cec5SDimitry Andric continue; 49030b57cec5SDimitry Andric } 49040b57cec5SDimitry Andric } 49050b57cec5SDimitry Andric 49060b57cec5SDimitry Andric if (CommonScopeName) { 49070b57cec5SDimitry Andric if (ScopeName) { 49080b57cec5SDimitry Andric Diag(ScopeLoc, diag::err_using_attribute_ns_conflict) 49090b57cec5SDimitry Andric << SourceRange(CommonScopeLoc); 49100b57cec5SDimitry Andric } else { 49110b57cec5SDimitry Andric ScopeName = CommonScopeName; 49120b57cec5SDimitry Andric ScopeLoc = CommonScopeLoc; 49130b57cec5SDimitry Andric } 49140b57cec5SDimitry Andric } 49150b57cec5SDimitry Andric 49160b57cec5SDimitry Andric // Parse attribute arguments 49170b57cec5SDimitry Andric if (Tok.is(tok::l_paren)) 4918fe6060f1SDimitry Andric AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc, 4919fe6060f1SDimitry Andric ScopeName, ScopeLoc, OpenMPTokens); 49200b57cec5SDimitry Andric 4921fe6060f1SDimitry Andric if (!AttrParsed) { 4922fe6060f1SDimitry Andric Attrs.addNew( 49230b57cec5SDimitry Andric AttrName, 49240b57cec5SDimitry Andric SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), 49250b57cec5SDimitry Andric ScopeName, ScopeLoc, nullptr, 0, 492606c3fb27SDimitry Andric getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11() 49275f757f3fSDimitry Andric : ParsedAttr::Form::C23()); 4928fe6060f1SDimitry Andric AttrParsed = true; 4929fe6060f1SDimitry Andric } 49300b57cec5SDimitry Andric 49310b57cec5SDimitry Andric if (TryConsumeToken(tok::ellipsis)) 4932972a253aSDimitry Andric Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) << AttrName; 49330b57cec5SDimitry Andric } 49340b57cec5SDimitry Andric 4935fe6060f1SDimitry Andric // If we hit an error and recovered by parsing up to a semicolon, eat the 4936fe6060f1SDimitry Andric // semicolon and don't issue further diagnostics about missing brackets. 4937fe6060f1SDimitry Andric if (Tok.is(tok::semi)) { 4938fe6060f1SDimitry Andric ConsumeToken(); 4939fe6060f1SDimitry Andric return; 4940fe6060f1SDimitry Andric } 4941fe6060f1SDimitry Andric 4942e8d8bef9SDimitry Andric SourceLocation CloseLoc = Tok.getLocation(); 49430b57cec5SDimitry Andric if (ExpectAndConsume(tok::r_square)) 49440b57cec5SDimitry Andric SkipUntil(tok::r_square); 4945e8d8bef9SDimitry Andric else if (Tok.is(tok::r_square)) 4946e8d8bef9SDimitry Andric checkCompoundToken(CloseLoc, tok::r_square, CompoundToken::AttrEnd); 4947fe6060f1SDimitry Andric if (EndLoc) 4948fe6060f1SDimitry Andric *EndLoc = Tok.getLocation(); 49490b57cec5SDimitry Andric if (ExpectAndConsume(tok::r_square)) 49500b57cec5SDimitry Andric SkipUntil(tok::r_square); 49510b57cec5SDimitry Andric } 49520b57cec5SDimitry Andric 49535f757f3fSDimitry Andric /// ParseCXX11Attributes - Parse a C++11 or C23 attribute-specifier-seq. 49540b57cec5SDimitry Andric /// 49550b57cec5SDimitry Andric /// attribute-specifier-seq: 49560b57cec5SDimitry Andric /// attribute-specifier-seq[opt] attribute-specifier 495781ad6265SDimitry Andric void Parser::ParseCXX11Attributes(ParsedAttributes &Attrs) { 495881ad6265SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 495981ad6265SDimitry Andric SourceLocation EndLoc = StartLoc; 49600b57cec5SDimitry Andric 49610b57cec5SDimitry Andric do { 496281ad6265SDimitry Andric ParseCXX11AttributeSpecifier(Attrs, &EndLoc); 496306c3fb27SDimitry Andric } while (isAllowedCXX11AttributeSpecifier()); 49640b57cec5SDimitry Andric 496581ad6265SDimitry Andric Attrs.Range = SourceRange(StartLoc, EndLoc); 49660b57cec5SDimitry Andric } 49670b57cec5SDimitry Andric 49680b57cec5SDimitry Andric void Parser::DiagnoseAndSkipCXX11Attributes() { 496906c3fb27SDimitry Andric auto Keyword = 497006c3fb27SDimitry Andric Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr; 49710b57cec5SDimitry Andric // Start and end location of an attribute or an attribute list. 49720b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 49730b57cec5SDimitry Andric SourceLocation EndLoc = SkipCXX11Attributes(); 49740b57cec5SDimitry Andric 49750b57cec5SDimitry Andric if (EndLoc.isValid()) { 49760b57cec5SDimitry Andric SourceRange Range(StartLoc, EndLoc); 497706c3fb27SDimitry Andric (Keyword ? Diag(StartLoc, diag::err_keyword_not_allowed) << Keyword 497806c3fb27SDimitry Andric : Diag(StartLoc, diag::err_attributes_not_allowed)) 497906c3fb27SDimitry Andric << Range; 49800b57cec5SDimitry Andric } 49810b57cec5SDimitry Andric } 49820b57cec5SDimitry Andric 49830b57cec5SDimitry Andric SourceLocation Parser::SkipCXX11Attributes() { 49840b57cec5SDimitry Andric SourceLocation EndLoc; 49850b57cec5SDimitry Andric 49860b57cec5SDimitry Andric if (!isCXX11AttributeSpecifier()) 49870b57cec5SDimitry Andric return EndLoc; 49880b57cec5SDimitry Andric 49890b57cec5SDimitry Andric do { 49900b57cec5SDimitry Andric if (Tok.is(tok::l_square)) { 49910b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_square); 49920b57cec5SDimitry Andric T.consumeOpen(); 49930b57cec5SDimitry Andric T.skipToEnd(); 49940b57cec5SDimitry Andric EndLoc = T.getCloseLocation(); 49957a6dacacSDimitry Andric } else if (Tok.isRegularKeywordAttribute() && 49967a6dacacSDimitry Andric !doesKeywordAttributeTakeArgs(Tok.getKind())) { 499706c3fb27SDimitry Andric EndLoc = Tok.getLocation(); 499806c3fb27SDimitry Andric ConsumeToken(); 49990b57cec5SDimitry Andric } else { 50007a6dacacSDimitry Andric assert((Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute()) && 50017a6dacacSDimitry Andric "not an attribute specifier"); 50020b57cec5SDimitry Andric ConsumeToken(); 50030b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 50040b57cec5SDimitry Andric if (!T.consumeOpen()) 50050b57cec5SDimitry Andric T.skipToEnd(); 50060b57cec5SDimitry Andric EndLoc = T.getCloseLocation(); 50070b57cec5SDimitry Andric } 50080b57cec5SDimitry Andric } while (isCXX11AttributeSpecifier()); 50090b57cec5SDimitry Andric 50100b57cec5SDimitry Andric return EndLoc; 50110b57cec5SDimitry Andric } 50120b57cec5SDimitry Andric 50130b57cec5SDimitry Andric /// Parse uuid() attribute when it appears in a [] Microsoft attribute. 50140b57cec5SDimitry Andric void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) { 50150b57cec5SDimitry Andric assert(Tok.is(tok::identifier) && "Not a Microsoft attribute list"); 50160b57cec5SDimitry Andric IdentifierInfo *UuidIdent = Tok.getIdentifierInfo(); 50170b57cec5SDimitry Andric assert(UuidIdent->getName() == "uuid" && "Not a Microsoft attribute list"); 50180b57cec5SDimitry Andric 50190b57cec5SDimitry Andric SourceLocation UuidLoc = Tok.getLocation(); 50200b57cec5SDimitry Andric ConsumeToken(); 50210b57cec5SDimitry Andric 50220b57cec5SDimitry Andric // Ignore the left paren location for now. 50230b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren); 50240b57cec5SDimitry Andric if (T.consumeOpen()) { 50250b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren; 50260b57cec5SDimitry Andric return; 50270b57cec5SDimitry Andric } 50280b57cec5SDimitry Andric 50290b57cec5SDimitry Andric ArgsVector ArgExprs; 50305f757f3fSDimitry Andric if (isTokenStringLiteral()) { 50310b57cec5SDimitry Andric // Easy case: uuid("...") -- quoted string. 50325f757f3fSDimitry Andric ExprResult StringResult = ParseUnevaluatedStringLiteralExpression(); 50330b57cec5SDimitry Andric if (StringResult.isInvalid()) 50340b57cec5SDimitry Andric return; 50350b57cec5SDimitry Andric ArgExprs.push_back(StringResult.get()); 50360b57cec5SDimitry Andric } else { 50370b57cec5SDimitry Andric // something like uuid({000000A0-0000-0000-C000-000000000049}) -- no 50380b57cec5SDimitry Andric // quotes in the parens. Just append the spelling of all tokens encountered 50390b57cec5SDimitry Andric // until the closing paren. 50400b57cec5SDimitry Andric 50410b57cec5SDimitry Andric SmallString<42> StrBuffer; // 2 "", 36 bytes UUID, 2 optional {}, 1 nul 50420b57cec5SDimitry Andric StrBuffer += "\""; 50430b57cec5SDimitry Andric 50440b57cec5SDimitry Andric // Since none of C++'s keywords match [a-f]+, accepting just tok::l_brace, 50450b57cec5SDimitry Andric // tok::r_brace, tok::minus, tok::identifier (think C000) and 50460b57cec5SDimitry Andric // tok::numeric_constant (0000) should be enough. But the spelling of the 50470b57cec5SDimitry Andric // uuid argument is checked later anyways, so there's no harm in accepting 50480b57cec5SDimitry Andric // almost anything here. 50490b57cec5SDimitry Andric // cl is very strict about whitespace in this form and errors out if any 50500b57cec5SDimitry Andric // is present, so check the space flags on the tokens. 50510b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 50520b57cec5SDimitry Andric while (Tok.isNot(tok::r_paren)) { 50530b57cec5SDimitry Andric if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) { 50540b57cec5SDimitry Andric Diag(Tok, diag::err_attribute_uuid_malformed_guid); 50550b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 50560b57cec5SDimitry Andric return; 50570b57cec5SDimitry Andric } 50580b57cec5SDimitry Andric SmallString<16> SpellingBuffer; 50590b57cec5SDimitry Andric SpellingBuffer.resize(Tok.getLength() + 1); 50600b57cec5SDimitry Andric bool Invalid = false; 50610b57cec5SDimitry Andric StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid); 50620b57cec5SDimitry Andric if (Invalid) { 50630b57cec5SDimitry Andric SkipUntil(tok::r_paren, StopAtSemi); 50640b57cec5SDimitry Andric return; 50650b57cec5SDimitry Andric } 50660b57cec5SDimitry Andric StrBuffer += TokSpelling; 50670b57cec5SDimitry Andric ConsumeAnyToken(); 50680b57cec5SDimitry Andric } 50690b57cec5SDimitry Andric StrBuffer += "\""; 50700b57cec5SDimitry Andric 50710b57cec5SDimitry Andric if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) { 50720b57cec5SDimitry Andric Diag(Tok, diag::err_attribute_uuid_malformed_guid); 50730b57cec5SDimitry Andric ConsumeParen(); 50740b57cec5SDimitry Andric return; 50750b57cec5SDimitry Andric } 50760b57cec5SDimitry Andric 50770b57cec5SDimitry Andric // Pretend the user wrote the appropriate string literal here. 50780b57cec5SDimitry Andric // ActOnStringLiteral() copies the string data into the literal, so it's 50790b57cec5SDimitry Andric // ok that the Token points to StrBuffer. 50800b57cec5SDimitry Andric Token Toks[1]; 50810b57cec5SDimitry Andric Toks[0].startToken(); 50820b57cec5SDimitry Andric Toks[0].setKind(tok::string_literal); 50830b57cec5SDimitry Andric Toks[0].setLocation(StartLoc); 50840b57cec5SDimitry Andric Toks[0].setLiteralData(StrBuffer.data()); 50850b57cec5SDimitry Andric Toks[0].setLength(StrBuffer.size()); 50860b57cec5SDimitry Andric StringLiteral *UuidString = 50875f757f3fSDimitry Andric cast<StringLiteral>(Actions.ActOnUnevaluatedStringLiteral(Toks).get()); 50880b57cec5SDimitry Andric ArgExprs.push_back(UuidString); 50890b57cec5SDimitry Andric } 50900b57cec5SDimitry Andric 50910b57cec5SDimitry Andric if (!T.consumeClose()) { 50920b57cec5SDimitry Andric Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr, 50930b57cec5SDimitry Andric SourceLocation(), ArgExprs.data(), ArgExprs.size(), 509406c3fb27SDimitry Andric ParsedAttr::Form::Microsoft()); 50950b57cec5SDimitry Andric } 50960b57cec5SDimitry Andric } 50970b57cec5SDimitry Andric 50980b57cec5SDimitry Andric /// ParseMicrosoftAttributes - Parse Microsoft attributes [Attr] 50990b57cec5SDimitry Andric /// 51000b57cec5SDimitry Andric /// [MS] ms-attribute: 51010b57cec5SDimitry Andric /// '[' token-seq ']' 51020b57cec5SDimitry Andric /// 51030b57cec5SDimitry Andric /// [MS] ms-attribute-seq: 51040b57cec5SDimitry Andric /// ms-attribute[opt] 51050b57cec5SDimitry Andric /// ms-attribute ms-attribute-seq 510681ad6265SDimitry Andric void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) { 51070b57cec5SDimitry Andric assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list"); 51080b57cec5SDimitry Andric 510981ad6265SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 511081ad6265SDimitry Andric SourceLocation EndLoc = StartLoc; 51110b57cec5SDimitry Andric do { 51120b57cec5SDimitry Andric // FIXME: If this is actually a C++11 attribute, parse it as one. 51130b57cec5SDimitry Andric BalancedDelimiterTracker T(*this, tok::l_square); 51140b57cec5SDimitry Andric T.consumeOpen(); 51150b57cec5SDimitry Andric 51165ffd83dbSDimitry Andric // Skip most ms attributes except for a specific list. 51170b57cec5SDimitry Andric while (true) { 5118349cc55cSDimitry Andric SkipUntil(tok::r_square, tok::identifier, 5119349cc55cSDimitry Andric StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); 5120349cc55cSDimitry Andric if (Tok.is(tok::code_completion)) { 5121349cc55cSDimitry Andric cutOffParsing(); 5122*0fca6ea1SDimitry Andric Actions.CodeCompletion().CodeCompleteAttribute( 5123*0fca6ea1SDimitry Andric AttributeCommonInfo::AS_Microsoft, 5124*0fca6ea1SDimitry Andric SemaCodeCompletion::AttributeCompletion::Attribute, 5125349cc55cSDimitry Andric /*Scope=*/nullptr); 5126349cc55cSDimitry Andric break; 5127349cc55cSDimitry Andric } 51280b57cec5SDimitry Andric if (Tok.isNot(tok::identifier)) // ']', but also eof 51290b57cec5SDimitry Andric break; 51300b57cec5SDimitry Andric if (Tok.getIdentifierInfo()->getName() == "uuid") 513181ad6265SDimitry Andric ParseMicrosoftUuidAttributeArgs(Attrs); 513281ad6265SDimitry Andric else { 513381ad6265SDimitry Andric IdentifierInfo *II = Tok.getIdentifierInfo(); 513481ad6265SDimitry Andric SourceLocation NameLoc = Tok.getLocation(); 51350b57cec5SDimitry Andric ConsumeToken(); 513681ad6265SDimitry Andric ParsedAttr::Kind AttrKind = 513781ad6265SDimitry Andric ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_Microsoft); 513881ad6265SDimitry Andric // For HLSL we want to handle all attributes, but for MSVC compat, we 513981ad6265SDimitry Andric // silently ignore unknown Microsoft attributes. 514081ad6265SDimitry Andric if (getLangOpts().HLSL || AttrKind != ParsedAttr::UnknownAttribute) { 514181ad6265SDimitry Andric bool AttrParsed = false; 514281ad6265SDimitry Andric if (Tok.is(tok::l_paren)) { 514381ad6265SDimitry Andric CachedTokens OpenMPTokens; 514481ad6265SDimitry Andric AttrParsed = 514581ad6265SDimitry Andric ParseCXX11AttributeArgs(II, NameLoc, Attrs, &EndLoc, nullptr, 514681ad6265SDimitry Andric SourceLocation(), OpenMPTokens); 514781ad6265SDimitry Andric ReplayOpenMPAttributeTokens(OpenMPTokens); 514881ad6265SDimitry Andric } 514981ad6265SDimitry Andric if (!AttrParsed) { 515081ad6265SDimitry Andric Attrs.addNew(II, NameLoc, nullptr, SourceLocation(), nullptr, 0, 515106c3fb27SDimitry Andric ParsedAttr::Form::Microsoft()); 515281ad6265SDimitry Andric } 515381ad6265SDimitry Andric } 515481ad6265SDimitry Andric } 51550b57cec5SDimitry Andric } 51560b57cec5SDimitry Andric 51570b57cec5SDimitry Andric T.consumeClose(); 515881ad6265SDimitry Andric EndLoc = T.getCloseLocation(); 51590b57cec5SDimitry Andric } while (Tok.is(tok::l_square)); 516081ad6265SDimitry Andric 516181ad6265SDimitry Andric Attrs.Range = SourceRange(StartLoc, EndLoc); 51620b57cec5SDimitry Andric } 51630b57cec5SDimitry Andric 51640b57cec5SDimitry Andric void Parser::ParseMicrosoftIfExistsClassDeclaration( 51650b57cec5SDimitry Andric DeclSpec::TST TagType, ParsedAttributes &AccessAttrs, 51660b57cec5SDimitry Andric AccessSpecifier &CurAS) { 51670b57cec5SDimitry Andric IfExistsCondition Result; 51680b57cec5SDimitry Andric if (ParseMicrosoftIfExistsCondition(Result)) 51690b57cec5SDimitry Andric return; 51700b57cec5SDimitry Andric 51710b57cec5SDimitry Andric BalancedDelimiterTracker Braces(*this, tok::l_brace); 51720b57cec5SDimitry Andric if (Braces.consumeOpen()) { 51730b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::l_brace; 51740b57cec5SDimitry Andric return; 51750b57cec5SDimitry Andric } 51760b57cec5SDimitry Andric 51770b57cec5SDimitry Andric switch (Result.Behavior) { 51780b57cec5SDimitry Andric case IEB_Parse: 51790b57cec5SDimitry Andric // Parse the declarations below. 51800b57cec5SDimitry Andric break; 51810b57cec5SDimitry Andric 51820b57cec5SDimitry Andric case IEB_Dependent: 51830b57cec5SDimitry Andric Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) 51840b57cec5SDimitry Andric << Result.IsIfExists; 51850b57cec5SDimitry Andric // Fall through to skip. 5186bdd1243dSDimitry Andric [[fallthrough]]; 51870b57cec5SDimitry Andric 51880b57cec5SDimitry Andric case IEB_Skip: 51890b57cec5SDimitry Andric Braces.skipToEnd(); 51900b57cec5SDimitry Andric return; 51910b57cec5SDimitry Andric } 51920b57cec5SDimitry Andric 51930b57cec5SDimitry Andric while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 51940b57cec5SDimitry Andric // __if_exists, __if_not_exists can nest. 51950b57cec5SDimitry Andric if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { 5196972a253aSDimitry Andric ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS); 51970b57cec5SDimitry Andric continue; 51980b57cec5SDimitry Andric } 51990b57cec5SDimitry Andric 52000b57cec5SDimitry Andric // Check for extraneous top-level semicolon. 52010b57cec5SDimitry Andric if (Tok.is(tok::semi)) { 52020b57cec5SDimitry Andric ConsumeExtraSemi(InsideStruct, TagType); 52030b57cec5SDimitry Andric continue; 52040b57cec5SDimitry Andric } 52050b57cec5SDimitry Andric 52060b57cec5SDimitry Andric AccessSpecifier AS = getAccessSpecifierIfPresent(); 52070b57cec5SDimitry Andric if (AS != AS_none) { 52080b57cec5SDimitry Andric // Current token is a C++ access specifier. 52090b57cec5SDimitry Andric CurAS = AS; 52100b57cec5SDimitry Andric SourceLocation ASLoc = Tok.getLocation(); 52110b57cec5SDimitry Andric ConsumeToken(); 52120b57cec5SDimitry Andric if (Tok.is(tok::colon)) 52130b57cec5SDimitry Andric Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(), 52140b57cec5SDimitry Andric ParsedAttributesView{}); 52150b57cec5SDimitry Andric else 52160b57cec5SDimitry Andric Diag(Tok, diag::err_expected) << tok::colon; 52170b57cec5SDimitry Andric ConsumeToken(); 52180b57cec5SDimitry Andric continue; 52190b57cec5SDimitry Andric } 52200b57cec5SDimitry Andric 5221*0fca6ea1SDimitry Andric ParsedTemplateInfo TemplateInfo; 52220b57cec5SDimitry Andric // Parse all the comma separated declarators. 5223*0fca6ea1SDimitry Andric ParseCXXClassMemberDeclaration(CurAS, AccessAttrs, TemplateInfo); 52240b57cec5SDimitry Andric } 52250b57cec5SDimitry Andric 52260b57cec5SDimitry Andric Braces.consumeClose(); 52270b57cec5SDimitry Andric } 5228