[cfe-commits] r118636 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ExprConstant.cpp lib/Sema/SemaChecking.cpp test/Lexer/constants.c test/Preprocessor/pushable-diagnostics.c test/Sema/constant-conversion.c test/Sema/conversion.c

John McCall rjmccall at apple.com
Tue Nov 9 14:22:12 PST 2010


Author: rjmccall
Date: Tue Nov  9 16:22:12 2010
New Revision: 118636

URL: http://llvm.org/viewvc/llvm-project?rev=118636&view=rev
Log:
Split out -Wconversion warnings about constant precision into their
own subcategory, -Wconstant-conversion, which is on by default.

Tweak the constant folder to give better results in the invalid
case of a negative shift amount.

Implements rdar://problem/6792488


Added:
    cfe/trunk/test/Sema/constant-conversion.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/Lexer/constants.c
    cfe/trunk/test/Preprocessor/pushable-diagnostics.c
    cfe/trunk/test/Sema/conversion.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Nov  9 16:22:12 2010
@@ -164,10 +164,15 @@
 // missing parentheses;  it is off by default.
 def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]>;
 
-// -Wconversion has its own warnings, but we split this one out for
-// legacy reasons.
+// -Wconversion has its own warnings, but we split a few out for
+// legacy reasons:
+//   - some people want just 64-to-32 warnings
+//   - conversion warnings with constant sources are on by default
+//   - bool-to-pointer conversion warnings are on by default
 def Conversion : DiagGroup<"conversion",
-                           [DiagGroup<"shorten-64-to-32">, BoolConversions]>,
+                           [DiagGroup<"shorten-64-to-32">,
+                            DiagGroup<"constant-conversion">,
+                            BoolConversions]>,
                  DiagCategory<"Value Conversion Issue">;
 
 def Unused : DiagGroup<"unused",

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Nov  9 16:22:12 2010
@@ -1041,6 +1041,9 @@
 def warn_impcast_integer_64_32 : Warning<
   "implicit conversion loses integer precision: %0 to %1">,
   InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
+def warn_impcast_integer_precision_constant : Warning<
+  "implicit conversion from %2 to %3 changes value from %0 to %1">,
+  InGroup<DiagGroup<"constant-conversion">>;
 
 def warn_cast_align : Warning<
   "cast from %0 to %1 increases required alignment from %2 to %3">,

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Nov  9 16:22:12 2010
@@ -1458,12 +1458,25 @@
       return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
     return Success(Result.getInt() % RHS, E);
   case BO_Shl: {
-    // FIXME: Warn about out of range shift amounts!
-    unsigned SA =
-      (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
+    // During constant-folding, a negative shift is an opposite shift.
+    if (RHS.isSigned() && RHS.isNegative()) {
+      RHS = -RHS;
+      goto shift_right;
+    }
+
+  shift_left:
+    unsigned SA
+      = (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
     return Success(Result.getInt() << SA, E);
   }
   case BO_Shr: {
+    // During constant-folding, a negative shift is an opposite shift.
+    if (RHS.isSigned() && RHS.isNegative()) {
+      RHS = -RHS;
+      goto shift_left;
+    }
+
+  shift_right:
     unsigned SA =
       (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
     return Success(Result.getInt() >> SA, E);

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Nov  9 16:22:12 2010
@@ -2165,8 +2165,12 @@
     if (const ComplexType *CT = dyn_cast<ComplexType>(T))
       T = CT->getElementType().getTypePtr();
 
+    // For enum types, use the known bit width of the enumerators.
     if (const EnumType *ET = dyn_cast<EnumType>(T)) {
       EnumDecl *Enum = ET->getDecl();
+      if (!Enum->isDefinition())
+        return IntRange(C.getIntWidth(QualType(T, 0)), false);
+
       unsigned NumPositive = Enum->getNumPositiveBits();
       unsigned NumNegative = Enum->getNumNegativeBits();
 
@@ -2590,6 +2594,15 @@
     << E->getType() << T << E->getSourceRange() << SourceRange(CContext);
 }
 
+std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
+  if (!Range.Width) return "0";
+
+  llvm::APSInt ValueInRange = Value;
+  ValueInRange.setIsSigned(!Range.NonNegative);
+  ValueInRange.trunc(Range.Width);
+  return ValueInRange.toString(10);
+}
+
 void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
                              SourceLocation CC, bool *ICContext = 0) {
   if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -2670,6 +2683,19 @@
   IntRange TargetRange = IntRange::forCanonicalType(S.Context, Target);
 
   if (SourceRange.Width > TargetRange.Width) {
+    // If the source is a constant, use a default-on diagnostic.
+    // TODO: this should happen for bitfield stores, too.
+    llvm::APSInt Value(32);
+    if (E->isIntegerConstantExpr(Value, S.Context)) {
+      std::string PrettySourceValue = Value.toString(10);
+      std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
+
+      S.Diag(E->getExprLoc(), diag::warn_impcast_integer_precision_constant)
+        << PrettySourceValue << PrettyTargetValue
+        << E->getType() << T << E->getSourceRange() << clang::SourceRange(CC);
+      return;
+    }
+
     // People want to build with -Wshorten-64-to-32 and not -Wconversion
     // and by god we'll let them.
     if (SourceRange.Width == 64 && TargetRange.Width == 32)

Modified: cfe/trunk/test/Lexer/constants.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/constants.c?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/test/Lexer/constants.c (original)
+++ cfe/trunk/test/Lexer/constants.c Tue Nov  9 16:22:12 2010
@@ -15,7 +15,7 @@
 #endif
 
 
-char c[] = {
+int c[] = {
   'df',   // expected-warning {{multi-character character constant}}
   '\t',
   '\\
@@ -34,12 +34,12 @@
 
 #pragma clang diagnostic ignored "-Wmultichar"
 
-char d = 'df'; // no warning.
-char e = 'abcd';  // still warn: expected-warning {{multi-character character constant}}
+int d = 'df'; // no warning.
+int e = 'abcd';  // still warn: expected-warning {{multi-character character constant}}
 
 #pragma clang diagnostic ignored "-Wfour-char-constants"
 
-char f = 'abcd';  // ignored.
+int f = 'abcd';  // ignored.
 
 // rdar://problem/6974641
 float t0[] = {

Modified: cfe/trunk/test/Preprocessor/pushable-diagnostics.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/pushable-diagnostics.c?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/pushable-diagnostics.c (original)
+++ cfe/trunk/test/Preprocessor/pushable-diagnostics.c Tue Nov  9 16:22:12 2010
@@ -4,14 +4,14 @@
 
 #pragma clang diagnostic puhs // expected-warning {{pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop'}}
 
-char a = 'df'; // expected-warning{{multi-character character constant}}
+int a = 'df'; // expected-warning{{multi-character character constant}}
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wmultichar"
 
-char b = 'df'; // no warning.
+int b = 'df'; // no warning.
 #pragma clang diagnostic pop
 
-char c = 'df';  // expected-warning{{multi-character character constant}}
+int c = 'df';  // expected-warning{{multi-character character constant}}
 
 #pragma clang diagnostic pop // expected-warning{{pragma diagnostic pop could not pop, no matching push}}

Added: cfe/trunk/test/Sema/constant-conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/constant-conversion.c?rev=118636&view=auto
==============================================================================
--- cfe/trunk/test/Sema/constant-conversion.c (added)
+++ cfe/trunk/test/Sema/constant-conversion.c Tue Nov  9 16:22:12 2010
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin %s
+
+// This file tests -Wconstant-conversion, a subcategory of -Wconversion
+// which is on by default.
+
+// rdar://problem/6792488
+void test_6792488(void) {
+  int x = 0x3ff0000000000000U; // expected-warning {{implicit conversion from 'unsigned long' to 'int' changes value from 4607182418800017408 to 0}}
+}

Modified: cfe/trunk/test/Sema/conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conversion.c?rev=118636&r1=118635&r2=118636&view=diff
==============================================================================
--- cfe/trunk/test/Sema/conversion.c (original)
+++ cfe/trunk/test/Sema/conversion.c Tue Nov  9 16:22:12 2010
@@ -40,17 +40,17 @@
   l = (long) 0;
 
   c = (char) BIG;
-  c = (short) BIG; // expected-warning {{implicit conversion loses integer precision}}
-  c = (int) BIG; // expected-warning {{implicit conversion loses integer precision}}
-  c = (long) BIG; // expected-warning {{implicit conversion loses integer precision}}
+  c = (short) BIG; // expected-warning {{implicit conversion from 'short' to 'char' changes value}}
+  c = (int) BIG; // expected-warning {{implicit conversion from 'int' to 'char' changes value}}
+  c = (long) BIG; // expected-warning {{implicit conversion from 'long' to 'char' changes value}}
   s = (char) BIG;
   s = (short) BIG;
-  s = (int) BIG; // expected-warning {{implicit conversion loses integer precision}}
-  s = (long) BIG; // expected-warning {{implicit conversion loses integer precision}}
+  s = (int) BIG; // expected-warning {{implicit conversion from 'int' to 'short' changes value}}
+  s = (long) BIG; // expected-warning {{implicit conversion from 'long' to 'short' changes value}}
   i = (char) BIG;
   i = (short) BIG;
   i = (int) BIG;
-  i = (long) BIG; // expected-warning {{implicit conversion loses integer precision}}
+  i = (long) BIG; // expected-warning {{implicit conversion from 'long' to 'int' changes value}}
   l = (char) BIG;
   l = (short) BIG;
   l = (int) BIG;
@@ -63,10 +63,10 @@
   return (int) ll; // expected-warning {{implicit conversion loses integer precision}}
   return (short) ll; // expected-warning {{implicit conversion loses integer precision}}
   return (char) ll;
-  return (long long) BIG; // expected-warning {{implicit conversion loses integer precision}}
-  return (long) BIG; // expected-warning {{implicit conversion loses integer precision}}
-  return (int) BIG; // expected-warning {{implicit conversion loses integer precision}}
-  return (short) BIG; // expected-warning {{implicit conversion loses integer precision}}
+  return (long long) BIG; // expected-warning {{implicit conversion from 'long long' to 'char' changes value}}
+  return (long) BIG; // expected-warning {{implicit conversion from 'long' to 'char' changes value}}
+  return (int) BIG; // expected-warning {{implicit conversion from 'int' to 'char' changes value}}
+  return (short) BIG; // expected-warning {{implicit conversion from 'short' to 'char' changes value}}
   return (char) BIG;
 }
 
@@ -76,9 +76,9 @@
   return (int) ll; // expected-warning {{implicit conversion loses integer precision}}
   return (short) ll;
   return (char) ll;
-  return (long long) BIG;  // expected-warning {{implicit conversion loses integer precision}}
-  return (long) BIG;  // expected-warning {{implicit conversion loses integer precision}}
-  return (int) BIG;  // expected-warning {{implicit conversion loses integer precision}}
+  return (long long) BIG;  // expected-warning {{implicit conversion from 'long long' to 'short' changes value}}
+  return (long) BIG;  // expected-warning {{implicit conversion from 'long' to 'short' changes value}}
+  return (int) BIG;  // expected-warning {{implicit conversion from 'int' to 'short' changes value}}
   return (short) BIG;
   return (char) BIG;
 }
@@ -89,8 +89,8 @@
   return (int) ll;
   return (short) ll;
   return (char) ll;
-  return (long long) BIG;  // expected-warning {{implicit conversion loses integer precision}}
-  return (long) BIG; // expected-warning {{implicit conversion loses integer precision}}
+  return (long long) BIG;  // expected-warning {{implicit conversion from 'long long' to 'int' changes value}}
+  return (long) BIG; // expected-warning {{implicit conversion from 'long' to 'int' changes value}}
   return (int) BIG;
   return (short) BIG;
   return (char) BIG;
@@ -277,7 +277,7 @@
 // <rdar://problem/7631400>
 void test_7631400(void) {
   // This should show up despite the caret being inside a macro substitution
-  char s = LONG_MAX; // expected-warning {{implicit conversion loses integer precision: 'long' to 'char'}}
+  char s = LONG_MAX; // expected-warning {{implicit conversion from 'long' to 'char' changes value}}
 }
 
 // <rdar://problem/7676608>: assertion for compound operators with non-integral RHS





More information about the cfe-commits mailing list