[cfe-commits] r50866 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/Sema/SemaDecl.cpp
Ted Kremenek
kremenek at apple.com
Thu May 8 12:43:35 PDT 2008
Author: kremenek
Date: Thu May 8 14:43:35 2008
New Revision: 50866
URL: http://llvm.org/viewvc/llvm-project?rev=50866&view=rev
Log:
Added initial support for supporting __NSString__ in attribute "format".
Still need to iron out some of the semantics (fixmes are present).
This addresses <rdar://problem/5916348>
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/Sema/SemaDecl.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=50866&r1=50865&r2=50866&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu May 8 14:43:35 2008
@@ -600,6 +600,8 @@
"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_attribute_invalid_size, ERROR,
"vector size not an integral multiple of component size")
DIAG(err_attribute_zero_size, ERROR,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=50866&r1=50865&r2=50866&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 8 14:43:35 2008
@@ -2350,6 +2350,22 @@
return 0;
}
+static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
+ if (!T->isPointerType())
+ return false;
+
+ T = T->getAsPointerType()->getPointeeType().getCanonicalType();
+ ObjCInterfaceType* ClsT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
+
+ if (!ClsT)
+ return false;
+
+ IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
+
+ // FIXME: Should we walk the chain of classes?
+ return ClsName == &Ctx.Idents.get("NSString") ||
+ ClsName == &Ctx.Idents.get("NSMutableString");
+}
/// Handle __attribute__((format(type,idx,firstarg))) attributes
/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
@@ -2393,10 +2409,28 @@
FormatLen -= 4;
}
- if (!((FormatLen == 5 && !memcmp(Format, "scanf", 5))
- || (FormatLen == 6 && !memcmp(Format, "printf", 6))
- || (FormatLen == 7 && !memcmp(Format, "strfmon", 7))
- || (FormatLen == 8 && !memcmp(Format, "strftime", 8)))) {
+ bool Supported = false;
+ bool is_NSString = false;
+ bool is_strftime = false;
+
+ switch (FormatLen) {
+ default: break;
+ case 5:
+ Supported = !memcmp(Format, "scanf", 5);
+ break;
+ 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));
+ break;
+ }
+
+ if (!Supported) {
Diag(rawAttr->getLoc(), diag::warn_attribute_type_not_supported,
"format", rawAttr->getParameterName()->getName());
return;
@@ -2417,16 +2451,32 @@
return;
}
+ // FIXME: Do we need to bounds check?
+ unsigned ArgIdx = Idx.getZExtValue() - 1;
+
// make sure the format string is really a string
- QualType Ty = proto->getArgType(Idx.getZExtValue()-1);
- if (!Ty->isPointerType() ||
+ QualType Ty = proto->getArgType(ArgIdx);
+
+ if (is_NSString) {
+ // FIXME: do we need to check if the type is NSString*? What are
+ // the semantics?
+ if (!isNSStringType(Ty, Context)) {
+ // FIXME: Should highlight the actual expression that has the
+ // wrong type.
+ Diag(rawAttr->getLoc(), diag::err_format_attribute_not_NSString,
+ IdxExpr->getSourceRange());
+ return;
+ }
+ }
+ else if (!Ty->isPointerType() ||
!Ty->getAsPointerType()->getPointeeType()->isCharType()) {
+ // FIXME: Should highlight the actual expression that has the
+ // wrong type.
Diag(rawAttr->getLoc(), diag::err_format_attribute_not_string,
IdxExpr->getSourceRange());
return;
}
-
// check the 3rd argument
Expr *FirstArgExpr = static_cast<Expr *>(rawAttr->getArg(1));
llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
@@ -2448,7 +2498,7 @@
// strftime requires FirstArg to be 0 because it doesn't read from any variable
// the input is just the current time + the format string
- if (FormatLen == 8 && !memcmp(Format, "strftime", 8)) {
+ if (is_strftime) {
if (FirstArg != 0) {
Diag(rawAttr->getLoc(), diag::err_format_strftime_third_parameter,
FirstArgExpr->getSourceRange());
More information about the cfe-commits
mailing list