1//===--- StmtUtils.cpp - Shared statement emission queries ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/CodeGenUtils/StmtUtils.h"
10#include "clang/AST/ASTContext.h"
11#include "clang/AST/Expr.h"
12
13namespace clang::CodeGenUtils {
14
15bool checkIfLoopMustProgress(const LangOptions &LangOpts,
16 const CodeGenOptions &CGOpts, ASTContext &Ctx,
17 const Expr *ControllingExpression,
18 bool HasEmptyBody,
19 llvm::function_ref<void()> RemoveMustProgress) {
20 if (CGOpts.getFiniteLoops() == CodeGenOptions::FiniteLoopsKind::Never)
21 return false;
22
23 // Now apply rules for plain C (see 6.8.5.6 in C11).
24 // Loops with constant conditions do not have to make progress in any C
25 // version.
26 // As an extension, we consisider loops whose constant expression
27 // can be constant-folded.
28 Expr::EvalResult Result;
29 bool CondIsConstInt =
30 !ControllingExpression ||
31 (ControllingExpression->EvaluateAsInt(Result, Ctx) && Result.Val.isInt());
32
33 bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
34 Result.Val.getInt().getBoolValue());
35
36 // Loops with non-constant conditions must make progress in C11 and later.
37 if (LangOpts.C11 && !CondIsConstInt)
38 return true;
39
40 // [C++26][intro.progress] (DR)
41 // The implementation may assume that any thread will eventually do one of the
42 // following:
43 // [...]
44 // - continue execution of a trivial infinite loop ([stmt.iter.general]).
45 if (CGOpts.getFiniteLoops() == CodeGenOptions::FiniteLoopsKind::Always ||
46 LangOpts.CPlusPlus11) {
47 if (HasEmptyBody && CondIsTrue) {
48 RemoveMustProgress();
49 return false;
50 }
51 return true;
52 }
53 return false;
54}
55
56} // namespace clang::CodeGenUtils
57