[cfe-commits] r149286 - in /cfe/trunk: lib/AST/ExprConstant.cpp lib/Sema/SemaOverload.cpp test/CXX/expr/expr.const/p2-0x.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Jan 30 14:27:02 PST 2012


Author: rsmith
Date: Mon Jan 30 16:27:01 2012
New Revision: 149286

URL: http://llvm.org/viewvc/llvm-project?rev=149286&view=rev
Log:
constexpr: disallow signed integer overflow in integral conversions in constant
expressions in C++11.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=149286&r1=149285&r2=149286&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Jan 30 16:27:01 2012
@@ -1086,13 +1086,21 @@
   return true;
 }
 
-static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType,
-                                 APSInt &Value, const ASTContext &Ctx) {
-  unsigned DestWidth = Ctx.getIntWidth(DestType);
+static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E,
+                                 QualType DestType, QualType SrcType,
+                                 APSInt &Value) {
+  unsigned DestWidth = Info.Ctx.getIntWidth(DestType);
   APSInt Result = Value;
   // Figure out if this is a truncate, extend or noop cast.
   // If the input is signed, do a sign extend, noop, or truncate.
   Result = Result.extOrTrunc(DestWidth);
+
+  // Check whether we overflowed. If so, fold the cast anyway.
+  if (DestType->isSignedIntegerOrEnumerationType() &&
+      ((Result.isNegative() && Value.isUnsigned()) ||
+       Result.extOrTrunc(Value.getBitWidth()) != Value))
+    (void)HandleOverflow(Info, E, Value, DestType);
+
   Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType());
   return Result;
 }
@@ -4703,8 +4711,8 @@
       return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType);
     }
 
-    return Success(HandleIntToIntCast(DestType, SrcType,
-                                      Result.getInt(), Info.Ctx), E);
+    return Success(HandleIntToIntCast(Info, E, DestType, SrcType,
+                                      Result.getInt()), E);
   }
 
   case CK_PointerToIntegral: {
@@ -4716,6 +4724,9 @@
 
     if (LV.getLValueBase()) {
       // Only allow based lvalue casts if they are lossless.
+      // FIXME: Allow a larger integer size than the pointer size, and allow
+      // narrowing back down to pointer width in subsequent integral casts.
+      // FIXME: Check integer type's active bits, not its type size.
       if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType))
         return Error(E);
 
@@ -4726,7 +4737,7 @@
 
     APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(), 
                                          SrcType);
-    return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
+    return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
   }
 
   case CK_IntegralComplexToReal: {
@@ -5200,8 +5211,8 @@
     QualType From
       = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType();
 
-    Result.IntReal = HandleIntToIntCast(To, From, Result.IntReal, Info.Ctx);
-    Result.IntImag = HandleIntToIntCast(To, From, Result.IntImag, Info.Ctx);
+    Result.IntReal = HandleIntToIntCast(Info, E, To, From, Result.IntReal);
+    Result.IntImag = HandleIntToIntCast(Info, E, To, From, Result.IntImag);
     return true;
   }
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=149286&r1=149285&r2=149286&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jan 30 16:27:01 2012
@@ -4646,6 +4646,7 @@
 
   // Check for a narrowing implicit conversion.
   APValue PreNarrowingValue;
+  bool Diagnosed = false;
   switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue)) {
   case NK_Variable_Narrowing:
     // Implicit conversion to a narrower type, and the value is not a constant
@@ -4657,11 +4658,13 @@
     Diag(From->getSourceRange().getBegin(), diag::err_cce_narrowing)
       << CCE << /*Constant*/1
       << PreNarrowingValue.getAsString(Context, QualType()) << T;
+    Diagnosed = true;
     break;
 
   case NK_Type_Narrowing:
     Diag(From->getSourceRange().getBegin(), diag::err_cce_narrowing)
       << CCE << /*Constant*/0 << From->getType() << T;
+    Diagnosed = true;
     break;
   }
 
@@ -4674,12 +4677,19 @@
     // The expression can't be folded, so we can't keep it at this position in
     // the AST.
     Result = ExprError();
-  } else if (Notes.empty()) {
-    // It's a constant expression.
+  } else {
     Value = Eval.Val.getInt();
-    return Result;
+
+    if (Notes.empty()) {
+      // It's a constant expression.
+      return Result;
+    }
   }
 
+  // Only issue one narrowing diagnostic.
+  if (Diagnosed)
+    return Result;
+
   // It's not a constant expression. Produce an appropriate diagnostic.
   if (Notes.size() == 1 &&
       Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
@@ -4690,7 +4700,7 @@
     for (unsigned I = 0; I < Notes.size(); ++I)
       Diag(Notes[I].first, Notes[I].second);
   }
-  return ExprError();
+  return Result;
 }
 
 /// dropPointerConversions - If the given standard conversion sequence

Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=149286&r1=149285&r2=149286&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Mon Jan 30 16:27:01 2012
@@ -118,6 +118,9 @@
   void f(int n) {
     switch (n) {
     case (int)4.4e9: // expected-error {{constant expression}} expected-note {{value 4.4E+9 is outside the range of representable values of type 'int'}}
+    case (int)10000000000ll: // expected-error {{constant expression}} expected-note {{value 10000000000 is outside the range of representable values of type 'int'}} expected-note {{here}}
+    case (int)0x80000000u: // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of representable values of type 'int'}}
+    case (unsigned int)10000000000ll: // expected-error {{duplicate case value}}
     case (int)(unsigned)(long long)4.4e9: // ok
     case (int)(float)1e300: // expected-error {{constant expression}} expected-note {{value 1.0E+300 is outside the range of representable values of type 'float'}}
     case (int)((float)1e37 / 1e30): // ok





More information about the cfe-commits mailing list