From 0c4dc00f01aa283e08bb04a6e10f9bc6627bdb25 Mon Sep 17 00:00:00 2001 From: Itamar Date: Fri, 6 Aug 2021 11:15:57 +0300 Subject: [PATCH] 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). --- .../Cpp/CppComprehensionEngine.cpp | 18 ++++++++++-------- Userland/Libraries/LibCpp/Parser.cpp | 2 +- Userland/Libraries/LibCpp/Parser.h | 2 +- Userland/Libraries/LibCpp/Preprocessor.cpp | 7 ++++++- Userland/Libraries/LibCpp/Preprocessor.h | 3 +++ 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp index fd07b4f370..84c776faff 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp @@ -569,11 +569,16 @@ OwnPtr CppComprehensionEngine::create_docu document_data->m_preprocessor = make(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::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(move(tokens), filename, move(preprocessor_definitions)); + document_data->m_parser = make(move(tokens), filename, document_data->preprocessor().definitions()); auto root = document_data->parser().parse(); diff --git a/Userland/Libraries/LibCpp/Parser.cpp b/Userland/Libraries/LibCpp/Parser.cpp index da0d479fda..4bcc5ecd67 100644 --- a/Userland/Libraries/LibCpp/Parser.cpp +++ b/Userland/Libraries/LibCpp/Parser.cpp @@ -15,7 +15,7 @@ namespace Cpp { -Parser::Parser(Vector const& tokens, const String& filename, Preprocessor::Definitions&& definitions) +Parser::Parser(Vector const& tokens, const String& filename, Preprocessor::Definitions const& definitions) : m_preprocessor_definitions(move(definitions)) , m_filename(filename) { diff --git a/Userland/Libraries/LibCpp/Parser.h b/Userland/Libraries/LibCpp/Parser.h index b21eca15bc..34e70bd7a6 100644 --- a/Userland/Libraries/LibCpp/Parser.h +++ b/Userland/Libraries/LibCpp/Parser.h @@ -18,7 +18,7 @@ class Parser final { AK_MAKE_NONCOPYABLE(Parser); public: - explicit Parser(Vector const& tokens, const String& filename, Preprocessor::Definitions&& = {}); + explicit Parser(Vector const& tokens, const String& filename, Preprocessor::Definitions const& = {}); ~Parser() = default; NonnullRefPtr parse(); diff --git a/Userland/Libraries/LibCpp/Preprocessor.cpp b/Userland/Libraries/LibCpp/Preprocessor.cpp index 85d5f143e4..cb7be70f7a 100644 --- a/Userland/Libraries/LibCpp/Preprocessor.cpp +++ b/Userland/Libraries/LibCpp/Preprocessor.cpp @@ -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; } diff --git a/Userland/Libraries/LibCpp/Preprocessor.h b/Userland/Libraries/LibCpp/Preprocessor.h index e3dd45aa40..6459a7582c 100644 --- a/Userland/Libraries/LibCpp/Preprocessor.h +++ b/Userland/Libraries/LibCpp/Preprocessor.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -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_in_header_callback { nullptr }; + private: using PreprocessorKeyword = StringView; PreprocessorKeyword handle_preprocessor_line(StringView const&);