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:
Douglas Gregor 2011-05-24 16:02:01 +00:00
Родитель 5b4e7b11e7
Коммит 63fe6814f3
3 изменённых файлов: 59 добавлений и 5 удалений

Просмотреть файл

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