Teach the warning about non-POD memset/memcpy/memmove to deal with the
__builtin_ versions of these functions as well as the normal function
versions, so that it works on platforms where memset/memcpy/memmove
are macros that map down to the builtins (e.g., Darwin). Fixes
<rdar://problem/9372688>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133173 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 81506bf..54900e0 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -320,12 +320,41 @@
   }
 
   // Memset/memcpy/memmove handling
-  if (FDecl->getLinkage() == ExternalLinkage &&
-      (!getLangOptions().CPlusPlus || FDecl->isExternC())) {
-    if (FnInfo->isStr("memset") || FnInfo->isStr("memcpy") || 
-        FnInfo->isStr("memmove"))
-      CheckMemsetcpymoveArguments(TheCall, FnInfo);
+  int CMF = -1;
+  switch (FDecl->getBuiltinID()) {
+  case Builtin::BI__builtin_memset:
+  case Builtin::BI__builtin___memset_chk:
+  case Builtin::BImemset:
+    CMF = CMF_Memset;
+    break;
+    
+  case Builtin::BI__builtin_memcpy:
+  case Builtin::BI__builtin___memcpy_chk:
+  case Builtin::BImemcpy:
+    CMF = CMF_Memcpy;
+    break;
+    
+  case Builtin::BI__builtin_memmove:
+  case Builtin::BI__builtin___memmove_chk:
+  case Builtin::BImemmove:
+    CMF = CMF_Memmove;
+    break;
+    
+  default:
+    if (FDecl->getLinkage() == ExternalLinkage &&
+        (!getLangOptions().CPlusPlus || FDecl->isExternC())) {
+      if (FnInfo->isStr("memset"))
+        CMF = CMF_Memset;
+      else if (FnInfo->isStr("memcpy"))
+        CMF = CMF_Memcpy;
+      else if (FnInfo->isStr("memmove"))
+        CMF = CMF_Memmove;
+    }
+    break;
   }
+   
+  if (CMF != -1)
+    CheckMemsetcpymoveArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo);
 
   return false;
 }
@@ -1856,14 +1885,14 @@
 ///
 /// \param Call The call expression to diagnose.
 void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call,
-                                       const IdentifierInfo *FnName) {
+                                       CheckedMemoryFunction CMF,
+                                       IdentifierInfo *FnName) {
   // It is possible to have a non-standard definition of memset.  Validate
-  // we have the proper number of arguments, and if not, abort further
-  // checking.
-  if (Call->getNumArgs() != 3)
+  // we have enough arguments, and if not, abort further checking.
+  if (Call->getNumArgs() < 3)
     return;
 
-  unsigned LastArg = FnName->isStr("memset")? 1 : 2;
+  unsigned LastArg = (CMF == CMF_Memset? 1 : 2);
   const Expr *LenExpr = Call->getArg(2)->IgnoreParenImpCasts();
 
   // We have special checking when the length is a sizeof expression.
@@ -1934,8 +1963,7 @@
       // Always complain about dynamic classes.
       if (isDynamicClassType(PointeeTy))
         DiagID = diag::warn_dyn_class_memaccess;
-      else if (PointeeTy.hasNonTrivialObjCLifetime() && 
-               !FnName->isStr("memset"))
+      else if (PointeeTy.hasNonTrivialObjCLifetime() && CMF != CMF_Memset)
         DiagID = diag::warn_arc_object_memaccess;
       else
         continue;