decl.c (min_location): New.
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 3 Jul 2018 21:03:51 +0000 (21:03 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 3 Jul 2018 21:03:51 +0000 (21:03 +0000)
/cp
2018-07-03  Paolo Carlini  <paolo.carlini@oracle.com>

* decl.c (min_location): New.
(smallest_type_quals_location): Use the latter.
(check_concept_fn): Use DECL_SOURCE_LOCATION.
(grokdeclarator): Use accurate locations in a number of error
messages involving ds_thread, ds_storage_class, ds_virtual,
ds_constexpr, ds_typedef and ds_friend; exploit min_location.

/testsuite
2018-07-03  Paolo Carlini  <paolo.carlini@oracle.com>

* g++.dg/other/locations1.C: New.
* g++.dg/tls/locations1.C: Likewise.
* g++.dg/diagnostic/virtual-constexpr.C: Likewise.
* g++.dg/diagnostic/virtual-static.C: Likewise.
* g++.dg/concepts/fn-concept2.C: Test the locations too.
* g++.dg/cpp0x/constexpr-virtual5.C: Likewise.
* g++.dg/cpp0x/pr51463.C: Likewise.
* g++.dg/other/typedef1.C: Likewise.
* g++.dg/parse/dtor13.C: Likewise.
* g++.dg/template/error44.C: Likewise.
* g++.dg/template/typedef4.C: Likewise.
* g++.dg/template/typedef5.C: Likewise.
* g++.dg/tls/diag-2.C: Likewise.
* g++.old-deja/g++.brendan/crash11.C: Likewise.

From-SVN: r262358

17 files changed:
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/concepts/fn-concept2.C
gcc/testsuite/g++.dg/cpp0x/constexpr-virtual5.C
gcc/testsuite/g++.dg/cpp0x/pr51463.C
gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/virtual-static.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/locations1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/typedef1.C
gcc/testsuite/g++.dg/parse/dtor13.C
gcc/testsuite/g++.dg/template/error44.C
gcc/testsuite/g++.dg/template/typedef4.C
gcc/testsuite/g++.dg/template/typedef5.C
gcc/testsuite/g++.dg/tls/diag-2.C
gcc/testsuite/g++.dg/tls/locations1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.brendan/crash11.C

index e4202e161babe4ace7dab75d0f7315b12079a8f1..c27e2deb2ce29ad6179d9ac94f86251223a0a8b7 100644 (file)
@@ -1,3 +1,12 @@
+2018-07-03  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * decl.c (min_location): New.
+       (smallest_type_quals_location): Use the latter.
+       (check_concept_fn): Use DECL_SOURCE_LOCATION.
+       (grokdeclarator): Use accurate locations in a number of error
+       messages involving ds_thread, ds_storage_class, ds_virtual,
+       ds_constexpr, ds_typedef and ds_friend; exploit min_location.
+
 2018-07-03  Marek Polacek  <polacek@redhat.com>
 
        PR c++/86201
index c04b9b7d457f122b8ddad6535c91ba811c67553d..0ea3c4a3490808739b3d326d32e3d4ec0f477724 100644 (file)
@@ -8545,15 +8545,18 @@ check_concept_fn (tree fn)
 {
   // A constraint is nullary.
   if (DECL_ARGUMENTS (fn))
-    error ("concept %q#D declared with function parameters", fn);
+    error_at (DECL_SOURCE_LOCATION (fn),
+             "concept %q#D declared with function parameters", fn);
 
   // The declared return type of the concept shall be bool, and
   // it shall not be deduced from it definition.
   tree type = TREE_TYPE (TREE_TYPE (fn));
   if (is_auto (type))
-    error ("concept %q#D declared with a deduced return type", fn);
+    error_at (DECL_SOURCE_LOCATION (fn),
+             "concept %q#D declared with a deduced return type", fn);
   else if (type != boolean_type_node)
-    error ("concept %q#D with non-%<bool%> return type %qT", fn, type);
+    error_at (DECL_SOURCE_LOCATION (fn),
+             "concept %q#D with non-%<bool%> return type %qT", fn, type);
 }
 
 /* Helper function.  Replace the temporary this parameter injected
@@ -9795,6 +9798,18 @@ create_array_type_for_decl (tree name, tree type, tree size)
   return build_cplus_array_type (type, itype);
 }
 
+/* Returns the smallest location that is not UNKNOWN_LOCATION.  */
+
+static location_t
+min_location (location_t loca, location_t locb)
+{
+  if (loca == UNKNOWN_LOCATION
+      || (locb != UNKNOWN_LOCATION
+         && linemap_location_before_p (line_table, locb, loca)))
+    return locb;
+  return loca;
+}
+
 /* Returns the smallest location != UNKNOWN_LOCATION among the
    three stored in LOCATIONS[ds_const], LOCATIONS[ds_volatile],
    and LOCATIONS[ds_restrict].  */
@@ -9807,13 +9822,11 @@ smallest_type_quals_location (int type_quals, const location_t* locations)
   if (type_quals & TYPE_QUAL_CONST)
     loc = locations[ds_const];
 
-  if ((type_quals & TYPE_QUAL_VOLATILE)
-      && (loc == UNKNOWN_LOCATION || locations[ds_volatile] < loc))
-    loc = locations[ds_volatile];
+  if (type_quals & TYPE_QUAL_VOLATILE)
+    loc = min_location (loc, locations[ds_volatile]);
 
-  if ((type_quals & TYPE_QUAL_RESTRICT)
-      && (loc == UNKNOWN_LOCATION || locations[ds_restrict] < loc))
-    loc = locations[ds_restrict];
+  if (type_quals & TYPE_QUAL_RESTRICT)
+    loc = min_location (loc, locations[ds_restrict]);
 
   return loc;
 }
