reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
//===- RecordLayout.h - Layout information for a struct/union ---*- 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 file defines the RecordLayout interface.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H
#define LLVM_CLANG_AST_RECORDLAYOUT_H

#include "clang/AST/ASTVector.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include <cassert>
#include <cstdint>

namespace clang {

class ASTContext;
class CXXRecordDecl;

/// ASTRecordLayout -
/// This class contains layout information for one RecordDecl,
/// which is a struct/union/class.  The decl represented must be a definition,
/// not a forward declaration.
/// This class is also used to contain layout information for one
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
public:
  struct VBaseInfo {
    /// The offset to this virtual base in the complete-object layout
    /// of this class.
    CharUnits VBaseOffset;

  private:
    /// Whether this virtual base requires a vtordisp field in the
    /// Microsoft ABI.  These fields are required for certain operations
    /// in constructors and destructors.
    bool HasVtorDisp = false;

  public:
    VBaseInfo() = default;
    VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp)
        : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}

    bool hasVtorDisp() const { return HasVtorDisp; }
  };

  using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>;

private:
  friend class ASTContext;

  /// Size - Size of record in characters.
  CharUnits Size;

  /// DataSize - Size of record in characters without tail padding.
  CharUnits DataSize;

  // Alignment - Alignment of record in characters.
  CharUnits Alignment;

  // UnadjustedAlignment - Maximum of the alignments of the record members in
  // characters.
  CharUnits UnadjustedAlignment;

  /// RequiredAlignment - The required alignment of the object.  In the MS-ABI
  /// the __declspec(align()) trumps #pramga pack and must always be obeyed.
  CharUnits RequiredAlignment;

  /// FieldOffsets - Array of field offsets in bits.
  ASTVector<uint64_t> FieldOffsets;

  /// CXXRecordLayoutInfo - Contains C++ specific layout information.
  struct CXXRecordLayoutInfo {
    /// NonVirtualSize - The non-virtual size (in chars) of an object, which is
    /// the size of the object without virtual bases.
    CharUnits NonVirtualSize;

    /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object,
    /// which is the alignment of the object without virtual bases.
    CharUnits NonVirtualAlignment;

    /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
    /// (either a base or a member). Will be zero if the class doesn't contain
    /// any empty subobjects.
    CharUnits SizeOfLargestEmptySubobject;

    /// VBPtrOffset - Virtual base table offset (Microsoft-only).
    CharUnits VBPtrOffset;

    /// HasOwnVFPtr - Does this class provide a virtual function table
    /// (vtable in Itanium, vftbl in Microsoft) that is independent from
    /// its base classes?
    bool HasOwnVFPtr : 1;

    /// HasVFPtr - Does this class have a vftable that could be extended by
    /// a derived class.  The class may have inherited this pointer from
    /// a primary base class.
    bool HasExtendableVFPtr : 1;

    /// EndsWithZeroSizedObject - True if this class contains a zero sized
    /// member or base or a base with a zero sized member or base.
    /// Only used for MS-ABI.
    bool EndsWithZeroSizedObject : 1;

    /// True if this class is zero sized or first base is zero sized or
    /// has this property.  Only used for MS-ABI.
    bool LeadsWithZeroSizedBase : 1;

    /// PrimaryBase - The primary base info for this record.
    llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;

    /// BaseSharingVBPtr - The base we share vbptr with.
    const CXXRecordDecl *BaseSharingVBPtr;

    /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
    using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>;

    /// BaseOffsets - Contains a map from base classes to their offset.
    BaseOffsetsMapTy BaseOffsets;

    /// VBaseOffsets - Contains a map from vbase classes to their offset.
    VBaseOffsetsMapTy VBaseOffsets;
  };

  /// CXXInfo - If the record layout is for a C++ record, this will have
  /// C++ specific information about the record.
  CXXRecordLayoutInfo *CXXInfo = nullptr;

  ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
                  CharUnits unadjustedAlignment,
                  CharUnits requiredAlignment, CharUnits datasize,
                  ArrayRef<uint64_t> fieldoffsets);

  using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;

  // Constructor for C++ records.
  ASTRecordLayout(const ASTContext &Ctx,
                  CharUnits size, CharUnits alignment,
                  CharUnits unadjustedAlignment,
                  CharUnits requiredAlignment,
                  bool hasOwnVFPtr, bool hasExtendableVFPtr,
                  CharUnits vbptroffset,
                  CharUnits datasize,
                  ArrayRef<uint64_t> fieldoffsets,
                  CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
                  CharUnits SizeOfLargestEmptySubobject,
                  const CXXRecordDecl *PrimaryBase,
                  bool IsPrimaryBaseVirtual,
                  const CXXRecordDecl *BaseSharingVBPtr,
                  bool EndsWithZeroSizedObject,
                  bool LeadsWithZeroSizedBase,
                  const BaseOffsetsMapTy& BaseOffsets,
                  const VBaseOffsetsMapTy& VBaseOffsets);

  ~ASTRecordLayout() = default;

  void Destroy(ASTContext &Ctx);

public:
  ASTRecordLayout(const ASTRecordLayout &) = delete;
  ASTRecordLayout &operator=(const ASTRecordLayout &) = delete;

  /// getAlignment - Get the record alignment in characters.
  CharUnits getAlignment() const { return Alignment; }

  /// getUnadjustedAlignment - Get the record alignment in characters, before
  /// alignment adjustement.
  CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }

  /// getSize - Get the record size in characters.
  CharUnits getSize() const { return Size; }

  /// getFieldCount - Get the number of fields in the layout.
  unsigned getFieldCount() const { return FieldOffsets.size(); }

  /// getFieldOffset - Get the offset of the given field index, in
  /// bits.
  uint64_t getFieldOffset(unsigned FieldNo) const {
    return FieldOffsets[FieldNo];
  }

  /// getDataSize() - Get the record data size, which is the record size
  /// without tail padding, in characters.
  CharUnits getDataSize() const {
    return DataSize;
  }

  /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
  /// which is the size of the object without virtual bases.
  CharUnits getNonVirtualSize() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");

    return CXXInfo->NonVirtualSize;
  }

  /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
  /// which is the alignment of the object without virtual bases.
  CharUnits getNonVirtualAlignment() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");

    return CXXInfo->NonVirtualAlignment;
  }

  /// getPrimaryBase - Get the primary base for this record.
  const CXXRecordDecl *getPrimaryBase() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");

    return CXXInfo->PrimaryBase.getPointer();
  }

  /// isPrimaryBaseVirtual - Get whether the primary base for this record
  /// is virtual or not.
  bool isPrimaryBaseVirtual() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");

    return CXXInfo->PrimaryBase.getInt();
  }

  /// getBaseClassOffset - Get the offset, in chars, for the given base class.
  CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");

    return CXXInfo->BaseOffsets[Base];
  }

  /// getVBaseClassOffset - Get the offset, in chars, for the given base class.
  CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");

    return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
  }

  CharUnits getSizeOfLargestEmptySubobject() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->SizeOfLargestEmptySubobject;
  }

  /// hasOwnVFPtr - Does this class provide its own virtual-function
  /// table pointer, rather than inheriting one from a primary base
  /// class?  If so, it is at offset zero.
  ///
  /// This implies that the ABI has no primary base class, meaning
  /// that it has no base classes that are suitable under the conditions
  /// of the ABI.
  bool hasOwnVFPtr() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->HasOwnVFPtr;
  }

  /// hasVFPtr - Does this class have a virtual function table pointer
  /// that can be extended by a derived class?  This is synonymous with
  /// this class having a VFPtr at offset zero.
  bool hasExtendableVFPtr() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->HasExtendableVFPtr;
  }

  /// hasOwnVBPtr - Does this class provide its own virtual-base
  /// table pointer, rather than inheriting one from a primary base
  /// class?
  ///
  /// This implies that the ABI has no primary base class, meaning
  /// that it has no base classes that are suitable under the conditions
  /// of the ABI.
  bool hasOwnVBPtr() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return hasVBPtr() && !CXXInfo->BaseSharingVBPtr;
  }

  /// hasVBPtr - Does this class have a virtual function table pointer.
  bool hasVBPtr() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return !CXXInfo->VBPtrOffset.isNegative();
  }

  CharUnits getRequiredAlignment() const {
    return RequiredAlignment;
  }

  bool endsWithZeroSizedObject() const {
    return CXXInfo && CXXInfo->EndsWithZeroSizedObject;
  }

  bool leadsWithZeroSizedBase() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->LeadsWithZeroSizedBase;
  }

  /// getVBPtrOffset - Get the offset for virtual base table pointer.
  /// This is only meaningful with the Microsoft ABI.
  CharUnits getVBPtrOffset() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->VBPtrOffset;
  }

  const CXXRecordDecl *getBaseSharingVBPtr() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->BaseSharingVBPtr;
  }

  const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
    assert(CXXInfo && "Record layout does not have C++ specific info!");
    return CXXInfo->VBaseOffsets;
  }
};

} // namespace clang

#endif // LLVM_CLANG_AST_RECORDLAYOUT_H