Simplify HandleFormatAttr.
 - 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
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 50ebb49..e57111f 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1202,6 +1202,35 @@
   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 @@
   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;
-  }
+  if (Format.startswith("__") && Format.endswith("__"))
+    Format = Format.substr(2, Format.size() - 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 (!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 @@
   // 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 @@
 
   // 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 @@
     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,