diff options
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 169 |
1 files changed, 99 insertions, 70 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 081d4d8b1209..ddcbb5615fee 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -155,7 +155,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, // Normal namespace definition, not a nested-namespace-definition. } else if (InlineLoc.isValid()) { Diag(InlineLoc, diag::err_inline_nested_namespace_definition); - } else if (getLangOpts().CPlusPlus2a) { + } else if (getLangOpts().CPlusPlus20) { Diag(ExtraNSs[0].NamespaceLoc, diag::warn_cxx14_compat_nested_namespace_definition); if (FirstNestedInlineLoc.isValid()) @@ -290,7 +290,9 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, CXXScopeSpec SS; // Parse (optional) nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false, + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + /*EnteringContext=*/false, /*MayBePseudoDestructor=*/nullptr, /*IsTypename=*/false, /*LastII=*/nullptr, @@ -530,7 +532,9 @@ Decl *Parser::ParseUsingDirective(DeclaratorContext Context, CXXScopeSpec SS; // Parse (optional) nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false, + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + /*EnteringContext=*/false, /*MayBePseudoDestructor=*/nullptr, /*IsTypename=*/false, /*LastII=*/nullptr, @@ -597,7 +601,9 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, // Parse nested-name-specifier. IdentifierInfo *LastII = nullptr; - if (ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false, + if (ParseOptionalCXXScopeSpecifier(D.SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + /*EnteringContext=*/false, /*MayBePseudoDtor=*/nullptr, /*IsTypename=*/false, /*LastII=*/&LastII, @@ -632,12 +638,12 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, D.Name.setConstructorName(Type, IdLoc, IdLoc); } else { if (ParseUnqualifiedId( - D.SS, /*EnteringContext=*/false, + D.SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, /*EnteringContext=*/false, /*AllowDestructorName=*/true, - /*AllowConstructorName=*/!(Tok.is(tok::identifier) && - NextToken().is(tok::equal)), - /*AllowDeductionGuide=*/false, - nullptr, nullptr, D.Name)) + /*AllowConstructorName=*/ + !(Tok.is(tok::identifier) && NextToken().is(tok::equal)), + /*AllowDeductionGuide=*/false, nullptr, D.Name)) return true; } @@ -978,10 +984,10 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { EnterExpressionEvaluationContext Unevaluated( Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, Sema::ExpressionEvaluationContextRecord::EK_Decltype); - Result = - Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) { - return E->hasPlaceholderType() ? ExprError() : E; - }); + Result = Actions.CorrectDelayedTyposInExpr( + ParseExpression(), /*InitDecl=*/nullptr, + /*RecoverUncorrectedTypos=*/false, + [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; }); if (Result.isInvalid()) { DS.SetTypeSpecError(); if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { @@ -1115,7 +1121,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Parse optional nested-name-specifier CXXScopeSpec SS; - if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false)) + if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + /*EnteringContext=*/false)) return true; BaseLoc = Tok.getLocation(); @@ -1139,19 +1147,14 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Check whether we have a template-id that names a type. if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); - if (TemplateId->Kind == TNK_Type_template || - TemplateId->Kind == TNK_Dependent_template_name || - TemplateId->Kind == TNK_Undeclared_template) { - AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + if (TemplateId->mightBeType()) { + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); - ParsedType Type = getTypeAnnotation(Tok); + TypeResult Type = getTypeAnnotation(Tok); EndLocation = Tok.getAnnotationEndLoc(); ConsumeAnnotationToken(); - - if (Type) - return Type; - return true; + return Type; } // Fall through to produce an error below. @@ -1168,7 +1171,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (Tok.is(tok::less)) { // It looks the user intended to write a template-id here, but the // template-name was wrong. Try to fix that. - TemplateNameKind TNK = TNK_Type_template; + // FIXME: Invoke ParseOptionalCXXScopeSpecifier in a "'template' is neither + // required nor permitted" mode, and do this there. + TemplateNameKind TNK = TNK_Non_template; TemplateTy Template; if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), &SS, Template, TNK)) { @@ -1176,14 +1181,6 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, << Id; } - if (!Template) { - TemplateArgList TemplateArgs; - SourceLocation LAngleLoc, RAngleLoc; - ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, - RAngleLoc); - return true; - } - // Form the template name UnqualifiedId TemplateName; TemplateName.setIdentifier(Id, IdLoc); @@ -1192,8 +1189,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), TemplateName)) return true; - if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name) - AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + if (Tok.is(tok::annot_template_id) && + takeTemplateIdAnnotation(Tok)->mightBeType()) + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); // If we didn't end up with a typename token, there's nothing more we // can do. @@ -1203,7 +1201,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Retrieve the type from the annotation token, consume that token, and // return. EndLocation = Tok.getAnnotationEndLoc(); - ParsedType Type = getTypeAnnotation(Tok); + TypeResult Type = getTypeAnnotation(Tok); ConsumeAnnotationToken(); return Type; } @@ -1285,7 +1283,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::annot_pragma_ms_pointers_to_members: return true; case tok::colon: - return CouldBeBitfield; // enum E { ... } : 2; + return CouldBeBitfield || // enum E { ... } : 2; + ColonIsSacred; // _Generic(..., enum E : 2); // Microsoft compatibility case tok::kw___cdecl: // struct foo {...} __cdecl x; case tok::kw___fastcall: // struct foo {...} __fastcall x; @@ -1547,7 +1546,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, CXXScopeSpec Spec; bool HasValidSpec = true; - if (ParseOptionalCXXScopeSpecifier(Spec, nullptr, EnteringContext)) { + if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + EnteringContext)) { DS.SetTypeSpecError(); HasValidSpec = false; } @@ -1620,9 +1621,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, NameLoc = ConsumeAnnotationToken(); if (TemplateId->Kind == TNK_Undeclared_template) { - // Try to resolve the template name to a type template. - Actions.ActOnUndeclaredTypeTemplateName(getCurScope(), TemplateId->Template, - TemplateId->Kind, NameLoc, Name); + // Try to resolve the template name to a type template. May update Kind. + Actions.ActOnUndeclaredTypeTemplateName( + getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name); if (TemplateId->Kind == TNK_Undeclared_template) { RecoverFromUndeclaredTemplateName( Name, NameLoc, @@ -1631,10 +1632,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } } - if (TemplateId && TemplateId->Kind != TNK_Type_template && - TemplateId->Kind != TNK_Dependent_template_name) { + if (TemplateId && !TemplateId->mightBeType()) { // The template-name in the simple-template-id refers to - // something other than a class template. Give an appropriate + // something other than a type template. Give an appropriate // error message and skip to the ';'. SourceRange Range(NameLoc); if (SS.isNotEmpty()) @@ -1681,7 +1681,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); Sema::TagUseKind TUK; - if (DSC == DeclSpecContext::DSC_trailing) + if (isDefiningTypeSpecifierContext(DSC) == AllowDefiningTypeSpec::No || + (getLangOpts().OpenMP && OpenMPDirectiveParsing)) TUK = Sema::TUK_Reference; else if (Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || @@ -1806,7 +1807,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // or explicit instantiation. ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && + if (TemplateId->isInvalid()) { + // Can't build the declaration. + } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { // This is an explicit instantiation of a class template. ProhibitAttributes(attrs); @@ -1826,7 +1829,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { ProhibitAttributes(attrs); TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc, - TemplateId->SS, + SS, TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->TemplateNameLoc, @@ -1876,7 +1879,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Build the class template specialization. TagOrTempResult = Actions.ActOnClassTemplateSpecialization( getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), - *TemplateId, attrs, + SS, *TemplateId, attrs, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0), @@ -1962,7 +1965,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get(); // Parse the definition body. - ParseStructUnionBody(StartLoc, TagType, D); + ParseStructUnionBody(StartLoc, TagType, cast<RecordDecl>(D)); if (SkipBody.CheckSameAsPrevious && !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), SkipBody)) { @@ -2182,7 +2185,6 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, // declarations. auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); getCurrentClass().LateParsedDeclarations.push_back(LateMethod); - LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); // Stash the exception-specification tokens in the late-pased method. LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; @@ -2501,7 +2503,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (isAccessDecl) { // Collect the scope specifier token we annotated earlier. CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, nullptr, + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, /*EnteringContext=*/false); if (SS.isInvalid()) { @@ -2512,8 +2515,9 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Try to parse an unqualified-id. SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (ParseUnqualifiedId(SS, false, true, true, false, nullptr, - &TemplateKWLoc, Name)) { + if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, false, true, true, + false, &TemplateKWLoc, Name)) { SkipUntil(tok::semi); return nullptr; } @@ -2642,6 +2646,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext); + if (TemplateInfo.TemplateParams) + DeclaratorInfo.setTemplateParameterLists(TemplateParams); VirtSpecifiers VS; // Hold late-parsed attributes so we can attach a Decl to them later. @@ -2656,7 +2662,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, auto &Zero = NextToken(); SmallString<8> Buffer; - if (Zero.isNot(tok::numeric_constant) || Zero.getLength() != 1 || + if (Zero.isNot(tok::numeric_constant) || PP.getSpelling(Zero, Buffer) != "0") return false; @@ -2707,6 +2713,11 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DefinitionKind = FDK_Defaulted; else if (KW.is(tok::kw_delete)) DefinitionKind = FDK_Deleted; + else if (KW.is(tok::code_completion)) { + Actions.CodeCompleteAfterFunctionEquals(DeclaratorInfo); + cutOffParsing(); + return nullptr; + } } } DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind); @@ -2714,7 +2725,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains // to a friend declaration, that declaration shall be a definition. if (DeclaratorInfo.isFunctionDeclarator() && - DefinitionKind != FDK_Definition && DS.isFriendSpecified()) { + DefinitionKind == FDK_Declaration && DS.isFriendSpecified()) { // Diagnose attributes that appear before decl specifier: // [[]] friend int foo(); ProhibitAttributes(FnAttrs); @@ -2782,7 +2793,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, !DS.isFriendSpecified()) { // It's a default member initializer. if (BitfieldSize.get()) - Diag(Tok, getLangOpts().CPlusPlus2a + Diag(Tok, getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_bitfield_member_init : diag::ext_bitfield_member_init); HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; @@ -2987,7 +2998,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, << 0 /* default */; else Diag(ConsumeToken(), diag::err_default_special_members) - << getLangOpts().CPlusPlus2a; + << getLangOpts().CPlusPlus20; return ExprError(); } } @@ -3334,6 +3345,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // Each iteration of this loop reads one member-declaration. ParseCXXClassMemberDeclarationWithPragmas( CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl); + MaybeDestroyTemplateIds(); } T.consumeClose(); } else { @@ -3359,6 +3371,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // are complete and we can parse the delayed portions of method // declarations and the lexed inline method definitions, along with any // delayed attributes. + + // Save the state of Sema.FPFeatures, and change the setting + // to the levels specified on the command line. Previous level + // will be restored when the RAII object is destroyed. + Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions); + FPOptionsOverride NewOverrides; + Actions.CurFPFeatures = NewOverrides.applyOverrides(getLangOpts()); + Actions.FpPragmaStack.Act(Tok.getLocation(), Sema::PSK_Reset, StringRef(), + 0 /*unused*/); + SourceLocation SavedPrevTokLocation = PrevTokLocation; ParseLexedPragmas(getCurrentClass()); ParseLexedAttributes(getCurrentClass()); @@ -3491,7 +3513,9 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // parse '::'[opt] nested-name-specifier[opt] CXXScopeSpec SS; - if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false)) + if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHadErrors=*/false, + /*EnteringContext=*/false)) return true; // : identifier @@ -3500,7 +3524,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // : declype(...) DeclSpec DS(AttrFactory); // : template_name<...> - ParsedType TemplateTypeTy; + TypeResult TemplateTypeTy; if (Tok.is(tok::identifier)) { // Get the identifier. This may be a member name or a class name, @@ -3517,15 +3541,11 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id) ? takeTemplateIdAnnotation(Tok) : nullptr; - if (TemplateId && (TemplateId->Kind == TNK_Type_template || - TemplateId->Kind == TNK_Dependent_template_name || - TemplateId->Kind == TNK_Undeclared_template)) { - AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + if (TemplateId && TemplateId->mightBeType()) { + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); ConsumeAnnotationToken(); - if (!TemplateTypeTy) - return true; } else { Diag(Tok, diag::err_expected_member_or_base_name); return true; @@ -3544,8 +3564,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation EllipsisLoc; TryConsumeToken(tok::ellipsis, EllipsisLoc); + if (TemplateTypeTy.isInvalid()) + return true; return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy, DS, IdLoc, + TemplateTypeTy.get(), DS, IdLoc, InitList.get(), EllipsisLoc); } else if(Tok.is(tok::l_paren)) { BalancedDelimiterTracker T(*this, tok::l_paren); @@ -3555,8 +3577,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { ExprVector ArgExprs; CommaLocsTy CommaLocs; auto RunSignatureHelp = [&] { + if (TemplateTypeTy.isInvalid()) + return QualType(); QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp( - getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II, + getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II, T.getOpenLocation()); CalledSignatureHelp = true; return PreferredType; @@ -3577,12 +3601,17 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation EllipsisLoc; TryConsumeToken(tok::ellipsis, EllipsisLoc); + if (TemplateTypeTy.isInvalid()) + return true; return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy, DS, IdLoc, + TemplateTypeTy.get(), DS, IdLoc, T.getOpenLocation(), ArgExprs, T.getCloseLocation(), EllipsisLoc); } + if (TemplateTypeTy.isInvalid()) + return true; + if (getLangOpts().CPlusPlus11) return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace; else @@ -3908,8 +3937,8 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { // after the top-level class is completely defined. Therefore, add // it to the list of nested classes within its parent. assert(getCurScope()->isClassScope() && "Nested class outside of class scope?"); - ClassStack.top()->LateParsedDeclarations.push_back(new LateParsedClass(this, Victim)); - Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope(); + ClassStack.top()->LateParsedDeclarations.push_back( + new LateParsedClass(this, Victim)); } /// Try to parse an 'identifier' which appears within an attribute-token. @@ -4364,7 +4393,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); - // Skip most ms attributes except for a whitelist. + // Skip most ms attributes except for a specific list. while (true) { SkipUntil(tok::r_square, tok::identifier, StopAtSemi | StopBeforeMatch); if (Tok.isNot(tok::identifier)) // ']', but also eof |