llvm/clang/lib/CodeGen/CGClass.cpp

//===--- CGClass.cpp - Emit LLVM Code for C++ classes -----------*- 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
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of classes
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "TargetInfo.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
#include <optional>

usingnamespaceclang;
usingnamespaceCodeGen;

/// Return the best known alignment for an unknown pointer to a
/// particular class.
CharUnits CodeGenModule::getClassPointerAlignment(const CXXRecordDecl *RD) {}

/// Return the smallest possible amount of storage that might be allocated
/// starting from the beginning of an object of a particular class.
///
/// This may be smaller than sizeof(RD) if RD has virtual base classes.
CharUnits CodeGenModule::getMinimumClassObjectSize(const CXXRecordDecl *RD) {}

/// Return the best known alignment for a pointer to a virtual base,
/// given the alignment of a pointer to the derived class.
CharUnits CodeGenModule::getVBaseAlignment(CharUnits actualDerivedAlign,
                                           const CXXRecordDecl *derivedClass,
                                           const CXXRecordDecl *vbaseClass) {}

CharUnits
CodeGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign,
                                         const CXXRecordDecl *baseDecl,
                                         CharUnits expectedTargetAlign) {}

Address CodeGenFunction::LoadCXXThisAddress() {}

/// Emit the address of a field using a member data pointer.
///
/// \param E Only used for emergency diagnostics
Address
CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
                                                 llvm::Value *memberPtr,
                                      const MemberPointerType *memberPtrType,
                                                 LValueBaseInfo *BaseInfo,
                                                 TBAAAccessInfo *TBAAInfo) {}

CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
    const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start,
    CastExpr::path_const_iterator End) {}

llvm::Constant *
CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
                                   CastExpr::path_const_iterator PathBegin,
                                   CastExpr::path_const_iterator PathEnd) {}

/// Gets the address of a direct base class within a complete object.
/// This should only be used for (1) non-virtual bases or (2) virtual bases
/// when the type is known to be complete (e.g. in complete destructors).
///
/// The object pointed to by 'This' is assumed to be non-null.
Address
CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This,
                                                   const CXXRecordDecl *Derived,
                                                   const CXXRecordDecl *Base,
                                                   bool BaseIsVirtual) {}

static Address
ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr,
                                CharUnits nonVirtualOffset,
                                llvm::Value *virtualOffset,
                                const CXXRecordDecl *derivedClass,
                                const CXXRecordDecl *nearestVBase) {}

Address CodeGenFunction::GetAddressOfBaseClass(
    Address Value, const CXXRecordDecl *Derived,
    CastExpr::path_const_iterator PathBegin,
    CastExpr::path_const_iterator PathEnd, bool NullCheckValue,
    SourceLocation Loc) {}

Address
CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
                                          const CXXRecordDecl *Derived,
                                        CastExpr::path_const_iterator PathBegin,
                                          CastExpr::path_const_iterator PathEnd,
                                          bool NullCheckValue) {}

llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
                                              bool ForVirtualBase,
                                              bool Delegating) {}

namespace {
  /// Call the destructor for a direct base class.
  struct CallBaseDtor final : EHScopeStack::Cleanup {};

  /// A visitor which checks whether an initializer uses 'this' in a
  /// way which requires the vtable to be properly set.
  struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {};
} // end anonymous namespace

static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {}

static void EmitBaseInitializer(CodeGenFunction &CGF,
                                const CXXRecordDecl *ClassDecl,
                                CXXCtorInitializer *BaseInit) {}

static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) {}

static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF,
                                                CXXCtorInitializer *MemberInit,
                                                LValue &LHS) {}

static void EmitMemberInitializer(CodeGenFunction &CGF,
                                  const CXXRecordDecl *ClassDecl,
                                  CXXCtorInitializer *MemberInit,
                                  const CXXConstructorDecl *Constructor,
                                  FunctionArgList &Args) {}

void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
                                              Expr *Init) {}

/// Checks whether the given constructor is a valid subject for the
/// complete-to-base constructor delegation optimization, i.e.
/// emitting the complete constructor as a simple call to the base
/// constructor.
bool CodeGenFunction::IsConstructorDelegationValid(
    const CXXConstructorDecl *Ctor) {}

// Emit code in ctor (Prologue==true) or dtor (Prologue==false)
// to poison the extra field paddings inserted under
// -fsanitize-address-field-padding=1|2.
void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) {}

/// EmitConstructorBody - Emits the body of the current constructor.
void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {}

namespace {
  /// RAII object to indicate that codegen is copying the value representation
  /// instead of the object representation. Useful when copying a struct or
  /// class which has uninitialized members and we're only performing
  /// lvalue-to-rvalue conversion on the object but not its members.
  class CopyingValueRepresentation {};
} // end anonymous namespace

namespace {
  class FieldMemcpyizer {};

  class ConstructorMemcpyizer : public FieldMemcpyizer {};

  class AssignmentMemcpyizer : public FieldMemcpyizer {};
} // end anonymous namespace

static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {}

/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
                                       CXXCtorType CtorType,
                                       FunctionArgList &Args) {}

static bool
FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);

static bool
HasTrivialDestructorBody(ASTContext &Context,
                         const CXXRecordDecl *BaseClassDecl,
                         const CXXRecordDecl *MostDerivedClassDecl)
{}

static bool
FieldHasTrivialDestructorBody(ASTContext &Context,
                                          const FieldDecl *Field)
{}

/// CanSkipVTablePointerInitialization - Check whether we need to initialize
/// any vtable pointers before calling this destructor.
static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
                                               const CXXDestructorDecl *Dtor) {}

/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {}

void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) {}

