aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaolo Carlini <paolo@gcc.gnu.org>2014-08-02 19:41:32 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2014-08-02 19:41:32 +0000
commite83a4a2e4040d52b9c0ef052b8f49b5afbed60ac (patch)
tree6de5ef6aa4224298ce3181785830dadf37745af8 /gcc
parent91bc34a94d157c64f82477e8cd44d55494e7b1b7 (diff)
downloadgcc-e83a4a2e4040d52b9c0ef052b8f49b5afbed60ac.zip
gcc-e83a4a2e4040d52b9c0ef052b8f49b5afbed60ac.tar.gz
gcc-e83a4a2e4040d52b9c0ef052b8f49b5afbed60ac.tar.bz2
re PR c++/15339 ([DR217] Adding default arguments to function templates in redeclarations should be forbidden)
/cp 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. From-SVN: r213519
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c62
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/g++.dg/other/default10.C4
-rw-r--r--gcc/testsuite/g++.dg/other/default3.C2
-rw-r--r--gcc/testsuite/g++.dg/other/default9.C18
6 files changed, 80 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 193a9c2..9fdd4c7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 88152f0..d4dde61 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aab6097..68c4cf6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..1c9731e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/default10.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/other/default3.C b/gcc/testsuite/g++.dg/other/default3.C
index 42c1fe4..025d2c1 100644
--- a/gcc/testsuite/g++.dg/other/default3.C
+++ b/gcc/testsuite/g++.dg/other/default3.C
@@ -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
index 0000000..62f0a79
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/default9.C
@@ -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) { }