diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 272 |
1 files changed, 203 insertions, 69 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 87d9909..53e4a41 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -558,6 +558,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Maybe this is an alias-declaration. TypeResult TypeAlias; bool IsAliasDecl = Tok.is(tok::equal); + Decl *DeclFromDeclSpec = nullptr; if (IsAliasDecl) { // If we had any misplaced attributes from earlier, this is where they // should have been written. @@ -612,10 +613,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(SS.getRange()); - TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ? - Declarator::AliasTemplateContext : - Declarator::AliasDeclContext, AS, OwnedType, - &Attrs); + TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind + ? Declarator::AliasTemplateContext + : Declarator::AliasDeclContext, + AS, &DeclFromDeclSpec, &Attrs); + if (OwnedType) + *OwnedType = DeclFromDeclSpec; } else { // C++11 attributes are not allowed on a using-declaration, but GNU ones // are. @@ -664,7 +667,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, UsingLoc, Name, Attrs.getList(), - TypeAlias); + TypeAlias, DeclFromDeclSpec); } return Actions.ActOnUsingDeclaration(getCurScope(), AS, @@ -796,7 +799,10 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, nullptr,/*IsDecltype=*/true); - Result = Actions.CorrectDelayedTyposInExpr(ParseExpression()); + Result = + Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) { + return E->hasPlaceholderType() ? ExprError() : E; + }); if (Result.isInvalid()) { DS.SetTypeSpecError(); if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { @@ -1223,10 +1229,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParsedAttributesWithRange attrs(AttrFactory); // If attributes exist after tag, parse them. MaybeParseGNUAttributes(attrs); - - // If declspecs exist after tag, parse them. - while (Tok.is(tok::kw___declspec)) - ParseMicrosoftDeclSpec(attrs); + MaybeParseMicrosoftDeclSpecs(attrs); // Parse inheritance specifiers. if (Tok.is(tok::kw___single_inheritance) || @@ -1310,11 +1313,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // is a base-specifier-list. ColonProtectionRAIIObject X(*this); - if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) + CXXScopeSpec Spec; + bool HasValidSpec = true; + if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), EnteringContext)) { DS.SetTypeSpecError(); - if (SS.isSet()) - if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) + HasValidSpec = false; + } + if (Spec.isSet()) + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) { Diag(Tok, diag::err_expected) << tok::identifier; + HasValidSpec = false; + } + if (HasValidSpec) + SS = Spec; } TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; @@ -1539,6 +1550,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TypeResult TypeResult = true; // invalid bool Owned = false; + Sema::SkipBodyInfo SkipBody; if (TemplateId) { // Explicit specialization, class template partial specialization, // or explicit instantiation. @@ -1625,7 +1637,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, *TemplateId, attrs.getList(), MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, - TemplateParams ? TemplateParams->size() : 0)); + TemplateParams ? TemplateParams->size() : 0), + &SkipBody); } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { @@ -1677,6 +1690,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TParams = MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); + handleDeclspecAlignBeforeClassKey(attrs, DS, TUK); + // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs.getList(), AS, @@ -1684,7 +1699,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TParams, Owned, IsDependent, SourceLocation(), false, clang::TypeResult(), - DSC == DSC_type_specifier); + DSC == DSC_type_specifier, + &SkipBody); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -1700,7 +1716,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || isCXX11FinalKeyword()); - if (getLangOpts().CPlusPlus) + if (SkipBody.ShouldSkip) + SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, + TagOrTempResult.get()); + else if (getLangOpts().CPlusPlus) ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); else @@ -1882,51 +1901,40 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const { /// the class definition. void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, Decl *ThisDecl) { - // We just declared a member function. If this member function - // has any default arguments or an exception-specification, we'll need to - // parse them later. - LateParsedMethodDeclaration *LateMethod = nullptr; DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo(); + // If there was a late-parsed exception-specification, we'll need a + // late parse + bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed; + + if (!NeedLateParse) { + // Look ahead to see if there are any default args + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { + auto Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param); + if (Param->hasUnparsedDefaultArg()) { + NeedLateParse = true; + break; + } + } + } - // If there was a late-parsed exception-specification, hold onto its tokens. - if (FTI.getExceptionSpecType() == EST_Unparsed) { + if (NeedLateParse) { // Push this method onto the stack of late-parsed method // declarations. - LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); + auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); getCurrentClass().LateParsedDeclarations.push_back(LateMethod); LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); - // Stash the exception-specification tokens in the late-pased mthod. + // Stash the exception-specification tokens in the late-pased method. LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; FTI.ExceptionSpecTokens = 0; - // Reserve space for the parameters. + // Push tokens for each parameter. Those that do not have + // defaults will be NULL. LateMethod->DefaultArgs.reserve(FTI.NumParams); - } - - for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { - if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) { - if (!LateMethod) { - // Push this method onto the stack of late-parsed method - // declarations. - LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); - getCurrentClass().LateParsedDeclarations.push_back(LateMethod); - LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); - - // Add all of the parameters prior to this one (they don't - // have default arguments). - LateMethod->DefaultArgs.reserve(FTI.NumParams); - for (unsigned I = 0; I < ParamIdx; ++I) - LateMethod->DefaultArgs.push_back( - LateParsedDefaultArgument(FTI.Params[I].Param)); - } - - // Add this parameter to the list of parameters (it may or may - // not have a default argument). + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument( - FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens)); - } + FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens)); } } @@ -2019,7 +2027,7 @@ bool Parser::isCXX11FinalKeyword() const { /// \brief Parse a C++ member-declarator up to, but not including, the optional /// brace-or-equal-initializer or pure-specifier. -void Parser::ParseCXXMemberDeclaratorBeforeInitializer( +bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize, LateParsedAttrList &LateParsedAttrs) { // member-declarator: @@ -2037,10 +2045,13 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( BitfieldSize = ParseConstantExpression(); if (BitfieldSize.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - } else + } else { ParseOptionalCXX11VirtSpecifierSeq( VS, getCurrentClass().IsInterface, DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); + if (!VS.isUnset()) + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); + } // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { @@ -2071,6 +2082,78 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); Attr = Attr->getNext(); } + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); + } + } + + // If this has neither a name nor a bit width, something has gone seriously + // wrong. Skip until the semi-colon or }. + if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) { + // If so, skip until the semi-colon or a }. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + return true; + } + return false; +} + +/// \brief Look for declaration specifiers possibly occurring after C++11 +/// virt-specifier-seq and diagnose them. +void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( + Declarator &D, + VirtSpecifiers &VS) { + DeclSpec DS(AttrFactory); + + // GNU-style and C++11 attributes are not allowed here, but they will be + // handled by the caller. Diagnose everything else. + ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false); + D.ExtendWithDeclSpec(DS); + + if (D.isFunctionDeclarator()) { + auto &Function = D.getFunctionTypeInfo(); + if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) { + auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual, + const char *FixItName, + SourceLocation SpecLoc, + unsigned* QualifierLoc) { + FixItHint Insertion; + if (DS.getTypeQualifiers() & TypeQual) { + if (!(Function.TypeQuals & TypeQual)) { + std::string Name(FixItName); + Name += " "; + Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name.c_str()); + Function.TypeQuals |= TypeQual; + *QualifierLoc = SpecLoc.getRawEncoding(); + } + Diag(SpecLoc, diag::err_declspec_after_virtspec) + << FixItName + << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) + << FixItHint::CreateRemoval(SpecLoc) + << Insertion; + } + }; + DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(), + &Function.ConstQualifierLoc); + DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(), + &Function.VolatileQualifierLoc); + DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(), + &Function.RestrictQualifierLoc); + } + + // Parse ref-qualifiers. + bool RefQualifierIsLValueRef = true; + SourceLocation RefQualifierLoc; + if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) { + const char *Name = (RefQualifierIsLValueRef ? "& " : "&& "); + FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name); + Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef; + Function.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + + Diag(RefQualifierLoc, diag::err_declspec_after_virtspec) + << (RefQualifierIsLValueRef ? "&" : "&&") + << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) + << FixItHint::CreateRemoval(RefQualifierLoc) + << Insertion; + D.SetRangeEnd(RefQualifierLoc); } } } @@ -2298,14 +2381,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, bool ExpectSemi = true; // Parse the first declarator. - ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, - LateParsedAttrs); - - // If this has neither a name nor a bit width, something has gone seriously - // wrong. Skip until the semi-colon or }. - if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) { - // If so, skip until the semi-colon or a }. - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + if (ParseCXXMemberDeclaratorBeforeInitializer( + DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) { TryConsumeToken(tok::semi); return; } @@ -2344,6 +2421,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DefinitionKind = FDK_Deleted; } } + DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind); // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains // to a friend declaration, that declaration shall be a definition. @@ -2354,7 +2432,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ProhibitAttributes(FnAttrs); } - if (DefinitionKind) { + if (DefinitionKind != FDK_Declaration) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params); ConsumeBrace(); @@ -2376,7 +2454,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, - VS, DefinitionKind, Init); + VS, Init); if (FunDecl) { for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { @@ -2530,16 +2608,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Parse the next declarator. DeclaratorInfo.clear(); VS.clear(); - BitfieldSize = true; - Init = true; + BitfieldSize = ExprResult(/*Invalid=*/false); + Init = ExprResult(/*Invalid=*/false); HasInitializer = false; DeclaratorInfo.setCommaLoc(CommaLoc); // GNU attributes are allowed before the second and subsequent declarator. MaybeParseGNUAttributes(DeclaratorInfo); - ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, - LateParsedAttrs); + if (ParseCXXMemberDeclaratorBeforeInitializer( + DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) + break; } if (ExpectSemi && @@ -2617,6 +2696,55 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, return ParseInitializer(); } +void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, + SourceLocation AttrFixitLoc, + unsigned TagType, Decl *TagDecl) { + // Skip the optional 'final' keyword. + if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { + assert(isCXX11FinalKeyword() && "not a class definition"); + ConsumeToken(); + + // Diagnose any C++11 attributes after 'final' keyword. + // We deliberately discard these attributes. + ParsedAttributesWithRange Attrs(AttrFactory); + CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc); + + // This can only happen if we had malformed misplaced attributes; + // we only get called if there is a colon or left-brace after the + // attributes. + if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace)) + return; + } + + // Skip the base clauses. This requires actually parsing them, because + // otherwise we can't be sure where they end (a left brace may appear + // within a template argument). + if (Tok.is(tok::colon)) { + // Enter the scope of the class so that we can correctly parse its bases. + ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); + ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true, + TagType == DeclSpec::TST_interface); + Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl); + + // Parse the bases but don't attach them to the class. + ParseBaseClause(nullptr); + + Actions.ActOnTagFinishSkippedDefinition(); + + if (!Tok.is(tok::l_brace)) { + Diag(PP.getLocForEndOfToken(PrevTokLocation), + diag::err_expected_lbrace_after_base_specifiers); + return; + } + } + + // Skip the body. + assert(Tok.is(tok::l_brace)); + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + T.skipToEnd(); +} + /// ParseCXXMemberSpecification - Parse the class definition. /// /// member-specification: @@ -2911,6 +3039,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, ParseLexedMemberInitializers(getCurrentClass()); ParseLexedMethodDefs(getCurrentClass()); PrevTokLocation = SavedPrevTokLocation; + + // We've finished parsing everything, including default argument + // initializers. + Actions.ActOnFinishCXXMemberDefaultArgs(TagDecl); } if (TagDecl) @@ -2965,9 +3097,11 @@ void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) { /// mem-initializer ...[opt] /// mem-initializer ...[opt] , mem-initializer-list void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { - assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); + assert(Tok.is(tok::colon) && + "Constructor initializer always starts with ':'"); - // Poison the SEH identifiers so they are flagged as illegal in constructor initializers + // Poison the SEH identifiers so they are flagged as illegal in constructor + // initializers. PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); SourceLocation ColonLoc = ConsumeToken(); @@ -3396,7 +3530,9 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { // Alternative tokens do not have identifier info, but their spelling // starts with an alphabetical character. SmallString<8> SpellingBuf; - StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf); + SourceLocation SpellingLoc = + PP.getSourceManager().getSpellingLoc(Tok.getLocation()); + StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf); if (isLetter(Spelling[0])) { Loc = ConsumeToken(); return &PP.getIdentifierTable().get(Spelling); @@ -3474,7 +3610,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // The attribute was allowed to have arguments, but none were provided // even though the attribute parsed successfully. This is an error. Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; - return false; } else if (!Attr->getMaxArgs()) { // The attribute parsed successfully, but was not allowed to have any // arguments. It doesn't matter whether any were provided -- the @@ -3482,7 +3617,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) << AttrName << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); - return false; } } } |