Skip to content

Commit e4adda3

Browse files
resolve static constexpr class attribute (#351)
* 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]>
1 parent 826be78 commit e4adda3

File tree

3 files changed

+122
-17
lines changed

3 files changed

+122
-17
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,10 @@ jobs:
310310
run: |
311311
brew update
312312
brew remove [email protected]
313-
brew remove unxip
313+
export ARCHITECHURE=$(uname -m)
314+
if [[ "$ARCHITECHURE" != "x86_64" ]]; then
315+
brew remove unxip
316+
fi
314317
# workaround for https://github.com/actions/setup-python/issues/577
315318
for pkg in $(brew list | grep '^python@'); do
316319
brew unlink "$pkg"
@@ -764,10 +767,11 @@ jobs:
764767
run: |
765768
brew update
766769
brew remove [email protected]
767-
brew remove unxip
768770
export ARCHITECHURE=$(uname -m)
769771
if [[ "$ARCHITECHURE" == "x86_64" ]]; then
770772
brew remove swiftlint
773+
else
774+
brew remove unxip
771775
fi
772776
# workaround for https://github.com/actions/setup-python/issues/577
773777
for pkg in $(brew list | grep '^python@'); do

lib/Interpreter/CppInterOp.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,22 @@ namespace Cpp {
12481248

12491249
if (!address)
12501250
address = I.getAddressOfGlobal(GD);
1251+
if (!address) {
1252+
if (!VD->hasInit()) {
1253+
#ifdef USE_CLING
1254+
cling::Interpreter::PushTransactionRAII RAII(&getInterp());
1255+
#endif // USE_CLING
1256+
getSema().InstantiateVariableDefinition(SourceLocation(), VD);
1257+
}
1258+
if (VD->hasInit() &&
1259+
(VD->isConstexpr() || VD->getType().isConstQualified())) {
1260+
if (const APValue* val = VD->evaluateValue()) {
1261+
if (VD->getType()->isIntegralType(C)) {
1262+
return (intptr_t)val->getInt().getRawData();
1263+
}
1264+
}
1265+
}
1266+
}
12511267
if (!address) {
12521268
auto Linkage = C.GetGVALinkageForVariable(VD);
12531269
// The decl was deferred by CodeGen. Force its emission.
@@ -1289,7 +1305,7 @@ namespace Cpp {
12891305
"Failed to GetVariableOffset:");
12901306
return 0;
12911307
}
1292-
return (intptr_t) jitTargetAddressToPointer<void*>(VDAorErr.get());
1308+
return (intptr_t)jitTargetAddressToPointer<void*>(VDAorErr.get());
12931309
}
12941310

12951311
return 0;

unittests/CppInterOp/VariableReflectionTest.cpp

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,20 @@ TEST(VariableReflectionTest, GetVariableType) {
191191
EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetVariableType(Decls[8])), "int[4]");
192192
}
193193

194-
#define CODE \
195-
int a; \
196-
const int N = 5; \
197-
class C { \
198-
public: \
199-
int a; \
200-
double b; \
201-
int *c; \
202-
int d; \
203-
static int s_a; \
204-
} c; \
205-
int C::s_a = 7 + N;
194+
#define CODE \
195+
int a; \
196+
const int N = 5; \
197+
static int S = N + 1; \
198+
static const int SN = S + 1; \
199+
class C { \
200+
public: \
201+
int a; \
202+
double b; \
203+
int* c; \
204+
int d; \
205+
static int s_a; \
206+
} c; \
207+
int C::s_a = 7 + SN;
206208

207209
CODE
208210

@@ -215,11 +217,15 @@ TEST(VariableReflectionTest, GetVariableOffset) {
215217
#undef Stringify
216218
#undef CODE
217219

220+
EXPECT_EQ(7, Decls.size());
221+
218222
std::vector<Cpp::TCppScope_t> datamembers;
219-
Cpp::GetDatamembers(Decls[2], datamembers);
223+
Cpp::GetDatamembers(Decls[4], datamembers);
220224

221225
EXPECT_TRUE((bool) Cpp::GetVariableOffset(Decls[0])); // a
222226
EXPECT_TRUE((bool) Cpp::GetVariableOffset(Decls[1])); // N
227+
EXPECT_TRUE((bool)Cpp::GetVariableOffset(Decls[2])); // S
228+
EXPECT_TRUE((bool)Cpp::GetVariableOffset(Decls[3])); // SN
223229

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

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

233-
auto *VD_C_s_a = Cpp::GetNamed("s_a", Decls[2]); // C::s_a
239+
auto* VD_C_s_a = Cpp::GetNamed("s_a", Decls[4]); // C::s_a
234240
EXPECT_TRUE((bool) Cpp::GetVariableOffset(VD_C_s_a));
235241
}
236242

