[cfe-commits] r150059 - in /cfe/trunk: include/clang/Basic/DiagnosticASTKinds.td lib/AST/ExprConstant.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/expr/expr.const/p2-0x.cpp test/SemaCXX/constexpr-sysheaders.cpp

Richard Smith richard-llvm at metafoo.co.uk
Tue Feb 7 22:14:53 PST 2012


Author: rsmith
Date: Wed Feb  8 00:14:53 2012
New Revision: 150059

URL: http://llvm.org/viewvc/llvm-project?rev=150059&view=rev
Log:
Implement the agreed resolution to DR1457: a signed left shift of a 1 bit into
the sign bit doesn't have undefined behavior, but a signed left shift of a 1 bit
out of the sign bit still does. As promised to Howard :)

The suppression of the potential constant expression checking in system headers
is also removed, since the problem it was working around is gone.

Removed:
    cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=150059&r1=150058&r2=150059&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Wed Feb  8 00:14:53 2012
@@ -24,6 +24,7 @@
 def note_constexpr_large_shift : Note<
   "shift count %0 >= width of type %1 (%2 bit%s2)">;
 def note_constexpr_lshift_of_negative : Note<"left shift of negative value %0">;
+def note_constexpr_lshift_discards : Note<"signed left shift discards bits">;
 def note_constexpr_invalid_function : Note<
   "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot "
   "be used in a constant expression">;

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=150059&r1=150058&r2=150059&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Feb  8 00:14:53 2012
@@ -4704,12 +4704,11 @@
         << RHS << E->getType() << LHS.getBitWidth();
     } else if (LHS.isSigned()) {
       // C++11 [expr.shift]p2: A signed left shift must have a non-negative
-      // operand, and must not overflow.
+      // operand, and must not overflow the corresponding unsigned type.
       if (LHS.isNegative())
         CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS;
-      else if (LHS.countLeadingZeros() <= SA)
-        HandleOverflow(Info, E, LHS.extend(LHS.getBitWidth() + SA) << SA,
-                       E->getType());
+      else if (LHS.countLeadingZeros() < SA)
+        CCEDiag(E, diag::note_constexpr_lshift_discards);
     }
 
     return Success(LHS << SA, E);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=150059&r1=150058&r2=150059&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb  8 00:14:53 2012
@@ -984,13 +984,8 @@
   // C++11 [dcl.constexpr]p4:
   //   - every constructor involved in initializing non-static data members and
   //     base class sub-objects shall be a constexpr constructor.
-  //
-  // FIXME: We currently disable this check inside system headers, to work
-  // around early STL implementations which contain constexpr functions which
-  // can't produce constant expressions.
   llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
-  if (!Context.getSourceManager().isInSystemHeader(Dcl->getLocation()) &&
-      !IsInstantiation && !Expr::isPotentialConstantExpr(Dcl, Diags)) {
+  if (!IsInstantiation && !Expr::isPotentialConstantExpr(Dcl, Diags)) {
     Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
       << isa<CXXConstructorDecl>(Dcl);
     for (size_t I = 0, N = Diags.size(); I != N; ++I)

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=150059&r1=150058&r2=150059&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Wed Feb  8 00:14:53 2012
@@ -144,8 +144,11 @@
   constexpr int shl_unsigned_overflow = 1024u << 31; // ok
   constexpr int shl_signed_negative = (-3) << 1; // expected-error {{constant expression}} expected-note {{left shift of negative value -3}}
   constexpr int shl_signed_ok = 1 << 30; // ok
-  constexpr int shl_signed_into_sign = 1 << 31; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
-  constexpr int shl_signed_overflow = 1024 << 31; // expected-error {{constant expression}} expected-note {{value 2199023255552 is outside the range}} expected-warning {{requires 43 bits to represent}}
+  constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457)
+  constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457)
+  constexpr int shl_signed_off_end = 2 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x100000000) requires 34 bits to represent, but 'int' only has 32 bits}}
+  constexpr int shl_signed_off_end_2 = 0x7fffffff << 2; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x1FFFFFFFC) requires 34 bits to represent, but 'int' only has 32 bits}}
+  constexpr int shl_signed_overflow = 1024 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{requires 43 bits to represent}}
   constexpr int shl_signed_ok2 = 1024 << 20; // ok
 
   constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}}

Removed: cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp?rev=150058&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp (original)
+++ cfe/trunk/test/SemaCXX/constexpr-sysheaders.cpp (removed)
@@ -1,25 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -include %s %s
-
-// libstdc++4.6 has a broken numeric_limits with a non-constant min() for signed
-// integral types. Disable the 'never produces a constant expression' error in
-// system headers to work around it. We still won't treat the function as
-// producing a constant expression, though.
-
-#ifndef INCLUDED_HEADER
-#define INCLUDED_HEADER
-
-#pragma GCC system_header
-
-// An approximation of libstdc++4.6's broken definition of numeric_limits.
-// FIXME: In the -include case, the line numbers are off by one for some reason!
-struct numeric_limits { // expected-note {{value 2147483648 is outside the range}}
-  static constexpr int min() throw() { return (int)1 << (sizeof(int) * 8 - 1); } // no-error
-  // expected-note {{in call to 'min()'}}
-  static constexpr int lowest() throw() { return min(); }
-};
-
-#else
-
-constexpr int k = numeric_limits::lowest(); // expected-error {{constant expression}} expected-note {{in call to 'lowest()'}}
-
-#endif





More information about the cfe-commits mailing list