Skip to content

Commit

Permalink
resolve static constexpr class attribute (#351)
Browse files Browse the repository at this point in the history
* fix `GetVariableOffset` for static constexpr class attribute

by explicitly initializing constexpr with `Sema::InstantiateVariableDefinition`

* brew remove unxip on OSX-ARM exclusively

fix for the osx dependency issue

* Update lib/Interpreter/CppInterOp.cpp

---------

Co-authored-by: Vassil Vassilev <[email protected]>
  • Loading branch information
Vipul-Cariappa and vgvassilev authored Nov 16, 2024
1 parent 826be78 commit e4adda3
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 17 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,10 @@ jobs:
run: |
brew update
brew remove [email protected]
brew remove unxip
export ARCHITECHURE=$(uname -m)
if [[ "$ARCHITECHURE" != "x86_64" ]]; then
brew remove unxip
fi
# workaround for https://github.com/actions/setup-python/issues/577
for pkg in $(brew list | grep '^python@'); do
brew unlink "$pkg"
Expand Down Expand Up @@ -764,10 +767,11 @@ jobs:
run: |
brew update
brew remove [email protected]
brew remove unxip
export ARCHITECHURE=$(uname -m)
if [[ "$ARCHITECHURE" == "x86_64" ]]; then
brew remove swiftlint
else
brew remove unxip
fi
# workaround for https://github.com/actions/setup-python/issues/577
for pkg in $(brew list | grep '^python@'); do
Expand Down
18 changes: 17 additions & 1 deletion lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,22 @@ namespace Cpp {

if (!address)
address = I.getAddressOfGlobal(GD);
if (!address) {
if (!VD->hasInit()) {
#ifdef USE_CLING
cling::Interpreter::PushTransactionRAII RAII(&getInterp());
#endif // USE_CLING
getSema().InstantiateVariableDefinition(SourceLocation(), VD);
}
if (VD->hasInit() &&
(VD->isConstexpr() || VD->getType().isConstQualified())) {
if (const APValue* val = VD->evaluateValue()) {
if (VD->getType()->isIntegralType(C)) {
return (intptr_t)val->getInt().getRawData();
}
}
}
}
if (!address) {
auto Linkage = C.GetGVALinkageForVariable(VD);
// The decl was deferred by CodeGen. Force its emission.
Expand Down Expand Up @@ -1289,7 +1305,7 @@ namespace Cpp {
"Failed to GetVariableOffset:");
return 0;
}
return (intptr_t) jitTargetAddressToPointer<void*>(VDAorErr.get());
return (intptr_t)jitTargetAddressToPointer<void*>(VDAorErr.get());
}

return 0;
Expand Down
113 changes: 99 additions & 14 deletions unittests/CppInterOp/VariableReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,20 @@ TEST(VariableReflectionTest, GetVariableType) {
EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetVariableType(Decls[8])), "int[4]");
}

#define CODE \
int a; \
const int N = 5; \
class C { \
public: \
int a; \
double b; \
int *c; \
int d; \
static int s_a; \
} c; \
int C::s_a = 7 + N;
#define CODE \
int a; \
const int N = 5; \
static int S = N + 1; \
static const int SN = S + 1; \
class C { \
public: \
int a; \
double b; \
int* c; \
int d; \
static int s_a; \
} c; \
int C::s_a = 7 + SN;

CODE

