]> granicus.if.org Git - clang/commitdiff
implement PR5654: add -fassume-sane-operator-new, which is enabled by default, and...
authorNuno Lopes <nunoplopes@sapo.pt>
Wed, 16 Dec 2009 16:59:22 +0000 (16:59 +0000)
committerNuno Lopes <nunoplopes@sapo.pt>
Wed, 16 Dec 2009 16:59:22 +0000 (16:59 +0000)
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

include/clang/Basic/LangOptions.h
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExprCXX.cpp
test/CodeGenCXX/new.cpp
test/CodeGenCXX/operator-new.cpp [new file with mode: 0644]
test/CodeGenCXX/static-init.cpp

index e17279e2664a6df7e8e1ea44dae5e59d513be27e..2b6092dea3095c1d81ab4147b35160ad441f5ddd 100644 (file)
@@ -89,7 +89,10 @@ public:
   unsigned ShortWChar        : 1; // Force wchar_t to be unsigned short int.
 
   unsigned OpenCL            : 1; // OpenCL C99 language extensions.
-
+  
+  unsigned AssumeSaneOperatorNew : 1; // Whether to add __attribute__((malloc))
+                                      // to the declaration of C++'s new
+                                      // operators
   unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
                                   // elided if possible.
   unsigned CatchUndefined     :1; // Generate code to check for undefined ops.
@@ -141,6 +144,8 @@ public:
     EmitAllDecls = 0;
     MathErrno = 1;
 
+    AssumeSaneOperatorNew = 1;
+
     // FIXME: The default should be 1.
     AccessControl = 0;
     ElideConstructors = 1;
index a9566f3f9d4711fa787261d0458ef36ead5a9e77..e830e473df8f07b29584ff1bacdd50b664122ca8 100644 (file)
@@ -304,6 +304,8 @@ def faltivec : Flag<"-faltivec">,
   HelpText<"Enable AltiVec vector initializer syntax">;
 def faccess_control : Flag<"-faccess-control">,
   HelpText<"Enable C++ access control">;
+def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">,
+  HelpText<"Don't assume that C++'s new operator is sane">;
 def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
   HelpText<"Allow '$' in identifiers">;
 def femit_all_decls : Flag<"-femit-all-decls">,
index 3592fc9468462eace41b56de53958e4de6fcc818..7b0ce6702595b7d5343ceb287c7bfee98542f6a1 100644 (file)
@@ -226,6 +226,7 @@ def fPIC : Flag<"-fPIC">, Group<f_Group>;
 def fPIE : Flag<"-fPIE">, Group<f_Group>;
 def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>;
 def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>;
+def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>;
 def fastcp : Flag<"-fastcp">, Group<f_Group>;
 def fastf : Flag<"-fastf">, Group<f_Group>;
 def fast : Flag<"-fast">, Group<f_Group>;
@@ -277,6 +278,7 @@ def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
 def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
 def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>;
 def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>;
+def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>;
 def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>;
 def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>;
 def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>;
index 70597ab91396382b132a3bee0ee663a9e5842764..8d823181279091361c50e1b14470839d5b95d49d 100644 (file)
@@ -945,6 +945,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   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())) {
index 7a3388ffbb97fd0d49921aeb7ce5c4417526a932..025f5ddf94d0db8b51ed3530072cfd62803f887e 100644 (file)
@@ -466,6 +466,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
     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 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
   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);
index 473f2c2820d2d7466476ada5909eeb30b4d36bd3..bca9ae9e5bc959cdbe89b1444e0109b769bb666c 100644 (file)
@@ -1976,7 +1976,8 @@ public:
                               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);
index 7a27e1185e316357635f660a1587abd3ea2095b7..bf5b350da0d51915f34488cf9d738cb124090a56 100644 (file)
@@ -2799,6 +2799,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                   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
index 8870a59d136e6b99a696c84fd377254b5e98cf8a..9108137a0008d1b590c1becab621f437c7afcd60 100644 (file)
@@ -715,13 +715,14 @@ void Sema::DeclareGlobalNewDelete() {
 
   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 @@ void Sema::DeclareGlobalNewDelete() {
 /// 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 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
     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);
index f3c14a78d362a7b2cab720f0404737572adf8d51..6ea12eb5f6badfa031e3ee279223a10d6498d4d0 100644 (file)
@@ -92,7 +92,7 @@ A* t10() {
 
 struct B { };
 void t11() {
-  // CHECK: call i8* @_Znwm
+  // CHECK: call noalias i8* @_Znwm
   // CHECK: call void @llvm.memset.i64(
   B* b = new B();
 }
diff --git a/test/CodeGenCXX/operator-new.cpp b/test/CodeGenCXX/operator-new.cpp
new file mode 100644 (file)
index 0000000..6becaae
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -o %t-1.ll %s
+// RUN: FileCheck -check-prefix SANE --input-file=%t-1.ll %s
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -fno-assume-sane-operator-new -o %t-2.ll %s
+// RUN: FileCheck -check-prefix SANENOT --input-file=%t-2.ll %s
+
+
+class teste {
+  int A;
+  teste() : A(2) {}
+  void* operator new(unsigned) {return ::new teste();}
+};
+
+void f1() {
+  new teste();
+}
+
+// CHECK-SANE: define linkonce_odr noalias i8* @_ZN5testenwEj(
+// CHECK-SANE: declare noalias i8* @_Znwj(
+
+// CHECK-SANENOT: define linkonce_odr i8* @_ZN5testenwEj(
+// CHECK-SANENOT: declare i8* @_Znwj(
index 2ad6e9411f48db712e06de533cf2dcb29c6b2033..cbd90e7894069b919ace21dd80d698a56fd94a1f 100644 (file)
@@ -11,7 +11,7 @@ void f() {
 }
 
 void g() {
-  // CHECK: call i8* @_Znwm(i64 1)
+  // CHECK: call noalias i8* @_Znwm(i64 1)
   // CHECK: call void @_ZN1AC1Ev(
   static A& a = *new A;
 }