From: Daniel Dunbar Date: Fri, 26 Sep 2008 03:32:58 +0000 (+0000) Subject: Add support for CFString in format attribute. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=085e8f7da37a227ceee7f98b724e0a42e04d01ca;p=clang Add support for CFString in format attribute. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56639 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index bbeea2a52c..92e56ba80a 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index c014e35569..764724aeca 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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; } diff --git a/test/SemaObjC/format-strings-objc.m b/test/SemaObjC/format-strings-objc.m index bdf12082a7..42c21705b5 100644 --- a/test/SemaObjC/format-strings-objc.m +++ b/test/SemaObjC/format-strings-objc.m @@ -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}}