зеркало из https://github.com/microsoft/clang.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131968 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
5b4e7b11e7
Коммит
63fe6814f3
|
@ -2957,6 +2957,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
||||||
case BO_LAnd:
|
case BO_LAnd:
|
||||||
case BO_LOr: {
|
case BO_LOr: {
|
||||||
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
|
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);
|
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
|
||||||
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
|
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
|
||||||
// Rare case where the RHS has a comma "side-effect"; we need
|
// 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();
|
return NoDiag();
|
||||||
}
|
}
|
||||||
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
|
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
|
||||||
ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
|
|
||||||
ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
|
|
||||||
if (CondResult.Val == 2)
|
if (CondResult.Val == 2)
|
||||||
return CondResult;
|
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)
|
if (TrueResult.Val == 2)
|
||||||
return TrueResult;
|
return TrueResult;
|
||||||
if (FalseResult.Val == 2)
|
if (FalseResult.Val == 2)
|
||||||
|
|
|
@ -5149,9 +5149,11 @@ namespace {
|
||||||
if (OrigDecl != ReferenceDecl) return;
|
if (OrigDecl != ReferenceDecl) return;
|
||||||
LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,
|
LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName,
|
||||||
Sema::NotForRedeclaration);
|
Sema::NotForRedeclaration);
|
||||||
S.Diag(SubExpr->getLocStart(), diag::warn_uninit_self_reference_in_init)
|
S.DiagRuntimeBehavior(SubExpr->getLocStart(), SubExpr,
|
||||||
<< Result.getLookupName() << OrigDecl->getLocation()
|
S.PDiag(diag::warn_uninit_self_reference_in_init)
|
||||||
<< SubExpr->getSourceRange();
|
<< 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;
|
Загрузка…
Ссылка в новой задаче