Skip to content

Commit 02ce20a

Browse files
authored
Merge pull request #232 from AntelopeIO/abi_fixes
Abi fixes
2 parents 9dc1399 + 74043a6 commit 02ce20a

10 files changed

+238
-85
lines changed

tests/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ add_unit_test( system_tests )
2121
add_unit_test( time_tests )
2222
add_unit_test( varint_tests )
2323

24-
add_test( NAME toolchain_tests COMMAND ${CMAKE_BINARY_DIR}/tools/toolchain-tester/toolchain-tester ${CMAKE_SOURCE_DIR}/tests/toolchain --cdt ${CMAKE_BINARY_DIR}/bin )
24+
add_test( NAME toolchain_tests COMMAND ${CMAKE_BINARY_DIR}/tools/toolchain-tester/toolchain-tester ${CMAKE_SOURCE_DIR}/tests/toolchain --cdt ${CMAKE_BINARY_DIR}/bin --verbose )
2525
set_property(TEST toolchain_tests PROPERTY LABELS toolchain_tests)
2626

2727
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unit/version_tests.sh ${CMAKE_BINARY_DIR}/tests/unit/version_tests.sh COPYONLY)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
3+
#include <eosio/eosio.hpp>
4+
#include <eosio/name.hpp>
5+
#include <eosio/singleton.hpp>
6+
#include <eosio/multi_index.hpp>
7+
8+
9+
10+
struct [[eosio::table]] out_of_class {
11+
uint64_t id;
12+
uint64_t primary_key() const { return id; }
13+
};
14+
typedef eosio::multi_index<"mi.config55"_n, out_of_class> out_of_class_index;
15+
using uout_of_class_index = eosio::multi_index<"mi.config551"_n, out_of_class>;
16+
17+
typedef eosio::singleton<"smpl.conf55"_n, eosio::name> smpl_config55;
18+
typedef eosio::singleton<"config55"_n, out_of_class> config55;
19+
typedef smpl_config55 smpl_config551;
20+
typedef config55 config551;
21+
using smpl_conf551 = eosio::singleton<"smpl.conf551"_n, eosio::name>;
22+
using config552 = eosio::singleton<"config552"_n, out_of_class>;
23+
using smpl_conf552 = smpl_conf551;
24+
using config553 = config551;
25+
26+
class [[eosio::contract("singleton_contract_simple2")]] singleton_contract_simple2 : public eosio::contract {
27+
public:
28+
using eosio::contract::contract;
29+
30+
[[eosio::action]]
31+
void whatever() {};
32+
33+
struct [[eosio::table]] inside_class {
34+
uint64_t id;
35+
uint64_t primary_key() const { return id; }
36+
};
37+
typedef eosio::singleton<"smpl.conf552"_n, eosio::name> smpl_conf552;
38+
typedef eosio::singleton<"config552"_n, inside_class> config552;
39+
typedef smpl_conf552 smpl_conf553;
40+
typedef config552 config553;
41+
using smpl_conf554 = eosio::singleton<"smpl.conf554"_n, eosio::name>;
42+
using config554 = eosio::singleton<"config554"_n, inside_class>;
43+
using smpl_conf555 = smpl_conf554;
44+
using config555 = config554;
45+
46+
47+
48+
typedef eosio::multi_index<"mi.config553"_n, inside_class> inside_class_index;
49+
using uinside_class_index = eosio::multi_index<"mi.config554"_n, inside_class>;
50+
};

tests/toolchain/abigen-pass/singleton_contract.abi

+48
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@
33
"version": "eosio::abi/1.2",
44
"types": [],
55
"structs": [
6+
{
7+
"name": "out_of_class",
8+
"base": "",
9+
"fields": [
10+
{
11+
"name": "id",
12+
"type": "uint64"
13+
}
14+
]
15+
},
16+
{
17+
"name": "out_of_class3",
18+
"base": "",
19+
"fields": [
20+
{
21+
"name": "id",
22+
"type": "uint64"
23+
}
24+
]
25+
},
626
{
727
"name": "tbl_config",
828
"base": "",
@@ -37,6 +57,34 @@
3757
"index_type": "i64",
3858
"key_names": [],
3959
"key_types": []
60+
},
61+
{
62+
"name": "config55",
63+
"type": "out_of_class",
64+
"index_type": "i64",
65+
"key_names": [],
66+
"key_types": []
67+
},
68+
{
69+
"name": "mi.config52",
70+
"type": "out_of_class3",
71+
"index_type": "i64",
72+
"key_names": [],
73+
"key_types": []
74+
},
75+
{
76+
"name": "smpl.conf5",
77+
"type": "name",
78+
"index_type": "i64",
79+
"key_names": [],
80+
"key_types": []
81+
},
82+
{
83+
"name": "smpl.config",
84+
"type": "name",
85+
"index_type": "i64",
86+
"key_names": [],
87+
"key_types": []
4088
}
4189
],
4290
"ricardian_clauses": [],

