Use Builtin ID as the return value
for FunctionDecl::getMemoryFunctionKind().

This is a follow up on the Chris's review for r148142: We don't want to
pollute FunctionDecl with an extra enum. (To make this work, added
memcmp and family to the library builtins.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148267 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 5c6b447..4016c20 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1986,26 +1986,11 @@
   /// definition of a member function.
   virtual bool isOutOfLine() const;
 
-  /// \brief Enumeration used to identify memory setting or copying functions
-  /// identified by getMemoryFunctionKind().
-  enum MemoryFunctionKind {
-    MFK_Memset,
-    MFK_Memcpy,
-    MFK_Memmove,
-    MFK_Memcmp,
-    MFK_Strncpy,
-    MFK_Strncmp,
-    MFK_Strncasecmp,
-    MFK_Strncat,
-    MFK_Strndup,
-    MFK_Strlcpy,
-    MFK_Strlcat,
-    MFK_Invalid
-  };
-
-  /// \brief If the given function is a memory copy or setting function, return
-  /// it's kind. If the function is not a memory function, returns MFK_Invalid.
-  MemoryFunctionKind getMemoryFunctionKind();
+  /// \brief Identify a memory copying or setting function.
+  /// If the given function is a memory copy or setting function, returns
+  /// the corresponding Builtin ID. If the function is not a memory function,
+  /// returns 0.
+  unsigned getMemoryFunctionKind();
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 5942e53..e3e2d7c 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -631,9 +631,12 @@
 LIBBUILTIN(realloc, "v*v*z",      "f",     "stdlib.h", ALL_LANGUAGES)
 // C99 string.h
 LIBBUILTIN(memcpy, "v*v*vC*z",    "f",     "string.h", ALL_LANGUAGES)
+LIBBUILTIN(memcmp, "ivC*vC*z",    "f",     "string.h", ALL_LANGUAGES)
 LIBBUILTIN(memmove, "v*v*vC*z",   "f",     "string.h", ALL_LANGUAGES)
 LIBBUILTIN(strcpy, "c*c*cC*",     "f",     "string.h", ALL_LANGUAGES)
 LIBBUILTIN(strncpy, "c*c*cC*z",   "f",     "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strcmp, "icC*cC*",     "f",     "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strncmp, "icC*cC*z",   "f",     "string.h", ALL_LANGUAGES)
 LIBBUILTIN(strcat, "c*c*cC*",     "f",     "string.h", ALL_LANGUAGES)
 LIBBUILTIN(strncat, "c*c*cC*z",   "f",     "string.h", ALL_LANGUAGES)
 LIBBUILTIN(strxfrm, "zc*cC*z",    "f",     "string.h", ALL_LANGUAGES)
@@ -678,6 +681,8 @@
 LIBBUILTIN(index, "c*cC*i",       "f",     "strings.h", ALL_LANGUAGES)
 LIBBUILTIN(rindex, "c*cC*i",      "f",     "strings.h", ALL_LANGUAGES)
 LIBBUILTIN(bzero, "vv*z",         "f",     "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(strcasecmp, "icC*cC*", "f",     "strings.h", ALL_LANGUAGES)
+LIBBUILTIN(strncasecmp, "icC*cC*z", "f",   "strings.h", ALL_LANGUAGES)
 // POSIX unistd.h
 LIBBUILTIN(_exit, "vi",           "fr",    "unistd.h", ALL_LANGUAGES)
 LIBBUILTIN(vfork, "i",            "fj",    "unistd.h", ALL_LANGUAGES)
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index c4af625..242af88 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -6315,7 +6315,7 @@
                                  bool isPrintf);
 
   void CheckMemaccessArguments(const CallExpr *Call,
-                               FunctionDecl::MemoryFunctionKind CMF,
+                               unsigned BId,
                                IdentifierInfo *FnName);
 
   void CheckStrlcpycatArguments(const CallExpr *Call,
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 96766dc..1951363 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2290,80 +2290,83 @@
   return SourceRange(getOuterLocStart(), EndRangeLoc);
 }
 
-FunctionDecl::MemoryFunctionKind FunctionDecl::getMemoryFunctionKind() {
+unsigned FunctionDecl::getMemoryFunctionKind() {
   IdentifierInfo *FnInfo = getIdentifier();
 
   if (!FnInfo)
-    return MFK_Invalid;
+    return 0;
     
   // Builtin handling.
   switch (getBuiltinID()) {
   case Builtin::BI__builtin_memset:
   case Builtin::BI__builtin___memset_chk:
   case Builtin::BImemset:
-    return MFK_Memset;
+    return Builtin::BImemset;
 
   case Builtin::BI__builtin_memcpy:
   case Builtin::BI__builtin___memcpy_chk:
   case Builtin::BImemcpy:
-    return MFK_Memcpy;
+    return Builtin::BImemcpy;
 
   case Builtin::BI__builtin_memmove:
   case Builtin::BI__builtin___memmove_chk:
   case Builtin::BImemmove:
-    return MFK_Memmove;
+    return Builtin::BImemmove;
 
   case Builtin::BIstrlcpy:
-    return MFK_Strlcpy;
+    return Builtin::BIstrlcpy;
   case Builtin::BIstrlcat:
-    return MFK_Strlcat;
+    return Builtin::BIstrlcat;
 
   case Builtin::BI__builtin_memcmp:
-    return MFK_Memcmp;
+  case Builtin::BImemcmp:
+    return Builtin::BImemcmp;
 
   case Builtin::BI__builtin_strncpy:
   case Builtin::BI__builtin___strncpy_chk:
   case Builtin::BIstrncpy:
-    return MFK_Strncpy;
+    return Builtin::BIstrncpy;
 
   case Builtin::BI__builtin_strncmp:
-    return MFK_Strncmp;
+  case Builtin::BIstrncmp:
+    return Builtin::BIstrncmp;
 
   case Builtin::BI__builtin_strncasecmp:
-    return MFK_Strncasecmp;
+  case Builtin::BIstrncasecmp:
+    return Builtin::BIstrncasecmp;
 
   case Builtin::BI__builtin_strncat:
   case Builtin::BIstrncat:
-    return MFK_Strncat;
+    return Builtin::BIstrncat;
 
   case Builtin::BI__builtin_strndup:
   case Builtin::BIstrndup:
-    return MFK_Strndup;
+    return Builtin::BIstrndup;
 
   default:
     if (isExternC()) {
       if (FnInfo->isStr("memset"))
-        return MFK_Memset;
+        return Builtin::BImemset;
       else if (FnInfo->isStr("memcpy"))
-        return MFK_Memcpy;
+        return Builtin::BImemcpy;
       else if (FnInfo->isStr("memmove"))
-        return MFK_Memmove;
+        return Builtin::BImemmove;
       else if (FnInfo->isStr("memcmp"))
-        return MFK_Memcmp;
+        return Builtin::BImemcmp;
       else if (FnInfo->isStr("strncpy"))
-        return MFK_Strncpy;
+        return Builtin::BIstrncpy;
       else if (FnInfo->isStr("strncmp"))
-        return MFK_Strncmp;
+        return Builtin::BIstrncmp;
       else if (FnInfo->isStr("strncasecmp"))
-        return MFK_Strncasecmp;
+        return Builtin::BIstrncasecmp;
       else if (FnInfo->isStr("strncat"))
-        return MFK_Strncat;
+        return Builtin::BIstrncat;
       else if (FnInfo->isStr("strndup"))
-        return MFK_Strndup;
+        return Builtin::BIstrndup;
     }
     break;
   }
-  return MFK_Invalid;
+  return 0;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 77c5717..af0eedd 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -482,15 +482,15 @@
                           TheCall->getCallee()->getLocStart());
   }
 
-  FunctionDecl::MemoryFunctionKind CMF = FDecl->getMemoryFunctionKind();
-  if (CMF == FunctionDecl::MFK_Invalid)
+  unsigned CMId = FDecl->getMemoryFunctionKind();
+  if (CMId == 0)
     return false;
 
   // Handle memory setting and copying functions.
-  if (CMF == FunctionDecl::MFK_Strlcpy || CMF == FunctionDecl::MFK_Strlcat)
+  if (CMId == Builtin::BIstrlcpy || CMId == Builtin::BIstrlcat)
     CheckStrlcpycatArguments(TheCall, FnInfo);
   else
-    CheckMemaccessArguments(TheCall, CMF, FnInfo);
+    CheckMemaccessArguments(TheCall, CMId, FnInfo);
 
   return false;
 }
