diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index db2b0f6fd5027..e4a66fad29c83 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -424,7 +424,8 @@ Bug Fixes to Attribute Support (#GH141504) and on types returned from indirect calls (#GH142453). - Fixes some late parsed attributes, when applied to function definitions, not being parsed in function try blocks, and some situations where parsing of the function body - is skipped, such as error recovery and code completion. (#GH153551) + is skipped, such as error recovery, code completion, and msvc-compatible delayed + template parsing. (#GH153551) - Using ``[[gnu::cleanup(some_func)]]`` where some_func is annotated with ``[[gnu::error("some error")]]`` now correctly triggers an error. (#GH146520) - Fix a crash when the function name is empty in the `swift_name` attribute. (#GH157075) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index bbff627d46600..ec01faf446e8d 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1272,7 +1272,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // tokens and store them for late parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && TemplateInfo.Kind == ParsedTemplateKind::Template && - Actions.canDelayFunctionBody(D)) { + LateParsedAttrs->empty() && Actions.canDelayFunctionBody(D)) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | @@ -1301,10 +1301,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, } return DP; } - else if (CurParsedObjCImpl && - !TemplateInfo.TemplateParams && - (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || - Tok.is(tok::colon)) && + if (CurParsedObjCImpl && !TemplateInfo.TemplateParams && + (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && Actions.CurContext->isTranslationUnit()) { ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope); @@ -1420,7 +1418,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Late attributes are parsed in the same scope as the function body. if (LateParsedAttrs) - ParseLexedAttributeList(*LateParsedAttrs, Res, false, true); + ParseLexedAttributeList(*LateParsedAttrs, Res, /*EnterScope=*/false, + /*OnDefinition=*/true); if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && trySkippingFunctionBody()) { diff --git a/clang/test/Parser/DelayedTemplateParsing.cpp b/clang/test/Parser/DelayedTemplateParsing.cpp index bcd286ae04492..072c7ce5162ee 100644 --- a/clang/test/Parser/DelayedTemplateParsing.cpp +++ b/clang/test/Parser/DelayedTemplateParsing.cpp @@ -43,10 +43,10 @@ void undeclared() } -template void foo5() {} //expected-note {{previous definition is here}} +template void foo5() {} //expected-note {{previous definition is here}} template void foo5() {} // expected-error {{redefinition of 'foo5'}} - + namespace PR11931 { @@ -195,3 +195,12 @@ template struct PR38460_2 { } }; template struct PR38460_2; + +namespace LateParsedAttrs { + template + void f(int a) __attribute__((__diagnose_if__(a > 0, "foo", "error"))) {} + // expected-note@-1 {{from 'diagnose_if' attribute on 'f'}} + void g() { + f(1); // expected-error {{foo}} + } +} // namespace LateParsedAttrs