[C++ PATCH] refactor duplicate_decls
authorNathan Sidwell <nathan@acm.org>
Fri, 2 Nov 2018 11:12:43 +0000 (11:12 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 2 Nov 2018 11:12:43 +0000 (11:12 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00085.html
gcc/cp/
* decl.c (duplicate_decls): Refactor checks.
gcc/testsuite/
* g++.dg/lookup/crash6.C: Adjust error
* g++.dg/parse/crash38.C: Likewise.

From-SVN: r265744

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/crash6.C
gcc/testsuite/g++.dg/parse/crash38.C

index b27ae1a..bb77e0b 100644 (file)
@@ -1,3 +1,7 @@
+2018-11-02  Nathan Sidwell  <nathan@acm.org>
+
+       * decl.c (duplicate_decls): Refactor checks.
+
 2018-11-01  Marek Polacek  <polacek@redhat.com>
 
        Implement P0846R0, ADL and function templates.
index f0033dd..cf93415 100644 (file)
@@ -1370,47 +1370,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       || TREE_TYPE (olddecl) == error_mark_node)
     return error_mark_node;
 
-  if (DECL_NAME (newdecl)
-      && DECL_NAME (olddecl)
-      && UDLIT_OPER_P (DECL_NAME (newdecl))
-      && UDLIT_OPER_P (DECL_NAME (olddecl)))
-    {
-      if (TREE_CODE (newdecl) == TEMPLATE_DECL
-         && TREE_CODE (olddecl) != TEMPLATE_DECL
-         && check_raw_literal_operator (olddecl))
-       error_at (newdecl_loc,
-                 "literal operator template %qD conflicts with"
-                 " raw literal operator %qD", newdecl, olddecl);
-      else if (TREE_CODE (newdecl) != TEMPLATE_DECL
-              && TREE_CODE (olddecl) == TEMPLATE_DECL
-              && check_raw_literal_operator (newdecl))
-       error_at (newdecl_loc,
-                 "raw literal operator %qD conflicts with"
-                 " literal operator template %qD", newdecl, olddecl);
-    }
-
-  /* True to merge attributes between the declarations, false to
-     set OLDDECL's attributes to those of NEWDECL (for template
-     explicit specializations that specify their own attributes
-     independent of those specified for the primary template).  */
-  const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL
-                          || !DECL_TEMPLATE_SPECIALIZATION (newdecl)
-                          || DECL_TEMPLATE_SPECIALIZATION (olddecl));
-
-  if (DECL_P (olddecl)
-      && TREE_CODE (newdecl) == FUNCTION_DECL
-      && TREE_CODE (olddecl) == FUNCTION_DECL
-      && merge_attr
-      && diagnose_mismatched_attributes (olddecl, newdecl))
-    {
-      if (DECL_INITIAL (olddecl))
-       inform (olddecl_loc,
-               "previous definition of %qD was here", olddecl);
-      else
-       inform (olddecl_loc,
-               "previous declaration of %qD was here", olddecl);
-    }
-
   /* Check for redeclaration and other discrepancies.  */
   if (TREE_CODE (olddecl) == FUNCTION_DECL
       && DECL_ARTIFICIAL (olddecl))
@@ -1634,38 +1593,45 @@ next_arg:;
       /* C++ Standard, 3.3, clause 4:
         "[Note: a namespace name or a class template name must be unique
         in its declarative region (7.3.2, clause 14). ]"  */
-      if (TREE_CODE (olddecl) != NAMESPACE_DECL
-         && TREE_CODE (newdecl) != NAMESPACE_DECL
-         && (TREE_CODE (olddecl) != TEMPLATE_DECL
-             || TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) != TYPE_DECL)
-         && (TREE_CODE (newdecl) != TEMPLATE_DECL
-             || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != TYPE_DECL))
-       {
-         if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
-              && TREE_CODE (newdecl) != TYPE_DECL)
-             || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
-                 && TREE_CODE (olddecl) != TYPE_DECL))
-           {
-             /* We do nothing special here, because C++ does such nasty
-                things with TYPE_DECLs.  Instead, just let the TYPE_DECL
-                get shadowed, and know that if we need to find a TYPE_DECL
-                for a given name, we can look in the IDENTIFIER_TYPE_VALUE
-                slot of the identifier.  */
-             return NULL_TREE;
-           }
-           
-           if ((TREE_CODE (newdecl) == FUNCTION_DECL
-                && DECL_FUNCTION_TEMPLATE_P (olddecl))
-               || (TREE_CODE (olddecl) == FUNCTION_DECL
-                   && DECL_FUNCTION_TEMPLATE_P (newdecl)))
-             return NULL_TREE;
+      if (TREE_CODE (olddecl) == NAMESPACE_DECL
+         || TREE_CODE (newdecl) == NAMESPACE_DECL)
+       /* Namespace conflicts with not namespace.  */;
+      else if (DECL_TYPE_TEMPLATE_P (olddecl)
+              || DECL_TYPE_TEMPLATE_P (newdecl))
+       /* Class template conflicts.  */;
+      else if ((TREE_CODE (newdecl) == FUNCTION_DECL
+               && DECL_FUNCTION_TEMPLATE_P (olddecl))
+              || (TREE_CODE (olddecl) == FUNCTION_DECL
+                  && DECL_FUNCTION_TEMPLATE_P (newdecl)))
+       {
+         /* One is a function and the other is a template
+            function.  */
+         if (!UDLIT_OPER_P (DECL_NAME (newdecl)))
+           return NULL_TREE;
+
+         /* There can only be one!  */
+         if (TREE_CODE (newdecl) == TEMPLATE_DECL
+             && check_raw_literal_operator (olddecl))
+           error_at (newdecl_loc,
+                     "literal operator %q#D conflicts with"
+                     " raw literal operator", newdecl);
+         else if (check_raw_literal_operator (newdecl))
+           error_at (newdecl_loc,
+                     "raw literal operator %q#D conflicts with"
+                     " literal operator template", newdecl);
+         else
+           return NULL_TREE;
+         
+         inform (olddecl_loc, "previous declaration %q#D", olddecl);
+         return error_mark_node;
        }
