Commit 6498dea6 by Paolo Carlini Committed by Paolo Carlini

re PR c++/59480 (Missing error diagnostic: friend declaration specifying a…

re PR c++/59480 (Missing error diagnostic: friend declaration specifying a default argument must be a definition)

/cp
2018-07-18  Paolo Carlini  <paolo.carlini@oracle.com>

	* class.c (note_name_declared_in_class): Prefer permerror + inform
	to a pair of permerrors; use DECL_SOURCE_LOCATION.

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

	* g++.dg/ext/uow-3.C: Adjust.
	* g++.dg/ext/uow-4.C: Likewise.
	* g++.dg/lookup/name-clash11.C: Likewise.
	* g++.dg/lookup/name-clash7.C: Likewise.
	* g++.dg/lookup/redecl1.C: Likewise.
	* g++.dg/warn/changes-meaning.C: Likewise.
	* g++.old-deja/g++.jason/scoping8.C: Likewise.
	* g++.old-deja/g++.law/nest1.C: Likewise.

/cp
2019-07-18  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/59480, DR 136
	* decl.c (check_no_redeclaration_friend_default_args): New.
	(duplicate_decls): Use the latter; also check that a friend
	declaration specifying default arguments is a definition.

/testsuite
2019-07-18  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/59480, DR 136
	* g++.dg/other/friend8.C: New.
	* g++.dg/other/friend9.C: Likewise.
	* g++.dg/other/friend10.C: Likewise.
	* g++.dg/other/friend11.C: Likewise.
	* g++.dg/other/friend12.C: Likewise.
	* g++.dg/parse/defarg4.C: Compile with -fpermissive -w.
	* g++.dg/parse/defarg8.C: Likewise.

From-SVN: r262851
parent 0559979c
2019-07-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/59480, DR 136
* decl.c (check_no_redeclaration_friend_default_args): New.
(duplicate_decls): Use the latter; also check that a friend
declaration specifying default arguments is a definition.
2018-07-18 Paolo Carlini <paolo.carlini@oracle.com>
* class.c (note_name_declared_in_class): Prefer permerror + inform
to a pair of permerrors; use DECL_SOURCE_LOCATION.
2018-07-18 Richard Biener <rguenther@suse.de>
PR debug/86523
......
......@@ -8285,10 +8285,12 @@ note_name_declared_in_class (tree name, tree decl)
A name N used in a class S shall refer to the same declaration
in its context and when re-evaluated in the completed scope of
S. */
permerror (input_location, "declaration of %q#D", decl);
permerror (location_of ((tree) n->value),
"changes meaning of %qD from %q#D",
OVL_NAME (decl), (tree) n->value);
if (permerror (DECL_SOURCE_LOCATION (decl),
"declaration of %q#D changes meaning of %qD",
decl, OVL_NAME (decl)))
inform (location_of ((tree) n->value),
"%qD declared here as %q#D",
OVL_NAME (decl), (tree) n->value);
}
}
......
......@@ -1280,6 +1280,39 @@ check_redeclaration_no_default_args (tree decl)
}
}
/* NEWDECL is a redeclaration of a function or function template OLDDECL.
If either the declaration or the redeclaration is a friend declaration
and specifies default arguments issue a diagnostic. Note: this is to
enforce C++17 11.3.6/4: "If a friend declaration specifies a default
argument expression, that declaration... shall be the only declaration
of the function or function template in the translation unit." */
static void
check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl)
{
bool olddecl_friend_p = DECL_FRIEND_P (STRIP_TEMPLATE (olddecl));
bool newdecl_friend_p = DECL_FRIEND_P (STRIP_TEMPLATE (newdecl));
if (!olddecl_friend_p && !newdecl_friend_p)
return;
tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
for (; t1 && t1 != void_list_node;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
if ((olddecl_friend_p && TREE_PURPOSE (t1))
|| (newdecl_friend_p && TREE_PURPOSE (t2)))
{
if (permerror (DECL_SOURCE_LOCATION (newdecl),
"friend declaration of %q#D specifies default "
"arguments and isn't the only declaration", newdecl))
inform (DECL_SOURCE_LOCATION (olddecl),
"previous declaration of %q#D", olddecl);
return;
}
}
/* Merge tree bits that correspond to attributes noreturn, nothrow,
const, malloc, and pure from NEWDECL with those of OLDDECL. */
......@@ -1876,6 +1909,12 @@ next_arg:;
olddecl);
}
}
/* C++17 11.3.6/4: "If a friend declaration specifies a default
argument expression, that declaration... shall be the only
declaration of the function or function template in the
translation unit." */
check_no_redeclaration_friend_default_args (olddecl, newdecl);
}
}
}
......@@ -2008,11 +2047,18 @@ next_arg:;
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. */
if (DECL_SOURCE_LOCATION (newdecl)
!= DECL_SOURCE_LOCATION (olddecl))
check_redeclaration_no_default_args (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);
/* C++17 11.3.6/4: "If a friend declaration specifies a default
argument expression, that declaration... shall be the only
declaration of the function or function template in the
translation unit." */
check_no_redeclaration_friend_default_args (olddecl, newdecl);
}
check_default_args (newdecl);
......@@ -8763,6 +8809,21 @@ grokfndecl (tree ctype,
}
}
/* C++17 11.3.6/4: "If a friend declaration specifies a default argument
expression, that declaration shall be a definition..." */
if (friendp && !funcdef_flag)
{
for (tree t = FUNCTION_FIRST_USER_PARMTYPE (decl);
t && t != void_list_node; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
permerror (DECL_SOURCE_LOCATION (decl),
"friend declaration of %qD specifies default "
"arguments and isn't a definition", decl);
break;
}
}
/* If this decl has namespace scope, set that up. */
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
......
2019-07-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/59480, DR 136
* g++.dg/other/friend8.C: New.
* g++.dg/other/friend9.C: Likewise.
* g++.dg/other/friend10.C: Likewise.
* g++.dg/other/friend11.C: Likewise.
* g++.dg/other/friend12.C: Likewise.
* g++.dg/parse/defarg4.C: Compile with -fpermissive -w.
* g++.dg/parse/defarg8.C: Likewise.
2018-07-18 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/ext/uow-3.C: Adjust.
* g++.dg/ext/uow-4.C: Likewise.
* g++.dg/lookup/name-clash11.C: Likewise.
* g++.dg/lookup/name-clash7.C: Likewise.
* g++.dg/lookup/redecl1.C: Likewise.
* g++.dg/warn/changes-meaning.C: Likewise.
* g++.old-deja/g++.jason/scoping8.C: Likewise.
* g++.old-deja/g++.law/nest1.C: Likewise.
2018-07-18 Richard Biener <rguenther@suse.de>
PR debug/86523
......
/* { dg-do compile } */
/* { dg-options "-Wall" } */
typedef int UOW; /* { dg-error "" } */
typedef int UOW; /* { dg-message "declared here" } */
struct ABC {
UOW UOW; /* { dg-error "" } */
UOW UOW; /* { dg-error "changes meaning" } */
};
......@@ -3,9 +3,9 @@
extern "C" {
typedef int UOW; /* { dg-error "" } */
typedef int UOW; /* { dg-message "declared here" } */
struct ABC {
UOW UOW; /* { dg-error "" } */
UOW UOW; /* { dg-error "changes meaning" } */
};
}
......
......@@ -13,11 +13,11 @@
void test_bitset ()
{
int x; // { dg-warning "changes meaning" }
int x; // { dg-message "declared here" }
{
struct S {
int x: sizeof x; // { dg-warning "declaration" }
int x: sizeof x; // { dg-warning "changes meaning" }
};
}
}
......@@ -25,11 +25,11 @@ void test_bitset ()
void test_enum ()
{
// Also exercise (not covered by c++/69023):
int y; // { dg-warning "changes meaning" }
int y; // { dg-message "declared here" }
{
struct S {
enum E {
y = sizeof y // { dg-warning "declaration" }
y = sizeof y // { dg-warning "9:declaration of .y. changes meaning" }
};
// Verify the enumerator has the correct value.
......@@ -40,7 +40,7 @@ void test_enum ()
void test_alignas ()
{
enum { A = 16 }; // { dg-warning "changes meaning" }
enum { A = 16 }; // { dg-message "declared here" }
{
struct S {
#if __cplusplus >= 201103L
......@@ -48,7 +48,7 @@ void test_alignas ()
#else
__attribute__ ((aligned (A)))
#endif
int A; // { dg-warning "declaration" }
int A; // { dg-warning "changes meaning" }
// Verify the member has the correct alignment.
void test () { ASSERT (__alignof__ (this->A) == 16); }
......@@ -58,10 +58,10 @@ void test_alignas ()
void test_array ()
{
enum { A = 16 }; // { dg-warning "changes meaning" }
enum { A = 16 }; // { dg-message "declared here" }
{
struct S {
int A [A]; // { dg-warning "declaration" }
int A [A]; // { dg-warning "changes meaning" }
// Verify the member has the correct alignment.
void test () { ASSERT (sizeof (this->A) == 16 * sizeof (int)); }
......@@ -71,10 +71,10 @@ void test_array ()
void test_vector ()
{
enum { A = 16 }; // { dg-warning "changes meaning" }
enum { A = 16 }; // { dg-message "declared here" }
{
struct S {
int A __attribute__ ((vector_size (A))); // { dg-warning "declaration" }
int A __attribute__ ((vector_size (A))); // { dg-warning "changes meaning" }
// Verify the member has the correct size.
void test () { ASSERT (sizeof (this->A) == 16); }
......
// PR c++/28513
class foo { // { dg-error "changes meaning" }
class foo { // { dg-message "declared here" }
public:
typedef int bar;
};
class baz {
public:
foo::bar foo; // { dg-error "declaration" }
foo::bar foo; // { dg-error "changes meaning" }
};
// PR c++/14668
class A {}; // { dg-error "" }
class A {}; // { dg-message "declared here" }
class B {
static A *A; // { dg-error "" }
static A *A; // { dg-error "changes meaning" }
};
A *B::A = 0;
// PR c++/59480
class test {
friend int foo(bool = true) { return 1; } // { dg-message "14:previous" }
template<typename> friend int bar(bool = true) { return 1; } // { dg-message "33:previous" }
};
int foo(bool); // { dg-error "5:friend declaration" }
template<typename> int bar(bool); // { dg-error "24:friend declaration" }
// PR c++/59480
class test {
friend int foo(bool = true) { return 1; } // { dg-message "14:previous" }
friend int foo(bool); // { dg-error "14:friend declaration" }
template<typename> friend int bar(bool = true) { return 1; } // { dg-message "33:previous" }
template<typename> friend int bar(bool); // { dg-error "33:friend declaration" }
};
// PR c++/59480
template<typename>
class test {
friend int foo(bool = true) { return 1; } // { dg-message "14:previous" }
friend int foo(bool); // { dg-error "14:friend declaration" }
template<typename> friend int bar(bool = true) { return 1; } // { dg-message "33:previous" }
template<typename> friend int bar(bool); // { dg-error "33:friend declaration" }
};
template class test<bool>;
// PR c++/59480
class test {
friend int foo(bool = true); // { dg-error "14:friend declaration" }
template<typename> friend int bar(bool = true); // { dg-error "33:friend declaration" }
};
// PR c++/59480
template<typename>
class test {
friend int foo(bool = true); // { dg-error "14:friend declaration" }
template<typename> friend int bar(bool = true); // { dg-error "33:friend declaration" }
};
template class test<bool>;
// { dg-do compile }
// { dg-options "-fpermissive -w" }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 3 Jul 2003 <nathan@codesourcery.com>
......
// { dg-options "-fpermissive -w" }
struct A {
static void g(int);
};
......
/* { dg-do compile } */
/* { dg-options "-fpermissive" } */
template <class _Tp> class auto_ptr {}; /* { dg-warning "changes meaning" } */
template <class _Tp> class auto_ptr {}; /* { dg-message "declared here" } */
template <class _Tp>
class counted_ptr
{
public:
auto_ptr<_Tp> auto_ptr(); /* { dg-warning "" } */
auto_ptr<_Tp> auto_ptr(); /* { dg-warning "17:declaration of .auto_ptr\\<_Tp\\>" } */
};
// { dg-do assemble }
// Bug: g++ allows two different meanings of a name in the same scope.
typedef int foo; // { dg-error "" }
typedef int foo; // { dg-message "declared here" }
struct A {
A (foo);
int foo (); // { dg-error "" } foo already used in scope
int foo (); // { dg-error "changes meaning" }
};
......@@ -6,10 +6,10 @@
// Subject: Local type names bug in g++ 2.3.3
// Message-ID: <1992Dec30.203807.17504@murdoch.acc.Virginia.EDU>
typedef char* T; // { dg-error "" } previous declaration
typedef char* T; // { dg-message "declared here" }
struct Y {
T a;
typedef long T; // error. See ARM p189-191 for details// { dg-error "" }
typedef long T; // { dg-error "changes meaning" }
T b;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment