{"id":810683,"url":"http://patchwork.ozlabs.org/api/patches/810683/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/34c52ab3-a673-b1d8-7860-f8273bad5670@acm.org/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<34c52ab3-a673-b1d8-7860-f8273bad5670@acm.org>","list_archive_url":null,"date":"2017-09-06T15:36:56","name":"[C++] Merge fn and non-fn lookup interface","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"d67d722b05a66b7f0dcb6aadd6a127f514fdfae3","submitter":{"id":9970,"url":"http://patchwork.ozlabs.org/api/people/9970/?format=json","name":"Nathan Sidwell","email":"nathan@acm.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/34c52ab3-a673-b1d8-7860-f8273bad5670@acm.org/mbox/","series":[{"id":1841,"url":"http://patchwork.ozlabs.org/api/series/1841/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=1841","date":"2017-09-06T15:36:56","name":"[C++] Merge fn and non-fn lookup interface","version":1,"mbox":"http://patchwork.ozlabs.org/series/1841/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/810683/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/810683/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-return-461625-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-461625-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"KtWNv7Hi\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xnSPg0GPdz9t43\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu,  7 Sep 2017 01:37:10 +1000 (AEST)","(qmail 127461 invoked by alias); 6 Sep 2017 15:37:03 -0000","(qmail 127446 invoked by uid 89); 6 Sep 2017 15:37:02 -0000","from mail-yw0-f169.google.com (HELO mail-yw0-f169.google.com)\n\t(209.85.161.169) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tWed, 06 Sep 2017 15:37:00 +0000","by mail-yw0-f169.google.com with SMTP id x144so22905864ywg.2 for\n\t<gcc-patches@gcc.gnu.org>; Wed, 06 Sep 2017 08:37:00 -0700 (PDT)","from ?IPv6:2620:10d:c0a3:20fb:7500:e7fb:4a6f:2254?\n\t([2620:10d:c091:200::16fd]) by smtp.googlemail.com with\n\tESMTPSA id y193sm46995ywy.5.2017.09.06.08.36.57\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256\n\tbits=128/128); Wed, 06 Sep 2017 08:36:58 -0700 (PDT)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:to\n\t:from:subject:message-id:date:mime-version:content-type; q=dns;\n\ts=default; b=b2zdOIfP++zgM/iNFeMvEWpIvzyS45ovacAQwZpjUgigWh8B1a\n\tieif7QBZdkV71c4V6osnmK9dcxS0gUvhHOqyqFLNW2XVQbk+p08NzT4+IibWhYsD\n\tW+0FnpHi53pADNjncbtMXmImwI7RFCfipzsHqvkG8nJCtlcGU9TigLLiA=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:to\n\t:from:subject:message-id:date:mime-version:content-type; s=\n\tdefault; bh=T0MxLr20s/ThODm0VJTaSPc5IS8=; b=KtWNv7Hi9p+buBs76m3b\n\tgtt4cI3xBI0rqRm1RmfFrrBUB0vbKh0TFBVc3wreSzrURnXZDPq6zQixIhohXGpt\n\tixCFJFiwqyD+Nu/fI6IGBEaHVKX30wUKvHsOxq6AJN4lGb2h03k0eAgpqtV+x4zp\n\tq4zMyTDoWx6g7TtfbYSnEBg=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-15.6 required=5.0 tests=BAYES_00,\n\tFREEMAIL_FROM, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tKAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=punch","X-HELO":"mail-yw0-f169.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:sender:to:from:subject:message-id:date\n\t:user-agent:mime-version:content-language;\n\tbh=KU9scXMUlh1AtbDrMCslveqHffmgUP41dnpokRgN6F0=;\n\tb=UU2t5GtEoKxOFKFrChD1hMVL7ciK5qKITpyplSVfilprH19jwooXb3VdP/YD3fu3hI\n\tEKh7mgJ9+lMgX06f6JJYioGAsyJS9X2zuEs7mZ2hyhCA9R8BG2ZDG7fG39crSd3ssX4k\n\taVjPvMhoVmy2NyL+P3wOJbv8irj11aT56tLhgMT6vWu9fpbwqJRoKg9EemQQqVQ5EyER\n\tA3x4yVm03LB4YePHBhqt2ZUFdcV6yryhmrWQX40+hSnBA9K3nbCMraCxMss2d8bpTUq0\n\tFzjWFCNRvE3xaHnS5zx5/FJ1c/pr7amrQwPzovBrtszscHwV1+XvXlJ+G+HdQ87gc/Oa\n\tPL/g==","X-Gm-Message-State":"AHPjjUhzEqpHZBm2hufKKh8Q3S92cn01DT3oeMrYEwV3kgzNba+yPvay\t0q5/T7/+2A51kg==","X-Google-Smtp-Source":"ADKCNb4VrSYsGbvD/2c14C/iKOO8qOl15HUQxnuUEsnPLBQEmsYY1jO+AV6QZin754AJ2WK9syJOFg==","X-Received":"by 10.129.193.74 with SMTP id e10mr2285886ywl.262.1504712218784;\n\tWed, 06 Sep 2017 08:36:58 -0700 (PDT)","To":"GCC Patches <gcc-patches@gcc.gnu.org>","From":"Nathan Sidwell <nathan@acm.org>","Subject":"[C++ PATCH] Merge fn and non-fn lookup interface","Message-ID":"<34c52ab3-a673-b1d8-7860-f8273bad5670@acm.org>","Date":"Wed, 6 Sep 2017 11:36:56 -0400","User-Agent":"Mozilla/5.0 (X11; Linux x86_64;\n\trv:52.0) Gecko/20100101 Thunderbird/52.2.1","MIME-Version":"1.0","Content-Type":"multipart/mixed;\n\tboundary=\"------------20D79AA4B109EA110EF277FC\""},"content":"This patch merges the lookup of function and non-function member lookup \ninto get_class_binding_direct.   lookup_field_1 becomes an internal detail.\n\nWe grow a tri-valued argument to get_class_binding_direct:\n<0 -- caller wants functions\n=0 -- caller wants whatever is bound\n >0 -- caller wants type_decl binding.\n\nThis has the nice property that lookup_field_1's want_type argument maps \nonto the latter two values.  The default is the first, which matches the \nexisting get_class_binding usage.  The two places where lookup_field_1 \nwas being called directly are converted and were:\n\n1) hierarchy searching.  This functionality is swallowed by \nget_class_binding_direct, and it passes in the want_type argument.\n\n2) named initializers.  this now passes in 0.  You'll notice this case \nis with the type being complete, so we now might get a binary search of \nMETHOD_VEC that we didn;t before.  This is going to be a short-lived \nperformance regression.\n\napplied to trunk.\n\nI'm going to hold off the next patch as (a) it's more invasive, but (b) \nit steals the punch line from my name-lookup cauldron talk.\n\nnathan","diff":"2017-09-06  Nathan Sidwell  <nathan@acm.org>\n\n\t* name-lookup.h (lookup_field_1): Delete.\n\t(get_class_binding_direct, get_class_binding): Add type_or_fns arg.\n\t* name-lookup.c\t(lookup_field_1): make static\n\t(method_vec_binary_search, method_vec_linear_search): New.  Broken\n\tout of ...\n\t(get_class_binding_direct): ... here.  Add TYPE_OR_FNS argument.\n\tDo complete search of this level.\n\t(get_class_binding): Adjust.\n\t* decl.c (reshape_init_class): Call get_class_binding.\n\t* search.c (lookup_field_r): Move field searching into\n\tget_class_binding_direct.\n\nIndex: decl.c\n===================================================================\n--- decl.c\t(revision 251782)\n+++ decl.c\t(working copy)\n@@ -5746,7 +5746,7 @@ reshape_init_class (tree type, reshape_i\n \t    /* We already reshaped this.  */\n \t    gcc_assert (d->cur->index == field);\n \t  else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)\n-\t    field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);\n+\t    field = get_class_binding (type, d->cur->index, false);\n \t  else\n \t    {\n \t      if (complain & tf_error)\nIndex: name-lookup.c\n===================================================================\n--- name-lookup.c\t(revision 251794)\n+++ name-lookup.c\t(working copy)\n@@ -1113,79 +1113,54 @@ extract_conversion_operator (tree fns, t\n   return convs;\n }\n \n-/* TYPE is a class type. Return the member functions in the method\n-   vector with name NAME.  Does not lazily declare implicitly-declared\n-   member functions.  */\n+/* Binary search of (ordered) METHOD_VEC for NAME.  */\n \n-tree\n-get_class_binding_direct (tree type, tree name)\n+static tree\n+method_vec_binary_search (vec<tree, va_gc> *method_vec, tree name)\n {\n-  vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type);\n-  if (!method_vec)\n-    return NULL_TREE;\n-\n-  /* Conversion operators can only be found by the marker conversion\n-     operator name.  */\n-  bool conv_op = IDENTIFIER_CONV_OP_P (name);\n-  tree lookup = conv_op ? conv_op_identifier : name;\n-  tree val = NULL_TREE;\n-  tree fns;\n-\n-  /* If the type is complete, use binary search.  */\n-  if (COMPLETE_TYPE_P (type))\n+  for (unsigned lo = 0, hi = method_vec->length (); lo < hi;)\n     {\n-      int lo = 0;\n-      int hi = method_vec->length ();\n-      while (lo < hi)\n-\t{\n-\t  int i = (lo + hi) / 2;\n-\n-\t  fns = (*method_vec)[i];\n-\t  tree fn_name = OVL_NAME (fns);\n-\t  if (fn_name > lookup)\n-\t    hi = i;\n-\t  else if (fn_name < lookup)\n-\t    lo = i + 1;\n-\t  else\n-\t    {\n-\t      val = fns;\n-\t      break;\n-\t    }\n-\t}\n+      unsigned mid = (lo + hi) / 2;\n+      tree binding = (*method_vec)[mid];\n+      tree binding_name = OVL_NAME (binding);\n+\n+      if (binding_name > name)\n+\thi = mid;\n+      else if (binding_name < name)\n+\tlo = mid + 1;\n+      else\n+\treturn binding;\n     }\n-  else\n-    for (int i = 0; vec_safe_iterate (method_vec, i, &fns); ++i)\n-      /* We can get a NULL binding during insertion of a new\n-\t method name, because the identifier_binding machinery\n-\t performs a lookup.  If we find such a NULL slot, that's\n-\t the thing we were looking for, so we might as well bail\n-\t out immediately.  */\n-      if (!fns)\n-\tbreak;\n-      else if (OVL_NAME (fns) == lookup)\n-\t{\n-\t  val = fns;\n-\t  break;\n-\t}\n \n-  /* Extract the conversion operators asked for, unless the general\n-     conversion operator was requested.   */\n-  if (val && conv_op)\n-    {\n-      gcc_checking_assert (OVL_FUNCTION (val) == conv_op_marker);\n-      val = OVL_CHAIN (val);\n-      if (tree type = TREE_TYPE (name))\n-\tval = extract_conversion_operator (val, type);\n-    }\n+  return NULL_TREE;\n+}\n \n-  return val;\n+/* Linear search of (unordered) METHOD_VEC for NAME.  */\n+\n+static tree\n+method_vec_linear_search (vec<tree, va_gc> *method_vec, tree name)\n+{\n+  for (int ix = method_vec->length (); ix--;)\n+    /* We can get a NULL binding during insertion of a new method\n+       name, because the identifier_binding machinery performs a\n+       lookup.  If we find such a NULL slot, that's the thing we were\n+       looking for, so we might as well bail out immediately.  */\n+    if (tree binding = (*method_vec)[ix])\n+      {\n+\tif (OVL_NAME (binding) == name)\n+\t  return binding;\n+      }\n+    else\n+      break;\n+\n+  return NULL_TREE;\n }\n \n /* Do a 1-level search for NAME as a member of TYPE.  The caller must\n    figure out whether it can access this field.  (Since it is only one\n    level, this is reasonable.)  */\n \n-tree\n+static tree\n lookup_field_1 (tree type, tree name, bool want_type)\n {\n   tree field;\n@@ -1281,11 +1256,62 @@ lookup_field_1 (tree type, tree name, bo\n   return NULL_TREE;\n }\n \n-/* TYPE is a class type. Return the overloads in\n-   the method vector with name NAME.  Lazily create ctors etc.  */\n+/* Look for NAME as an immediate member of KLASS (including\n+   anon-members or unscoped enum member).  TYPE_OR_FNS is zero for\n+   regular search.  >0 to get a type binding (if there is one) and <0\n+   if you want (just) the member function binding.\n+\n+   Use this if you do not want lazy member creation.  */\n+\n+tree\n+get_class_binding_direct (tree klass, tree name, int type_or_fns)\n+{\n+  gcc_checking_assert (RECORD_OR_UNION_TYPE_P (klass));\n+\n+  /* Conversion operators can only be found by the marker conversion\n+     operator name.  */\n+  bool conv_op = IDENTIFIER_CONV_OP_P (name);\n+  tree lookup = conv_op ? conv_op_identifier : name;\n+  tree val = NULL_TREE;\n+  vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (klass);\n+\n+  if (!method_vec || type_or_fns > 0)\n+    ;\n+  else if (COMPLETE_TYPE_P (klass))\n+    val = method_vec_binary_search (method_vec, lookup);\n+  else\n+    val = method_vec_linear_search (method_vec, lookup);\n+\n+  if (type_or_fns < 0)\n+    /* Don't bother looking for field.  We don't want it.  */;\n+  else if (!val || (TREE_CODE (val) == OVERLOAD && OVL_USING_P (val)))\n+    {\n+      /* Dependent using declarations are a 'field', make sure we\n+\t return that even if we saw an overload already.  */\n+      if (tree field_val = lookup_field_1 (klass, lookup, type_or_fns > 0))\n+\tif (!val || TREE_CODE (field_val) == USING_DECL)\n+\t  val = field_val;\n+    }\n+\n+  /* Extract the conversion operators asked for, unless the general\n+     conversion operator was requested.   */\n+  if (val && conv_op)\n+    {\n+      gcc_checking_assert (OVL_FUNCTION (val) == conv_op_marker);\n+      val = OVL_CHAIN (val);\n+      if (tree type = TREE_TYPE (name))\n+\tval = extract_conversion_operator (val, type);\n+    }\n+\n+  return val;\n+}\n+\n+/* Look for NAME's binding in exactly KLASS.  See\n+   get_class_binding_direct for argument description.  Does lazy\n+   special function creation as necessary.  */\n \n tree\n-get_class_binding (tree type, tree name)\n+get_class_binding (tree type, tree name, int type_or_fns)\n {\n   type = complete_type (type);\n \n@@ -1314,7 +1340,7 @@ get_class_binding (tree type, tree name)\n \t}\n     }\n \n-  return get_class_binding_direct (type, name);\n+  return get_class_binding_direct (type, name, type_or_fns);\n }\n \n /* Find the slot containing overloads called 'NAME'.  If there is no\nIndex: name-lookup.h\n===================================================================\n--- name-lookup.h\t(revision 251782)\n+++ name-lookup.h\t(working copy)\n@@ -319,9 +319,8 @@ extern void pop_decl_namespace (void);\n extern void do_namespace_alias (tree, tree);\n extern tree do_class_using_decl (tree, tree);\n extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *);\n-extern tree lookup_field_1\t\t\t(tree, tree, bool);\n-extern tree get_class_binding_direct (tree, tree);\n-extern tree get_class_binding (tree, tree);\n+extern tree get_class_binding_direct (tree, tree, int type_or_fns = -1);\n+extern tree get_class_binding (tree, tree, int type_or_fns = -1);\n extern tree *get_method_slot (tree klass, tree name);\n extern void resort_type_method_vec (void *, void *,\n \t\t\t\t    gt_pointer_operator, void *);\nIndex: search.c\n===================================================================\n--- search.c\t(revision 251782)\n+++ search.c\t(working copy)\n@@ -974,23 +974,7 @@ lookup_field_r (tree binfo, void *data)\n       && !BINFO_VIRTUAL_P (binfo))\n     return dfs_skip_bases;\n \n-  /* First, look for a function.  There can't be a function and a data\n-     member with the same name, and if there's a function and a type\n-     with the same name, the type is hidden by the function.  */\n-  if (!lfi->want_type)\n-    nval = get_class_binding (type, lfi->name);\n-\n-  if (!nval)\n-    /* Look for a data member or type.  */\n-    nval = lookup_field_1 (type, lfi->name, lfi->want_type);\n-  else if (TREE_CODE (nval) == OVERLOAD && OVL_USING_P (nval))\n-    {\n-      /* If we have both dependent and non-dependent using-declarations, return\n-\t the dependent one rather than an incomplete list of functions.  */\n-      tree dep_using = lookup_field_1 (type, lfi->name, lfi->want_type);\n-      if (dep_using && TREE_CODE (dep_using) == USING_DECL)\n-\tnval = dep_using;\n-    }\n+  nval = get_class_binding (type, lfi->name, lfi->want_type);\n \n   /* If we're looking up a type (as with an elaborated type specifier)\n      we ignore all non-types we find.  */\n","prefixes":["C++"]}