Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -277,7 +277,7 @@ METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]] METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num] METADATA_SUBRANGE = 13, // [distinct, count, lo] - METADATA_ENUMERATOR = 14, // [distinct, value, name] + METADATA_ENUMERATOR = 14, // [isUnsigned|distinct, value, name] METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] METADATA_FILE = 16, // [distinct, filename, directory, checksumkind, checksum] METADATA_DERIVED_TYPE = 17, // [distinct, ...] Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -166,7 +166,7 @@ DIFile *File); /// Create a single enumerator value. - DIEnumerator *createEnumerator(StringRef Name, int64_t Val); + DIEnumerator *createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned = false); /// Create a DWARF unspecified type. DIBasicType *createUnspecifiedType(StringRef Name); @@ -445,10 +445,11 @@ /// \param Elements Enumeration elements. /// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// \param UniqueIdentifier A unique identifier for the enum. + /// \param IsFixed Boolean flag indicate if this is C++11/ObjC fixed enum. DICompositeType *createEnumerationType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements, - DIType *UnderlyingType, StringRef UniqueIdentifier = ""); + DIType *UnderlyingType, StringRef UniqueIdentifier = "", bool IsFixed = false); /// Create subroutine type. /// \param ParameterTypes An array of subroutine parameter types. This Index: include/llvm/IR/DebugInfoFlags.def =================================================================== --- include/llvm/IR/DebugInfoFlags.def +++ include/llvm/IR/DebugInfoFlags.def @@ -45,6 +45,7 @@ HANDLE_DI_FLAG((1 << 21), MainSubprogram) HANDLE_DI_FLAG((1 << 22), TypePassByValue) HANDLE_DI_FLAG((1 << 23), TypePassByReference) +HANDLE_DI_FLAG((1 << 24), FixedEnum) // To avoid needing a dedicated value for IndirectVirtualBase, we use // the bitwise or of Virtual and FwdDecl, which does not otherwise @@ -54,7 +55,7 @@ #ifdef DI_FLAG_LARGEST_NEEDED // intended to be used with ADT/BitmaskEnum.h // NOTE: always must be equal to largest flag, check this when adding new flag -HANDLE_DI_FLAG((1 << 23), Largest) +HANDLE_DI_FLAG((1 << 24), Largest) #undef DI_FLAG_LARGEST_NEEDED #endif Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -396,36 +396,38 @@ friend class MDNode; int64_t Value; - DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, - ArrayRef Ops) + bool IsUnsigned, ArrayRef Ops) : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), - Value(Value) {} + Value(Value) { + SubclassData32 = IsUnsigned; + } ~DIEnumerator() = default; static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, - StringRef Name, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, - ShouldCreate); + bool IsUnsigned, StringRef Name, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Value, IsUnsigned, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); } static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, - MDString *Name, StorageType Storage, - bool ShouldCreate = true); + bool IsUnsigned, MDString *Name, + StorageType Storage, bool ShouldCreate = true); TempDIEnumerator cloneImpl() const { - return getTemporary(getContext(), getValue(), getName()); + return getTemporary(getContext(), getValue(), isUnsigned(), getName()); } public: - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name), - (Value, Name)) - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name), - (Value, Name)) + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name), + (Value, IsUnsigned, Name)) + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name), + (Value, IsUnsigned, Name)) TempDIEnumerator clone() const { return cloneImpl(); } int64_t getValue() const { return Value; } + bool isUnsigned() const { return SubclassData32; } StringRef getName() const { return getStringOperand(0); } MDString *getRawName() const { return getOperandAs(0); } Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -3636,6 +3636,22 @@ } }; +struct MDSignedOrUnsignedField + : MDEitherFieldImpl { + MDSignedOrUnsignedField() : ImplTy(MDSignedField(0), MDUnsignedField(0)) {} + + bool isMDSignedField() const { return WhatIs == IsTypeA; } + bool isMDUnsignedField() const { return WhatIs == IsTypeB; } + int64_t getMDSignedValue() const { + assert(isMDSignedField() && "Wrong field type"); + return A.Val; + } + uint64_t getMDUnsignedValue() const { + assert(isMDUnsignedField() && "Wrong field type"); + return B.Val; + } +}; + } // end anonymous namespace namespace llvm { @@ -3913,6 +3929,29 @@ } template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, + MDSignedOrUnsignedField &Result) { + if (Lex.getKind() != lltok::APSInt) + return false; + + if (Lex.getAPSIntVal().isSigned()) { + MDSignedField Res = Result.A; + if (!ParseMDField(Loc, Name, Res)) { + Result.assign(Res); + return false; + } + return true; + } + + MDUnsignedField Res = Result.B; + if (!ParseMDField(Loc, Name, Res)) { + Result.assign(Res); + return false; + } + return true; +} + +template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { LocTy ValueLoc = Lex.getLoc(); std::string S; @@ -4077,15 +4116,24 @@ } /// ParseDIEnumerator: -/// ::= !DIEnumerator(value: 30, name: "SomeKind") +/// ::= !DIEnumerator(value: 30, isUnsigned: true, name: "SomeKind") bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(name, MDStringField, ); \ - REQUIRED(value, MDSignedField, ); + REQUIRED(value, MDSignedOrUnsignedField, ); \ + OPTIONAL(isUnsigned, MDBoolField, (false)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DIEnumerator, (Context, value.Val, name.Val)); + if (isUnsigned.Val && value.isMDSignedField()) + return TokError("unsigned enumerator with negative value"); + + int64_t Value = value.isMDSignedField() + ? value.getMDSignedValue() + : static_cast(value.getMDUnsignedValue()); + Result = + GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val)); + return false; } Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -1200,10 +1200,11 @@ if (Record.size() != 3) return error("Invalid record"); - IsDistinct = Record[0]; + IsDistinct = Record[0] & 1; + bool IsUnsigned = Record[0] & 2; MetadataList.assignValue( GET_OR_DISTINCT(DIEnumerator, (Context, unrotateSign(Record[1]), - getMDString(Record[2]))), + IsUnsigned, getMDString(Record[2]))), NextMetadataNo); NextMetadataNo++; break; Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1457,7 +1457,7 @@ void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, SmallVectorImpl &Record, unsigned Abbrev) { - Record.push_back(N->isDistinct()); + Record.push_back((N->isUnsigned() << 1) | N->isDistinct()); Record.push_back(rotateSign(N->getValue())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1395,6 +1395,15 @@ } void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) { + const DIType *DTy = resolve(CTy->getBaseType()); + bool IsUnsigned = DTy && isUnsignedDIType(DD, DTy); + if (DTy && DD->getDwarfVersion() >= 3) + addType(Buffer, DTy); + if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagFixedEnum)) { + assert(DTy); + addFlag(Buffer, dwarf::DW_AT_enum_class); + } + DINodeArray Elements = CTy->getElements(); // Add enumerators to enumeration type. @@ -1404,16 +1413,10 @@ DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer); StringRef Name = Enum->getName(); addString(Enumerator, dwarf::DW_AT_name, Name); - int64_t Value = Enum->getValue(); - addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, - Value); + auto Value = static_cast(Enum->getValue()); + addConstantValue(Enumerator, IsUnsigned, Value); } } - const DIType *DTy = resolve(CTy->getBaseType()); - if (DTy) { - addType(Buffer, DTy); - addFlag(Buffer, dwarf::DW_AT_enum_class); - } } void DwarfUnit::constructContainingTypeDIEs() { Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1629,7 +1629,13 @@ Out << "!DIEnumerator("; MDFieldPrinter Printer(Out); Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false); - Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false); + if (N->isUnsigned()) { + auto Value = static_cast(N->getValue()); + Printer.printInt("value", Value, /* ShouldSkipZero */ false); + Printer.printBool("isUnsigned", true); + } else { + Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false); + } Out << ")"; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -233,9 +233,10 @@ return MF; } -DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val) { +DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val, + bool IsUnsigned) { assert(!Name.empty() && "Unable to create enumerator without name"); - return DIEnumerator::get(VMContext, Val, Name); + return DIEnumerator::get(VMContext, Val, IsUnsigned, Name); } DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) { @@ -467,11 +468,12 @@ DICompositeType *DIBuilder::createEnumerationType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements, - DIType *UnderlyingType, StringRef UniqueIdentifier) { + DIType *UnderlyingType, StringRef UniqueIdentifier, bool IsFixed) { auto *CTy = DICompositeType::get( VMContext, dwarf::DW_TAG_enumeration_type, Name, File, LineNumber, getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0, - DINode::FlagZero, Elements, 0, nullptr, nullptr, UniqueIdentifier); + IsFixed ? DINode::FlagFixedEnum : DINode::FlagZero, Elements, 0, nullptr, + nullptr, UniqueIdentifier); AllEnumTypes.push_back(CTy); trackIfUnresolved(CTy); return CTy; Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -263,12 +263,12 @@ } DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value, - MDString *Name, StorageType Storage, - bool ShouldCreate) { + bool IsUnsigned, MDString *Name, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, Name)); + DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name)); Metadata *Ops[] = {Name}; - DEFINE_GETIMPL_STORE(DIEnumerator, (Value), Ops); + DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops); } DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -354,13 +354,17 @@ template <> struct MDNodeKeyImpl { int64_t Value; MDString *Name; + bool IsUnsigned; - MDNodeKeyImpl(int64_t Value, MDString *Name) : Value(Value), Name(Name) {} + MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name) + : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {} MDNodeKeyImpl(const DIEnumerator *N) - : Value(N->getValue()), Name(N->getRawName()) {} + : Value(N->getValue()), Name(N->getRawName()), + IsUnsigned(N->isUnsigned()) {} bool isKeyOf(const DIEnumerator *RHS) const { - return Value == RHS->getValue() && Name == RHS->getRawName(); + return Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() && + Name == RHS->getRawName(); } unsigned getHashValue() const { return hash_combine(Value, Name); } Index: test/DebugInfo/Generic/debug-info-enum.ll =================================================================== --- /dev/null +++ test/DebugInfo/Generic/debug-info-enum.ll @@ -0,0 +1,171 @@ +; RUN: llc -debugger-tune=gdb -dwarf-version=4 -filetype=obj -o %t.o < %s +; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DW4 +; RUN: llc -debugger-tune=gdb -dwarf-version=2 -filetype=obj -o %t.o < %s +; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DW2 + +@x0 = global i8 0, align 1, !dbg !0 +@x1 = global i8 0, align 1, !dbg !46 +@x2 = global i16 0, align 2, !dbg !48 +@x3 = global i16 0, align 2, !dbg !50 +@x4 = global i32 0, align 4, !dbg !52 +@x5 = global i32 0, align 4, !dbg !54 +@x6 = global i64 0, align 8, !dbg !56 +@x7 = global i64 0, align 8, !dbg !58 +@x8 = global i32 0, align 4, !dbg !60 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!62} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x0", scope: !2, file: !3, line: 5, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (/data/src/llvm/tools/clang 0c08d9830124a75675348b4eeb47256f3da6693d) (/data/src/llvm cf29510f52faa77b98510cd53276f564d1f4f41f)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !45) +!3 = !DIFile(filename: "/data/src/llvm-dev/tools/clang/test/CodeGen/debug-info-enum.cpp", directory: "/work/build/clang-dev") +!4 = !{!5, !10, !14, !19, !23, !28, !32, !37, !41} +!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E0", file: !3, line: 2, baseType: !6, size: 8, flags: DIFlagFixedEnum, elements: !7, identifier: "_ZTS2E0") +!6 = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char) +!7 = !{!8, !9} +!8 = !DIEnumerator(name: "A0", value: -128) +!9 = !DIEnumerator(name: "B0", value: 127) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"signed char" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E0") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A0") +; CHECK-NEXT: DW_AT_const_value (-128) +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("B0") +; CHECK-NEXT: DW_AT_const_value (127) + +!10 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1", file: !3, line: 12, baseType: !11, size: 8, flags: DIFlagFixedEnum, elements: !12, identifier: "_ZTS2E1") +!11 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char) +!12 = !{!13} +!13 = !DIEnumerator(name: "A1", value: 255, isUnsigned: true) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"unsigned char" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E1") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A1") +; CHECK-NEXT: DW_AT_const_value (255) + +!14 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2", file: !3, line: 18, baseType: !15, size: 16, flags: DIFlagFixedEnum, elements: !16, identifier: "_ZTS2E2") +!15 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) +!16 = !{!17, !18} +!17 = !DIEnumerator(name: "A2", value: -32768) +!18 = !DIEnumerator(name: "B2", value: 32767) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}} "short" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E2") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A2") +; CHECK-NEXT: DW_AT_const_value (-32768) +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("B2") +; CHECK-NEXT: DW_AT_const_value (32767) + +!19 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3", file: !3, line: 28, baseType: !20, size: 16, flags: DIFlagFixedEnum, elements: !21, identifier: "_ZTS2E3") +!20 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned) +!21 = !{!22} +!22 = !DIEnumerator(name: "A3", value: 65535, isUnsigned: true) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"unsigned short" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E3") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A3") +; CHECK-NEXT: DW_AT_const_value (65535) + +!23 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E4", file: !3, line: 34, baseType: !24, size: 32, flags: DIFlagFixedEnum, elements: !25, identifier: "_ZTS2E4") +!24 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!25 = !{!26, !27} +!26 = !DIEnumerator(name: "A4", value: -2147483648) +!27 = !DIEnumerator(name: "B4", value: 2147483647) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"int" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E4") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A4") +; CHECK-NEXT: DW_AT_const_value (-2147483648) +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("B4") +; CHECK-NEXT: DW_AT_const_value (2147483647) + +!28 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E5", file: !3, line: 41, baseType: !29, size: 32, flags: DIFlagFixedEnum, elements: !30, identifier: "_ZTS2E5") +!29 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!30 = !{!31} +!31 = !DIEnumerator(name: "A5", value: 4294967295, isUnsigned: true) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"unsigned int" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E5") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A5") +; CHECK-NEXT: DW_AT_const_value (4294967295) + +!32 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E6", file: !3, line: 47, baseType: !33, size: 64, flags: DIFlagFixedEnum, elements: !34, identifier: "_ZTS2E6") +!33 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!34 = !{!35, !36} +!35 = !DIEnumerator(name: "A6", value: -9223372036854775808) +!36 = !DIEnumerator(name: "B6", value: 9223372036854775807) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"long long int" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E6") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A6") +; CHECK-NEXT: DW_AT_const_value (-9223372036854775808) +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("B6") +; CHECK-NEXT: DW_AT_const_value (9223372036854775807) + +!37 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E7", file: !3, line: 57, baseType: !38, size: 64, flags: DIFlagFixedEnum, elements: !39, identifier: "_ZTS2E7") +!38 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!39 = !{!40} +!40 = !DIEnumerator(name: "A7", value: 18446744073709551615, isUnsigned: true) +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"long long unsigned int" +; CHECK-DW4: DW_AT_enum_class (true) +; CHECK: DW_AT_name ("E7") +; CHECK: DW_TAG_enumerator +; CHECK: DW_AT_name ("A7") +; CHECK-NEXT: DW_AT_const_value (18446744073709551615) + +!41 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E8", file: !3, line: 63, baseType: !24, size: 32, elements: !42, identifier: "_ZTS2E8") +!42 = !{!43, !44} +!43 = !DIEnumerator(name: "A8", value: -128) +!44 = !DIEnumerator(name: "B8", value: 127) +!45 = !{!0, !46, !48, !50, !52, !54, !56, !58, !60} +; CHECK: DW_TAG_enumeration_type +; CHECK-DW2-NOT: DW_AT_type +; CHECK-DW4: DW_AT_type{{.*}}"int" +; CHECK-NOT: DW_AT_enum_class +; CHECK: DW_AT_name ("E8") + +!46 = !DIGlobalVariableExpression(var: !47, expr: !DIExpression()) +!47 = distinct !DIGlobalVariable(name: "x1", scope: !2, file: !3, line: 12, type: !10, isLocal: false, isDefinition: true) +!48 = !DIGlobalVariableExpression(var: !49, expr: !DIExpression()) +!49 = distinct !DIGlobalVariable(name: "x2", scope: !2, file: !3, line: 21, type: !14, isLocal: false, isDefinition: true) +!50 = !DIGlobalVariableExpression(var: !51, expr: !DIExpression()) +!51 = distinct !DIGlobalVariable(name: "x3", scope: !2, file: !3, line: 28, type: !19, isLocal: false, isDefinition: true) +!52 = !DIGlobalVariableExpression(var: !53, expr: !DIExpression()) +!53 = distinct !DIGlobalVariable(name: "x4", scope: !2, file: !3, line: 34, type: !23, isLocal: false, isDefinition: true) +!54 = !DIGlobalVariableExpression(var: !55, expr: !DIExpression()) +!55 = distinct !DIGlobalVariable(name: "x5", scope: !2, file: !3, line: 41, type: !28, isLocal: false, isDefinition: true) +!56 = !DIGlobalVariableExpression(var: !57, expr: !DIExpression()) +!57 = distinct !DIGlobalVariable(name: "x6", scope: !2, file: !3, line: 50, type: !32, isLocal: false, isDefinition: true) +!58 = !DIGlobalVariableExpression(var: !59, expr: !DIExpression()) +!59 = distinct !DIGlobalVariable(name: "x7", scope: !2, file: !3, line: 57, type: !37, isLocal: false, isDefinition: true) +!60 = !DIGlobalVariableExpression(var: !61, expr: !DIExpression()) +!61 = distinct !DIGlobalVariable(name: "x8", scope: !2, file: !3, line: 63, type: !41, isLocal: false, isDefinition: true) +!62 = !{i32 2, !"Debug Info Version", i32 3} Index: test/DebugInfo/X86/enum-class.ll =================================================================== --- test/DebugInfo/X86/enum-class.ll +++ test/DebugInfo/X86/enum-class.ll @@ -13,13 +13,13 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 4, type: !3, isLocal: false, isDefinition: true) !2 = !DIFile(filename: "foo.cpp", directory: "/Users/echristo/tmp") -!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "A", file: !2, line: 1, baseType: !4, size: 32, align: 32, elements: !5) +!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "A", file: !2, line: 1, baseType: !4, size: 32, flags: DIFlagFixedEnum, align: 32, elements: !5) !4 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !5 = !{!6} !6 = !DIEnumerator(name: "A1", value: 1) !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression()) ; [ DW_TAG_enumerator ] !8 = !DIGlobalVariable(name: "b", scope: null, file: !2, line: 5, type: !9, isLocal: false, isDefinition: true) -!9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "B", file: !2, line: 2, baseType: !10, size: 64, align: 64, elements: !11) +!9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "B", file: !2, line: 2, baseType: !10, size: 64, flags: DIFlagFixedEnum, align: 64, elements: !11) !10 = !DIBasicType(name: "long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned) !11 = !{!12} !12 = !DIEnumerator(name: "B1", value: 1) ; [ DW_TAG_enumerator ] @@ -44,6 +44,6 @@ ; CHECK: DW_AT_enum_class [DW_FORM_flag_present] (true) ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "B") -; CHECK: DW_TAG_enumeration_type [6] +; CHECK: DW_TAG_enumeration_type ; CHECK-NOT: DW_AT_enum_class ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "C") Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -978,14 +978,16 @@ typedef MetadataTest DIEnumeratorTest; TEST_F(DIEnumeratorTest, get) { - auto *N = DIEnumerator::get(Context, 7, "name"); + auto *N = DIEnumerator::get(Context, 7, false, "name"); EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag()); EXPECT_EQ(7, N->getValue()); + EXPECT_EQ(false, N->isUnsigned()); EXPECT_EQ("name", N->getName()); - EXPECT_EQ(N, DIEnumerator::get(Context, 7, "name")); + EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name")); - EXPECT_NE(N, DIEnumerator::get(Context, 8, "name")); - EXPECT_NE(N, DIEnumerator::get(Context, 7, "nam")); + EXPECT_NE(N, DIEnumerator::get(Context, 7, true, "name")); + EXPECT_NE(N, DIEnumerator::get(Context, 8, false, "name")); + EXPECT_NE(N, DIEnumerator::get(Context, 7, false, "nam")); TempDIEnumerator Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));