[clang] 22dea69 - [clang][ObjC] allow the use of NSAttributedString * argument type with format attribute

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 11 13:24:46 PDT 2021


Author: Alex Lorenz
Date: 2021-06-11T13:24:32-07:00
New Revision: 22dea6923155b18d172db64e5dab4b71afe19e6e

URL: https://github.com/llvm/llvm-project/commit/22dea6923155b18d172db64e5dab4b71afe19e6e
DIFF: https://github.com/llvm/llvm-project/commit/22dea6923155b18d172db64e5dab4b71afe19e6e.diff

LOG: [clang][ObjC] allow the use of NSAttributedString * argument type with format attribute

This is useful for APIs that want to accept an attributed NSString as their format string

rdar://79163229

Added: 
    

Modified: 
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/test/SemaObjC/format-strings-objc.m

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 2448636bdd52..17fe8c071345 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3471,7 +3471,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   } else if (Kind == NSStringFormat) {
     // FIXME: do we need to check if the type is NSString*?  What are the
     // semantics?
-    if (!isNSStringType(Ty, S.Context)) {
+    if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true)) {
       S.Diag(AL.getLoc(), diag::err_format_attribute_not)
         << "an NSString" << IdxExpr->getSourceRange()
         << getFunctionOrMethodParamRange(D, ArgIdx);

diff  --git a/clang/test/SemaObjC/format-strings-objc.m b/clang/test/SemaObjC/format-strings-objc.m
index e5a1a824abba..d80424487c6f 100644
--- a/clang/test/SemaObjC/format-strings-objc.m
+++ b/clang/test/SemaObjC/format-strings-objc.m
@@ -34,6 +34,11 @@ @interface NSSimpleCString : NSString {} @end
 @interface NSConstantString : NSSimpleCString @end
 extern void *_NSConstantStringClassReference;
 
+ at interface NSAttributedString : NSObject
++(instancetype)stringWithFormat:(NSAttributedString *)fmt, ...
+    __attribute__((format(__NSString__, 1, 2)));
+ at end
+
 typedef const struct __CFString * CFStringRef;
 extern void CFStringCreateWithFormat(CFStringRef format, ...) __attribute__((format(CFString, 1, 2)));
 #define CFSTR(cStr)  ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr ""))
@@ -317,6 +322,9 @@ - (NSString *)someRandomMethod:(NSString *)key
                          value:(nullable NSString *)value
                          table:(nullable NSString *)tableName
     __attribute__((format_arg(1)));
+
+- (NSAttributedString *)someMethod2:(NSString *)key
+    __attribute__((format_arg(1)));
 @end
 
 void useLocalizedStringForKey(NSBundle *bndl) {
@@ -341,4 +349,9 @@ void useLocalizedStringForKey(NSBundle *bndl) {
               [bndl someRandomMethod:@"flerp"
                                value:0
                                table:0], 42]; // expected-warning{{data argument not used by format string}}
+
+  [NSAttributedString stringWithFormat:
+              [bndl someMethod2: @"test"], 5]; // expected-warning{{data argument not used by format string}}
+  [NSAttributedString stringWithFormat:
+              [bndl someMethod2: @"%f"], 42]; // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
 }


        


More information about the cfe-commits mailing list