Expand All @@ -215,11 +217,15 @@ TEST(VariableReflectionTest, GetVariableOffset) {
#undef Stringify
#undef CODE

EXPECT_EQ(7, Decls.size());

std::vector<Cpp::TCppScope_t> datamembers;
Cpp::GetDatamembers(Decls[2], datamembers);
Cpp::GetDatamembers(Decls[4], datamembers);

EXPECT_TRUE((bool) Cpp::GetVariableOffset(Decls[0])); // a
EXPECT_TRUE((bool) Cpp::GetVariableOffset(Decls[1])); // N
EXPECT_TRUE((bool)Cpp::GetVariableOffset(Decls[2])); // S
EXPECT_TRUE((bool)Cpp::GetVariableOffset(Decls[3])); // SN

EXPECT_EQ(Cpp::GetVariableOffset(datamembers[0]), 0);

Expand All @@ -230,7 +236,7 @@ TEST(VariableReflectionTest, GetVariableOffset) {
EXPECT_EQ(Cpp::GetVariableOffset(datamembers[3]),
((intptr_t) &(c.d)) - ((intptr_t) &(c.a)));

auto *VD_C_s_a = Cpp::GetNamed("s_a", Decls[2]); // C::s_a
auto* VD_C_s_a = Cpp::GetNamed("s_a", Decls[4]); // C::s_a
EXPECT_TRUE((bool) Cpp::GetVariableOffset(VD_C_s_a));
}

Expand Down Expand Up @@ -355,3 +361,82 @@ TEST(VariableReflectionTest, DISABLED_GetArrayDimensions) {
// EXPECT_TRUE(is_vec_eq(Cpp::GetArrayDimensions(Decls[1]), {1}));
// EXPECT_TRUE(is_vec_eq(Cpp::GetArrayDimensions(Decls[2]), {1,2}));
}

TEST(VariableReflectionTest, StaticConstExprDatamember) {
if (llvm::sys::RunningOnValgrind())
GTEST_SKIP() << "XFAIL due to Valgrind report";

#ifdef _WIN32
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
#endif

Cpp::CreateInterpreter();

Cpp::Declare(R"(
class MyClass {
public:
static constexpr int x = 3;
};
template<int i>
class MyTemplatedClass {
public:
static constexpr int x = i;
};
template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
};
template<typename... Eles>
struct Elements
: public integral_constant<int, sizeof...(Eles)> {};
)");

Cpp::TCppScope_t MyClass = Cpp::GetNamed("MyClass");
EXPECT_TRUE(MyClass);

std::vector<Cpp::TCppScope_t> datamembers;
Cpp::GetStaticDatamembers(MyClass, datamembers);
EXPECT_EQ(datamembers.size(), 1);

intptr_t offset = Cpp::GetVariableOffset(datamembers[0]);
EXPECT_EQ(3, *(int*)offset);

ASTContext& C = Interp->getCI()->getASTContext();
std::vector<Cpp::TemplateArgInfo> template_args = {
{C.IntTy.getAsOpaquePtr(), "5"}};

Cpp::TCppFunction_t MyTemplatedClass =
Cpp::InstantiateTemplate(Cpp::GetNamed("MyTemplatedClass"),
template_args.data(), template_args.size());
EXPECT_TRUE(MyTemplatedClass);

datamembers.clear();
Cpp::GetStaticDatamembers(MyTemplatedClass, datamembers);
EXPECT_EQ(datamembers.size(), 1);

offset = Cpp::GetVariableOffset(datamembers[0]);
EXPECT_EQ(5, *(int*)offset);

std::vector<Cpp::TemplateArgInfo> ele_template_args = {
{C.IntTy.getAsOpaquePtr()}, {C.FloatTy.getAsOpaquePtr()}};

Cpp::TCppFunction_t Elements = Cpp::InstantiateTemplate(
Cpp::GetNamed("Elements"), ele_template_args.data(),
ele_template_args.size());
EXPECT_TRUE(Elements);

EXPECT_EQ(1, Cpp::GetNumBases(Elements));

Cpp::TCppScope_t IC = Cpp::GetBaseClass(Elements, 0);

datamembers.clear();
Cpp::GetStaticDatamembers(IC, datamembers);
EXPECT_EQ(datamembers.size(), 1);

offset = Cpp::GetVariableOffset(datamembers[0]);
EXPECT_EQ(2, *(int*)offset);
}

0 comments on commit e4adda3

Please sign in to comment.