@@ -2433,17 +2433,19 @@
 ///
 /// \param Call The call expression to diagnose.
 void Sema::CheckMemaccessArguments(const CallExpr *Call,
-                                   FunctionDecl::MemoryFunctionKind CMF,
+                                   unsigned BId,
                                    IdentifierInfo *FnName) {
+  assert(BId != 0);
+
   // It is possible to have a non-standard definition of memset.  Validate
   // we have enough arguments, and if not, abort further checking.
-  unsigned ExpectedNumArgs = (CMF == FunctionDecl::MFK_Strndup ? 2 : 3);
+  unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3);
   if (Call->getNumArgs() < ExpectedNumArgs)
     return;
 
-  unsigned LastArg = (CMF == FunctionDecl::MFK_Memset ||
-                      CMF == FunctionDecl::MFK_Strndup ? 1 : 2);
-  unsigned LenArg = (CMF == FunctionDecl::MFK_Strndup ? 1 : 2);
+  unsigned LastArg = (BId == Builtin::BImemset ||
+                      BId == Builtin::BIstrndup ? 1 : 2);
+  unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
   const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
 
   // We have special checking when the length is a sizeof expression.
@@ -2488,7 +2490,7 @@
             ActionIdx = 2; // If the pointee's size is sizeof(char),
                            // suggest an explicit length.
           unsigned DestSrcSelect =
