From: Nathan Sidwell Date: Tue, 8 Dec 2020 13:03:43 +0000 (-0800) Subject: c++: module directive FSM X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=76a1719f0ff8e802cd3124ec102da174e5c67f15;p=gcc.git c++: module directive FSM As mentioned in the preprocessor patches, there's a new kind of preprocessor directive for modules, and it interacts with the compiler-proper, as that has to stream in header-unit macro information (when the directive is an import that names a header-unit). This is that machinery. It's an FSM that inspects the token stream and does the minimal parsing to detect such imports. This ends up being called from the C++ parser's tokenizer and from the -E tokenizer (via a lang hook). The actual module streaming is a stub here. gcc/cp/ * cp-tree.h (module_token_pre, module_token_cdtor) (module_token_lang): Declare. * lex.c: Include langhooks. (struct module_token_filter): New. * cp-tree.h (module_token_pre, module_token_cdtor) (module_token_lang): Define. * module.cc (get_module, preprocess_module, preprocessed_module): Nop stubs. --- diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b72069eecda..aa2b0f782fa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6849,6 +6849,10 @@ extern void set_identifier_kind (tree, cp_identifier_kind); extern bool cxx_init (void); extern void cxx_finish (void); extern bool in_main_input_context (void); +extern uintptr_t module_token_pre (cpp_reader *, const cpp_token *, uintptr_t); +extern uintptr_t module_token_cdtor (cpp_reader *, uintptr_t); +extern uintptr_t module_token_lang (int type, int keyword, tree value, + location_t, uintptr_t); /* in method.c */ extern void init_method (void); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 795f5718198..6053848535e 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-objc.h" #include "gcc-rich-location.h" #include "cp-name-hint.h" +#include "langhooks.h" static int interface_strcmp (const char *); static void init_cp_pragma (void); @@ -380,7 +381,206 @@ interface_strcmp (const char* s) return 1; } - +/* We've just read a cpp-token, figure out our next state. Hey, this + is a hand-coded co-routine! */ + +struct module_token_filter +{ + enum state + { + idle, + module_first, + module_cont, + module_end, + }; + + enum state state : 8; + bool is_import : 1; + bool got_export : 1; + bool got_colon : 1; + bool want_dot : 1; + + location_t token_loc; + cpp_reader *reader; + module_state *module; + module_state *import; + + module_token_filter (cpp_reader *reader) + : state (idle), is_import (false), + got_export (false), got_colon (false), want_dot (false), + token_loc (UNKNOWN_LOCATION), + reader (reader), module (NULL), import (NULL) + { + }; + + /* Process the next token. Note we cannot see CPP_EOF inside a + pragma -- a CPP_PRAGMA_EOL always happens. */ + uintptr_t resume (int type, int keyword, tree value, location_t loc) + { + unsigned res = 0; + + switch (state) + { + case idle: + if (type == CPP_KEYWORD) + switch (keyword) + { + default: + break; + + case RID__EXPORT: + got_export = true; + res = lang_hooks::PT_begin_pragma; + break; + + case RID__IMPORT: + is_import = true; + /* FALLTHRU */ + case RID__MODULE: + state = module_first; + want_dot = false; + got_colon = false; + token_loc = loc; + import = NULL; + if (!got_export) + res = lang_hooks::PT_begin_pragma; + break; + } + break; + + case module_first: + if (is_import && type == CPP_HEADER_NAME) + { + /* A header name. The preprocessor will have already + done include searching and canonicalization. */ + state = module_end; + goto header_unit; + } + + if (type == CPP_PADDING || type == CPP_COMMENT) + break; + + state = module_cont; + if (type == CPP_COLON && module) + { + got_colon = true; + import = module; + break; + } + /* FALLTHROUGH */ + + case module_cont: + switch (type) + { + case CPP_PADDING: + case CPP_COMMENT: + break; + + default: + /* If we ever need to pay attention to attributes for + header modules, more logic will be needed. */ + state = module_end; + break; + + case CPP_COLON: + if (got_colon) + state = module_end; + got_colon = true; + /* FALLTHROUGH */ + case CPP_DOT: + if (!want_dot) + state = module_end; + want_dot = false; + break; + + case CPP_PRAGMA_EOL: + goto module_end; + + case CPP_NAME: + if (want_dot) + { + /* Got name instead of [.:]. */ + state = module_end; + break; + } + header_unit: + import = get_module (value, import, got_colon); + want_dot = true; + break; + } + break; + + case module_end: + if (type == CPP_PRAGMA_EOL) + { + module_end:; + /* End of the directive, handle the name. */ + if (import) + if (module_state *m + = preprocess_module (import, token_loc, module != NULL, + is_import, got_export, reader)) + if (!module) + module = m; + + is_import = got_export = false; + state = idle; + } + break; + } + + return res; + } +}; + +/* Initialize or teardown. */ + +uintptr_t +module_token_cdtor (cpp_reader *pfile, uintptr_t data_) +{ + if (module_token_filter *filter = reinterpret_cast (data_)) + { + preprocessed_module (pfile); + delete filter; + data_ = 0; + } + else if (modules_p ()) + data_ = reinterpret_cast (new module_token_filter (pfile)); + + return data_; +} + +uintptr_t +module_token_lang (int type, int keyword, tree value, location_t loc, + uintptr_t data_) +{ + module_token_filter *filter = reinterpret_cast (data_); + return filter->resume (type, keyword, value, loc); +} + +uintptr_t +module_token_pre (cpp_reader *pfile, const cpp_token *tok, uintptr_t data_) +{ + if (!tok) + return module_token_cdtor (pfile, data_); + + int type = tok->type; + int keyword = RID_MAX; + tree value = NULL_TREE; + + if (tok->type == CPP_NAME) + { + value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node.node)); + if (IDENTIFIER_KEYWORD_P (value)) + { + keyword = C_RID_CODE (value); + type = CPP_KEYWORD; + } + } + else if (tok->type == CPP_HEADER_NAME) + value = build_string (tok->val.str.len, (const char *)tok->val.str.text); + + return module_token_lang (type, keyword, value, tok->src_loc, data_); +} /* Parse a #pragma whose sole argument is a string constant. If OPT is true, the argument is optional. */ diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index f250d6c1819..91a16815811 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -64,3 +64,20 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "langhooks.h" +module_state * +get_module (tree, module_state *, bool) +{ + return nullptr; +} + +module_state * +preprocess_module (module_state *, unsigned, bool, bool, bool, cpp_reader *) +{ + return nullptr; +} + +void +preprocessed_module (cpp_reader *) +{ +} +