Skip to content

Commit

Permalink
Merge pull request #232 from AntelopeIO/abi_fixes
Browse files Browse the repository at this point in the history
Abi fixes
  • Loading branch information
dimas1185 authored Oct 5, 2023
2 parents 9dc1399 + 74043a6 commit 02ce20a
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 85 deletions.
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ add_unit_test( system_tests )
add_unit_test( time_tests )
add_unit_test( varint_tests )

add_test( NAME toolchain_tests COMMAND ${CMAKE_BINARY_DIR}/tools/toolchain-tester/toolchain-tester ${CMAKE_SOURCE_DIR}/tests/toolchain --cdt ${CMAKE_BINARY_DIR}/bin )
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 )
set_property(TEST toolchain_tests PROPERTY LABELS toolchain_tests)

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unit/version_tests.sh ${CMAKE_BINARY_DIR}/tests/unit/version_tests.sh COPYONLY)
Expand Down
50 changes: 50 additions & 0 deletions tests/toolchain/abigen-pass/exclude_from_abi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <eosio/eosio.hpp>
#include <eosio/name.hpp>
#include <eosio/singleton.hpp>
#include <eosio/multi_index.hpp>



struct [[eosio::table]] out_of_class {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"mi.config55"_n, out_of_class> out_of_class_index;
using uout_of_class_index = eosio::multi_index<"mi.config551"_n, out_of_class>;

typedef eosio::singleton<"smpl.conf55"_n, eosio::name> smpl_config55;
typedef eosio::singleton<"config55"_n, out_of_class> config55;
typedef smpl_config55 smpl_config551;
typedef config55 config551;
using smpl_conf551 = eosio::singleton<"smpl.conf551"_n, eosio::name>;
using config552 = eosio::singleton<"config552"_n, out_of_class>;
using smpl_conf552 = smpl_conf551;
using config553 = config551;

class [[eosio::contract("singleton_contract_simple2")]] singleton_contract_simple2 : public eosio::contract {
public:
using eosio::contract::contract;

[[eosio::action]]
void whatever() {};

struct [[eosio::table]] inside_class {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::singleton<"smpl.conf552"_n, eosio::name> smpl_conf552;
typedef eosio::singleton<"config552"_n, inside_class> config552;
typedef smpl_conf552 smpl_conf553;
typedef config552 config553;
using smpl_conf554 = eosio::singleton<"smpl.conf554"_n, eosio::name>;
using config554 = eosio::singleton<"config554"_n, inside_class>;
using smpl_conf555 = smpl_conf554;
using config555 = config554;



typedef eosio::multi_index<"mi.config553"_n, inside_class> inside_class_index;
using uinside_class_index = eosio::multi_index<"mi.config554"_n, inside_class>;
};
48 changes: 48 additions & 0 deletions tests/toolchain/abigen-pass/singleton_contract.abi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@
"version": "eosio::abi/1.2",
"types": [],
"structs": [
{
"name": "out_of_class",
"base": "",
"fields": [
{
"name": "id",
"type": "uint64"
}
]
},
{
"name": "out_of_class3",
"base": "",
"fields": [
{
"name": "id",
"type": "uint64"
}
]
},
{
"name": "tbl_config",
"base": "",
Expand Down Expand Up @@ -37,6 +57,34 @@
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "config55",
"type": "out_of_class",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "mi.config52",
"type": "out_of_class3",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "smpl.conf5",
"type": "name",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "smpl.config",
"type": "name",
"index_type": "i64",
"key_names": [],
"key_types": []
}
],
"ricardian_clauses": [],
Expand Down
31 changes: 29 additions & 2 deletions tests/toolchain/abigen-pass/singleton_contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,33 @@
#include <eosio/eosio.hpp>
#include <eosio/name.hpp>
#include <eosio/singleton.hpp>

#include "exclude_from_abi.hpp"

using namespace eosio;


struct [[eosio::table]] out_of_class2 {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"mi.config5"_n, out_of_class2> out_of_class_index51;
using uout_of_class_index51 = eosio::multi_index<"mi.config51"_n, out_of_class2>;

struct [[eosio::table, eosio::contract("singleton_contract")]] out_of_class3 {
uint64_t id;
uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"mi.config52"_n, out_of_class3> out_of_class_index52;

typedef eosio::singleton<"smpl.conf5"_n, eosio::name> smpl_config5;
typedef eosio::singleton<"config5"_n, out_of_class2> config5;
typedef smpl_config5 smpl_config51;
typedef config5 config51;
using smpl_conf51 = eosio::singleton<"smpl.conf51"_n, eosio::name>;
using config52 = eosio::singleton<"config52"_n, out_of_class2>;
using smpl_conf52 = smpl_conf51;
using config53 = config51;

class [[eosio::contract("singleton_contract")]] singleton_contract : public contract {
public:
using contract::contract;
Expand All @@ -17,5 +41,8 @@ class [[eosio::contract("singleton_contract")]] singleton_contract : public cont
uint64_t x;
};

typedef eosio::singleton<"config"_n, tbl_config> config;
typedef eosio::singleton<"config"_n, tbl_config> config;
typedef eosio::singleton<"smpl.config"_n, name> smpl_config;
using smpl_config2 = smpl_config5;
typedef config551 config2; //from exclude_from_abi.hpp
};
31 changes: 0 additions & 31 deletions tests/toolchain/abigen-pass/singleton_contract_simple.abi

This file was deleted.

16 changes: 0 additions & 16 deletions tests/toolchain/abigen-pass/singleton_contract_simple.cpp

This file was deleted.

10 changes: 0 additions & 10 deletions tests/toolchain/abigen-pass/singleton_contract_simple.json

This file was deleted.

107 changes: 95 additions & 12 deletions tools/include/eosio/abigen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,11 @@ namespace eosio { namespace cdt {
ctables.insert(t);
}

void add_table( uint64_t name, const clang::CXXRecordDecl* decl, bool force=false ) {
if (force || decl->isEosioTable() && abigen::is_eosio_contract(decl, get_contract_name())) {
abi_table t;
t.type = decl->getNameAsString();
t.name = name_to_string(name);
_abi.tables.insert(t);
}
void add_table( uint64_t name, const clang::CXXRecordDecl* decl ) {
abi_table t;
t.type = decl->getNameAsString();
t.name = name_to_string(name);
_abi.tables.insert(t);
}

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

public:
explicit eosio_abigen_visitor(CompilerInstance *CI) {
Expand Down Expand Up @@ -799,18 +798,99 @@ namespace eosio { namespace cdt {
}
return true;
}

bool is_same_type(const clang::Decl* decl1, const clang::CXXRecordDecl* decl2) const {
if (!decl1 || !decl2)
return false;
if (decl1 == decl2)
return true;

// checking if declaration is a typedef or using
if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast<clang::TypedefNameDecl>(decl1)) {
if (const auto* cur_type = typedef_decl->getUnderlyingType().getTypePtrOrNull()) {
if (decl2 == cur_type->getAsCXXRecordDecl()) {
return true;
}
}
}

return false;
}

bool defined_in_contract(const clang::ClassTemplateSpecializationDecl* decl) {

if (!contract_class) {
// currently this is unreachable as we do not traverse non-main file translation units
CDT_WARN("codegen_warning", decl->getLocation(), "contract class not found: " + ag.get_contract_name());
return false;
}

for (const clang::Decl* cur_decl : contract_class->decls()) {
if (is_same_type(cur_decl, decl))
return true;
}

return false;
}

virtual bool VisitDecl(clang::Decl* decl) {
if (const auto* d = dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
bool is_singleton = d->getName() == "singleton";
if (d->getName() == "multi_index" || is_singleton) {
ag.add_table(d->getTemplateArgs()[0].getAsIntegral().getExtValue(),
d->getTemplateArgs()[1].getAsType().getTypePtr()->getAsCXXRecordDecl(), is_singleton);
if (d->getName() == "multi_index" || d->getName() == "singleton") {
// second template parameter is table type
const auto* table_type = d->getTemplateArgs()[1].getAsType().getTypePtr()->getAsCXXRecordDecl();
if ((table_type->isEosioTable() && ag.is_eosio_contract(table_type, ag.get_contract_name())) || defined_in_contract(d)) {
// first parameter is table name
ag.add_table(d->getTemplateArgs()[0].getAsIntegral().getExtValue(), table_type);
if (table_type->isEosioTable())
ag.add_struct(table_type);
}
}
}
return true;
}
inline void set_contract_class(const CXXRecordDecl* decl) {
contract_class = decl;
}
};
class contract_class_finder : public RecursiveASTVisitor<contract_class_finder> {
private:
abigen& ag = abigen::get();
const clang::CXXRecordDecl* contract_class = nullptr;
public:
virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl* cxx_decl) {
if (cxx_decl->isEosioContract()) {
bool is_eosio_contract = false;
// on this point it could be just an attribute so let's check base classes
for (const auto& base : cxx_decl->bases()) {
if (const clang::Type *base_type = base.getType().getTypePtrOrNull()) {
if (const auto* cur_cxx_decl = base_type->getAsCXXRecordDecl()) {
if (cur_cxx_decl->getQualifiedNameAsString() == "eosio::contract") {
is_eosio_contract = true;
break;
}
}
}
}
if (!is_eosio_contract)
return true;

auto attr_name = cxx_decl->getEosioContractAttr()->getName();
auto name = attr_name.empty() ? cxx_decl->getName() : attr_name;
if (name == llvm::StringRef(ag.get_contract_name())) {
contract_class = cxx_decl;
return false;
}
}

return true;
}
inline bool contract_found() const {
return contract_class != nullptr;
}
inline const clang::CXXRecordDecl* get_contract() const {
return contract_class;
}
};
class eosio_abigen_consumer : public ASTConsumer {
private:
eosio_abigen_visitor *visitor;
Expand All @@ -826,7 +906,10 @@ namespace eosio { namespace cdt {
auto& f_mgr = src_mgr.getFileManager();
auto main_fe = f_mgr.getFile(main_file);
if (main_fe) {
auto fid = src_mgr.getOrCreateFileID(f_mgr.getFile(main_file), SrcMgr::CharacteristicKind::C_User);
contract_class_finder cf;
cf.TraverseDecl(Context.getTranslationUnitDecl());
if (cf.contract_found())
visitor->set_contract_class(cf.get_contract());
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
}
Expand Down
8 changes: 5 additions & 3 deletions tools/include/eosio/error_emitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ namespace eosio { namespace cdt {
#define CDT_ERROR(e, l, s) \
get_error_emitter().emit_error(l, get_error_emitter().diags.get(e), s);

#define CDT_INTERNAL_ERROR(s) \
std::cerr << s << "\n"; \
throw internal_error_ex;
#define CDT_INTERNAL_ERROR(s) \
do { \
std::cerr << s << "\n"; \
throw internal_error_ex; \
} while (false)
Loading

0 comments on commit 02ce20a

Please sign in to comment.