tests/toolchain/abigen-pass/singleton_contract.cpp

+29-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,33 @@
22
#include <eosio/eosio.hpp>
33
#include <eosio/name.hpp>
44
#include <eosio/singleton.hpp>
5+
6+
#include "exclude_from_abi.hpp"
57

68
using namespace eosio;
7-
9+
10+
struct [[eosio::table]] out_of_class2 {
11+
uint64_t id;
12+
uint64_t primary_key() const { return id; }
13+
};
14+
typedef eosio::multi_index<"mi.config5"_n, out_of_class2> out_of_class_index51;
15+
using uout_of_class_index51 = eosio::multi_index<"mi.config51"_n, out_of_class2>;
16+
17+
struct [[eosio::table, eosio::contract("singleton_contract")]] out_of_class3 {
18+
uint64_t id;
19+
uint64_t primary_key() const { return id; }
20+
};
21+
typedef eosio::multi_index<"mi.config52"_n, out_of_class3> out_of_class_index52;
22+
23+
typedef eosio::singleton<"smpl.conf5"_n, eosio::name> smpl_config5;
24+
typedef eosio::singleton<"config5"_n, out_of_class2> config5;
25+
typedef smpl_config5 smpl_config51;
26+
typedef config5 config51;
27+
using smpl_conf51 = eosio::singleton<"smpl.conf51"_n, eosio::name>;
28+
using config52 = eosio::singleton<"config52"_n, out_of_class2>;
29+
using smpl_conf52 = smpl_conf51;
30+
using config53 = config51;
31+
832
class [[eosio::contract("singleton_contract")]] singleton_contract : public contract {
933
public:
1034
using contract::contract;
@@ -17,5 +41,8 @@ class [[eosio::contract("singleton_contract")]] singleton_contract : public cont
1741
uint64_t x;
1842
};
1943

20-
typedef eosio::singleton<"config"_n, tbl_config> config;
44+
typedef eosio::singleton<"config"_n, tbl_config> config;
45+
typedef eosio::singleton<"smpl.config"_n, name> smpl_config;
46+
using smpl_config2 = smpl_config5;
47+
typedef config551 config2; //from exclude_from_abi.hpp
2148
};

tests/toolchain/abigen-pass/singleton_contract_simple.abi

-31
This file was deleted.

tests/toolchain/abigen-pass/singleton_contract_simple.cpp

-16
This file was deleted.

tests/toolchain/abigen-pass/singleton_contract_simple.json

-10
This file was deleted.

tools/include/eosio/abigen.hpp

