forked from OSchip/llvm-project
Implement the initial part of C++0x [expr.const]p2, which specifies
that the unevaluated subexpressions of &&, ||, and ? : are not considered when determining whether the expression is a constant expression. Also, turn the "used in its own initializer" warning into a runtime-behavior warning, so that it doesn't fire when a variable is used as part of an unevaluated subexpression of its own initializer. Fixes PR9999. llvm-svn: 131968
This commit is contained in:
parent
7c2c664500
commit
fcafc6e3de
|
@ -2957,6 +2957,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
|||
case BO_LAnd:
|
||||
case BO_LOr: {
|
||||
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
|
||||
|
||||
// C++0x [expr.const]p2:
|
||||
// [...] subexpressions of logical AND (5.14), logical OR
|
||||
// (5.15), and condi- tional (5.16) operations that are not
|
||||
// evaluated are not considered.
|
||||
if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) {
|
||||
if (Exp->getOpcode() == BO_LAnd &&
|
||||
Exp->getLHS()->EvaluateAsInt(Ctx) == 0)
|
||||
return LHSResult;
|
||||
|
||||
if (Exp->getOpcode() == BO_LOr &&
|
||||
Exp->getLHS()->EvaluateAsInt(Ctx) != 0)
|
||||
return LHSResult;
|
||||
}
|
||||
|
||||
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
|
||||
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
|
||||
// Rare case where the RHS has a comma "side-effect"; we need
|
||||
|
@ -3015,10 +3030,22 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
|||
return NoDiag();
|
||||
}
|
||||
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
|
||||
ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
|
||||
ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
|
||||
if (CondResult.Val == 2)
|
||||
return CondResult;
|
||||
|
||||
// C++0x [expr.const]p2:
|
||||
// subexpressions of [...] conditional (5.16) operations that
|
||||
// are not evaluated are not considered
|
||||
bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x
|
||||
? Exp->getCond()->EvaluateAsInt(Ctx) != 0
|
||||
: false;
|
||||
ICEDiag TrueResult = NoDiag();
|
||||
if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch)
|
||||
TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
|
||||
ICEDiag FalseResult = NoDiag();
|
||||
if (!Ctx.getLangOptions().CPlusPlus0x || !TrueBranch)
|
||||
FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
|
||||
|
||||
if (TrueResult.Val == 2)
|
||||
return TrueResult;
|
||||
if (FalseResult.Val == 2)
|
||||
|
|
|
@ -5149,9 +5149,11 @@ namespace {
|
|||
if (OrigDecl != ReferenceDecl) return;
|
||||
LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,
|
||||
Sema::NotForRedeclaration);
|
||||
S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init)
|
||||
<< Result.getLookupName() << OrigDecl->getLocation()
|
||||
<< SubExpr->getSourceRange();
|
||||
S.DiagRuntimeBehavior(SubExpr->getLocStart(), SubExpr,
|
||||
S.PDiag(diag::warn_uninit_self_reference_in_init)
|
||||
<< Result.getLookupName()
|
||||
<< OrigDecl->getLocation()
|
||||
<< SubExpr->getSourceRange());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s
|
||||
|
||||
// PR9999
|
||||
template<bool v>
|
||||
class bitWidthHolding {
|
||||
public:
|
||||
static const
|
||||
unsigned int width = (v == 0 ? 0 : bitWidthHolding<(v >> 1)>::width + 1);
|
||||
};
|
||||
|
||||
static const int width=bitWidthHolding<255>::width;
|
||||
|
||||
template<bool b>
|
||||
struct always_false {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<bool b>
|
||||
struct and_or {
|
||||
static const bool and_value = b && and_or<always_false<b>::value>::and_value;
|
||||
static const bool or_value = !b || and_or<always_false<b>::value>::or_value;
|
||||
};
|
||||
|
||||
static const bool and_value = and_or<true>::and_value;
|
||||
static const bool or_value = and_or<true>::or_value;
|
Loading…
Reference in New Issue