diff options
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 211 |
1 files changed, 165 insertions, 46 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 45e1c3e465ce..ad4005747310 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -25,6 +25,7 @@ #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaDiagnostic.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -301,10 +302,10 @@ unsigned Parser::ParseAttributeArgsCommon( // Parse the non-empty comma-separated list of expressions. do { - std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated; - if (attributeParsedArgsUnevaluated(*AttrName)) - Unevaluated.reset( - new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated)); + bool ShouldEnter = attributeParsedArgsUnevaluated(*AttrName); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::Unevaluated, /*LambdaContextDecl=*/nullptr, + /*IsDecltype=*/false, ShouldEnter); ExprResult ArgExpr( Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); @@ -366,13 +367,13 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, // These may refer to the function arguments, but need to be parsed early to // participate in determining whether it's a redeclaration. - std::unique_ptr<ParseScope> PrototypeScope; + llvm::Optional<ParseScope> PrototypeScope; if (normalizeAttrName(AttrName->getName()) == "enable_if" && D && D->isFunctionDeclarator()) { DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo(); - PrototypeScope.reset(new ParseScope(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | - Scope::DeclScope)); + PrototypeScope.emplace(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope); for (unsigned i = 0; i != FTI.NumParams; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param); Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param); @@ -605,6 +606,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { case tok::kw___fastcall: case tok::kw___stdcall: case tok::kw___thiscall: + case tok::kw___regcall: case tok::kw___cdecl: case tok::kw___vectorcall: case tok::kw___ptr64: @@ -1407,39 +1409,53 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { << attrs.Range; } -void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { - AttributeList *AttrList = attrs.getList(); - while (AttrList) { - if (AttrList->isCXX11Attribute()) { - Diag(AttrList->getLoc(), diag::err_attribute_not_type_attr) - << AttrList->getName(); - AttrList->setInvalid(); +void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, + unsigned DiagID) { + for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) { + if (!Attr->isCXX11Attribute()) + continue; + if (Attr->getKind() == AttributeList::UnknownAttribute) + Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored) + << Attr->getName(); + else { + Diag(Attr->getLoc(), DiagID) + << Attr->getName(); + Attr->setInvalid(); } - AttrList = AttrList->getNext(); } } +// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute +// applies to var, not the type Foo. // As an exception to the rule, __declspec(align(...)) before the // class-key affects the type instead of the variable. -void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs, - DeclSpec &DS, - Sema::TagUseKind TUK) { +// Also, Microsoft-style [attributes] seem to affect the type instead of the +// variable. +// This function moves attributes that should apply to the type off DS to Attrs. +void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, + DeclSpec &DS, + Sema::TagUseKind TUK) { if (TUK == Sema::TUK_Reference) return; ParsedAttributes &PA = DS.getAttributes(); AttributeList *AL = PA.getList(); AttributeList *Prev = nullptr; + AttributeList *TypeAttrHead = nullptr; + AttributeList *TypeAttrTail = nullptr; while (AL) { AttributeList *Next = AL->getNext(); - // We only consider attributes using the appropriate '__declspec' spelling. - // This behavior doesn't extend to any other spellings. - if (AL->getKind() == AttributeList::AT_Aligned && - AL->isDeclspecAttribute()) { + if ((AL->getKind() == AttributeList::AT_Aligned && + AL->isDeclspecAttribute()) || + AL->isMicrosoftAttribute()) { // Stitch the attribute into the tag's attribute list. - AL->setNext(nullptr); - Attrs.add(AL); + if (TypeAttrTail) + TypeAttrTail->setNext(AL); + else + TypeAttrHead = AL; + TypeAttrTail = AL; + TypeAttrTail->setNext(nullptr); // Remove the attribute from the variable's attribute list. if (Prev) { @@ -1457,6 +1473,12 @@ void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs, AL = Next; } + + // Find end of type attributes Attrs and add NewTypeAttributes in the same + // order they were in originally. (Remember, in AttributeList things earlier + // in source order are later in the list, since new attributes are added to + // the front of the list.) + Attrs.addAllAtEnd(TypeAttrHead); } /// ParseDeclaration - Parse a full 'declaration', which consists of @@ -1484,7 +1506,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, ObjCDeclContextSwitch ObjCDC(*this); Decl *SingleDecl = nullptr; - Decl *OwnedType = nullptr; switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: @@ -1504,9 +1525,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, ProhibitAttributes(attrs); return ParseNamespace(Context, DeclEnd); case tok::kw_using: - SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), - DeclEnd, attrs, &OwnedType); - break; + return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), + DeclEnd, attrs); case tok::kw_static_assert: case tok::kw__Static_assert: ProhibitAttributes(attrs); @@ -1517,9 +1537,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, } // This routine returns a DeclGroup, if the thing we parsed only contains a - // single decl, convert it now. Alias declarations can also declare a type; - // include that too if it is present. - return Actions.ConvertDeclToDeclGroup(SingleDecl, OwnedType); + // single decl, convert it now. + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] @@ -2717,7 +2736,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Reject C++11 attributes that appertain to decl specifiers as // we don't support any C++11 attributes that appertain to decl // specifiers. This also conforms to what g++ 4.8 is doing. - ProhibitCXX11Attributes(attrs); + ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr); DS.takeAttributesFrom(attrs); } @@ -3117,6 +3136,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___regcall: case tok::kw___vectorcall: ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; @@ -4067,7 +4087,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } - handleDeclspecAlignBeforeClassKey(attrs, DS, TUK); + stripTypeAttributesOffDeclSpec(attrs, DS, TUK); Sema::SkipBodyInfo SkipBody; if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) && @@ -4169,7 +4189,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // C does not allow an empty enumerator-list, C++ does [dcl.enum]. if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) - Diag(Tok, diag::error_empty_enum); + Diag(Tok, diag::err_empty_enum); SmallVector<Decl *, 32> EnumConstantDecls; SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags; @@ -4224,7 +4244,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { if (Tok.is(tok::identifier)) { // We're missing a comma between enumerators. - SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); + SourceLocation Loc = getEndOfPreviousToken(); Diag(Loc, diag::err_enumerator_list_missing_comma) << FixItHint::CreateInsertion(Loc, ", "); continue; @@ -4434,6 +4454,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___regcall: case tok::kw___vectorcall: case tok::kw___w64: case tok::kw___ptr64: @@ -4618,6 +4639,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___regcall: case tok::kw___vectorcall: case tok::kw___w64: case tok::kw___sptr: @@ -4856,6 +4878,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___regcall: case tok::kw___vectorcall: if (AttrReqs & AR_DeclspecAttributesParsed) { ParseMicrosoftTypeAttributes(DS.getAttributes()); @@ -5200,12 +5223,22 @@ static SourceLocation getMissingDeclaratorIdLoc(Declarator &D, /// '~' class-name /// template-id /// +/// C++17 adds the following, which we also handle here: +/// +/// simple-declaration: +/// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';' +/// /// Note, any additional constructs added here may need corresponding changes /// in isConstructorDeclarator. void Parser::ParseDirectDeclarator(Declarator &D) { DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec()); if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) { + // This might be a C++17 structured binding. + if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() && + D.getCXXScopeSpec().isEmpty()) + return ParseDecompositionDeclarator(D); + // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in // this context it is a bitfield. Also in range-based for statement colon // may delimit for-range-declaration. @@ -5228,6 +5261,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Change the declaration context for name lookup, until this function // is exited (and the declarator has been parsed). DeclScopeObj.EnterDeclaratorScope(); + else if (getObjCDeclContext()) { + // Ensure that we don't interpret the next token as an identifier when + // dealing with declarations in an Objective-C container. + D.SetIdentifier(nullptr, Tok.getLocation()); + D.setInvalidType(true); + ConsumeToken(); + goto PastIdentifier; + } } // C++0x [dcl.fct]p14: @@ -5435,6 +5476,70 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } } +void Parser::ParseDecompositionDeclarator(Declarator &D) { + assert(Tok.is(tok::l_square)); + + // If this doesn't look like a structured binding, maybe it's a misplaced + // array declarator. + // FIXME: Consume the l_square first so we don't need extra lookahead for + // this. + if (!(NextToken().is(tok::identifier) && + GetLookAheadToken(2).isOneOf(tok::comma, tok::r_square)) && + !(NextToken().is(tok::r_square) && + GetLookAheadToken(2).isOneOf(tok::equal, tok::l_brace))) + return ParseMisplacedBracketDeclarator(D); + + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + + SmallVector<DecompositionDeclarator::Binding, 32> Bindings; + while (Tok.isNot(tok::r_square)) { + if (!Bindings.empty()) { + if (Tok.is(tok::comma)) + ConsumeToken(); + else { + if (Tok.is(tok::identifier)) { + SourceLocation EndLoc = getEndOfPreviousToken(); + Diag(EndLoc, diag::err_expected) + << tok::comma << FixItHint::CreateInsertion(EndLoc, ","); + } else { + Diag(Tok, diag::err_expected_comma_or_rsquare); + } + + SkipUntil(tok::r_square, tok::comma, tok::identifier, + StopAtSemi | StopBeforeMatch); + if (Tok.is(tok::comma)) + ConsumeToken(); + else if (Tok.isNot(tok::identifier)) + break; + } + } + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected) << tok::identifier; + break; + } + + Bindings.push_back({Tok.getIdentifierInfo(), Tok.getLocation()}); + ConsumeToken(); + } + + if (Tok.isNot(tok::r_square)) + // We've already diagnosed a problem here. + T.skipToEnd(); + else { + // C++17 does not allow the identifier-list in a structured binding + // to be empty. + if (Bindings.empty()) + Diag(Tok.getLocation(), diag::ext_decomp_decl_empty); + + T.consumeClose(); + } + + return D.setDecompositionBindings(T.getOpenLocation(), Bindings, + T.getCloseLocation()); +} + /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is /// only called before the identifier, so these are most likely just grouping /// parens for precedence. If we find that these are actually function @@ -5719,6 +5824,21 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } } + // Collect non-parameter declarations from the prototype if this is a function + // declaration. They will be moved into the scope of the function. Only do + // this in C and not C++, where the decls will continue to live in the + // surrounding context. + SmallVector<NamedDecl *, 0> DeclsInPrototype; + if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope && + !getLangOpts().CPlusPlus) { + for (Decl *D : getCurScope()->decls()) { + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (!ND || isa<ParmVarDecl>(ND)) + continue; + DeclsInPrototype.push_back(ND); + } + } + // Remember that we parsed a function type, and remember the attributes. D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, IsAmbiguous, @@ -5738,6 +5858,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, ExceptionSpecTokens, + DeclsInPrototype, StartLoc, LocalEndLoc, D, TrailingReturnType), FnAttrs, EndLoc); @@ -5783,7 +5904,8 @@ bool Parser::isFunctionDeclaratorIdentifierList() { // To handle this, we check to see if the token after the first // identifier is a "," or ")". Only then do we parse it as an // identifier list. - && (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)); + && (!Tok.is(tok::eof) && + (NextToken().is(tok::comma) || NextToken().is(tok::r_paren))); } /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator @@ -5921,7 +6043,7 @@ void Parser::ParseParameterDeclarationClause( // DefArgToks is used when the parsing of default arguments needs // to be delayed. - CachedTokens *DefArgToks = nullptr; + std::unique_ptr<CachedTokens> DefArgToks; // If no parameter was specified, verify that *something* was specified, // otherwise we have a missing type and identifier. @@ -5957,13 +6079,11 @@ void Parser::ParseParameterDeclarationClause( // If we're inside a class definition, cache the tokens // corresponding to the default argument. We'll actually parse // them when we see the end of the class definition. - // FIXME: Can we use a smart pointer for Toks? - DefArgToks = new CachedTokens; + DefArgToks.reset(new CachedTokens); SourceLocation ArgStartLoc = NextToken().getLocation(); if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) { - delete DefArgToks; - DefArgToks = nullptr; + DefArgToks.reset(); Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); } else { Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc, @@ -5999,7 +6119,7 @@ void Parser::ParseParameterDeclarationClause( ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, ParmDeclarator.getIdentifierLoc(), - Param, DefArgToks)); + Param, std::move(DefArgToks))); } if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { @@ -6149,8 +6269,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { T.consumeClose(); - ParsedAttributes attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); + MaybeParseCXX11Attributes(DS.getAttributes()); // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), @@ -6158,7 +6277,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { NumElements.get(), T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + DS.getAttributes(), T.getCloseLocation()); } /// Diagnose brackets before an identifier. |