+95-12
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,11 @@ namespace eosio { namespace cdt {
243243
ctables.insert(t);
244244
}
245245

246-
void add_table( uint64_t name, const clang::CXXRecordDecl* decl, bool force=false ) {
247-
if (force || decl->isEosioTable() && abigen::is_eosio_contract(decl, get_contract_name())) {
248-
abi_table t;
249-
t.type = decl->getNameAsString();
250-
t.name = name_to_string(name);
251-
_abi.tables.insert(t);
252-
}
246+
void add_table( uint64_t name, const clang::CXXRecordDecl* decl ) {
247+
abi_table t;
248+
t.type = decl->getNameAsString();
249+
t.name = name_to_string(name);
250+
_abi.tables.insert(t);
253251
}
254252

255253
void add_clauses( const std::vector<std::pair<std::string, std::string>>& clauses ) {
@@ -755,6 +753,7 @@ namespace eosio { namespace cdt {
755753
private:
756754
bool has_added_clauses = false;
757755
abigen& ag = abigen::get();
756+
const clang::CXXRecordDecl* contract_class = NULL;
758757

759758
public:
760759
explicit eosio_abigen_visitor(CompilerInstance *CI) {
@@ -799,18 +798,99 @@ namespace eosio { namespace cdt {
799798
}
800799
return true;
801800
}
801+
802+
bool is_same_type(const clang::Decl* decl1, const clang::CXXRecordDecl* decl2) const {
803+
if (!decl1 || !decl2)
804+
return false;
805+
if (decl1 == decl2)
806+
return true;
807+
808+
// checking if declaration is a typedef or using
809+
if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast<clang::TypedefNameDecl>(decl1)) {
810+
if (const auto* cur_type = typedef_decl->getUnderlyingType().getTypePtrOrNull()) {
811+
if (decl2 == cur_type->getAsCXXRecordDecl()) {
812+
return true;
813+
}
814+
}
815+
}
816+
817+
return false;
818+
}
819+
820+
bool defined_in_contract(const clang::ClassTemplateSpecializationDecl* decl) {
821+
822+
if (!contract_class) {
823+
// currently this is unreachable as we do not traverse non-main file translation units
824+
CDT_WARN("codegen_warning", decl->getLocation(), "contract class not found: " + ag.get_contract_name());
825+
return false;
826+
}
827+
828+
for (const clang::Decl* cur_decl : contract_class->decls()) {
829+
if (is_same_type(cur_decl, decl))
830+
return true;
831+
}
832+
833+
return false;
834+
}
835+
802836
virtual bool VisitDecl(clang::Decl* decl) {
803837
if (const auto* d = dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
804-
bool is_singleton = d->getName() == "singleton";
805-
if (d->getName() == "multi_index" || is_singleton) {
806-
ag.add_table(d->getTemplateArgs()[0].getAsIntegral().getExtValue(),
807-
d->getTemplateArgs()[1].getAsType().getTypePtr()->getAsCXXRecordDecl(), is_singleton);
838+
if (d->getName() == "multi_index" || d->getName() == "singleton") {
839+
// second template parameter is table type
840+
const auto* table_type = d->getTemplateArgs()[1].getAsType().getTypePtr()->getAsCXXRecordDecl();
841+
if ((table_type->isEosioTable() && ag.is_eosio_contract(table_type, ag.get_contract_name())) || defined_in_contract(d)) {
842+
// first parameter is table name
843+
ag.add_table(d->getTemplateArgs()[0].getAsIntegral().getExtValue(), table_type);
844+
if (table_type->isEosioTable())
845+
ag.add_struct(table_type);
846+
}
808847
}
809848
}
810849
return true;
811850
}
851+
inline void set_contract_class(const CXXRecordDecl* decl) {
852+
contract_class = decl;
853+
}
812854
};
855+
class contract_class_finder : public RecursiveASTVisitor<contract_class_finder> {
856+
private:
857+
abigen& ag = abigen::get();
858+
const clang::CXXRecordDecl* contract_class = nullptr;
859+
public:
860+
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl* cxx_decl) {
861+
if (cxx_decl->isEosioContract()) {
862+
bool is_eosio_contract = false;
863+
// on this point it could be just an attribute so let's check base classes
864+
for (const auto& base : cxx_decl->bases()) {
865+
if (const clang::Type *base_type = base.getType().getTypePtrOrNull()) {
866+
if (const auto* cur_cxx_decl = base_type->getAsCXXRecordDecl()) {
867+
if (cur_cxx_decl->getQualifiedNameAsString() == "eosio::contract") {
868+
is_eosio_contract = true;
869+
break;
870+
}
871+
}
872+
}
873+
}
874+
if (!is_eosio_contract)
875+
return true;
876+
877+
auto attr_name = cxx_decl->getEosioContractAttr()->getName();
878+
auto name = attr_name.empty() ? cxx_decl->getName() : attr_name;
879+
if (name == llvm::StringRef(ag.get_contract_name())) {
880+
contract_class = cxx_decl;
881+
return false;
882+
}
883+
}
813884

885+
return true;
886+
}
887+
inline bool contract_found() const {
888+
return contract_class != nullptr;
889+
}
890+
inline const clang::CXXRecordDecl* get_contract() const {
891+
return contract_class;
892+
}
893+
};
814894
class eosio_abigen_consumer : public ASTConsumer {
815895
private:
816896
eosio_abigen_visitor *visitor;
@@ -826,7 +906,10 @@ namespace eosio { namespace cdt {
826906
auto& f_mgr = src_mgr.getFileManager();
827907
auto main_fe = f_mgr.getFile(main_file);
828908
if (main_fe) {
829-
auto fid = src_mgr.getOrCreateFileID(f_mgr.getFile(main_file), SrcMgr::CharacteristicKind::C_User);
909+
contract_class_finder cf;
910+
cf.TraverseDecl(Context.getTranslationUnitDecl());
911+
if (cf.contract_found())
912+
visitor->set_contract_class(cf.get_contract());
830913
visitor->TraverseDecl(Context.getTranslationUnitDecl());
831914
}
832915
}

tools/include/eosio/error_emitter.hpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ namespace eosio { namespace cdt {
6161
#define CDT_ERROR(e, l, s) \
6262
get_error_emitter().emit_error(l, get_error_emitter().diags.get(e), s);
6363

64-
#define CDT_INTERNAL_ERROR(s) \
65-
std::cerr << s << "\n"; \
66-
throw internal_error_ex;
64+
#define CDT_INTERNAL_ERROR(s) \
65+
do { \
66+
std::cerr << s << "\n"; \
67+
throw internal_error_ex; \
68+
} while (false)

0 commit comments

Comments
 (0)