diff options
| author | Daniel Dunbar <daniel@zuster.org> | 2008-09-26 03:32:58 +0000 |
|---|---|---|
| committer | Daniel Dunbar <daniel@zuster.org> | 2008-09-26 03:32:58 +0000 |
| commit | 980c66946b746faf80a4ffaf6592799989da6f34 (patch) | |
| tree | b9bb9de312f0af5122fdb477d8cfbc0e348aa6cc /clang/lib/Sema/SemaDeclAttr.cpp | |
| parent | 2c793a2ecdc5696dce535c5b04e772c7e8ebde0e (diff) | |
| download | bcm5719-llvm-980c66946b746faf80a4ffaf6592799989da6f34.tar.gz bcm5719-llvm-980c66946b746faf80a4ffaf6592799989da6f34.zip | |
Add support for CFString in format attribute.
llvm-svn: 56639
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c014e355699..764724aeca0 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/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; } |

