public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/65498 (ICE with constexpr template argument)
@ 2015-03-24 19:37 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2015-03-24 19:37 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 615 bytes --]

This testcase was breaking because is_same::operator() is only used in 
constexpr evaluation, so cgraph decides it isn't used and throws it 
away.  Then mangling tries to use it for constexpr evaluation while 
re-instantiating F<A> under get_mostly_instantiated_function_type, and 
sadness ensues.

It occurred to me that we really ought to be able to avoid re-doing this 
instantiation, since DECL_TI_TEMPLATE of a function is a partially 
instantiated template that already has the type we want.  And indeed 
this seems to work well, even fixing a bug in mangling.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: 65498.patch --]
[-- Type: text/x-patch, Size: 4163 bytes --]

commit 11b13941b2b09f20cb0d42a48199b17a927f624f
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Mar 23 18:44:04 2015 -0400

    	PR c++/65498
    	* pt.c (get_mostly_instantiated_function_type): Just return the
    	type of the partially instantiated template in DECL_TI_TEMPLATE.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ea82621..c649cad 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -20748,62 +20748,8 @@ tsubst_enum (tree tag, tree newtag, tree args)
 tree
 get_mostly_instantiated_function_type (tree decl)
 {
-  tree fn_type;
-  tree tmpl;
-  tree targs;
-  tree tparms;
-  int parm_depth;
-
-  tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
-  targs = DECL_TI_ARGS (decl);
-  tparms = DECL_TEMPLATE_PARMS (tmpl);
-  parm_depth = TMPL_PARMS_DEPTH (tparms);
-
-  /* There should be as many levels of arguments as there are levels
-     of parameters.  */
-  gcc_assert (parm_depth == TMPL_ARGS_DEPTH (targs));
-
-  fn_type = TREE_TYPE (tmpl);
-
-  if (parm_depth == 1)
-    /* No substitution is necessary.  */
-    ;
-  else
-    {
-      int i;
-      tree partial_args;
-
-      /* Replace the innermost level of the TARGS with NULL_TREEs to
-	 let tsubst know not to substitute for those parameters.  */
-      partial_args = make_tree_vec (TREE_VEC_LENGTH (targs));
-      for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
-	SET_TMPL_ARGS_LEVEL (partial_args, i,
-			     TMPL_ARGS_LEVEL (targs, i));
-      SET_TMPL_ARGS_LEVEL (partial_args,
-			   TMPL_ARGS_DEPTH (targs),
-			   make_tree_vec (DECL_NTPARMS (tmpl)));
-
-      /* Make sure that we can see identifiers, and compute access
-	 correctly.  */
-      push_access_scope (decl);
-
-      ++processing_template_decl;
-      /* Now, do the (partial) substitution to figure out the
-	 appropriate function type.  */
-      fn_type = tsubst (fn_type, partial_args, tf_error, NULL_TREE);
-      --processing_template_decl;
-
-      /* Substitute into the template parameters to obtain the real
-	 innermost set of parameters.  This step is important if the
-	 innermost set of template parameters contains value
-	 parameters whose types depend on outer template parameters.  */
-      TREE_VEC_LENGTH (partial_args)--;
-      tparms = tsubst_template_parms (tparms, partial_args, tf_error);
-
-      pop_access_scope (decl);
-    }
-
-  return fn_type;
+  /* For a function, DECL_TI_TEMPLATE is partially instantiated.  */
+  return TREE_TYPE (DECL_TI_TEMPLATE (decl));
 }
 
 /* Return truthvalue if we're processing a template different from
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ2.C
new file mode 100644
index 0000000..285d6c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ2.C
@@ -0,0 +1,40 @@
+// PR c++/65498
+// { dg-do compile { target c++11 } }
+
+template <typename, typename>
+struct is_same
+{
+  enum { value = false };
+  constexpr bool operator()() const noexcept { return value; }
+};
+
+template <typename T>
+struct is_same<T, T>
+{
+  enum { value = true };
+  constexpr bool operator()() const noexcept { return value; }
+};
+
+template <bool, typename = void>
+struct enable_if { };
+
+template <typename T>
+struct enable_if<true, T> { typedef T type; };
+
+struct A;
+
+template <typename, typename = void>
+struct F { };
+
+template <typename X>
+struct F<X, typename enable_if<is_same<X, A>{}()>::type> {
+    template <typename MakeDependent>
+    F(MakeDependent) {
+        auto ICE_HERE = __func__;
+        (void)ICE_HERE; // avoid -Wunused-variable
+    }
+};
+
+int main() {
+    F<A>{1};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C
index 2b1a605..01fe3f6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template13.C
@@ -20,5 +20,5 @@ void bar ()
   c.foo (1);
 }
 
-// { dg-final { scan-assembler "_ZN8functionC1IZN1CIiE3fooIiEEvT_S_Ed_UlvE_EET_" } }
+// { dg-final { scan-assembler "_ZN8functionC1IZN1CIiE3fooIiEEvT_S_Ed_UlvE_EES4_" } }
 // { dg-final { scan-assembler-not "_ZZN1CIiE3fooIiEEvT_8functionEd_NKUlvE_clEv" } }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-03-24 19:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-24 19:37 C++ PATCH for c++/65498 (ICE with constexpr template argument) Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).