Everywhere: Warn on function definitions without prototypes

If no header includes the prototype of a function, then it cannot be
used from outside the translation unit it was defined in. In that case,
it should be marked as `static`, in order to avoid possible ODR
problems, unnecessary exported symbols, and allow the compiler to better
optimize those.

If this warning triggers in a function defined in a header, `inline`
needs to be added, otherwise if the header is included in more than one
TU, it will fail to link with a duplicate definition error.

The reason this diff got so big is that Lagom-only code wasn't built
with this flag even in Serenity times.
This commit is contained in:
Daniel Bertalan 2024-07-14 18:29:33 +02:00
commit c62240aa80
Notes: sideshowbarker 2024-07-18 08:27:14 +09:00
24 changed files with 146 additions and 97 deletions

View file

@ -16,6 +16,7 @@
#include <ctype.h>
#include <stdio.h>
namespace {
struct Parameter {
Vector<ByteString> attributes;
ByteString type;
@ -823,6 +824,7 @@ void build(StringBuilder& builder, Vector<Endpoint> const& endpoints)
for (auto const& endpoint : endpoints)
build_endpoint(generator.fork(), endpoint);
}
} // end anonymous namespace
ErrorOr<int> serenity_main(Main::Arguments arguments)
{

View file

@ -15,6 +15,7 @@
#include <LibCore/File.h>
#include <LibMain/Main.h>
namespace {
struct LookupTable {
u32 first_pointer;
u32 max_code_point;
@ -175,6 +176,7 @@ namespace TextCodec {
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {};
}
} // end anonymous namespace
ErrorOr<int> serenity_main(Main::Arguments arguments)
{

View file

@ -10,6 +10,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "IDLGenerators.h"
#include "Namespaces.h"
#include <AK/Array.h>
#include <AK/LexicalPath.h>
@ -17,10 +18,10 @@
#include <AK/QuickSort.h>
#include <LibIDL/Types.h>
Vector<StringView> s_header_search_paths;
namespace IDL {
Vector<StringView> g_header_search_paths;
// FIXME: Generate this automatically somehow.
static bool is_platform_object(Type const& type)
{
@ -284,7 +285,7 @@ static void generate_include_for(auto& generator, auto& path)
{
auto forked_generator = generator.fork();
auto path_string = path;
for (auto& search_path : s_header_search_paths) {
for (auto& search_path : g_header_search_paths) {
if (!path.starts_with(search_path))
continue;
auto relative_path = LexicalPath::relative_path(path, search_path);

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2020-2023, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2023, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
* Copyright (c) 2023-2024, Kenneth Myhra <kennethmyhra@serenityos.org>
* Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Matthew Olsson <mattco@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/StringBuilder.h>
#include <LibIDL/Types.h>
namespace IDL {
void generate_namespace_header(IDL::Interface const&, StringBuilder&);
void generate_namespace_implementation(IDL::Interface const&, StringBuilder&);
void generate_constructor_header(IDL::Interface const&, StringBuilder&);
void generate_constructor_implementation(IDL::Interface const&, StringBuilder&);
void generate_prototype_header(IDL::Interface const&, StringBuilder&);
void generate_prototype_implementation(IDL::Interface const&, StringBuilder&);
void generate_iterator_prototype_header(IDL::Interface const&, StringBuilder&);
void generate_iterator_prototype_implementation(IDL::Interface const&, StringBuilder&);
void generate_global_mixin_header(IDL::Interface const&, StringBuilder&);
void generate_global_mixin_implementation(IDL::Interface const&, StringBuilder&);
extern Vector<StringView> g_header_search_paths;
}

View file

@ -8,6 +8,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "IDLGenerators.h"
#include "Namespaces.h"
#include <AK/Debug.h>
#include <AK/LexicalPath.h>
@ -16,21 +17,6 @@
#include <LibIDL/IDLParser.h>
#include <LibIDL/Types.h>
extern Vector<StringView> s_header_search_paths;
namespace IDL {
void generate_namespace_header(IDL::Interface const&, StringBuilder&);
void generate_namespace_implementation(IDL::Interface const&, StringBuilder&);
void generate_constructor_header(IDL::Interface const&, StringBuilder&);
void generate_constructor_implementation(IDL::Interface const&, StringBuilder&);
void generate_prototype_header(IDL::Interface const&, StringBuilder&);
void generate_prototype_implementation(IDL::Interface const&, StringBuilder&);
void generate_iterator_prototype_header(IDL::Interface const&, StringBuilder&);
void generate_iterator_prototype_implementation(IDL::Interface const&, StringBuilder&);
void generate_global_mixin_header(IDL::Interface const&, StringBuilder&);
void generate_global_mixin_implementation(IDL::Interface const&, StringBuilder&);
}
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
Core::ArgsParser args_parser;
@ -47,7 +33,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
.short_name = 'i',
.value_name = "path",
.accept_value = [&](StringView s) {
s_header_search_paths.append(s);
IDL::g_header_search_paths.append(s);
return true;
},
});

View file

@ -10,34 +10,7 @@
#include <LibCore/ArgsParser.h>
#include <LibMain/Main.h>
ErrorOr<void> generate_header_file(JsonObject& roles_data, Core::File& file);
ErrorOr<void> generate_implementation_file(JsonObject& roles_data, Core::File& file);
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
StringView generated_header_path;
StringView generated_implementation_path;
StringView identifiers_json_path;
Core::ArgsParser args_parser;
args_parser.add_option(generated_header_path, "Path to the TransformFunctions header file to generate", "generated-header-path", 'h', "generated-header-path");
args_parser.add_option(generated_implementation_path, "Path to the TransformFunctions implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
args_parser.add_option(identifiers_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path");
args_parser.parse(arguments);
auto json = TRY(read_entire_file_as_json(identifiers_json_path));
VERIFY(json.is_object());
auto roles_data = json.as_object();
auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write));
auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write));
TRY(generate_header_file(roles_data, *generated_header_file));
TRY(generate_implementation_file(roles_data, *generated_implementation_file));
return 0;
}
namespace {
ErrorOr<void> generate_header_file(JsonObject& roles_data, Core::File& file)
{
StringBuilder builder;
@ -387,3 +360,29 @@ NameFromSource @name@::name_from_source() const
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {};
}
} // end anonymous namespace
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
StringView generated_header_path;
StringView generated_implementation_path;
StringView identifiers_json_path;
Core::ArgsParser args_parser;
args_parser.add_option(generated_header_path, "Path to the TransformFunctions header file to generate", "generated-header-path", 'h', "generated-header-path");
args_parser.add_option(generated_implementation_path, "Path to the TransformFunctions implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
args_parser.add_option(identifiers_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path");
args_parser.parse(arguments);
auto json = TRY(read_entire_file_as_json(identifiers_json_path));
VERIFY(json.is_object());
auto roles_data = json.as_object();
auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write));
auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write));
TRY(generate_header_file(roles_data, *generated_header_file));
TRY(generate_implementation_file(roles_data, *generated_implementation_file));
return 0;
}

