diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3084,15 +3084,17 @@ SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); - // Create elements for each enumerator. + // Create elements for each enumerator. Use the signed-ness of the enum type, + // not the signedness of the enumerator. This matches the DWARF produced by + // GCC for C enums with positive enumerators. SmallVector Enumerators; ED = ED->getDefinition(); bool IsSigned = ED->getIntegerType()->isSignedIntegerType(); for (const auto *Enum : ED->enumerators()) { - const auto &InitVal = Enum->getInitVal(); - auto Value = IsSigned ? InitVal.getSExtValue() : InitVal.getZExtValue(); + llvm::APSInt Value = Enum->getInitVal(); + Value.setIsSigned(IsSigned); Enumerators.push_back( - DBuilder.createEnumerator(Enum->getName(), Value, !IsSigned)); + DBuilder.createEnumerator(Enum->getName(), std::move(Value))); } // Return a CompositeType for the enum itself. diff --git a/clang/test/CodeGenCXX/debug-info-enum-i128.cpp b/clang/test/CodeGenCXX/debug-info-enum-i128.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-enum-i128.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -debug-info-kind=limited -emit-llvm -o - | FileCheck %s + +enum class uns : __uint128_t { unsval = __uint128_t(1) << 64 }; +uns t1() { return uns::unsval; } + +enum class sig : __int128 { sigval = -(__int128(1) << 64) }; +sig t2() { return sig::sigval; } + + +// CHECK-LABEL: !DICompositeType(tag: DW_TAG_enumeration_type, name: "uns", {{.*}}) +// CHECK: !DIEnumerator(name: "unsval", value: 18446744073709551616, isUnsigned: true) + +// CHECK-LABEL: !DICompositeType(tag: DW_TAG_enumeration_type, name: "sig", {{.*}}) +// CHECK: !DIEnumerator(name: "sigval", value: -18446744073709551616) diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -181,7 +181,9 @@ DIFile *File); /// Create a single enumerator value. - DIEnumerator *createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned = false); + DIEnumerator *createEnumerator(StringRef Name, APSInt Value); + DIEnumerator *createEnumerator(StringRef Name, int64_t Val, + bool IsUnsigned = false); /// Create a DWARF unspecified type. DIBasicType *createUnspecifiedType(StringRef Name); diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -250,6 +250,11 @@ Name); } +DIEnumerator *DIBuilder::createEnumerator(StringRef Name, APSInt Value) { + assert(!Name.empty() && "Unable to create enumerator without name"); + return DIEnumerator::get(VMContext, APInt(Value), Value.isUnsigned(), Name); +} + DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) { assert(!Name.empty() && "Unable to create type without name"); return DIBasicType::get(VMContext, dwarf::DW_TAG_unspecified_type, Name);