[committed] d: Use weak linkage for template symbols instead of gnu.linkonce (PR99914)

2021-04-05 Thread Iain Buclaw via Gcc-patches
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

2021-04-05 Thread Nathan Sidwell

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]

2021-04-05 Thread Jason Merrill via Gcc-patches
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]

2021-04-05 Thread Jason Merrill via Gcc-patches
'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

2021-04-05 Thread H.J. Lu via Gcc-patches
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]

2021-04-05 Thread Nathan Sidwell


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]

2021-04-05 Thread David Malcolm via Gcc-patches
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]

2021-04-05 Thread David Malcolm via Gcc-patches
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]

2021-04-05 Thread Patrick Palka via Gcc-patches
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]

2021-04-05 Thread Patrick Palka via Gcc-patches
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

2021-04-05 Thread Eric Botcazou
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]

2021-04-05 Thread Jason Merrill via Gcc-patches

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]

2021-04-05 Thread Jason Merrill via Gcc-patches
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]

2021-04-05 Thread Jason Merrill via Gcc-patches
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

2021-04-05 Thread Iain Buclaw via Gcc-patches
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

2021-04-05 Thread Iain Buclaw via Gcc-patches
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

2021-04-05 Thread Iain Buclaw via Gcc-patches
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

2021-04-05 Thread Jan Hubicka
> >  /* 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]

2021-04-05 Thread Jason Merrill via Gcc-patches
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]

2021-04-05 Thread Jason Merrill via Gcc-patches
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

2021-04-05 Thread H.J. Lu via Gcc-patches
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]

2021-04-05 Thread Jason Merrill via Gcc-patches
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