[llvm-branch-commits] [clang] [CIR][CodeGen][NFC] Retire the CodeGenUtils.h catch-all header (PR #223451)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Sep 29 04:23:38 PDT 2026


https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223451

>From 74cbb5d53a1acddf9a5484ce71ffb5d7dfdf18d0 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Mon, 14 Sep 2026 16:22:27 +0000
Subject: [PATCH] [CIR][CodeGen][NFC] Retire the CodeGenUtils.h catch-all
 header

Moves the last helpers out of `CodeGenUtils.h` into `ClassUtils.h`,
`ModuleUtils.h`, `TargetUtils.h` and `FunctionUtils.h` (`checkTargetFeatures`,
since it came from CodeGenFunction.cpp) and deletes the header. Only moves code
already on main, so it can be dropped on its own.
---
 clang/include/clang/CodeGenUtils/ClassUtils.h |  18 ++
 .../include/clang/CodeGenUtils/CodeGenUtils.h |  65 -----
 .../clang/CodeGenUtils/FunctionUtils.h        |  26 +-
 .../include/clang/CodeGenUtils/ModuleUtils.h  |   7 +
 .../include/clang/CodeGenUtils/TargetUtils.h  |   4 +
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |   2 +-
 clang/lib/CIR/CodeGen/CIRGenClass.cpp         |   1 -
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          |   2 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp      |   2 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        |   1 -
 .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp |   2 +-
 clang/lib/CodeGen/CGClass.cpp                 |   1 -
 clang/lib/CodeGen/CGExpr.cpp                  |   2 +-
 clang/lib/CodeGen/CGRecordLayoutBuilder.cpp   |   2 +-
 clang/lib/CodeGen/CodeGenFunction.cpp         |   1 -
 clang/lib/CodeGen/CodeGenModule.cpp           |   1 -
 clang/lib/CodeGenUtils/CMakeLists.txt         |   1 -
 clang/lib/CodeGenUtils/ClassUtils.cpp         |  78 ++++++
 clang/lib/CodeGenUtils/CodeGenUtils.cpp       | 233 ------------------
 clang/lib/CodeGenUtils/FunctionUtils.cpp      | 120 +++++++++
 clang/lib/CodeGenUtils/ModuleUtils.cpp        |  17 ++
 clang/lib/CodeGenUtils/TargetUtils.cpp        |   5 +
 22 files changed, 279 insertions(+), 312 deletions(-)
 delete mode 100644 clang/include/clang/CodeGenUtils/CodeGenUtils.h
 delete mode 100644 clang/lib/CodeGenUtils/CodeGenUtils.cpp

diff --git a/clang/include/clang/CodeGenUtils/ClassUtils.h b/clang/include/clang/CodeGenUtils/ClassUtils.h
index 63664ed737933..570c67110e120 100644
--- a/clang/include/clang/CodeGenUtils/ClassUtils.h
+++ b/clang/include/clang/CodeGenUtils/ClassUtils.h
@@ -24,6 +24,24 @@ namespace clang::CodeGenUtils {
 /// properly set.
 bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init);
 
+/// Check whether we need to initialize any vtable pointers before calling this
+/// destructor.
+bool canSkipVTablePointerInitialization(ASTContext &Ctx,
+                                        const CXXDestructorDecl *Dtor);
+
+/// Check whether destructing \p Field has no observable behaviors, and thus can
+/// be skipped when creating a destructor body. So non-record types, anonymous
+/// structs/unions, or record types where the destructor doesnt DO anything are
+/// considered as this version of 'trivial'.
+/// Note: This is a more liberal definition of trivial destruction than the C++
+/// Standard's version, and thus cannot be used as a substitute for C++ Standard
+/// requirements.
+bool fieldHasTrivialDestructorBody(ASTContext &Ctx, const FieldDecl *Field);
+
+/// Return whether \p BaseInit initializes a base class that is dynamic, that
+/// is, one whose vtable pointer must be set before the initializer runs.
+bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit);
+
 } // namespace clang::CodeGenUtils
 
 #endif // LLVM_CLANG_CODEGENUTILS_CLASSUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/CodeGenUtils.h b/clang/include/clang/CodeGenUtils/CodeGenUtils.h
