diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 1126289aee..1206fe7fb3 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 3965a45171..7bcd205b22 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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()); } }; } diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp new file mode 100644 index 0000000000..1b38cf19b4 --- /dev/null +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +// PR9999 +template +class bitWidthHolding { +public: + static const + unsigned int width = (v == 0 ? 0 : bitWidthHolding<(v >> 1)>::width + 1); +}; + +static const int width=bitWidthHolding<255>::width; + +template +struct always_false { + static const bool value = false; +}; + +template +struct and_or { + static const bool and_value = b && and_or::value>::and_value; + static const bool or_value = !b || and_or::value>::or_value; +}; + +static const bool and_value = and_or::and_value; +static const bool or_value = and_or::or_value;