LibCpp: Import definitions from headers while processing

When the preprocessor encounters an #include statement it now adds
the preprocessor definitions that exist in the included header to its
own set of definitions.

We previously only aggregated the definitions from headers after
processing the source, which was less correct. (For example, there
could be an #ifdef that depends on a definition from another header).
This commit is contained in:
Itamar 2021-08-06 11:15:57 +03:00 committed by Andreas Kling
parent 4673a517f6
commit 0c4dc00f01
Notes: sideshowbarker 2024-07-18 07:18:12 +09:00
5 changed files with 21 additions and 11 deletions

View file

@ -569,11 +569,16 @@ OwnPtr<CppComprehensionEngine::DocumentData> CppComprehensionEngine::create_docu
document_data->m_preprocessor = make<Preprocessor>(document_data->m_filename, document_data->text());
document_data->preprocessor().set_ignore_unsupported_keywords(true);
document_data->preprocessor().set_keep_include_statements(true);
auto tokens = document_data->preprocessor().process_and_lex();
Preprocessor::Definitions preprocessor_definitions;
for (auto item : document_data->preprocessor().definitions())
preprocessor_definitions.set(move(item.key), move(item.value));
document_data->preprocessor().definitions_in_header_callback = [this](StringView include_path) -> Preprocessor::Definitions {
auto included_document = get_or_create_document_data(document_path_from_include_path(include_path));
if (!included_document)
return {};
return included_document->preprocessor().definitions();
};
auto tokens = document_data->preprocessor().process_and_lex();
for (auto include_path : document_data->preprocessor().included_paths()) {
auto include_fullpath = document_path_from_include_path(include_path);
@ -585,12 +590,9 @@ OwnPtr<CppComprehensionEngine::DocumentData> CppComprehensionEngine::create_docu
for (auto& header : included_document->m_available_headers)
document_data->m_available_headers.set(header);
for (auto item : included_document->parser().preprocessor_definitions())
preprocessor_definitions.set(move(item.key), move(item.value));
}
document_data->m_parser = make<Parser>(move(tokens), filename, move(preprocessor_definitions));
document_data->m_parser = make<Parser>(move(tokens), filename, document_data->preprocessor().definitions());
auto root = document_data->parser().parse();

View file

@ -15,7 +15,7 @@
namespace Cpp {
Parser::Parser(Vector<Token> const& tokens, const String& filename, Preprocessor::Definitions&& definitions)
Parser::Parser(Vector<Token> const& tokens, const String& filename, Preprocessor::Definitions const& definitions)
: m_preprocessor_definitions(move(definitions))
, m_filename(filename)
{

View file

@ -18,7 +18,7 @@ class Parser final {
AK_MAKE_NONCOPYABLE(Parser);
public:
explicit Parser(Vector<Token> const& tokens, const String& filename, Preprocessor::Definitions&& = {});
explicit Parser(Vector<Token> const& tokens, const String& filename, Preprocessor::Definitions const& = {});
~Parser() = default;
NonnullRefPtr<TranslationUnit> parse();

View file

@ -108,7 +108,12 @@ void Preprocessor::handle_preprocessor_keyword(const StringView& keyword, Generi
{
if (keyword == "include") {
consume_whitespace(line_lexer);
m_included_paths.append(line_lexer.consume_all());
auto include_path = line_lexer.consume_all();
m_included_paths.append(include_path);
if (definitions_in_header_callback) {
for (auto& def : definitions_in_header_callback(include_path))
m_definitions.set(def.key, def.value);
}
return;
}

View file

@ -7,6 +7,7 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/Optional.h>
#include <AK/String.h>
@ -36,6 +37,8 @@ public:
void set_ignore_unsupported_keywords(bool ignore) { m_options.ignore_unsupported_keywords = ignore; }
void set_keep_include_statements(bool keep) { m_options.keep_include_statements = keep; }
Function<Definitions(StringView)> definitions_in_header_callback { nullptr };
private:
using PreprocessorKeyword = StringView;
PreprocessorKeyword handle_preprocessor_line(StringView const&);