]> granicus.if.org Git - clang/commitdiff
Simplify HandleFormatAttr.
authorDaniel Dunbar <daniel@zuster.org>
Sun, 18 Oct 2009 02:09:17 +0000 (02:09 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Sun, 18 Oct 2009 02:09:17 +0000 (02:09 +0000)
 - I have this crazy dream that one day someone will invent a miraculous tool so
   that developers, instead of hand optimizing their source code to obscure its
   intent and decrease its maleability, will instead write what they mean, and
   this strange and wonderful tool -- which I imagine would be called something
   fancy sounding like "an optimizing compiler" -- will make their code fast
   *for* them. With all the saved time, developers could maybe even focus on
   making the magic "optimizing compiler" better!!

 - No intended functionality change, all though I expect the universe to mock me
   for snarkiness.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84390 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclAttr.cpp

index 50ebb49e7d5b49222bfa49d8e0118454b2da6d46..e57111f6cd882208e918335ee2b6f111721c2b05 100644 (file)
@@ -1202,6 +1202,35 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
 }
 
+enum FormatAttrKind {
+  CFStringFormat,
+  NSStringFormat,
+  StrftimeFormat,
+  SupportedFormat,
+  InvalidFormat
+};
+
+/// getFormatAttrKind - Map from format attribute names to supported format
+/// types.
+static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
+  // Check for formats that get handled specially.
+  if (Format == "NSString")
+    return NSStringFormat;
+  if (Format == "CFString")
+    return CFStringFormat;
+  if (Format == "strftime")
+    return StrftimeFormat;
+
+  // Otherwise, check for supported formats.
+  if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
+      Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
+      Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
+      Format == "zcmn_err")
+    return SupportedFormat;
+
+  return InvalidFormat;
+}
+
 /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
 /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
 static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1226,40 +1255,17 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
   unsigned FirstIdx = 1;
 
-  const char *Format = Attr.getParameterName()->getName();
-  unsigned FormatLen = Attr.getParameterName()->getLength();
+  llvm::StringRef Format = Attr.getParameterName()->getNameStr();
 
   // Normalize the argument, __foo__ becomes foo.
-  if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
-      Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
-    Format += 2;
-    FormatLen -= 4;
-  }
-
-  bool Supported = false;
-  bool is_NSString = false;
-  bool is_strftime = false;
-  bool is_CFString = 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, "printf0", 7) ||
-                      !memcmp(Format, "strfmon", 7) ||
-                      !memcmp(Format, "cmn_err", 7); break;
-  case 8:
-    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
-                (is_NSString = !memcmp(Format, "NSString", 8)) ||
-                !memcmp(Format, "vcmn_err", 8) ||
-                !memcmp(Format, "zcmn_err", 8) ||
-                (is_CFString = !memcmp(Format, "CFString", 8));
-    break;
-  }
+  if (Format.startswith("__") && Format.endswith("__"))
+    Format = Format.substr(2, Format.size() - 4);
 
-  if (!Supported) {
+  // Check for supported formats.
+  FormatAttrKind Kind = getFormatAttrKind(Format);
+  if (Kind == InvalidFormat) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
-      << "format" << Attr.getParameterName()->getName();
+      << "format" << Attr.getParameterName()->getNameStr();
     return;
   }
 
@@ -1296,13 +1302,13 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // make sure the format string is really a string
   QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
 
-  if (is_CFString) {
+  if (Kind == CFStringFormat) {
     if (!isCFStringType(Ty, S.Context)) {
       S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
         << "a CFString" << IdxExpr->getSourceRange();
       return;
     }
-  } else if (is_NSString) {
+  } else if (Kind == NSStringFormat) {
     // FIXME: do we need to check if the type is NSString*?  What are the
     // semantics?
     if (!isNSStringType(Ty, S.Context)) {
@@ -1340,7 +1346,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
 
   // 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 (is_strftime) {
+  if (Kind == StrftimeFormat) {
     if (FirstArg != 0) {
       S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
         << FirstArgExpr->getSourceRange();
@@ -1353,8 +1359,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     return;
   }
 
-  d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen),
-                            Idx.getZExtValue(), FirstArg.getZExtValue()));
+  d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(),
+                                          FirstArg.getZExtValue()));
 }
 
 static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,