From 459fa3226d29775507e306fcf74dae84650ff586 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Mon, 10 Jul 2023 16:20:10 -0400 Subject: [PATCH 01/18] handle correctly included contracts types --- tools/include/eosio/abigen.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 479c9fec73..0ac4bc655e 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -787,7 +787,7 @@ namespace eosio { namespace cdt { ag.add_contracts(ag.parse_contracts()); has_added_clauses = true; } - if ((decl->isEosioAction() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) { + if (decl->isEosioAction() || decl->isEosioTable()) { ag.add_struct(decl); if (decl->isEosioAction()) ag.add_action(decl); From 19b3b249aaca43a8ed06cb06d3d9aa420c438cc7 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Mon, 17 Jul 2023 23:27:35 -0400 Subject: [PATCH 02/18] redesign of abigen for multi_index and singleton --- tests/CMakeLists.txt | 2 +- .../abigen-pass/exclude_from_abi.hpp | 50 +++++++++++ .../abigen-pass/singleton_contract.abi | 7 ++ .../abigen-pass/singleton_contract.cpp | 23 ++++- .../abigen-pass/singleton_contract_simple.abi | 31 ------- .../abigen-pass/singleton_contract_simple.cpp | 16 ---- .../singleton_contract_simple.json | 10 --- tools/include/eosio/abigen.hpp | 90 ++++++++++++++++++- 8 files changed, 167 insertions(+), 62 deletions(-) create mode 100644 tests/toolchain/abigen-pass/exclude_from_abi.hpp delete mode 100644 tests/toolchain/abigen-pass/singleton_contract_simple.abi delete mode 100644 tests/toolchain/abigen-pass/singleton_contract_simple.cpp delete mode 100644 tests/toolchain/abigen-pass/singleton_contract_simple.json diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d4bd2cf6e4..2590f7345b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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) diff --git a/tests/toolchain/abigen-pass/exclude_from_abi.hpp b/tests/toolchain/abigen-pass/exclude_from_abi.hpp new file mode 100644 index 0000000000..3b90f866ac --- /dev/null +++ b/tests/toolchain/abigen-pass/exclude_from_abi.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include + + + +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>; +}; diff --git a/tests/toolchain/abigen-pass/singleton_contract.abi b/tests/toolchain/abigen-pass/singleton_contract.abi index 4c6e9853a5..ade07a444d 100644 --- a/tests/toolchain/abigen-pass/singleton_contract.abi +++ b/tests/toolchain/abigen-pass/singleton_contract.abi @@ -37,6 +37,13 @@ "index_type": "i64", "key_names": [], "key_types": [] + }, + { + "name": "smpl.config", + "type": "name", + "index_type": "i64", + "key_names": [], + "key_types": [] } ], "ricardian_clauses": [], diff --git a/tests/toolchain/abigen-pass/singleton_contract.cpp b/tests/toolchain/abigen-pass/singleton_contract.cpp index 89831854c9..0a27c52aa4 100644 --- a/tests/toolchain/abigen-pass/singleton_contract.cpp +++ b/tests/toolchain/abigen-pass/singleton_contract.cpp @@ -2,9 +2,27 @@ #include #include #include + +#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>; + +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; @@ -17,5 +35,6 @@ 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; }; diff --git a/tests/toolchain/abigen-pass/singleton_contract_simple.abi b/tests/toolchain/abigen-pass/singleton_contract_simple.abi deleted file mode 100644 index 8600eb2f76..0000000000 --- a/tests/toolchain/abigen-pass/singleton_contract_simple.abi +++ /dev/null @@ -1,31 +0,0 @@ -{ - "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", - "version": "eosio::abi/1.2", - "types": [], - "structs": [ - { - "name": "whatever", - "base": "", - "fields": [] - } - ], - "actions": [ - { - "name": "whatever", - "type": "whatever", - "ricardian_contract": "" - } - ], - "tables": [ - { - "name": "smpl.config", - "type": "name", - "index_type": "i64", - "key_names": [], - "key_types": [] - } - ], - "ricardian_clauses": [], - "variants": [], - "action_results": [] -} diff --git a/tests/toolchain/abigen-pass/singleton_contract_simple.cpp b/tests/toolchain/abigen-pass/singleton_contract_simple.cpp deleted file mode 100644 index 2afdc7c332..0000000000 --- a/tests/toolchain/abigen-pass/singleton_contract_simple.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include - -using namespace eosio; - -class [[eosio::contract("singleton_contract_simple")]] singleton_contract_simple : public contract { - public: - using contract::contract; - - [[eosio::action]] - void whatever() {}; - - typedef eosio::singleton<"smpl.config"_n, name> config; -}; diff --git a/tests/toolchain/abigen-pass/singleton_contract_simple.json b/tests/toolchain/abigen-pass/singleton_contract_simple.json deleted file mode 100644 index 0bf81acc1e..0000000000 --- a/tests/toolchain/abigen-pass/singleton_contract_simple.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "tests" : [ - { - "expected" : { - "abi-file" : "singleton_contract_simple.abi" - } - } - ] - } - \ No newline at end of file diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 0ac4bc655e..77c301ae09 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -755,6 +755,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) { @@ -787,7 +788,7 @@ namespace eosio { namespace cdt { ag.add_contracts(ag.parse_contracts()); has_added_clauses = true; } - if (decl->isEosioAction() || decl->isEosioTable()) { + if ((decl->isEosioAction() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) { ag.add_struct(decl); if (decl->isEosioAction()) ag.add_action(decl); @@ -799,10 +800,95 @@ namespace eosio { namespace cdt { } return true; } + + const clang::CXXRecordDecl* find_contract_class(const clang::Decl* decl) const { + const auto* translation_unit = decl->getASTContext().getTranslationUnitDecl(); + + for (clang::Decl* cur_decl : translation_unit->decls()) { + if (const auto* cxx_decl = llvm::dyn_cast(cur_decl)) { + + if (cxx_decl->isEosioContract()) { + auto attr_name = cxx_decl->getEosioContractAttr()->getName().str(); + auto name = attr_name.empty() ? cxx_decl->getName().str() : attr_name; + if (name == ag.get_contract_name()) + return cxx_decl; + } + else { + auto pd = llvm::dyn_cast(cxx_decl->getParent()); + if (pd && pd->isEosioContract()) { + auto attr_name = pd->getEosioContractAttr()->getName().str(); + auto name = attr_name.empty() ? pd->getName().str() : attr_name; + if (name == ag.get_contract_name()) + return pd; + } + } + } + } + + return NULL; + } + + bool is_same_type(const clang::Decl* decl1, const clang::CXXRecordDecl* decl2) const { + if (decl1 == decl2) + return true; + + if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast(decl1)) { + if (const auto* cxx_rec1 = typedef_decl->getUnderlyingType()->getAsCXXRecordDecl()) { + if (cxx_rec1 == decl2) + return true; + } + } + + return false; + } + + bool aliased_in_contract(const clang::Decl* decl) const { + for (const auto* contract_decl : contract_class->decls()) { + if (const auto* cur_contract_decl = llvm::dyn_cast(contract_decl)) { + if (const auto* cur_contract_rec = cur_contract_decl->getUnderlyingType()->getAsCXXRecordDecl()) { + if (cur_contract_rec == decl) + return true; + } + } + } + } + + // recursively check all declarations from declaration context if any of them is equal to decl + bool is_decl_in_contract(const clang::Decl* cur_decl, const clang::CXXRecordDecl* decl) { + if (is_same_type(cur_decl, decl) && aliased_in_contract(decl)) + return true; + + if (const auto* decl_ctx = llvm::dyn_cast(cur_decl)) { + // The Decl is also a DeclContext, so it might contain other Decls. + for (const auto* child_decl : decl_ctx->decls()) { + if(is_decl_in_contract(child_decl, decl)) + return true; + } + } + + return false; + } + + bool defined_in_contract(const clang::ClassTemplateSpecializationDecl* decl) { + + if (!contract_class) + contract_class = find_contract_class(decl); + if (!contract_class) CDT_ERROR("abigen_error", decl->getLocation(), "contract class not found"); + + const auto* translation_unit = decl->getASTContext().getTranslationUnitDecl(); + + for (const auto* cur_decl : translation_unit->decls()) { + // Recursively traverse the AST. + if (is_decl_in_contract(cur_decl, decl)) + return true; + } + return false; + } + virtual bool VisitDecl(clang::Decl* decl) { if (const auto* d = dyn_cast(decl)) { bool is_singleton = d->getName() == "singleton"; - if (d->getName() == "multi_index" || is_singleton) { + if ((d->getName() == "multi_index" || is_singleton) && defined_in_contract(d)) { ag.add_table(d->getTemplateArgs()[0].getAsIntegral().getExtValue(), d->getTemplateArgs()[1].getAsType().getTypePtr()->getAsCXXRecordDecl(), is_singleton); } From 482de2c29ed9977ce92d66dcfef5853f441f1ba1 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Mon, 17 Jul 2023 23:41:06 -0400 Subject: [PATCH 03/18] singleton tests extension --- tests/toolchain/abigen-pass/singleton_contract.abi | 14 ++++++++++++++ tests/toolchain/abigen-pass/singleton_contract.cpp | 2 ++ 2 files changed, 16 insertions(+) diff --git a/tests/toolchain/abigen-pass/singleton_contract.abi b/tests/toolchain/abigen-pass/singleton_contract.abi index ade07a444d..6cdc4a8c72 100644 --- a/tests/toolchain/abigen-pass/singleton_contract.abi +++ b/tests/toolchain/abigen-pass/singleton_contract.abi @@ -38,6 +38,20 @@ "key_names": [], "key_types": [] }, + { + "name": "config55", + "type": "out_of_class", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "smpl.conf5", + "type": "name", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, { "name": "smpl.config", "type": "name", diff --git a/tests/toolchain/abigen-pass/singleton_contract.cpp b/tests/toolchain/abigen-pass/singleton_contract.cpp index 0a27c52aa4..f1999c27bc 100644 --- a/tests/toolchain/abigen-pass/singleton_contract.cpp +++ b/tests/toolchain/abigen-pass/singleton_contract.cpp @@ -37,4 +37,6 @@ class [[eosio::contract("singleton_contract")]] singleton_contract : public cont 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 }; From 134a7cd14194449957941dad2d63ad57ccbf3d43 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Tue, 18 Jul 2023 00:37:50 -0400 Subject: [PATCH 04/18] update cicd ubuntu 20.04->20.10 --- .cicd/platforms/ubuntu22.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cicd/platforms/ubuntu22.Dockerfile b/.cicd/platforms/ubuntu22.Dockerfile index ca38aad5cd..9b510d36c8 100644 --- a/.cicd/platforms/ubuntu22.Dockerfile +++ b/.cicd/platforms/ubuntu22.Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:jammy +FROM ubuntu:kinetic RUN apt-get update && apt-get upgrade -y && \ DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \ From 0a747a936d262573dc1ca2fef750cda62a51ff22 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Tue, 18 Jul 2023 22:22:42 -0400 Subject: [PATCH 05/18] try to fix crash in tests --- tools/include/eosio/abigen.hpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 77c301ae09..ba0062f5f8 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -861,7 +861,7 @@ namespace eosio { namespace cdt { if (const auto* decl_ctx = llvm::dyn_cast(cur_decl)) { // The Decl is also a DeclContext, so it might contain other Decls. for (const auto* child_decl : decl_ctx->decls()) { - if(is_decl_in_contract(child_decl, decl)) + if(child_decl && is_decl_in_contract(child_decl, decl)) return true; } } @@ -875,14 +875,15 @@ namespace eosio { namespace cdt { contract_class = find_contract_class(decl); if (!contract_class) CDT_ERROR("abigen_error", decl->getLocation(), "contract class not found"); - const auto* translation_unit = decl->getASTContext().getTranslationUnitDecl(); - - for (const auto* cur_decl : translation_unit->decls()) { - // Recursively traverse the AST. - if (is_decl_in_contract(cur_decl, decl)) - return true; - } - return false; + return aliased_in_contract(decl); + // const auto* translation_unit = decl->getASTContext().getTranslationUnitDecl(); + + // for (const auto* cur_decl : translation_unit->decls()) { + // // Recursively traverse the AST. + // if (is_decl_in_contract(cur_decl, decl)) + // return true; + // } + // return false; } virtual bool VisitDecl(clang::Decl* decl) { From e644e75d3ec58cb1a93558ea8352d22edc2a9bf6 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Wed, 19 Jul 2023 13:17:59 -0400 Subject: [PATCH 06/18] trying to fix build seg fault --- tools/include/eosio/abigen.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index ba0062f5f8..904836b2fc 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -845,9 +845,11 @@ namespace eosio { namespace cdt { bool aliased_in_contract(const clang::Decl* decl) const { for (const auto* contract_decl : contract_class->decls()) { if (const auto* cur_contract_decl = llvm::dyn_cast(contract_decl)) { - if (const auto* cur_contract_rec = cur_contract_decl->getUnderlyingType()->getAsCXXRecordDecl()) { - if (cur_contract_rec == decl) - return true; + if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { + if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { + if (cur_contract_rec == decl) + return true; + } } } } From 9e3d4a0a72a3a9d7eced5ea1f6e06ebf65d4dd2d Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Wed, 19 Jul 2023 13:38:52 -0400 Subject: [PATCH 07/18] more checks to deal with seg fault --- tools/include/eosio/abigen.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 904836b2fc..79d54fba5a 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -829,13 +829,17 @@ namespace eosio { namespace cdt { } bool is_same_type(const clang::Decl* decl1, const clang::CXXRecordDecl* decl2) const { + if (!decl1 || !decl2) + return false; if (decl1 == decl2) return true; - if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast(decl1)) { - if (const auto* cxx_rec1 = typedef_decl->getUnderlyingType()->getAsCXXRecordDecl()) { - if (cxx_rec1 == decl2) - return true; + if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast_or_null(decl1)) { + if (const auto* cur_type = typedef_decl->getUnderlyingType().getTypePtrOrNull()) { + if (const auto* cxx_rec1 = cur_type->getAsCXXRecordDecl()) { + if (cxx_rec1 == decl2) + return true; + } } } @@ -844,7 +848,7 @@ namespace eosio { namespace cdt { bool aliased_in_contract(const clang::Decl* decl) const { for (const auto* contract_decl : contract_class->decls()) { - if (const auto* cur_contract_decl = llvm::dyn_cast(contract_decl)) { + if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(contract_decl)) { if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { if (cur_contract_rec == decl) From c1eca818a9cd9e0ef96cd1600e014ea354ce9f04 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Wed, 19 Jul 2023 17:10:22 -0400 Subject: [PATCH 08/18] fix build seg fault --- tools/include/eosio/abigen.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 79d54fba5a..976b19d6ac 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -847,8 +847,8 @@ namespace eosio { namespace cdt { } bool aliased_in_contract(const clang::Decl* decl) const { - for (const auto* contract_decl : contract_class->decls()) { - if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(contract_decl)) { + for (const auto decl_iter : contract_class->decls()) { + if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(&*decl_iter)) { if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { if (cur_contract_rec == decl) From b2d6f0b18d7648e19b1ed26697a0c55f8f7bac58 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Wed, 19 Jul 2023 21:22:18 -0400 Subject: [PATCH 09/18] trying to fix seg fault --- tools/include/eosio/abigen.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 976b19d6ac..5667f524a1 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -848,11 +848,13 @@ namespace eosio { namespace cdt { bool aliased_in_contract(const clang::Decl* decl) const { for (const auto decl_iter : contract_class->decls()) { - if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(&*decl_iter)) { - if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { - if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { - if (cur_contract_rec == decl) - return true; + if (llvm::isa(&*decl_iter)) { + if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(&*decl_iter)) { + if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { + if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { + if (cur_contract_rec == decl) + return true; + } } } } From dc8d62c5c74c01da6d83f75ebaa7c7b9c2b6cafc Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Wed, 19 Jul 2023 22:29:40 -0400 Subject: [PATCH 10/18] trying to fix seg fault + logs --- tools/include/eosio/abigen.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 5667f524a1..b54198e51b 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -848,8 +848,11 @@ namespace eosio { namespace cdt { bool aliased_in_contract(const clang::Decl* decl) const { for (const auto decl_iter : contract_class->decls()) { - if (llvm::isa(&*decl_iter)) { - if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(&*decl_iter)) { + const clang::Decl* decl_ptr = &*decl_iter; + llvm::errs() << "before llvm::isa(decl_ptr)\n"; + if (decl_ptr && llvm::isa(decl_ptr)) { + llvm::errs() << "after llvm::isa(decl_ptr)\n"; + if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(decl_ptr)) { if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { if (cur_contract_rec == decl) From 208274a8f6b0cc3d002970a475f3bc31b4a635f9 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Fri, 21 Jul 2023 11:13:26 -0400 Subject: [PATCH 11/18] fixing seg fault in release build --- tools/include/eosio/abigen.hpp | 79 +++++++++------------------------- 1 file changed, 21 insertions(+), 58 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index b54198e51b..2db8a4abf2 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -801,10 +801,10 @@ namespace eosio { namespace cdt { return true; } - const clang::CXXRecordDecl* find_contract_class(const clang::Decl* decl) const { - const auto* translation_unit = decl->getASTContext().getTranslationUnitDecl(); - - for (clang::Decl* cur_decl : translation_unit->decls()) { + const clang::CXXRecordDecl* find_contract_class(const clang::ASTContext &ctx) const { + const auto* translation_unit = ctx.getTranslationUnitDecl(); + // scanning entire translation unit to find contract class + for (const clang::Decl* cur_decl : translation_unit->decls()) { if (const auto* cxx_decl = llvm::dyn_cast(cur_decl)) { if (cxx_decl->isEosioContract()) { @@ -814,12 +814,12 @@ namespace eosio { namespace cdt { return cxx_decl; } else { - auto pd = llvm::dyn_cast(cxx_decl->getParent()); - if (pd && pd->isEosioContract()) { - auto attr_name = pd->getEosioContractAttr()->getName().str(); - auto name = attr_name.empty() ? pd->getName().str() : attr_name; + const auto* parent_decl = llvm::dyn_cast(cxx_decl->getParent()); + if (parent_decl && parent_decl->isEosioContract()) { + auto attr_name = parent_decl->getEosioContractAttr()->getName().str(); + auto name = attr_name.empty() ? parent_decl->getName().str() : attr_name; if (name == ag.get_contract_name()) - return pd; + return parent_decl; } } } @@ -834,10 +834,10 @@ namespace eosio { namespace cdt { if (decl1 == decl2) return true; - if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast_or_null(decl1)) { + // checking if declaration is a typedef or using + if (const clang::TypedefNameDecl* typedef_decl = llvm::dyn_cast(decl1)) { if (const auto* cur_type = typedef_decl->getUnderlyingType().getTypePtrOrNull()) { - if (const auto* cxx_rec1 = cur_type->getAsCXXRecordDecl()) { - if (cxx_rec1 == decl2) + if (decl2 == cur_type->getAsCXXRecordDecl()) { return true; } } @@ -845,56 +845,19 @@ namespace eosio { namespace cdt { return false; } + + bool defined_in_contract(const clang::ClassTemplateSpecializationDecl* decl) { - bool aliased_in_contract(const clang::Decl* decl) const { - for (const auto decl_iter : contract_class->decls()) { - const clang::Decl* decl_ptr = &*decl_iter; - llvm::errs() << "before llvm::isa(decl_ptr)\n"; - if (decl_ptr && llvm::isa(decl_ptr)) { - llvm::errs() << "after llvm::isa(decl_ptr)\n"; - if (const auto* cur_contract_decl = llvm::dyn_cast_or_null(decl_ptr)) { - if (const auto* cur_type = cur_contract_decl->getUnderlyingType().getTypePtrOrNull()) { - if (const auto* cur_contract_rec = cur_type->getAsCXXRecordDecl()) { - if (cur_contract_rec == decl) - return true; - } - } - } - } + if (!contract_class) { + contract_class = find_contract_class(decl->getASTContext()); + if (!contract_class) + CDT_ERROR("abigen_error", decl->getLocation(), "contract class not found"); } - } - - // recursively check all declarations from declaration context if any of them is equal to decl - bool is_decl_in_contract(const clang::Decl* cur_decl, const clang::CXXRecordDecl* decl) { - if (is_same_type(cur_decl, decl) && aliased_in_contract(decl)) - return true; - if (const auto* decl_ctx = llvm::dyn_cast(cur_decl)) { - // The Decl is also a DeclContext, so it might contain other Decls. - for (const auto* child_decl : decl_ctx->decls()) { - if(child_decl && is_decl_in_contract(child_decl, decl)) - return true; - } + for (const clang::Decl* cur_decl : contract_class->decls()) { + if (is_same_type(cur_decl, decl)) + return true; } - - return false; - } - - bool defined_in_contract(const clang::ClassTemplateSpecializationDecl* decl) { - - if (!contract_class) - contract_class = find_contract_class(decl); - if (!contract_class) CDT_ERROR("abigen_error", decl->getLocation(), "contract class not found"); - - return aliased_in_contract(decl); - // const auto* translation_unit = decl->getASTContext().getTranslationUnitDecl(); - - // for (const auto* cur_decl : translation_unit->decls()) { - // // Recursively traverse the AST. - // if (is_decl_in_contract(cur_decl, decl)) - // return true; - // } - // return false; } virtual bool VisitDecl(clang::Decl* decl) { From 19749dd297ad8ef6b3e363a54737ed57d37f404f Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Fri, 21 Jul 2023 12:07:32 -0400 Subject: [PATCH 12/18] seg fault fix --- tools/include/eosio/abigen.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 2db8a4abf2..228441625d 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -825,7 +825,7 @@ namespace eosio { namespace cdt { } } - return NULL; + return nullptr; } bool is_same_type(const clang::Decl* decl1, const clang::CXXRecordDecl* decl2) const { @@ -858,6 +858,8 @@ namespace eosio { namespace cdt { if (is_same_type(cur_decl, decl)) return true; } + + return false; } virtual bool VisitDecl(clang::Decl* decl) { From 73662c240a1f16478ff66077de8841ed828f9383 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Mon, 24 Jul 2023 14:52:59 -0400 Subject: [PATCH 13/18] cicd revert ubuntu 22 to LTS --- .cicd/platforms/ubuntu22.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cicd/platforms/ubuntu22.Dockerfile b/.cicd/platforms/ubuntu22.Dockerfile index 9b510d36c8..ca38aad5cd 100644 --- a/.cicd/platforms/ubuntu22.Dockerfile +++ b/.cicd/platforms/ubuntu22.Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:kinetic +FROM ubuntu:jammy RUN apt-get update && apt-get upgrade -y && \ DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \ From 6c78f0ae61c29c311440415583c994ae440e0900 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Wed, 26 Jul 2023 17:26:59 -0400 Subject: [PATCH 14/18] change error macro to throw error --- tools/include/eosio/abigen.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index 228441625d..b7710107ad 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -851,7 +851,7 @@ namespace eosio { namespace cdt { if (!contract_class) { contract_class = find_contract_class(decl->getASTContext()); if (!contract_class) - CDT_ERROR("abigen_error", decl->getLocation(), "contract class not found"); + CDT_INTERNAL_ERROR("contract class not found"); } for (const clang::Decl* cur_decl : contract_class->decls()) { From 34ad214294173d9806a60a9b0b5bc72d3dd28c08 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Thu, 27 Jul 2023 13:17:17 -0400 Subject: [PATCH 15/18] fix CDT_INTERNAL_ERROR macro --- tools/include/eosio/error_emitter.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/include/eosio/error_emitter.hpp b/tools/include/eosio/error_emitter.hpp index 70e4157b3e..0b2de429dd 100644 --- a/tools/include/eosio/error_emitter.hpp +++ b/tools/include/eosio/error_emitter.hpp @@ -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) From 8f467812bc413bc89fc6d5e5ccee4c1a5abd24d7 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Thu, 27 Jul 2023 15:21:45 -0400 Subject: [PATCH 16/18] #201 reivew concerns addressed --- tools/include/eosio/abigen.hpp | 15 +++------------ tools/include/eosio/gen.hpp | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index b7710107ad..e05ff9faff 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -808,20 +808,11 @@ namespace eosio { namespace cdt { if (const auto* cxx_decl = llvm::dyn_cast(cur_decl)) { if (cxx_decl->isEosioContract()) { - auto attr_name = cxx_decl->getEosioContractAttr()->getName().str(); - auto name = attr_name.empty() ? cxx_decl->getName().str() : attr_name; - if (name == ag.get_contract_name()) + 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())) return cxx_decl; } - else { - const auto* parent_decl = llvm::dyn_cast(cxx_decl->getParent()); - if (parent_decl && parent_decl->isEosioContract()) { - auto attr_name = parent_decl->getEosioContractAttr()->getName().str(); - auto name = attr_name.empty() ? parent_decl->getName().str() : attr_name; - if (name == ag.get_contract_name()) - return parent_decl; - } - } } } diff --git a/tools/include/eosio/gen.hpp b/tools/include/eosio/gen.hpp index 8e2494d428..3637e74fea 100644 --- a/tools/include/eosio/gen.hpp +++ b/tools/include/eosio/gen.hpp @@ -155,7 +155,7 @@ struct generation_utils { inline void set_contract_name( const std::string& cn ) { contract_name = cn; } - inline std::string get_contract_name()const { return contract_name; } + inline const std::string& get_contract_name()const { return contract_name; } static inline std::string get_parsed_contract_name() { return parsed_contract_name; } inline void set_resource_dirs( const std::vector& rd ) { llvm::SmallString<128> cwd; @@ -274,30 +274,30 @@ struct generation_utils { } static inline bool is_eosio_contract( const clang::CXXMethodDecl* decl, const std::string& cn ) { - std::string name = ""; + llvm::StringRef name; if (decl->isEosioContract()) name = decl->getEosioContractAttr()->getName(); else if (decl->getParent()->isEosioContract()) name = decl->getParent()->getEosioContractAttr()->getName(); if (name.empty()) { - name = decl->getParent()->getName().str(); + name = decl->getParent()->getName(); } - parsed_contract_name = name; + parsed_contract_name = name.str(); return cn == parsed_contract_name; } static inline bool is_eosio_contract( const clang::CXXRecordDecl* decl, const std::string& cn ) { - std::string name = ""; + llvm::StringRef name; auto pd = llvm::dyn_cast(decl->getParent()); if (decl->isEosioContract()) { - auto nm = decl->getEosioContractAttr()->getName().str(); - name = nm.empty() ? decl->getName().str() : nm; + auto nm = decl->getEosioContractAttr()->getName(); + name = nm.empty() ? decl->getName() : nm; } else if (pd && pd->isEosioContract()) { - auto nm = pd->getEosioContractAttr()->getName().str(); - name = nm.empty() ? pd->getName().str() : nm; + auto nm = pd->getEosioContractAttr()->getName(); + name = nm.empty() ? pd->getName() : nm; } - parsed_contract_name = name; + parsed_contract_name = name.str(); return cn == parsed_contract_name; } From 6e98fda59f02d209d9a99bd07f96e2413b6d2039 Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Thu, 27 Jul 2023 16:07:02 -0400 Subject: [PATCH 17/18] error->warning if contract class is not found + refactor --- tools/include/eosio/abigen.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/include/eosio/abigen.hpp b/tools/include/eosio/abigen.hpp index e05ff9faff..9d83babcd2 100644 --- a/tools/include/eosio/abigen.hpp +++ b/tools/include/eosio/abigen.hpp @@ -841,8 +841,11 @@ namespace eosio { namespace cdt { if (!contract_class) { contract_class = find_contract_class(decl->getASTContext()); - if (!contract_class) - CDT_INTERNAL_ERROR("contract class not found"); + 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"); + return false; + } } for (const clang::Decl* cur_decl : contract_class->decls()) { @@ -880,7 +883,6 @@ 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); visitor->TraverseDecl(Context.getTranslationUnitDecl()); } } From b2386d9ff36468fc46ead51ebb4e17d3f9335b5c Mon Sep 17 00:00:00 2001 From: Dmytro Sydorchenko Date: Thu, 27 Jul 2023 17:23:28 -0400 Subject: [PATCH 18/18] empty commit to address gh issue