diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 55 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 9 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 21 |
3 files changed, 69 insertions, 16 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 914a5acd09..0b98274002 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -132,14 +132,15 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, if (Tok.is(tok::l_paren)) { // handle "parameterized" attributes - if (LateAttrs && !ClassStack.empty() && - isAttributeLateParsed(*AttrName)) { - // Delayed parsing is only available for attributes that occur - // in certain locations within a class scope. + if (LateAttrs && isAttributeLateParsed(*AttrName)) { LateParsedAttribute *LA = new LateParsedAttribute(this, *AttrName, AttrNameLoc); LateAttrs->push_back(LA); - getCurrentClass().LateParsedDeclarations.push_back(LA); + + // Attributes in a class are parsed at the end of the class, along + // with other late-parsed declarations. + if (!ClassStack.empty()) + getCurrentClass().LateParsedDeclarations.push_back(LA); // consume everything up to and including the matching right parens ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false); @@ -711,7 +712,7 @@ void Parser::LateParsedClass::ParseLexedAttributes() { } void Parser::LateParsedAttribute::ParseLexedAttributes() { - Self->ParseLexedAttribute(*this); + Self->ParseLexedAttribute(*this, true, false); } /// Wrapper class which calls ParseLexedAttribute, after setting up the @@ -736,12 +737,25 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { } } + +/// \brief Parse all attributes in LAs, and attach them to Decl D. +void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, + bool EnterScope, bool OnDefinition) { + for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) { + LAs[i]->setDecl(D); + ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition); + } + LAs.clear(); +} + + /// \brief Finish parsing an attribute for which parsing was delayed. /// This will be called at the end of parsing a class declaration /// for each LateParsedAttribute. We consume the saved tokens and /// create an attribute with the arguments filled in. We add this /// to the Attribute list for the decl. -void Parser::ParseLexedAttribute(LateParsedAttribute &LA) { +void Parser::ParseLexedAttribute(LateParsedAttribute &LA, + bool EnterScope, bool OnDefinition) { // Save the current token position. SourceLocation OrigLoc = Tok.getLocation(); @@ -752,17 +766,23 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA) { // Consume the previously pushed token. ConsumeAnyToken(); + if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) { + Diag(Tok, diag::warn_attribute_on_function_definition) + << LA.AttrName.getName(); + } + ParsedAttributes Attrs(AttrFactory); SourceLocation endLoc; // If the Decl is templatized, add template parameters to scope. - bool HasTemplateScope = LA.D && LA.D->isTemplateDecl(); + bool HasTemplateScope = EnterScope && LA.D && LA.D->isTemplateDecl(); ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); if (HasTemplateScope) Actions.ActOnReenterTemplateScope(Actions.CurScope, LA.D); // If the Decl is on a function, add function parameters to the scope. - bool HasFunctionScope = LA.D && LA.D->isFunctionOrFunctionTemplate(); + bool HasFunctionScope = EnterScope && LA.D && + LA.D->isFunctionOrFunctionTemplate(); ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope); if (HasFunctionScope) Actions.ActOnReenterFunctionContext(Actions.CurScope, LA.D); @@ -1064,6 +1084,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, return DeclGroupPtrTy(); } + // Save late-parsed attributes for now; they need to be parsed in the + // appropriate function scope after the function Decl has been constructed. + LateParsedAttrList LateParsedAttrs; + if (D.isFunctionDeclarator()) + MaybeParseGNUAttributes(D, &LateParsedAttrs); + // Check to see if we have a function *definition* which must have a body. if (AllowFunctionDefinitions && D.isFunctionDeclarator() && // Look at the next token to make sure that this isn't a function @@ -1079,7 +1105,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, DS.ClearStorageClassSpecs(); } - Decl *TheDecl = ParseFunctionDefinition(D); + Decl *TheDecl = + ParseFunctionDefinition(D, ParsedTemplateInfo(), &LateParsedAttrs); return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -1096,7 +1123,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } } - if (ParseAttributesAfterDeclarator(D)) + if (ParseAsmAttributesAfterDeclarator(D)) return DeclGroupPtrTy(); // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we @@ -1117,6 +1144,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, SmallVector<Decl *, 8> DeclsInGroup; Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D); + if (LateParsedAttrs.size() > 0) + ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); if (FirstDecl) DeclsInGroup.push_back(FirstDecl); @@ -1185,7 +1214,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, /// Parse an optional simple-asm-expr and attributes, and attach them to a /// declarator. Returns true on an error. -bool Parser::ParseAttributesAfterDeclarator(Declarator &D) { +bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) { // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { SourceLocation Loc; @@ -1227,7 +1256,7 @@ bool Parser::ParseAttributesAfterDeclarator(Declarator &D) { /// Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo) { - if (ParseAttributesAfterDeclarator(D)) + if (ParseAsmAttributesAfterDeclarator(D)) return 0; return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 1222fb08f5..a30ef96d63 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -241,6 +241,10 @@ Parser::ParseSingleDeclarationAfterTemplate( return 0; } + LateParsedAttrList LateParsedAttrs; + if (DeclaratorInfo.isFunctionDeclarator()) + MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); + // If we have a declaration or declarator list, handle it. if (isDeclarationAfterDeclarator()) { // Parse this declaration. @@ -256,6 +260,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // Eat the semi colon after the declaration. ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); + if (LateParsedAttrs.size() > 0) + ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); DeclaratorInfo.complete(ThisDecl); return ThisDecl; } @@ -270,7 +276,8 @@ Parser::ParseSingleDeclarationAfterTemplate( << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); DS.ClearStorageClassSpecs(); } - return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo); + return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo, + &LateParsedAttrs); } if (DeclaratorInfo.isFunctionDeclarator()) diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4d8f474514..c797436948 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -821,7 +821,8 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, /// decl-specifier-seq[opt] declarator function-try-block /// Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo) { + const ParsedTemplateInfo &TemplateInfo, + LateParsedAttrList *LateParsedAttrs) { // Poison the SEH identifiers so they are flagged as illegal in function bodies PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); @@ -844,7 +845,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (FTI.isKNRPrototype()) ParseKNRParamDeclarations(D); - // We should have either an opening brace or, in a C++ constructor, // we may have a colon. if (Tok.isNot(tok::l_brace) && @@ -861,6 +861,19 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return 0; } + // Check to make sure that any normal attributes are allowed to be on + // a definition. Late parsed attributes are checked at the end. + if (Tok.isNot(tok::equal)) { + AttributeList *DtorAttrs = D.getAttributes(); + while (DtorAttrs) { + if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName())) { + Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) + << DtorAttrs->getName()->getName(); + } + DtorAttrs = DtorAttrs->getNext(); + } + } + // In delayed template parsing mode, for function template we consume the // tokens and store them for late parsing at the end of the translation unit. if (getLang().DelayedTemplateParsing && @@ -974,6 +987,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, } else Actions.ActOnDefaultCtorInitializers(Res); + // Late attributes are parsed in the same scope as the function body. + if (LateParsedAttrs) + ParseLexedAttributeList(*LateParsedAttrs, Res, false, true); + return ParseFunctionStatementBody(Res, BodyScope); } |