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 @@ -1858,6 +1858,7 @@ def NSErrorDomain : Attr { let Spellings = [GNU<"ns_error_domain">]; + let Subjects = SubjectList<[Enum]>; let Args = [IdentifierArgument<"ErrorDomain">]; let Documentation = [NSErrorDomainDocs]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3314,9 +3314,31 @@ } def NSErrorDomainDocs : Documentation { - let Category = DocCatFunction; + let Category = DocCatType; let Content = [{ -The ``ns_error_domain`` attribute indicates a global constant representing the error domain. +In Cocoa frameworks in Objective-C, one can group related error codes in enums +and categorize these enums with error domains. + +The ``ns_error_domain`` attribute indicates a global constant representing the +error domain that error codes belong to. This attribute is attached to enums +that describe error codes. + +This metadata is useful for documentation purposes, for static analysis, and for +improving interoperability between Objective-C and Swift. It is not used for +code generation in Objective-C. + +For example: + + .. code-block:: objc + + #define NS_ERROR_ENUM(_type, _name, _domain) \ + enum _name : _type _name; enum __attribute__((ns_error_domain(_domain))) _name : _type + + const char *MyErrorDomain; + typedef NS_ERROR_ENUM(unsigned char, MyErrorEnum, MyErrorDomain) { + MyErrFirst, + MyErrSecond, + }; }]; } 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 @@ -5327,9 +5327,9 @@ D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs)); } -static void handleNSErrorDomain(Sema &S, Decl *D, const AttributeList &Attr) { +static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &Attr) { if (!isa(D)) { - S.Diag(D->getLocStart(), diag::err_nserrordomain_not_tagdecl) + S.Diag(D->getBeginLoc(), diag::err_nserrordomain_not_tagdecl) << S.getLangOpts().CPlusPlus; return; } @@ -5339,7 +5339,7 @@ // Try to locate the argument directly SourceLocation loc = Attr.getLoc(); if (Attr.isArgExpr(0) && Attr.getArgAsExpr(0)) - loc = Attr.getArgAsExpr(0)->getLocStart(); + loc = Attr.getArgAsExpr(0)->getBeginLoc(); S.Diag(loc, diag::err_nserrordomain_requires_identifier); return; @@ -5357,8 +5357,7 @@ } D->addAttr(::new (S.Context) - NSErrorDomainAttr(Attr.getRange(), S.Context, identLoc->Ident, - Attr.getAttributeSpellingListIndex())); + NSErrorDomainAttr(S.Context, Attr, identLoc->Ident)); } static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -7132,8 +7131,8 @@ case ParsedAttr::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; - case AttributeList::AT_NSErrorDomain: - handleNSErrorDomain(S, D, Attr); + case ParsedAttr::AT_NSErrorDomain: + handleNSErrorDomain(S, D, AL); break; case ParsedAttr::AT_CFAuditedTransfer: handleSimpleAttributeWithExclusions