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:
parent
d7c0c068dd
commit
1eee69dd71
19 changed files with 149 additions and 34 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
30
gcc/cp/pt.c
30
gcc/cp/pt.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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" }
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// { dg-additional-sources "nolinkage1a.cc" }
|
||||
// { dg-do link }
|
||||
// { dg-options -std=c++0x }
|
||||
|
||||
#include "nolinkage1.h"
|
||||
|
||||
|
|
|
@ -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\]" } }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// PR c++/14401
|
||||
|
||||
struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
|
||||
// { dg-warning "anonymous" "anon" { target *-*-* } 3 }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
|
||||
// { dg-do compile }
|
||||
|
||||
enum { a = 3 } x;
|
||||
enum { a = 3 } x; // { dg-warning "anonymous type" }
|
||||
|
|
|
@ -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" "" }
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ template <typename T> void foo() {}
|
|||
|
||||
int main () {
|
||||
struct S {};
|
||||
foo<S> ();
|
||||
foo<S> (); // { dg-error "match" }
|
||||
}
|
||||
|
|
|
@ -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.*
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue