[committed] d: Use weak linkage for template symbols instead of gnu.linkonce (PR99914)
Hi, This patch changes the default linkage of templates in the D language to be DECL_WEAK instead of DECL_ONE_ONLY, if supported. This better matches the expected override semantics of template symbols compiled to object code. For example: module rt.config; template rt_flag() { pragma(mangle, "rt_flag") __gshared bool rt_flag = true; } module main; extern(C) __gshared bool rt_flag = false; The above currently does not succeed in linking due to there being multiple definitions of `rt_flag' in different sections that aren't considered mergeable. The compiler flag enabling toggling of this has been given a clearer name `-fweak-templates', distinguishing itself from G++ `-fweak', which is intended for testing only. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and committed to mainline. Regards, Iain. --- gcc/d/ChangeLog: PR d/99914 * d-lang.cc (d_init): Disable flag_weak_templates if no support for weak or one-only symbols. * d-tree.h (VAR_OR_FUNCTION_DECL_CHECK): New macro. (DECL_INSTANTIATED): New macro. (d_comdat_linkage): Remove declaration. (d_linkonce_linkage): Remove declaration. (set_linkage_for_decl): New declaration. * decl.cc (DeclVisitor::visit (StructDeclaration *)): Replace call to d_linkonce_linkage with setting DECL_INSTANTIATED. (DeclVisitor::visit (ClassDeclaration *)): Likewise. (DeclVisitor::visit (EnumDeclaration *)): Likewise. (DeclVisitor::visit (InterfaceDeclaration *)): Remove call to d_linkonce_linkage. (get_symbol_decl): Call set_linkage_for_decl instead of d_linkonce_linkage. (d_finish_decl): Call set_linkage_for_decl. (d_comdat_linkage): Made function static. Only set DECL_COMDAT for DECL_INSTANTIATED decls. (d_linkonce_linkage): Remove function. (d_weak_linkage): New function. (set_linkage_for_decl): New function. * gdc.texi (Runtime Options): Rename -fno-weak to -fno-weak-templates, update documentation of option. * lang.opt (fweak): Rename option to ... (fweak-templates): ... this. Update help string. * modules.cc (get_internal_fn): Add Prot parameter. Set generated function flag. (build_internal_fn): Update call to get_internal_fn. (build_dso_cdtor_fn): Likewise. (register_moduleinfo): Call d_finish_decl on dso_slot_node and dso_initialized_node. * typeinfo.cc (TypeInfoVisitor::internal_reference): Call set_linkage_for_decl instead of d_comdat_linkage. (TypeInfoDeclVisitor::visit (TypeInfoDeclaration *)): Remove calls to d_linkonce_linkage and d_comdat_linkage. (get_cpp_typeinfo_decl): Likewise. gcc/testsuite/ChangeLog: PR d/99914 * gdc.dg/pr99914.d: New test. --- gcc/d/d-lang.cc| 2 +- gcc/d/d-tree.h | 15 -- gcc/d/decl.cc | 92 +- gcc/d/gdc.texi | 14 +++--- gcc/d/lang.opt | 6 +-- gcc/d/modules.cc | 20 +++- gcc/d/typeinfo.cc | 12 + gcc/testsuite/gdc.dg/pr99914.d | 5 ++ 8 files changed, 94 insertions(+), 72 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/pr99914.d diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 5028698a5bc..a65af290cb8 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -386,7 +386,7 @@ d_init (void) using_eh_for_cleanups (); if (!supports_one_only ()) -flag_weak = 0; +flag_weak_templates = 0; /* This is the C main, not the D main. */ main_identifier_node = get_identifier ("main"); diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index 724a0bfd87b..c1b6f275149 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -59,7 +59,13 @@ typedef Array Expressions; Usage of DECL_LANG_FLAG_?: 0: LABEL_VARIABLE_CASE (in LABEL_DECL). DECL_BUILT_IN_CTFE (in FUNCTION_DECL). - 1: DECL_IN_UNITTEST_CONDITION_P (in FUNCTION_DECL). */ + 1: DECL_IN_UNITTEST_CONDITION_P (in FUNCTION_DECL). + 2: DECL_INSTANTIATED (in FUNCTION_DECL, VAR_DECL). */ + +/* Language-specific tree checkers. */ + +#define VAR_OR_FUNCTION_DECL_CHECK(NODE) \ + TREE_CHECK2 (NODE, VAR_DECL, FUNCTION_DECL) /* The kinds of scopes we recognize. */ @@ -388,6 +394,10 @@ lang_tree_node #define DECL_IN_UNITTEST_CONDITION_P(NODE) \ (DECL_LANG_FLAG_1 (FUNCTION_DECL_CHECK (NODE))) +/* True if the decl comes from a template instance. */ +#define DECL_INSTANTIATED(NODE) \ + (DECL_LANG_FLAG_1 (VAR_OR_FUNCTION_DECL_CHECK (NODE))) + enum d_tree_index { DTI_VTABLE_ENTRY_TYPE, @@ -631,8 +641,7 @@ extern tree enum_initializer_decl (EnumDeclaration *); extern tree build_artificial_decl (tree, tree, const char * = NULL); extern tree create_field_decl (tree, const char *, int, int); extern void build_type_decl (tree, Dsymbol *); -extern void
Re: [PATCH RFC] c++: Fix print-tree module handling for TEMPLATE_DECL
On 4/3/21 10:54 AM, Jason Merrill wrote: The if allows TEMPLATE_DECL, but then checking DECL_MODULE_IMPORT_P crashes on TEMPLATE_DECL. Fixed by stripping TEMPLATE_DECL first. Nathan, does this look right to you? gcc/cp/ChangeLog: * ptree.c (cxx_print_decl): Check DECL_MODULE_IMPORT_P on template result. Yes, this is probably more useful than just not looking at template_decl's instance of these flags. Just shows how little I've had to use the printer recently :) --- gcc/cp/ptree.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 95a4fdf284a..33b73fb24b6 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -59,16 +59,16 @@ cxx_print_decl (FILE *file, tree node, int indent) bool need_indent = true; - if (TREE_CODE (node) == FUNCTION_DECL - || TREE_CODE (node) == VAR_DECL - || TREE_CODE (node) == TYPE_DECL - || TREE_CODE (node) == TEMPLATE_DECL - || TREE_CODE (node) == CONCEPT_DECL - || TREE_CODE (node) == NAMESPACE_DECL) + tree ntnode = STRIP_TEMPLATE (node); + if (TREE_CODE (ntnode) == FUNCTION_DECL + || TREE_CODE (ntnode) == VAR_DECL + || TREE_CODE (ntnode) == TYPE_DECL + || TREE_CODE (ntnode) == CONCEPT_DECL + || TREE_CODE (ntnode) == NAMESPACE_DECL) { unsigned m = 0; - if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_IMPORT_P (node)) - m = get_importing_module (node, true); + if (DECL_LANG_SPECIFIC (ntnode) && DECL_MODULE_IMPORT_P (ntnode)) + m = get_importing_module (ntnode, true); if (const char *name = m == ~0u ? "" : module_name (m, true)) { @@ -78,7 +78,7 @@ cxx_print_decl (FILE *file, tree node, int indent) need_indent = false; } - if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_PURVIEW_P (node)) + if (DECL_LANG_SPECIFIC (ntnode) && DECL_MODULE_PURVIEW_P (ntnode)) { if (need_indent) indent_to (file, indent + 3); base-commit: a40015780f8cc49476741b6914bd5ee97bd10f1d -- Nathan Sidwell
[pushed] c++: constexpr if and nested generic lambda [PR99201]
When building up *_EXTRA_ARGS for a constexpr if or pack expansion, we need to walk into the body of a lambda to find all the local_specializations that we need to remember, like we do in find_parameter_packs_r. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/99201 * pt.c (class el_data): Add visited field. (extract_local_specs): Pass it to cp_walk_tree. (extract_locals_r): Walk into the body of a lambda. gcc/testsuite/ChangeLog: PR c++/99201 * g++.dg/cpp1z/constexpr-if-lambda4.C: New test. --- gcc/cp/pt.c | 15 - .../g++.dg/cpp1z/constexpr-if-lambda4.C | 22 +++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda4.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2763aa15f1f..1d19a59dd62 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12757,7 +12757,11 @@ tsubst_binary_right_fold (tree t, tree args, tsubst_flags_t complain, class el_data { public: + /* Set of variables declared within the pattern. */ hash_set internal; + /* Set of AST nodes that have been visited by the traversal. */ + hash_set visited; + /* List of local_specializations used within the pattern. */ tree extra; tsubst_flags_t complain; @@ -12777,6 +12781,15 @@ extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data_) if (TREE_CODE (*tp) == DECL_EXPR) data.internal.add (DECL_EXPR_DECL (*tp)); + else if (TREE_CODE (*tp) == LAMBDA_EXPR) +{ + /* Since we defer implicit capture, look in the parms and body. */ + tree fn = lambda_function (*tp); + cp_walk_tree (&TREE_TYPE (fn), &extract_locals_r, &data, + &data.visited); + cp_walk_tree (&DECL_SAVED_TREE (fn), &extract_locals_r, &data, + &data.visited); +} else if (tree spec = retrieve_local_specialization (*tp)) { if (data.internal.contains (*tp)) @@ -12833,7 +12846,7 @@ static tree extract_local_specs (tree pattern, tsubst_flags_t complain) { el_data data (complain); - cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &data); + cp_walk_tree (&pattern, extract_locals_r, &data, &data.visited); return data.extra; } diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda4.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda4.C new file mode 100644 index 000..99408025629 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda4.C @@ -0,0 +1,22 @@ +// PR c++/99201 +// { dg-do compile { target c++17 } } + +template + auto + make_tester(const RefF& reffun) + { +return [=](auto in) { + auto&& expected = [&](const auto&... vs) { +if constexpr (sizeof(in) > 0) + return [&](int i) { return reffun(vs[i]...); }(0); +else + return [&](int i) { return reffun(vs[i]...); }(0); + }; +}; + } + +int main() +{ + make_tester([](int x) { return x; })(0); + return 0; +} base-commit: a44a753a35542f86e82e198595ce3553f6d718f6 -- 2.27.0
[pushed] c++: extern template and static data member [PR99066]
'extern template' should mean that the relevant symbols are never emitted. But in this case we were assuming that DECL_EXTERNAL was already set on the variable, so we just needed to clear DECL_NOT_REALLY_EXTERN. Since DECL_EXTERNAL was not set, we emitted a definition of npos. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/99066 * pt.c (mark_decl_instantiated): Set DECL_EXTERNAL. gcc/testsuite/ChangeLog: PR c++/99066 * g++.dg/cpp0x/extern_template-6.C: New test. --- gcc/cp/pt.c| 5 - gcc/testsuite/g++.dg/cpp0x/extern_template-6.C | 17 + 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/extern_template-6.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1d19a59dd62..396e622c4db 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -24204,7 +24204,10 @@ mark_decl_instantiated (tree result, int extern_p) DECL_COMDAT (result) = 0; if (extern_p) -DECL_NOT_REALLY_EXTERN (result) = 0; +{ + DECL_EXTERNAL (result) = 1; + DECL_NOT_REALLY_EXTERN (result) = 0; +} else { mark_definable (result); diff --git a/gcc/testsuite/g++.dg/cpp0x/extern_template-6.C b/gcc/testsuite/g++.dg/cpp0x/extern_template-6.C new file mode 100644 index 000..8aff3ae6b02 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/extern_template-6.C @@ -0,0 +1,17 @@ +// PR c++/99066 +// { dg-do compile { target c++11 } } + +template struct basic_string { + static const int npos = 1; +}; +template const int basic_string::npos; + +struct e { template int f() const; }; + +template int e::f() const { + return basic_string::npos; +} + +extern template class basic_string; + +// { dg-final { scan-assembler-not "_ZN12basic_stringIcE4nposE" } } base-commit: a99a7b0afe9a1f6f866e25b8572856ae8c1d3f8d -- 2.27.0
Re: [PATCH 2/3] x86: Update memcpy/memset inline strategies for Skylake family CPUs
On Mon, Mar 22, 2021 at 6:16 AM H.J. Lu wrote: > > Simply memcpy and memset inline strategies to avoid branches for > Skylake family CPUs: > > 1. With MOVE_RATIO and CLEAR_RATIO == 17, GCC will use integer/vector >load and store for up to 16 * 16 (256) bytes when the data size is >fixed and known. > 2. Inline only if data size is known to be <= 256. >a. Use "rep movsb/stosb" with simple code sequence if the data size > is a constant. >b. Use loop if data size is not a constant. > 3. Use memcpy/memset libray function if data size is unknown or > 256. > > On Cascadelake processor with -march=native -Ofast -flto, > > 1. Performance impacts of SPEC CPU 2017 rate are: > > 500.perlbench_r 0.17% > 502.gcc_r -0.36% > 505.mcf_r0.00% > 520.omnetpp_r0.08% > 523.xalancbmk_r -0.62% > 525.x264_r 1.04% > 531.deepsjeng_r 0.11% > 541.leela_r -1.09% > 548.exchange2_r -0.25% > 557.xz_r 0.17% > Geomean -0.08% > > 503.bwaves_r 0.00% > 507.cactuBSSN_r 0.69% > 508.namd_r -0.07% > 510.parest_r 1.12% > 511.povray_r 1.82% > 519.lbm_r0.00% > 521.wrf_r -1.32% > 526.blender_r -0.47% > 527.cam4_r 0.23% > 538.imagick_r -1.72% > 544.nab_r -0.56% > 549.fotonik3d_r 0.12% > 554.roms_r 0.43% > Geomean 0.02% > > 2. Significant impacts on eembc benchmarks are: > > eembc/idctrn01 9.23% > eembc/nnet_test 29.26% > > gcc/ > > * config/i386/x86-tune-costs.h (skylake_memcpy): Updated. > (skylake_memset): Likewise. > (skylake_cost): Change CLEAR_RATIO to 17. > * config/i386/x86-tune.def (X86_TUNE_PREFER_KNOWN_REP_MOVSB_STOSB): > Replace m_CANNONLAKE, m_ICELAKE_CLIENT, m_ICELAKE_SERVER, > m_TIGERLAKE and m_SAPPHIRERAPIDS with m_SKYLAKE and m_CORE_AVX512. > > gcc/testsuite/ > > * gcc.target/i386/memcpy-strategy-9.c: New test. > * gcc.target/i386/memcpy-strategy-10.c: Likewise. > * gcc.target/i386/memcpy-strategy-11.c: Likewise. > * gcc.target/i386/memset-strategy-7.c: Likewise. > * gcc.target/i386/memset-strategy-8.c: Likewise. > * gcc.target/i386/memset-strategy-9.c: Likewise. > --- > gcc/config/i386/x86-tune-costs.h | 27 --- > gcc/config/i386/x86-tune.def | 3 +-- > .../gcc.target/i386/memcpy-strategy-10.c | 11 > .../gcc.target/i386/memcpy-strategy-11.c | 18 + > .../gcc.target/i386/memcpy-strategy-9.c | 9 +++ > .../gcc.target/i386/memset-strategy-7.c | 11 > .../gcc.target/i386/memset-strategy-8.c | 9 +++ > .../gcc.target/i386/memset-strategy-9.c | 17 > 8 files changed, 93 insertions(+), 12 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/memcpy-strategy-10.c > create mode 100644 gcc/testsuite/gcc.target/i386/memcpy-strategy-11.c > create mode 100644 gcc/testsuite/gcc.target/i386/memcpy-strategy-9.c > create mode 100644 gcc/testsuite/gcc.target/i386/memset-strategy-7.c > create mode 100644 gcc/testsuite/gcc.target/i386/memset-strategy-8.c > create mode 100644 gcc/testsuite/gcc.target/i386/memset-strategy-9.c > > diff --git a/gcc/config/i386/x86-tune-costs.h > b/gcc/config/i386/x86-tune-costs.h > index 0e00ff99df3..ffe810f2bcb 100644 > --- a/gcc/config/i386/x86-tune-costs.h > +++ b/gcc/config/i386/x86-tune-costs.h > @@ -1822,17 +1822,24 @@ struct processor_costs znver3_cost = { > > /* skylake_cost should produce code tuned for Skylake familly of CPUs. */ > static stringop_algs skylake_memcpy[2] = { > - {libcall, {{1024, rep_prefix_4_byte, true}, {-1, libcall, false}}}, > - {libcall, {{16, loop, false}, {512, unrolled_loop, false}, > - {-1, libcall, false; > + {libcall, > + {{256, rep_prefix_1_byte, true}, > +{256, loop, false}, > +{-1, libcall, false}}}, > + {libcall, > + {{256, rep_prefix_1_byte, true}, > +{256, loop, false}, > +{-1, libcall, false; > > static stringop_algs skylake_memset[2] = { > - {libcall, {{6, loop_1_byte, true}, > - {24, loop, true}, > - {8192, rep_prefix_4_byte, true}, > - {-1, libcall, false}}}, > - {libcall, {{24, loop, true}, {512, unrolled_loop, false}, > - {-1, libcall, false; > + {libcall, > + {{256, rep_prefix_1_byte, true}, > +{256, loop, false}, > +{-1, libcall, false}}}, > + {libcall, > + {{256, rep_prefix_1_byte, true}, > +{256, loop, false}, > +{-1, libcall, false; > > static const > struct processor_costs skylake_cost = { > @@ -1889,7 +1896,7 @@ struct processor_costs skylake_cost = { >COSTS_N_INSNS (0), /* cost of movzx */ >8, /* "large" insn */ >17, /* MOVE_RATIO */ > - 6, /* CLEAR_RATIO */ > + 17, /* CLEAR_RATIO */ >{4, 4, 4},
c++: Unneeded export query [PR 99380]
This problem got introduced fixing a module numbering problem. When preprocessing a header unit, we don't need to send an EXPORT query unless we're also determining dependencies, or the mapper askedus to. Sadly the testsuite isn't set up to test this kind of subtlety. I manually did that with stdin/stdout. PR c++/99380 gcc/cp/ * module.cc (name_pending_imports): Drop 'atend' parm. Don't query export when not needed. (preprocess_module, preprocessed_module): Adjust. -- Nathan Sidwell diff --git i/gcc/cp/module.cc w/gcc/cp/module.cc index d5b7d28ded5..c80c7bcc70f 100644 --- i/gcc/cp/module.cc +++ w/gcc/cp/module.cc @@ -19262,15 +19262,11 @@ module_begin_main_file (cpp_reader *reader, line_maps *lmaps, filenames. */ static void -name_pending_imports (cpp_reader *reader, bool at_end) +name_pending_imports (cpp_reader *reader) { auto *mapper = get_mapper (cpp_main_loc (reader)); - bool only_headers = (flag_preprocess_only - && !bool (mapper->get_flags () & Cody::Flags::NameOnly) - && !cpp_get_deps (reader)); - if (at_end - && (!vec_safe_length (pending_imports) || only_headers)) + if (!vec_safe_length (pending_imports)) /* Not doing anything. */ return; @@ -19278,40 +19274,56 @@ name_pending_imports (cpp_reader *reader, bool at_end) auto n = dump.push (NULL); dump () && dump ("Resolving direct import names"); + bool want_deps = (bool (mapper->get_flags () & Cody::Flags::NameOnly) + || cpp_get_deps (reader)); + bool any = false; - mapper->Cork (); for (unsigned ix = 0; ix != pending_imports->length (); ix++) { module_state *module = (*pending_imports)[ix]; gcc_checking_assert (module->is_direct ()); - if (!module->filename - && !module->visited_p - && (module->is_header () || !only_headers)) + if (!module->filename && !module->visited_p) { - module->visited_p = true; - Cody::Flags flags = (flag_preprocess_only - ? Cody::Flags::None : Cody::Flags::NameOnly); + bool export_p = (module->module_p + && (module->is_partition () || module->exported_p)); - if (module->module_p - && (module->is_partition () || module->exported_p)) + Cody::Flags flags = Cody::Flags::None; + if (flag_preprocess_only + && !(module->is_header () && !export_p)) + { + if (!want_deps) + continue; + flags = Cody::Flags::NameOnly; + } + + if (!any) + { + any = true; + mapper->Cork (); + } + if (export_p) mapper->ModuleExport (module->get_flatname (), flags); else mapper->ModuleImport (module->get_flatname (), flags); + module->visited_p = true; } } - - auto response = mapper->Uncork (); - auto r_iter = response.begin (); - for (unsigned ix = 0; ix != pending_imports->length (); ix++) + + if (any) { - module_state *module = (*pending_imports)[ix]; - if (module->visited_p) + auto response = mapper->Uncork (); + auto r_iter = response.begin (); + for (unsigned ix = 0; ix != pending_imports->length (); ix++) { - module->visited_p = false; - gcc_checking_assert (!module->filename); + module_state *module = (*pending_imports)[ix]; + if (module->visited_p) + { + module->visited_p = false; + gcc_checking_assert (!module->filename); - module->set_filename (*r_iter); - ++r_iter; + module->set_filename (*r_iter); + ++r_iter; + } } } @@ -19384,7 +19396,7 @@ preprocess_module (module_state *module, location_t from_loc, unsigned n = dump.push (NULL); dump () && dump ("Reading %M preprocessor state", module); - name_pending_imports (reader, false); + name_pending_imports (reader); /* Preserve the state of the line-map. */ unsigned pre_hwm = LINEMAPS_ORDINARY_USED (line_table); @@ -19446,7 +19458,7 @@ preprocessed_module (cpp_reader *reader) dump () && dump ("Completed phase-4 (tokenization) processing"); - name_pending_imports (reader, true); + name_pending_imports (reader); vec_free (pending_imports); spans.maybe_init ();
[committed] analyzer: fix apparent hang with -fanalyzer-verbosity=0 [PR analyzer/99886]
The analyzer appeared to enter an infinite loop on malloc-1.c when -fanalyzer-verbosity=0 was used. In fact, it was slowly counting from 0 to 0x. Root cause is looping up to effectively ((unsigned)0) - 1 in diagnostic_manager::consolidate_conditions when there are no events in the path. Fixed by the following, which uses signed integers when subtracting from path->num_events () when simplifying checker_paths. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r11-7987-g69b66ff02353a87585329bb3cf4ac20d6dee1b16. gcc/analyzer/ChangeLog: PR analyzer/99886 * diagnostic-manager.cc (diagnostic_manager::prune_interproc_events): Use signed integers when subtracting one from path->num_events (). (diagnostic_manager::consolidate_conditions): Likewise. Convert next_idx to a signed int. gcc/testsuite/ChangeLog: PR analyzer/99886 * gcc.dg/analyzer/pr99886.c: New test. --- gcc/analyzer/diagnostic-manager.cc | 8 +--- gcc/testsuite/gcc.dg/analyzer/pr99886.c | 21 + 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr99886.c diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 9ec3e899e85..443ff058f65 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -2081,7 +2081,7 @@ diagnostic_manager::prune_interproc_events (checker_path *path) const do { changed = false; - int idx = path->num_events () - 1; + int idx = (signed)path->num_events () - 1; while (idx >= 0) { /* Prune [..., call, function-entry, return, ...] triples. */ @@ -2200,7 +2200,9 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const if (flag_analyzer_verbose_edges) return; - for (unsigned start_idx = 0; start_idx < path->num_events () - 1; start_idx++) + for (int start_idx = 0; + start_idx < (signed)path->num_events () - 1; + start_idx++) { if (path->cfg_edge_pair_at_p (start_idx)) { @@ -2231,7 +2233,7 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const [start_idx, next_idx) where all apart from the final event are on the same line, and all are either TRUE or FALSE edges, matching the initial. */ - unsigned next_idx = start_idx + 2; + int next_idx = start_idx + 2; while (path->cfg_edge_pair_at_p (next_idx) && same_line_as_p (start_exp_loc, path, next_idx)) { diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99886.c b/gcc/testsuite/gcc.dg/analyzer/pr99886.c new file mode 100644 index 000..da768ba6298 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr99886.c @@ -0,0 +1,21 @@ +/* Regression test for hang with -fanalyzer-verbosity=0. */ +/* { dg-additional-options "-fanalyzer-verbosity=0" } */ + +#include + +struct coord { + float x; + float y; +}; + +void test_34 (void) +{ + float *q; + struct coord *p = malloc (sizeof (struct coord)); + if (!p) +return; + p->x = 0.0f; + q = &p->x; + free (p); + *q = 1.0f; /* { dg-warning "use after 'free' of 'q'" } */ +}; -- 2.26.2
[committed] analyzer: fix ICE on zero-arg calls passed to __attribute__((nonnull)) [PR 99906]
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r11-7988-g7d8f4240c94e2e7643ac13cda1fdd0bb6ca3a3fb. gcc/analyzer/ChangeLog: PR analyzer/99906 * analyzer.cc (maybe_reconstruct_from_def_stmt): Fix NULL dereference on calls with zero arguments. * sm-malloc.cc (malloc_state_machine::on_stmt): When handling __attribute__((nonnull)), only call get_diagnostic_tree if the result will be used. gcc/testsuite/ChangeLog: PR analyzer/99906 * gcc.dg/analyzer/pr99906.c: New test. --- gcc/analyzer/analyzer.cc| 2 +- gcc/analyzer/sm-malloc.cc | 3 ++- gcc/testsuite/gcc.dg/analyzer/pr99906.c | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr99906.c diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc index 2b4cffd08f5..12c03f6cfbd 100644 --- a/gcc/analyzer/analyzer.cc +++ b/gcc/analyzer/analyzer.cc @@ -148,7 +148,7 @@ maybe_reconstruct_from_def_stmt (tree ssa_name, } return build_call_array_loc (gimple_location (call_stmt), return_type, fn, -num_args, &args[0]); +num_args, args.address ()); } break; } diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index ae03b068a88..1d5b8601b1f 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -1600,11 +1600,11 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, if (bitmap_empty_p (nonnull_args) || bitmap_bit_p (nonnull_args, i)) { - tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); state_t state = sm_ctxt->get_state (stmt, arg); /* Can't use a switch as the states are non-const. */ if (unchecked_p (state)) { + tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, new possible_null_arg (*this, diag_arg, callee_fndecl, @@ -1616,6 +1616,7 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt, } else if (state == m_null) { + tree diag_arg = sm_ctxt->get_diagnostic_tree (arg); sm_ctxt->warn (node, stmt, arg, new null_arg (*this, diag_arg, callee_fndecl, i)); diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99906.c b/gcc/testsuite/gcc.dg/analyzer/pr99906.c new file mode 100644 index 000..bb399a3e2ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr99906.c @@ -0,0 +1,3 @@ +void bar(void *) __attribute__((__nonnull__)); +void *baz(void); +void foo(void) { bar(baz()); } -- 2.26.2
[PATCH] c++: placeholder type constraint on structured binding [PR99899]
In this PR, we're crashing because the constraint handling inside do_auto_deduction doesn't expect to see an adc_decomp_type context. This patch fixes this by treating adc_decomp_type like adc_variable_type and adc_return_type during the constraint handling. Meanwhile, I noticed we weren't checking constraints at all when binding an array via a structured binding, since do_auto_deduction would exit early and bypass the constraint check. This patch fixes this by replacing the early exit with an appropriate setup of the 'targs' vector. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? gcc/cp/ChangeLog: PR c++/99899 * pt.c (do_auto_deduction): Don't exit early when deducing the array type of a structured binding. Also handle adc_decomp_type during constraint checking. gcc/testsuite/ChangeLog: PR c++/99899 * g++.dg/cpp2a/concepts-placeholder7.C: New test. --- gcc/cp/pt.c | 22 +++- .../g++.dg/cpp2a/concepts-placeholder7.C | 34 +++ 2 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1d19a59dd62..0f9f5858038 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29438,8 +29438,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, tsubst_flags_t complain, auto_deduction_context context, tree outer_targs, int flags) { - tree targs; - if (init == error_mark_node) return error_mark_node; @@ -29503,14 +29501,19 @@ do_auto_deduction (tree type, tree init, tree auto_node, else init = resolve_nondeduced_context (init, complain); + tree targs; if (context == adc_decomp_type && auto_node == type && init != error_mark_node && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) -/* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers - and initializer has array type, deduce cv-qualified array type. */ -return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), -complain); +{ + /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers +and initializer has array type, deduce cv-qualified array type. */ + targs = make_tree_vec (1); + TREE_VEC_ELT (targs, 0) + = cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), + complain); +} else if (AUTO_IS_DECLTYPE (auto_node)) { tree stripped_init = tree_strip_any_location_wrapper (init); @@ -29596,7 +29599,8 @@ do_auto_deduction (tree type, tree init, tree auto_node, if (processing_template_decl) { gcc_checking_assert (context == adc_variable_type - || context == adc_return_type); + || context == adc_return_type + || context == adc_decomp_type); gcc_checking_assert (!type_dependent_expression_p (init)); /* If the constraint is dependent, we need to wait until instantiation time to resolve the placeholder. */ @@ -29604,7 +29608,9 @@ do_auto_deduction (tree type, tree init, tree auto_node, return type; } - if ((context == adc_return_type || context == adc_variable_type) + if ((context == adc_return_type + || context == adc_variable_type + || context == adc_decomp_type) && current_function_decl && DECL_TEMPLATE_INFO (current_function_decl)) outer_targs = DECL_TI_ARGS (current_function_decl); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C new file mode 100644 index 000..db352a01e83 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C @@ -0,0 +1,34 @@ +// PR c++/99899 +// { dg-do compile { target c++20 } } + +template concept C1 = sizeof(T) > sizeof(int[1]); + +template +void f() { + int x[] = {1,2}; + int y[] = {3}; + C1 auto [a,b] = x; + C1 auto [c] = y; // { dg-error "constraints" } +} + +template +void g() { + T x[] = {1,2}; + T y[] = {3}; + C1 auto [a,b] = x; + C1 auto [c] = y; // { dg-error "constraints" } +} + +template void g(); + + +template concept C2 = sizeof...(Ts) > 1; + +struct S { int a, b; } s; + +template +void h() { + const C2 auto& [a, b] = s; +} + +template void h(); -- 2.31.1.189.g2e36527f23
Re: [PATCH] c++: placeholder type constraint on structured binding [PR99899]
On Mon, 5 Apr 2021, Patrick Palka wrote: > In this PR, we're crashing because the constraint handling inside > do_auto_deduction doesn't expect to see an adc_decomp_type context. > This patch fixes this by treating adc_decomp_type like adc_variable_type > and adc_return_type during the constraint handling. > > Meanwhile, I noticed we weren't checking constraints at all when binding > an array via a structured binding, since do_auto_deduction would exit > early and bypass the constraint check. This patch fixes this by > replacing the early exit with an appropriate setup of the 'targs' > vector. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk? > > gcc/cp/ChangeLog: > > PR c++/99899 > * pt.c (do_auto_deduction): Don't exit early when deducing the > array type of a structured binding. Also handle adc_decomp_type > during constraint checking. > > gcc/testsuite/ChangeLog: > > PR c++/99899 > * g++.dg/cpp2a/concepts-placeholder7.C: New test. > --- > gcc/cp/pt.c | 22 +++- > .../g++.dg/cpp2a/concepts-placeholder7.C | 34 +++ > 2 files changed, 48 insertions(+), 8 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index 1d19a59dd62..0f9f5858038 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -29438,8 +29438,6 @@ do_auto_deduction (tree type, tree init, tree > auto_node, > tsubst_flags_t complain, auto_deduction_context context, > tree outer_targs, int flags) > { > - tree targs; > - >if (init == error_mark_node) > return error_mark_node; > > @@ -29503,14 +29501,19 @@ do_auto_deduction (tree type, tree init, tree > auto_node, >else > init = resolve_nondeduced_context (init, complain); > > + tree targs; >if (context == adc_decomp_type >&& auto_node == type >&& init != error_mark_node >&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) > -/* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers > - and initializer has array type, deduce cv-qualified array type. */ > -return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), > - complain); > +{ > + /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers > + and initializer has array type, deduce cv-qualified array type. */ > + targs = make_tree_vec (1); > + TREE_VEC_ELT (targs, 0) > + = cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), > + complain); On second thought, I think we can get away with using just TREE_TYPE (init) here and leaving the propagation of type qualifiers to tsubst. This has the effect of making us reject the testcase placeholder8.C below, which is consistent with the non-array case. IIUC, the type qualifiers on a constrained 'auto' shouldn't be relevant during constraint checking. I'm testing the following: -- >8 -- gcc/cp/ChangeLog: PR c++/99899 * pt.c (do_auto_deduction): Don't exit early when deducing the array type of a structured binding. Also handle adc_decomp_type during constraint checking. gcc/testsuite/ChangeLog: PR c++/99899 * g++.dg/cpp2a/concepts-placeholder7.C: New test. * g++.dg/cpp2a/concepts-placeholder8.C: New test. --- gcc/cp/pt.c | 20 +++- .../g++.dg/cpp2a/concepts-placeholder7.C | 32 +++ .../g++.dg/cpp2a/concepts-placeholder8.C | 10 ++ 3 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder8.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1d19a59dd62..fd1e4db42cf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29438,8 +29438,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, tsubst_flags_t complain, auto_deduction_context context, tree outer_targs, int flags) { - tree targs; - if (init == error_mark_node) return error_mark_node; @@ -29503,14 +29501,17 @@ do_auto_deduction (tree type, tree init, tree auto_node, else init = resolve_nondeduced_context (init, complain); + tree targs; if (context == adc_decomp_type && auto_node == type && init != error_mark_node && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) -/* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers - and initializer has array type, deduce cv-qualified array type. */ -return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), -complain); +{ + /* [dcl.struct.bind]/1 - if decomposition declaration has no ref-qualifiers +
[c-family] Fix small regression with -fdump-ada-spec
When the enumeration constants of an enumeration type are defined by explicit values, the binding generated by -fdump-ada-spec does not use an enumeration type on the Ada side, because the set of allowed values in C/C++ is larger than the set of allowed values in Ada, but instead use an integer subtype and defines a set of explicit constants, which used to be of this subtype but were changed to the base type at some point. This reinstates the subtype for them. Tested on x86-64/Linux, applied on the mainline. 2021-04-05 Eric Botcazou * c-ada-spec.c (is_simple_enum): Minor tweaks. (dump_ada_enum_type): Add TYPE and PARENT parameters. For non-simple enumeral types, use again the type name for the enumeration constants. (dump_ada_node): Adjust call to dump_ada_enum_type. (dump_nested_type): Likewise. -- Eric Botcazoudiff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index dd8e8bbd90a..9fef5f05cc8 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -1932,8 +1932,8 @@ dump_ada_template (pretty_printer *buffer, tree t, int spc) return num_inst > 0; } -/* Return true if NODE is a simple enum types, that can be mapped to an - Ada enum type directly. */ +/* Return true if NODE is a simple enumeral type that can be mapped to an + Ada enumeration type directly. */ static bool is_simple_enum (tree node) @@ -1947,9 +1947,7 @@ is_simple_enum (tree node) if (TREE_CODE (int_val) != INTEGER_CST) int_val = DECL_INITIAL (int_val); - if (!tree_fits_shwi_p (int_val)) - return false; - else if (tree_to_shwi (int_val) != count) + if (!tree_fits_shwi_p (int_val) || tree_to_shwi (int_val) != count) return false; count++; @@ -1958,11 +1956,12 @@ is_simple_enum (tree node) return true; } -/* Dump in BUFFER an enumeral type NODE in Ada syntax. SPC is the indentation - level. */ +/* Dump in BUFFER the declaration of enumeral NODE of type TYPE in Ada syntax. + PARENT is the parent node of NODE. SPC is the indentation level. */ static void -dump_ada_enum_type (pretty_printer *buffer, tree node, int spc) +dump_ada_enum_type (pretty_printer *buffer, tree node, tree type, tree parent, + int spc) { if (is_simple_enum (node)) { @@ -1993,25 +1992,29 @@ dump_ada_enum_type (pretty_printer *buffer, tree node, int spc) pp_string (buffer, "unsigned"); else pp_string (buffer, "int"); + for (tree value = TYPE_VALUES (node); value; value = TREE_CHAIN (value)) { + tree int_val = TREE_VALUE (value); + + if (TREE_CODE (int_val) != INTEGER_CST) + int_val = DECL_INITIAL (int_val); + pp_semicolon (buffer); newline_and_indent (buffer, spc); pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node, false); pp_string (buffer, " : constant "); - if (TYPE_UNSIGNED (node)) - pp_string (buffer, "unsigned"); + if (TYPE_NAME (node)) + dump_ada_node (buffer, node, NULL_TREE, spc, false, true); + else if (type) + dump_ada_node (buffer, type, NULL_TREE, spc, false, true); else - pp_string (buffer, "int"); + dump_anonymous_type_name (buffer, node, parent); pp_string (buffer, " := "); - dump_ada_node (buffer, - TREE_CODE (TREE_VALUE (value)) == INTEGER_CST - ? TREE_VALUE (value) - : DECL_INITIAL (TREE_VALUE (value)), - node, spc, false, true); + dump_ada_node (buffer, int_val, node, spc, false, true); } } } @@ -2098,7 +2101,7 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, if (name_only) dump_ada_node (buffer, TYPE_NAME (node), node, spc, false, true); else - dump_ada_enum_type (buffer, node, spc); + dump_ada_enum_type (buffer, node, type, NULL_TREE, spc); break; case REAL_TYPE: @@ -2577,7 +2580,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, else dump_anonymous_type_name (buffer, field_type, parent); pp_string (buffer, " is "); - dump_ada_enum_type (buffer, field_type, spc); + dump_ada_enum_type (buffer, field_type, NULL_TREE, parent, spc); pp_semicolon (buffer); newline_and_indent (buffer, spc); break;
Re: [PATCH] c++: placeholder type constraint on structured binding [PR99899]
On 4/5/21 12:31 PM, Patrick Palka wrote: On Mon, 5 Apr 2021, Patrick Palka wrote: In this PR, we're crashing because the constraint handling inside do_auto_deduction doesn't expect to see an adc_decomp_type context. This patch fixes this by treating adc_decomp_type like adc_variable_type and adc_return_type during the constraint handling. Meanwhile, I noticed we weren't checking constraints at all when binding an array via a structured binding, since do_auto_deduction would exit early and bypass the constraint check. This patch fixes this by replacing the early exit with an appropriate setup of the 'targs' vector. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? OK. gcc/cp/ChangeLog: PR c++/99899 * pt.c (do_auto_deduction): Don't exit early when deducing the array type of a structured binding. Also handle adc_decomp_type during constraint checking. gcc/testsuite/ChangeLog: PR c++/99899 * g++.dg/cpp2a/concepts-placeholder7.C: New test. --- gcc/cp/pt.c | 22 +++- .../g++.dg/cpp2a/concepts-placeholder7.C | 34 +++ 2 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1d19a59dd62..0f9f5858038 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29438,8 +29438,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, tsubst_flags_t complain, auto_deduction_context context, tree outer_targs, int flags) { - tree targs; - if (init == error_mark_node) return error_mark_node; @@ -29503,14 +29501,19 @@ do_auto_deduction (tree type, tree init, tree auto_node, else init = resolve_nondeduced_context (init, complain); + tree targs; if (context == adc_decomp_type && auto_node == type && init != error_mark_node && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) -/* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers - and initializer has array type, deduce cv-qualified array type. */ -return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), -complain); +{ + /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers +and initializer has array type, deduce cv-qualified array type. */ + targs = make_tree_vec (1); + TREE_VEC_ELT (targs, 0) + = cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), + complain); On second thought, I think we can get away with using just TREE_TYPE (init) here and leaving the propagation of type qualifiers to tsubst. This has the effect of making us reject the testcase placeholder8.C below, which is consistent with the non-array case. IIUC, the type qualifiers on a constrained 'auto' shouldn't be relevant during constraint checking. I'm testing the following: -- >8 -- gcc/cp/ChangeLog: PR c++/99899 * pt.c (do_auto_deduction): Don't exit early when deducing the array type of a structured binding. Also handle adc_decomp_type during constraint checking. gcc/testsuite/ChangeLog: PR c++/99899 * g++.dg/cpp2a/concepts-placeholder7.C: New test. * g++.dg/cpp2a/concepts-placeholder8.C: New test. --- gcc/cp/pt.c | 20 +++- .../g++.dg/cpp2a/concepts-placeholder7.C | 32 +++ .../g++.dg/cpp2a/concepts-placeholder8.C | 10 ++ 3 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder8.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1d19a59dd62..fd1e4db42cf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29438,8 +29438,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, tsubst_flags_t complain, auto_deduction_context context, tree outer_targs, int flags) { - tree targs; - if (init == error_mark_node) return error_mark_node; @@ -29503,14 +29501,17 @@ do_auto_deduction (tree type, tree init, tree auto_node, else init = resolve_nondeduced_context (init, complain); + tree targs; if (context == adc_decomp_type && auto_node == type && init != error_mark_node && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) -/* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers - and initializer has array type, deduce cv-qualified array type. */ -return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type), -complain); +{ + /* [dcl.struct.bind]/1 - if decomposition declaration has no ref-qualifiers +and initializer has
[pushed] c++: lambda in DMI in class template [PR95870]
Here enclosing_instantiation_of was failing to find a match because otctx is struct S and current_function_decl is S::S(), so the latter has more function contexts, and we end up trying to compare S() to NULL_TREE. After spending a bit of time working on establishing the correspondence in this case (class <=> constructor), it occurred to me that we could just use DECL_SOURCE_LOCATION, which is unique for lambdas, since they cannot be redeclared. Since we're so close to release, for now I'm only doing this for the case that was failing before. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/95870 * pt.c (enclosing_instantiation_of): Compare DECL_SOURCE_LOCATION if there is no enclosing non-lambda function. gcc/testsuite/ChangeLog: PR c++/95870 * g++.dg/cpp0x/lambda/lambda-nsdmi10.C: New test. --- gcc/cp/pt.c| 13 + gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C | 12 2 files changed, 25 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 396e622c4db..d6a8ede386d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -14371,6 +14371,19 @@ enclosing_instantiation_of (tree otctx) || instantiated_lambda_fn_p (tctx)); tctx = decl_function_context (tctx)) ++lambda_count; + + if (!tctx) +{ + /* Match using DECL_SOURCE_LOCATION, which is unique for all lambdas. + +For GCC 11 the above condition limits this to the previously failing +case where all enclosing functions are lambdas (95870). FIXME. */ + for (tree ofn = fn; ofn; ofn = decl_function_context (ofn)) + if (DECL_SOURCE_LOCATION (ofn) == DECL_SOURCE_LOCATION (otctx)) + return ofn; + gcc_unreachable (); +} + for (; fn; fn = decl_function_context (fn)) { tree ofn = fn; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C new file mode 100644 index 000..810ed538719 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C @@ -0,0 +1,12 @@ +// PR c++/95870 +// { dg-do compile { target c++11 } } + +template struct S { + S(); + int b = []() -> int { enum E {}; return 1; }(); +}; +struct C : S { + C(); +}; +template S::S() = default; +C::C() {} base-commit: 7ebdef2076fda56cb4cffb941f6c2576f980f3b3 -- 2.27.0
[pushed] c++: enum in generic lambda in template [PR95317]
Here we weren't instantiating the enumerators because the arglist still had the template parameter for the generic lambda, so looking one up failed. We need to instantiate if the non-lambda enclosing scope is non-dependent. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/95317 * pt.c (lookup_template_class_1): Do tsubst_enum when tsubsting a generic lambda. gcc/testsuite/ChangeLog: PR c++/95317 * g++.dg/cpp1y/lambda-generic-enum1.C: New test. --- gcc/cp/pt.c | 3 ++- gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum1.C | 10 ++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum1.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d6a8ede386d..41bc633cfce 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10173,7 +10173,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, = tree_cons (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (found)); - if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type + if (TREE_CODE (template_type) == ENUMERAL_TYPE + && !uses_template_parms (current_nonlambda_scope ()) && !DECL_ALIAS_TEMPLATE_P (gen_tmpl)) /* Now that the type has been registered on the instantiations list, we set up the enumerators. Because the enumeration diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum1.C new file mode 100644 index 000..de15443bfcf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-enum1.C @@ -0,0 +1,10 @@ +// PR c++/95317 +// { dg-do compile { target c++14 } } + +template void fn1() { + [](auto) { +enum { VALUE }; +VALUE; + }; +} +int main() { fn1; } base-commit: 7ebdef2076fda56cb4cffb941f6c2576f980f3b3 prerequisite-patch-id: 22fd889eedb29aa662bdfc0fcc38e7a1072b47b4 -- 2.27.0
[PATCH 1/3] d: Add TARGET_D_HAS_STDCALL_CONVENTION
Hi, This patch adds TARGET_D_HAS_STDCALL_CONVENTION as a new D front-end target hook. It replaces the use of the D front-end `is64bit' parameter in determining whether to insert the "stdcall" function attribute. It is also used to determine whether `extern(System)' should be the same as `extern(Windows)' in the implementation of Target::systemLinkage. Both are prerequesites for being able to compile libphobos on MinGW. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and tested on x86_64-w64-mingw64 for getting the libphobos port set-up. Any issues with the implementation, or OK to commit? Regards, Iain. --- gcc/ChangeLog: * config/i386/i386-d.c (ix86_d_has_stdcall_convention): New function. * config/i386/i386-protos.h (ix86_d_has_stdcall_convention): Declare. * config/i386/i386.h (TARGET_D_HAS_STDCALL_CONVENTION): Define. * doc/tm.texi: Regenerate. * doc/tm.texi.in (D language and ABI): Add @hook for TARGET_D_HAS_STDCALL_CONVENTION. gcc/d/ChangeLog: * d-target.cc (Target::systemLinkage): Return LINKwindows if d_has_stdcall_convention applies to LINKsystem. * d-target.def (d_has_stdcall_convention): New hook. * types.cc (TypeVisitor::visit (TypeFunction *)): Insert "stdcall" function attribute if d_has_stdcall_convention applies to LINKwindows. --- gcc/config/i386/i386-d.c | 20 gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.h| 3 ++- gcc/d/d-target.cc | 12 +++- gcc/d/d-target.def| 13 + gcc/d/types.cc| 19 +-- gcc/doc/tm.texi | 8 gcc/doc/tm.texi.in| 2 ++ 8 files changed, 70 insertions(+), 8 deletions(-) diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c index b79be85e661..58b4790fdad 100644 --- a/gcc/config/i386/i386-d.c +++ b/gcc/config/i386/i386-d.c @@ -44,3 +44,23 @@ ix86_d_target_versions (void) else d_add_builtin_version ("D_SoftFloat"); } + +/* Implement TARGET_D_HAS_STDCALL_CONVENTION for x86 targets. */ + +bool +ix86_d_has_stdcall_convention (unsigned int *link_system, + unsigned int *link_windows) +{ + if (ix86_abi == MS_ABI) +{ + *link_system = 1; + *link_windows = (!TARGET_64BIT) ? 1 : 0; +} + else +{ + *link_system = 0; + *link_windows = 0; +} + + return true; +} diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 9f8a69ea7dc..acfb9f5fe87 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void); /* In i386-d.c */ extern void ix86_d_target_versions (void); +extern bool ix86_d_has_stdcall_convention (unsigned int *, unsigned int *); /* In winnt.c */ extern void i386_pe_unique_section (tree, int); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index b4001d21b70..17e233a4e74 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -801,8 +801,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /* Target Pragmas. */ #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas () -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS ix86_d_target_versions +#define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention #ifndef CC1_SPEC #define CC1_SPEC "%(cc1_cpu) " diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index a1dc2ee286f..f1814df110d 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -435,11 +435,21 @@ TargetCPP::derivedClassOffset(ClassDeclaration *base_class) return base_class->structsize; } -/* Return the default system linkage for the target. */ +/* Return the default `extern (System)' linkage for the target. */ LINK Target::systemLinkage (void) { + unsigned link_system, link_windows; + + if (targetdm.d_has_stdcall_convention (&link_system, &link_windows)) +{ + /* In [attribute/linkage], `System' is the same as `Windows' on Windows +platforms, and `C' on other platforms. */ + if (link_system) + return LINKwindows; +} + return LINKc; } diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def index d1426a17e99..f79ffb9cd7d 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -71,5 +71,18 @@ as the name of the symbol indicating the end address of the module info\n\ section", const char *, NULL) +/* The "stdcall" convention is really supported on 32-bit x86/Windows only. + The following hook is a helper to determine whether to apply the attribute + on declarations with `extern(System)' and `extern(Windows)' linkage. */ +DEFHOOK +(d_has_stdcall_convention, + "Returns @code{true} if the target supports the stdcall calling convention.\n\ +The hook should also set @var{link_system} to @code{1} if the @code{stdcall}\n\ +at
[PATCH 2/3] d: Add TARGET_D_REGISTER_CPU_TARGET_INFO
Hi, This patch adds TARGET_D_REGISTER_CPU_TARGET_INFO as a new D front-end target hook, implementing `__traits(getTargetInfo, "floatAbi")' for all targets that have D support files. This trait was added earlier in the front-end as a stub, however the target-specific implementation was left out until now. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and tested on x86_64-darwin for getting the libphobos port set-up. Any issues with this, or OK to commit? Regards Iain. --- gcc/ChangeLog: * config/aarch64/aarch64-d.c (aarch64_d_handle_target_float_abi): New function. (aarch64_d_register_target_info): New function. * config/aarch64/aarch64-protos.h (aarch64_d_register_target_info): Declare. * config/aarch64/aarch64.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/arm/arm-d.c (arm_d_handle_target_float_abi): New function. (arm_d_register_target_info): New function. * config/arm/arm-protos.h (arm_d_register_target_info): Declare. * config/arm/arm.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/i386/i386-d.c (ix86_d_handle_target_float_abi): New function. (ix86_d_register_target_info): New function. * config/i386/i386-protos.h (ix86_d_register_target_info): Declare. * config/i386/i386.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/mips/mips-d.c (mips_d_handle_target_float_abi): New function. (mips_d_register_target_info): New function. * config/mips/mips-protos.h (mips_d_register_target_info): Declare. * config/mips/mips.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/pa/pa-d.c (pa_d_handle_target_float_abi): New function. (pa_d_register_target_info): New function. * config/pa/pa-protos.h (pa_d_register_target_info): Declare. * config/pa/pa.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/riscv/riscv-d.c (riscv_d_handle_target_float_abi): New function. (riscv_d_register_target_info): New function. * config/riscv/riscv-protos.h (riscv_d_register_target_info): Declare. * config/riscv/riscv.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/rs6000/rs6000-d.c (rs6000_d_handle_target_float_abi): New function. (rs6000_d_register_target_info): New function. * config/rs6000/rs6000-protos.h (rs6000_d_register_target_info): Declare. * config/rs6000/rs6000.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/s390/s390-d.c (s390_d_handle_target_float_abi): New function. (s390_d_register_target_info): New function. * config/s390/s390-protos.h (s390_d_register_target_info): Declare. * config/s390/s390.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/sparc/sparc-d.c (sparc_d_handle_target_float_abi): New function. (sparc_d_register_target_info): New function. * config/sparc/sparc-protos.h (sparc_d_register_target_info): Declare. * config/sparc/sparc.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * doc/tm.texi: Regenerate. * doc/tm.texi.in (D language and ABI): Add @hook for TARGET_D_REGISTER_CPU_TARGET_INFO. gcc/d/ChangeLog: * d-target.cc (Target::_init): Call new targetdm hook to register CPU specific target info keys. * d-target.def (d_register_cpu_target_info): New hook. --- gcc/config/aarch64/aarch64-d.c | 23 ++ gcc/config/aarch64/aarch64-protos.h | 1 + gcc/config/aarch64/aarch64.h| 3 +- gcc/config/arm/arm-d.c | 42 ++ gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.h| 3 +- gcc/config/i386/i386-d.c| 28 + gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.h | 1 + gcc/config/mips/mips-d.c| 30 ++ gcc/config/mips/mips-protos.h | 1 + gcc/config/mips/mips.h | 3 +- gcc/config/pa/pa-d.c| 28 + gcc/config/pa/pa-protos.h | 1 + gcc/config/pa/pa.h | 3 +- gcc/config/riscv/riscv-d.c | 47 + gcc/config/riscv/riscv-protos.h | 1 + gcc/config/riscv/riscv.h| 3 +- gcc/config/rs6000/rs6000-d.c| 30 ++ gcc/config/rs6000/rs6000-protos.h | 1 + gcc/config/rs6000/rs6000.h | 3 +- gcc/config/s390/s390-d.c| 30 ++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.h | 3 +- gcc/config/sparc/sparc-d.c | 28 + gcc/config/sparc/sparc-protos.h | 1 + gcc/config/sparc/sparc.h| 3 +- gcc/d/d-target.cc | 1 + gcc/d/d-target.def | 12 gcc/doc/tm.texi | 9 ++ gcc/do
[PATCH 3/3] d: Add TARGET_D_REGISTER_OS_TARGET_INFO
Hi, This patch adds TARGET_D_REGISTER_OS_TARGET_INFO as a new D front-end target hook, implementing `__traits(getTargetInfo, "objectFormat")' for all targets that have D support files. This trait was added earlier in the front-end as a stub, however the target-specific implementation was left out until now. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and tested on x86_64-darwin for getting the libphobos port set-up. Any issues with this, or OK to commit? Regards Iain. --- gcc/ChangeLog: * config/darwin-d.c (darwin_d_handle_target_object_format): New function. (darwin_d_register_target_info): New function. (TARGET_D_REGISTER_OS_TARGET_INFO): Define. * config/dragonfly-d.c (dragonfly_d_handle_target_object_format): New function. (dragonfly_d_register_target_info): New function. (TARGET_D_REGISTER_OS_TARGET_INFO): Define. * config/freebsd-d.c (freebsd_d_handle_target_object_format): New function. (freebsd_d_register_target_info): New function. (TARGET_D_REGISTER_OS_TARGET_INFO): Define. * config/glibc-d.c (glibc_d_handle_target_object_format): New function. (glibc_d_register_target_info): New function. (TARGET_D_REGISTER_OS_TARGET_INFO): Define. * config/netbsd-d.c (netbsd_d_handle_target_object_format): New function. (netbsd_d_register_target_info): New function. (TARGET_D_REGISTER_OS_TARGET_INFO): Define. * config/sol2-d.c (solaris_d_handle_target_object_format): New function. (solaris_d_register_target_info): New function. (TARGET_D_REGISTER_OS_TARGET_INFO): Define. * doc/tm.texi: Regenerate. * doc/tm.texi.in (D language and ABI): Add @hook for TARGET_D_REGISTER_OS_TARGET_INFO. gcc/d/ChangeLog: * d-target.cc (Target::_init): Call new targetdm hook to register OS specific target info keys. * d-target.def (d_register_os_target_info): New hook. --- gcc/config/darwin-d.c| 26 ++ gcc/config/dragonfly-d.c | 26 ++ gcc/config/freebsd-d.c | 26 ++ gcc/config/glibc-d.c | 26 ++ gcc/config/netbsd-d.c| 26 ++ gcc/config/sol2-d.c | 26 ++ gcc/d/d-target.cc| 1 + gcc/d/d-target.def | 8 gcc/doc/tm.texi | 5 + gcc/doc/tm.texi.in | 2 ++ 10 files changed, 172 insertions(+) diff --git a/gcc/config/darwin-d.c b/gcc/config/darwin-d.c index afc32da4ad8..67d69b721b5 100644 --- a/gcc/config/darwin-d.c +++ b/gcc/config/darwin-d.c @@ -32,9 +32,35 @@ darwin_d_os_builtins (void) d_add_builtin_version ("darwin"); } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +darwin_d_handle_target_object_format (void) +{ + const char *objfmt = "macho"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for Darwin targets. */ + +static void +darwin_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { +{ "objectFormat", darwin_d_handle_target_object_format }, +{ NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS darwin_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO darwin_d_register_target_info + /* Define TARGET_D_MINFO_SECTION for Darwin targets. */ #undef TARGET_D_MINFO_SECTION diff --git a/gcc/config/dragonfly-d.c b/gcc/config/dragonfly-d.c index 76f4cc02ff7..dc301b54e8f 100644 --- a/gcc/config/dragonfly-d.c +++ b/gcc/config/dragonfly-d.c @@ -31,7 +31,33 @@ dragonfly_d_os_builtins (void) d_add_builtin_version ("Posix"); } +/* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ + +static tree +dragonfly_d_handle_target_object_format (void) +{ + const char *objfmt = "elf"; + + return build_string_literal (strlen (objfmt) + 1, objfmt); +} + +/* Implement TARGET_D_REGISTER_OS_TARGET_INFO for DragonFly targets. */ + +static void +dragonfly_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { +{ "objectFormat", dragonfly_d_handle_target_object_format }, +{ NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + #undef TARGET_D_OS_VERSIONS #define TARGET_D_OS_VERSIONS dragonfly_d_os_builtins +#undef TARGET_D_REGISTER_OS_TARGET_INFO +#define TARGET_D_REGISTER_OS_TARGET_INFO dragonfly_d_register_target_info + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/freebsd-d.c b/gcc/config/freebsd-d.c index 8a8ddd92884..8bebe79c895 100644 --- a/gcc/config/freebsd-d.c +++ b/gcc/config/freebsd-d.c @@ -37,7 +37,33 @@ freebsd_d_os_builtins (void) d_add_builtin_version ("Posix"); } +/* Handle a call to `__
Re: [PATCH 2/3] x86: Update memcpy/memset inline strategies for Skylake family CPUs
> > /* skylake_cost should produce code tuned for Skylake familly of CPUs. */ > > static stringop_algs skylake_memcpy[2] = { > > - {libcall, {{1024, rep_prefix_4_byte, true}, {-1, libcall, false}}}, > > - {libcall, {{16, loop, false}, {512, unrolled_loop, false}, > > - {-1, libcall, false; > > + {libcall, > > + {{256, rep_prefix_1_byte, true}, > > +{256, loop, false}, > > +{-1, libcall, false}}}, > > + {libcall, > > + {{256, rep_prefix_1_byte, true}, > > +{256, loop, false}, > > +{-1, libcall, false; > > > > static stringop_algs skylake_memset[2] = { > > - {libcall, {{6, loop_1_byte, true}, > > - {24, loop, true}, > > - {8192, rep_prefix_4_byte, true}, > > - {-1, libcall, false}}}, > > - {libcall, {{24, loop, true}, {512, unrolled_loop, false}, > > - {-1, libcall, false; > > + {libcall, > > + {{256, rep_prefix_1_byte, true}, > > +{256, loop, false}, > > +{-1, libcall, false}}}, > > + {libcall, > > + {{256, rep_prefix_1_byte, true}, > > +{256, loop, false}, > > +{-1, libcall, false; > > > > If there are no objections, I will check it in on Wednesday. On my skylake notebook if I run the benchmarking script I get: jan@skylake:~/trunk/contrib> ./bench-stringop 64 64000 gcc -march=native memcpy block size libcall rep1noalg rep4noalg rep8noalg loop noalg unrlnoalg sse noalg bytePGO dynamicBEST 8192000 0:00.23 0:00.21 0:00.21 0:00.21 0:00.21 0:00.22 0:00.24 0:00.28 0:00.22 0:00.20 0:00.21 0:00.19 0:00.19 0:00.77 0:00.18 0:00.180:00.19 sse 819200 0:00.09 0:00.18 0:00.18 0:00.18 0:00.18 0:00.18 0:00.20 0:00.19 0:00.16 0:00.15 0:00.16 0:00.13 0:00.14 0:00.63 0:00.09 0:00.090:00.09 libcall 81920 0:00.06 0:00.07 0:00.07 0:00.06 0:00.06 0:00.06 0:00.06 0:00.12 0:00.11 0:00.11 0:00.10 0:00.07 0:00.08 0:00.66 0:00.11 0:00.060:00.06 libcall 20480 0:00.06 0:00.07 0:00.05 0:00.06 0:00.07 0:00.07 0:00.08 0:00.14 0:00.14 0:00.10 0:00.11 0:00.06 0:00.07 0:01.11 0:00.07 0:00.090:00.05 rep1noalign 8192 0:00.06 0:00.05 0:00.04 0:00.05 0:00.06 0:00.07 0:00.07 0:00.12 0:00.15 0:00.11 0:00.10 0:00.06 0:00.06 0:00.64 0:00.06 0:00.050:00.04 rep1noalign 4096 0:00.05 0:00.05 0:00.05 0:00.06 0:00.07 0:00.05 0:00.05 0:00.09 0:00.14 0:00.11 0:00.10 0:00.07 0:00.06 0:00.61 0:00.05 0:00.070:00.05 libcall 2048 0:00.04 0:00.05 0:00.05 0:00.05 0:00.05 0:00.05 0:00.05 0:00.10 0:00.14 0:00.09 0:00.09 0:00.09 0:00.07 0:00.64 0:00.06 0:00.070:00.04 libcall 1024 0:00.06 0:00.08 0:00.08 0:00.10 0:00.11 0:00.06 0:00.06 0:00.12 0:00.15 0:00.09 0:00.09 0:00.16 0:00.09 0:00.63 0:00.05 0:00.060:00.06 libcall 512 0:00.06 0:00.07 0:00.08 0:00.12 0:00.08 0:00.10 0:00.09 0:00.13 0:00.16 0:00.10 0:00.10 0:00.28 0:00.18 0:00.66 0:00.13 0:00.080:00.06 libcall 256 0:00.10 0:00.12 0:00.11 0:00.14 0:00.11 0:00.12 0:00.13 0:00.14 0:00.16 0:00.13 0:00.12 0:00.49 0:00.30 0:00.68 0:00.14 0:00.120:00.10 libcall 128 0:00.15 0:00.19 0:00.18 0:00.20 0:00.19 0:00.20 0:00.18 0:00.19 0:00.21 0:00.17 0:00.15 0:00.49 0:00.43 0:00.72 0:00.17 0:00.170:00.15 libcall 64 0:00.29 0:00.28 0:00.29 0:00.33 0:00.33 0:00.34 0:00.29 0:00.25 0:00.29 0:00.26 0:00.26 0:01.01 0:00.97 0:01.13 0:00.32 0:00.280:00.25 loop 48 0:00.37 0:00.39 0:00.38 0:00.45 0:00.41 0:00.45 0:00.44 0:00.45 0:00.33 0:00.32 0:00.33 0:02.21 0:02.22 0:00.87 0:00.32 0:00.310:00.32 unrl 32 0:00.54 0:00.52 0:00.50 0:00.60 0:00.62 0:00.61 0:00.52 0:00.42 0:00.43 0:00.40 0:00.42 0:01.18 0:01.16 0:01.14 0:00.39 0:00.400:00.40 unrl 24 0:00.71 0:00.74 0:00.77 0:00.83 0:00.78 0:00.81 0:00.75 0:00.52 0:00.52 0:00.52 0:00.50 0:02.28 0:02.27 0:00.94 0:00.49 0:00.500:00.50 unrlnoalign 16 0:00.97 0:01.03 0:01.20 0:01.52 0:01.37 0:01.84 0:01.10 0:00.90 0:00.86 0:00.79 0:00.77 0:01.27 0:01.32 0:01.25 0:00.91 0:00.910:00.77 unrlnoalign 14 0:01.35 0:01.37 0:01.39 0:01.76 0:01.44 0:01.53 0:01.58 0:01.01 0:00.99 0:00.94 0:00.94 0:01.34 0:01.29 0:01.28 0:01.01 0:00.990:00.94 unrl 12 0:01.48 0:01.55 0:01.55 0:01.70 0:01.55 0:02.01 0:01.52 0:01.11 0:01.07 0:01.02 0:01.04 0:02.21 0:02.25 0:01.19 0:01.11 0:01.100:01.02 unrl 10 0:01.73 0:01.90 0:01.88 0:02.05 0:01.86 0:02.09 0:01.78 0:01.32 0:01.41 0:01.25 0:01.23 0:02.46 0:02.25 0:01.36 0:01.50 0:01.380:01.23 unrlnoalign 8 0:02.22 0:02.17 0:02.18 0:02.43 0:02.09 0:02.55 0:01.92 0:01.54 0:01.46 0:01.38 0:01.38 0:01.51 0:01.62 0:01.54 0:01.55 0:01.550:01.38 unrl So indeed rep byte seems consistently outperforming rep4/rep8 however urolled variant seems to be better than rep byte for small block sizes. Do you have some data for blocks in size 8...256 to be faster with rep1 compared to unrolled loop for perhaps
[pushed] c++: reinterpret_cast from prvalue to rvalue ref [PR98440]
In r260622 I allowed this under the general principle that [basic.lval] "Whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, the temporary materialization conversion (7.3.4) is applied to convert the expression to an xvalue." But [expr.reinterpret.cast] specifically excludes creating a temporary in this case. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/98440 * typeck.c (build_reinterpret_cast_1): Don't perform temporary materialization. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/rv-cast6.C: Expect reinterpret_cast error. --- gcc/cp/typeck.c| 18 +++--- gcc/testsuite/g++.dg/cpp0x/reinterpret_cast2.C | 2 +- gcc/testsuite/g++.dg/cpp0x/rv-cast6.C | 2 +- gcc/testsuite/g++.old-deja/g++.jason/rvalue3.C | 2 +- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index dff4e9b63ca..8535ecc2d93 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -7938,22 +7938,18 @@ build_reinterpret_cast_1 (location_t loc, tree type, tree expr, type = cv_unqualified (type); /* [expr.reinterpret.cast] - A glvalue expression of type T1 can be cast to the type + A glvalue of type T1, designating an object x, can be cast to the type "reference to T2" if an expression of type "pointer to T1" can be - explicitly converted to the type "pointer to T2" using a - reinterpret_cast. */ + explicitly converted to the type "pointer to T2" using a reinterpret_cast. + The result is that of *reinterpret_cast(p) where p is a pointer to x + of type "pointer to T1". No temporary is created, no copy is made, and no + constructors (11.4.4) or conversion functions (11.4.7) are called. */ if (TYPE_REF_P (type)) { - if (TYPE_REF_IS_RVALUE (type) && !VOID_TYPE_P (intype)) - { - if (!obvalue_p (expr)) - /* Perform the temporary materialization conversion. */ - expr = get_target_expr_sfinae (expr, complain); - } - else if (!lvalue_p (expr)) + if (!glvalue_p (expr)) { if (complain & tf_error) -error_at (loc, "invalid cast of an rvalue expression of type " + error_at (loc, "invalid cast of a prvalue expression of type " "%qT to type %qT", intype, type); return error_mark_node; diff --git a/gcc/testsuite/g++.dg/cpp0x/reinterpret_cast2.C b/gcc/testsuite/g++.dg/cpp0x/reinterpret_cast2.C index c173576e287..5402e825aa5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/reinterpret_cast2.C +++ b/gcc/testsuite/g++.dg/cpp0x/reinterpret_cast2.C @@ -6,5 +6,5 @@ struct S { }; void foo () { - auto a = reinterpret_cast(foo ()); // { dg-error "12:invalid cast of an rvalue expression of type 'void' to type" } + auto a = reinterpret_cast(foo ()); // { dg-error "12:invalid cast of a prvalue expression of type 'void' to type" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast6.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast6.C index 3ae5691c5fd..3adf683f881 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-cast6.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast6.C @@ -5,7 +5,7 @@ struct A { virtual void f(); }; struct B : A {}; auto && a = static_cast(B()); -auto && b = reinterpret_cast(B()); +auto && b = reinterpret_cast(B()); // { dg-error "prvalue" } auto && c = dynamic_cast(B()); auto && d = dynamic_cast(static_cast(B())); auto && e = const_cast(B()); diff --git a/gcc/testsuite/g++.old-deja/g++.jason/rvalue3.C b/gcc/testsuite/g++.old-deja/g++.jason/rvalue3.C index 49191c9e408..77969bc60ee 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/rvalue3.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/rvalue3.C @@ -2,5 +2,5 @@ int main () { int i; - int &ir = (int&)(int)i; // { dg-error "14:invalid cast of an rvalue expression" } casting rvalue to reference type + int &ir = (int&)(int)i; // { dg-error "14:invalid cast of a prvalue expression" } casting rvalue to reference type } base-commit: 9f4c41147a41d08a74990eafe69a1064a3c13435 -- 2.27.0
[pushed] c++: -Wunused, constant, and generic lambda [PR96311]
We never called mark_use for a return value in a function with dependent return type. In that situation we don't know if the use is as an rvalue or lvalue, but we can use mark_exp_read instead. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/96311 * typeck.c (check_return_expr): Call mark_exp_read in dependent case. gcc/testsuite/ChangeLog: PR c++/96311 * g++.dg/cpp1y/lambda-generic-Wunused.C: New test. --- gcc/cp/typeck.c| 3 +++ .../g++.dg/cpp1y/lambda-generic-Wunused.C | 18 ++ 2 files changed, 21 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-Wunused.C diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 8535ecc2d93..11dee7d8753 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -10215,6 +10215,9 @@ check_return_expr (tree retval, bool *no_warning) dependent: /* We should not have changed the return value. */ gcc_assert (retval == saved_retval); + /* We don't know if this is an lvalue or rvalue use, but +either way we can mark it as read. */ + mark_exp_read (retval); return retval; } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-Wunused.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-Wunused.C new file mode 100644 index 000..b43cbe6b675 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-Wunused.C @@ -0,0 +1,18 @@ +// PR c++/96311 +// { dg-do compile { target c++14 } } +// { dg-additional-options -Wunused } + +auto foo() +{ + constexpr int used = 0; + return +[](auto unused) +{ + return used; +}; +} + +int main() +{ + foo()(42); +} base-commit: 9f4c41147a41d08a74990eafe69a1064a3c13435 prerequisite-patch-id: 3be338a0d789cd159b27785251afb4e692b30d15 -- 2.27.0
Re: [PATCH 2/3] x86: Update memcpy/memset inline strategies for Skylake family CPUs
On Mon, Apr 5, 2021 at 2:14 PM Jan Hubicka wrote: > > > > /* skylake_cost should produce code tuned for Skylake familly of CPUs. > > > */ > > > static stringop_algs skylake_memcpy[2] = { > > > - {libcall, {{1024, rep_prefix_4_byte, true}, {-1, libcall, false}}}, > > > - {libcall, {{16, loop, false}, {512, unrolled_loop, false}, > > > - {-1, libcall, false; > > > + {libcall, > > > + {{256, rep_prefix_1_byte, true}, > > > +{256, loop, false}, > > > +{-1, libcall, false}}}, > > > + {libcall, > > > + {{256, rep_prefix_1_byte, true}, > > > +{256, loop, false}, > > > +{-1, libcall, false; > > > > > > static stringop_algs skylake_memset[2] = { > > > - {libcall, {{6, loop_1_byte, true}, > > > - {24, loop, true}, > > > - {8192, rep_prefix_4_byte, true}, > > > - {-1, libcall, false}}}, > > > - {libcall, {{24, loop, true}, {512, unrolled_loop, false}, > > > - {-1, libcall, false; > > > + {libcall, > > > + {{256, rep_prefix_1_byte, true}, > > > +{256, loop, false}, > > > +{-1, libcall, false}}}, > > > + {libcall, > > > + {{256, rep_prefix_1_byte, true}, > > > +{256, loop, false}, > > > +{-1, libcall, false; > > > > > > > If there are no objections, I will check it in on Wednesday. > > On my skylake notebook if I run the benchmarking script I get: > > jan@skylake:~/trunk/contrib> ./bench-stringop 64 64000 gcc -march=native > memcpy > block size libcall rep1noalg rep4noalg rep8noalg loop > noalg unrlnoalg sse noalg bytePGO dynamicBEST > 8192000 0:00.23 0:00.21 0:00.21 0:00.21 0:00.21 0:00.22 0:00.24 0:00.28 > 0:00.22 0:00.20 0:00.21 0:00.19 0:00.19 0:00.77 0:00.18 0:00.180:00.19 sse > 819200 0:00.09 0:00.18 0:00.18 0:00.18 0:00.18 0:00.18 0:00.20 0:00.19 > 0:00.16 0:00.15 0:00.16 0:00.13 0:00.14 0:00.63 0:00.09 0:00.090:00.09 > libcall >81920 0:00.06 0:00.07 0:00.07 0:00.06 0:00.06 0:00.06 0:00.06 0:00.12 > 0:00.11 0:00.11 0:00.10 0:00.07 0:00.08 0:00.66 0:00.11 0:00.060:00.06 > libcall >20480 0:00.06 0:00.07 0:00.05 0:00.06 0:00.07 0:00.07 0:00.08 0:00.14 > 0:00.14 0:00.10 0:00.11 0:00.06 0:00.07 0:01.11 0:00.07 0:00.090:00.05 > rep1noalign > 8192 0:00.06 0:00.05 0:00.04 0:00.05 0:00.06 0:00.07 0:00.07 0:00.12 > 0:00.15 0:00.11 0:00.10 0:00.06 0:00.06 0:00.64 0:00.06 0:00.050:00.04 > rep1noalign > 4096 0:00.05 0:00.05 0:00.05 0:00.06 0:00.07 0:00.05 0:00.05 0:00.09 > 0:00.14 0:00.11 0:00.10 0:00.07 0:00.06 0:00.61 0:00.05 0:00.070:00.05 > libcall > 2048 0:00.04 0:00.05 0:00.05 0:00.05 0:00.05 0:00.05 0:00.05 0:00.10 > 0:00.14 0:00.09 0:00.09 0:00.09 0:00.07 0:00.64 0:00.06 0:00.070:00.04 > libcall > 1024 0:00.06 0:00.08 0:00.08 0:00.10 0:00.11 0:00.06 0:00.06 0:00.12 > 0:00.15 0:00.09 0:00.09 0:00.16 0:00.09 0:00.63 0:00.05 0:00.060:00.06 > libcall > 512 0:00.06 0:00.07 0:00.08 0:00.12 0:00.08 0:00.10 0:00.09 0:00.13 > 0:00.16 0:00.10 0:00.10 0:00.28 0:00.18 0:00.66 0:00.13 0:00.080:00.06 > libcall > 256 0:00.10 0:00.12 0:00.11 0:00.14 0:00.11 0:00.12 0:00.13 0:00.14 > 0:00.16 0:00.13 0:00.12 0:00.49 0:00.30 0:00.68 0:00.14 0:00.120:00.10 > libcall > 128 0:00.15 0:00.19 0:00.18 0:00.20 0:00.19 0:00.20 0:00.18 0:00.19 > 0:00.21 0:00.17 0:00.15 0:00.49 0:00.43 0:00.72 0:00.17 0:00.170:00.15 > libcall > 64 0:00.29 0:00.28 0:00.29 0:00.33 0:00.33 0:00.34 0:00.29 0:00.25 > 0:00.29 0:00.26 0:00.26 0:01.01 0:00.97 0:01.13 0:00.32 0:00.280:00.25 > loop > 48 0:00.37 0:00.39 0:00.38 0:00.45 0:00.41 0:00.45 0:00.44 0:00.45 > 0:00.33 0:00.32 0:00.33 0:02.21 0:02.22 0:00.87 0:00.32 0:00.310:00.32 > unrl > 32 0:00.54 0:00.52 0:00.50 0:00.60 0:00.62 0:00.61 0:00.52 0:00.42 > 0:00.43 0:00.40 0:00.42 0:01.18 0:01.16 0:01.14 0:00.39 0:00.400:00.40 > unrl > 24 0:00.71 0:00.74 0:00.77 0:00.83 0:00.78 0:00.81 0:00.75 0:00.52 > 0:00.52 0:00.52 0:00.50 0:02.28 0:02.27 0:00.94 0:00.49 0:00.500:00.50 > unrlnoalign > 16 0:00.97 0:01.03 0:01.20 0:01.52 0:01.37 0:01.84 0:01.10 0:00.90 > 0:00.86 0:00.79 0:00.77 0:01.27 0:01.32 0:01.25 0:00.91 0:00.910:00.77 > unrlnoalign > 14 0:01.35 0:01.37 0:01.39 0:01.76 0:01.44 0:01.53 0:01.58 0:01.01 > 0:00.99 0:00.94 0:00.94 0:01.34 0:01.29 0:01.28 0:01.01 0:00.990:00.94 > unrl > 12 0:01.48 0:01.55 0:01.55 0:01.70 0:01.55 0:02.01 0:01.52 0:01.11 > 0:01.07 0:01.02 0:01.04 0:02.21 0:02.25 0:01.19 0:01.11 0:01.100:01.02 > unrl > 10 0:01.73 0:01.90 0:01.88 0:02.05 0:01.86 0:02.09 0:01.78 0:01.32 > 0:01.41 0:01.25 0:01.23 0:02.46 0:02.25 0:01.36 0:01.50 0:01.380:01.23 > unrlnoalign >8 0:02.22 0:02.17 0:02.18 0:02.43 0:02.09 0:02.55 0:01.92 0:01.54 > 0:01.46 0:01.38 0:01.38 0:01.51 0:01.62 0:01.54 0:01.55 0:01.550:01.38
[pushed] c++: mangling of lambdas in default args [PR91241]
In this testcase, the parms remembered in LAMBDA_EXPR_EXTRA_SCOPE are no longer the parms of the FUNCTION_DECL they have as their DECL_CONTEXT, so we were mangling both lambdas as parm #0. But since the parms are numbered from right to left we don't need to need to find them in the FUNCTION_DECL, we can measure their own DECL_CHAIN. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/91241 * mangle.c (write_compact_number): Add sanity check. (write_local_name): Use list_length for parm number. gcc/testsuite/ChangeLog: PR c++/91241 * g++.dg/abi/lambda-defarg1.C: New test. --- gcc/cp/mangle.c | 11 ++- gcc/testsuite/g++.dg/abi/lambda-defarg1.C | 11 +++ 2 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/lambda-defarg1.C diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 6c111342b97..4399165ee23 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1628,6 +1628,7 @@ write_literal_operator_name (tree identifier) static void write_compact_number (int num) { + gcc_checking_assert (num >= 0); if (num > 0) write_unsigned_number (num - 1); write_char ('_'); @@ -2027,15 +2028,7 @@ write_local_name (tree function, const tree local_entity, /* For this purpose, parameters are numbered from right-to-left. */ if (parm) { - tree t; - int i = 0; - for (t = DECL_ARGUMENTS (function); t; t = DECL_CHAIN (t)) - { - if (t == parm) - i = 1; - else if (i) - ++i; - } + int i = list_length (parm); write_char ('d'); write_compact_number (i - 1); } diff --git a/gcc/testsuite/g++.dg/abi/lambda-defarg1.C b/gcc/testsuite/g++.dg/abi/lambda-defarg1.C new file mode 100644 index 000..8c538581240 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-defarg1.C @@ -0,0 +1,11 @@ +// PR c++/91241 +// { dg-do compile { target c++11 } } + +struct A { + int *b(const int & = []() -> int { return 0; }(), +const int & = []() -> int { return 0; }()); +}; +int *A::b(const int &, const int &) { b(); return 0; } +// { dg-final { scan-assembler "_ZN1A1bERKiS1_" } } +// { dg-final { scan-assembler "_ZZN1A1bERKiS1_Ed_NKUlvE_clEv" } } +// { dg-final { scan-assembler "_ZZN1A1bERKiS1_Ed0_NKUlvE_clEv" } } base-commit: b07dd9b0d0e501a0083da79e2bca17041c007ec8 -- 2.27.0