summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-09-26 03:32:58 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-09-26 03:32:58 +0000
commit980c66946b746faf80a4ffaf6592799989da6f34 (patch)
treeb9bb9de312f0af5122fdb477d8cfbc0e348aa6cc /clang/lib/Sema/SemaDeclAttr.cpp
parent2c793a2ecdc5696dce535c5b04e772c7e8ebde0e (diff)
downloadbcm5719-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.cpp38
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;
}
OpenPOWER on IntegriCloud