/cp
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 2 Aug 2014 19:41:32 +0000 (19:41 +0000)
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 2 Aug 2014 19:41:32 +0000 (19:41 +0000)
2014-08-02  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/15339
* decl.c (check_redeclaration_no_default_args): New.
(duplicate_decls): Use it, handle default arguments
in redeclarations of function templates.

/testsuite
2014-08-02  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/15339
* g++.dg/other/default9.C: New.
* g++.dg/other/default10.C: Likewise.
* g++.dg/other/default3.C: Remove xfail.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213519 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/default10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/default3.C
gcc/testsuite/g++.dg/other/default9.C [new file with mode: 0644]

index 193a9c2..9fdd4c7 100644 (file)
@@ -1,3 +1,10 @@
+2014-08-02  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/15339
+       * decl.c (check_redeclaration_no_default_args): New.
+       (duplicate_decls): Use it, handle default arguments
+       in redeclarations of function templates.
+
 2014-08-02  Trevor Saunders  <tsaunders@mozilla.com>
 
        * optimize.c, semantics.c: Use hash_map instead of pointer_map.
index 88152f0..d4dde61 100644 (file)
@@ -1236,6 +1236,27 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl)
   return true;
 }
 
+/* DECL is a redeclaration of a function or function template.  If
+   it does have default arguments issue a diagnostic.  Note: this
+   function is used to enforce the requirements in C++11 8.3.6 about
+   no default arguments in redeclarations.  */
+
+static void
+check_redeclaration_no_default_args (tree decl)
+{
+  gcc_assert (DECL_DECLARES_FUNCTION_P (decl));
+
+  for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl);
+       t && t != void_list_node; t = TREE_CHAIN (t))
+    if (TREE_PURPOSE (t))
+      {
+       permerror (input_location,
+                  "redeclaration of %q#D may not have default "
+                  "arguments", decl);
+       return;
+      }
+}
+
 #define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn)                  \
                          && lookup_attribute ("gnu_inline",            \
                                               DECL_ATTRIBUTES (fn)))
@@ -1706,28 +1727,23 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        ;
       else if (TREE_CODE (olddecl) == FUNCTION_DECL)
        {
-         tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
-         tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
-         int i = 1;
-
-         if (DECL_FUNCTION_MEMBER_P (newdecl)
-             && CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (newdecl)))
-           {
-             /* C++11 8.3.6/6.
-                Default arguments for a member function of a class template
-                shall be specified on the initial declaration of the member
-                function within the class template.  */
-             for (; t2 && t2 != void_list_node; t2 = TREE_CHAIN (t2))
-               if (TREE_PURPOSE (t2))
-                 {
-                   permerror (input_location,
-                              "redeclaration of %q#D may not have default "
-                              "arguments", newdecl);
-                   break;
-                 }
-           }
+         /* Note: free functions, as TEMPLATE_DECLs, are handled below.  */
+         if (DECL_FUNCTION_MEMBER_P (olddecl)
+             && (/* grokfndecl passes member function templates too
+                    as FUNCTION_DECLs.  */
+                 DECL_TEMPLATE_INFO (olddecl)
+                 /* C++11 8.3.6/6.
+                    Default arguments for a member function of a class
+                    template shall be specified on the initial declaration
+                    of the member function within the class template.  */
+                 || CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (olddecl))))
+           check_redeclaration_no_default_args (newdecl);
          else
            {
+             tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
+             tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
+             int i = 1;
+
              for (; t1 && t1 != void_list_node;
                   t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
                if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
@@ -1864,6 +1880,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 
       if (DECL_FUNCTION_TEMPLATE_P (newdecl))
        {
+         /* Per C++11 8.3.6/4, default arguments cannot be added in later
+            declarations of a function template.  */
+         check_redeclaration_no_default_args (newdecl);
+
+         check_default_args (newdecl);
+
          if (GNU_INLINE_P (old_result) != GNU_INLINE_P (new_result)
              && DECL_INITIAL (new_result))
            {
index aab6097..68c4cf6 100644 (file)
@@ -1,4 +1,11 @@
-2014-08-01  Jan Hubicka  <hubicka@ucw.cz>
+2014-08-02  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/15339
+       * g++.dg/other/default9.C: New.
+       * g++.dg/other/default10.C: Likewise.
+       * g++.dg/other/default3.C: Remove xfail.
+
+2014-08-02  Jan Hubicka  <hubicka@ucw.cz>
 
        * g++.dg/warn/Wsuggest-final.C: New testcase.
        * g++.dg/ipa/devirt-34.C: Fix.
diff --git a/gcc/testsuite/g++.dg/other/default10.C b/gcc/testsuite/g++.dg/other/default10.C
new file mode 100644 (file)
index 0000000..1c9731e
--- /dev/null
@@ -0,0 +1,4 @@
+// PR c++/15339
+
+template<typename> void g3(int, int);
+template<typename> void g3(int = 0, int) { }  // { dg-error "may not have default arguments|default argument missing" }
index 42c1fe4..025d2c1 100644 (file)
@@ -25,7 +25,7 @@ template<typename> void g3(int, int);
 template<typename> void g3(int = 0, int);    // { dg-error "default" }
 
 template<typename> void g4(int, int);
-template<typename> void g4(int = 0, int) {}  // { dg-error "default" "" { xfail *-*-* } }
+template<typename> void g4(int = 0, int) {}  // { dg-error "default" }
 
 template<typename> void g5();
 template<typename> void g5(int = 0, int);    // { dg-error "default" }
diff --git a/gcc/testsuite/g++.dg/other/default9.C b/gcc/testsuite/g++.dg/other/default9.C
new file mode 100644 (file)
index 0000000..62f0a79
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/15339
+
+template<typename> void fun(int); 
+template<typename> void fun(int = 0);  // { dg-error "default arguments" }
+
+class A
+{
+  template<typename> void fun(int);
+};
+
+template<typename> void A::fun(int = 0) { } // { dg-error "default arguments" }
+
+class B
+{
+  void fun(int);
+};
+
+void B::fun(int = 0) { }