diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 52e368f36..1803d68bb 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -911,6 +911,11 @@ class Parser : public ParserState { // @param opts Options used to parce a schema and generate code. static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts); + // Get the set of included files that are directly referenced by the file + // being parsed. This does not include files that are transitively included by + // others includes. + std::vector GetIncludedFiles() const; + private: class ParseDepthGuard; diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index da28dac48..b1d9ca042 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -221,33 +221,34 @@ class CppGenerator : public BaseGenerator { } void GenIncludeDependencies() { - int num_includes = 0; if (opts_.generate_object_based_api) { for (auto it = parser_.native_included_files_.begin(); it != parser_.native_included_files_.end(); ++it) { code_ += "#include \"" + *it + "\""; - num_includes++; } } - std::vector include_files; - for (auto it = parser_.included_files_.begin(); - it != parser_.included_files_.end(); ++it) { - if (it->second.empty()) continue; - include_files.push_back(it->second); - } - std::stable_sort(include_files.begin(), include_files.end()); + // Get the directly included file of the file being parsed. + std::vector included_files(parser_.GetIncludedFiles()); - for (auto it = include_files.begin(); it != include_files.end(); ++it) { - auto noext = flatbuffers::StripExtension(*it); - auto basename = flatbuffers::StripPath(noext); - auto includeName = - GeneratedFileName(opts_.include_prefix, - opts_.keep_include_path ? noext : basename, opts_); - code_ += "#include \"" + includeName + "\""; - num_includes++; + // We are safe to sort them alphabetically, since there shouldn't be any + // interdependence between them. + std::stable_sort(included_files.begin(), included_files.end()); + + for (const std::string &included_file : included_files) { + auto noext = flatbuffers::StripExtension(included_file); + code_ += + "#include \"" + + GeneratedFileName( + opts_.include_prefix, + opts_.keep_include_path ? noext : flatbuffers::StripPath(noext), + opts_) + + "\""; + } + + if (!parser_.native_included_files_.empty() || !included_files.empty()) { + code_ += ""; } - if (num_includes) code_ += ""; } void GenExtraIncludes() { diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 8dcec894b..cb1861981 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2189,12 +2189,8 @@ template void EnumDef::ChangeEnumValue(EnumVal *ev, T new_value) { } namespace EnumHelper { -template struct EnumValType { - typedef int64_t type; -}; -template<> struct EnumValType { - typedef uint64_t type; -}; +template struct EnumValType { typedef int64_t type; }; +template<> struct EnumValType { typedef uint64_t type; }; } // namespace EnumHelper struct EnumValBuilder { @@ -2464,6 +2460,13 @@ CheckedError Parser::CheckClash(std::vector &fields, return NoError(); } +std::vector Parser::GetIncludedFiles() const { + const auto it = files_included_per_file_.find(file_being_parsed_); + if (it == files_included_per_file_.end()) { return {}; } + + return { it->second.cbegin(), it->second.cend() }; +} + bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) { static FLATBUFFERS_CONSTEXPR unsigned long supported_langs = IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster | @@ -3332,8 +3335,8 @@ CheckedError Parser::CheckPrivatelyLeakedFields(const Definition &def, const auto is_field_private = value_type.attributes.Lookup("private"); if (!is_private && is_field_private) { return Error( - "Leaking private implementation, verify all objects have similar " - "annotations"); + "Leaking private implementation, verify all objects have similar " + "annotations"); } return NoError(); }