deleted file mode 100644
index b24f457f9537c..0000000000000
--- a/clang/include/clang/CodeGenUtils/CodeGenUtils.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//===--- CodeGenUtils.h - Shared Classic CodeGen/CIR CodeGen Utils--C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
-#define LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/SourceLocation.h"
-
-namespace clang {
-class CallExpr;
-class DiagnosticsEngine;
-class FunctionDecl;
-class LangOptions;
-} // namespace clang
-
-namespace clang::CodeGenUtils {
-/// Check whether we need to initialize any vtable pointers before calling this
-/// destructor.
-bool canSkipVTablePointerInitialization(ASTContext &Ctx,
-                                        const CXXDestructorDecl *Dtor);
-
-/// Check whether destructing \p Field has no observable behaviors, and thus can
-/// be skipped when creating a destructor body. So non-record types, anonymous
-/// structs/unions, or record types where the destructor doesnt DO anything are
-/// considered as this version of 'trivial'.
-/// Note: This is a more liberal definition of trivial destruction than the C++
-/// Standard's version, and thus cannot be used as a substitute for C++ Standard
-/// requirements.
-bool fieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);
-
-/// Determines whether the language options require us to model
-/// unwind exceptions.  We treat -fexceptions as mandating this
-/// except under the fragile ObjC ABI with only ObjC exceptions
-/// enabled.  This means, for example, that C with -fexceptions
-/// enables this.
-bool hasUnwindExceptions(const LangOptions &LangOpts);
-
-/// Helper method to check if the underlying ABI is AAPCS
-bool isAAPCS(const TargetInfo &TargetInfo);
-
-bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit);
-
-/// Check that a call to a target-specific builtin has the required target
-/// features enabled in the caller, emitting an error diagnostic if not.
-/// \p caller is the FunctionDecl of the enclosing function (may be null).
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
-                         const LangOptions &LangOpts, const CallExpr *E,
-                         const FunctionDecl *Caller,
-                         const FunctionDecl *TargetDecl);
-
-/// Overload taking a raw source location instead of a CallExpr.
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
-                         const LangOptions &LangOpts, SourceLocation Loc,
-                         const FunctionDecl *Caller,
-                         const FunctionDecl *TargetDecl);
-
-} // namespace clang::CodeGenUtils
-
-#endif // LLVM_CLANG_CODEGENUTILS_CODEGENUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/FunctionUtils.h b/clang/include/clang/CodeGenUtils/FunctionUtils.h
index f924874d829e0..4e500aa8d3c0b 100644
--- a/clang/include/clang/CodeGenUtils/FunctionUtils.h
+++ b/clang/include/clang/CodeGenUtils/FunctionUtils.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file holds the queries that both classic CodeGen and CIR CodeGen need
-// while emitting a function body.
+// This file holds the queries and checks that both classic CodeGen and CIR
+// CodeGen need while emitting a function body.
 //
 //===----------------------------------------------------------------------===//
 
@@ -16,6 +16,14 @@
 
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class ASTContext;
+class CallExpr;
+class DiagnosticsEngine;
+class FunctionDecl;
+} // namespace clang
 
 namespace clang::CodeGenUtils {
 
@@ -23,6 +31,20 @@ namespace clang::CodeGenUtils {
 bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
                                const LangOptions &LangOpts);
 
+/// Check that a call to a target-specific builtin has the required target
+/// features enabled in the caller, emitting an error diagnostic if not.
+/// \p Caller is the FunctionDecl of the enclosing function (may be null).
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+                         const LangOptions &LangOpts, const CallExpr *E,
+                         const FunctionDecl *Caller,
+                         const FunctionDecl *TargetDecl);
+
+/// Overload taking a raw source location instead of a CallExpr.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+                         const LangOptions &LangOpts, SourceLocation Loc,
+                         const FunctionDecl *Caller,
+                         const FunctionDecl *TargetDecl);
+
 } // namespace clang::CodeGenUtils
 
 #endif // LLVM_CLANG_CODEGENUTILS_FUNCTIONUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/ModuleUtils.h b/clang/include/clang/CodeGenUtils/ModuleUtils.h
