Implement DR 757...
Implement DR 757: It's OK for a decl to use a type without linkage so long as the decl is defined in the current translation unit. * decl2.c (no_linkage_decls): New vector. (mark_used): Add decls that use types with no linkage. (cp_write_global_declarations): Check that they are defined. (decl_defined_p, no_linkage_error): New fns. * cp-tree.h (DECL_NO_LINKAGE_CHECKED): New macro. (struct lang_decl_base): Add flag. * decl.c (grokfndecl): Don't check type linkage. (grokvardecl): If the type has no linkage, just make sure DECL_LANG_SPECIFIC is set. * pt.c (check_instantiated_arg): Don't check type linkage. * name-lookup.c (is_local_extern): New fn. * name-lookup.h: Declare it. From-SVN: r150634
This commit is contained in:
parent
8d1b99e26a
commit
e8f43da6f9
|
@ -1,3 +1,20 @@
|
||||||
|
2009-08-10 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
Implement DR 757: It's OK for a decl to use a type without linkage
|
||||||
|
so long as the decl is defined in the current translation unit.
|
||||||
|
* decl2.c (no_linkage_decls): New vector.
|
||||||
|
(mark_used): Add decls that use types with no linkage.
|
||||||
|
(cp_write_global_declarations): Check that they are defined.
|
||||||
|
(decl_defined_p, no_linkage_error): New fns.
|
||||||
|
* cp-tree.h (DECL_NO_LINKAGE_CHECKED): New macro.
|
||||||
|
(struct lang_decl_base): Add flag.
|
||||||
|
* decl.c (grokfndecl): Don't check type linkage.
|
||||||
|
(grokvardecl): If the type has no linkage, just make sure
|
||||||
|
DECL_LANG_SPECIFIC is set.
|
||||||
|
* pt.c (check_instantiated_arg): Don't check type linkage.
|
||||||
|
* name-lookup.c (is_local_extern): New fn.
|
||||||
|
* name-lookup.h: Declare it.
|
||||||
|
|
||||||
2009-08-05 Jason Merrill <jason@redhat.com>
|
2009-08-05 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
PR c++/40948
|
PR c++/40948
|
||||||
|
|
|
@ -1579,8 +1579,9 @@ struct GTY(()) lang_decl_base {
|
||||||
unsigned anticipated_p : 1; /* fn or type */
|
unsigned anticipated_p : 1; /* fn or type */
|
||||||
unsigned friend_attr : 1; /* fn or type */
|
unsigned friend_attr : 1; /* fn or type */
|
||||||
unsigned template_conv_p : 1; /* template only? */
|
unsigned template_conv_p : 1; /* template only? */
|
||||||
|
unsigned no_linkage_checked : 1; /* var or fn */
|
||||||
unsigned u2sel : 1;
|
unsigned u2sel : 1;
|
||||||
/* 2 spare bits */
|
/* 1 spare bit */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* True for DECL codes which have template info and access. */
|
/* True for DECL codes which have template info and access. */
|
||||||
|
@ -1982,6 +1983,14 @@ struct GTY(()) lang_decl {
|
||||||
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
|
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
|
||||||
->u.base.initialized_in_class)
|
->u.base.initialized_in_class)
|
||||||
|
|
||||||
|
/* Nonzero if we've checked whether DECL uses types without linkage in a
|
||||||
|
potentially invalid way.
|
||||||
|
??? Instead, should fix mark_used to only set TREE_USED when we're
|
||||||
|
really using something, and just return if it's already set. */
|
||||||
|
#define DECL_NO_LINKAGE_CHECKED(DECL) \
|
||||||
|
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
|
||||||
|
->u.base.no_linkage_checked)
|
||||||
|
|
||||||
/* Nonzero for DECL means that this decl is just a friend declaration,
|
/* Nonzero for DECL means that this decl is just a friend declaration,
|
||||||
and should not be added to the list of members for this class. */
|
and should not be added to the list of members for this class. */
|
||||||
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr)
|
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr)
|
||||||
|
|
|
@ -6747,36 +6747,6 @@ grokfndecl (tree ctype,
|
||||||
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
|
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
|
||||||
publicp = 0;
|
publicp = 0;
|
||||||
|
|
||||||
if (publicp)
|
|
||||||
{
|
|
||||||
/* [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.
|
|
||||||
|
|
||||||
Only check this for public decls for now. See core 319, 389. */
|
|
||||||
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;
|
TREE_PUBLIC (decl) = publicp;
|
||||||
if (! publicp)
|
if (! publicp)
|
||||||
{
|
{
|
||||||
|
@ -7021,36 +6991,13 @@ grokvardecl (tree type,
|
||||||
|
|
||||||
if (TREE_PUBLIC (decl))
|
if (TREE_PUBLIC (decl))
|
||||||
{
|
{
|
||||||
/* [basic.link]: A name with no linkage (notably, the name of a class
|
/* If the type of the decl has no linkage, make sure that we'll
|
||||||
or enumeration declared in a local scope) shall not be used to
|
notice that in mark_used. */
|
||||||
declare an entity with linkage.
|
if (DECL_LANG_SPECIFIC (decl) == NULL
|
||||||
|
&& TREE_PUBLIC (decl)
|
||||||
Only check this for public decls for now. */
|
&& !DECL_EXTERN_C_P (decl)
|
||||||
tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
|
&& no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
|
||||||
if (t)
|
retrofit_lang_decl (decl);
|
||||||
{
|
|
||||||
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
|
else
|
||||||
DECL_INTERFACE_KNOWN (decl) = 1;
|
DECL_INTERFACE_KNOWN (decl) = 1;
|
||||||
|
|
|
@ -84,6 +84,7 @@ static void write_out_vars (tree);
|
||||||
static void import_export_class (tree);
|
static void import_export_class (tree);
|
||||||
static tree get_guard_bits (tree);
|
static tree get_guard_bits (tree);
|
||||||
static void determine_visibility_from_class (tree, tree);
|
static void determine_visibility_from_class (tree, tree);
|
||||||
|
static bool decl_defined_p (tree);
|
||||||
|
|
||||||
/* A list of static class variables. This is needed, because a
|
/* A list of static class variables. This is needed, because a
|
||||||
static class variable can be declared inside the class without
|
static class variable can be declared inside the class without
|
||||||
|
@ -94,6 +95,10 @@ static GTY(()) VEC(tree,gc) *pending_statics;
|
||||||
may need to emit outline anyway. */
|
may need to emit outline anyway. */
|
||||||
static GTY(()) VEC(tree,gc) *deferred_fns;
|
static GTY(()) VEC(tree,gc) *deferred_fns;
|
||||||
|
|
||||||
|
/* A list of decls that use types with no linkage, which we need to make
|
||||||
|
sure are defined. */
|
||||||
|
static GTY(()) VEC(tree,gc) *no_linkage_decls;
|
||||||
|
|
||||||
/* Nonzero if we're done parsing and into end-of-file activities. */
|
/* Nonzero if we're done parsing and into end-of-file activities. */
|
||||||
|
|
||||||
int at_eof;
|
int at_eof;
|
||||||
|
@ -3332,6 +3337,40 @@ build_java_method_aliases (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true iff there is a definition available for variable or
|
||||||
|
function DECL. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
decl_defined_p (tree decl)
|
||||||
|
{
|
||||||
|
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||||
|
return (DECL_INITIAL (decl) != NULL_TREE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CODE (decl) == VAR_DECL);
|
||||||
|
return !DECL_EXTERNAL (decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complain that DECL uses a type with no linkage but is never defined. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
no_linkage_error (tree decl)
|
||||||
|
{
|
||||||
|
tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
|
||||||
|
if (TYPE_ANONYMOUS_P (t))
|
||||||
|
{
|
||||||
|
permerror (0, "%q+#D, declared using anonymous type, "
|
||||||
|
"is used but never defined", decl);
|
||||||
|
if (is_typedef_decl (TYPE_NAME (t)))
|
||||||
|
permerror (0, "%q+#D does not refer to the unqualified type, "
|
||||||
|
"so it is not used for linkage", TYPE_NAME (t));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
permerror (0, "%q+#D, declared using local type %qT, "
|
||||||
|
"is used but never defined", decl, t);
|
||||||
|
}
|
||||||
|
|
||||||
/* This routine is called at the end of compilation.
|
/* This routine is called at the end of compilation.
|
||||||
Its job is to create all the code needed to initialize and
|
Its job is to create all the code needed to initialize and
|
||||||
destroy the global aggregates. We do the destruction
|
destroy the global aggregates. We do the destruction
|
||||||
|
@ -3613,6 +3652,11 @@ cp_write_global_declarations (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* So must decls that use a type with no linkage. */
|
||||||
|
for (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i)
|
||||||
|
if (!decl_defined_p (decl))
|
||||||
|
no_linkage_error (decl);
|
||||||
|
|
||||||
/* We give C linkage to static constructors and destructors. */
|
/* We give C linkage to static constructors and destructors. */
|
||||||
push_lang_context (lang_name_c);
|
push_lang_context (lang_name_c);
|
||||||
|
|
||||||
|
@ -3851,6 +3895,32 @@ mark_used (tree decl)
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* DR 757: A type without linkage shall not be used as the type of a
|
||||||
|
variable or function with linkage, unless
|
||||||
|
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 (TREE_PUBLIC (decl)
|
||||||
|
&& (TREE_CODE (decl) == FUNCTION_DECL
|
||||||
|
|| TREE_CODE (decl) == VAR_DECL)
|
||||||
|
&& DECL_LANG_SPECIFIC (decl)
|
||||||
|
&& !DECL_NO_LINKAGE_CHECKED (decl))
|
||||||
|
{
|
||||||
|
DECL_NO_LINKAGE_CHECKED (decl) = true;
|
||||||
|
if (!DECL_EXTERN_C_P (decl)
|
||||||
|
&& !DECL_ARTIFICIAL (decl)
|
||||||
|
&& !decl_defined_p (decl)
|
||||||
|
&& no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
|
||||||
|
{
|
||||||
|
if (is_local_extern (decl))
|
||||||
|
/* There's no way to define a local extern, and adding it to
|
||||||
|
the vector interferes with GC, so give an error now. */
|
||||||
|
no_linkage_error (decl);
|
||||||
|
else
|
||||||
|
VEC_safe_push (tree, gc, no_linkage_decls, decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
|
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
|
||||||
&& !TREE_ASM_WRITTEN (decl))
|
&& !TREE_ASM_WRITTEN (decl))
|
||||||
/* Remember it, so we can check it was defined. */
|
/* Remember it, so we can check it was defined. */
|
||||||
|
|
|
@ -4392,6 +4392,34 @@ lookup_name_innermost_nonclass_level (tree name)
|
||||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
|
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true iff DECL is a block-scope extern declaration of a function
|
||||||
|
or variable. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_local_extern (tree decl)
|
||||||
|
{
|
||||||
|
cxx_binding *binding;
|
||||||
|
|
||||||
|
/* For functions, this is easy. */
|
||||||
|
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||||
|
return DECL_LOCAL_FUNCTION_P (decl);
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) != VAR_DECL)
|
||||||
|
return false;
|
||||||
|
if (!current_function_decl)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* For variables, this is not easy. We need to look at the binding stack
|
||||||
|
for the identifier to see whether the decl we have is a local. */
|
||||||
|
for (binding = IDENTIFIER_BINDING (DECL_NAME (decl));
|
||||||
|
binding && binding->scope->kind != sk_namespace;
|
||||||
|
binding = binding->previous)
|
||||||
|
if (binding->value == decl)
|
||||||
|
return LOCAL_BINDING_P (binding);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Like lookup_name_innermost_nonclass_level, but for types. */
|
/* Like lookup_name_innermost_nonclass_level, but for types. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
|
|
|
@ -318,6 +318,7 @@ extern tree remove_hidden_names (tree);
|
||||||
extern tree lookup_qualified_name (tree, tree, bool, bool);
|
extern tree lookup_qualified_name (tree, tree, bool, bool);
|
||||||
extern tree lookup_name_nonclass (tree);
|
extern tree lookup_name_nonclass (tree);
|
||||||
extern tree lookup_name_innermost_nonclass_level (tree);
|
extern tree lookup_name_innermost_nonclass_level (tree);
|
||||||
|
extern bool is_local_extern (tree);
|
||||||
extern tree lookup_function_nonclass (tree, VEC(tree,gc) *, bool);
|
extern tree lookup_function_nonclass (tree, VEC(tree,gc) *, bool);
|
||||||
extern void push_local_binding (tree, tree, int);
|
extern void push_local_binding (tree, tree, int);
|
||||||
extern bool pushdecl_class_level (tree);
|
extern bool pushdecl_class_level (tree);
|
||||||
|
|
27
gcc/cp/pt.c
27
gcc/cp/pt.c
|
@ -12215,7 +12215,7 @@ tsubst_copy_and_build (tree t,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that the instantiated ARGS are valid. For type arguments,
|
/* Verify that the instantiated ARGS are valid. For type arguments,
|
||||||
make sure that the type's linkage is ok. For non-type arguments,
|
make sure that the type is not variably modified. For non-type arguments,
|
||||||
make sure they are constants if they are integral or enumerations.
|
make sure they are constants if they are integral or enumerations.
|
||||||
Emit an error under control of COMPLAIN, and return TRUE on error. */
|
Emit an error under control of COMPLAIN, and return TRUE on error. */
|
||||||
|
|
||||||
|
@ -12236,30 +12236,7 @@ check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
|
||||||
}
|
}
|
||||||
else if (TYPE_P (t))
|
else if (TYPE_P (t))
|
||||||
{
|
{
|
||||||
/* [basic.link]: A name with no linkage (notably, the name
|
if (variably_modified_type_p (t, NULL_TREE))
|
||||||
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. */
|
|
||||||
tree nt = 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)
|
if (complain & tf_error)
|
||||||
error ("%qT is a variably modified type", t);
|
error ("%qT is a variably modified type", t);
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
2009-08-10 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* g++.dg/other/linkage2.C: New test for types-without-linkage
|
||||||
|
handling.
|
||||||
|
* g++.dg/ext/anon-struct4.C: No error about anonymous type.
|
||||||
|
* 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: Use the undefined decls.
|
||||||
|
* g++.old-deja/g++.other/linkage1.C: Likewise.
|
||||||
|
|
||||||
2009-08-10 Manuel López-Ibáñez <manu@gcc.gnu.org>
|
2009-08-10 Manuel López-Ibáñez <manu@gcc.gnu.org>
|
||||||
|
|
||||||
* gcc.dg/dg.exp: Test also c-c++-common dir.
|
* gcc.dg/dg.exp: Test also c-c++-common dir.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// PR c++/14401
|
// PR c++/14401
|
||||||
|
|
||||||
struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
|
struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
|
||||||
// { dg-warning "anonymous" "anon" { target *-*-* } 3 }
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
// { dg-options "" }
|
// { dg-options "" }
|
||||||
|
|
||||||
// Make sure we issue a diagnostic if a type with no linkage is used
|
// Make sure we don't issue a diagnostic if a type with no linkage is used
|
||||||
// to declare a a variable that has linkage.
|
// to declare a a variable that has linkage if that variable is defined.
|
||||||
|
|
||||||
struct { int i; } a; // { dg-warning "anonymous type" }
|
struct { int i; } a;
|
||||||
|
|
||||||
void foo() { a.i; }
|
void foo() { a.i; }
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
|
|
||||||
enum { a = 3 } x; // { dg-warning "anonymous type" }
|
enum { a = 3 } x;
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// DR 743: A type without linkage shall not be used as the type of a
|
||||||
|
// variable or function with linkage, unless
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
template <typename T> struct B {
|
||||||
|
void g(T){}
|
||||||
|
void h(T); // { dg-error "never defined" }
|
||||||
|
friend void i(B, T){}
|
||||||
|
static T t1; // { dg-error "never defined" }
|
||||||
|
static T t2;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> T B<T>::t2 = { };
|
||||||
|
|
||||||
|
enum {} e1; // OK, defined
|
||||||
|
extern enum {} e2; // { dg-error "never defined" }
|
||||||
|
extern "C" enum {} e3; // OK, extern "C"
|
||||||
|
|
||||||
|
void f() {
|
||||||
|
struct A { int x; }; // no linkage
|
||||||
|
A a = {1};
|
||||||
|
B<A> ba; // declares B<A>::g(A) and B<A>::h(A)
|
||||||
|
ba.t1 = a; // error, B<T>::t never defined
|
||||||
|
ba.t2 = a; // OK
|
||||||
|
ba.g(a); // OK
|
||||||
|
ba.h(a); // error, B<T>::h never defined
|
||||||
|
i(ba, a); // OK
|
||||||
|
e1+e2+e3;
|
||||||
|
}
|
|
@ -10,5 +10,5 @@ template <typename T> class X {};
|
||||||
void fn ()
|
void fn ()
|
||||||
{
|
{
|
||||||
class L {};
|
class L {};
|
||||||
X<L> f; // { dg-error "uses local type|trying to instantiate|no type|invalid type" "" }
|
X<L> f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,5 @@ template <typename T> void foo() {}
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
struct S {};
|
struct S {};
|
||||||
foo<S> (); // { dg-error "match" }
|
foo<S> ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ foo() {std::cout << "foo created" << std::endl; }
|
||||||
};
|
};
|
||||||
|
|
||||||
foo **f2;
|
foo **f2;
|
||||||
allocate2d(d1, d2, f2);// { dg-error "" } type.*// ERROR - trying to.*
|
allocate2d(d1, d2, f2);
|
||||||
ffree(d1, f2);// { dg-error "" } type.*// ERROR - trying to.*
|
ffree(d1, f2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,3 +4,8 @@
|
||||||
|
|
||||||
typedef const struct { int i; } T; // { dg-error "" } referenced below
|
typedef const struct { int i; } T; // { dg-error "" } referenced below
|
||||||
void f (T* t); // { dg-error "" } uses unnamed type
|
void f (T* t); // { dg-error "" } uses unnamed type
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
|
|
@ -3,13 +3,16 @@ typedef struct {
|
||||||
int i;
|
int i;
|
||||||
} *p;
|
} *p;
|
||||||
|
|
||||||
void f (p) { } // { dg-error "uses anonymous type" }
|
void f (p) { }
|
||||||
p q; // { dg-warning "uses anonymous type" }
|
p q;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
extern p j; // { dg-warning "uses anonymous type" }
|
extern p j; // { dg-error "anonymous type" }
|
||||||
|
j+1;
|
||||||
struct A { int j; };
|
struct A { int j; };
|
||||||
extern A a; // { dg-warning "uses local type" }
|
extern A a; // { dg-error "local type" }
|
||||||
extern void f (A); // { dg-error "uses local type" }
|
a.j+1;
|
||||||
|
extern void f (A); // { dg-error "local type" }
|
||||||
|
f(a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ extern GDBM_FILE gdbm_open();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct { int dummy[10]; } *FAIL_FILE;
|
typedef struct { int dummy[10]; } *FAIL_FILE;
|
||||||
extern FAIL_FILE fail_open(); // { dg-error "" } non-local function
|
extern FAIL_FILE fail_open(); // OK because it's never used
|
||||||
|
|
||||||
typedef struct { int dummy[10]; } *SUCCESS_FILE, S;
|
typedef struct { int dummy[10]; } *SUCCESS_FILE, S;
|
||||||
extern SUCCESS_FILE success_open();
|
extern SUCCESS_FILE success_open();
|
||||||
|
|
|
@ -8,7 +8,7 @@ void fn(T)
|
||||||
{
|
{
|
||||||
enum tern { H, L, X, U };
|
enum tern { H, L, X, U };
|
||||||
|
|
||||||
vector<tern> ternvec; // { dg-error "" } composed from a local type
|
vector<tern> ternvec;
|
||||||
}
|
}
|
||||||
|
|
||||||
template void fn(int);
|
template void fn(int);
|
||||||
|
|
Loading…
Reference in New Issue