diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index 6ad4d8d7e..fb93e5dc0 100644 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -878,12 +878,16 @@ TypeRef GetEnumConstantType(ConstDeclRef DRef) { return INTEROP_RETURN(nullptr); } -size_t GetEnumConstantValue(ConstDeclRef DRef) { +int64_t GetEnumConstantValue(ConstDeclRef DRef) { INTEROP_TRACE(DRef); const auto* D = unwrap(DRef); if (const auto* ECD = llvm::dyn_cast_or_null(D)) { const llvm::APSInt& Val = ECD->getInitVal(); - return INTEROP_RETURN(Val.getExtValue()); + if (Val.isRepresentableByInt64()) + return INTEROP_RETURN(Val.getExtValue()); + // Do not round-trip through a string and std::stoul: unsigned long is + // 32 bit on LLP64/ILP32 and throws out_of_range for these values. + return INTEROP_RETURN((int64_t)Val.getZExtValue()); } return INTEROP_RETURN(0); } diff --git a/lib/CppInterOp/CppInterOp.td b/lib/CppInterOp/CppInterOp.td index be9cd1e86..4f4c45e86 100644 --- a/lib/CppInterOp/CppInterOp.td +++ b/lib/CppInterOp/CppInterOp.td @@ -1059,10 +1059,11 @@ def GetEnumConstantType : CppInterOpAPI { } def GetEnumConstantValue : CppInterOpAPI { - let Doc = [{Gets the index value (0,1,2, etcetera) of the enum constant -that was passed into this function.}]; + let Doc = [{Gets the value of the enum constant that was passed into this +function, as its 64-bit bit pattern (values above INT64_MAX come back as +their two's complement representation).}]; - let ReturnType = "size_t"; + let ReturnType = "int64_t"; let Args = [ Arg<"ConstDeclRef", "DRef"> ]; diff --git a/unittests/CppInterOp/EnumReflectionTest.cpp b/unittests/CppInterOp/EnumReflectionTest.cpp index 0e5d56025..0696cd71d 100644 --- a/unittests/CppInterOp/EnumReflectionTest.cpp +++ b/unittests/CppInterOp/EnumReflectionTest.cpp @@ -237,6 +237,10 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnumConstantValue) { MinusTen = -10, MinusNine }; + enum Huge : unsigned long long { + Big = ((unsigned long long)1) << 63, + Max = 0xFFFFFFFFFFFFFFFFULL + }; int a = 10; )"; @@ -250,7 +254,12 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnumConstantValue) { EXPECT_EQ(Cpp::GetEnumConstantValue(EnumConstants[4]), 54); EXPECT_EQ(Cpp::GetEnumConstantValue(EnumConstants[5]), -10); EXPECT_EQ(Cpp::GetEnumConstantValue(EnumConstants[6]), -9); - EXPECT_EQ(Cpp::GetEnumConstantValue(Decls[1]), 0); // Checking value of non enum constant + EXPECT_EQ(Cpp::GetEnumConstantValue(Decls[2]), 0); // Checking value of non enum constant + + auto HugeConstants = Cpp::GetEnumConstants(Decls[1]); + EXPECT_EQ(Cpp::GetEnumConstantValue(HugeConstants[0]), + (int64_t)((uint64_t)1 << 63)); + EXPECT_EQ(Cpp::GetEnumConstantValue(HugeConstants[1]), (int64_t)-1); } TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnums) {