[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