]> granicus.if.org Git - clang/commitdiff
Add support for CFString in format attribute.
authorDaniel Dunbar <daniel@zuster.org>
Fri, 26 Sep 2008 03:32:58 +0000 (03:32 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 26 Sep 2008 03:32:58 +0000 (03:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56639 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
lib/Sema/SemaDeclAttr.cpp
test/SemaObjC/format-strings-objc.m

index bbeea2a52c43cee51f2ebc68d32f60059d6dd0b5..92e56ba80a07e6eb0e23d451cb87a685af98f93a 100644 (file)
@@ -658,10 +658,8 @@ DIAG(err_format_strftime_third_parameter, ERROR,
      "strftime format attribute requires 3rd parameter to be 0")
 DIAG(err_format_attribute_requires_variadic, ERROR,
      "format attribute requires variadic function")
-DIAG(err_format_attribute_not_string, ERROR,
-     "format argument not a string type")
-DIAG(err_format_attribute_not_NSString, ERROR,
-    "format argument is not an NSString")
+DIAG(err_format_attribute_not, ERROR,
+     "format argument not %0")
 DIAG(err_attribute_invalid_size, ERROR,
      "vector size not an integral multiple of component size")
 DIAG(err_attribute_zero_size, ERROR,
index c014e355699506c1efd7828c3eaec3148582f06e..764724aeca032f0830966787e294fe379c2cdd01 100644 (file)
@@ -61,6 +61,22 @@ static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
          ClsName == &Ctx.Idents.get("NSMutableString");
 }
 
+static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
+  const PointerType *PT = T->getAsPointerType();
+  if (!PT)
+    return false;
+
+  const RecordType *RT = PT->getPointeeType()->getAsRecordType();
+  if (!RT)
+    return false;
+  
+  const RecordDecl *RD = RT->getDecl();
+  if (RD->getTagKind() != TagDecl::TK_struct)
+    return false;
+
+  return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
+}
+
 //===----------------------------------------------------------------------===//
 // Attribute Implementations
 //===----------------------------------------------------------------------===//
@@ -648,6 +664,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   bool Supported = false;
   bool is_NSString = false;
   bool is_strftime = false;
+  bool is_CFString = false;
   
   switch (FormatLen) {
   default: break;
@@ -655,8 +672,9 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   case 6: Supported = !memcmp(Format, "printf", 6); break;
   case 7: Supported = !memcmp(Format, "strfmon", 7); break;
   case 8:
-    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) || 
-                (is_NSString = !memcmp(Format, "NSString", 8));
+    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
+                (is_NSString = !memcmp(Format, "NSString", 8)) ||
+                (is_CFString = !memcmp(Format, "CFString", 8));
     break;
   }
       
@@ -687,22 +705,28 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // make sure the format string is really a string
   QualType Ty = proto->getArgType(ArgIdx);
 
-  if (is_NSString) {
+  if (is_CFString) {
+    if (!isCFStringType(Ty, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not,
+             "a CFString", IdxExpr->getSourceRange());
+      return;
+    }
+  } else if (is_NSString) {
     // FIXME: do we need to check if the type is NSString*?  What are
     //  the semantics?
     if (!isNSStringType(Ty, S.Context)) {
       // FIXME: Should highlight the actual expression that has the
       // wrong type.
-      S.Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
-             IdxExpr->getSourceRange());
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not,
+             "an NSString", IdxExpr->getSourceRange());
       return;
     }    
   } else if (!Ty->isPointerType() ||
              !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
     // FIXME: Should highlight the actual expression that has the
     // wrong type.
-    S.Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
-           IdxExpr->getSourceRange());
+    S.Diag(Attr.getLoc(), diag::err_format_attribute_not,
+           "a string type", IdxExpr->getSourceRange());
     return;
   }
 
index bdf12082a70c724b58b449aa3b831fc87dbb0731..42c21705b50b3fb89e42bcfd0185d9f40fef0d85 100644 (file)
@@ -26,6 +26,9 @@ typedef float CGFloat;
 @interface NSConstantString : NSSimpleCString @end
 extern void *_NSConstantStringClassReference;
 
+typedef const struct __CFString * CFStringRef;
+extern void CFStringCreateWithFormat(CFStringRef format, ...) __attribute__((format(CFString, 1, 2)));
+
 //===----------------------------------------------------------------------===//
 // Test cases.
 //===----------------------------------------------------------------------===//
@@ -34,3 +37,7 @@ void check_nslog(unsigned k) {
   NSLog(@"%d%%", k); // no-warning
   NSLog(@"%s%lb%d", "unix", 10,20); // expected-warning {{lid conversion '%lb'}}
 }
+
+// Check type validation
+extern void NSLog2(int format, ...) __attribute__((format(__NSString__, 1, 2))); // expected-error {{format argument not an NSString}}
+extern void CFStringCreateWithFormat2(int *format, ...) __attribute__((format(CFString, 1, 2))); // expected-error {{format argument not a CFString}}