diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index a2f7b7a5bc1f..085d2bac1dea 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3594,9 +3594,10 @@ def NSErrorDomainDocs : Documentation { 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 ``NSString`` constant -representing the error domain that an error code belongs to. For pointer -uniqueness and code size this is a constant symbol, not a literal. +The ``ns_error_domain`` attribute indicates a global ``NSString`` or +``CFString`` constant representing the error domain that an error code belongs +to. For pointer uniqueness and code size this is a constant symbol, not a +literal. The domain and error code need to be used together. The ``ns_error_domain`` attribute links error codes to their domain at the source level. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 63475811b117..554d5943a63a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9597,7 +9597,7 @@ def err_nsreturns_retained_attribute_mismatch : Error< def err_nserrordomain_invalid_decl : Error< "domain argument %select{|%1 }0does not refer to global constant">; def err_nserrordomain_wrong_type : Error< - "domain argument %0 does not point to an NSString constant">; + "domain argument %0 does not point to an NSString or CFString constant">; def warn_nsconsumed_attribute_mismatch : Warning< err_nsconsumed_attribute_mismatch.Text>, InGroup; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ec3ea9ebd85e..a2df339151fb 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5436,7 +5436,8 @@ static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (!isNSStringType(VD->getType(), S.Context)) { + if (!isNSStringType(VD->getType(), S.Context) && + !isCFStringType(VD->getType(), S.Context)) { S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD; return; } diff --git a/clang/test/Sema/ns_error_enum.m b/clang/test/Sema/ns_error_enum.m index c8323d903d15..895f9b8b3356 100644 --- a/clang/test/Sema/ns_error_enum.m +++ b/clang/test/Sema/ns_error_enum.m @@ -36,9 +36,24 @@ typedef NS_ERROR_ENUM(unsigned char, MyTypedefErrorEnum, MyTypedefErrorDomain) { MyTypedefErrSecond, }; +typedef const struct __CFString * CFStringRef; + +extern CFStringRef const MyCFErrorDomain; +typedef NS_ERROR_ENUM(unsigned char, MyCFErrorEnum, MyCFErrorDomain) { + MyCFErrFirst, + MyCFErrSecond, +}; + +typedef CFStringRef CFErrorDomain; +extern CFErrorDomain const MyCFTypedefErrorDomain; +typedef NS_ERROR_ENUM(unsigned char, MyCFTypedefErrorEnum, MyCFTypedefErrorDomain) { + MyCFTypedefErrFirst, + MyCFTypedefErrSecond, +}; + extern char *const WrongErrorDomainType; enum __attribute__((ns_error_domain(WrongErrorDomainType))) MyWrongErrorDomainType { MyWrongErrorDomain }; -// expected-error@-1{{domain argument 'WrongErrorDomainType' does not point to an NSString constant}} +// expected-error@-1{{domain argument 'WrongErrorDomainType' does not point to an NSString or CFString constant}} struct __attribute__((ns_error_domain(MyErrorDomain))) MyStructWithErrorDomain {}; // expected-error@-1{{'ns_error_domain' attribute only applies to enums}}