diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -27,6 +27,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/SyncScope.h" #include "clang/Basic/TypeTraits.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" @@ -3804,12 +3805,37 @@ /// value-dependent). If either x or y is type-dependent, or if the /// "+" resolves to an overloaded operator, CXXOperatorCallExpr will /// be used to express the computation. +namespace { + +enum ICEKind { + /// This expression is an ICE. + IK_ICE, + /// This expression is not an ICE, but if it isn't evaluated, it's + /// a legal subexpression for an ICE. This return value is used to handle + /// the comma operator in C99 mode, and non-constant subexpressions. + IK_ICEIfUnevaluated, + /// This expression is not an ICE, and is not a legal subexpression for one. + IK_NotICE, +}; + +struct ICEDiag { + ICEKind Kind; + SourceLocation Loc; + + ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} +}; + +} + class BinaryOperator : public Expr { enum { LHS, RHS, END_EXPR }; Stmt *SubExprs[END_EXPR]; public: typedef BinaryOperatorKind Opcode; + /* ICEDiag Diag{IK_NotYetEvaluated, SourceLocation()}; */ + llvm::Optional IK; + /* ICEKind IK = IK_NotYetEvaluated; */ protected: size_t offsetOfTrailingStorage() const; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15283,27 +15283,6 @@ // in the rare cases where CheckICE actually cares about the evaluated // value, it calls into Evaluate. -namespace { - -enum ICEKind { - /// This expression is an ICE. - IK_ICE, - /// This expression is not an ICE, but if it isn't evaluated, it's - /// a legal subexpression for an ICE. This return value is used to handle - /// the comma operator in C99 mode, and non-constant subexpressions. - IK_ICEIfUnevaluated, - /// This expression is not an ICE, and is not a legal subexpression for one. - IK_NotICE -}; - -struct ICEDiag { - ICEKind Kind; - SourceLocation Loc; - - ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} -}; - -} static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); } @@ -15322,7 +15301,7 @@ return NoDiag(); } -static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { +static ICEDiag CheckICE(Expr* E, const ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); if (!E->getType()->isIntegralOrEnumerationType()) return ICEDiag(IK_NotICE, E->getBeginLoc()); @@ -15533,7 +15512,9 @@ return NoDiag(); } case Expr::BinaryOperatorClass: { - const BinaryOperator *Exp = cast(E); + BinaryOperator *Exp = cast(E); + if (Exp->IK.has_value()) return ICEDiag(Exp->IK.value(), E->getBeginLoc()); + /* if (Exp->IK != IK_NotYetEvaluated) return ICEDiag(Exp->IK, E->getBeginLoc()); */ switch (Exp->getOpcode()) { case BO_PtrMemD: case BO_PtrMemI: @@ -15551,6 +15532,7 @@ // C99 6.6/3 allows assignments within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an lvalue operand. + Exp->IK = IK_NotICE; return ICEDiag(IK_NotICE, E->getBeginLoc()); case BO_Mul: @@ -15579,12 +15561,16 @@ // we don't evaluate one. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); - if (REval == 0) + if (REval == 0) { + Exp->IK = IK_ICEIfUnevaluated; return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); + } if (REval.isSigned() && REval.isAllOnes()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); - if (LEval.isMinSignedValue()) + if (LEval.isMinSignedValue()) { + Exp->IK = IK_ICEIfUnevaluated; return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); + } } } } @@ -15592,14 +15578,19 @@ if (Ctx.getLangOpts().C99) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. - if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) + if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { + Exp->IK = IK_ICEIfUnevaluated; return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); + } } else { // In both C89 and C++, commas in ICEs are illegal. + Exp->IK = IK_NotICE; return ICEDiag(IK_NotICE, E->getBeginLoc()); } } - return Worst(LHSResult, RHSResult); + ICEDiag D = Worst(LHSResult, RHSResult); + Exp->IK = D.Kind; + return D; } case BO_LAnd: case BO_LOr: { @@ -15610,12 +15601,16 @@ // to actually check the condition to see whether the side // with the comma is evaluated. if ((Exp->getOpcode() == BO_LAnd) != - (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) + (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) { + Exp->IK = RHSResult.Kind; return RHSResult; + } + Exp->IK = IK_ICE; return NoDiag(); } - - return Worst(LHSResult, RHSResult); + ICEDiag WorstResult = Worst(LHSResult, RHSResult); + Exp->IK = WorstResult.Kind; + return WorstResult; } } llvm_unreachable("invalid binary operator kind"); @@ -15747,7 +15742,6 @@ if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); - ICEDiag D = CheckICE(this, Ctx); if (D.Kind != IK_ICE) { if (Loc) *Loc = D.Loc;