This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for new testcase in c++/14912


A recent comment to closed PR 14912 shows a problem with the patch: substituting into the default template argument can require class template instantiations that would not normally be needed, which is particularly problematic if those instantiations are ill-formed. Fixed thus.

Tested x86_64-pc-linux-gnu, applied to trunk.
2009-07-29  Jason Merrill  <jason@redhat.com>

	PR c++/14912
	* cp-tree.h (enum tsubst_flags): Add tf_no_class_instantiations.
	* error.c (count_non_default_template_args): Pass it.
	* pt.c (tsubst) [TYPENAME_TYPE]: Don't complete type if it's set.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2bc2d62..dcad934 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3616,6 +3616,8 @@ enum tsubst_flags {
 				    conversion.  */
   tf_no_access_control = 1 << 7, /* Do not perform access checks, even
 				    when issuing other errors.   */
+  /* Do not instantiate classes (used by count_non_default_template_args). */
+  tf_no_class_instantiations = 1 << 8,
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 };
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c5310ff..25a0580 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -182,7 +182,10 @@ count_non_default_template_args (tree args, tree params)
       if (uses_template_parms (def))
 	{
 	  ++processing_template_decl;
-	  def = tsubst_copy_and_build (def, args, tf_none, NULL_TREE, false, true);
+	  /* This speculative substitution must not cause any classes to be
+	     instantiated that otherwise wouldn't be.  */
+	  def = tsubst_copy_and_build (def, args, tf_no_class_instantiations,
+				       NULL_TREE, false, true);
 	  --processing_template_decl;
 	}
       if (!cp_tree_equal (TREE_VEC_ELT (inner_args, last), def))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index de9f828..ed45324 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9890,7 +9890,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	       But, such constructs have already been resolved by this
 	       point, so here CTX really should have complete type, unless
 	       it's a partial instantiation.  */
-	    ctx = complete_type (ctx);
+	    if (!(complain & tf_no_class_instantiations))
+	      ctx = complete_type (ctx);
 	    if (!COMPLETE_TYPE_P (ctx))
 	      {
 		if (complain & tf_error)
diff --git a/gcc/testsuite/g++.dg/template/defarg13.C b/gcc/testsuite/g++.dg/template/defarg13.C
new file mode 100644
index 0000000..ba2980b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/defarg13.C
@@ -0,0 +1,19 @@
+// PR c++/14912
+// Bug: We were instantiating A<B> in order to compare it to the matching
+// argument for C<B,B>, which fails.
+
+template <class T>
+struct A
+{
+  typedef typename T::F F;
+};
+
+struct B { };
+
+template <class T, class U = typename A<T>::F >
+struct C
+{
+  typename T::F f;		// { dg-error "no type" }
+};
+
+C<B, B> c;			// { dg-message "instantiated" }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]