Author: rjmccall Date: Wed Mar 2 05:33:24 2011 New Revision: 126839 URL: http://llvm.org/viewvc/llvm-project?rev=126839&view=rev Log: Provide an attribute, objc_method_family, to allow the inferred family of an Objective-C method to be overridden on a case-by-case basis. This is a higher-level tool than ns_returns_retained &c.; it lets users specify that not only does a method have different retain/release semantics, but that it semantically acts differently than one might assume from its name. This in turn is quite useful to static analysis.
Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/AttributeList.h cfe/trunk/lib/AST/DeclObjC.cpp cfe/trunk/lib/Lex/PPMacroExpansion.cpp cfe/trunk/lib/Sema/AttributeList.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Wed Mar 2 05:33:24 2011 @@ -369,6 +369,15 @@ let Spellings = ["objc_exception"]; } +def ObjCMethodFamily : InheritableAttr { + let Spellings = ["objc_method_family"]; + let Subjects = [ObjCMethod]; + let Args = [EnumArgument<"Family", "FamilyKind", + ["none", "alloc", "copy", "init", "mutableCopy", "new"], + ["OMF_None", "OMF_alloc", "OMF_copy", "OMF_init", + "OMF_mutableCopy", "OMF_new"]>]; +} + def ObjCNSObject : InheritableAttr { let Spellings = ["NSObject"]; } Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 2 05:33:24 2011 @@ -1028,6 +1028,7 @@ def err_format_attribute_implicit_this_format_string : Error< "format attribute cannot specify the implicit this argument as the format " "string">; +def warn_unknown_method_family : Warning<"unrecognized method family">; def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; Modified: cfe/trunk/include/clang/Sema/AttributeList.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/AttributeList.h (original) +++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Mar 2 05:33:24 2011 @@ -125,6 +125,7 @@ AT_nothrow, AT_nsobject, AT_objc_exception, + AT_objc_method_family, AT_cf_returns_not_retained, // Clang-specific. AT_cf_returns_retained, // Clang-specific. AT_ns_returns_not_retained, // Clang-specific. Modified: cfe/trunk/lib/AST/DeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclObjC.cpp (original) +++ cfe/trunk/lib/AST/DeclObjC.cpp Wed Mar 2 05:33:24 2011 @@ -403,6 +403,22 @@ if (family != InvalidObjCMethodFamily) return family; + // Check for an explicit attribute. + if (const ObjCMethodFamilyAttr *attr = getAttr<ObjCMethodFamilyAttr>()) { + // The unfortunate necessity of mapping between enums here is due + // to the attributes framework. + switch (attr->getFamily()) { + case ObjCMethodFamilyAttr::OMF_None: family = OMF_None; break; + case ObjCMethodFamilyAttr::OMF_alloc: family = OMF_alloc; break; + case ObjCMethodFamilyAttr::OMF_copy: family = OMF_copy; break; + case ObjCMethodFamilyAttr::OMF_init: family = OMF_init; break; + case ObjCMethodFamilyAttr::OMF_mutableCopy: family = OMF_mutableCopy; break; + case ObjCMethodFamilyAttr::OMF_new: family = OMF_new; break; + } + Family = static_cast<unsigned>(family); + return family; + } + family = getSelector().getMethodFamily(); switch (family) { case OMF_None: break; Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Mar 2 05:33:24 2011 @@ -540,6 +540,7 @@ .Case("attribute_ns_consumed", true) .Case("attribute_cf_consumed", true) .Case("attribute_objc_ivar_unused", true) + .Case("attribute_objc_method_family", true) .Case("attribute_overloadable", true) .Case("attribute_unavailable_with_message", true) .Case("blocks", LangOpts.Blocks) Modified: cfe/trunk/lib/Sema/AttributeList.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/lib/Sema/AttributeList.cpp (original) +++ cfe/trunk/lib/Sema/AttributeList.cpp Wed Mar 2 05:33:24 2011 @@ -98,6 +98,7 @@ .Case("returns_twice", IgnoredAttribute) .Case("vec_type_hint", IgnoredAttribute) .Case("objc_exception", AT_objc_exception) + .Case("objc_method_family", AT_objc_method_family) .Case("ext_vector_type", AT_ext_vector_type) .Case("neon_vector_type", AT_neon_vector_type) .Case("neon_polyvector_type", AT_neon_polyvector_type) Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=126839&r1=126838&r2=126839&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Mar 2 05:33:24 2011 @@ -1094,6 +1094,51 @@ d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); } +static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr, + Sema &S) { + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl); + if (!method) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_decl_type) + << 13; // methods + return; + } + + if (attr.getNumArgs() != 0 || !attr.getParameterName()) { + if (!attr.getParameterName() && attr.getNumArgs() == 1) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "objc_method_family" << 1; + } else { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + } + attr.setInvalid(); + return; + } + + llvm::StringRef param = attr.getParameterName()->getName(); + ObjCMethodFamilyAttr::FamilyKind family; + if (param == "none") + family = ObjCMethodFamilyAttr::OMF_None; + else if (param == "alloc") + family = ObjCMethodFamilyAttr::OMF_alloc; + else if (param == "copy") + family = ObjCMethodFamilyAttr::OMF_copy; + else if (param == "init") + family = ObjCMethodFamilyAttr::OMF_init; + else if (param == "mutableCopy") + family = ObjCMethodFamilyAttr::OMF_mutableCopy; + else if (param == "new") + family = ObjCMethodFamilyAttr::OMF_new; + else { + // Just warn and ignore it. This is future-proof against new + // families being used in system headers. + S.Diag(attr.getParameterLoc(), diag::warn_unknown_method_family); + return; + } + + decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(), + S.Context, family)); +} + static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (Attr.getNumArgs() != 0) { @@ -2752,6 +2797,9 @@ case AttributeList::AT_objc_exception: HandleObjCExceptionAttr(D, Attr, S); break; + case AttributeList::AT_objc_method_family: + HandleObjCMethodFamilyAttr(D, Attr, S); + break; case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits