diff options
-rw-r--r-- | include/clang/Basic/LangOptions.h | 7 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 2 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 12 | ||||
-rw-r--r-- | test/CodeGenCXX/new.cpp | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/operator-new.cpp | 21 | ||||
-rw-r--r-- | test/CodeGenCXX/static-init.cpp | 2 |
11 files changed, 56 insertions, 7 deletions
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index e17279e266..2b6092dea3 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -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; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index a9566f3f9d..e830e473df 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -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">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 3592fc9468..7b0ce67025 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -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>; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 70597ab913..8d82318127 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -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())) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 7a3388ffbb..025f5ddf94 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 473f2c2820..bca9ae9e5b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7a27e1185e..bf5b350da0 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8870a59d13..9108137a00 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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); diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index f3c14a78d3..6ea12eb5f6 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -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 index 0000000000..6becaae72c --- /dev/null +++ b/test/CodeGenCXX/operator-new.cpp @@ -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( diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index 2ad6e9411f..cbd90e7894 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -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; } |