+      else if (DECL_IMPLICIT_TYPEDEF_P (olddecl)
+              || DECL_IMPLICIT_TYPEDEF_P (newdecl))
+       /* One is an implicit typedef, that's ok.  */
+       return NULL_TREE;
 
-      error ("%q#D redeclared as different kind of symbol", newdecl);
-      if (TREE_CODE (olddecl) == TREE_LIST)
-       olddecl = TREE_VALUE (olddecl);
-      inform (olddecl_loc,
-             "previous declaration %q#D", olddecl);
+      error ("%q#D redeclared as different kind of entity", newdecl);
+      inform (olddecl_loc, "previous declaration %q#D", olddecl);
 
       return error_mark_node;
     }
@@ -1700,8 +1666,8 @@ next_arg:;
                      return type.  */
                   && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
                                   TREE_TYPE (TREE_TYPE (olddecl)))
-                   // Template functions can also be disambiguated by
-                   // constraints.
+                   /* Template functions can also be disambiguated by
+                     constraints.  */
                    && equivalently_constrained (olddecl, newdecl))
            {
              error_at (newdecl_loc, "ambiguating new declaration %q#D",
@@ -1938,16 +1904,30 @@ next_arg:;
          || DECL_IMPLICIT_TYPEDEF_P (newdecl)))
     return NULL_TREE;
 
+  if (!validate_constexpr_redeclaration (olddecl, newdecl))
+    return error_mark_node;
+
+  /* We have committed to returning OLDDECL at this point.  */
+
   /* If new decl is `static' and an `extern' was seen previously,
      warn about it.  */
   warn_extern_redeclared_static (newdecl, olddecl);
 
-  if (!validate_constexpr_redeclaration (olddecl, newdecl))
-    return error_mark_node;
+  /* True to merge attributes between the declarations, false to
+     set OLDDECL's attributes to those of NEWDECL (for template
+     explicit specializations that specify their own attributes
+     independent of those specified for the primary template).  */
+  const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL
+                          || !DECL_TEMPLATE_SPECIALIZATION (newdecl)
+                          || DECL_TEMPLATE_SPECIALIZATION (olddecl));
 
-  /* We have committed to returning 1 at this point.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
+      if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl))
+       inform (olddecl_loc, DECL_INITIAL (olddecl)
+               ? G_("previous definition of %qD here")
+               : G_("previous declaration of %qD here"), olddecl);
+
       /* Now that functions must hold information normally held
         by field decls, there is extra work to do so that
         declaration information does not get destroyed during
@@ -2027,7 +2007,7 @@ next_arg:;
   else
     DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
 
-  if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
+  if (DECL_DECLARES_FUNCTION_P (olddecl))
     {
       olddecl_friend = DECL_FRIEND_P (olddecl);
       olddecl_hidden_friend = DECL_HIDDEN_FRIEND_P (olddecl);
index 0824f9a..74fa20c 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-02  Nathan Sidwell  <nathan@acm.org>
+
+       * g++.dg/lookup/crash6.C: Adjust error
+       * g++.dg/parse/crash38.C: Likewise.
+
 2018-11-02  Andreas Schwab  <schwab@linux-m68k.org>
 
        * gcc.c-torture/execute/20010904-2.c: Fix last change.
index b8481be..b824edd 100644 (file)
@@ -5,4 +5,4 @@
 // PR c++/18652: ICE redeclaring variable as template.
 
 int A;                 // { dg-message "previous declaration" }
-template<int> struct A; // { dg-error "different kind of symbol" }
+template<int> struct A; // { dg-error "different kind of" }
index 7a0c265..5747f9f 100644 (file)
@@ -2,10 +2,10 @@
 
 /* This would not ICE.  */
 namespace M { } /* { dg-message "previous declaration" } */
-struct M; /* { dg-error "redeclared as different kind of symbol" } */
+struct M; /* { dg-error "redeclared as different kind of" } */
 M *p; /* { dg-error "does not name a type" } */
 
 /* This would ICE when processing 'p'.  */
 namespace N { } /* { dg-message "previous declaration" } */
-struct N; /* { dg-error "redeclared as different kind of symbol" } */
-struct N* p; /* { dg-error "redeclared as different kind of symbol|invalid type" } */
+struct N; /* { dg-error "redeclared as different kind of" } */
+struct N* p; /* { dg-error "redeclared as different kind of" } */