Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1754,6 +1754,12 @@ let Documentation = [SomeAttr]; } +def PrivateMethod : InheritableAttr { + let Spellings = [GCC<"objc_private_method">]; + let Subjects = SubjectList<[ObjCMethod]>; + let Documentation = [ObjCPrivateMethodDocs]; +} + def SomeAnotherAttr : InheritableAttr { let Spellings = [GNU<"SomeThing">]; let Subjects = SubjectList<[Method], ErrorDiag>; Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1002,6 +1002,36 @@ }]; } +def ObjCPrivateMethodDocs : Documentation { + + let Category = DocCatFunction; + let Content = [{ + +In order to hide the APIs which are only meant to be used within a module, +there are many interfaces which are declared internally within a source +file (.m/.mm), and several methods which are declared/defined +internally as well. Adding this attribute enables compiler optimizations +that may benefit code size as well as performance. The compiler will remove +the ObjC_msgSend to these calls by devirtualizing the call sites. + +**Usage**: ``__attribute__((objc_private_method))``. This attribute can only +be placed at the end of a objective C method declaration: + +.. code-block:: objc + +@interface MYObject () +- (void)MYObject_privateMethod __attribute__((objc_private_method)); +@end + +This attribute can only be applied to method declarations within a class. + +The user can define a macro that provides syntactic sugar for this attribute. +This macro is conditionally defined depending on the compiler's support for +this attribute. If the compiler does not support the attribute the macro +expands to nothing. + + + def SomeMore : Documentation { let Category = DocCatFunction; let Content = [{ Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2520,6 +2520,8 @@ AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range, IdentifierInfo *Ident, unsigned AttrSpellingListIndex); + PrivateMethodAttr *mergePrivateMethodAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex); OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range, Index: lib/CodeGen/CGObjC.cpp =================================================================== --- lib/CodeGen/CGObjC.cpp +++ lib/CodeGen/CGObjC.cpp @@ -729,6 +729,20 @@ const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD); CGM.SetInternalFunctionAttributes(OMD, Fn, FI); + // Add private method attribute. + if (const ObjCInterfaceDecl *iface = dyn_cast(CD)) { + Selector Sel = OMD->getSelector(); + if (Attr *A = OMD->getAttr()) { + // The attribute may be set in the source code or may be inferred + // in the SemaDeclObjC. + if (!Fn->hasFnAttribute(llvm::Attribute::OptimizeNone)) { + Fn->removeFnAttr(llvm::Attribute::NoInline); + Fn->removeFnAttr(llvm::Attribute::OptimizeNone); + Fn->addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::AlwaysInline); + } + } + } // Always add annotation on definitions so we know what are defined, and // which selector has a unique definition. Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4147,6 +4147,16 @@ InternalLinkageAttr(AL.getRange(), Context, AL.getSpellingListIndex()); } +PrivateMethodAttr * +Sema::mergePrivateMethodAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { + if (D->hasAttr()) + return nullptr; + + return ::new (Context) + PrivateMethodAttr(Range, Context, AttrSpellingListIndex); +} + MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (OptimizeNoneAttr *Optnone = D->getAttr()) { @@ -5058,6 +5068,20 @@ Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex())); } +static void handlePrivateMethodAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (D->getKind() != Decl::ObjCMethod) { + S.Diag(Attr.getLoc(), diag::err_stmt_attribute_invalid_on_decl) + << Attr.getName() << D->getLocation(); + // Drop the attribute. + return; + } + + if (PrivateMethodAttr *A = S.mergePrivateMethodAttr( + D, Attr.getRange(), Attr.getAttributeSpellingListIndex())) + D->addAttr(A); +} + static void handleAttr(Sema &S, Decl *D, const AttributeList &attr, bool Act = false) { @@ -6931,6 +6955,9 @@ case ParsedAttr::AT_Artificial: handleSimpleAttribute(S, D, AL); break; + case AttributeList::AT_PrivateMethod: + handlePrivateMethodAttr(S, D, AL); + break; case ParsedAttr::AT_AnalyzerNoReturn: handleAnalyzerNoReturnAttr(S, D, AL); break;