-            (CMF == FunctionDecl::MFK_Strndup ? 1 : ArgIdx);
+            (BId == Builtin::BIstrndup ? 1 : ArgIdx);
           DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest,
                               PDiag(diag::warn_sizeof_pointer_expr_memaccess)
                                 << FnName << DestSrcSelect << ActionIdx
@@ -2514,19 +2516,29 @@
       }
 
       // Always complain about dynamic classes.
-      if (isDynamicClassType(PointeeTy))
+      if (isDynamicClassType(PointeeTy)) {
+
+        unsigned OperationType = 0;
+        // "overwritten" if we're warning about the destination for any call
+        // but memcmp; otherwise a verb appropriate to the call.
+        if (ArgIdx != 0 || BId == Builtin::BImemcmp) {
+          if (BId == Builtin::BImemcpy)
+            OperationType = 1;
+          else if(BId == Builtin::BImemmove)
+            OperationType = 2;
+          else if (BId == Builtin::BImemcmp)
+            OperationType = 3;
+        }
+          
         DiagRuntimeBehavior(
           Dest->getExprLoc(), Dest,
           PDiag(diag::warn_dyn_class_memaccess)
-            << (CMF == FunctionDecl::MFK_Memcmp ? ArgIdx + 2 : ArgIdx)
+            << (BId == Builtin::BImemcmp ? ArgIdx + 2 : ArgIdx)
             << FnName << PointeeTy
-            // "overwritten" if we're warning about the destination for any call
-            // but memcmp; otherwise a verb appropriate to the call.
-            << (ArgIdx == 0 &&
-                CMF != FunctionDecl::MFK_Memcmp ? 0 : (unsigned)CMF)
+            << OperationType
             << Call->getCallee()->getSourceRange());
-      else if (PointeeTy.hasNonTrivialObjCLifetime() &&
-               CMF != FunctionDecl::MFK_Memset)
+      } else if (PointeeTy.hasNonTrivialObjCLifetime() &&
+               BId != Builtin::BImemset)
         DiagRuntimeBehavior(
           Dest->getExprLoc(), Dest,
           PDiag(diag::warn_arc_object_memaccess)