Add support for CFString in format attribute.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56639 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2008-09-26 03:32:58 +00:00
Родитель 248e1c01d3
Коммит 085e8f7da3
3 изменённых файлов: 40 добавлений и 11 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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}}