index 5c7423ad4fac5..3bb94184a03f0 100644
--- a/clang/include/clang/CodeGenUtils/ModuleUtils.h
+++ b/clang/include/clang/CodeGenUtils/ModuleUtils.h
@@ -19,6 +19,13 @@
 
 namespace clang::CodeGenUtils {
 
+/// Determines whether the language options require us to model
+/// unwind exceptions.  We treat -fexceptions as mandating this
+/// except under the fragile ObjC ABI with only ObjC exceptions
+/// enabled.  This means, for example, that C with -fexceptions
+/// enables this.
+bool hasUnwindExceptions(const LangOptions &LangOpts);
+
 /// Check whether \p D is a strong definition, and thus must not be given
 /// common linkage.  \p NoCommon reflects -fno-common.
 bool isVarDeclStrongDefinition(const ASTContext &Ctx, const VarDecl *D,
diff --git a/clang/include/clang/CodeGenUtils/TargetUtils.h b/clang/include/clang/CodeGenUtils/TargetUtils.h
index a44541c572590..2c812c6a2b617 100644
--- a/clang/include/clang/CodeGenUtils/TargetUtils.h
+++ b/clang/include/clang/CodeGenUtils/TargetUtils.h
@@ -21,6 +21,7 @@
 namespace clang {
 class Decl;
 class FunctionDecl;
+class TargetInfo;
 } // namespace clang
 
 namespace clang::CodeGenUtils {
@@ -53,6 +54,9 @@ ArmSMEInlinability getArmSMEInlinability(const FunctionDecl *Caller,
 /// TODO: Make this return false for SISD builtins.
 bool hasExtraNeonArgument(unsigned BuiltinID);
 
+/// Helper method to check if the underlying ABI is AAPCS
+bool isAAPCS(const TargetInfo &TargetInfo);
+
 /// Returns whether \p D must be given protected visibility on AMDGPU.
 /// \p HasHiddenVisibility is whether the emitted global currently has hidden
 /// visibility.
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 245708691b7d9..56cf268e119a6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -26,7 +26,7 @@
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/FunctionUtils.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 28db1763fd3cb..9633b915bd669 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -20,7 +20,6 @@
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/MissingFeatures.h"
 #include "clang/CodeGenUtils/ClassUtils.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index d285800111c45..8f57a90c06218 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -30,8 +30,8 @@
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/ExprUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
 #include <optional>
 
 using namespace clang;
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 823ccbe1d2e82..0f3aca2f67e4e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -21,7 +21,7 @@
 #include "clang/AST/GlobalDecl.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/ClassUtils.h"
 #include "clang/CodeGenUtils/FunctionUtils.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/IR/FPEnv.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 8978f8305b267..6509df09ee8dd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -36,7 +36,6 @@
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/Interfaces/CIROpInterfaces.h"
 #include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/ModuleUtils.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index 63715e1f6e814..49651c08c76d2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -22,8 +22,8 @@
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDataLayout.h"
 #include "clang/CIR/MissingFeatures.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/RecordLayoutUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
 #include "llvm/Support/Casting.h"
 
 #include <memory>
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 63f5d9ae13dbf..31965c98c75bb 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -26,7 +26,6 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGenUtils/ClassUtils.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/Support/SaveAndRestore.h"
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 25e775f8328b9..b23b347643dcd 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -39,8 +39,8 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/ExprUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 905382f5ea939..dc6a7bfca35f6 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -21,8 +21,8 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/CodeGenOptions.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/RecordLayoutUtils.h"
+#include "clang/CodeGenUtils/TargetUtils.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Type.h"
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 8f4d9aae1603e..4e9883a091261 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -36,7 +36,6 @@
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/FunctionUtils.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ScopeExit.h"
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 6cdd35d5e1308..da04faa954875 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -48,7 +48,6 @@
 #include "clang/Basic/Version.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
-#include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "clang/CodeGenUtils/ModuleUtils.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ABI/IRTypeMapper.h"
diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt b/clang/lib/CodeGenUtils/CMakeLists.txt
index edd32da5b5f7c..b083d95e9d47c 100644
--- a/clang/lib/CodeGenUtils/CMakeLists.txt
+++ b/clang/lib/CodeGenUtils/CMakeLists.txt
@@ -5,7 +5,6 @@ set(LLVM_LINK_COMPONENTS
 add_clang_library(clangCodeGenUtils
   CallUtils.cpp
   ClassUtils.cpp
-  CodeGenUtils.cpp
   EHPersonality.cpp
   ExprUtils.cpp
   FunctionUtils.cpp
diff --git a/clang/lib/CodeGenUtils/ClassUtils.cpp b/clang/lib/CodeGenUtils/ClassUtils.cpp
index 90bab38280c30..5a504ca0b5beb 100644
--- a/clang/lib/CodeGenUtils/ClassUtils.cpp
+++ b/clang/lib/CodeGenUtils/ClassUtils.cpp
@@ -36,4 +36,82 @@ bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init) {
   return Checker.UsesThis;
 }
 
+static bool
+hasTrivialDestructorBody(ASTContext &Ctx, const CXXRecordDecl *BaseClassDecl,
+                         const CXXRecordDecl *MostDerivedClassDecl) {
+  // If the destructor is trivial we don't have to check anything else.
+  if (BaseClassDecl->hasTrivialDestructor())
+    return true;
+
+  if (!BaseClassDecl->getDestructor()->hasTrivialBody())
+    return false;
+
+  // Check fields.
+  for (const auto *Field : BaseClassDecl->fields())
+    if (!fieldHasTrivialDestructorBody(Ctx, Field))
+      return false;
+
+  // Check non-virtual bases.
+  for (const auto &I : BaseClassDecl->bases()) {
+    if (I.isVirtual())
+      continue;
+
+    const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();
+    if (!hasTrivialDestructorBody(Ctx, NonVirtualBase, MostDerivedClassDecl))
+      return false;
+  }
+
+  if (BaseClassDecl == MostDerivedClassDecl) {
+    // Check virtual bases.
+    for (const auto &I : BaseClassDecl->vbases()) {
+      const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
+      if (!hasTrivialDestructorBody(Ctx, VirtualBase, MostDerivedClassDecl))
+        return false;
+    }
+  }
+
+  return true;
+}
+
+bool fieldHasTrivialDestructorBody(ASTContext &Ctx, const FieldDecl *Field) {
+  QualType FieldBaseElementType = Ctx.getBaseElementType(Field->getType());
+
+  auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
+  if (!FieldClassDecl)
+    return true;
+
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+    return true;
+
+  return hasTrivialDestructorBody(Ctx, FieldClassDecl, FieldClassDecl);
+}
+
+bool canSkipVTablePointerInitialization(ASTContext &Ctx,
+                                        const CXXDestructorDecl *Dtor) {
+  const CXXRecordDecl *ClassDecl = Dtor->getParent();
+  if (!ClassDecl->isDynamicClass())
+    return true;
+
+  // For a final class, the vtable pointer is known to already point to the
+  // class's vtable.
+  if (ClassDecl->isEffectivelyFinal())
+    return true;
+
+  if (!Dtor->hasTrivialBody())
+    return false;
+
+  // Check the fields.
+  for (const auto *Field : ClassDecl->fields())
+    if (!fieldHasTrivialDestructorBody(Ctx, Field))
+      return false;
+
+  return true;
+}
+
+bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
+  const Type *BaseType = BaseInit->getBaseClass();
+  return BaseType->castAsCXXRecordDecl()->isDynamicClass();
+}
+
 } // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/CodeGenUtils.cpp b/clang/lib/CodeGenUtils/CodeGenUtils.cpp
deleted file mode 100644
index 4fd78d6997e95..0000000000000
--- a/clang/lib/CodeGenUtils/CodeGenUtils.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-//==--- CodeGenUtils.cpp - Shared Classic CodeGen/CIR CodeGen Utils--C++ -*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/CodeGenUtils/CodeGenUtils.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/Expr.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Basic/TargetBuiltins.h"
-#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/StringMap.h"
-
-namespace clang::CodeGenUtils {
-static bool
-hasTrivialDestructorBody(ASTContext &Context,
-                         const CXXRecordDecl *BaseClassDecl,
-                         const CXXRecordDecl *MostDerivedClassDecl) {
-  // If the destructor is trivial we don't have to check anything else.
-  if (BaseClassDecl->hasTrivialDestructor())
-    return true;
-
-  if (!BaseClassDecl->getDestructor()->hasTrivialBody())
-    return false;
-
-  // Check fields.
-  for (const auto *Field : BaseClassDecl->fields())
-    if (!fieldHasTrivialDestructorBody(Context, Field))
-      return false;
-
-  // Check non-virtual bases.
-  for (const auto &I : BaseClassDecl->bases()) {
-    if (I.isVirtual())
-      continue;
-
-    const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();
-    if (!hasTrivialDestructorBody(Context, NonVirtualBase,
-                                  MostDerivedClassDecl))
-      return false;
-  }
-
-  if (BaseClassDecl == MostDerivedClassDecl) {
-    // Check virtual bases.
-    for (const auto &I : BaseClassDecl->vbases()) {
-      const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
-      if (!hasTrivialDestructorBody(Context, VirtualBase, MostDerivedClassDecl))
-        return false;
-    }
-  }
-
-  return true;
-}
-
-bool fieldHasTrivialDestructorBody(ASTContext &Context,
-                                   const FieldDecl *Field) {
-  QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
-
-  auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
-  if (!FieldClassDecl)
-    return true;
-
-  // The destructor for an implicit anonymous union member is never invoked.
-  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
-    return true;
-
-  return hasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
-}
-
-/// Check whether we need to initialize any vtable pointers before calling this
-/// destructor.
-bool canSkipVTablePointerInitialization(ASTContext &Ctx,
-                                        const CXXDestructorDecl *Dtor) {
-  const CXXRecordDecl *ClassDecl = Dtor->getParent();
-  if (!ClassDecl->isDynamicClass())
-    return true;
-
-  // For a final class, the vtable pointer is known to already point to the
-  // class's vtable.
-  if (ClassDecl->isEffectivelyFinal())
-    return true;
-
-  if (!Dtor->hasTrivialBody())
-    return false;
-
-  // Check the fields.
-  for (const auto *Field : ClassDecl->fields())
-    if (!fieldHasTrivialDestructorBody(Ctx, Field))
-      return false;
-
-  return true;
-}
-bool hasUnwindExceptions(const LangOptions &LangOpts) {
-  // If exceptions are completely disabled, obviously this is false.
-  if (!LangOpts.Exceptions)
-    return false;
-
-  // If C++ exceptions are enabled, this is true.
-  if (LangOpts.CXXExceptions)
-    return true;
-
-  // If ObjC exceptions are enabled, this depends on the ABI.
-  if (LangOpts.ObjCExceptions) {
-    return LangOpts.ObjCRuntime.hasUnwindExceptions();
-  }
-
-  return true;
-}
-
-bool isAAPCS(const TargetInfo &TargetInfo) {
-  return TargetInfo.getABI().starts_with("aapcs");
-}
-bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
-  const Type *BaseType = BaseInit->getBaseClass();
-  return BaseType->castAsCXXRecordDecl()->isDynamicClass();
-}
-
-// Emits an error if we don't have a valid set of target features for the
-// called function.
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
-                         const LangOptions &LangOpts, const CallExpr *E,
-                         const FunctionDecl *Caller,
-                         const FunctionDecl *TargetDecl) {
-  // SemaChecking cannot handle these x86 builtins because they have different
-  // parameter ranges depending on the caller's TargetAttribute.
-  if (Ctx.getTargetInfo().getTriple().isX86()) {
-    unsigned BuiltinID = TargetDecl->getBuiltinID();
-    if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
-        BuiltinID == X86::BI__builtin_ia32_cmpss ||
-        BuiltinID == X86::BI__builtin_ia32_cmppd ||
-        BuiltinID == X86::BI__builtin_ia32_cmpsd) {
-      llvm::StringMap<bool> TargetFeatureMap;
-      Ctx.getFunctionFeatureMap(TargetFeatureMap, Caller);
-      llvm::APSInt Result = *(E->getArg(2)->getIntegerConstantExpr(Ctx));
-      if (Result.getSExtValue() > 7 && !TargetFeatureMap.lookup("avx"))
-        Diags.Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
-            << TargetDecl->getDeclName() << "avx";
-    }
-  }
-  checkTargetFeatures(Ctx, Diags, LangOpts, E->getBeginLoc(), Caller,
-                      TargetDecl);
-}
-
-// Emits an error if we don't have a valid set of target features for the
-// called function.
-void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
-                         const LangOptions &LangOpts, SourceLocation Loc,
-                         const FunctionDecl *Caller,
-                         const FunctionDecl *TargetDecl) {
-  if (!TargetDecl || !Caller)
-    return;
-
-  bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
-  bool IsFlatten = Caller->hasAttr<FlattenAttr>();
-
-  unsigned BuiltinID = TargetDecl->getBuiltinID();
-  std::string MissingFeature;
-  llvm::StringMap<bool> CallerFeatureMap;
-  Ctx.getFunctionFeatureMap(CallerFeatureMap, Caller);
-  // When compiling in HipStdPar mode we have to be conservative in rejecting
-  // target specific features in the FE, and defer the possible error to the
-  // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
-  // referenced by an accelerator executable function, we emit an error.
-  bool IsHipStdPar = LangOpts.HIPStdPar && LangOpts.CUDAIsDevice;
-  if (BuiltinID) {
-    StringRef FeatureList(Ctx.BuiltinInfo.getRequiredFeatures(BuiltinID));
-    if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
-                                                 CallerFeatureMap) &&
-        !IsHipStdPar)
-      Diags.Report(Loc, diag::err_builtin_needs_feature)
-          << TargetDecl->getDeclName() << FeatureList;
-  } else if (!TargetDecl->isMultiVersion() &&
-             TargetDecl->hasAttr<TargetAttr>()) {
-    // Get the required features for the callee.
-    const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
-    ParsedTargetAttr ParsedAttr = Ctx.filterFunctionTargetAttrs(TD);
-
-    SmallVector<StringRef, 1> ReqFeatures;
-    llvm::StringMap<bool> CalleeFeatureMap;
-    Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
-
-    for (const auto &F : ParsedAttr.Features) {
-      if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
-        ReqFeatures.push_back(StringRef(F).substr(1));
-    }
-    for (const auto &F : CalleeFeatureMap) {
-      if (F.getValue())
-        ReqFeatures.push_back(F.getKey());
-    }
-    if (!llvm::all_of(ReqFeatures,
-                      [&](StringRef Feature) {
-                        if (!CallerFeatureMap.lookup(Feature)) {
-                          MissingFeature = Feature.str();
-                          return false;
-                        }
-                        return true;
-                      }) &&
-        !IsHipStdPar) {
-      if (IsAlwaysInline)
-        Diags.Report(Loc, diag::err_function_needs_feature)
-            << Caller->getDeclName() << TargetDecl->getDeclName()
-            << MissingFeature;
-      else if (IsFlatten)
-        Diags.Report(Loc, diag::err_flatten_function_needs_feature)
-            << Caller->getDeclName() << TargetDecl->getDeclName()
-            << MissingFeature;
-    }
-  } else if (!Caller->isMultiVersion() && Caller->hasAttr<TargetAttr>()) {
-    llvm::StringMap<bool> CalleeFeatureMap;
-    Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
-
-    for (const auto &F : CalleeFeatureMap) {
-      if (F.getValue() &&
-          (!CallerFeatureMap.lookup(F.getKey()) ||
-           !CallerFeatureMap.find(F.getKey())->getValue()) &&
-          !IsHipStdPar) {
-        if (IsAlwaysInline)
-          Diags.Report(Loc, diag::err_function_needs_feature)
-              << Caller->getDeclName() << TargetDecl->getDeclName()
-              << F.getKey();
-        else if (IsFlatten)
-          Diags.Report(Loc, diag::err_flatten_function_needs_feature)
-              << Caller->getDeclName() << TargetDecl->getDeclName()
-              << F.getKey();
-      }
-    }
-  }
-}
-
-} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/FunctionUtils.cpp b/clang/lib/CodeGenUtils/FunctionUtils.cpp
index 9f01745abbf82..083c04d30bec4 100644
--- a/clang/lib/CodeGenUtils/FunctionUtils.cpp
+++ b/clang/lib/CodeGenUtils/FunctionUtils.cpp
@@ -7,6 +7,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/CodeGenUtils/FunctionUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringMap.h"
 
 namespace clang::CodeGenUtils {
 
@@ -26,4 +34,116 @@ bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
   return CGOpts.OptimizationLevel != 0;
 }
 
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+                         const LangOptions &LangOpts, const CallExpr *E,
+                         const FunctionDecl *Caller,
+                         const FunctionDecl *TargetDecl) {
+  // SemaChecking cannot handle these x86 builtins because they have different
+  // parameter ranges depending on the caller's TargetAttribute.
+  if (Ctx.getTargetInfo().getTriple().isX86()) {
+    unsigned BuiltinID = TargetDecl->getBuiltinID();
+    if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
+        BuiltinID == X86::BI__builtin_ia32_cmpss ||
+        BuiltinID == X86::BI__builtin_ia32_cmppd ||
+        BuiltinID == X86::BI__builtin_ia32_cmpsd) {
+      llvm::StringMap<bool> TargetFeatureMap;
+      Ctx.getFunctionFeatureMap(TargetFeatureMap, Caller);
+      llvm::APSInt Result = *(E->getArg(2)->getIntegerConstantExpr(Ctx));
+      if (Result.getSExtValue() > 7 && !TargetFeatureMap.lookup("avx"))
+        Diags.Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
+            << TargetDecl->getDeclName() << "avx";
+    }
+  }
+  checkTargetFeatures(Ctx, Diags, LangOpts, E->getBeginLoc(), Caller,
+                      TargetDecl);
+}
+
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void checkTargetFeatures(ASTContext &Ctx, DiagnosticsEngine &Diags,
+                         const LangOptions &LangOpts, SourceLocation Loc,
+                         const FunctionDecl *Caller,
+                         const FunctionDecl *TargetDecl) {
+  if (!TargetDecl || !Caller)
+    return;
+
+  bool IsAlwaysInline = TargetDecl->hasAttr<AlwaysInlineAttr>();
+  bool IsFlatten = Caller->hasAttr<FlattenAttr>();
+
+  unsigned BuiltinID = TargetDecl->getBuiltinID();
+  std::string MissingFeature;
+  llvm::StringMap<bool> CallerFeatureMap;
+  Ctx.getFunctionFeatureMap(CallerFeatureMap, Caller);
+  // When compiling in HipStdPar mode we have to be conservative in rejecting
+  // target specific features in the FE, and defer the possible error to the
+  // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
+  // referenced by an accelerator executable function, we emit an error.
+  bool IsHipStdPar = LangOpts.HIPStdPar && LangOpts.CUDAIsDevice;
+  if (BuiltinID) {
+    StringRef FeatureList(Ctx.BuiltinInfo.getRequiredFeatures(BuiltinID));
+    if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
+                                                 CallerFeatureMap) &&
+        !IsHipStdPar)
+      Diags.Report(Loc, diag::err_builtin_needs_feature)
+          << TargetDecl->getDeclName() << FeatureList;
+  } else if (!TargetDecl->isMultiVersion() &&
+             TargetDecl->hasAttr<TargetAttr>()) {
+    // Get the required features for the callee.
+    const TargetAttr *TD = TargetDecl->getAttr<TargetAttr>();
+    ParsedTargetAttr ParsedAttr = Ctx.filterFunctionTargetAttrs(TD);
+
+    SmallVector<StringRef, 1> ReqFeatures;
+    llvm::StringMap<bool> CalleeFeatureMap;
+    Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+    for (const auto &F : ParsedAttr.Features) {
+      if (F[0] == '+' && CalleeFeatureMap.lookup(F.substr(1)))
+        ReqFeatures.push_back(StringRef(F).substr(1));
+    }
+    for (const auto &F : CalleeFeatureMap) {
+      if (F.getValue())
+        ReqFeatures.push_back(F.getKey());
+    }
+    if (!llvm::all_of(ReqFeatures,
+                      [&](StringRef Feature) {
+                        if (!CallerFeatureMap.lookup(Feature)) {
+                          MissingFeature = Feature.str();
+                          return false;
+                        }
+                        return true;
+                      }) &&
+        !IsHipStdPar) {
+      if (IsAlwaysInline)
+        Diags.Report(Loc, diag::err_function_needs_feature)
+            << Caller->getDeclName() << TargetDecl->getDeclName()
+            << MissingFeature;
+      else if (IsFlatten)
+        Diags.Report(Loc, diag::err_flatten_function_needs_feature)
+            << Caller->getDeclName() << TargetDecl->getDeclName()
+            << MissingFeature;
+    }
+  } else if (!Caller->isMultiVersion() && Caller->hasAttr<TargetAttr>()) {
+    llvm::StringMap<bool> CalleeFeatureMap;
+    Ctx.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+
+    for (const auto &F : CalleeFeatureMap) {
+      if (F.getValue() &&
+          (!CallerFeatureMap.lookup(F.getKey()) ||
+           !CallerFeatureMap.find(F.getKey())->getValue()) &&
+          !IsHipStdPar) {
+        if (IsAlwaysInline)
+          Diags.Report(Loc, diag::err_function_needs_feature)
+              << Caller->getDeclName() << TargetDecl->getDeclName()
+              << F.getKey();
+        else if (IsFlatten)
+          Diags.Report(Loc, diag::err_flatten_function_needs_feature)
+              << Caller->getDeclName() << TargetDecl->getDeclName()
+              << F.getKey();
+      }
+    }
+  }
+}
+
 } // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/ModuleUtils.cpp b/clang/lib/CodeGenUtils/ModuleUtils.cpp
