NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
class_test.cpp
Go to the documentation of this file.
1//#ifdef BUILD_UNITTEST
2//
3//#include "warning_push.h"
4//
5//
6//#include "clang/Tooling/Tooling.h"
7//#include "clang/Tooling/CommonOptionsParser.h"
8//
9//#include <gtest/gtest.h>
10//#include "warning_pop.h"
11//
12//#include "jit.h"
13//
14//
15//using namespace newlang;
16//
17//static llvm::cl::OptionCategory MyToolCategory("my-tool options");
18//
42//
43//
44//class MyPrinter : public clang::ast_matchers::MatchFinder::MatchCallback {
45//public:
46//
47// clang::MangleContext *m_mangle_ctx;
48// std::vector<std::string > mangle_list;
49//
50// MyPrinter() : m_mangle_ctx(nullptr) {
51// }
52//
53// ~MyPrinter() {
54// if (m_mangle_ctx) {
55// delete m_mangle_ctx;
56// m_mangle_ctx = nullptr;
57// }
58// }
59//
60// virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) {
61//
62// clang::ASTContext *ctx = Result.Context;
63// ASSERT(ctx);
64//
65// if (!m_mangle_ctx) {
66// m_mangle_ctx = ctx->createMangleContext();
67// }
68// ASSERT(m_mangle_ctx);
69//
70//
71// std::string name;
72// llvm::raw_string_ostream raw(name);
73//
74// // llvm::outs() << Result.Nodes.getMap().size() << " nodes matched\n";
75// // Context->DumpRecordLayout()
76//
77//
78// if (const auto decl = Result.Nodes.getNodeAs<clang::Decl>("decl")) {
79// name = decl->getDeclKindName();
80// if (name.compare("LinkageSpec") == 0
81// || name.compare("Namespace") == 0
82// || name.compare("ParmVar") == 0
83// || name.compare("Empty") == 0
84// || name.compare("TranslationUnit") == 0
85// || name.compare("Typedef") == 0
86// ) {
87// return;
88// }
89// name.clear();
90// }
91//
92// if (const auto decl = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("decl")) {
93// // Ignore
94// // Определение класса, ссылка на класс (предварительное определение), в том числе скрытая
95// if (decl->isReferenced() || decl->isImplicit() || decl->isClass()) {
96// return;
97// }
98// }
99//
100// if (const auto decl = Result.Nodes.getNodeAs<clang::CXXDestructorDecl>("decl")) {
101// // decl->dump();
102// // //
103// // // ASSERT(mangler->shouldMangleDeclName(decl));
104// // // mangler->mangleCXXDtorThunk(clang::GlobalDecl(decl), raw);
105// // // LOG_DEBUG("CXXDestructorDecl %s", name.c_str());
106// // //
107// // mangle_list.push_back(decl->getNameAsString());
108// } else if (const auto decl = Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("decl")) {
109// // decl->dump();
110// //
111// // mangle_list.push_back(decl->getNameAsString());
112// //
113// // //
114// // // ASSERT(mangler->shouldMangleDeclName(decl));
115// // // mangler->mangleCtorBlock(decl, raw);
116// // // LOG_DEBUG("CXXConstructorDecl %s", name.c_str());
117// // //
118// } else if (const auto decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("decl")) {
119// if (m_mangle_ctx->shouldMangleCXXName(decl)) {
120// m_mangle_ctx->mangleCXXName(decl, raw);
121//
122// if (name.compare("_Znwm") == 0
123// || name.compare("_Znam") == 0
124// || name.compare("_ZdlPv") == 0
125// || name.compare("_ZdaPv") == 0
126// || name.rfind("SEOS_") != std::string::npos
127// || name.rfind("SEOS0_") != std::string::npos //name::ns_class::operator=(name::ns_class&&)
128// || name.rfind("SERKS_") != std::string::npos //class_body::operator=(class_body const&)
129// || name.rfind("SERKS0_") != std::string::npos //name::ns_class::operator=(name::ns_class const&)
130// ) {
131// return;
132// }
133// } else {
134// name = decl->getNameAsString();
135// }
136// // LOG_DEBUG("FunctionDecl %s", name.c_str());
137// mangle_list.push_back(name);
138//
139// } else if (const auto decl = Result.Nodes.getNodeAs<clang::VarDecl>("decl")) {
140// if (m_mangle_ctx->shouldMangleCXXName(decl)) {
141// m_mangle_ctx->mangleCXXName(decl, raw);
142// } else {
143// name = decl->getNameAsString();
144// }
145// // LOG_DEBUG("%s", decl->getNameAsString().c_str());
146// mangle_list.push_back(name);
147//
148// } else if (const auto decl = Result.Nodes.getNodeAs<clang::FieldDecl>("decl")) {
149// if (m_mangle_ctx->shouldMangleCXXName(decl)) {
150// m_mangle_ctx->mangleCXXName(decl, raw);
151// } else {
152// name = decl->getNameAsString();
153// }
154// // LOG_DEBUG("FieldDecl %s", name.c_str());
155// mangle_list.push_back(name);
156//
157// } else if (const auto decl = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("decl")) {
158//
159// decl->dump();
160// LOG_RUNTIME("CXXRecordDecl");
161//
162// } else if (const auto decl = Result.Nodes.getNodeAs<clang::Decl>("decl")) {
163//
164// // decl->dump();
165// // LOG_RUNTIME("DeclKindName: %s", decl->getDeclKindName());
166//
167// } else {
168// for (const auto &elem : Result.Nodes.getMap()) {
169//
170// LOG_DEBUG("%s", elem.first.c_str());
171// }
172// LOG_RUNTIME("ELSE");
173// }
174// }
175//};
176//
177//
178//const char * func_text = \
179// "int func(int arg, char, signed char, unsigned char);\n"
180// "int func(signed int arg, unsigned int arg2, signed short int arg3, unsigned short int arg4);\n"
181// "int func(const signed int arg, const unsigned int arg2);\n"
182// "int func(int &arg, int &&arg2, int *arg3); //, int **arg4, int **arg5, int ****arg6 \n"
183// "int func(const int &arg, const int &&arg2, const int *arg3); //, const int **arg4, const int **arg5, const int ****arg6 \n"
184// "void func(int arg, double arg2);\n"
185// "extern \"C\" int printf(const char * format, ...);\n"
186// "const int value_const=0;\n"
187// "namespace n { const int value_const=0; };\n"
188// "int value_value;\n"
189// "extern \"C\" int value_c;\n"
190// "namespace n { int value; };\n"
191// "class header_only;\n"
192// "class class_body{\n"
193// " int field;\n"
194// " class_body(){};\n"
195// " virtual ~class_body(){};\n"
196// " void method_header();\n"
197// " void method_body(){};\n"
198// " static header_only * static_call(header_only *);"
199// "};\n"
200// "namespace name {\n"
201// "int func(int arg);\n"
202// "class ns_class {"
203// " void method();"
204// " virtual void method_v();"
205// " virtual void method_v2()=0;"
206// " static void method_static();"
207// "};"
208// "};\n";
209//
210//
212// * Импорт обычных и вирутальных
213// */
214//
215//std::vector <const char *> mangle_name = {
216// "_Z4funcicah",
217// "_Z4funcijst",
218// "_Z4funcij",
219// "_Z4funcRiOiPi", //_Z4funcRiOiPiPS1_S2_PPS2_
220// "_Z4funcRKiOS_PS_", //_Z4funcRKiOS_PS_PS2_S3_PPS3_
221// "_Z4funcid",
222// "printf",
223// "_ZL11value_const",
224// "_ZN1nL11value_constE",
225// "value_value",
226// "value_c",
227// "_ZN1n5valueE",
228// "_ZN10class_body5fieldE",
229// "_ZN10class_body13method_headerEv",
230// "_ZN10class_body11method_bodyEv",
231// "_ZN10class_body11static_callEP11header_only",
232// "_ZN4name4funcEi",
233// "_ZN4name8ns_class6methodEv",
234// "_ZN4name8ns_class8method_vEv",
235// "_ZN4name8ns_class9method_v2Ev",
236// "_ZN4name8ns_class13method_staticEv",
237//};
238//
239//#define ATTR
241//
243//ATTR int func1(int arg, char c1, signed char c2, unsigned char c3) {
244//
245// return arg;
246//}
247//
249//ATTR int func2(signed int arg, unsigned int arg2, signed short int arg3, unsigned short int arg4) {
250//
251// return arg;
252//}
253//
255//ATTR int func3(int &arg, int &&arg2, int *arg3) {
256//
257// return arg;
258//}
259//
261//ATTR int func4(const int &arg, const int &&arg2, const int *arg3) {
262//
263// return arg;
264//}
265//
267//ATTR void func5(signed long long int arg, double arg2) {
268//}
269//
270//namespace ns {
271//
272// double func6(signed long long int arg1, const unsigned short arg2) {
273// return arg1*arg2;
274// };
275//
276// namespace ns {
277//
278// float func7(unsigned long long int arg1, double arg2) {
279// return arg1 + arg2;
280// };
281//
282// }
283// /* ns::value_const^: Int32*/
284// ATTR signed int value_const;
285//
286// /* ::ns::value: Int32 */
287// ATTR int value;
288//
289// /* ::ns::value_ptr: &* Int32 */
290// static ATTR int * value_ptr;
291//}
292//
294//ATTR int value_value;
296//extern "C" {
297//
298// ATTR int value_c;
299//}
300//
301//std::string toCXXProto(const TermPtr term) {
302//
303// int i1 = ns::value_const;
304// int i2 = ns::value;
305//
306// ASSERT(term);
307// ASSERT(isNativeName(term->m_text)); // %
308// // ASSERT(isStaticName(term->m_text)); // ::
309// ASSERT(!isFieldName(term->m_text)); // .
310// ASSERT(!isLocalName(term->m_text)); // $
311//
312// ASSERT(term->m_type);
313// ObjType res_type = RunTime::BaseTypeFromString(nullptr, term->m_type->m_text);
314//
315// std::string cpp_prototype;
316//
317// // Real name
318// std::string name = &term->m_text[1];
319// std::string suffix;
320// bool is_static = (isStaticName(name) && !term->isCall());
321// bool is_global = (isGlobalScope(name) && !term->isCall());
322//
323// if (isStaticName(name)) {
324// if (isGlobalScope(name)) {
325// name = name.substr(2);
326// }
327// ASSERT(!isGlobalScope(name));
328// while (isStaticName(name)) {
329// cpp_prototype += "namespace ";
330// cpp_prototype += name.substr(0, name.find("::"));
331// cpp_prototype += " { ";
332// suffix += "; }";
333// name = name.substr(name.find("::") + 2);
334// }
335// }
336//
337// if (is_static && !is_global) {
338// cpp_prototype += "static ";
339// }
340//
341// cpp_prototype += toCXXType(res_type, false);
342// cpp_prototype += " ";
343//
344// if (term->m_type->m_ref) {
345// cpp_prototype += toCXXRef(term->m_type->m_ref->m_text);
346// cpp_prototype += " ";
347// }
348//
349// ASSERT(!name.empty());
350// cpp_prototype += name;
351//
352// if (term->isCall()) {
353// // Функция
354// cpp_prototype += "(";
355// for (int i = 0; i < term->size(); i++) {
356// if (i) {
357// cpp_prototype += ", ";
358// }
359// TermPtr arg = term->at(i).second;
360//
361// if (!arg->m_type) {
362// LOG_RUNTIME("Type arg %d not defined '%s'", i, term->toString().c_str());
363// }
364//
365// // LOG_DEBUG("%s", arg->m_type_name.c_str());
366// ObjType arg_type = RunTime::BaseTypeFromString(nullptr, arg->m_type->m_text);
367// if (arg->m_type->m_ref) {
368// cpp_prototype += " ";
369// cpp_prototype += toCXXRef(arg->GetType()->m_ref->m_text);
370// }
371// if (arg->m_type->m_is_const) {
372// cpp_prototype += "const ";
373// }
374// cpp_prototype += toCXXType(arg_type, false);
375// }
376// cpp_prototype += ")";
377//
378// if (term->m_is_const) {
379// cpp_prototype.insert(0, " const");
380// }
381// }
382//
383// if (term->m_is_const && !term->isCall()) {
384// if (isStringChar(res_type)) {
385// cpp_prototype += "=\"\"";
386// } else if (isStringWide(res_type)) {
387// cpp_prototype += "=L\"\"";
388// } else if (isArithmeticType(res_type)) {
389// cpp_prototype += "=0";
390// } else {
391// cpp_prototype += "=nullptr";
392// }
393// }
394//
395// if (term->m_is_const) {
396// cpp_prototype += "const ";
397// }
398//
399// cpp_prototype += suffix;
400// cpp_prototype += ";";
401//
402// return cpp_prototype;
403//}
404//
405//std::string toCXXProto(std::string name) {
406// std::string result;
407// name += ":= _";
408// TermPtr term = Parser::ParseString(name, nullptr);
409//
410// return toCXXProto(term->Left());
411//}
412//
414// * void foo() {} // _Z3foov == _Z3foov
415// * void foo(int a){} // _Z3fooi == _Z3fooi
416// * double foo(double d){return 0;} // _Z3food == _Z3food
417// * void foo(int a, double d) {} // _Z3fooid == _Z3fooid
418// * namespace test {
419// * void foo(int a) {} // _ZN4test3fooEi == _ZN4test3fooEi
420// * double foo(double d) {return 0;} //_ZN4test3fooEd == _ZN4test3fooEd
421// * }
422// *
423// *
424//Posted on 25. October 2019 by JP Lehr
425//Name mangling in C++ with Clang and GCC
426//
427//I recently came across the question whether it is possible to use lists of mangled function names (generated with a Clang-based tool) in a GCC compiler plugin. I am aware that name mangling is compiler dependent and not standardized, yet I had hopes that this would be something I can achieve.
428//
429//I started with a quick web search. That, however, did not lead to satisfying answers, as I was still unsure whether it could actually work. Most of the answers I found were about the status when GCC 5 came out. Now, I am working with GCC 8 and things may change.
430//
431//So, I continued by implementing very basic test cases to start this off experimentally, i.e., to get an idea on whether more reading about all this is worth my time. Codes were as simple as the one shown below. The first name in the comment is the GCC mangled name (g++ 8.3) and the second name is the Clang mangled name (clang++ 9.0).
432//
433//void foo() {} // _Z3foov == _Z3foov
434//void foo(int a){} // _Z3fooi == _Z3fooi
435//double foo(double d){return 0;} // _Z3food == _Z3food
436//void foo(int a, double d) {} // _Z3fooid == _Z3fooid
437//namespace test {
438// void foo(int a) {} // _ZN4test3fooEi == _ZN4test3fooEi
439// double foo(double d) {return 0;} //_ZN4test3fooEd == _ZN4test3fooEd
440//}
441//
442// * So, at least given this small set of samples, there do not seem to be differences.
443// * I did similar tiny-scale experiments for classes and templates. All of them were simple enough to not discover differences.
444// * Eventually, I applied both compilers to a basic C++ implementation of the game of life (sources) and filtered the object code
445// * to get a list of all the function names in the resulting binary.
446// * I compiled at optimization level 0 to let the compiler not do inlining or other optimizations.
447// * I’m sure listing all functions in an object can be done much easier (e.g., using nm),
448// * but this is what I did (accordingly for a version of the code compiled with g++):
449// *
450// * objdump -d clang++90.GoL | grep ">:" | awk '{ print $2 }' | sed -e "s/://" | uniq | sort > clang++90_names
451// *
452// * Inspecting both lists of generated function names, I found differences. In particular, in the mangled name
453// * of the constructor of the GameOfLife class.
454// *
455// * class GameOfLife {
456// * public:
457// * GameOfLife(int numX, int numY) : dimX(numX),
458// * dimY(numY),
459// * gridA(dimXdimY,
460// * gridB(dimXdimY){}
461// * // other members are omitted
462// * };
463// *
464// * The constructor is mangled into _ZN10GameOfLifeC1Eii by GCC and into _ZN10GameOfLifeC2Eii by Clang.
465// * The difference is the C1 vs. the C2 in the name.
466// *
467// * <ctor-dtor-name> ::= C1 # complete object constructor
468// ::= C2 # base object constructor
469// ::= C3 # complete object allocating constructor
470// ::= D0 # deleting destructor
471// ::= D1 # complete object destructor
472// ::= D2 # base object destructor
473// *
474//
475// First of all, choose different names for different things.
476//
477// Second, the non-static member function pointer should be declared as:
478//
479// void (classA::*memfun)(void); //note the syntax
480//
481// then the assignment should be as:
482//
483// memfun = &classA::function_a; //note &, and note the syntax on both sides.
484//
485// and you call this as:
486//
487// classA instance;
488// (instance.*memfun)();
489//
490// That is what you do in C++03.
491//
492// However, in C++11, you can use std::function as well. Here is how you do it:
493//
494// std::function<void(classA*)> memfun(&classA::function_a);
495//
496// and you call this as:
497//
498// classA instance;
499// memfun(&instance);
500//
501// *
502// */
503//
504//std::vector<std::string> GetMangledNames(const std::string input_source) {
505//
506// clang::CompilerInstance compilerInstance;
507//
508// constexpr int COUNT = 3;
509// int argc = COUNT;
510// const char *argv[COUNT] = {"", "clang_mangled_names.cpp", "--"};
511//
512// auto OptionsParser = clang::tooling::CommonOptionsParser::create(argc, argv, MyToolCategory, llvm::cl::OneOrMore);
513// if (!OptionsParser) {
514// LOG_RUNTIME("Fail create OptionsParser!");
515// }
516//
517// clang::tooling::ClangTool Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList());
518//
519// Tool.mapVirtualFile("clang_mangled_names.cpp", clang::StringRef(input_source));
520//
521// MyPrinter Printer;
522// auto functionMatcher = clang::ast_matchers::decl(clang::ast_matchers::anything()).bind("decl");
523//
524// clang::ast_matchers::MatchFinder Finder;
525// Finder.addMatcher(functionMatcher, &Printer);
526//
527// if (0 != Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get())) {
528//
529// LOG_RUNTIME("Fail run FrontendAction!");
530// }
531//
532// // if (Printer.mangle_list.size() != names.size()) {
533// // LOG_RUNTIME("Fail matching result!");
534// // }
535// return Printer.mangle_list;
536//}
537//
538//std::string GetMangledString(const std::string_view source) {
539// std::vector<std::string> list = GetMangledNames(toCXXProto(std::string(source)));
540// if (list.size() != 1) {
541// LOG_RUNTIME("Source '%s' not a single mangled name!", source.begin());
542// }
543// return list[0];
544//}
545//
546//TEST(Class, MangledSimple) {
547//
548// std::string name;
549// std::string mandled;
550//
551// LLVMLoadLibraryPermanently(nullptr);
552//
553// EXPECT_TRUE(LLVMSearchForAddressOfSymbol("printf"));
554// EXPECT_TRUE(LLVMSearchForAddressOfSymbol("fopen"));
555//
556// ASSERT_STREQ("signed int value_c;", toCXXProto("%value_c:Int32").c_str());
557// ASSERT_NO_THROW(mandled = GetMangledString("%value_c:Int32"));
558// ASSERT_STREQ("value_c", mandled.c_str());
559// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
560//
561//
562// ASSERT_STREQ("signed int func1(signed int, char, signed char, unsigned char);",
563// toCXXProto("%::func1(arg:Int32, arg:Int8, arg:Char, arg:Byte): Int32").c_str());
564// ASSERT_NO_THROW(mandled = GetMangledString("%::func1(arg:Int32, arg:Int8, arg:Char, arg:Byte): Int32"));
565// ASSERT_STREQ("_Z5func1icah", mandled.c_str());
566// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
567//
568//
569// ASSERT_STREQ("signed int func2(signed int, unsigned int, signed short, unsigned short);",
570// toCXXProto("%::func2(arg:Int32, arg2:DWord, arg3:Int16, arg4:Word): Int32").c_str());
571// ASSERT_NO_THROW(mandled = GetMangledString("%::func2(arg:Int32, arg2:DWord, arg3:Int16, arg4:Word): Int32"));
572// ASSERT_STREQ("_Z5func2ijst", mandled.c_str());
573// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
574//
575//
576// ASSERT_STREQ("void func5(signed long long int, double);",
577// toCXXProto("%::func5(arg:Int64, arg2:Double):None").c_str());
578// ASSERT_NO_THROW(mandled = GetMangledString("%::func5(arg:Int64, arg2:Double):None"));
579// ASSERT_STREQ("_Z5func5xd", mandled.c_str());
580// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
581//
582//
583// ASSERT_STREQ("namespace ns { double func6(signed long long int, const unsigned short); };",
584// toCXXProto("%::ns::func6(arg:Int64, arg2: Word^):Double").c_str());
585// ASSERT_NO_THROW(mandled = GetMangledString("%::ns::func6(arg:Int64, arg2:Word^):Double"));
586// ASSERT_STREQ("_ZN2ns5func6Ext", mandled.c_str());
587// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
588//
589//
590// ASSERT_STREQ("namespace ns { namespace ns { float func7(unsigned long long int, double); }; };",
591// toCXXProto("%ns::ns::func7(arg:DWord64, arg2:Double):Single").c_str());
592// ASSERT_NO_THROW(mandled = GetMangledString("%ns::ns::func7(arg:DWord64, arg2:Double):Single"));
593// ASSERT_STREQ("_ZN2ns2ns5func7Eyd", mandled.c_str());
594// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
595//
596//
597// ASSERT_STREQ("namespace ns { signed int value_const; };", toCXXProto("%::ns::value_const:Int32").c_str());
598// ASSERT_NO_THROW(mandled = GetMangledString("%::ns::value_const:Int32"));
599// ASSERT_STREQ("_ZN2ns11value_constE", mandled.c_str());
600// //"_ZN2nsL11value_constE"
601// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
602//
603//
604// ASSERT_STREQ("signed int value_value;", toCXXProto("%value_value:Int32").c_str());
605// ASSERT_NO_THROW(mandled = GetMangledString("%value_value:Int32"));
606// ASSERT_STREQ("value_value", mandled.c_str());
607// ASSERT_TRUE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
608//
609// name = "%ns::value_ptr: &* Int32";
610// ASSERT_STREQ("namespace ns { static signed int * value_ptr; };", toCXXProto(name).c_str());
611// ASSERT_NO_THROW(mandled = GetMangledString(name)) << name;
612// ASSERT_STREQ("_ZN2nsL9value_ptrE", mandled.c_str());
613// //_ZN2ns9value_ptrE
614// // Статической переменной нет в таблице символов!!!!
615// ASSERT_FALSE(LLVMSearchForAddressOfSymbol(mandled.c_str())) << mandled;
616//
617//
618// // ASSERT_NO_THROW(list = GetMangledNames("%::class_body.field:Int32"));
619// // ASSERT_EQ(1, list.size()) << Dump(list);
620// // ASSERT_STREQ("", list[0].c_str()) << list[0];
621// //
622// // ASSERT_NO_THROW(list = GetMangledNames("%::class_body.method():Int32"));
623// // ASSERT_EQ(1, list.size()) << Dump(list);
624// // ASSERT_STREQ("", list[0].c_str()) << list[0];
625//
626//
627//}
628//
629//struct class_body {
630// int field;
631// static char static_field;
632//
633// class_body() {
634// }
635//
636// class_body(int, int *) {
637// }
638//
639// virtual ~class_body() {
640// }
641//
642// void method_body() {
643// }
644//
645// int method_body(int arg) {
646// return arg;
647// }
648//
649// double method_body(double arg) {
650// return arg;
651// }
652//
653// int method_body2(int arg) {
654// return arg * 2;
655// }
656//
657// virtual double method_virt() {
658// return 3.14;
659// }
660//
661// static float method_static() {
662// return 3.1415;
663// }
664//};
665//
667// * У нативных классов можно импортировть только публичные не статические <не виртуальные?????> методы!!!
668// * Прегруженные методы пока под вопросом?
669// * Поля использовать нельзя из-за их определения как смещения в объекте, а не адресом в памяти, как тело функции.
670// * Статические поля и методы использовать нельзя из-за отсутсвия на них ссылки в глобальной таблице имен.
671// * У виртуальных функций есть адрес в глобальной таблице имен, но как их вызывать, пока не понятно.
672// * Причем обычные методы, если на них нет ссылки (не используются), могут удаляться из приложения линкером.
673// */
674//
675//const char * cls = ""
676// "class class_body {"
677// "public:"
678// " int field;"
679// ""
680// "static char static_field;"
681// ""
682// " class_body();"
683// ""
684// " class_body(int, int *);"
685// ""
686// " virtual ~class_body();"
687// ""
688// " void method_body();"
689// ""
690// " int method_body(int arg);"
691// ""
692// " double method_body(double arg);"
693// ""
694// " int method_body2(int arg);"
695// ""
696// " virtual double method_virt();"
697// ""
698// " static float method_static();"
699// "};"
700// "";
701//
702//std::string FindMandledField(std::string source, std::vector<std::string> &list) {
703//
704// source += ":= _";
705// TermPtr term = Parser::ParseString(source, nullptr);
706// ASSERT(term->m_left);
707//
708// std::vector<std::string> names = GetMangledNames(toCXXProto(term->m_left));
709// if (names.size() != 1) {
710// LOG_RUNTIME("Source '%s' not a single mangled name!", source.c_str());
711// }
712// std::string mangled = names[0];
713//
714// std::string search = term->m_left->m_text.substr(1);
715// if (isGlobalScope(search)) {
716// search = search.substr(2);
717// }
718// ASSERT(!isStaticName(search));
719//
720// std::string arg_types("E");
721// if (term->m_left->isCall()) {
722// arg_types += mangled.substr(mangled.find(search) + search.size());
723// }
724//
725// for (auto &elem : list) {
726// if (elem.find(search) != std::string::npos && (arg_types.empty() || elem.find(arg_types) != std::string::npos)) {
727// return elem;
728// }
729// }
730// LOG_RUNTIME("Filed '%s' (%s)(%s) not found!", term->m_left->m_text.c_str(), search.c_str(), arg_types.c_str());
731//}
732//
733//template<typename OUT, typename IN>
734//OUT ForceCast(IN in) {
735//
736// union {
737// IN in;
738// OUT out;
739// }
740// u = {in};
741//
742// return u.out;
743//};
744//
745//char class_body::static_field = 0;
746//
747//TEST(Class, MangledClass) {
748//
749// class_body data;
750// data.field = 0;
751// data.method_body();
752// data.method_body(0);
753// data.method_body(0.0);
754// data.method_body2(0);
755// data.method_static();
756//
757// std::string name;
758// std::vector<std::string> list;
759//
760// void *cast;
761// LLVMLoadLibraryPermanently(nullptr);
762//
763// ASSERT_NO_THROW(list = GetMangledNames(cls));
764// ASSERT_EQ(8, list.size()) << Dump(list);
765//
766// ASSERT_STREQ("void method_body();", toCXXProto("%method_body(): None").c_str());
767// ASSERT_NO_THROW(name = GetMangledString("%method_body(): None"));
768// ASSERT_STREQ("_Z11method_bodyv", name.c_str());
769// ASSERT_NO_THROW(name = FindMandledField("%method_body():None", list)) << Dump(list);
770// EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
771//
772// ASSERT_STREQ("signed int method_body(signed int);", toCXXProto("%method_body(arg:Int32): Int32").c_str());
773// ASSERT_NO_THROW(name = GetMangledString("%method_body(arg:Int32): Int32"));
774// ASSERT_STREQ("_Z11method_bodyi", name.c_str());
775// ASSERT_NO_THROW(name = FindMandledField("%method_body(arg:Int32): Int32", list)) << Dump(list);
776// EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
777//
778// ASSERT_STREQ("double method_body(double);", toCXXProto("%method_body(arg:Double): Double").c_str());
779// ASSERT_NO_THROW(name = GetMangledString("%method_body(arg:Double): Double"));
780// ASSERT_STREQ("_Z11method_bodyd", name.c_str());
781// ASSERT_NO_THROW(name = FindMandledField("%method_body(arg:Double): Double", list)) << Dump(list);
782// EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
783//
786//
787// ASSERT_STREQ("signed int method_body2(signed int);", toCXXProto("%method_body2(arg:Int32): Int32").c_str());
788// ASSERT_NO_THROW(name = GetMangledString("%method_body2(arg:Int32): Int32"));
789// ASSERT_STREQ("_Z12method_body2i", name.c_str());
790// ASSERT_NO_THROW(name = FindMandledField("%method_body2(arg:Int32): Int32", list)) << Dump(list);
791// EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
792//
793// cast = ForceCast<void *>(&class_body::method_body2);
794// ASSERT_EQ(cast, LLVMSearchForAddressOfSymbol(name.c_str()));
795//
796// ASSERT_STREQ("double method_virt();", toCXXProto("%method_virt(): Double").c_str());
797// ASSERT_NO_THROW(name = GetMangledString("%method_virt(): Double"));
798// ASSERT_STREQ("_Z11method_virtv", name.c_str());
799// ASSERT_NO_THROW(name = FindMandledField("%method_virt(): Double", list)) << Dump(list);
800// EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
801//
804//
805// // ASSERT_STREQ("float method_static();", toCXXProto("%::method_static(): Single").c_str());
806// // ASSERT_NO_THROW(name = GetMangledString("%::method_static(): Single"));
807// // ASSERT_STREQ("_Z13method_staticv", name.c_str());
808// // ASSERT_NO_THROW(name = FindMandledField("%::method_static(): Single", list)) << Dump(list);
809// // EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
810//
811// // ASSERT_STREQ("signed int field;", toCXXProto("%field: Int32").c_str());
812// // ASSERT_NO_THROW(name = GetMangledString("%field: Int32"));
813// // ASSERT_STREQ("field", name.c_str());
814// // ASSERT_NO_THROW(name = FindMandledField("%field: Int32", list)) << Dump(list);
815// // EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
816// // EXPECT_TRUE(dlsym(nullptr, name.c_str()));
817//
818//
819// ASSERT_STREQ("signed int static_field;", toCXXProto("%::static_field: Int32").c_str());
820// ASSERT_NO_THROW(name = GetMangledString("%::static_field: Int32"));
821// ASSERT_STREQ("static_field", name.c_str());
822// ASSERT_NO_THROW(name = FindMandledField("%::static_field: Int32", list)) << Dump(list);
823// EXPECT_TRUE(LLVMSearchForAddressOfSymbol(name.c_str())) << name << "\n" << Dump(list);
824//
825//}
826//
956//
957//void test_void_func() {
958//}
959//
960//const int test_void_val = 0;
961//
962//TEST(Class, Symbols) {
963//
964// auto rt = RunTime::Init();
965//
966//
967// EXPECT_TRUE(LLVMSearchForAddressOfSymbol("printf"));
968// EXPECT_TRUE(LLVMSearchForAddressOfSymbol("fopen"));
969//
970// EXPECT_FALSE(LLVMSearchForAddressOfSymbol("test_void_func"));
971// EXPECT_FALSE(LLVMSearchForAddressOfSymbol("test_void_val"));
972//
973// LLVMAddSymbol("test_void_func", (void *) &test_void_func);
974// LLVMAddSymbol("test_void_val", (void *) &test_void_val);
975//
976// EXPECT_TRUE(LLVMSearchForAddressOfSymbol("test_void_func"));
977// EXPECT_TRUE(LLVMSearchForAddressOfSymbol("test_void_val"));
978//
979// EXPECT_EQ(&test_void_func, LLVMSearchForAddressOfSymbol("test_void_func"));
980// EXPECT_EQ(&test_void_val, LLVMSearchForAddressOfSymbol("test_void_val"));
981//}
982//
983//
984//
1446//
1447//
1514//#endif // BUILD_UNITTEST