decl.c (grokdeclarator): Use id_loc in five additional places in the last part of...
authorPaolo Carlini <paolo.carlini@oracle.com>
Thu, 13 Jun 2019 08:45:46 +0000 (08:45 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Thu, 13 Jun 2019 08:45:46 +0000 (08:45 +0000)
/cp
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

* decl.c (grokdeclarator): Use id_loc in five additional places
in the last part of the function.

/testsuite
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

* g++.dg/diagnostic/variably-modified-type-1.C: New.
* g++.dg/cpp0x/alias-decl-1.C: Test the location too.
* g++.dg/other/pr84792-1.C: Likewise.
* g++.dg/other/pr84792-2.C: Likewise.
* g++.dg/parse/error24.C: Likewise.
* g++.dg/parse/error32.C: Likewise.
* g++.dg/parse/error33.C: Likewise.
* g++.dg/parse/saved1.C: Likewise.
* g++.dg/template/operator6.C: Likewise.
* g++.dg/template/pr61745.C: Likewise.
* g++.dg/template/typedef41.C: Likewise.
* g++.old-deja/g++.jason/crash10.C: Likewise.

/cp
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

* decl.c (grokdeclarator): Move further up the declaration of
id_loc, use it immediately, update its value after the loop
over declarator, use it again in the final part of function;
improve locations of error messages about multiple data types
and conflicting specifiers.

/testsuite
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

* g++.dg/diagnostic/conflicting-specifiers-1.C: New.
* g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise.
* g++.dg/parse/error10.C: Adjust location.
* g++.dg/parse/pragma2.C: Likewise.

From-SVN: r272236

19 files changed:
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/pr84792-1.C
gcc/testsuite/g++.dg/other/pr84792-2.C
gcc/testsuite/g++.dg/parse/error10.C
gcc/testsuite/g++.dg/parse/error24.C
gcc/testsuite/g++.dg/parse/error32.C
gcc/testsuite/g++.dg/parse/error33.C
gcc/testsuite/g++.dg/parse/pragma2.C
gcc/testsuite/g++.dg/parse/saved1.C
gcc/testsuite/g++.dg/template/operator6.C
gcc/testsuite/g++.dg/template/pr61745.C
gcc/testsuite/g++.dg/template/typedef41.C
gcc/testsuite/g++.old-deja/g++.jason/crash10.C

index da5dec37b19b0607b353d5a20b746be50da2e50f..c6823b57aa7b0cab3e6b6e55f942d94c4c36c99a 100644 (file)
@@ -1,3 +1,16 @@
+2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * decl.c (grokdeclarator): Use id_loc in five additional places
+       in the last part of the function.
+
+2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * decl.c (grokdeclarator): Move further up the declaration of
+       id_loc, use it immediately, update its value after the loop
+       over declarator, use it again in the final part of function;
+       improve locations of error messages about multiple data types
+       and conflicting specifiers.
+
 2019-06-13  Richard Biener  <rguenther@suse.de>
 
        PR c++/90801
index ca248111eb55628ddecce6afb1856c3f207db328..0a3ef452536fa836c3b37e227304ebccd878ee41 100644 (file)
@@ -10456,6 +10456,10 @@ grokdeclarator (const cp_declarator *declarator,
   if (typespec_loc == UNKNOWN_LOCATION)
     typespec_loc = input_location;
 
+  location_t id_loc = declarator ? declarator->id_loc : input_location;
+  if (id_loc == UNKNOWN_LOCATION)
+    id_loc = input_location;
+
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   for (id_declarator = declarator;
@@ -10620,8 +10624,7 @@ grokdeclarator (const cp_declarator *declarator,
      D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
     {
-      error_at (declarator->id_loc,
-               "function definition does not declare parameters");
+      error_at (id_loc, "function definition does not declare parameters");
       return error_mark_node;
     }
 
@@ -10629,8 +10632,7 @@ grokdeclarator (const cp_declarator *declarator,
       && innermost_code != cdk_function
       && ! (ctype && !declspecs->any_specifiers_p))
     {
-      error_at (declarator->id_loc,
-               "declaration of %qD as non-function", dname);
+      error_at (id_loc, "declaration of %qD as non-function", dname);
       return error_mark_node;
     }
 
@@ -10639,8 +10641,7 @@ grokdeclarator (const cp_declarator *declarator,
       if (UDLIT_OPER_P (dname)
          && innermost_code != cdk_function)
        {
-         error_at (declarator->id_loc,
-                   "declaration of %qD as non-function", dname);
+         error_at (id_loc, "declaration of %qD as non-function", dname);
          return error_mark_node;
        }
 
@@ -10648,14 +10649,12 @@ grokdeclarator (const cp_declarator *declarator,
        {
          if (typedef_p)
            {
-             error_at (declarator->id_loc,
-                       "declaration of %qD as %<typedef%>", dname);
+             error_at (id_loc, "declaration of %qD as %<typedef%>", dname);
              return error_mark_node;
            }
          else if (decl_context == PARM || decl_context == CATCHPARM)
            {
-             error_at (declarator->id_loc,
-                       "declaration of %qD as parameter", dname);
+             error_at (id_loc, "declaration of %qD as parameter", dname);
              return error_mark_node;
            }
        }
@@ -10705,13 +10704,16 @@ grokdeclarator (const cp_declarator *declarator,
      issue an error message.  */
   if (declspecs->multiple_types_p)
     {
-      error ("two or more data types in declaration of %qs", name);
+      error_at (typespec_loc,
+               "two or more data types in declaration of %qs", name);
       return error_mark_node;
     }
 
   if (declspecs->conflicting_specifiers_p)
     {
-      error ("conflicting specifiers in declaration of %qs", name);
+      error_at (min_location (declspecs->locations[ds_typedef],
+                             declspecs->locations[ds_storage_class]),
+               "conflicting specifiers in declaration of %qs", name);
       return error_mark_node;
     }
 
@@ -11861,6 +11863,8 @@ grokdeclarator (const cp_declarator *declarator,
        }
     }
 
+  id_loc = declarator ? declarator->id_loc : input_location;
+
   /* A `constexpr' specifier used in an object declaration declares
      the object as `const'.  */
   if (constexpr_p && innermost_code != cdk_function)
@@ -11884,8 +11888,6 @@ grokdeclarator (const cp_declarator *declarator,
       unqualified_id = dname;
     }
 
-  location_t loc = declarator ? declarator->id_loc : input_location;
-
   /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly
      qualified with a class-name, turn it into a METHOD_TYPE, unless
      we know that the function is static.  We take advantage of this
@@ -11912,7 +11914,7 @@ grokdeclarator (const cp_declarator *declarator,
              friendp = 0;
            }
          else
-           permerror (loc, "extra qualification %<%T::%> on member %qs",
+           permerror (id_loc, "extra qualification %<%T::%> on member %qs",
                       ctype, name);
        }
       else if (/* If the qualifying type is already complete, then we
@@ -11941,7 +11943,7 @@ grokdeclarator (const cp_declarator *declarator,
          if (current_class_type
              && (!friendp || funcdef_flag || initialized))
            {
-             error_at (loc, funcdef_flag || initialized
+             error_at (id_loc, funcdef_flag || initialized
                        ? G_("cannot define member function %<%T::%s%> "
                             "within %qT")
                        : G_("cannot declare member function %<%T::%s%> "
@@ -11952,7 +11954,7 @@ grokdeclarator (const cp_declarator *declarator,
        }
       else if (typedef_p && current_class_type)
        {
-         error_at (loc, "cannot declare member %<%T::%s%> within %qT",
+         error_at (id_loc, "cannot declare member %<%T::%s%> within %qT",
                    ctype, name, current_class_type);
          return error_mark_node;
        }
@@ -12000,9 +12002,11 @@ grokdeclarator (const cp_declarator *declarator,
       && variably_modified_type_p (type, NULL_TREE))
     {
       if (decl_context == FIELD)
-       error ("data member may not have variably modified type %qT", type);
+       error_at (id_loc,
+                 "data member may not have variably modified type %qT", type);
       else
-       error ("parameter may not have variably modified type %qT", type);
+       error_at (id_loc,
+                 "parameter may not have variably modified type %qT", type);
       type = error_mark_node;
     }
 
@@ -12106,14 +12110,14 @@ grokdeclarator (const cp_declarator *declarator,
 
       if (id_declarator && declarator->u.id.qualifying_scope)
        {
-         error ("typedef name may not be a nested-name-specifier");
+         error_at (id_loc, "typedef name may not be a nested-name-specifier");
          type = error_mark_node;
        }
 
       if (decl_context == FIELD)
-       decl = build_lang_decl_loc (loc, TYPE_DECL, unqualified_id, type);
+       decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
       else
-       decl = build_decl (loc, TYPE_DECL, unqualified_id, type);
+       decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type);
 
       if (decl_context != FIELD)
        {
@@ -12130,7 +12134,7 @@ grokdeclarator (const cp_declarator *declarator,
        }
       else if (current_class_type
               && constructor_name_p (unqualified_id, current_class_type))
-       permerror (input_location, "ISO C++ forbids nested type %qD with same name "
+       permerror (id_loc, "ISO C++ forbids nested type %qD with same name "
                   "as enclosing class",
                   unqualified_id);
 
@@ -12288,7 +12292,7 @@ grokdeclarator (const cp_declarator *declarator,
       /* Only functions may be declared using an operator-function-id.  */
       if (dname && IDENTIFIER_ANY_OP_P (dname))
        {
-         error ("declaration of %qD as non-function", dname);
+         error_at (id_loc, "declaration of %qD as non-function", dname);
          return error_mark_node;
        }
 
@@ -12398,8 +12402,8 @@ grokdeclarator (const cp_declarator *declarator,
                if (in_system_header_at (input_location))
                  /* Do not warn on flexible array members in system
                     headers because glibc uses them.  */;
-               else if (name && declarator)
-                 pedwarn (declarator->id_loc, OPT_Wpedantic,
+               else if (name)
+                 pedwarn (id_loc, OPT_Wpedantic,
                           "ISO C++ forbids flexible array member %qs", name);
                else
                  pedwarn (input_location, OPT_Wpedantic,
@@ -12551,7 +12555,7 @@ grokdeclarator (const cp_declarator *declarator,
                               initialized == SD_DELETED, sfk,
                               funcdef_flag, late_return_type_p,
                               template_count, in_namespace,
-                              attrlist, declarator->id_loc);
+                              attrlist, id_loc);
             decl = set_virt_specifiers (decl, virt_specifiers);
            if (decl == NULL_TREE)
              return error_mark_node;
@@ -12584,8 +12588,7 @@ grokdeclarator (const cp_declarator *declarator,
              {
                if (unqualified_id)
                  {
-                   error_at (declarator->id_loc,
-                             "field %qD has incomplete type %qT",
+                   error_at (id_loc, "field %qD has incomplete type %qT",
                              unqualified_id, type);
                    cxx_incomplete_type_inform (strip_array_types (type));
                  }
@@ -12600,8 +12603,8 @@ grokdeclarator (const cp_declarator *declarator,
          {
            if (friendp)
              {
-               if (unqualified_id && declarator)
-                 error_at (declarator->id_loc,
+               if (unqualified_id)
+                 error_at (id_loc,
                            "%qE is neither function nor member function; "
                            "cannot be declared friend", unqualified_id);
                else
@@ -12645,7 +12648,7 @@ grokdeclarator (const cp_declarator *declarator,
              {
                /* C++ allows static class members.  All other work
                   for this is done by grokfield.  */
-               decl = build_lang_decl_loc (loc, VAR_DECL,
+               decl = build_lang_decl_loc (id_loc, VAR_DECL,
                                            unqualified_id, type);
                set_linkage_for_static_data_member (decl);
                if (concept_p)
@@ -12693,7 +12696,7 @@ grokdeclarator (const cp_declarator *declarator,
                              unqualified_id);
                    constexpr_p = false;
                  }
-               decl = build_decl (loc, FIELD_DECL, unqualified_id, type);
+               decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
                DECL_NONADDRESSABLE_P (decl) = bitfield;
                if (bitfield && !unqualified_id)
                  {
@@ -12811,7 +12814,7 @@ grokdeclarator (const cp_declarator *declarator,
                            funcdef_flag,
                           late_return_type_p,
                           template_count, in_namespace, attrlist,
-                          declarator->id_loc);
+                          id_loc);
        if (decl == NULL_TREE)
          return error_mark_node;
 
@@ -12858,7 +12861,7 @@ grokdeclarator (const cp_declarator *declarator,
                            concept_p,
                            template_count,
                            ctype ? ctype : in_namespace,
-                           loc);
+                           id_loc);
        if (decl == NULL_TREE)
          return error_mark_node;
 
@@ -12904,7 +12907,7 @@ grokdeclarator (const cp_declarator *declarator,
        if (innermost_code == cdk_decomp)
          {
            gcc_assert (declarator && declarator->kind == cdk_decomp);
-           DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+           DECL_SOURCE_LOCATION (decl) = id_loc;
            DECL_ARTIFICIAL (decl) = 1;
            fit_decomposition_lang_decl (decl, NULL_TREE);
          }
index f82dc9e09edc8911b91039a6a8cf255faa8141a2..865408b76dd35bafd93af8dd3cc5da2a24076204 100644 (file)
@@ -1,3 +1,25 @@
+2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * g++.dg/diagnostic/variably-modified-type-1.C: New.
+       * g++.dg/cpp0x/alias-decl-1.C: Test the location too.
+       * g++.dg/other/pr84792-1.C: Likewise.
+       * g++.dg/other/pr84792-2.C: Likewise.
+       * g++.dg/parse/error24.C: Likewise.
+       * g++.dg/parse/error32.C: Likewise.
+       * g++.dg/parse/error33.C: Likewise.
+       * g++.dg/parse/saved1.C: Likewise.
+       * g++.dg/template/operator6.C: Likewise.
+       * g++.dg/template/pr61745.C: Likewise.
+       * g++.dg/template/typedef41.C: Likewise.
+       * g++.old-deja/g++.jason/crash10.C: Likewise.
+
+2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * g++.dg/diagnostic/conflicting-specifiers-1.C: New.
+       * g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise.
+       * g++.dg/parse/error10.C: Adjust location.
+       * g++.dg/parse/pragma2.C: Likewise.
+
 2019-06-13  Feng Xue  <fxue@os.amperecomputing.com>
 
        PR tree-optimization/89713
index c52ab46aa5e5c62d80d3ef2a4175ea6c6d2e3c42..43284d76978b15de709036085cc315ff978db240 100644 (file)
@@ -11,5 +11,6 @@ template <class U> using Ptr = U*;
 template<class U> struct Ptr<U*> {}; // { dg-error "specialization" }
 
 struct A {
-    using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }
+    using A = int;  // { dg-error "11:ISO C\\+\\+ forbids nested type .A." }
+// { dg-error "same name as" "" { target c++11 } .-1 }  
 };
diff --git a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C
new file mode 100644 (file)
index 0000000..1a8ac02
--- /dev/null
@@ -0,0 +1 @@
+static typedef int i __attribute__((unused));  // { dg-error "1:conflicting specifiers" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C b/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C
new file mode 100644 (file)
index 0000000..4323a36
--- /dev/null
@@ -0,0 +1 @@
+char int i __attribute__((unused));  // { dg-error "1:two or more data types" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C b/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C
new file mode 100644 (file)
index 0000000..4402d12
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "" }
+
+void foo ()
+{
+  int n;
+  typedef int X[n];
+  struct Z
+  {
+    X x __attribute__((unused)); // { dg-error "7:data member may not have variably modified type" }
+    void bar (X x __attribute__((unused))); // { dg-error "17:parameter may not have variably modified type" }
+  };
+}
index 23df8ae18ad5f43eaee4be3aead59e572a1745e7..9949efd0959b328aa21741afe919993ea67d769d 100644 (file)
@@ -3,4 +3,4 @@ struct A {};
 typedef struct
 {
   virtual void foo() {}
-} A::B;  // { dg-error "typedef" }
+} A::B;  // { dg-error "3:typedef" }
index a393d5771cefd089c84e4305937a82cdf6800298..082baae747f6ba3bc864486ab0103254d0fac09a 100644 (file)
@@ -3,4 +3,4 @@ struct A {};
 typedef struct
 {
   void foo() {}
-} A::B;  // { dg-error "typedef" }
+} A::B;  // { dg-error "3:typedef" }
index 46c9eff7bbcc0be43f6265ca4c9bea38641adb54..4750e5cbb5a3e22fc47034711ef475a976f1563a 100644 (file)
@@ -14,4 +14,4 @@ template <typename T> void foo()
   enum typename A<T>::E    e4;
 }
 
-// { dg-error "28:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 }
+// { dg-error "3:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 }
index c8ab6d9921aa19728d605803cd56f435f63b5982..190812e9f0a12ee9b8d8ecb938a4db8450e5c5d8 100644 (file)
@@ -2,7 +2,7 @@
 // PR c++/19395
 
 struct A {
-  typedef int ::X; // { dg-error "17:typedef name may not be a nested-name-specifier" }
+  typedef int ::X; // { dg-error "15:typedef name may not be a nested-name-specifier" }
 };
 
 
index da27afdda2b4a57dcba67dc007117db33fe66e51..1993c068b47045a0c4ad81f04889a0ed7aa6d909 100644 (file)
@@ -3,7 +3,7 @@
 
 struct A {};
 
-typedef void (A::T)(); /* { dg-error "typedef name may not be a nested-name-specifier" } */
+typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested-name-specifier" } */
 
 void foo()
 {
index e3a7166edda718c2fb059c064889e0f81b5e02fb..0d25386a879cabc883d38d280d47b0b0de284155 100644 (file)
@@ -6,7 +6,7 @@ struct A
   void foo();
 };
 
-typedef void (A::T)(); /* { dg-error "typedef name may not be a nested" } */
+typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested" } */
 
 void bar(T); /* { dg-message "note: declared here" } */
 
index c5616ff74f53e49d2141e8a71a7eda4a32fae2c2..c7d4f10751cdf35320dd673be5216876d70885e2 100644 (file)
@@ -4,5 +4,6 @@
 // does not.
 int f(int x,
 #pragma interface  // { dg-error "not allowed here" }
+// { dg-bogus "two or more" "" { xfail *-*-* } .-1 }      
       // The parser gets confused and issues an error on the next line.
-      int y); // { dg-bogus "" "" { xfail *-*-* } } 
+      int y);
index 0153fb2a1a606827f39085b7f048286b08b0819e..979a05676d2069911eb8c47c994ddf2fc4fb4ab8 100644 (file)
@@ -1,6 +1,7 @@
 // Test that the parser doesn't go into an infinite loop from ignoring the
 // PRE_PARSED_FUNCTION_DECL token.
 
-class C { static void* operator new(size_t); }; // { dg-error "" }
+class C { static void* operator new(size_t); }; // { dg-error "24:declaration of .operator new. as non-function" }
+// { dg-error "expected|ISO C\\+\\+ forbids" "" { target *-*-* } .-1 }
 void* C::operator new(size_t) { return 0; } // { dg-error "" }
 class D { D(int i): integer(i){}}; // { dg-error "" }
index 94a869bccd5fcb3d33d362df76b4e5872a1ead30..189dcc26e150e3d0563e5b67ee43e49a7584d84c 100644 (file)
@@ -1,4 +1,4 @@
 // PR c++/27315
 // { dg-do compile }
 
-template void operator+; // { dg-error "non-function" }
+template void operator+; // { dg-error "15:declaration of .operator\\+. as non-function" }
index da5973e38679a2152d55aaedb6d3b1235259f732..a44bfa8afe14fab02b3ef59e6bc0d668fa6340a6 100644 (file)
@@ -20,5 +20,6 @@ public:
   Zp  operator-() const { return Zp(p-val); }
   // In C++2A, we have an unqualified-id (operator-) followed by
   // '<', and name lookup found a function.
-  friend Zp<INT,P> operator- <>(const Zp<INT,P>& a, const Zp<INT,P>& b); // { dg-error "declaration|expected" "" { target c++17_down } }
+  friend Zp<INT,P> operator- <>(const Zp<INT,P>& a, const Zp<INT,P>& b); // { dg-error "20:declaration of .operator\\-. as non-function" "" { target c++17_down } }
+  // { dg-error "expected" "" { target c++17_down } .-1 }
 };
index dc25518bf06d1cf17e9a17a6e85b326e87ee5c77..e6619d7dccda216fe880e523f497cbeab8fa62d8 100644 (file)
@@ -2,7 +2,7 @@
 
 template<int> struct A
 {
-  typedef int ::X;             // { dg-error "" }
+  typedef int ::X;             // { dg-error "15:typedef name" }
 };
 
 A<0> a;
index cd9b7b0b2d2cb5533dbfda779e7322e5cb39b4c1..2d1f71db1923341f14ee29f3f6bfea603f6358e6 100644 (file)
@@ -5,4 +5,4 @@ struct A {
   enum foo { bar };
 };
 
-typedef A::foo A::foo;         // { dg-error "" } causes compiler segfault
+typedef A::foo A::foo;         // { dg-error "16:typedef name" } causes compiler segfault