diff mbox

C++ PATCH to improve various small diagnostic issues

Message ID CADzB+2mijPN1Lv-qsspo71Yjyq76qqASNjeis1XBZ0CtqdhtPw@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Nov. 14, 2016, 4:55 a.m. UTC
A few things I noticed while working on C++17 decomposition.

* We were omitting any explicit template arguments in the "no match" error.
* We were complaining about a missing nested type rather than an
incomplete enclosing type.
* We weren't printing the new type when an alias-declaration is
redeclared to a different type.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit d221ee0ac4e748bfa910d95bbaf994d803154589
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Nov 11 16:54:03 2016 -0800

    Improve various diagnostic issues.
    
      * decl.c (make_typename_type): Call cxx_incomplete_type_error.
      * parser.c (cp_parser_diagnose_invalid_type_name): Likewise.
      * error.c (dump_decl): Fix printing of alias declaration.
      * call.c (build_new_method_call_1): Include template arguments in error.
diff mbox

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 0dcf322..f6f4590 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4146,8 +4146,16 @@  static void
 print_error_for_call_failure (tree fn, vec<tree, va_gc> *args,
 			      struct z_candidate *candidates)
 {
+  tree targs = NULL_TREE;
+  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+    {
+      targs = TREE_OPERAND (fn, 1);
+      fn = TREE_OPERAND (fn, 0);
+    }
   tree name = DECL_NAME (OVL_CURRENT (fn));
   location_t loc = location_of (name);
+  if (targs)
+    name = lookup_template_function (name, targs);
 
   if (!any_strictly_viable (candidates))
     error_at (loc, "no matching function for call to %<%D(%A)%>",
@@ -4215,8 +4223,6 @@  build_new_function_call (tree fn, vec<tree, va_gc> **args, bool koenig_p,
 	    return cp_build_function_call_vec (candidates->fn, args, complain);
 
 	  // Otherwise, emit notes for non-viable candidates.
-	  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
-	    fn = TREE_OPERAND (fn, 0);
 	  print_error_for_call_failure (fn, *args, candidates);
 	}
       result = error_mark_node;
@@ -8649,19 +8655,20 @@  build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
 		   TREE_TYPE (instance));
 	  else
 	    {
-	      char *pretty_name;
-	      bool free_p;
-	      tree arglist;
-
-	      pretty_name = name_as_c_string (name, basetype, &free_p);
-	      arglist = build_tree_list_vec (user_args);
+	      tree arglist = build_tree_list_vec (user_args);
+	      tree errname = name;
+	      if (IDENTIFIER_CTOR_OR_DTOR_P (errname))
+		{
+		  tree fn = DECL_ORIGIN (get_first_fn (fns));
+		  errname = DECL_NAME (fn);
+		}
+	      if (explicit_targs)
+		errname = lookup_template_function (errname, explicit_targs);
 	      if (skip_first_for_error)
 		arglist = TREE_CHAIN (arglist);
-	      error ("no matching function for call to %<%T::%s(%A)%#V%>",
-		     basetype, pretty_name, arglist,
+	      error ("no matching function for call to %<%T::%E(%A)%#V%>",
+		     basetype, errname, arglist,
 		     TREE_TYPE (instance));
-	      if (free_p)
-		free (pretty_name);
 	    }
 	  print_z_candidates (location_of (name), candidates);
 	}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6101504..ccd65b1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3756,8 +3756,13 @@  make_typename_type (tree context, tree name, enum tag_types tag_type,
   if (!t)
     {
       if (complain & tf_error)
-	error (want_template ? G_("no class template named %q#T in %q#T")
-	       : G_("no type named %q#T in %q#T"), name, context);
+	{
+	  if (!COMPLETE_TYPE_P (context))
+	    cxx_incomplete_type_error (NULL_TREE, context);
+	  else
+	    error (want_template ? G_("no class template named %q#T in %q#T")
+		   : G_("no type named %q#T in %q#T"), name, context);
+	}
       return error_mark_node;
     }
   
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index aa92a7e..fe1f751 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1049,7 +1049,9 @@  dump_decl (cxx_pretty_printer *pp, tree t, int flags)
 	  pp_cxx_whitespace (pp);
 	  pp_cxx_ws_string (pp, "=");
 	  pp_cxx_whitespace (pp);
-	  dump_type (pp, DECL_ORIGINAL_TYPE (t), flags);
+	  dump_type (pp, (DECL_ORIGINAL_TYPE (t)
+			  ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t)),
+		     flags);
 	  break;
 	}
       if ((flags & TFF_DECL_SPECIFIERS)
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8db6cfd..172ec82 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -565,7 +565,8 @@  supplement_binding_1 (cxx_binding *binding, tree decl)
     }
   else
     {
-      diagnose_name_conflict (decl, bval);
+      if (!error_operand_p (bval))
+	diagnose_name_conflict (decl, bval);
       ok = false;
     }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b3b69b3..4204fa5 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3272,7 +3272,10 @@  cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
 		  parser->scope, id, parser->scope);
       else if (TYPE_P (parser->scope))
 	{
-	  if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+	  if (!COMPLETE_TYPE_P (parser->scope))
+	    cxx_incomplete_type_error (location_of (id), NULL_TREE,
+				       parser->scope);
+	  else if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
 	    error_at (location_of (id),
 		      "%qE in %q#T does not name a template type",
 		      id, parser->scope);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1a7c478..d390bf4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2259,7 +2259,7 @@  perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
 	}
     }
 
