Add a warning (-Wnon-pod-memset) for calls to memset() with
a destination pointer that points to a non-POD type. This can flag such
horrible bugs as overwriting vptrs when a previously POD structure is
suddenly given a virtual method, or creating objects that crash on
practically any use by zero-ing out a member when its changed from
a const char* to a std::string, etc.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130299 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 9dec259..6b21961 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -318,6 +318,10 @@
                           TheCall->getCallee()->getLocStart());
   }
 
+  // Memset handling
+  if (FnInfo->isStr("memset"))
+    CheckMemsetArguments(TheCall);
+
   return false;
 }
 
@@ -1791,6 +1795,36 @@
   }
 }
 
+//===--- CHECK: Standard memory functions ---------------------------------===//
+
+/// \brief Check for dangerous or invalid arguments to memset().
+///
+/// This issues warnings on known problematic or dangerous or unspecified
+/// arguments to the standard 'memset' function call.
+///
+/// \param Call The call expression to diagnose.
+void Sema::CheckMemsetArguments(const CallExpr *Call) {
+  assert(Call->getNumArgs() == 3 && "Unexpected number of arguments to memset");
+  const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts();
+
+  QualType DestTy = Dest->getType();
+  if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
+    QualType PointeeTy = DestPtrTy->getPointeeType();
+    if (!PointeeTy->isPODType()) {
+      DiagRuntimeBehavior(
+        Dest->getExprLoc(), Dest,
+        PDiag(diag::warn_non_pod_memset)
+          << PointeeTy << Call->getCallee()->getSourceRange());
+
+      SourceRange ArgRange = Call->getArg(0)->getSourceRange();
+      DiagRuntimeBehavior(
+        Dest->getExprLoc(), Dest,
+        PDiag(diag::note_non_pod_memset_silence)
+          << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
+    }
+  }
+}
+
 //===--- CHECK: Return Address of Stack Variable --------------------------===//
 
 static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars);