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:
parent
5bc1712940
commit
da7c4ba1af
|
@ -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">;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in New Issue