@@ -355,3 +361,82 @@ TEST(VariableReflectionTest, DISABLED_GetArrayDimensions) {
355361
// EXPECT_TRUE(is_vec_eq(Cpp::GetArrayDimensions(Decls[1]), {1}));
356362
// EXPECT_TRUE(is_vec_eq(Cpp::GetArrayDimensions(Decls[2]), {1,2}));
357363
}
364+
365+
TEST(VariableReflectionTest, StaticConstExprDatamember) {
366+
if (llvm::sys::RunningOnValgrind())
367+
GTEST_SKIP() << "XFAIL due to Valgrind report";
368+
369+
#ifdef _WIN32
370+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
371+
#endif
372+
373+
Cpp::CreateInterpreter();
374+
375+
Cpp::Declare(R"(
376+
class MyClass {
377+
public:
378+
static constexpr int x = 3;
379+
};
380+
381+
template<int i>
382+
class MyTemplatedClass {
383+
public:
384+
static constexpr int x = i;
385+
};
386+
387+
template<typename _Tp, _Tp __v>
388+
struct integral_constant
389+
{
390+
static constexpr _Tp value = __v;
391+
};
392+
393+
template<typename... Eles>
394+
struct Elements
395+
: public integral_constant<int, sizeof...(Eles)> {};
396+
)");
397+
398+
Cpp::TCppScope_t MyClass = Cpp::GetNamed("MyClass");
399+
EXPECT_TRUE(MyClass);
400+
401+
std::vector<Cpp::TCppScope_t> datamembers;
402+
Cpp::GetStaticDatamembers(MyClass, datamembers);
403+
EXPECT_EQ(datamembers.size(), 1);
404+
405+
intptr_t offset = Cpp::GetVariableOffset(datamembers[0]);
406+
EXPECT_EQ(3, *(int*)offset);
407+
408+
ASTContext& C = Interp->getCI()->getASTContext();
409+
std::vector<Cpp::TemplateArgInfo> template_args = {
410+
{C.IntTy.getAsOpaquePtr(), "5"}};
411+
412+
Cpp::TCppFunction_t MyTemplatedClass =
413+
Cpp::InstantiateTemplate(Cpp::GetNamed("MyTemplatedClass"),
414+
template_args.data(), template_args.size());
415+
EXPECT_TRUE(MyTemplatedClass);
416+
417+
datamembers.clear();
418+
Cpp::GetStaticDatamembers(MyTemplatedClass, datamembers);
419+
EXPECT_EQ(datamembers.size(), 1);
420+
421+
offset = Cpp::GetVariableOffset(datamembers[0]);
422+
EXPECT_EQ(5, *(int*)offset);
423+
424+
std::vector<Cpp::TemplateArgInfo> ele_template_args = {
425+
{C.IntTy.getAsOpaquePtr()}, {C.FloatTy.getAsOpaquePtr()}};
426+
427+
Cpp::TCppFunction_t Elements = Cpp::InstantiateTemplate(
428+
Cpp::GetNamed("Elements"), ele_template_args.data(),
429+
ele_template_args.size());
430+
EXPECT_TRUE(Elements);
431+
432+
EXPECT_EQ(1, Cpp::GetNumBases(Elements));
433+
434+
Cpp::TCppScope_t IC = Cpp::GetBaseClass(Elements, 0);
435+
436+
datamembers.clear();
437+
Cpp::GetStaticDatamembers(IC, datamembers);
438+
EXPECT_EQ(datamembers.size(), 1);
439+
440+
offset = Cpp::GetVariableOffset(datamembers[0]);
441+
EXPECT_EQ(2, *(int*)offset);
442+
}

0 commit comments

Comments
 (0)