From 3cf63c94df4712569e0ab996155013a3a043bed3 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 2 Sep 2020 16:47:37 -0400 Subject: [PATCH] c++: Add make_temp_override generator functions A common pattern before C++17 is the generator function, used to avoid having to specify the type of a container element by using a function call to get type deduction; for example, std::make_pair. C++17 added class type argument deduction, making generator functions unnecessary for many uses, but GCC won't be written in C++17 for years yet. gcc/cp/ChangeLog: * cp-tree.h (struct type_identity): New. (make_temp_override): New. * decl.c (grokdeclarator): Use it. * except.c (maybe_noexcept_warning): Use it. * parser.c (cp_parser_enum_specifier): Use it. (cp_parser_parameter_declaration_clause): Use it. (cp_parser_gnu_attributes_opt): Use it. (cp_parser_std_attribute): Use it. --- gcc/cp/cp-tree.h | 32 ++++++++++++++++++++++++++++++++ gcc/cp/decl.c | 2 +- gcc/cp/except.c | 2 +- gcc/cp/parser.c | 8 ++++---- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5304f6b..5cd2999 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1932,6 +1932,38 @@ public: ~temp_override() { overridden_variable = saved_value; } }; +/* Wrapping a template parameter in type_identity_t hides it from template + argument deduction. */ +#if __cpp_lib_type_identity +using std::type_identity_t; +#else +template +struct type_identity { typedef T type; }; +template +using type_identity_t = typename type_identity::type; +#endif + +/* Object generator function for temp_override, so you don't need to write the + type of the object as a template argument. + + Use as auto x = make_temp_override (flag); */ + +template +inline temp_override +make_temp_override (T& var) +{ + return { var }; +} + +/* Likewise, but use as auto x = make_temp_override (flag, value); */ + +template +inline temp_override +make_temp_override (T& var, type_identity_t overrider) +{ + return { var, overrider }; +} + /* The cached class binding level, from the most recently exited class, or NULL if none. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ae93fe1..b56eb11 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -11513,7 +11513,7 @@ grokdeclarator (const cp_declarator *declarator, /* An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ - temp_override ds (deprecated_state); + auto ds = make_temp_override (deprecated_state); if (attrlist && lookup_attribute ("deprecated", *attrlist)) deprecated_state = DEPRECATED_SUPPRESS; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 0f6c76b..e76ade2 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1101,7 +1101,7 @@ maybe_noexcept_warning (tree fn) && (!DECL_IN_SYSTEM_HEADER (fn) || global_dc->dc_warn_system_headers)) { - temp_override s (global_dc->dc_warn_system_headers, true); + auto s = make_temp_override (global_dc->dc_warn_system_headers, true); auto_diagnostic_group d; if (warning (OPT_Wnoexcept, "noexcept-expression evaluates to % " "because of a call to %qD", fn)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 39957d4..7ea8c28 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19732,7 +19732,7 @@ cp_parser_enum_specifier (cp_parser* parser) bool is_unnamed = false; tree underlying_type = NULL_TREE; cp_token *type_start_token = NULL; - temp_override cleanup (parser->colon_corrects_to_scope_p, false); + auto cleanup = make_temp_override (parser->colon_corrects_to_scope_p, false); /* Parse tentatively so that we can back up if we don't find a enum-specifier. */ @@ -23381,7 +23381,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser, cp_token *token; bool ellipsis_p; - temp_override cleanup + auto cleanup = make_temp_override (parser->auto_is_implicit_function_template_parm_p); if (!processing_specialization @@ -27488,7 +27488,7 @@ cp_parser_gnu_attributes_opt (cp_parser* parser) { tree attributes = NULL_TREE; - temp_override cleanup + auto cleanup = make_temp_override (parser->auto_is_implicit_function_template_parm_p, false); while (true) @@ -27688,7 +27688,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) tree attribute, attr_id = NULL_TREE, arguments; cp_token *token; - temp_override cleanup + auto cleanup = make_temp_override (parser->auto_is_implicit_function_template_parm_p, false); /* First, parse name of the attribute, a.k.a attribute-token. */ -- 2.7.4