index 0d4882345e303..89655301400e6 100644
--- a/clang/lib/CodeGenUtils/ModuleUtils.cpp
+++ b/clang/lib/CodeGenUtils/ModuleUtils.cpp
@@ -12,6 +12,23 @@
 
 namespace clang::CodeGenUtils {
 
+bool hasUnwindExceptions(const LangOptions &LangOpts) {
+  // If exceptions are completely disabled, obviously this is false.
+  if (!LangOpts.Exceptions)
+    return false;
+
+  // If C++ exceptions are enabled, this is true.
+  if (LangOpts.CXXExceptions)
+    return true;
+
+  // If ObjC exceptions are enabled, this depends on the ABI.
+  if (LangOpts.ObjCExceptions) {
+    return LangOpts.ObjCRuntime.hasUnwindExceptions();
+  }
+
+  return true;
+}
+
 bool isVarDeclStrongDefinition(const ASTContext &Ctx, const VarDecl *D,
                                bool NoCommon) {
   // Don't give variables common linkage if -fno-common was specified unless it
diff --git a/clang/lib/CodeGenUtils/TargetUtils.cpp b/clang/lib/CodeGenUtils/TargetUtils.cpp
index f72218f4dda2d..86ebb29410d10 100644
--- a/clang/lib/CodeGenUtils/TargetUtils.cpp
+++ b/clang/lib/CodeGenUtils/TargetUtils.cpp
@@ -10,6 +10,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
 
 namespace clang::CodeGenUtils {
 
@@ -72,6 +73,10 @@ bool hasExtraNeonArgument(unsigned BuiltinID) {
   return mask != 0;
 }
 
+bool isAAPCS(const TargetInfo &TargetInfo) {
+  return TargetInfo.getABI().starts_with("aapcs");
+}
+
 bool requiresAMDGPUProtectedVisibility(const Decl *D,
                                        bool HasHiddenVisibility) {
   if (!HasHiddenVisibility)



More information about the llvm-branch-commits mailing list