re PR c++/26693 (Access checks not performed for types in templates)
gcc/ChangeLog: 2009-04-02 Dodji Seketeli <dodji@redhat.com> PR c++/26693 * c-decl.c: (clone_underlying_type): Move this ... * c-common.c (set_underlying_type): ... here. Also, make sure the function properly sets TYPE_STUB_DECL() on the newly created typedef variant type. * c-common.h (is_typedef_decl, set_underlying_type): Declare ... * c-common.c (is_typedef_decl, set_underlying_type): ... new entry points. gcc/cp/ChangeLog: 2009-04-02 Dodji Seketeli <dodji@redhat.com> PR c++/26693 * decl2.c (grokfield): when a typedef appears in a class, create the typedef variant type node for it. (save_template_attributes): Creating typedef variant type node here is now useless. * decl.c (grokdeclarator): If the typedef'ed struct/class was anonymous, set the proper type name to all its type variants. (xref_basetypes) : Fixup the variant types after setting TYPE_BINFO on REF. * name-lookup.c (pushdecl_maybe_friend): Reuse the set_underlying_type function to install typedef variant types. * cp-tree.h (MEMBER_TYPES_NEEDING_ACCESS_CHECK): New template accessor macro. (append_type_to_template_for_access_check): New entry points. * semantics.c (check_accessibility_of_qualified_id): When a typedef that is a member of a class appears in a template, add it to the template. It will be ... * class.c (finish_struct_bits): Split type variant fixup into ... (fixup_type_variants): A new entry point. * pt.c (instantiate_class_template, instantiate_template ): ... access checked at template instantiation time. (resolve_type_name_type): The type name should be the name of the main type variant. (retrieve_specialization): Specializations of template typedefs aren't to be looked up in DECL_TEMPLATE_INSTANTIATIONS (tmpl). (append_type_to_template_for_access_check): New entry point. (tsubst_decl): For typedefs, build the variant type from the correct original type. (get_class_bindings): Fix function comment. (perform_typedefs_access_check): New entry point. gcc/testsuite/ChangeLog: 2009-04-02 Dodji Seketeli <dodji@redhat.com> PR c++/26693 * g++.dg/template/typedef11.C: New test. * g++.dg/template/typedef12.C: Likewise. * g++.dg/template/typedef13.C: Likewise. * g++.dg/template/typedef14.C: Likewise. * g++.dg/template/typedef15.C: Likewise. * g++.dg/template/typedef16.C: Likewise. * g++.dg/template/sfinae3.C: Compile this pedantically. The only errors expected should be the one saying the typedef is ill formed. * g++.old-deja/g++.pt/typename8.C: Likewise. * g++.dg/template/access11.C: Update this. libstdc++-v3/ChangeLog: 2009-04-02 Dodji Seketeli <dodji@redhat.com> * include/ext/bitmap_allocator.h: the typedefs should be made public if we want them to be accessible. This has been revealed by the patch that fixes PR c++/26693 in g++. From-SVN: r145440
This commit is contained in:
parent
bf1cbdc6e4
commit
d0940d5662
|
@ -1,3 +1,13 @@
|
|||
2009-04-02 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
PR c++/26693
|
||||
* c-decl.c: (clone_underlying_type): Move this ...
|
||||
* c-common.c (set_underlying_type): ... here.
|
||||
Also, make sure the function properly sets TYPE_STUB_DECL() on
|
||||
the newly created typedef variant type.
|
||||
* c-common.h (is_typedef_decl, set_underlying_type): Declare ...
|
||||
* c-common.c (is_typedef_decl, set_underlying_type): ... new entry points.
|
||||
|
||||
2009-04-02 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/37221
|
||||
|
|
|
@ -9172,4 +9172,76 @@ warn_for_sign_compare (location_t location,
|
|||
}
|
||||
}
|
||||
|
||||
/* Setup a TYPE_DECL node as a typedef representation.
|
||||
|
||||
X is a TYPE_DECL for a typedef statement. Create a brand new
|
||||
..._TYPE node (which will be just a variant of the existing
|
||||
..._TYPE node with identical properties) and then install X
|
||||
as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
|
||||
|
||||
The whole point here is to end up with a situation where each
|
||||
and every ..._TYPE node the compiler creates will be uniquely
|
||||
associated with AT MOST one node representing a typedef name.
|
||||
This way, even though the compiler substitutes corresponding
|
||||
..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
|
||||
early on, later parts of the compiler can always do the reverse
|
||||
translation and get back the corresponding typedef name. For
|
||||
example, given:
|
||||
|
||||
typedef struct S MY_TYPE;
|
||||
MY_TYPE object;
|
||||
|
||||
Later parts of the compiler might only know that `object' was of
|
||||
type `struct S' if it were not for code just below. With this
|
||||
code however, later parts of the compiler see something like:
|
||||
|
||||
struct S' == struct S
|
||||
typedef struct S' MY_TYPE;
|
||||
struct S' object;
|
||||
|
||||
And they can then deduce (from the node for type struct S') that
|
||||
the original object declaration was:
|
||||
|
||||
MY_TYPE object;
|
||||
|
||||
Being able to do this is important for proper support of protoize,
|
||||
and also for generating precise symbolic debugging information
|
||||
which takes full account of the programmer's (typedef) vocabulary.
|
||||
|
||||
Obviously, we don't want to generate a duplicate ..._TYPE node if
|
||||
the TYPE_DECL node that we are now processing really represents a
|
||||
standard built-in type. */
|
||||
|
||||
void
|
||||
set_underlying_type (tree x)
|
||||
{
|
||||
if (x == error_mark_node)
|
||||
return;
|
||||
if (DECL_IS_BUILTIN (x))
|
||||
{
|
||||
if (TYPE_NAME (TREE_TYPE (x)) == 0)
|
||||
TYPE_NAME (TREE_TYPE (x)) = x;
|
||||
}
|
||||
else if (TREE_TYPE (x) != error_mark_node
|
||||
&& DECL_ORIGINAL_TYPE (x) == NULL_TREE)
|
||||
{
|
||||
tree tt = TREE_TYPE (x);
|
||||
DECL_ORIGINAL_TYPE (x) = tt;
|
||||
tt = build_variant_type_copy (tt);
|
||||
TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
|
||||
TYPE_NAME (tt) = x;
|
||||
TREE_USED (tt) = TREE_USED (x);
|
||||
TREE_TYPE (x) = tt;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if X is a typedef decl. */
|
||||
|
||||
bool
|
||||
is_typedef_decl (tree x)
|
||||
{
|
||||
return (x && TREE_CODE (x) == TYPE_DECL
|
||||
&& DECL_ORIGINAL_TYPE (x) != NULL_TREE);
|
||||
}
|
||||
|
||||
#include "gt-c-common.h"
|
||||
|
|
|
@ -1009,6 +1009,8 @@ extern void warn_for_sign_compare (location_t,
|
|||
tree op0, tree op1,
|
||||
tree result_type,
|
||||
enum tree_code resultcode);
|
||||
extern void set_underlying_type (tree x);
|
||||
extern bool is_typedef_decl (tree x);
|
||||
|
||||
/* In c-gimplify.c */
|
||||
extern void c_genericize (tree);
|
||||
|
|
63
gcc/c-decl.c
63
gcc/c-decl.c
|
@ -2002,67 +2002,6 @@ warn_if_shadowing (tree new_decl)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Subroutine of pushdecl.
|
||||
|
||||
X is a TYPE_DECL for a typedef statement. Create a brand new
|
||||
..._TYPE node (which will be just a variant of the existing
|
||||
..._TYPE node with identical properties) and then install X
|
||||
as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
|
||||
|
||||
The whole point here is to end up with a situation where each
|
||||
and every ..._TYPE node the compiler creates will be uniquely
|
||||
associated with AT MOST one node representing a typedef name.
|
||||
This way, even though the compiler substitutes corresponding
|
||||
..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
|
||||
early on, later parts of the compiler can always do the reverse
|
||||
translation and get back the corresponding typedef name. For
|
||||
example, given:
|
||||
|
||||
typedef struct S MY_TYPE;
|
||||
MY_TYPE object;
|
||||
|
||||
Later parts of the compiler might only know that `object' was of
|
||||
type `struct S' if it were not for code just below. With this
|
||||
code however, later parts of the compiler see something like:
|
||||
|
||||
struct S' == struct S
|
||||
typedef struct S' MY_TYPE;
|
||||
struct S' object;
|
||||
|
||||
And they can then deduce (from the node for type struct S') that
|
||||
the original object declaration was:
|
||||
|
||||
MY_TYPE object;
|
||||
|
||||
Being able to do this is important for proper support of protoize,
|
||||
and also for generating precise symbolic debugging information
|
||||
which takes full account of the programmer's (typedef) vocabulary.
|
||||
|
||||
Obviously, we don't want to generate a duplicate ..._TYPE node if
|
||||
the TYPE_DECL node that we are now processing really represents a
|
||||
standard built-in type. */
|
||||
|
||||
static void
|
||||
clone_underlying_type (tree x)
|
||||
{
|
||||
if (DECL_IS_BUILTIN (x))
|
||||
{
|
||||
if (TYPE_NAME (TREE_TYPE (x)) == 0)
|
||||
TYPE_NAME (TREE_TYPE (x)) = x;
|
||||
}
|
||||
else if (TREE_TYPE (x) != error_mark_node
|
||||
&& DECL_ORIGINAL_TYPE (x) == NULL_TREE)
|
||||
{
|
||||
tree tt = TREE_TYPE (x);
|
||||
DECL_ORIGINAL_TYPE (x) = tt;
|
||||
tt = build_variant_type_copy (tt);
|
||||
TYPE_NAME (tt) = x;
|
||||
TREE_USED (tt) = TREE_USED (x);
|
||||
TREE_TYPE (x) = tt;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record a decl-node X as belonging to the current lexical scope.
|
||||
Check for errors (such as an incompatible declaration for the same
|
||||
name already seen in the same scope).
|
||||
|
@ -2288,7 +2227,7 @@ pushdecl (tree x)
|
|||
|
||||
skip_external_and_shadow_checks:
|
||||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
clone_underlying_type (x);
|
||||
set_underlying_type (x);
|
||||
|
||||
bind (name, x, scope, /*invisible=*/false, nested, locus);
|
||||
|
||||
|
|
|
@ -1,3 +1,36 @@
|
|||
2009-04-02 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
PR c++/26693
|
||||
* decl2.c (grokfield): when a typedef appears in a
|
||||
class, create the typedef variant type node for it.
|
||||
(save_template_attributes): Creating typedef variant type node
|
||||
here is now useless.
|
||||
* decl.c (grokdeclarator): If the typedef'ed struct/class was
|
||||
anonymous, set the proper type name to all its type variants.
|
||||
(xref_basetypes) : Fixup the variant types after setting
|
||||
TYPE_BINFO on REF.
|
||||
* name-lookup.c (pushdecl_maybe_friend): Reuse the
|
||||
set_underlying_type function to install typedef variant types.
|
||||
* cp-tree.h (MEMBER_TYPES_NEEDING_ACCESS_CHECK): New template accessor
|
||||
macro.
|
||||
(append_type_to_template_for_access_check): New entry points.
|
||||
* semantics.c (check_accessibility_of_qualified_id):
|
||||
When a typedef that is a member of a class appears in a template,
|
||||
add it to the template. It will be ...
|
||||
* class.c (finish_struct_bits): Split type variant fixup into ...
|
||||
(fixup_type_variants): A new entry point.
|
||||
* pt.c (instantiate_class_template, instantiate_template ): ... access
|
||||
checked at template instantiation time.
|
||||
(resolve_type_name_type): The type name should be the name of the
|
||||
main type variant.
|
||||
(retrieve_specialization): Specializations of template typedefs aren't
|
||||
to looked up in DECL_TEMPLATE_INSTANTIATIONS (tmpl).
|
||||
(append_type_to_template_for_access_check): New entry point.
|
||||
(tsubst_decl): For typedefs, build the variant type from the correct
|
||||
original type.
|
||||
(get_class_bindings): Fix function comment.
|
||||
(perform_typedefs_access_check): New entry point.
|
||||
|
||||
2009-03-31 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/34691
|
||||
|
|
|
@ -1439,16 +1439,17 @@ determine_primary_bases (tree t)
|
|||
BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set memoizing fields and bits of T (and its variants) for later
|
||||
use. */
|
||||
|
||||
static void
|
||||
finish_struct_bits (tree t)
|
||||
/* Update the variant types of T. */
|
||||
|
||||
void
|
||||
fixup_type_variants (tree t)
|
||||
{
|
||||
tree variants;
|
||||
|
||||
/* Fix up variants (if any). */
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
for (variants = TYPE_NEXT_VARIANT (t);
|
||||
variants;
|
||||
variants = TYPE_NEXT_VARIANT (variants))
|
||||
|
@ -1472,6 +1473,17 @@ finish_struct_bits (tree t)
|
|||
/* All variants of a class have the same attributes. */
|
||||
TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set memoizing fields and bits of T (and its variants) for later
|
||||
use. */
|
||||
|
||||
static void
|
||||
finish_struct_bits (tree t)
|
||||
{
|
||||
/* Fix up variants (if any). */
|
||||
fixup_type_variants (t);
|
||||
|
||||
if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
|
||||
/* For a class w/o baseclasses, 'finish_struct' has set
|
||||
|
|
|
@ -3181,6 +3181,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
|||
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \
|
||||
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE))
|
||||
|
||||
/* The chained list of typedefs that are referenced in templates.
|
||||
These typedefs need to be access checked at template instantiation time.
|
||||
There are put here at parsing time. */
|
||||
#define MEMBER_TYPES_NEEDING_ACCESS_CHECK(NODE) DECL_ACCESS (NODE)
|
||||
|
||||
/* Nonzero if NODE which declares a type. */
|
||||
#define DECL_DECLARES_TYPE_P(NODE) \
|
||||
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
|
||||
|
@ -4278,6 +4283,7 @@ extern bool type_has_user_nondefault_constructor (tree);
|
|||
extern bool type_has_user_provided_constructor (tree);
|
||||
extern bool type_has_user_provided_default_constructor (tree);
|
||||
extern bool defaultable_fn_p (tree);
|
||||
extern void fixup_type_variants (tree);
|
||||
|
||||
/* in cvt.c */
|
||||
extern tree convert_to_reference (tree, tree, int, int, tree);
|
||||
|
@ -4548,6 +4554,7 @@ extern tree check_explicit_specialization (tree, tree, int, int);
|
|||
extern tree make_auto (void);
|
||||
extern tree do_auto_deduction (tree, tree, tree);
|
||||
extern tree type_uses_auto (tree);
|
||||
extern void append_type_to_template_for_access_check (tree, tree, tree);
|
||||
extern tree splice_late_return_type (tree, tree);
|
||||
extern bool is_auto (const_tree);
|
||||
extern tree process_template_parm (tree, tree, bool, bool);
|
||||
|
|
|
@ -8823,12 +8823,11 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
&& TYPE_ANONYMOUS_P (type)
|
||||
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
|
||||
{
|
||||
tree oldname = TYPE_NAME (type);
|
||||
tree t;
|
||||
|
||||
/* Replace the anonymous name with the real name everywhere. */
|
||||
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
|
||||
if (TYPE_NAME (t) == oldname)
|
||||
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
|
||||
TYPE_NAME (t) = decl;
|
||||
|
||||
if (TYPE_LANG_SPECIFIC (type))
|
||||
|
@ -10787,6 +10786,9 @@ xref_basetypes (tree ref, tree base_list)
|
|||
BINFO_OFFSET (binfo) = size_zero_node;
|
||||
BINFO_TYPE (binfo) = ref;
|
||||
|
||||
/* Apply base-class info set up to the variants of this type. */
|
||||
fixup_type_variants (ref);
|
||||
|
||||
if (max_bases)
|
||||
{
|
||||
BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, max_bases);
|
||||
|
|
|
@ -820,6 +820,9 @@ grokfield (const cp_declarator *declarator,
|
|||
cplus_decl_attributes (&value, attrlist, attrflags);
|
||||
}
|
||||
|
||||
if (declspecs->specs[(int)ds_typedef])
|
||||
set_underlying_type (value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -1125,19 +1128,6 @@ save_template_attributes (tree *attr_p, tree *decl_p)
|
|||
if (!late_attrs)
|
||||
return;
|
||||
|
||||
/* Give this type a name so we know to look it up again at instantiation
|
||||
time. */
|
||||
if (TREE_CODE (*decl_p) == TYPE_DECL
|
||||
&& DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
|
||||
{
|
||||
tree oldt = TREE_TYPE (*decl_p);
|
||||
tree newt = build_variant_type_copy (oldt);
|
||||
DECL_ORIGINAL_TYPE (*decl_p) = oldt;
|
||||
TREE_TYPE (*decl_p) = newt;
|
||||
TYPE_NAME (newt) = *decl_p;
|
||||
TREE_USED (newt) = TREE_USED (*decl_p);
|
||||
}
|
||||
|
||||
if (DECL_P (*decl_p))
|
||||
q = &DECL_ATTRIBUTES (*decl_p);
|
||||
else
|
||||
|
|
|
@ -862,28 +862,20 @@ pushdecl_maybe_friend (tree x, bool is_friend)
|
|||
|
||||
/* If declaring a type as a typedef, copy the type (unless we're
|
||||
at line 0), and install this TYPE_DECL as the new type's typedef
|
||||
name. See the extensive comment in ../c-decl.c (pushdecl). */
|
||||
name. See the extensive comment of set_underlying_type (). */
|
||||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
{
|
||||
tree type = TREE_TYPE (x);
|
||||
if (DECL_IS_BUILTIN (x))
|
||||
{
|
||||
if (TYPE_NAME (type) == 0)
|
||||
TYPE_NAME (type) = x;
|
||||
}
|
||||
else if (type != error_mark_node && TYPE_NAME (type) != x
|
||||
/* We don't want to copy the type when all we're
|
||||
doing is making a TYPE_DECL for the purposes of
|
||||
inlining. */
|
||||
&& (!TYPE_NAME (type)
|
||||
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
|
||||
{
|
||||
DECL_ORIGINAL_TYPE (x) = type;
|
||||
type = build_variant_type_copy (type);
|
||||
TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
|
||||
TYPE_NAME (type) = x;
|
||||
TREE_TYPE (x) = type;
|
||||
}
|
||||
|
||||
if (DECL_IS_BUILTIN (x)
|
||||
|| (TREE_TYPE (x) != error_mark_node
|
||||
&& TYPE_NAME (type) != x
|
||||
/* We don't want to copy the type when all we're
|
||||
doing is making a TYPE_DECL for the purposes of
|
||||
inlining. */
|
||||
&& (!TYPE_NAME (type)
|
||||
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
|
||||
set_underlying_type (x);
|
||||
|
||||
if (type != error_mark_node
|
||||
&& TYPE_NAME (type)
|
||||
|
|
99
gcc/cp/pt.c
99
gcc/cp/pt.c
|
@ -175,6 +175,7 @@ static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool);
|
|||
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
|
||||
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
|
||||
static tree tsubst_decl (tree, tree, tsubst_flags_t);
|
||||
static void perform_typedefs_access_check (tree tmpl, tree targs);
|
||||
|
||||
/* Make the current scope suitable for access checking when we are
|
||||
processing T. T can be FUNCTION_DECL for instantiated function
|
||||
|
@ -949,6 +950,7 @@ retrieve_specialization (tree tmpl, tree args,
|
|||
DECL_TEMPLATE_SPECIALIZATIONS list. */
|
||||
if (!class_specializations_p
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
|
||||
&& !is_typedef_decl (DECL_TEMPLATE_RESULT (tmpl))
|
||||
&& TAGGED_TYPE_P (TREE_TYPE (tmpl)))
|
||||
sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
|
||||
else
|
||||
|
@ -6928,6 +6930,37 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
|
|||
}
|
||||
}
|
||||
|
||||
/* Perform (or defer) access check for typedefs that were referenced
|
||||
from within the template TMPL code.
|
||||
This is a subroutine of instantiate_template and instantiate_class_template.
|
||||
TMPL is the template to consider and TARGS is the list of arguments of
|
||||
that template. */
|
||||
|
||||
static void
|
||||
perform_typedefs_access_check (tree tmpl, tree targs)
|
||||
{
|
||||
tree t;
|
||||
|
||||
if (!tmpl || TREE_CODE (tmpl) != TEMPLATE_DECL)
|
||||
return;
|
||||
|
||||
for (t = MEMBER_TYPES_NEEDING_ACCESS_CHECK (tmpl); t; t = TREE_CHAIN (t))
|
||||
{
|
||||
tree type_decl = TREE_PURPOSE (t);
|
||||
tree type_scope = TREE_VALUE (t);
|
||||
|
||||
if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
|
||||
continue;
|
||||
|
||||
if (uses_template_parms (type_decl))
|
||||
type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
|
||||
if (uses_template_parms (type_scope))
|
||||
type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
|
||||
|
||||
perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl);
|
||||
}
|
||||
}
|
||||
|
||||
tree
|
||||
instantiate_class_template (tree type)
|
||||
{
|
||||
|
@ -7403,6 +7436,12 @@ instantiate_class_template (tree type)
|
|||
&& DECL_TEMPLATE_INFO (t))
|
||||
tsubst_default_arguments (t);
|
||||
|
||||
/* Some typedefs referenced from within the template code need to be access
|
||||
checked at template instantiation time, i.e now. These types were
|
||||
added to the template at parsing time. Let's get those and perform
|
||||
the acces checks then. */
|
||||
perform_typedefs_access_check (templ, args);
|
||||
perform_deferred_access_checks ();
|
||||
pop_nested_class ();
|
||||
pop_from_top_level ();
|
||||
pop_deferring_access_checks ();
|
||||
|
@ -12024,6 +12063,12 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
|
|||
/* Now we know the specialization, compute access previously
|
||||
deferred. */
|
||||
push_access_scope (fndecl);
|
||||
|
||||
/* Some typedefs referenced from within the template code need to be access
|
||||
checked at template instantiation time, i.e now. These types were
|
||||
added to the template at parsing time. Let's get those and perfom
|
||||
the acces checks then. */
|
||||
perform_typedefs_access_check (tmpl, targ_ptr);
|
||||
perform_deferred_access_checks ();
|
||||
pop_access_scope (fndecl);
|
||||
pop_deferring_access_checks ();
|
||||
|
@ -14404,7 +14449,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
|
|||
|
||||
/* Return the innermost template arguments that, when applied to a
|
||||
template specialization whose innermost template parameters are
|
||||
TPARMS, and whose specialization arguments are PARMS, yield the
|
||||
TPARMS, and whose specialization arguments are SPEC_ARGS, yield the
|
||||
ARGS.
|
||||
|
||||
For example, suppose we have:
|
||||
|
@ -16722,7 +16767,15 @@ resolve_typename_type (tree type, bool only_current_p)
|
|||
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
|
||||
|
||||
scope = TYPE_CONTEXT (type);
|
||||
name = TYPE_IDENTIFIER (type);
|
||||
/* Usually the non-qualified identifier of a TYPENAME_TYPE is
|
||||
TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
|
||||
a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
|
||||
the typedef. In that case TYPE_IDENTIFIER (type) is not the non-qualified
|
||||
identifier of the TYPENAME_TYPE anymore.
|
||||
So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
|
||||
TYPENAME_TYPE instead, we avoid messing up with a possible
|
||||
typedef variant case. */
|
||||
name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
|
||||
|
||||
/* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
|
||||
it first before we can figure out what NAME refers to. */
|
||||
|
@ -17047,4 +17100,46 @@ type_uses_auto (tree type)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Append TYPE_DECL to the template TEMPL.
|
||||
TEMPL is either a class type or a FUNCTION_DECL associated
|
||||
to a TEMPLATE_DECL.
|
||||
At TEMPL instanciation time, TYPE_DECL will be checked to see
|
||||
if it can be accessed through SCOPE. */
|
||||
|
||||
void
|
||||
append_type_to_template_for_access_check (tree templ,
|
||||
tree type_decl,
|
||||
tree scope)
|
||||
{
|
||||
tree node, templ_decl;
|
||||
|
||||
gcc_assert (templ
|
||||
&& get_template_info (templ)
|
||||
&& TI_TEMPLATE (get_template_info (templ))
|
||||
&& type_decl
|
||||
&& (TREE_CODE (type_decl) == TYPE_DECL));
|
||||
|
||||
templ_decl = TI_TEMPLATE (get_template_info (templ));
|
||||
gcc_assert (templ_decl);
|
||||
|
||||
/* Make sure we don't append the type to the template twice.
|
||||
If this appears to be too slow, the
|
||||
MEMBER_TYPE_NEEDING_ACCESS_CHECK property
|
||||
of templ should be a hash table instead. */
|
||||
for (node = MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl);
|
||||
node;
|
||||
node = TREE_CHAIN (node))
|
||||
{
|
||||
tree decl = TREE_PURPOSE (node);
|
||||
tree type_scope = TREE_VALUE (node);
|
||||
|
||||
if (decl == type_decl && type_scope == scope)
|
||||
return;
|
||||
}
|
||||
|
||||
MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl) =
|
||||
tree_cons (type_decl, scope,
|
||||
MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl));
|
||||
}
|
||||
|
||||
#include "gt-cp-pt.h"
|
||||
|
|
|
@ -1528,6 +1528,32 @@ check_accessibility_of_qualified_id (tree decl,
|
|||
tree scope;
|
||||
tree qualifying_type = NULL_TREE;
|
||||
|
||||
/* If we are parsing a template declaration and if decl is a typedef,
|
||||
add it to a list tied to the template.
|
||||
At template instantiation time, that list will be walked and
|
||||
access check performed. */
|
||||
if (is_typedef_decl (decl))
|
||||
{
|
||||
/* This the scope through which type_decl is accessed.
|
||||
It will be useful information later to do access check for
|
||||
type_decl usage. */
|
||||
tree scope = nested_name_specifier
|
||||
? nested_name_specifier
|
||||
: DECL_CONTEXT (decl);
|
||||
tree templ_info = NULL;
|
||||
tree cs = current_scope ();
|
||||
|
||||
if (cs && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL))
|
||||
templ_info = get_template_info (cs);
|
||||
|
||||
if (templ_info
|
||||
&& TI_TEMPLATE (templ_info)
|
||||
&& scope
|
||||
&& CLASS_TYPE_P (scope)
|
||||
&& !currently_open_class (scope))
|
||||
append_type_to_template_for_access_check (current_scope (), decl, scope);
|
||||
}
|
||||
|
||||
/* If we're not checking, return immediately. */
|
||||
if (deferred_access_no_check)
|
||||
return;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
2009-04-02 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
PR c++/26693
|
||||
* g++.dg/template/typedef11.C: New test.
|
||||
* g++.dg/template/typedef12.C: Likewise.
|
||||
* g++.dg/template/typedef13.C: Likewise.
|
||||
* g++.dg/template/typedef14.C: Likewise.
|
||||
* g++.dg/template/typedef15.C: Likewise.
|
||||
* g++.dg/template/typedef16.C: Likewise.
|
||||
* g++.dg/template/sfinae3.C: Compile this pedantically.
|
||||
The only errors expected should be the one saying the typedef is ill
|
||||
formed.
|
||||
* g++.old-deja/g++.pt/typename8.C: Likewise.
|
||||
* g++.dg/template/access11.C: Update this.
|
||||
|
||||
2009-04-02 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/37221
|
||||
|
|
|
@ -17,8 +17,8 @@ template <> struct X::Y<int> {
|
|||
A::X x; // { dg-error "this context" }
|
||||
};
|
||||
|
||||
template <typename T> struct X::Y {
|
||||
template <typename T> struct X::Y { // { dg-error "this context" }
|
||||
typename T::X x; // { dg-error "this context" }
|
||||
};
|
||||
|
||||
template struct X::Y<A>; // { dg-message "instantiated" }
|
||||
template struct X::Y<A>; // { dg-message "instantiated from here" }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PR c++/24671
|
||||
// { dg-options "" }
|
||||
// { dg-do compile }
|
||||
|
||||
template<typename> struct A
|
||||
{
|
||||
|
@ -9,9 +9,9 @@ template<typename> struct A
|
|||
|
||||
template<typename> struct B
|
||||
{
|
||||
B(const B&); // { dg-message "candidate" }
|
||||
typedef typename A<char[A<B>::i]>::X Y;
|
||||
template<typename T> B(T, Y); // { dg-error "call" }
|
||||
B(const B&);
|
||||
typedef typename A<char[A<B>::i]>::X Y; // { dg-error "forbids zero-size array" }
|
||||
template<typename T> B(T, Y);
|
||||
};
|
||||
|
||||
B<int> b(0,0);
|
||||
B<int> b(0,0); // { dg-message "instantiated from here" }
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// Author: Dodji Seketeli <dodji@redhat.com>
|
||||
// Origin: PR c++/26693
|
||||
// { dg-do compile }
|
||||
|
||||
|
||||
class Alpha
|
||||
{
|
||||
typedef int X; // { dg-error "'typedef int Alpha::X' is private" }
|
||||
};
|
||||
|
||||
template<int>
|
||||
class Beta
|
||||
{
|
||||
typedef int Y; // { dg-error "'typedef int Beta<0>::Y' is private" }
|
||||
};
|
||||
|
||||
template <int>
|
||||
int
|
||||
bar ()
|
||||
{
|
||||
Beta<0>::Y i = 0;
|
||||
return Alpha::X ();
|
||||
}
|
||||
|
||||
int i = bar<0> (); // { dg-error "within this context" }
|
|
@ -0,0 +1,23 @@
|
|||
// Contributed by Dodji Seketeli <dodji@redhat.com>
|
||||
// Origin: Jason Merrill <jason@redhat.com>, PR c++/26693
|
||||
// { dg-do compile }
|
||||
|
||||
class A
|
||||
{
|
||||
protected:
|
||||
typedef int mytype;
|
||||
};
|
||||
|
||||
template <class T> class B;
|
||||
|
||||
class C: public A
|
||||
{
|
||||
template <class T> friend class B;
|
||||
};
|
||||
|
||||
template <class T> class B
|
||||
{
|
||||
C::mytype mem;
|
||||
};
|
||||
|
||||
B<int> b;
|
|
@ -0,0 +1,16 @@
|
|||
// Contributed by Dodji Seketeli <dodji@redhat.com>
|
||||
// Origin: PR c++/26693
|
||||
// { dg-do compile }
|
||||
|
||||
class A
|
||||
{
|
||||
typedef int mytype; // { dg-error "typedef int A::mytype' is private" }
|
||||
};
|
||||
|
||||
template <class T> class B : public A
|
||||
{ // { dg-error "within this context" }
|
||||
mytype mem;
|
||||
};
|
||||
|
||||
B<int> b; // { dg-message "instantiated from here" }
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Contributed by Dodji Seketeli <dodji@redhat.com>
|
||||
// Origin: PR c++/26693
|
||||
// { dg-do compile }
|
||||
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
typedef int mytype;
|
||||
|
||||
void
|
||||
foo ()
|
||||
{
|
||||
mytype v = ~static_cast<mytype> (0);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Contributed by Dodji Seketeli <dodji@redhat.com>
|
||||
// Origin: PR c++/26693
|
||||
// { dg-do compile }
|
||||
|
||||
template<class T> struct C0;
|
||||
|
||||
struct Foo {
|
||||
typedef int TypedefedFoo;
|
||||
typedef C0<Foo> TypedefedC0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct C0
|
||||
{
|
||||
typedef Foo TypedefedFoo;
|
||||
typename T::TypedefedC0::TypedefedFoo m;
|
||||
};
|
||||
|
||||
template<class U>
|
||||
struct C1
|
||||
{
|
||||
typedef C0<Foo> TypedefedC0;
|
||||
};
|
||||
|
||||
C0<C1<int> > c;
|
|
@ -0,0 +1,27 @@
|
|||
// Contributed by Dodji Seketeli <dodji@redhat.com>
|
||||
// Origin PR c++/26693
|
||||
// { dg-do compile }
|
||||
|
||||
struct C0
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct C1
|
||||
{
|
||||
typedef C0 TypedefedC0;
|
||||
|
||||
template<class W>
|
||||
void foo (TypedefedC0 *, W)
|
||||
{
|
||||
}
|
||||
|
||||
template<class W> C1 (W w)
|
||||
{
|
||||
TypedefedC0 c;
|
||||
foo (&c, w);
|
||||
}
|
||||
|
||||
};
|
||||
C0 c0;
|
||||
C1<int, char> c1 (&c0);
|
|
@ -5,14 +5,14 @@ template < class T > class A
|
|||
public:
|
||||
typedef typename T::myT anotherT; // { dg-error "" } undefined type
|
||||
|
||||
anotherT t; // { dg-error "" } undefined type
|
||||
anotherT t;
|
||||
|
||||
A() { }
|
||||
A(anotherT _t) { // { dg-error "" } undefined type
|
||||
A(anotherT _t) {
|
||||
t=_t;
|
||||
}
|
||||
|
||||
anotherT getT() { // { dg-error "" } undefined type
|
||||
anotherT getT() {
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2009-04-02 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
* include/ext/bitmap_allocator.h: the typedefs should be made public
|
||||
if we want them to be accessible. This has been revealed by the patch
|
||||
that fixes PR c++/26693 in g++.
|
||||
|
||||
2009-04-02 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/abi/post/powerpc64-linux-gnu/32/baseline_symbols.txt:
|
||||
|
@ -785,11 +791,6 @@
|
|||
on HPUX.
|
||||
* configure: Regenerate.
|
||||
|
||||
2009-01-22 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
* include/ext/bitmap_allocator.h: Reverting changes related to PR
|
||||
c++/26693.
|
||||
|
||||
2009-01-21 Benjamin Kosnik <bkoz@redhat.com>
|
||||
|
||||
* testsuite/29_atomics/headers/stdatomic.h/functions.c: Remove
|
||||
|
@ -797,10 +798,6 @@
|
|||
|
||||
2009-01-21 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
* include/ext/bitmap_allocator.h: the typedefs should be made public
|
||||
if we want them to be accessible. This has been revealed by the patch
|
||||
that fixes PR c++/26693 in g++.
|
||||
|
||||
2009-01-20 Benjamin Kosnik <bkoz@redhat.com>
|
||||
Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
|
|
|
@ -550,11 +550,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
|
|||
*/
|
||||
class free_list
|
||||
{
|
||||
public:
|
||||
typedef size_t* value_type;
|
||||
typedef __detail::__mini_vector<value_type> vector_type;
|
||||
typedef vector_type::iterator iterator;
|
||||
typedef __mutex __mutex_type;
|
||||
|
||||
private:
|
||||
struct _LT_pointer_compare
|
||||
{
|
||||
bool
|
||||
|
|
Loading…
Reference in New Issue