diff options
-rw-r--r-- | include/clang/Basic/DiagnosticFrontendKinds.td | 3 | ||||
-rw-r--r-- | include/clang/Basic/LangOptions.h | 34 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 66 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 14 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 14 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 7 | ||||
-rw-r--r-- | test/CodeGen/builtins-ppc-altivec.c | 6 | ||||
-rw-r--r-- | test/CodeGen/exprs.c | 15 | ||||
-rw-r--r-- | test/CodeGen/extern-inline.c | 2 | ||||
-rw-r--r-- | test/CodeGen/integer-overflow.c | 33 |
13 files changed, 125 insertions, 73 deletions
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 50937790d8..989ec38d29 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -189,9 +189,6 @@ def warn_pch_math_errno : Error< "math functions %select{do not respect|respect}0 'errno' in PCH " "file but they are currently set to %select{not respect|respect}1 " "'errno'">; -def warn_pch_overflow_checking : Error< - "signed integer overflow checking was %select{disabled|enabled}0 in PCH " - "file but is currently %select{disabled|enabled}1">; def warn_pch_optimize : Error< "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in " "the PCH file but is currently %select{undefined|defined}1">; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index cd9849d5db..c09d8aab44 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -66,9 +66,6 @@ public: unsigned MathErrno : 1; // Math functions must respect errno // (modulo the platform support). - unsigned OverflowChecking : 1; // Extension to call a handler function when - // signed integer arithmetic overflows. - unsigned HeinousExtensions : 1; // Extensions that we really don't like and // may be ripped out at any time. @@ -109,15 +106,12 @@ public: unsigned NoBitFieldTypeAlign : 1; private: - unsigned GC : 2; // Objective-C Garbage Collection modes. We - // declare this enum as unsigned because MSVC - // insists on making enums signed. Set/Query - // this value using accessors. + // We declare multibit enums as unsigned because MSVC insists on making enums + // signed. Set/Query these values using accessors. + unsigned GC : 2; // Objective-C Garbage Collection modes. unsigned SymbolVisibility : 3; // Symbol's visibility. - unsigned StackProtector : 2; // Whether stack protectors are on. We declare - // this enum as unsigned because MSVC insists - // on making enums signed. Set/Query this - // value using accessors. + unsigned StackProtector : 2; // Whether stack protectors are on. + unsigned SignedOverflowBehavior : 2; // How to handle signed integer overflow. public: unsigned InstantiationDepth; // Maximum template instantiation depth. @@ -131,6 +125,12 @@ public: Protected, Hidden }; + + enum SignedOverflowBehaviorTy { + SOB_Undefined, // Default C standard behavior. + SOB_Defined, // -fwrapv + SOB_Trapping // -ftrapv + }; LangOptions() { Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; @@ -154,14 +154,15 @@ public: Blocks = 0; EmitAllDecls = 0; MathErrno = 1; - + SignedOverflowBehavior = SOB_Undefined; + AssumeSaneOperatorNew = 1; // FIXME: The default should be 1. AccessControl = 0; ElideConstructors = 1; - OverflowChecking = 0; + SignedOverflowBehavior = 0; ObjCGCBitmapPrint = 0; InstantiationDepth = 1024; @@ -197,6 +198,13 @@ public: return (VisibilityMode) SymbolVisibility; } void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; } + + SignedOverflowBehaviorTy getSignedOverflowBehavior() const { + return (SignedOverflowBehaviorTy)SignedOverflowBehavior; + } + void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) { + SignedOverflowBehavior = (unsigned)V; + } }; } // end namespace clang diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index c1de8b1d3a..65284fbc9d 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -426,6 +426,8 @@ def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, HelpText<"enable objective-c's enhanced nonfragile abi">; def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; +def fwrapv : Flag<"-fwrapv">, + HelpText<"Treat signed integer overflow as two's complement">; def pic_level : Separate<"-pic-level">, HelpText<"Value for __PIC__">; def pthread : Flag<"-pthread">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 129ce5e139..1e3669597f 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -388,6 +388,7 @@ def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>; def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>; +def fwrapv : Flag<"-fwrapv">, Group<f_Group>; def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>; def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>; diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 4372279175..72da22695f 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -291,9 +291,17 @@ public: // Binary Operators. Value *EmitMul(const BinOpInfo &Ops) { - if (CGF.getContext().getLangOptions().OverflowChecking - && Ops.Ty->isSignedIntegerType()) - return EmitOverflowCheckedBinOp(Ops); + if (Ops.Ty->isSignedIntegerType()) { + switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { + case LangOptions::SOB_Undefined: + return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul"); + case LangOptions::SOB_Defined: + return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul"); + case LangOptions::SOB_Trapping: + return EmitOverflowCheckedBinOp(Ops); + } + } + if (Ops.LHS->getType()->isFPOrFPVectorTy()) return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul"); return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul"); @@ -1119,9 +1127,17 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { return Builder.CreateFNeg(Op, "neg"); // Signed integer overflow is undefined behavior. - if (E->getType()->isSignedIntegerType()) - return Builder.CreateNSWNeg(Op, "neg"); - + if (E->getType()->isSignedIntegerType()) { + switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { + case LangOptions::SOB_Trapping: + // FIXME: Implement -ftrapv for negate. + case LangOptions::SOB_Undefined: + return Builder.CreateNSWNeg(Op, "neg"); + case LangOptions::SOB_Defined: + return Builder.CreateNeg(Op, "neg"); + } + } + return Builder.CreateNeg(Op, "neg"); } @@ -1397,17 +1413,20 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { if (!Ops.Ty->isAnyPointerType()) { - if (CGF.getContext().getLangOptions().OverflowChecking && - Ops.Ty->isSignedIntegerType()) - return EmitOverflowCheckedBinOp(Ops); - + if (Ops.Ty->isSignedIntegerType()) { + switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { + case LangOptions::SOB_Undefined: + return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add"); + case LangOptions::SOB_Defined: + return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add"); + case LangOptions::SOB_Trapping: + return EmitOverflowCheckedBinOp(Ops); + } + } + if (Ops.LHS->getType()->isFPOrFPVectorTy()) return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add"); - // Signed integer overflow is undefined behavior. - if (Ops.Ty->isSignedIntegerType()) - return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add"); - return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add"); } @@ -1473,17 +1492,20 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { if (!isa<llvm::PointerType>(Ops.LHS->getType())) { - if (CGF.getContext().getLangOptions().OverflowChecking - && Ops.Ty->isSignedIntegerType()) - return EmitOverflowCheckedBinOp(Ops); - + if (Ops.Ty->isSignedIntegerType()) { + switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) { + case LangOptions::SOB_Undefined: + return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub"); + case LangOptions::SOB_Defined: + return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub"); + case LangOptions::SOB_Trapping: + return EmitOverflowCheckedBinOp(Ops); + } + } + if (Ops.LHS->getType()->isFPOrFPVectorTy()) return Builder.CreateFSub(Ops.LHS, Ops.RHS, "sub"); - // Signed integer overflow is undefined behavior. - if (Ops.Ty->isSignedIntegerType()) - return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub"); - return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub"); } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index e7cff8ea89..22b14825ef 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1182,6 +1182,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); Args.AddLastArg(CmdArgs, options::OPT_ftrapv); + Args.AddLastArg(CmdArgs, options::OPT_fwrapv); Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_pthread); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index e7a75a619d..76770ae36c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -549,8 +549,11 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-femit-all-decls"); if (Opts.MathErrno) Res.push_back("-fmath-errno"); - if (Opts.OverflowChecking) - Res.push_back("-ftrapv"); + switch (Opts.getSignedOverflowBehavior()) { + case LangOptions::SOB_Undefined: break; + case LangOptions::SOB_Defined: Res.push_back("-fwrapv"); break; + case LangOptions::SOB_Trapping: Res.push_back("-ftrapv"); break; + } if (Opts.HeinousExtensions) Res.push_back("-fheinous-gnu-extensions"); // Optimize is implicit. @@ -1257,8 +1260,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fvisibility_inlines_hidden)) Opts.InlineVisibilityHidden = 1; - - Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); + + if (Args.hasArg(OPT_ftrapv)) + Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); + else if (Args.hasArg(OPT_fwrapv)) + Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined); // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs // is specified, or -std is set to a conforming mode. diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 5bd3c0481a..c220e269c2 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -93,7 +93,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); PARSE_LANGOPT_BENIGN(EmitAllDecls); PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); - PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking); + PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior()); PARSE_LANGOPT_IMPORTANT(HeinousExtensions, diag::warn_pch_heinous_extensions); // FIXME: Most of the options below are benign if the macro wasn't @@ -1915,7 +1915,8 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(Blocks); PARSE_LANGOPT(EmitAllDecls); PARSE_LANGOPT(MathErrno); - PARSE_LANGOPT(OverflowChecking); + LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy) + Record[Idx++]); PARSE_LANGOPT(HeinousExtensions); PARSE_LANGOPT(Optimize); PARSE_LANGOPT(OptimizeSize); @@ -1926,13 +1927,10 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(AccessControl); PARSE_LANGOPT(CharIsSigned); PARSE_LANGOPT(ShortWChar); - LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]); - ++Idx; - LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]); - ++Idx; + LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]); + LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]); LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode) - Record[Idx]); - ++Idx; + Record[Idx++]); PARSE_LANGOPT(InstantiationDepth); PARSE_LANGOPT(OpenCL); PARSE_LANGOPT(CatchUndefined); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 3c42d474dc..efed0f0a6c 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -833,11 +833,8 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.MathErrno); // Math functions must respect errno // (modulo the platform support). - Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when - // signed integer arithmetic overflows. - - Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and - // may be ripped out at any time. + Record.push_back(LangOpts.getSignedOverflowBehavior()); + Record.push_back(LangOpts.HeinousExtensions); Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined. Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c index 1ffb05905a..4b9c3d5c42 100644 --- a/test/CodeGen/builtins-ppc-altivec.c +++ b/test/CodeGen/builtins-ppc-altivec.c @@ -428,13 +428,13 @@ int main () res_vus = vec_mladd(vus, vus, vus); // CHECK: mul <8 x i16> // CHECK: add <8 x i16> - res_vs = vec_mladd(vus, vs, vs); // CHECK: mul <8 x i16> + res_vs = vec_mladd(vus, vs, vs); // CHECK: mul nsw <8 x i16> // CHECK: add nsw <8 x i16> - res_vs = vec_mladd(vs, vus, vus); // CHECK: mul <8 x i16> + res_vs = vec_mladd(vs, vus, vus); // CHECK: mul nsw <8 x i16> // CHECK: add nsw <8 x i16> - res_vs = vec_mladd(vs, vs, vs); // CHECK: mul <8 x i16> + res_vs = vec_mladd(vs, vs, vs); // CHECK: mul nsw <8 x i16> // CHECK: add nsw <8 x i16> /* vec_mradds */ diff --git a/test/CodeGen/exprs.c b/test/CodeGen/exprs.c index a90ae58dc3..d182ce81ca 100644 --- a/test/CodeGen/exprs.c +++ b/test/CodeGen/exprs.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - // PR1895 // sizeof function @@ -119,16 +119,3 @@ void f9(struct S *x) { void f10() { __builtin_sin(0); } - -// Tests for signed integer overflow stuff. -// rdar://7432000 -void f11() { - // CHECK: define void @f11 - extern volatile int f11G, a, b; - // CHECK: add nsw i32 - f11G = a + b; - // CHECK: sub nsw i32 - f11G = a - b; - // CHECK: sub nsw i32 0, - f11G = -a; -} diff --git a/test/CodeGen/extern-inline.c b/test/CodeGen/extern-inline.c index 5dd9bfda57..60f6d034bf 100644 --- a/test/CodeGen/extern-inline.c +++ b/test/CodeGen/extern-inline.c @@ -19,7 +19,7 @@ int g2(void) {return f2(0,1);} static int f2(int a, int b) {return a*b;} // CHECK: load i32* %{{.*}} // CHECK: load i32* %{{.*}} -// CHECK: mul i32 %{{.*}}, %{{.*}} +// CHECK: mul nsw i32 %{{.*}}, %{{.*}} int h2(void) {return f2(1,2);} // CHECK: call i32 @f2 diff --git a/test/CodeGen/integer-overflow.c b/test/CodeGen/integer-overflow.c new file mode 100644 index 0000000000..7969216104 --- /dev/null +++ b/test/CodeGen/integer-overflow.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT +// RUN: %clang_cc1 %s -emit-llvm -o - -fwrapv | FileCheck %s --check-prefix=WRAPV +// RUN: %clang_cc1 %s -emit-llvm -o - -ftrapv | FileCheck %s --check-prefix=TRAPV + + +// Tests for signed integer overflow stuff. +// rdar://7432000 rdar://7221421 +void test1() { + // DEFAULT: define void @test1 + // WRAPV: define void @test1 + // TRAPV: define void @test1 + extern volatile int f11G, a, b; + + // DEFAULT: add nsw i32 + // WRAPV: add i32 + // TRAPV: llvm.sadd.with.overflow.i32 + f11G = a + b; + + // DEFAULT: sub nsw i32 + // WRAPV: sub i32 + // TRAPV: llvm.ssub.with.overflow.i32 + f11G = a - b; + + // DEFAULT: sub nsw i32 0, + // WRAPV: sub i32 0, + // TRAPV: sub nsw i32 0, + f11G = -a; + + // DEFAULT: mul nsw i32 + // WRAPV: mul i32 + // TRAPV: llvm.smul.with.overflow.i32 + f11G = a * b; +} |