diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -101,6 +101,10 @@ [{!S->isStatic() && !S->isConst()}], "non-static non-const member functions">; +def FunctionDefinition : SubsetSubjectisThisDeclarationADefinition()}], + "function definition">; + def ObjCInstanceMethod : SubsetSubjectisInstanceMethod()}], "Objective-C instance methods">; @@ -417,8 +421,11 @@ def SubRuleForCXXMethod : AttrSubjectMatcherSubRule<"is_member", [CXXMethod]> { let LangOpts = [CPlusPlus]; } +// function(is_definition) +def SubRuleForFunctionDefiniton + : AttrSubjectMatcherSubRule<"is_definition", [FunctionDefinition]> {} def SubjectMatcherForFunction : AttrSubjectMatcherRule<"function", [Function], [ - SubRuleForCXXMethod + SubRuleForCXXMethod, SubRuleForFunctionDefiniton ]>; // hasType is abstract, it should be used with one of the sub-rules. def SubjectMatcherForType : AttrSubjectMatcherRule<"hasType", [], [ diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7690,6 +7690,26 @@ } } +namespace { +/// The `attribute push` matcher `function(is_definition)` needs to know if a +/// function declaration is a definition but we might check before the relevant +/// parts have been parsed. This RAII helper will set the `WillHaveBody` flag +/// if appropriate to make the matcher possible. +struct MarkDeclerationsForParamMatcherRAII { + FunctionDecl *FD; + bool OldWillHaveBody; + MarkDeclerationsForParamMatcherRAII(FunctionDecl *FD, const Declarator &PD) + : FD(FD), OldWillHaveBody(FD && FD->willHaveBody()) { + if (FD && PD.isFunctionDefinition()) + FD->setWillHaveBody(true); + } + ~MarkDeclerationsForParamMatcherRAII() { + if (FD) + FD->setWillHaveBody(OldWillHaveBody); + } +}; +} // namespace + /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. @@ -7710,7 +7730,10 @@ ProcessDeclAttributeList(S, D, PD.getAttributes()); // Apply additional attributes specified by '#pragma clang attribute'. - AddPragmaAttributes(S, D); + { + MarkDeclerationsForParamMatcherRAII MDFPM(dyn_cast(D), PD); + AddPragmaAttributes(S, D); + } } /// Is the given declaration allowed to use a forbidden type?