Restrict DR 757 change to C++0x mode.

* decl2.c (mark_used): Check cxx_dialect.
	* decl.c (grokfndecl): Do check type linkage in C++98 mode.
	(grokvardecl): Likewise.
	* pt.c (check_instantiated_arg): Likewise.

From-SVN: r153816
This commit is contained in:
Jason Merrill 2009-11-02 11:14:26 -05:00 committed by Jason Merrill
parent d7c0c068dd
commit 1eee69dd71
19 changed files with 149 additions and 34 deletions

View File

@ -1,3 +1,11 @@
2009-11-02 Jason Merrill <jason@redhat.com>
Restrict DR 757 change to C++0x mode.
* decl2.c (mark_used): Check cxx_dialect.
* decl.c (grokfndecl): Do check type linkage in C++98 mode.
(grokvardecl): Likewise.
* pt.c (check_instantiated_arg): Likewise.
2009-11-02 Jakub Jelinek <jakub@redhat.com>
PR c++/41774

View File

@ -6768,6 +6768,36 @@ grokfndecl (tree ctype,
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
if (publicp && cxx_dialect == cxx98)
{
/* [basic.link]: A name with no linkage (notably, the name of a class
or enumeration declared in a local scope) shall not be used to
declare an entity with linkage.
DR 757 relaxes this restriction for C++0x. */
t = no_linkage_check (TREE_TYPE (decl),
/*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
{
if (DECL_EXTERN_C_P (decl))
/* Allow this; it's pretty common in C. */;
else
{
permerror (input_location, "non-local function %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
permerror (input_location, "%q+#D does not refer to the unqualified "
"type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
permerror (input_location, "non-local function %q#D uses local type %qT", decl, t);
}
}
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
@ -7007,15 +7037,48 @@ grokvardecl (tree type,
if (declspecs->specs[(int)ds_thread])
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
/* If the type of the decl has no linkage, make sure that we'll
notice that in mark_used. */
if (cxx_dialect > cxx98
&& decl_linkage (decl) != lk_none
&& DECL_LANG_SPECIFIC (decl) == NULL
&& !DECL_EXTERN_C_P (decl)
&& no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
retrofit_lang_decl (decl);
if (TREE_PUBLIC (decl))
{
/* If the type of the decl has no linkage, make sure that we'll
notice that in mark_used. */
if (DECL_LANG_SPECIFIC (decl) == NULL
&& TREE_PUBLIC (decl)
&& !DECL_EXTERN_C_P (decl)
&& no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
retrofit_lang_decl (decl);
/* [basic.link]: A name with no linkage (notably, the name of a class
or enumeration declared in a local scope) shall not be used to
declare an entity with linkage.
DR 757 relaxes this restriction for C++0x. */
tree t = (cxx_dialect > cxx98 ? NULL_TREE
: no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false));
if (t)
{
if (TYPE_ANONYMOUS_P (t))
{
if (DECL_EXTERN_C_P (decl))
/* Allow this; it's pretty common in C. */
;
else
{
/* DRs 132, 319 and 389 seem to indicate types with
no linkage can only be used to declare extern "C"
entities. Since it's not always an error in the
ISO C++ 90 Standard, we only issue a warning. */
warning (0, "non-local variable %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
warning (0, "%q+#D does not refer to the unqualified "
"type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
warning (0, "non-local variable %q#D uses local type %qT", decl, t);
}
}
else
DECL_INTERFACE_KNOWN (decl) = 1;

View File

@ -3990,7 +3990,8 @@ mark_used (tree decl)
o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
o the variable or function is not used (3.2 [basic.def.odr]) or is
defined in the same translation unit. */
if (decl_linkage (decl) != lk_none
if (cxx_dialect > cxx98
&& decl_linkage (decl) != lk_none
&& !DECL_EXTERN_C_P (decl)
&& !DECL_ARTIFICIAL (decl)
&& !decl_defined_p (decl)

View File

@ -12479,7 +12479,7 @@ tsubst_copy_and_build (tree t,
}
/* Verify that the instantiated ARGS are valid. For type arguments,
make sure that the type is not variably modified. For non-type arguments,
make sure that the type's linkage is ok. For non-type arguments,
make sure they are constants if they are integral or enumerations.
Emit an error under control of COMPLAIN, and return TRUE on error. */
@ -12500,7 +12500,33 @@ check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
}
else if (TYPE_P (t))
{
if (variably_modified_type_p (t, NULL_TREE))
/* [basic.link]: A name with no linkage (notably, the name
of a class or enumeration declared in a local scope)
shall not be used to declare an entity with linkage.
This implies that names with no linkage cannot be used as
template arguments
DR 757 relaxes this restriction for C++0x. */
tree nt = (cxx_dialect > cxx98 ? NULL_TREE
: no_linkage_check (t, /*relaxed_p=*/false));
if (nt)
{
/* DR 488 makes use of a type with no linkage cause
type deduction to fail. */
if (complain & tf_error)
{
if (TYPE_ANONYMOUS_P (nt))
error ("%qT is/uses anonymous type", t);
else
error ("template argument for %qD uses local type %qT",
tmpl, t);
}
return true;
}
/* In order to avoid all sorts of complications, we do not
allow variably-modified types as template arguments. */
else if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
error ("%qT is a variably modified type", t);

View File

@ -1,3 +1,21 @@
2009-11-02 Jason Merrill <jason@redhat.com>
* g++.dg/other/linkage2.C: Move to...
* g++.dg/cpp0x/linkage2.C: ..here.
* g++.dg/abi/mangle32.C: Add -std=c++0x.
* g++.dg/cpp0x/nolinkage1.C: Likewise.
* g++.dg/debug/dwarf2/anonname1.C: Likewise.
* g++.dg/ext/anon-struct4.C: Revert earlier change.
* g++.dg/lookup/anon2.C: Likewise.
* g++.dg/other/anon3.C: Likewise.
* g++.dg/template/arg2.C: Likewise.
* g++.dg/template/local4.C: Likewise.
* g++.old-deja/g++.law/operators32.C: Likewise.
* g++.old-deja/g++.other/linkage2.C: Likewise.
* g++.old-deja/g++.pt/enum6.C: Likewise.
* g++.old-deja/g++.other/anon9.C: Likewise.
* g++.old-deja/g++.other/linkage1.C: Likewise.
2009-11-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
PR tree-optimization/41857

View File

@ -2,6 +2,9 @@
// namespace-scope unnamed types have no linkage, so we only test that they
// are distinct.
// { dg-options -std=c++0x }
typedef struct { } *A;
typedef struct { } *B;

View File

@ -4,6 +4,8 @@
// o the variable or function is not used (3.2 [basic.def.odr]) or is
// defined in the same translation unit.
// { dg-options -std=c++0x }
template <typename T> struct B {
void g(T){}
void h(T); // { dg-error "never defined" }

View File

@ -3,6 +3,7 @@
// { dg-additional-sources "nolinkage1a.cc" }
// { dg-do link }
// { dg-options -std=c++0x }
#include "nolinkage1.h"

View File

@ -1,6 +1,6 @@
// PR debug/41828
// { dg-do compile }
// { dg-options "-gdwarf-2 -dA" }
// { dg-options "-gdwarf-2 -dA -std=c++0x" }
// { dg-final { scan-assembler-not "<anonymous" } }
// { dg-final { scan-assembler-not "\._\[0-9\]" } }
// { dg-final { scan-assembler-not "\$_\[0-9\]" } }

View File

@ -1,3 +1,4 @@
// PR c++/14401
struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
// { dg-warning "anonymous" "anon" { target *-*-* } 3 }

View File

@ -1,9 +1,9 @@
// { dg-do compile }
// { dg-options "" }
// Make sure we don't issue a diagnostic if a type with no linkage is used
// to declare a a variable that has linkage if that variable is defined.
// Make sure we issue a diagnostic if a type with no linkage is used
// to declare a a variable that has linkage.
struct { int i; } a;
struct { int i; } a; // { dg-warning "anonymous type" }
void foo() { a.i; }

View File

@ -4,4 +4,4 @@
// { dg-do compile }
enum { a = 3 } x;
enum { a = 3 } x; // { dg-warning "anonymous type" }

View File

@ -10,5 +10,5 @@ template <typename T> class X {};
void fn ()
{
class L {};
X<L> f;
X<L> f; // { dg-error "uses local type|trying to instantiate|no type|invalid type" "" }
}

View File

@ -4,5 +4,5 @@ template <typename T> void foo() {}
int main () {
struct S {};
foo<S> ();
foo<S> (); // { dg-error "match" }
}

View File

@ -49,7 +49,7 @@ foo() {std::cout << "foo created" << std::endl; }
};
foo **f2;
allocate2d(d1, d2, f2);
ffree(d1, f2);
allocate2d(d1, d2, f2);// { dg-error "" } type.*// ERROR - trying to.*
ffree(d1, f2);// { dg-error "" } type.*// ERROR - trying to.*
}

View File

@ -4,8 +4,3 @@
typedef const struct { int i; } T; // { dg-error "" } referenced below
void f (T* t); // { dg-error "" } uses unnamed type
int main()
{
f(0);
}

View File

@ -3,16 +3,13 @@ typedef struct {
int i;
} *p;
void f (p) { }
p q;
void f (p) { } // { dg-error "uses anonymous type" }
p q; // { dg-warning "uses anonymous type" }
int main()
{
extern p j; // { dg-error "anonymous type" }
j+1;
extern p j; // { dg-warning "uses anonymous type" }
struct A { int j; };
extern A a; // { dg-error "local type" }
a.j+1;
extern void f (A); // { dg-error "local type" }
f(a);
extern A a; // { dg-warning "uses local type" }
extern void f (A); // { dg-error "uses local type" }
}

View File

@ -7,7 +7,7 @@ extern GDBM_FILE gdbm_open();
}
typedef struct { int dummy[10]; } *FAIL_FILE;
extern FAIL_FILE fail_open(); // OK because it's never used
extern FAIL_FILE fail_open(); // { dg-error "" } non-local function
typedef struct { int dummy[10]; } *SUCCESS_FILE, S;
extern SUCCESS_FILE success_open();

View File

@ -8,7 +8,7 @@ void fn(T)
{
enum tern { H, L, X, U };
vector<tern> ternvec;
vector<tern> ternvec; // { dg-error "" } composed from a local type
}
template void fn(int);