24#include "llvm/Support/Casting.h"
37struct CIRRecordLowering final {
42 struct MemberInfo final {
44 enum class InfoKind { VFPtr,
Field,
Base, VBase } kind;
50 MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
53 MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
54 const CXXRecordDecl *rd)
55 : offset{offset}, kind{kind}, data{data},
cxxRecordDecl{rd} {}
57 bool operator<(
const MemberInfo &other)
const {
58 return offset < other.offset;
62 CIRRecordLowering(CIRGenTypes &cirGenTypes,
const RecordDecl *recordDecl,
66 MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) {
67 return MemberInfo(offset, MemberInfo::InfoKind::Field, data);
71 void setBitFieldInfo(
const FieldDecl *fd, CharUnits startOffset,
72 mlir::Type storageType);
74 void lower(
bool NonVirtualBaseType);
78 void determinePacked(
bool nvBaseType);
82 void computeVolatileBitfields();
83 void accumulateBases();
84 void accumulateVPtrs();
85 void accumulateVBases();
86 void accumulateFields();
91 mlir::Type getVFPtrType();
94 return astContext.getTargetInfo().getABI().starts_with(
"aapcs");
98 bool isBigEndian()
const {
return astContext.getTargetInfo().isBigEndian(); }
104 bool isOverlappingVBaseABI() {
105 return !astContext.getTargetInfo().getCXXABI().isMicrosoft();
109 bool hasOwnStorage(
const CXXRecordDecl *
decl,
const CXXRecordDecl *query);
116 bool isDiscreteBitFieldABI() {
117 return astContext.getTargetInfo().getCXXABI().isMicrosoft() ||
118 recordDecl->isMsStruct(astContext);
121 CharUnits bitsToCharUnits(uint64_t bitOffset) {
122 return astContext.toCharUnitsFromBits(bitOffset);
125 void calculateZeroInit();
127 CharUnits getSize(mlir::Type Ty) {
130 CharUnits getSizeInBits(mlir::Type ty) {
133 CharUnits getAlignment(mlir::Type Ty) {
137 bool isZeroInitializable(
const FieldDecl *fd) {
138 return cirGenTypes.isZeroInitializable(fd->
getType());
140 bool isZeroInitializable(
const RecordDecl *rd) {
141 return cirGenTypes.isZeroInitializable(rd);
145 mlir::Type getUIntNType(uint64_t numBits) {
146 unsigned alignedBits = llvm::PowerOf2Ceil(numBits);
147 alignedBits = std::max(8u, alignedBits);
148 return cir::IntType::get(&cirGenTypes.getMLIRContext(), alignedBits,
152 mlir::Type getCharType() {
153 return cir::IntType::get(&cirGenTypes.getMLIRContext(),
154 astContext.getCharWidth(),
158 mlir::Type getByteArrayType(CharUnits numberOfChars) {
159 assert(!numberOfChars.
isZero() &&
"Empty byte arrays aren't allowed.");
160 mlir::Type
type = getCharType();
167 mlir::Type getStorageType(
const CXXRecordDecl *RD) {
168 return cirGenTypes.getCIRGenRecordLayout(RD).getBaseSubobjectCIRType();
173 mlir::Type getBitfieldStorageType(
unsigned numBits) {
174 unsigned alignedBits = llvm::alignTo(numBits, astContext.getCharWidth());
176 return builder.getUIntNTy(alignedBits);
178 mlir::Type
type = getCharType();
179 return cir::ArrayType::get(
type, alignedBits / astContext.getCharWidth());
182 mlir::Type getStorageType(
const FieldDecl *
fieldDecl) {
183 mlir::Type
type = cirGenTypes.convertTypeForMem(
fieldDecl->getType());
185 cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
186 "getStorageType for bitfields");
192 return astRecordLayout.getFieldOffset(
fieldDecl->getFieldIndex());
196 void fillOutputFields();
198 void appendPaddingBytes(CharUnits size) {
200 fieldTypes.push_back(getByteArrayType(size));
205 CIRGenTypes &cirGenTypes;
206 CIRGenBuilderTy &builder;
207 const ASTContext &astContext;
208 const RecordDecl *recordDecl;
209 const CXXRecordDecl *cxxRecordDecl;
210 const ASTRecordLayout &astRecordLayout;
212 std::vector<MemberInfo> members;
214 llvm::SmallVector<mlir::Type, 16> fieldTypes;
215 llvm::DenseMap<const FieldDecl *, CIRGenBitFieldInfo> bitFields;
216 llvm::DenseMap<const FieldDecl *, unsigned> fieldIdxMap;
217 llvm::DenseMap<const CXXRecordDecl *, unsigned> nonVirtualBases;
218 llvm::DenseMap<const CXXRecordDecl *, unsigned> virtualBases;
219 cir::CIRDataLayout dataLayout;
221 LLVM_PREFERRED_TYPE(
bool)
222 unsigned zeroInitializable : 1;
223 LLVM_PREFERRED_TYPE(
bool)
224 unsigned zeroInitializableAsBase : 1;
225 LLVM_PREFERRED_TYPE(
bool)
227 LLVM_PREFERRED_TYPE(
bool)
231 CIRRecordLowering(
const CIRRecordLowering &) =
delete;
232 void operator=(
const CIRRecordLowering &) =
delete;
236CIRRecordLowering::CIRRecordLowering(
CIRGenTypes &cirGenTypes,
238 : cirGenTypes{cirGenTypes}, builder{cirGenTypes.getBuilder()},
242 cirGenTypes.getASTContext().getASTRecordLayout(
recordDecl)},
243 dataLayout{cirGenTypes.getCGModule().getModule()},
244 zeroInitializable{
true}, zeroInitializableAsBase{
true}, packed{packed},
247void CIRRecordLowering::setBitFieldInfo(
const FieldDecl *fd,
249 mlir::Type storageType) {
253 (unsigned)(getFieldBitOffset(fd) - astContext.
toBits(startOffset));
255 info.
storageSize = getSizeInBits(storageType).getQuantity();
274void CIRRecordLowering::lower(
bool nonVirtualBaseType) {
277 computeVolatileBitfields();
289 if (members.empty()) {
290 appendPaddingBytes(size);
291 computeVolatileBitfields();
294 if (!nonVirtualBaseType)
298 llvm::stable_sort(members);
303 members.push_back(makeStorageInfo(size, getUIntNType(8)));
304 determinePacked(nonVirtualBaseType);
310 computeVolatileBitfields();
313void CIRRecordLowering::fillOutputFields() {
314 for (
const MemberInfo &member : members) {
316 fieldTypes.push_back(
member.data);
317 if (
member.kind == MemberInfo::InfoKind::Field) {
319 fieldIdxMap[
member.fieldDecl->getCanonicalDecl()] =
320 fieldTypes.size() - 1;
324 setBitFieldInfo(
member.fieldDecl,
member.offset, fieldTypes.back());
325 }
else if (
member.kind == MemberInfo::InfoKind::Base) {
326 nonVirtualBases[
member.cxxRecordDecl] = fieldTypes.size() - 1;
327 }
else if (
member.kind == MemberInfo::InfoKind::VBase) {
328 virtualBases[
member.cxxRecordDecl] = fieldTypes.size() - 1;
336 if (isDiscreteBitFieldABI()) {
347 for (; field != fieldEnd && field->isBitField(); ++field) {
349 if (field->isZeroLengthBitField()) {
353 uint64_t bitOffset = getFieldBitOffset(*field);
357 if (run == fieldEnd || bitOffset >= tail) {
359 startBitOffset = bitOffset;
365 makeStorageInfo(bitsToCharUnits(startBitOffset),
type));
369 members.push_back(MemberInfo(bitsToCharUnits(startBitOffset),
370 MemberInfo::InfoKind::Field,
nullptr,
387 CharUnits beginOffset;
396 CharUnits bestEndOffset;
404 bool atAlignedBoundary =
false;
406 if (field != fieldEnd && field->isBitField()) {
407 uint64_t bitOffset = getFieldBitOffset(*field);
408 if (begin == fieldEnd) {
413 assert((bitOffset % charBits) == 0 &&
"Not at start of char");
414 beginOffset = bitsToCharUnits(bitOffset);
415 bitSizeSinceBegin = 0;
416 }
else if ((bitOffset % charBits) != 0) {
424 astContext.
toBits(beginOffset) + bitSizeSinceBegin &&
425 "Concatenating non-contiguous bitfields");
430 if (field->isZeroLengthBitField())
432 atAlignedBoundary =
true;
437 if (begin == fieldEnd)
441 atAlignedBoundary =
true;
447 bool installBest =
false;
448 if (atAlignedBoundary) {
454 CharUnits accessSize = bitsToCharUnits(bitSizeSinceBegin + charBits - 1);
455 if (bestEnd == begin) {
459 bestEndOffset = beginOffset + accessSize;
462 if (!bitSizeSinceBegin)
466 }
else if (accessSize > regSize) {
475 mlir::Type
type = getUIntNType(astContext.
toBits(accessSize));
478 field->getSourceRange(),
"NYI CheapUnalignedBitFieldAccess");
485 CharUnits limitOffset;
486 for (
auto probe = field; probe != fieldEnd; ++probe)
489 assert((getFieldBitOffset(*probe) % charBits) == 0 &&
490 "Next storage is not byte-aligned");
491 limitOffset = bitsToCharUnits(getFieldBitOffset(*probe));
498 CharUnits typeSize = getSize(
type);
499 if (beginOffset + typeSize <= limitOffset) {
502 bestEndOffset = beginOffset + typeSize;
511 .FineGrainedBitfieldAccesses) {
517 bitSizeSinceBegin = astContext.
toBits(limitOffset - beginOffset);
524 assert((field == fieldEnd || !field->isBitField() ||
525 (getFieldBitOffset(*field) % charBits) == 0) &&
526 "Installing but not at an aligned bitfield or limit");
527 CharUnits accessSize = bestEndOffset - beginOffset;
528 if (!accessSize.
isZero()) {
534 assert(getSize(getUIntNType(astContext.
toBits(accessSize))) >
536 "Clipped access need not be clipped");
537 type = getByteArrayType(accessSize);
539 type = getUIntNType(astContext.
toBits(accessSize));
540 assert(getSize(
type) == accessSize &&
541 "Unclipped access must be clipped");
543 members.push_back(makeStorageInfo(beginOffset,
type));
544 for (; begin != bestEnd; ++begin)
545 if (!begin->isZeroLengthBitField())
546 members.push_back(MemberInfo(
547 beginOffset, MemberInfo::InfoKind::Field,
nullptr, *begin));
553 assert(field != fieldEnd && field->isBitField() &&
554 "Accumulating past end of bitfields");
555 assert(!
barrier &&
"Accumulating across barrier");
557 bitSizeSinceBegin += field->getBitWidthValue();
565void CIRRecordLowering::accumulateFields() {
568 field != fieldEnd;) {
569 if (field->isBitField()) {
570 field = accumulateBitFields(field, fieldEnd);
571 assert((field == fieldEnd || !field->isBitField()) &&
572 "Failed to accumulate all the bitfields");
573 }
else if (!field->isZeroSize(astContext)) {
574 members.push_back(MemberInfo(bitsToCharUnits(getFieldBitOffset(*field)),
575 MemberInfo::InfoKind::Field,
576 getStorageType(*field), *field));
586void CIRRecordLowering::calculateZeroInit() {
587 for (
const MemberInfo &member : members) {
588 if (
member.kind == MemberInfo::InfoKind::Field) {
589 if (!
member.fieldDecl || isZeroInitializable(
member.fieldDecl))
591 zeroInitializable = zeroInitializableAsBase =
false;
593 }
else if (
member.kind == MemberInfo::InfoKind::Base ||
594 member.kind == MemberInfo::InfoKind::VBase) {
595 if (isZeroInitializable(
member.cxxRecordDecl))
597 zeroInitializable =
false;
598 if (
member.kind == MemberInfo::InfoKind::Base)
599 zeroInitializableAsBase =
false;
604void CIRRecordLowering::determinePacked(
bool nvBaseType) {
613 for (
const MemberInfo &member : members) {
620 if (
member.offset < nvSize)
621 nvAlignment = std::max(nvAlignment, getAlignment(
member.data));
622 alignment = std::max(alignment, getAlignment(
member.data));
626 if (members.back().offset % alignment)
631 if (nvSize % nvAlignment)
635 members.back().data = getUIntNType(astContext.
toBits(alignment));
638void CIRRecordLowering::insertPadding() {
639 std::vector<std::pair<CharUnits, CharUnits>> padding;
641 for (
const MemberInfo &member : members) {
644 CharUnits offset =
member.offset;
645 assert(offset >= size);
649 padding.push_back(std::make_pair(size, offset - size));
650 size = offset + getSize(
member.data);
656 for (
const std::pair<CharUnits, CharUnits> &paddingPair : padding)
657 members.push_back(makeStorageInfo(paddingPair.first,
658 getByteArrayType(paddingPair.second)));
659 llvm::stable_sort(members);
662std::unique_ptr<CIRGenRecordLayout>
664 CIRRecordLowering lowering(*
this, rd,
false);
665 assert(ty->isIncomplete() &&
"recomputing record layout?");
666 lowering.lower(
false);
669 cir::RecordType baseTy;
670 if (llvm::isa<CXXRecordDecl>(rd) && !rd->
isUnion() &&
674 lowering.astRecordLayout.
getSize()) {
675 CIRRecordLowering baseLowering(*
this, rd, lowering.packed);
676 baseLowering.lower(
true);
678 baseTy = builder.getCompleteNamedRecordType(
679 baseLowering.fieldTypes, baseLowering.packed, baseLowering.padded,
685 assert(lowering.packed == baseLowering.packed &&
686 "Non-virtual and complete types must agree on packedness");
694 ty->complete(lowering.fieldTypes, lowering.packed, lowering.padded);
696 auto rl = std::make_unique<CIRGenRecordLayout>(
697 ty ? *ty : cir::RecordType{}, baseTy ? baseTy : cir::RecordType{},
698 (bool)lowering.zeroInitializable, (bool)lowering.zeroInitializableAsBase);
702 rl->nonVirtualBases.swap(lowering.nonVirtualBases);
703 rl->completeObjectVirtualBases.swap(lowering.virtualBases);
708 rl->fieldIdxMap.swap(lowering.fieldIdxMap);
710 rl->bitFields.swap(lowering.bitFields);
714 llvm::outs() <<
"\n*** Dumping CIRgen Record Layout\n";
715 llvm::outs() <<
"Record: ";
716 rd->
dump(llvm::outs());
717 llvm::outs() <<
"\nLayout: ";
718 rl->print(llvm::outs());
726 os <<
"<CIRecordLayout\n";
727 os <<
" CIR Type:" << completeObjectType <<
"\n";
728 if (baseSubobjectType)
729 os <<
" NonVirtualBaseCIRType:" << baseSubobjectType <<
"\n";
730 os <<
" IsZeroInitializable:" << zeroInitializable <<
"\n";
731 os <<
" BitFields:[\n";
732 std::vector<std::pair<unsigned, const CIRGenBitFieldInfo *>> bitInfo;
733 for (
auto &[
decl, info] : bitFields) {
738 bitInfo.push_back(std::make_pair(
index, &info));
740 llvm::array_pod_sort(bitInfo.begin(), bitInfo.end());
741 for (std::pair<unsigned, const CIRGenBitFieldInfo *> &info : bitInfo) {
743 info.second->
print(os);
750 os <<
"<CIRBitFieldInfo" <<
" name:" <<
name <<
" offset:" <<
offset
763void CIRRecordLowering::lowerUnion() {
765 mlir::Type storageType =
nullptr;
766 bool seenNamedMember =
false;
771 mlir::Type fieldType;
772 if (field->isBitField()) {
773 if (field->isZeroLengthBitField())
775 fieldType = getBitfieldStorageType(field->getBitWidthValue());
778 fieldType = getStorageType(field);
782 fieldIdxMap[field->getCanonicalDecl()] = 0;
790 if (!seenNamedMember) {
791 seenNamedMember = field->getIdentifier();
792 if (!seenNamedMember)
793 if (
const RecordDecl *fieldRD = field->getType()->getAsRecordDecl())
794 seenNamedMember = fieldRD->findFirstNamedDataMember();
795 if (seenNamedMember && !isZeroInitializable(field)) {
796 zeroInitializable = zeroInitializableAsBase =
false;
797 storageType = fieldType;
803 if (!zeroInitializable)
807 if (!storageType || getAlignment(fieldType) > getAlignment(storageType) ||
808 (getAlignment(fieldType) == getAlignment(storageType) &&
809 getSize(fieldType) > getSize(storageType)))
810 storageType = fieldType;
814 fieldTypes.push_back(fieldType);
819 "No-storage Union NYI");
821 if (layoutSize < getSize(storageType))
822 storageType = getByteArrayType(layoutSize);
824 appendPaddingBytes(layoutSize - getSize(storageType));
827 if (layoutSize % getAlignment(storageType))
831bool CIRRecordLowering::hasOwnStorage(
const CXXRecordDecl *
decl,
832 const CXXRecordDecl *query) {
836 for (
const auto &base :
decl->bases())
837 if (!hasOwnStorage(base.getType()->getAsCXXRecordDecl(), query))
855void CIRRecordLowering::computeVolatileBitfields() {
860 for (
auto &[field, info] : bitFields) {
864 getSizeInBits(resLTy).getQuantity())
872 const unsigned oldOffset =
876 const unsigned absoluteOffset =
880 const unsigned storageSize = getSizeInBits(resLTy).getQuantity();
883 if (info.
storageSize == storageSize && (oldOffset % storageSize == 0))
887 unsigned offset = absoluteOffset & (storageSize - 1);
892 if (offset + info.
size > storageSize)
897 offset = storageSize - (offset + info.
size);
899 const CharUnits storageOffset =
901 const CharUnits end = storageOffset +
905 const ASTRecordLayout &layout =
908 const CharUnits recordSize = layout.
getSize();
909 if (end >= recordSize)
913 bool conflict =
false;
916 if (f->isBitField() && !f->isZeroLengthBitField())
926 if (f->isZeroLengthBitField()) {
927 if (end > fOffset && storageOffset < fOffset) {
933 const CharUnits fEnd =
940 if (end < fOffset || fEnd < storageOffset)
961void CIRRecordLowering::accumulateBases() {
965 members.push_back(MemberInfo(
CharUnits::Zero(), MemberInfo::InfoKind::Base,
966 getStorageType(baseDecl), baseDecl));
971 if (base.isVirtual())
975 const CXXRecordDecl *baseDecl = base.getType()->getAsCXXRecordDecl();
979 MemberInfo::InfoKind::Base,
980 getStorageType(baseDecl), baseDecl));
985void CIRRecordLowering::accumulateVBases() {
987 const CXXRecordDecl *baseDecl = base.getType()->getAsCXXRecordDecl();
993 if (isOverlappingVBaseABI() && astContext.
isNearlyEmpty(baseDecl) &&
996 MemberInfo(offset, MemberInfo::InfoKind::VBase,
nullptr, baseDecl));
1002 ->second.hasVtorDisp())
1005 members.push_back(MemberInfo(offset, MemberInfo::InfoKind::VBase,
1006 getStorageType(baseDecl), baseDecl));
1010void CIRRecordLowering::accumulateVPtrs() {
1012 members.push_back(MemberInfo(
CharUnits::Zero(), MemberInfo::InfoKind::VFPtr,
1017 "accumulateVPtrs: hasOwnVBPtr");
1020mlir::Type CIRRecordLowering::getVFPtrType() {
1021 return cir::VPtrType::get(builder.getContext());
Defines the clang::ASTContext interface.
static bool isAAPCS(const TargetInfo &targetInfo)
Helper method to check if the underlying ABI is AAPCS.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
llvm::TypeSize getTypeAllocSizeInBits(mlir::Type ty) const
Returns the offset in bits between successive objects of the specified type, including alignment padd...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
bool isNearlyEmpty(const CXXRecordDecl *RD) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding,...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
const clang::CodeGenOptions & getCodeGenOpts() const
LLVM_DUMP_METHOD void dump() const
void print(raw_ostream &os) const
This class organizes the cross-module state that is used while lowering AST types to CIR types.
CIRGenModule & getCGModule() const
std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)
clang::ASTContext & getASTContext() const
std::unique_ptr< CIRGenRecordLayout > computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty)
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
Represents a C++ struct/union/class.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Represents a member of a struct/union/class.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents a struct/union/class.
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
virtual unsigned getRegisterWidth() const
Return the "preferred" register width on this target.
bool hasCheapUnalignedBitFieldAccess() const
Return true iff unaligned accesses are cheap.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isValidFundamentalIntWidth(unsigned width)
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
bool isEmptyRecordForLayout(const ASTContext &context, QualType t)
isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl
Matches class, struct, and union declarations.
The JSON file list parser is used to communicate input to InstallAPI.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Diagnostic wrappers for TextAPI types for error reporting.
void __ovld __conv barrier(cl_mem_fence_flags)
All work-items in a work-group executing the kernel on a processor must execute this function before ...
static bool zeroSizeRecordMembers()
static bool astRecordDeclAttr()
static bool recordZeroInit()
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
void print(llvm::raw_ostream &os) const
LLVM_DUMP_METHOD void dump() const
unsigned storageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned volatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
clang::CharUnits storageOffset
The offset of the bitfield storage from the start of the record.
unsigned size
The total size of the bit-field, in bits.
unsigned isSigned
Whether the bit-field is signed.
clang::CharUnits volatileStorageOffset
The offset of the bitfield storage from the start of the record.
unsigned volatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
llvm::StringRef name
The name of a bitfield.