diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2013-03-29 00:22:03 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2013-03-29 00:22:03 +0000 |
commit | dff2be8ba441f5c61af8444479f7133b22dcfcf4 (patch) | |
tree | 05047b198d451e2e70f4d59221e9f15e87510585 | |
parent | 0f5c5c60e9806d13f0907cd99d7204ffab0e08f7 (diff) |
Revert r178273 as it broke the Linux bootstrap due to false positives
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178320 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 135 | ||||
-rw-r--r-- | test/Sema/constant-conversion.c | 42 |
3 files changed, 17 insertions, 165 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 98663a05a8..2a71b17293 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2084,11 +2084,6 @@ def warn_impcast_integer_64_32 : Warning< def warn_impcast_integer_precision_constant : Warning< "implicit conversion from %2 to %3 changes value from %0 to %1">, InGroup<ConstantConversion>; -def warn_impcast_integer_precision_binop_constant : Warning< - "implicit conversion of binary operation from %2 to %3 may change its value; " - "value of operand would be changed from %0 to %1 if converted before " - "operation">, - InGroup<ConstantConversion>; def warn_impcast_bitfield_precision_constant : Warning< "implicit truncation from %2 to bitfield changes value from %0 to %1">, InGroup<ConstantConversion>; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a6294e5764..4e11b3aa79 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -4686,8 +4686,7 @@ static void AnalyzeAssignment(Sema &S, BinaryOperator *E) { // We want to recurse on the RHS as normal unless we're assigning to // a bitfield. if (FieldDecl *Bitfield = E->getLHS()->getBitField()) { - if (E->getOpcode() != BO_AndAssign && - AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(), + if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(), E->getOperatorLoc())) { // Recurse, ignoring any implicit conversions on the RHS. return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(), @@ -4796,82 +4795,8 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, } } -// Try to evaluate E as an integer. If EvaluateAsInt succeeds, Value is set to -// the resulting value, ResultExpr is set to E. -// Otherwise, the output parameters are not modified. -static bool EvalAsInt(ASTContext &Ctx, llvm::APSInt &Value, Expr *E, - Expr **ResultExpr) { - if (E->EvaluateAsInt(Value, Ctx, Expr::SE_AllowSideEffects)) { - *ResultExpr = E; - return true; - } - return false; -} - -// Returns true when Value's value would change when narrowed to TargetRange. -static bool TruncationChangesValue(const llvm::APSInt &Value, - const IntRange &TargetRange, - bool IsBitwiseAnd) { - // Checks if there are any active non-sign bits past the width of TargetRange. - if (IsBitwiseAnd) - return Value.getBitWidth() - Value.getNumSignBits() > TargetRange.Width; - - llvm::APSInt UnsignedValue(Value); - unsigned BitWidth = TargetRange.NonNegative ? - UnsignedValue.getActiveBits() : Value.getMinSignedBits(); - return BitWidth > TargetRange.Width; -} - -// Determine if E is an expression containing or likely to contain an implicit -// narrowing bug involving a constant. -// If so, Value is set to the value of that constant. NarrowedExpr is set to the -// problematic sub-expression if it is a strict subset of E. -static bool OperandMightImplicitlyNarrow(ASTContext &Ctx, llvm::APSInt &Value, - Expr *E, IntRange TargetRange, - Expr **NarrowedExpr) { - BinaryOperator *BO = dyn_cast<BinaryOperator>(E); - if (!BO) - return false; - - switch (BO->getOpcode()) { - case BO_And: - case BO_AndAssign: - return (EvalAsInt(Ctx, Value, BO->getLHS(), NarrowedExpr) - && TruncationChangesValue(Value, TargetRange, true)) || - (EvalAsInt(Ctx, Value, BO->getRHS(), NarrowedExpr) - && TruncationChangesValue(Value, TargetRange, true)); - - case BO_Or: - case BO_OrAssign: - // FIXME: Include BO_Add, BO_Sub, and BO_Xor when we avoid false positives. - case BO_AddAssign: - case BO_SubAssign: - case BO_Mul: - case BO_MulAssign: - case BO_XorAssign: - return (EvalAsInt(Ctx, Value, BO->getLHS(), NarrowedExpr) - && TruncationChangesValue(Value, TargetRange, false)) || - (EvalAsInt(Ctx, Value, BO->getRHS(), NarrowedExpr) - && TruncationChangesValue(Value, TargetRange, false)); - - // We can ignore the left side of the comma operator, since the value is - // explicitly ignored anyway. - case BO_Comma: - return EvalAsInt(Ctx, Value, BO->getRHS(), NarrowedExpr) && - TruncationChangesValue(Value, TargetRange, false); - - case BO_Shl: - return EvalAsInt(Ctx, Value, BO->getLHS(), NarrowedExpr) && - TruncationChangesValue(Value, TargetRange, false); - - default: - break; - } - return false; -} - void CheckImplicitConversion(Sema &S, Expr *E, QualType T, - SourceLocation CC, bool *ICContext = NULL) { + SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); @@ -5052,30 +4977,17 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, IntRange SourceRange = GetExprRange(S.Context, E); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); - llvm::APSInt Value(32); - Expr *NarrowedExpr = NULL; - // Use a default-on diagnostic if the source is involved in a - // narrowing-prone binary operation with a constant. - if (OperandMightImplicitlyNarrow(S.Context, Value, E, TargetRange, - &NarrowedExpr)) { - std::string PrettySourceValue = Value.toString(10); - std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - - S.DiagRuntimeBehavior(E->getExprLoc(), NarrowedExpr, - S.PDiag(diag::warn_impcast_integer_precision_binop_constant) - << PrettySourceValue << PrettyTargetValue - << E->getType() << T << NarrowedExpr->getSourceRange() - << clang::SourceRange(CC)); - return; - } else if (SourceRange.Width > TargetRange.Width) { - // People want to build with -Wshorten-64-to-32 and not -Wconversion. - if (S.SourceMgr.isInSystemMacro(CC)) - return; - + if (SourceRange.Width > TargetRange.Width) { // If the source is a constant, use a default-on diagnostic. - if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) { + // TODO: this should happen for bitfield stores, too. + llvm::APSInt Value(32); + if (E->isIntegerConstantExpr(Value, S.Context)) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); + S.DiagRuntimeBehavior(E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_precision_constant) << PrettySourceValue << PrettyTargetValue @@ -5084,6 +4996,10 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } + // People want to build with -Wshorten-64-to-32 and not -Wconversion. + if (S.SourceMgr.isInSystemMacro(CC)) + return; + if (TargetRange.Width == 32 && S.Context.getIntWidth(E->getType()) == 64) return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32, /* pruneControlFlow */ true); @@ -5213,25 +5129,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { if (E->getType() != T) CheckImplicitConversion(S, E, T, CC); - // For CompoundAssignmentOperators, check the conversion from the computed - // LHS type to the type of the assignee. - if (CompoundAssignOperator *CAO = dyn_cast<CompoundAssignOperator>(E)) { - QualType LHST = CAO->getComputationLHSType(); - // This CheckImplicitConversion would trigger a warning in addition to the - // more serious problem of using NULLs in arithmetic. - // Let the call to CheckImplicitConversion on the child expressions at the - // bottom of this function handle them by filtering those out here. - // Similarly, disable the extra check for shift assignments, since any - // narrowing would be less serious than a too-large shift count. - if (LHST != T && - T->isIntegralType(S.Context) && LHST->isIntegralType(S.Context) && - !CAO->isShiftAssignOp() && - CAO->getRHS()->isNullPointerConstant(S.Context, - Expr::NPC_ValueDependentIsNotNull) - != Expr::NPCK_GNUNull) - CheckImplicitConversion(S, CAO->getRHS(), T, CC); - } - // Now continue drilling into this expression. // Skip past explicit casts. @@ -5245,8 +5142,8 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { if (BO->isComparisonOp()) return AnalyzeComparison(S, BO); - // And with assignments. - if (BO->isAssignmentOp()) + // And with simple assignments. + if (BO->getOpcode() == BO_Assign) return AnalyzeAssignment(S, BO); } diff --git a/test/Sema/constant-conversion.c b/test/Sema/constant-conversion.c index 91e428bc5b..1376333967 100644 --- a/test/Sema/constant-conversion.c +++ b/test/Sema/constant-conversion.c @@ -66,18 +66,13 @@ void test7() { struct { unsigned int twoBits1:2; unsigned int twoBits2:2; - unsigned int twoBits3:2; - unsigned int reserved:26; + unsigned int reserved:28; } f; f.twoBits1 = ~1; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -2 to 2}} f.twoBits2 = ~2; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -3 to 1}} f.twoBits1 &= ~1; // no-warning f.twoBits2 &= ~2; // no-warning - f.twoBits3 |= 4; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 4 to 0}} - f.twoBits3 += 4; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 4 to 0}} - f.twoBits3 *= 4; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 4 to 0}} - f.twoBits3 |= 1; // no-warning } void test8() { @@ -85,38 +80,3 @@ void test8() { struct { enum E x : 1; } f; f.x = C; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 2 to 0}} } - -int func(int); - -void test9() { - unsigned char x = 0; - unsigned char y = 0; - x = y | 0x1ff; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - x = y | 0xff; // no-warning - x = y & 0xdff; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 3583 to 255 if converted before operation}} - x = y & 0xff; // no-warning - x = y & ~1; // no-warning - x = 0x1ff | y; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - x = 0xff | y; // no-warning - x = (y | 0x1ff); // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - x = (y | 0xff); // no-warning - x = 0xff + y; // no-warning - x += 0x1ff; // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}} - x = 0xff - y; // no-warning - x -= 0x1ff; // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}} - x = y * 0x1ff; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - x = y * 0xff; // no-warning - x *= 0x1ff; // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}} - x = y ^ 0xff; // no-warning - x ^= 0x1ff; // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}} - x = (func(1), 0x1ff); // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - x = (func(1), 0xff); // no-warning - x = 0xff << y; // no-warning - x = 0x1ff << y; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - - - // These next two tests make sure that both LHS and RHS are checked for - // narrowing operations. - x = 0x1ff | 0xff; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} - x = 0xff | 0x1ff; // expected-warning {{implicit conversion of binary operation from 'int' to 'unsigned char' may change its value; value of operand would be changed from 511 to 255 if converted before operation}} -} |