@@ -10710,14 +10723,20 @@ grokdeclarator (const cp_declarator *declarator,
     {
       if (staticp == 2)
        {
-         error ("member %qD cannot be declared both %<virtual%> "
-                "and %<static%>", dname);
+         rich_location richloc (line_table, declspecs->locations[ds_virtual]);
+         richloc.add_range (declspecs->locations[ds_storage_class], false);
+         error_at (&richloc, "member %qD cannot be declared both %<virtual%> "
+                   "and %<static%>", dname);
          storage_class = sc_none;
          staticp = 0;
        }
       if (constexpr_p)
-       error ("member %qD cannot be declared both %<virtual%> "
-              "and %<constexpr%>", dname);
+       {
+         rich_location richloc (line_table, declspecs->locations[ds_virtual]);
+         richloc.add_range (declspecs->locations[ds_constexpr], false);
+         error_at (&richloc, "member %qD cannot be declared both %<virtual%> "
+                   "and %<constexpr%>", dname);
+       }
     }
   friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
 
@@ -10726,18 +10745,27 @@ grokdeclarator (const cp_declarator *declarator,
     {
       if (typedef_p)
        {
-         error ("typedef declaration invalid in parameter declaration");
+         error_at (declspecs->locations[ds_typedef],
+                   "typedef declaration invalid in parameter declaration");
          return error_mark_node;
        }
       else if (template_parm_flag && storage_class != sc_none)
        {
-         error ("storage class specified for template parameter %qs", name);
+         error_at (min_location (declspecs->locations[ds_thread],
+                                 declspecs->locations[ds_storage_class]),
+                   "storage class specified for template parameter %qs",
+                   name);
          return error_mark_node;
        }
       else if (storage_class == sc_static
               || storage_class == sc_extern
               || thread_p)
-       error ("storage class specifiers invalid in parameter declarations");
+       {
+         error_at (min_location (declspecs->locations[ds_thread],
+                                 declspecs->locations[ds_storage_class]),
+                   "storage class specified for parameter %qs", name);
+         return error_mark_node;
+       }
 
       /* Function parameters cannot be concept. */
       if (concept_p)
@@ -10871,15 +10899,15 @@ grokdeclarator (const cp_declarator *declarator,
        ;
       else
        {
+         location_t loc
+           = min_location (declspecs->locations[ds_thread],
+                           declspecs->locations[ds_storage_class]);
          if (decl_context == FIELD)
-           error ("storage class specified for %qs", name);
+           error_at (loc, "storage class specified for %qs", name);
+         else if (decl_context == PARM || decl_context == CATCHPARM)
+           error_at (loc, "storage class specified for parameter %qs", name);
          else
-           {
-             if (decl_context == PARM || decl_context == CATCHPARM)
-               error ("storage class specified for parameter %qs", name);
-             else
-               error ("storage class specified for typename");
-           }
+           error_at (loc, "storage class specified for typename");
          if (storage_class == sc_register
              || storage_class == sc_auto
              || storage_class == sc_extern
@@ -10900,7 +10928,8 @@ grokdeclarator (const cp_declarator *declarator,
           && storage_class != sc_static)
     {
       if (declspecs->gnu_thread_keyword_p)
-       pedwarn (input_location, 0, "function-scope %qs implicitly auto and "
+       pedwarn (declspecs->locations[ds_thread],
+                0, "function-scope %qs implicitly auto and "
                 "declared %<__thread%>", name);
 
       /* When thread_local is applied to a variable of block scope the
@@ -10912,7 +10941,10 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (storage_class && friendp)
     {
-      error ("storage class specifiers invalid in friend function declarations");
+      error_at (min_location (declspecs->locations[ds_thread],
+                             declspecs->locations[ds_storage_class]),
+               "storage class specifiers invalid in friend function "
+               "declarations");
       storage_class = sc_none;
       staticp = 0;
     }
@@ -11238,7 +11270,8 @@ grokdeclarator (const cp_declarator *declarator,
                if (virtualp)
                  {
                    /* Cannot be both friend and virtual.  */
-                   error ("virtual functions cannot be friends");
+                   error_at (declspecs->locations[ds_friend],
+                             "virtual functions cannot be friends");
                    friendp = 0;
                  }
                if (decl_context == NORMAL)
@@ -12369,15 +12402,18 @@ grokdeclarator (const cp_declarator *declarator,
        else if (thread_p)
          {
            if (declspecs->gnu_thread_keyword_p)
-             error ("storage class %<__thread%> invalid for function %qs",
-                    name);
+             error_at (declspecs->locations[ds_thread],
+                       "storage class %<__thread%> invalid for function %qs",
+                       name);
            else
-             error ("storage class %<thread_local%> invalid for function %qs",
-                    name);
+             error_at (declspecs->locations[ds_thread],
+                       "storage class %<thread_local%> invalid for "
+                       "function %qs", name);
          }
 
         if (virt_specifiers)
-          error ("virt-specifiers in %qs not allowed outside a class definition", name);
+          error ("virt-specifiers in %qs not allowed outside a class "
+                "definition", name);
        /* Function declaration not at top level.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
index d18061088b8428ecb829fe9f41f584b07d29ad54..d4f97d24162e4b27ba795635bbaeeb3a40e66848 100644 (file)
@@ -1,3 +1,20 @@
+2018-07-03  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * g++.dg/other/locations1.C: New.
+       * g++.dg/tls/locations1.C: Likewise.
+       * g++.dg/diagnostic/virtual-constexpr.C: Likewise.
+       * g++.dg/diagnostic/virtual-static.C: Likewise.
+       * g++.dg/concepts/fn-concept2.C: Test the locations too.
+       * g++.dg/cpp0x/constexpr-virtual5.C: Likewise.
+       * g++.dg/cpp0x/pr51463.C: Likewise.
+       * g++.dg/other/typedef1.C: Likewise.
+       * g++.dg/parse/dtor13.C: Likewise.
+       * g++.dg/template/error44.C: Likewise.
+       * g++.dg/template/typedef4.C: Likewise.
+       * g++.dg/template/typedef5.C: Likewise.
+       * g++.dg/tls/diag-2.C: Likewise.
+       * g++.old-deja/g++.brendan/crash11.C: Likewise.
+
 2018-07-03  Marek Polacek  <polacek@redhat.com>
 
        PR c++/86201
index 9acc24177ce58f3c5b33e0e593f94fb5e2d25d7b..fe88dce1bd4863b27866a2841d1d1ffecd653f25 100644 (file)
@@ -1,7 +1,10 @@
 // { dg-options "-std=c++17 -fconcepts" }
 
 template<typename T>
-  concept auto C1() { return 0; } // { dg-error "deduced return type" }
+  concept auto C1() { return 0; } // { dg-error "16:concept .concept auto C1\\(\\). declared with a deduced return type" }
 
 template<typename T>
-  concept int C2() { return 0; } // { dg-error "return type" }
+  concept int C2() { return 0; } // { dg-error "15:concept .concept int C2\\(\\). with non-.bool. return type .int." }
+
+template<typename T>
+  concept bool C3(int) { return 0; } // { dg-error "16:concept .concept bool C3\\(int\\). declared with function parameters" }
index 895de506d6740de3b65b970b1dc5c66b1655b299..2465f9d9b4f3b095afb07b8d24c89384d1ffcfbe 100644 (file)
@@ -2,5 +2,5 @@
 // { dg-do compile { target c++11 } }
 
 struct S {
-  constexpr virtual int f() { return 1; }  // { dg-error "both 'virtual' and 'constexpr'" }
+  constexpr virtual int f() { return 1; }  // { dg-error "13:member .f. cannot be declared both .virtual. and .constexpr." }
 };
index 75de47d60e469b490148e64b6c889b757dc1c076..472a812205aadfed6c93b3727f59539fb0613c04 100644 (file)
@@ -3,5 +3,6 @@
 
 struct A
 {
-  static virtual int i = 0;    // { dg-error "both 'virtual' and 'static'|declared as" }
+  static virtual int i = 0;    // { dg-error "10:member .i. cannot be declared both .virtual. and .static." }
+  // { dg-error "declared as" "" { target *-*-* } .-1 }
 };
diff --git a/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C b/gcc/testsuite/g++.dg/diagnostic/virtual-constexpr.C
new file mode 100644 (file)
index 0000000..2c83236
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-options "-fdiagnostics-show-caret" }
+// { dg-do compile { target c++11 } }
+
+struct S
+{
+  virtual constexpr void foo();  // { dg-error "3:member .foo. cannot be declared both .virtual. and .constexpr." }
+/* { dg-begin-multiline-output "" }
+   virtual constexpr void foo();
+   ^~~~~~~ ~~~~~~~~~
+   { dg-end-multiline-output "" } */
+  constexpr virtual void bar();  // { dg-error "13:member .bar. cannot be declared both .virtual. and .constexpr." }
+/* { dg-begin-multiline-output "" }
+   constexpr virtual void bar();
+   ~~~~~~~~~ ^~~~~~~
+   { dg-end-multiline-output "" } */
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/virtual-static.C b/gcc/testsuite/g++.dg/diagnostic/virtual-static.C
new file mode 100644 (file)
index 0000000..bffb05e
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+struct S
+{
+  virtual static void foo();  // { dg-error "3:member .foo. cannot be declared both .virtual. and .static." }
+/* { dg-begin-multiline-output "" }
+   virtual static void foo();
+   ^~~~~~~ ~~~~~~
+   { dg-end-multiline-output "" } */
+  static virtual void bar();  // { dg-error "10:member .bar. cannot be declared both .virtual. and .static." }
+/* { dg-begin-multiline-output "" }
+   static virtual void bar();
+   ~~~~~~ ^~~~~~~
+   { dg-end-multiline-output "" } */
+};
diff --git a/gcc/testsuite/g++.dg/other/locations1.C b/gcc/testsuite/g++.dg/other/locations1.C
new file mode 100644 (file)
index 0000000..77b009f
--- /dev/null
@@ -0,0 +1 @@
+void foo(static int p);  // { dg-error "10:storage class specified" }
index ef1684d7aeffa17fb009b7092f763eef7ed3e3d9..83eab1625b8507f983600b3bee351fd210f9f60d 100644 (file)
@@ -1,7 +1,10 @@
 // PR c++/27572
 // { dg-do compile }
 
-void f1(typedef) {}        // { dg-error "no type|typedef declaration" }
-void f2(typedef x) {}      // { dg-error "type|typedef declaration" }
-void f3(typedef x[]) {}    // { dg-error "type|typedef declaration" }
-void f4(typedef int x) {}  // { dg-error "typedef declaration" }
+void f1(typedef) {}        // { dg-error "9:typedef declaration" }
+// { dg-error "no type" "" { target *-*-* } .-1 }
+void f2(typedef x) {}      // { dg-error "9:typedef declaration" }
+// { dg-error "type" "" { target *-*-* } .-1 }
+void f3(typedef x[]) {}    // { dg-error "9:typedef declaration" }
+// { dg-error "type" "" { target *-*-* } .-1 }
+void f4(typedef int x) {}  // { dg-error "9:typedef declaration" }
index 96c0d227b045d143750d1de03e0ea113f331fe24..c68d41e83720b4fa53ae70bc8508f826e39df10b 100644 (file)
@@ -3,6 +3,7 @@
 
 struct A
 {
-  static friend A::~A(); /* { dg-error "storage class specifiers|extra qualification|implicitly friend" } */
+  static friend A::~A(); /* { dg-error "3:storage class specifiers" } */
+  /* { dg-error "extra qualification|implicitly friend" "" { target *-*-* } .-1 } */
 };
 
index 51053b2d8db4a4fbbd202cccb60d4079e3ead1fd..8cf40801efbf056d13e98c04f78f0f09feb26adf 100644 (file)
@@ -1,7 +1,8 @@
 // PR c++/32056
 
-template <auto int T> struct A {}; // { dg-error "storage class specified|two or more" }
-template <extern int T> struct B {}; // { dg-error "storage class specified" }
-template <static int T> struct C {}; // { dg-error "storage class specified" }
-template <register int T> struct D {}; // { dg-error "storage class specified" }
-template <mutable int T> struct E {}; // { dg-error "storage class specified" }
+template <auto int T> struct A {}; // { dg-error "11:storage class specified" "" { target c++98_only } }
+// { dg-error "two or more" "" { target c++11 } .-1 }
+template <extern int T> struct B {}; // { dg-error "11:storage class specified" }
+template <static int T> struct C {}; // { dg-error "11:storage class specified" }
+template <register int T> struct D {}; // { dg-error "11:storage class specified" }
+template <mutable int T> struct E {}; // { dg-error "11:storage class specified" }
index 2676d8fec1df467097d3fe1ab3c0709c49909e34..f776f331c669f797e6873907bf10762edf2ff815 100644 (file)
@@ -1,7 +1,8 @@
 // PR c++/27572
 // { dg-do compile }
 
-template<typedef> void foo();  // { dg-error "no type|typedef declaration|template" }
+template<typedef> void foo();  // { dg-error "10:typedef declaration" }
+// { dg-error "no type|template" "" { target *-*-* } .-1 }
 
 void bar()
 {
index 04b8eac3bcc283c7f08d5e2821db7b08a5f2ef2c..eaa6143355694228e957bee616586eabe14f30d7 100644 (file)
@@ -1,7 +1,10 @@
 // PR c++/27572
 // { dg-do compile }
 
-template<typedef,int>        struct A1; // { dg-error "no type|typedef declaration|default argument" }
-template<typedef x,int>      struct A2; // { dg-error "type|typedef declaration|default argument" }
-template<typedef x[],int>    struct A3; // { dg-error "no type|typedef declaration|expected" }
-template<typedef int x, int> struct A4; // { dg-error "typedef declaration|default argument" }
+template<typedef,int>        struct A1; // { dg-error "10:typedef declaration" }
+// { dg-error "no type|default argument" "" { target *-*-* } .-1 }
+template<typedef x,int>      struct A2; // { dg-error "10:typedef declaration" }
+// { dg-error "type|default argument" "" { target *-*-* } .-1 }
+template<typedef x[],int>    struct A3; // { dg-error "typedef declaration|no type|expected" }
+template<typedef int x, int> struct A4; // { dg-error "10:typedef declaration" }
+// { dg-error "default argument" "" { target *-*-* } .-1 }
index f76763f3431677d4236f2e8bce84c93e415394ba..c247a9787a26d353933034c68550459751845372 100644 (file)
@@ -8,19 +8,19 @@ typedef __thread int g4;      /* { dg-error "multiple storage classes" } */
 
 void foo()
 {
-  __thread int l1;             /* { dg-error "implicitly auto and declared '__thread'" } */
+  __thread int l1;             /* { dg-error "3:function-scope .l1. implicitly auto and declared '__thread'" } */
   auto __thread int l2;                /* { dg-error "multiple storage classes|data types" } */
   __thread extern int l3;      /* { dg-error "'__thread' before 'extern'" } */
   register __thread int l4;    /* { dg-error "multiple storage classes" } */
 }                              /* { dg-error "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } .-1 } */
 
-__thread void f1 ();           /* { dg-error "invalid for function" } */
-extern __thread void f2 ();    /* { dg-error "invalid for function" } */
-static __thread void f3 ();    /* { dg-error "invalid for function" } */
-__thread void f4 () { }                /* { dg-error "invalid for function" } */
+__thread void f1 ();           /* { dg-error "1:storage class .__thread. invalid for function" } */
+extern __thread void f2 ();    /* { dg-error "8:storage class .__thread. invalid for function" } */
+static __thread void f3 ();    /* { dg-error "8:storage class .__thread. invalid for function" } */
+__thread void f4 () { }                /* { dg-error "1:storage class .__thread. invalid for function" } */
 
-void bar(__thread int p1);     /* { dg-error "(invalid in parameter)|(specified for parameter)" } */
+void bar(__thread int p1);     /* { dg-error "10:storage class specified for parameter" } */
 
 struct A {
-  __thread int i;              /* { dg-error "storage class specified" } */
+  __thread int i;              /* { dg-error "3:storage class specified" } */
 };
diff --git a/gcc/testsuite/g++.dg/tls/locations1.C b/gcc/testsuite/g++.dg/tls/locations1.C
new file mode 100644 (file)
index 0000000..8ca3c6e
--- /dev/null
@@ -0,0 +1,4 @@
+/* { dg-require-effective-target tls } */
+
+template <__thread int T> struct F {}; // { dg-error "11:storage class specified" }
+template <static __thread int T> struct G {}; // { dg-error "11:storage class specified" }
index 1683de2b47f77d484704157cf4616ed7428d6bef..246f5a03aa557642a823ab46598dce2033533744 100644 (file)
@@ -9,13 +9,14 @@ class A {
        int     h;
        A() { i=10; j=20; }
        virtual void f1() { printf("i=%d j=%d\n",i,j); }
-       friend virtual void f2() { printf("i=%d j=%d\n",i,j); }// { dg-error "" }  virtual.*
+       friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "2:virtual functions cannot be friends" }
 };
 
 class B : public A {
     public:
        virtual void f1() { printf("i=%d j=%d\n",i,j); }// { dg-error "" }  member.*// ERROR -  member.*
-       friend virtual void f2() { printf("i=%d j=%d\n",i,j); }// { dg-error "" }  virtual.*// ERROR -  member.*// ERROR -  member.*
+       friend virtual void f2() { printf("i=%d j=%d\n",i,j); }  // { dg-error "2:virtual functions cannot be friends" }
+// { dg-error "private" "" { target *-*-* } .-1 }
 };
 
 int