namespace {
  llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
                                     const CXXDestructorDecl *DD) {}

  /// Call the operator delete associated with the current destructor.
  struct CallDtorDelete final : EHScopeStack::Cleanup {};

  void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,
                                     llvm::Value *ShouldDeleteCondition,
                                     bool ReturnAfterDelete) {}

  struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {};

  class DestroyField  final : public EHScopeStack::Cleanup {};

  class DeclAsInlineDebugLocation {};

  static void EmitSanitizerDtorCallback(
      CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
      std::optional<CharUnits::QuantityType> PoisonSize = {}

  static void
  EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
                                  CharUnits::QuantityType PoisonSize) {}

  /// Poison base class with a trivial destructor.
  struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {};

  class SanitizeDtorFieldRange final : public EHScopeStack::Cleanup {};

 class SanitizeDtorVTable final : public EHScopeStack::Cleanup {};

 class SanitizeDtorCleanupBuilder {};
} // end anonymous namespace

/// Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes
/// in reverse order of their construction.
///
/// For a deleting destructor, this also handles the case where a destroying
/// operator delete completely overrides the definition.
void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
                                        CXXDtorType DtorType) {}

/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
/// constructor for each of several members of an array.
///
/// \param ctor the constructor to call for each element
/// \param arrayType the type of the array to initialize
/// \param arrayBegin an arrayType*
/// \param zeroInitialize true if each element should be
///   zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(
    const CXXConstructorDecl *ctor, const ArrayType *arrayType,
    Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked,
    bool zeroInitialize) {}

/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
/// constructor for each of several members of an array.
///
/// \param ctor the constructor to call for each element
/// \param numElements the number of elements in the array;
///   may be zero
/// \param arrayBase a T*, where T is the type constructed by ctor
/// \param zeroInitialize true if each element should be
///   zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
                                                 llvm::Value *numElements,
                                                 Address arrayBase,
                                                 const CXXConstructExpr *E,
                                                 bool NewPointerIsChecked,
                                                 bool zeroInitialize) {}

void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
                                       Address addr,
                                       QualType type) {}

void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
                                             CXXCtorType Type,
                                             bool ForVirtualBase,
                                             bool Delegating,
                                             AggValueSlot ThisAVS,
                                             const CXXConstructExpr *E) {}

static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
                                    const CXXConstructorDecl *Ctor,
                                    CXXCtorType Type, CallArgList &Args) {}

void CodeGenFunction::EmitCXXConstructorCall(
    const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase,
    bool Delegating, Address This, CallArgList &Args,
    AggValueSlot::Overlap_t Overlap, SourceLocation Loc,
    bool NewPointerIsChecked, llvm::CallBase **CallOrInvoke) {}

void CodeGenFunction::EmitInheritedCXXConstructorCall(
    const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
    bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {}

void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
    const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase,
    bool Delegating, CallArgList &Args) {}

void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) {}

void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl,
                                                Address This) {}

void
CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
                                                Address This, Address Src,
                                                const CXXConstructExpr *E) {}

void
CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
                                                CXXCtorType CtorType,
                                                const FunctionArgList &Args,
                                                SourceLocation Loc) {}

namespace {
  struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {};
} // end anonymous namespace

void
CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
                                                  const FunctionArgList &Args) {}

void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
                                            CXXDtorType Type,
                                            bool ForVirtualBase,
                                            bool Delegating, Address This,
                                            QualType ThisTy) {}

namespace {
  struct CallLocalDtor final : EHScopeStack::Cleanup {};
} // end anonymous namespace

void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
                                            QualType T, Address Addr) {}

void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {}

void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {}

CodeGenFunction::VPtrsVector
CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) {}

void CodeGenFunction::getVTablePointers(BaseSubobject Base,
                                        const CXXRecordDecl *NearestVBase,
                                        CharUnits OffsetFromNearestVBase,
                                        bool BaseIsNonVirtualPrimaryBase,
                                        const CXXRecordDecl *VTableClass,
                                        VisitedVirtualBasesSetTy &VBases,
                                        VPtrsVector &Vptrs) {}

void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {}

llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
                                           llvm::Type *VTableTy,
                                           const CXXRecordDecl *RD,
                                           VTableAuthMode AuthMode) {}

// If a class has a single non-virtual base and does not introduce or override
// virtual member functions or fields, it will have the same layout as its base.
// This function returns the least derived such class.
//
// Casting an instance of a base class to such a derived class is technically
// undefined behavior, but it is a relatively common hack for introducing member
// functions on class instances with specific properties (e.g. llvm::Operator)
// that works under most compilers and should not have security implications, so
// we allow it by default. It can be disabled with -fsanitize=cfi-cast-strict.
static const CXXRecordDecl *
LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {}

void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
                                                   llvm::Value *VTable,
                                                   SourceLocation Loc) {}

void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
                                                llvm::Value *VTable,
                                                CFITypeCheckKind TCK,
                                                SourceLocation Loc) {}

void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,
                                                bool MayBeNull,
                                                CFITypeCheckKind TCK,
                                                SourceLocation Loc) {}

void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
                                         llvm::Value *VTable,
                                         CFITypeCheckKind TCK,
                                         SourceLocation Loc) {}

bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {}

llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
    const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
    uint64_t VTableByteOffset) {}

void CodeGenFunction::EmitForwardingCallToLambda(
    const CXXMethodDecl *callOperator, CallArgList &callArgs,
    const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) {}

void CodeGenFunction::EmitLambdaBlockInvokeBody() {}

void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {}

void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD,
                                                     CallArgList &CallArgs) {}

void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) {}

void CodeGenFunction::EmitLambdaInAllocaImplFn(
    const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo,
    llvm::Function **ImplFn) {}