================ @@ -908,6 +908,74 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { incrementProfileCounter(&S); } +bool CodeGenFunction::checkIfLoopMustProgress(const Expr *ControllingExpression, + bool IsTrivialCXXLoop) { + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Always) + return true; + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Never) + return false; + + // Now apply rules for plain C (see 6.8.5.6 in C11). + // Loops with constant conditions do not have to make progress in any C + // version. + // As an extension, we consisider loops whose constant expression + // can be constant-folded. + Expr::EvalResult Result; + bool CondIsConstInt = + !ControllingExpression || + (ControllingExpression->EvaluateAsInt(Result, getContext()) && + Result.Val.isInt()); + + bool CondIsTrue = CondIsConstInt && + (!ControllingExpression || Result.Val.getInt().getBoolValue()); + + if (getLangOpts().C99 && CondIsConstInt) + return false; + + // Loops with non-constant conditions must make progress in C11 and later. + if (getLangOpts().C11) + return true; + + // [C++26][intro.progress] (DR) + // The implementation may assume that any thread will eventually do one of the + // following: + // [...] + // - continue execution of a trivial infinite loop ([stmt.iter.general]). + if (getLangOpts().CPlusPlus11) { + if (IsTrivialCXXLoop && CondIsTrue) { + CurFn->removeFnAttr(llvm::Attribute::MustProgress); + return false; + } + return true; + } + + return false; +} + +// [C++26][stmt.iter.general] (DR) +// A trivially empty iteration statement is an iteration statement matching one +// of the following forms: +// - while ( expression ) ; +// - while ( expression ) { } +// - do ; while ( expression ) ; +// - do { } while ( expression ) ; +// - for ( init-statement expression(opt); ) ; +// - for ( init-statement expression(opt); ) { } +template <typename LoopStmt> static bool hasEmptyLoopBody(const LoopStmt &S) { + if constexpr (std::is_same_v<LoopStmt, ForStmt>) { + if (S.getInc()) + return false; + } + const Stmt *Body = S.getBody(); + if (!Body || isa<NullStmt>(Body)) + return true; + if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) ---------------- shafik wrote:
It does not look like the test cover the `CompoundStmt` case. https://github.com/llvm/llvm-project/pull/90066 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits