"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">;
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.
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.
Protected,
Hidden
};
+
+ enum SignedOverflowBehaviorTy {
+ SOB_Undefined, // Default C standard behavior.
+ SOB_Defined, // -fwrapv
+ SOB_Trapping // -ftrapv
+ };
LangOptions() {
Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
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;
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
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">,
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>;
// 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");
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");
}
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");
}
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");
}
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);
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.
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.
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
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);
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);
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
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 */
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o -
// PR1895
// sizeof function
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;
-}
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
--- /dev/null
+// 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;
+}