diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 06e02ed0e11c..7234a656e9d1 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -225,6 +225,7 @@ Parser::LateParsedDeclaration::~LateParsedDeclaration() {} void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {} void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} +void Parser::LateParsedDeclaration::ParseLexedAttributes() {} void Parser::LateParsedDeclaration::ParseLexedPragmas() {} Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) @@ -246,6 +247,10 @@ void Parser::LateParsedClass::ParseLexedMethodDefs() { Self->ParseLexedMethodDefs(*Class); } +void Parser::LateParsedClass::ParseLexedAttributes() { + Self->ParseLexedAttributes(*Class); +} + void Parser::LateParsedClass::ParseLexedPragmas() { Self->ParseLexedPragmas(*Class); } @@ -262,6 +267,10 @@ void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() { Self->ParseLexedMemberInitializer(*this); } +void Parser::LateParsedAttribute::ParseLexedAttributes() { + Self->ParseLexedAttribute(*this, true, false); +} + void Parser::LateParsedPragma::ParseLexedPragmas() { Self->ParseLexedPragma(*this); } @@ -662,6 +671,141 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { ConsumeAnyToken(); } +/// Wrapper class which calls ParseLexedAttribute, after setting up the +/// scope appropriately. +void Parser::ParseLexedAttributes(ParsingClass &Class) { + // Deal with templates + // FIXME: Test cases to make sure this does the right thing for templates. + bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; + ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, + HasTemplateScope); + if (HasTemplateScope) + Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); + + // Set or update the scope flags. + bool AlreadyHasClassScope = Class.TopLevelClass; + unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope; + ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); + ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); + + // Enter the scope of nested classes + if (!AlreadyHasClassScope) + Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), + Class.TagOrTemplate); + if (!Class.LateParsedDeclarations.empty()) { + for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){ + Class.LateParsedDeclarations[i]->ParseLexedAttributes(); + } + } + + if (!AlreadyHasClassScope) + Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), + Class.TagOrTemplate); +} + +/// Parse all attributes in LAs, and attach them to Decl D. +void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, + bool EnterScope, bool OnDefinition) { + assert(LAs.parseSoon() && + "Attribute list should be marked for immediate parsing."); + for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) { + if (D) + LAs[i]->addDecl(D); + ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition); + delete LAs[i]; + } + LAs.clear(); +} + +/// 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, + bool EnterScope, bool OnDefinition) { + // Create a fake EOF so that attribute parsing won't go off the end of the + // attribute. + Token AttrEnd; + AttrEnd.startToken(); + AttrEnd.setKind(tok::eof); + AttrEnd.setLocation(Tok.getLocation()); + AttrEnd.setEofData(LA.Toks.data()); + LA.Toks.push_back(AttrEnd); + + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LA.Toks.push_back(Tok); + PP.EnterTokenStream(LA.Toks, true, /*IsReinject=*/true); + // Consume the previously pushed token. + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); + + ParsedAttributes Attrs(AttrFactory); + SourceLocation endLoc; + + if (LA.Decls.size() > 0) { + Decl *D = LA.Decls[0]; + NamedDecl *ND = dyn_cast(D); + RecordDecl *RD = dyn_cast_or_null(D->getDeclContext()); + + // Allow 'this' within late-parsed attributes. + Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(), + ND && ND->isCXXInstanceMember()); + + if (LA.Decls.size() == 1) { + // If the Decl is templatized, add template parameters to scope. + bool HasTemplateScope = EnterScope && D->isTemplateDecl(); + ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); + if (HasTemplateScope) + Actions.ActOnReenterTemplateScope(Actions.CurScope, D); + + // If the Decl is on a function, add function parameters to the scope. + bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate(); + ParseScope FnScope( + this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, + HasFunScope); + if (HasFunScope) + Actions.ActOnReenterFunctionContext(Actions.CurScope, D); + + ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, + nullptr, SourceLocation(), ParsedAttr::AS_GNU, + nullptr); + + if (HasFunScope) { + Actions.ActOnExitFunctionContext(); + FnScope.Exit(); // Pop scope, and remove Decls from IdResolver + } + if (HasTemplateScope) { + TempScope.Exit(); + } + } else { + // If there are multiple decls, then the decl cannot be within the + // function scope. + ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, + nullptr, SourceLocation(), ParsedAttr::AS_GNU, + nullptr); + } + } else { + Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); + } + + if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && + Attrs.begin()->isKnownToGCC()) + Diag(Tok, diag::warn_attribute_on_function_definition) + << &LA.AttrName; + + for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) + Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs); + + // Due to a parsing error, we either went over the cached tokens or + // there are still cached tokens left, so we skip the leftover tokens. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData()) + ConsumeAnyToken(); +} + void Parser::ParseLexedPragmas(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 79a3b19bac57..f336af6f1abc 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1409,154 +1409,6 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, Syntax); } -// Late Parsed Attributes: -// See other examples of late parsing in lib/Parse/ParseCXXInlineMethods - -void Parser::LateParsedDeclaration::ParseLexedAttributes() {} - -void Parser::LateParsedClass::ParseLexedAttributes() { - Self->ParseLexedAttributes(*Class); -} - -void Parser::LateParsedAttribute::ParseLexedAttributes() { - Self->ParseLexedAttribute(*this, true, false); -} - -/// Wrapper class which calls ParseLexedAttribute, after setting up the -/// scope appropriately. -void Parser::ParseLexedAttributes(ParsingClass &Class) { - // Deal with templates - // FIXME: Test cases to make sure this does the right thing for templates. - bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; - ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, - HasTemplateScope); - if (HasTemplateScope) - Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); - - // Set or update the scope flags. - bool AlreadyHasClassScope = Class.TopLevelClass; - unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope; - ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); - ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); - - // Enter the scope of nested classes - if (!AlreadyHasClassScope) - Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), - Class.TagOrTemplate); - if (!Class.LateParsedDeclarations.empty()) { - for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){ - Class.LateParsedDeclarations[i]->ParseLexedAttributes(); - } - } - - if (!AlreadyHasClassScope) - Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), - Class.TagOrTemplate); -} - -/// Parse all attributes in LAs, and attach them to Decl D. -void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, - bool EnterScope, bool OnDefinition) { - assert(LAs.parseSoon() && - "Attribute list should be marked for immediate parsing."); - for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) { - if (D) - LAs[i]->addDecl(D); - ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition); - delete LAs[i]; - } - LAs.clear(); -} - -/// 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, - bool EnterScope, bool OnDefinition) { - // Create a fake EOF so that attribute parsing won't go off the end of the - // attribute. - Token AttrEnd; - AttrEnd.startToken(); - AttrEnd.setKind(tok::eof); - AttrEnd.setLocation(Tok.getLocation()); - AttrEnd.setEofData(LA.Toks.data()); - LA.Toks.push_back(AttrEnd); - - // Append the current token at the end of the new token stream so that it - // doesn't get lost. - LA.Toks.push_back(Tok); - PP.EnterTokenStream(LA.Toks, true, /*IsReinject=*/true); - // Consume the previously pushed token. - ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - - ParsedAttributes Attrs(AttrFactory); - SourceLocation endLoc; - - if (LA.Decls.size() > 0) { - Decl *D = LA.Decls[0]; - NamedDecl *ND = dyn_cast(D); - RecordDecl *RD = dyn_cast_or_null(D->getDeclContext()); - - // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(), - ND && ND->isCXXInstanceMember()); - - if (LA.Decls.size() == 1) { - // If the Decl is templatized, add template parameters to scope. - bool HasTemplateScope = EnterScope && D->isTemplateDecl(); - ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); - if (HasTemplateScope) - Actions.ActOnReenterTemplateScope(Actions.CurScope, D); - - // If the Decl is on a function, add function parameters to the scope. - bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate(); - ParseScope FnScope( - this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, - HasFunScope); - if (HasFunScope) - Actions.ActOnReenterFunctionContext(Actions.CurScope, D); - - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), ParsedAttr::AS_GNU, - nullptr); - - if (HasFunScope) { - Actions.ActOnExitFunctionContext(); - FnScope.Exit(); // Pop scope, and remove Decls from IdResolver - } - if (HasTemplateScope) { - TempScope.Exit(); - } - } else { - // If there are multiple decls, then the decl cannot be within the - // function scope. - ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), ParsedAttr::AS_GNU, - nullptr); - } - } else { - Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); - } - - if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && - Attrs.begin()->isKnownToGCC()) - Diag(Tok, diag::warn_attribute_on_function_definition) - << &LA.AttrName; - - for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) - Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs); - - // Due to a parsing error, we either went over the cached tokens or - // there are still cached tokens left, so we skip the leftover tokens. - while (Tok.isNot(tok::eof)) - ConsumeAnyToken(); - - if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData()) - ConsumeAnyToken(); -} - void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs,