[DebugInfo] Support for DW_AT_associated and DW_AT_allocated.

Summary:
This support is needed for the Fortran array variables with pointer/allocatable
attribute. This support enables debugger to identify the status of variable
whether that is currently allocated/associated.

  for pointer array (before allocation/association)
  without DW_AT_associated

(gdb) pt ptr
type = integer (140737345375288:140737354129776)
(gdb) p ptr
value requires 35017956 bytes, which is more than max-value-size

  with DW_AT_associated

(gdb) pt ptr
type = integer (:)
(gdb) p ptr
$1 = <not associated>

  for allocatable array (before allocation)

  without DW_AT_allocated

(gdb) pt arr
type = integer (140737345375288:140737354129776)
(gdb) p arr
value requires 35017956 bytes, which is more than max-value-size

  with DW_AT_allocated

(gdb) pt arr
type = integer, allocatable (:)
(gdb) p arr
$1 = <not allocated>

    Testing
- unit test cases added
- check-llvm
- check-debuginfo

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D83544
This commit is contained in:
Alok Kumar Sharma 2020-07-20 19:50:37 +05:30 committed by Sourabh Singh Tomar
parent 5e999cbe8d
commit 2d10258a31
20 changed files with 472 additions and 62 deletions

View File

@ -4886,7 +4886,12 @@ DIExpression that describes how to get from an object's address to the actual
raw data, if they aren't equivalent. This is only supported for array types,
particularly to describe Fortran arrays, which have an array descriptor in
addition to the array data. Alternatively it can also be DIVariable which
has the address of the actual raw data.
has the address of the actual raw data. The Fortran language supports pointer
arrays which can be attached to actual arrays, this attachement between pointer
and pointee is called association. The optional ``associated`` is a
DIExpression that describes whether the pointer array is currently associated.
The optional ``allocated`` is a DIExpression that describes whether the
allocatable array is currently allocated.
For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator
descriptors <DIEnumerator>`, each representing the definition of an enumeration

View File

@ -942,13 +942,14 @@ class DICompositeType : public DIType {
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams, StringRef Identifier,
DIDerivedType *Discriminator, Metadata *DataLocation,
StorageType Storage, bool ShouldCreate = true) {
Metadata *Associated, Metadata *Allocated, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
Flags, Elements.get(), RuntimeLang, VTableHolder,
TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator,
DataLocation, Storage, ShouldCreate);
DataLocation, Associated, Allocated, Storage, ShouldCreate);
}
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@ -957,15 +958,16 @@ class DICompositeType : public DIType {
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
StorageType Storage, bool ShouldCreate = true);
Metadata *Associated, Metadata *Allocated, StorageType Storage,
bool ShouldCreate = true);
TempDICompositeType cloneImpl() const {
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
getScope(), getBaseType(), getSizeInBits(),
getAlignInBits(), getOffsetInBits(), getFlags(),
getElements(), getRuntimeLang(), getVTableHolder(),
getTemplateParams(), getIdentifier(),
getDiscriminator(), getRawDataLocation());
return getTemporary(
getContext(), getTag(), getName(), getFile(), getLine(), getScope(),
getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(),
getFlags(), getElements(), getRuntimeLang(), getVTableHolder(),
getTemplateParams(), getIdentifier(), getDiscriminator(),
getRawDataLocation(), getRawAssociated(), getRawAllocated());
}
public:
@ -977,10 +979,11 @@ public:
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams = nullptr,
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
Metadata *DataLocation = nullptr),
Metadata *DataLocation = nullptr, Metadata *Associated = nullptr,
Metadata *Allocated = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation))
Identifier, Discriminator, DataLocation, Associated, Allocated))
DEFINE_MDNODE_GET(
DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
@ -988,10 +991,11 @@ public:
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr,
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr),
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr,
Metadata *Associated = nullptr, Metadata *Allocated = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation))
Identifier, Discriminator, DataLocation, Associated, Allocated))
TempDICompositeType clone() const { return cloneImpl(); }
@ -1009,7 +1013,7 @@ public:
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation);
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated);
static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
MDString &Identifier);
@ -1022,14 +1026,13 @@ public:
///
/// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns
/// nullptr.
static DICompositeType *
buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation);
static DICompositeType *buildODRType(
LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated);
DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
DINodeArray getElements() const {
@ -1058,6 +1061,20 @@ public:
DIExpression *getDataLocationExp() const {
return dyn_cast_or_null<DIExpression>(getRawDataLocation());
}
Metadata *getRawAssociated() const { return getOperand(10); }
DIVariable *getAssociated() const {
return dyn_cast_or_null<DIVariable>(getRawAssociated());
}
DIExpression *getAssociatedExp() const {
return dyn_cast_or_null<DIExpression>(getRawAssociated());
}
Metadata *getRawAllocated() const { return getOperand(11); }
DIVariable *getAllocated() const {
return dyn_cast_or_null<DIVariable>(getRawAllocated());
}
DIExpression *getAllocatedExp() const {
return dyn_cast_or_null<DIExpression>(getRawAllocated());
}
/// Replace operands.
///

View File

@ -4682,7 +4682,9 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(templateParams, MDField, ); \
OPTIONAL(identifier, MDStringField, ); \
OPTIONAL(discriminator, MDField, ); \
OPTIONAL(dataLocation, MDField, );
OPTIONAL(dataLocation, MDField, ); \
OPTIONAL(associated, MDField, ); \
OPTIONAL(allocated, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
@ -4692,7 +4694,8 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val,
scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val,
elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val,
discriminator.Val, dataLocation.Val)) {
discriminator.Val, dataLocation.Val, associated.Val,
allocated.Val)) {
Result = CT;
return false;
}
@ -4704,7 +4707,7 @@ bool LLParser::ParseDICompositeType(MDNode *&Result, bool IsDistinct) {
(Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val,
size.Val, align.Val, offset.Val, flags.Val, elements.Val,
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
discriminator.Val, dataLocation.Val));
discriminator.Val, dataLocation.Val, associated.Val, allocated.Val));
return false;
}

View File

@ -1350,7 +1350,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_COMPOSITE_TYPE: {
if (Record.size() < 16 || Record.size() > 18)
if (Record.size() < 16 || Record.size() > 20)
return error("Invalid record");
// If we have a UUID and this is not a forward declaration, lookup the
@ -1375,6 +1375,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Metadata *TemplateParams = nullptr;
Metadata *Discriminator = nullptr;
Metadata *DataLocation = nullptr;
Metadata *Associated = nullptr;
Metadata *Allocated = nullptr;
auto *Identifier = getMDString(Record[15]);
// If this module is being parsed so that it can be ThinLTO imported
// into another module, composite types only need to be imported
@ -1399,13 +1401,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Discriminator = getMDOrNull(Record[16]);
if (Record.size() > 17)
DataLocation = getMDOrNull(Record[17]);
if (Record.size() > 19) {
Associated = getMDOrNull(Record[18]);
Allocated = getMDOrNull(Record[19]);
}
}
DICompositeType *CT = nullptr;
if (Identifier)
CT = DICompositeType::buildODRType(
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Discriminator, DataLocation);
VTableHolder, TemplateParams, Discriminator, DataLocation, Associated,
Allocated);
// Create a node if we didn't get a lazy ODR type.
if (!CT)
@ -1413,7 +1420,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
(Context, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags,
Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation));
Identifier, Discriminator, DataLocation, Associated,
Allocated));
if (!IsNotUsedInTypeRef && Identifier)
MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));

View File

@ -1632,6 +1632,8 @@ void ModuleBitcodeWriter::writeDICompositeType(
Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier()));
Record.push_back(VE.getMetadataOrNullID(N->getDiscriminator()));
Record.push_back(VE.getMetadataOrNullID(N->getRawDataLocation()));
Record.push_back(VE.getMetadataOrNullID(N->getRawAssociated()));
Record.push_back(VE.getMetadataOrNullID(N->getRawAllocated()));
Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
Record.clear();

View File

@ -803,6 +803,10 @@ static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
return Result;
if (auto *DLVar = Array->getDataLocation())
Result.push_back(DLVar);
if (auto *AsVar = Array->getAssociated())
Result.push_back(AsVar);
if (auto *AlVar = Array->getAllocated())
Result.push_back(AlVar);
for (auto *El : Array->getElements()) {
if (auto *Subrange = dyn_cast<DISubrange>(El)) {
if (auto Count = Subrange->getCount())

View File

@ -1445,6 +1445,28 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addBlock(Buffer, dwarf::DW_AT_data_location, DwarfExpr.finalize());
}
if (DIVariable *Var = CTy->getAssociated()) {
if (auto *VarDIE = getDIE(Var))
addDIEEntry(Buffer, dwarf::DW_AT_associated, *VarDIE);
} else if (DIExpression *Expr = CTy->getAssociatedExp()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
DwarfExpr.setMemoryLocationKind();
DwarfExpr.addExpression(Expr);
addBlock(Buffer, dwarf::DW_AT_associated, DwarfExpr.finalize());
}
if (DIVariable *Var = CTy->getAllocated()) {
if (auto *VarDIE = getDIE(Var))
addDIEEntry(Buffer, dwarf::DW_AT_allocated, *VarDIE);
} else if (DIExpression *Expr = CTy->getAllocatedExp()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, getCU(), *Loc);
DwarfExpr.setMemoryLocationKind();
DwarfExpr.addExpression(Expr);
addBlock(Buffer, dwarf::DW_AT_allocated, DwarfExpr.finalize());
}
// Emit the element type.
addType(Buffer, CTy->getBaseType());

View File

@ -1962,6 +1962,8 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
Printer.printString("identifier", N->getIdentifier());
Printer.printMetadata("discriminator", N->getRawDiscriminator());
Printer.printMetadata("dataLocation", N->getRawDataLocation());
Printer.printMetadata("associated", N->getRawAssociated());
Printer.printMetadata("allocated", N->getRawAllocated());
Out << ")";
}

View File

@ -493,7 +493,8 @@ DICompositeType *DICompositeType::getImpl(
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation, StorageType Storage, bool ShouldCreate) {
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType.
@ -501,10 +502,10 @@ DICompositeType *DICompositeType::getImpl(
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements,
RuntimeLang, VTableHolder, TemplateParams, Identifier,
Discriminator, DataLocation));
Discriminator, DataLocation, Associated, Allocated));
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, Identifier,
Discriminator, DataLocation};
Discriminator, DataLocation, Associated, Allocated};
DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
AlignInBits, OffsetInBits, Flags),
Ops);
@ -516,7 +517,7 @@ DICompositeType *DICompositeType::buildODRType(
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation) {
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@ -526,7 +527,7 @@ DICompositeType *DICompositeType::buildODRType(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, &Identifier, Discriminator,
DataLocation);
DataLocation, Associated, Allocated);
// Only mutate CT if it's a forward declaration and the new operands aren't.
assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@ -538,7 +539,7 @@ DICompositeType *DICompositeType::buildODRType(
Flags);
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, &Identifier,
Discriminator, DataLocation};
Discriminator, DataLocation, Associated, Allocated};
assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
"Mismatched number of operands");
for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@ -553,7 +554,7 @@ DICompositeType *DICompositeType::getODRType(
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation) {
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@ -562,7 +563,8 @@ DICompositeType *DICompositeType::getODRType(
CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
TemplateParams, &Identifier, Discriminator, DataLocation);
TemplateParams, &Identifier, Discriminator, DataLocation, Associated,
Allocated);
return CT;
}

View File

@ -525,6 +525,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
MDString *Identifier;
Metadata *Discriminator;
Metadata *DataLocation;
Metadata *Associated;
Metadata *Allocated;
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
@ -532,13 +534,15 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation)
Metadata *DataLocation, Metadata *Associated,
Metadata *Allocated)
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
TemplateParams(TemplateParams), Identifier(Identifier),
Discriminator(Discriminator), DataLocation(DataLocation) {}
Discriminator(Discriminator), DataLocation(DataLocation),
Associated(Associated), Allocated(Allocated) {}
MDNodeKeyImpl(const DICompositeType *N)
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
Line(N->getLine()), Scope(N->getRawScope()),
@ -549,7 +553,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
TemplateParams(N->getRawTemplateParams()),
Identifier(N->getRawIdentifier()),
Discriminator(N->getRawDiscriminator()),
DataLocation(N->getRawDataLocation()) {}
DataLocation(N->getRawDataLocation()),
Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()) {}
bool isKeyOf(const DICompositeType *RHS) const {
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
@ -564,7 +569,9 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
TemplateParams == RHS->getRawTemplateParams() &&
Identifier == RHS->getRawIdentifier() &&
Discriminator == RHS->getRawDiscriminator() &&
DataLocation == RHS->getRawDataLocation();
DataLocation == RHS->getRawDataLocation() &&
Associated == RHS->getRawAssociated() &&
Allocated == RHS->getRawAllocated();
}
unsigned getHashValue() const {

View File

@ -1035,6 +1035,16 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"dataLocation can only appear in array type");
}
if (N.getRawAssociated()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"associated can only appear in array type");
}
if (N.getRawAllocated()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"allocated can only appear in array type");
}
}
void Verifier::visitDISubroutineType(const DISubroutineType &N) {

View File

@ -0,0 +1,32 @@
;; This test checks dataLocation field of DICompositeType
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}}, allocated: !{{[0-9]+}})
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), allocated: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
; ModuleID = 'allocated.f90'
source_filename = "/dir/allocated.ll"
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4)
!3 = !DIFile(filename: "allocated.f90", directory: "/dir")
!4 = !{}
!5 = !{!6, !17}
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !10, allocated: !15)
!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!8 = !{!9}
!9 = !DISubrange(count: 19, lowerBound: 2)
!10 = distinct !DILocalVariable(scope: !11, file: !3, type: !14, flags: DIFlagArtificial)
!11 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !12, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!12 = !DISubroutineType(cc: DW_CC_program, types: !13)
!13 = !{null}
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
!15 = distinct !DILocalVariable(scope: !11, file: !3, type: !16, flags: DIFlagArtificial)
!16 = !DIBasicType(name: "logical", size: 32, align: 32, encoding: DW_ATE_signed)
!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), allocated: !DIExpression(DW_OP_push_object_address, DW_OP_deref))

View File

@ -0,0 +1,32 @@
;; This test checks dataLocation field of DICompositeType
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !{{[0-9]+}}, associated: !{{[0-9]+}})
; CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: !{{[0-9]+}}, size: 32, align: 32, elements: !{{[0-9]+}}, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
; ModuleID = 'associated.f90'
source_filename = "/dir/associated.ll"
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4)
!3 = !DIFile(filename: "associated.f90", directory: "/dir")
!4 = !{}
!5 = !{!6, !17}
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !10, associated: !15)
!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!8 = !{!9}
!9 = !DISubrange(count: 19, lowerBound: 2)
!10 = distinct !DILocalVariable(scope: !11, file: !3, type: !14, flags: DIFlagArtificial)
!11 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !12, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!12 = !DISubroutineType(cc: DW_CC_program, types: !13)
!13 = !{null}
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
!15 = distinct !DILocalVariable(scope: !11, file: !3, type: !16, flags: DIFlagArtificial)
!16 = !DIBasicType(name: "logical", size: 32, align: 32, encoding: DW_ATE_signed)
!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32, align: 32, elements: !8, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref))

View File

@ -0,0 +1,56 @@
; RUN: llc %s -O2 -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
; Test whether DW_AT_data_location is generated.
; CHECK-LABEL: DW_TAG_array_type
; CHECK: DW_AT_allocated (DW_OP_push_object_address, DW_OP_deref)
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_subrange_type
; Test case is hand written with the help of below testcase
;------------------------------
;program main
;integer, allocatable :: arr(:)
;allocate(arr(2:20))
;arr(2)=99
;print *, arr
;end program main
;------------------------------
; ModuleID = 'allocated.ll'
source_filename = "allocated.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0640_333 = alloca i32*, align 8
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !13
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !14, metadata !DIExpression()), !dbg !13
ret void, !dbg !16
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "allocated.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !5, file: !3, type: !9)
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !11, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), allocated: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DISubrange(count: 19, lowerBound: 2)
!13 = !DILocation(line: 0, scope: !5)
!14 = distinct !DILocalVariable(scope: !5, file: !3, type: !15, flags: DIFlagArtificial)
!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 32, align: 32)
!16 = !DILocation(line: 6, column: 1, scope: !5)

View File

@ -0,0 +1,68 @@
;; This test checks whether DW_AT_data_location attribute
;; accepts DIVariable
; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK: [[ALCDIE:0x.+]]: DW_TAG_variable
; CHECK: DW_AT_type ({{0x[0-9]+}} "logical")
; CHECK: [[LOCDIE:0x.+]]: DW_TAG_variable
; CHECK: DW_AT_type ({{0x[0-9]+}} "integer*")
; CHECK: DW_AT_artificial (true)
; CHECK: DW_TAG_variable
; CHECK: DW_AT_name ("arr")
; CHECK: DW_TAG_array_type
; CHECK-NEXT: DW_AT_data_location ([[LOCDIE]])
; CHECK-NEXT: DW_AT_allocated ([[ALCDIE]])
;; Test case is hand written with the help of below testcase
;;------------------------------
;;program main
;;integer, allocatable :: arr(:)
;;allocate(arr(2:20))
;;arr(2)=99
;;print *, arr
;;end program main
;;------------------------------
; ModuleID = 'allocated.ll'
source_filename = "allocated.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0640_333 = alloca i32*, align 8
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !17
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !13, metadata !DIExpression()), !dbg !17
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !15, metadata !DIExpression()), !dbg !17
ret void, !dbg !18
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "allocated.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !5, file: !3, type: !9)
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !11, dataLocation: !13, allocated: !15)
!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DISubrange(count: 19, lowerBound: 2)
!13 = distinct !DILocalVariable(scope: !5, file: !3, type: !14, flags: DIFlagArtificial)
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 32, align: 32)
!15 = distinct !DILocalVariable(scope: !5, file: !3, type: !16, flags: DIFlagArtificial)
!16 = !DIBasicType(name: "logical", size: 32, align: 32, encoding: DW_ATE_signed)
!17 = !DILocation(line: 0, scope: !5)
!18 = !DILocation(line: 6, column: 1, scope: !5)

View File

@ -0,0 +1,56 @@
; RUN: llc %s -O2 -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
; Test whether DW_AT_data_location is generated.
; CHECK-LABEL: DW_TAG_array_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_associated (DW_OP_push_object_address, DW_OP_deref)
; CHECK: DW_TAG_subrange_type
; Test case is hand written with the help of below testcase
;------------------------------
;program main
;integer, pointer :: arr(:)
;allocate(arr(2:20))
;arr(2)=99
;print *, arr
;end program main
;------------------------------
; ModuleID = 'associated.ll'
source_filename = "associated.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0640_333 = alloca i32*, align 8
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !13
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !14, metadata !DIExpression()), !dbg !13
ret void, !dbg !16
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "associated.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !5, file: !3, type: !9)
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !11, dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref), associated: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DISubrange(count: 19, lowerBound: 2)
!13 = !DILocation(line: 0, scope: !5)
!14 = distinct !DILocalVariable(scope: !5, file: !3, type: !15, flags: DIFlagArtificial)
!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 32, align: 32)
!16 = !DILocation(line: 6, column: 1, scope: !5)

View File

@ -0,0 +1,68 @@
;; This test checks whether DW_AT_data_location attribute
;; accepts DIVariable
; RUN: llc -mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
;; Test whether DW_AT_data_location is generated.
; CHECK: [[ALCDIE:0x.+]]: DW_TAG_variable
; CHECK: DW_AT_type ({{0x[0-9]+}} "logical")
; CHECK: [[LOCDIE:0x.+]]: DW_TAG_variable
; CHECK: DW_AT_type ({{0x[0-9]+}} "integer*")
; CHECK: DW_AT_artificial (true)
; CHECK: DW_TAG_variable
; CHECK: DW_AT_name ("arr")
; CHECK: DW_TAG_array_type
; CHECK-NEXT: DW_AT_data_location ([[LOCDIE]])
; CHECK-NEXT: DW_AT_associated ([[ALCDIE]])
;; Test case is hand written with the help of below testcase
;;------------------------------
;;program main
;;integer, pointer :: arr(:)
;;allocate(arr(2:20))
;;arr(2)=99
;;print *, arr
;;end program main
;;------------------------------
; ModuleID = 'associated.ll'
source_filename = "associated.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0640_333 = alloca i32*, align 8
%"arr$sd1_349" = alloca [16 x i64], align 8
call void @llvm.dbg.declare(metadata [16 x i64]* %"arr$sd1_349", metadata !8, metadata !DIExpression()), !dbg !17
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !13, metadata !DIExpression()), !dbg !17
call void @llvm.dbg.declare(metadata i32** %.Z0640_333, metadata !15, metadata !DIExpression()), !dbg !17
ret void, !dbg !18
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "associated.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = !DILocalVariable(name: "arr", scope: !5, file: !3, type: !9)
!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !11, dataLocation: !13, associated: !15)
!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DISubrange(count: 19, lowerBound: 2)
!13 = distinct !DILocalVariable(scope: !5, file: !3, type: !14, flags: DIFlagArtificial)
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 32, align: 32)
!15 = distinct !DILocalVariable(scope: !5, file: !3, type: !16, flags: DIFlagArtificial)
!16 = !DIBasicType(name: "logical", size: 32, align: 32, encoding: DW_ATE_signed)
!17 = !DILocation(line: 0, scope: !5)
!18 = !DILocation(line: 6, column: 1, scope: !5)

View File

@ -0,0 +1,6 @@
; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s
!named = !{!0}
!0 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", size: 64, allocated: !DIExpression(DW_OP_constu, 6789))
; CHECK: allocated can only appear in array type

View File

@ -0,0 +1,6 @@
; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s
!named = !{!0}
!0 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", size: 64, associated: !DIExpression(DW_OP_constu, 6789))
; CHECK: associated can only appear in array type

View File

@ -30,7 +30,7 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
EXPECT_FALSE(DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
nullptr));
nullptr, nullptr, nullptr));
// Enable the mapping. There still shouldn't be a type.
Context.enableDebugTypeODRUniquing();
@ -40,7 +40,7 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
auto &CT = *DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
nullptr);
nullptr, nullptr, nullptr);
EXPECT_EQ(UUID.getString(), CT.getIdentifier());
// Check that we get it back, even if we change a field.
@ -48,12 +48,12 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr, nullptr));
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type,
MDString::get(Context, "name"), nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr,
nullptr, nullptr, nullptr));
nullptr, nullptr, nullptr, nullptr, nullptr));
// Check that it's discarded with the type map.
Context.disableDebugTypeODRUniquing();
@ -73,34 +73,36 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
auto &CT = *DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr,
nullptr, nullptr);
nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with another forward decl. This should be a no-op.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl,
nullptr, 0, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(&CT,
DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with a definition. This time we should see a change.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero,
nullptr, 0, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(&CT,
DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
// Further updates should be ignored.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr,
0, nullptr, nullptr, nullptr, nullptr));
0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr, nullptr, nullptr));
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
}
@ -112,7 +114,8 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
MDString &UUID = *MDString::get(Context, "UUID");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr);
DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr);
// Create macros for running through all the fields except Identifier and Flags.
#define FOR_EACH_MDFIELD() \
@ -141,11 +144,12 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
#undef DO_FOR_FIELD
// Replace all the fields with new values that are distinct from each other.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits,
DINode::FlagArtificial, Elements, RuntimeLang,
VTableHolder, TemplateParams, nullptr, nullptr));
EXPECT_EQ(&CT,
DICompositeType::buildODRType(
Context, UUID, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr,
nullptr, nullptr, nullptr));
// Confirm that all the right fields got updated.
#define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());