implement PR5654: add -fassume-sane-operator-new, which is enabled by default, and adds the malloc attribute to the global function new() and to the overloaded new operators.

feel free to chage the name to this lengthy argument

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91543 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 70597ab..8d82318 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -945,6 +945,10 @@
   if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
     CmdArgs.push_back("-fno-builtin");
 
+  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+                    options::OPT_fno_assume_sane_operator_new))
+    CmdArgs.push_back("-fno-assume-sane-operator-new");
+
   // -fblocks=0 is default.
   if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
                    getToolChain().IsBlocksDefault())) {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 7a3388f..025f5dd 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -466,6 +466,8 @@
     Res.push_back("-ffreestanding");
   if (Opts.NoBuiltin)
     Res.push_back("-fno-builtin");
+  if (!Opts.AssumeSaneOperatorNew)
+    Res.push_back("-fno-assume-sane-operator-new");
   if (Opts.ThreadsafeStatics)
     llvm::llvm_report_error("FIXME: Not yet implemented!");
   if (Opts.POSIXThreads)
@@ -1140,6 +1142,7 @@
   Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
   Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
   Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
+  Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
   Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
   Opts.AccessControl = Args.hasArg(OPT_faccess_control);
   Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 473f2c2..bca9ae9 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1976,7 +1976,8 @@
                               bool AllowMissing, FunctionDecl *&Operator);
   void DeclareGlobalNewDelete();
   void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
-                                       QualType Argument);
+                                       QualType Argument,
+                                       bool addMallocAttr = false);
 
   bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, 
                                 DeclarationName Name, FunctionDecl* &Operator);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7a27e11..bf5b350 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2799,6 +2799,11 @@
                                   D.getIdentifierLoc(), Name, R, TInfo,
                                   isStatic, isInline);
 
+    if ((Name.getCXXOverloadedOperator() == OO_New ||
+	 Name.getCXXOverloadedOperator() == OO_Array_New) &&
+	getLangOptions().AssumeSaneOperatorNew)
+      NewFD->addAttr(::new (Context) MallocAttr());
+
     isVirtualOkay = !isStatic;
   } else {
     // Determine whether the function was written with a
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 8870a59..9108137 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -715,13 +715,14 @@
 
   QualType VoidPtr = Context.getPointerType(Context.VoidTy);
   QualType SizeT = Context.getSizeType();
+  bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew;
 
   DeclareGlobalAllocationFunction(
       Context.DeclarationNames.getCXXOperatorName(OO_New),
-      VoidPtr, SizeT);
+      VoidPtr, SizeT, AssumeSaneOperatorNew);
   DeclareGlobalAllocationFunction(
       Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
-      VoidPtr, SizeT);
+      VoidPtr, SizeT, AssumeSaneOperatorNew);
   DeclareGlobalAllocationFunction(
       Context.DeclarationNames.getCXXOperatorName(OO_Delete),
       Context.VoidTy, VoidPtr);
@@ -733,7 +734,8 @@
 /// DeclareGlobalAllocationFunction - Declares a single implicit global
 /// allocation function if it doesn't already exist.
 void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
-                                           QualType Return, QualType Argument) {
+                                           QualType Return, QualType Argument,
+                                           bool AddMallocAttr) {
   DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
 
   // Check if this function is already declared.
@@ -766,6 +768,10 @@
     FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
                          FnType, /*TInfo=*/0, FunctionDecl::None, false, true);
   Alloc->setImplicit();
+  
+  if (AddMallocAttr)
+    Alloc->addAttr(::new (Context) MallocAttr());
+  
   ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
                                            0, Argument, /*TInfo=*/0,
                                            VarDecl::None, 0);