-  if (fn && template_id)
+  if (fn && template_id && fn != error_mark_node)
     fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args);
   
   return fn;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-56.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-56.C
new file mode 100644
index 0000000..7e894cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-56.C
@@ -0,0 +1,4 @@ 
+// { dg-do compile { target c++11 } }
+
+using I = int;			// { dg-message "int" }
+using I = float;		// { dg-error "float" }
diff --git a/gcc/testsuite/g++.dg/template/crash7.C b/gcc/testsuite/g++.dg/template/crash7.C
index 5bd275e..691628e 100644
--- a/gcc/testsuite/g++.dg/template/crash7.C
+++ b/gcc/testsuite/g++.dg/template/crash7.C
@@ -7,7 +7,7 @@ 
 
 template <typename> struct A
 {
-    template <typename> A(typename A::X) {} // { dg-error "no type" }
+    template <typename> A(typename A::X) {} // { dg-error "incomplete" }
 };
 
 // We currently don't give the "no match" error because we don't add the
diff --git a/gcc/testsuite/g++.dg/template/error56.C b/gcc/testsuite/g++.dg/template/error56.C
new file mode 100644
index 0000000..3eda04c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error56.C
@@ -0,0 +1,12 @@ 
+// Test that the error message mentions the template arguments.
+
+struct A
+{
+  template <class T> void f(T);
+  void f();
+};
+
+int main()
+{
+  A().f<1>();			// { dg-error "f<1>" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/forward-inner.C b/gcc/testsuite/g++.dg/warn/forward-inner.C
index dae9948..5336d4e 100644
--- a/gcc/testsuite/g++.dg/warn/forward-inner.C
+++ b/gcc/testsuite/g++.dg/warn/forward-inner.C
@@ -3,13 +3,13 @@ 
 
 // Verify warnings for and within classes, and by extension, struct and union.
 class C1;
-class C1::C2;      // { dg-error "does not name a type" }
+class C1::C2;      // { dg-error "incomplete" }
 class C1::C2::C3;  // { dg-error "has not been declared" }
 
 class C1 {
  public:
   class C2;
-  class C2::C3;    // { dg-error "does not name a type" }
+  class C2::C3;    // { dg-error "incomplete" }
   class C2 {
    public:
     class C3;
diff --git a/gcc/testsuite/g++.old-deja/g++.other/decl5.C b/gcc/testsuite/g++.old-deja/g++.other/decl5.C
index 2a7a5f2..aa2acf8 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/decl5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/decl5.C
@@ -19,7 +19,7 @@  struct A {
   struct Z;
   expand me;          // { dg-error "'expand' does not name a type" }
   void foo(struct A::e);
-  void foo(struct A::z);  // { dg-error "does not name a type" }
+  void foo(struct A::z);  // { dg-error "incomplete" }
 };
 
 struct Q;
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index 4f0720a..a659716 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -41,7 +41,7 @@  void test01()
   typedef make_signed<float>::type  	test5_type;
 }
 
-// { dg-error "does not name a type" "" { target *-*-* } 32 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 32 }
 // { dg-error "required from here" "" { target *-*-* } 34 }
 // { dg-error "required from here" "" { target *-*-* } 36 }
 // { dg-error "required from here" "" { target *-*-* } 39 }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index 8eea6b9..6a93e2f3 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -41,7 +41,7 @@  void test01()
   typedef make_unsigned<float>::type  		test5_type;
 }
 
-// { dg-error "does not name a type" "" { target *-*-* } 32 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 32 }
 // { dg-error "required from here" "" { target *-*-* } 34 }
 // { dg-error "required from here" "" { target *-*-* } 36 }
 // { dg-error "required from here" "" { target *-*-* } 39 }