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.

llvm-svn: 150059
This commit is contained in:
Richard Smith 2012-02-08 06:14:53 +00:00
parent 5bc1712940
commit da7c4ba1af
5 changed files with 10 additions and 37 deletions

View File

@ -24,6 +24,7 @@ def note_constexpr_negative_shift : Note<"negative shift count %0">;
def note_constexpr_large_shift : Note< def note_constexpr_large_shift : Note<
"shift count %0 >= width of type %1 (%2 bit%s2)">; "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_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< def note_constexpr_invalid_function : Note<
"%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot " "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot "
"be used in a constant expression">; "be used in a constant expression">;

View File

@ -4704,12 +4704,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
<< RHS << E->getType() << LHS.getBitWidth(); << RHS << E->getType() << LHS.getBitWidth();
} else if (LHS.isSigned()) { } else if (LHS.isSigned()) {
// C++11 [expr.shift]p2: A signed left shift must have a non-negative // 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()) if (LHS.isNegative())
CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS;
else if (LHS.countLeadingZeros() <= SA) else if (LHS.countLeadingZeros() < SA)
HandleOverflow(Info, E, LHS.extend(LHS.getBitWidth() + SA) << SA, CCEDiag(E, diag::note_constexpr_lshift_discards);
E->getType());
} }
return Success(LHS << SA, E); return Success(LHS << SA, E);

View File

@ -984,13 +984,8 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body,
// C++11 [dcl.constexpr]p4: // C++11 [dcl.constexpr]p4:
// - every constructor involved in initializing non-static data members and // - every constructor involved in initializing non-static data members and
// base class sub-objects shall be a constexpr constructor. // 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; llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
if (!Context.getSourceManager().isInSystemHeader(Dcl->getLocation()) && if (!IsInstantiation && !Expr::isPotentialConstantExpr(Dcl, Diags)) {
!IsInstantiation && !Expr::isPotentialConstantExpr(Dcl, Diags)) {
Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr) Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl); << isa<CXXConstructorDecl>(Dcl);
for (size_t I = 0, N = Diags.size(); I != N; ++I) for (size_t I = 0, N = Diags.size(); I != N; ++I)

View File

@ -144,8 +144,11 @@ namespace UndefinedBehavior {
constexpr int shl_unsigned_overflow = 1024u << 31; // ok 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_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_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_into_sign = 1 << 31; // ok (DR1457)
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_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 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}} constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}}

View File

@ -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