View file

@ -10,34 +10,7 @@
#include <LibCore/ArgsParser.h>
#include <LibMain/Main.h>
ErrorOr<void> generate_header_file(JsonObject& functions_data, Core::File& file);
ErrorOr<void> generate_implementation_file(JsonObject& functions_data, Core::File& file);
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
StringView generated_header_path;
StringView generated_implementation_path;
StringView identifiers_json_path;
Core::ArgsParser args_parser;
args_parser.add_option(generated_header_path, "Path to the MathFunctions header file to generate", "generated-header-path", 'h', "generated-header-path");
args_parser.add_option(generated_implementation_path, "Path to the MathFunctions implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
args_parser.add_option(identifiers_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path");
args_parser.parse(arguments);
auto json = TRY(read_entire_file_as_json(identifiers_json_path));
VERIFY(json.is_object());
auto math_functions_data = json.as_object();
auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write));
auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write));
TRY(generate_header_file(math_functions_data, *generated_header_file));
TRY(generate_implementation_file(math_functions_data, *generated_implementation_file));
return 0;
}
namespace {
ErrorOr<void> generate_header_file(JsonObject& functions_data, Core::File& file)
{
StringBuilder builder;
@ -378,3 +351,29 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {};
}
} // end anonymous namespace
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
StringView generated_header_path;
StringView generated_implementation_path;
StringView identifiers_json_path;
Core::ArgsParser args_parser;
args_parser.add_option(generated_header_path, "Path to the MathFunctions header file to generate", "generated-header-path", 'h', "generated-header-path");
args_parser.add_option(generated_implementation_path, "Path to the MathFunctions implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
args_parser.add_option(identifiers_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path");
args_parser.parse(arguments);
auto json = TRY(read_entire_file_as_json(identifiers_json_path));
VERIFY(json.is_object());
auto math_functions_data = json.as_object();
auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write));
auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write));
TRY(generate_header_file(math_functions_data, *generated_header_file));
TRY(generate_implementation_file(math_functions_data, *generated_implementation_file));
return 0;
}

View file

@ -13,7 +13,7 @@
#include <LibCore/File.h>
#include <ctype.h>
String title_casify(StringView dashy_name)
inline String title_casify(StringView dashy_name)
{
auto parts = dashy_name.split_view('-');
StringBuilder builder;
@ -28,7 +28,7 @@ String title_casify(StringView dashy_name)
return MUST(builder.to_string());
}
String camel_casify(StringView dashy_name)
inline String camel_casify(StringView dashy_name)
{
auto parts = dashy_name.split_view('-');
StringBuilder builder;
@ -49,14 +49,14 @@ String camel_casify(StringView dashy_name)
return MUST(builder.to_string());
}
String snake_casify(StringView dashy_name)
inline String snake_casify(StringView dashy_name)
{
// FIXME: We don't really need to convert dashy_name to a String first, but currently
// all the `replace` functions that take a StringView return ByteString.
return MUST(MUST(String::from_utf8(dashy_name)).replace("-"sv, "_"sv, ReplaceMode::All));
}
ErrorOr<JsonValue> read_entire_file_as_json(StringView filename)
inline ErrorOr<JsonValue> read_entire_file_as_json(StringView filename)
{
auto file = TRY(Core::File::open(filename, Core::File::OpenMode::Read));
auto json_size = TRY(file->size());