[C++ PATCH] Deferred access checking & template instantiation
Kriang Lerdsuwanakij
lerdsuwa@users.sourceforge.net
Sat Jan 18 17:35:00 GMT 2003
Hi
The appended patch extends my earlier deferred access check
infrastructure to template instantiation. Now make_typename_type
and such no longer need to know whether they are called from
the parser. The 'tf_parsing' flag is now removed as well.
Bootstrapped and tested on i686-pc-linux-gnu with no regressions.
OK for the main trunk?
--Kriang
2003-01-19 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* cp-tree.h (tsubst_flags_t): Remove tf_parsing.
* decl.c (make_typename_type): Adjust.
(make_unbound_class_template): Likewise.
* parser.c (cp_parser_postfix_expression): Use tf_error.
(cp_parser_elaborated_type_specifier): Likewise.
(cp_parser_lookup_name): Likewise.
(cp_parser_class_name): Use tf_error. Remove tf_parsing.
(cp_parser_template_argument): Remove tf_parsing.
* pt.c (instantiate_class_template): Disable deferred
access checks.
2003-01-19 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.dg/template/access8.C: New test.
* g++.dg/template/access9.C: New test.
diff -cprN gcc-main-save/gcc/cp/cp-tree.h gcc-main-new/gcc/cp/cp-tree.h
*** gcc-main-save/gcc/cp/cp-tree.h Fri Jan 17 19:13:57 2003
--- gcc-main-new/gcc/cp/cp-tree.h Sat Jan 18 22:52:00 2003
*************** typedef enum tsubst_flags_t {
*** 3120,3129 ****
tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
tf_keep_type_decl = 1 << 4, /* retain typedef type decls
(make_typename_type use) */
! tf_ptrmem_ok = 1 << 5, /* pointers to member ok (internal
instantiate_type use) */
- tf_parsing = 1 << 6 /* called from parser
- (make_typename_type use) */
} tsubst_flags_t;
/* The kind of checking we can do looking in a class hierarchy. */
--- 3120,3127 ----
tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
tf_keep_type_decl = 1 << 4, /* retain typedef type decls
(make_typename_type use) */
! tf_ptrmem_ok = 1 << 5 /* pointers to member ok (internal
instantiate_type use) */
} tsubst_flags_t;
/* The kind of checking we can do looking in a class hierarchy. */
diff -cprN gcc-main-save/gcc/cp/decl.c gcc-main-new/gcc/cp/decl.c
*** gcc-main-save/gcc/cp/decl.c Fri Jan 17 19:13:59 2003
--- gcc-main-new/gcc/cp/decl.c Sat Jan 18 22:48:56 2003
*************** make_typename_type (tree context, tree n
*** 5533,5544 ****
}
if (complain & tf_error)
! {
! if (complain & tf_parsing)
! perform_or_defer_access_check (context, tmpl);
! else
! enforce_access (context, tmpl);
! }
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
--- 5533,5539 ----
}
if (complain & tf_error)
! perform_or_defer_access_check (context, tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
*************** make_typename_type (tree context, tree n
*** 5568,5579 ****
}
if (complain & tf_error)
! {
! if (complain & tf_parsing)
! perform_or_defer_access_check (context, t);
! else
! enforce_access (context, t);
! }
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
--- 5563,5569 ----
}
if (complain & tf_error)
! perform_or_defer_access_check (context, t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
*************** make_unbound_class_template (tree contex
*** 5630,5641 ****
}
if (complain & tf_error)
! {
! if (complain & tf_parsing)
! perform_or_defer_access_check (context, tmpl);
! else
! enforce_access (context, tmpl);
! }
return tmpl;
}
--- 5620,5626 ----
}
if (complain & tf_error)
! perform_or_defer_access_check (context, tmpl);
return tmpl;
}
diff -cprN gcc-main-save/gcc/cp/parser.c gcc-main-new/gcc/cp/parser.c
*** gcc-main-save/gcc/cp/parser.c Fri Jan 17 19:13:59 2003
--- gcc-main-new/gcc/cp/parser.c Sat Jan 18 22:55:24 2003
*************** cp_parser_postfix_expression (cp_parser
*** 3939,3946 ****
id = cp_parser_identifier (parser);
/* Create a TYPENAME_TYPE to represent the type to which the
functional cast is being performed. */
! type = make_typename_type (parser->scope, id,
! /*complain=*/1);
postfix_expression = cp_parser_functional_cast (parser, type);
}
--- 3939,3945 ----
id = cp_parser_identifier (parser);
/* Create a TYPENAME_TYPE to represent the type to which the
functional cast is being performed. */
! type = make_typename_type (parser->scope, id, tf_error);
postfix_expression = cp_parser_functional_cast (parser, type);
}
*************** cp_parser_template_argument (parser)
*** 8444,8450 ****
if (template_p)
argument = make_unbound_class_template (TREE_OPERAND (argument, 0),
TREE_OPERAND (argument, 1),
! tf_error | tf_parsing);
else if (TREE_CODE (argument) != TEMPLATE_DECL)
cp_parser_error (parser, "expected template-name");
}
--- 8443,8449 ----
if (template_p)
argument = make_unbound_class_template (TREE_OPERAND (argument, 0),
TREE_OPERAND (argument, 1),
! tf_error);
else if (TREE_CODE (argument) != TEMPLATE_DECL)
cp_parser_error (parser, "expected template-name");
}
*************** cp_parser_elaborated_type_specifier (par
*** 9024,9031 ****
template will correspond to a class. */
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& tag_type == typename_type)
! type = make_typename_type (parser->scope, decl,
! /*complain=*/1);
else
type = TREE_TYPE (decl);
}
--- 9023,9029 ----
template will correspond to a class. */
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& tag_type == typename_type)
! type = make_typename_type (parser->scope, decl, tf_error);
else
type = TREE_TYPE (decl);
}
*************** cp_parser_elaborated_type_specifier (par
*** 9040,9047 ****
/* For a `typename', we needn't call xref_tag. */
if (tag_type == typename_type)
! return make_typename_type (parser->scope, identifier,
! /*complain=*/1);
/* Look up a qualified name in the usual way. */
if (parser->scope)
{
--- 9038,9045 ----
/* For a `typename', we needn't call xref_tag. */
if (tag_type == typename_type)
! return make_typename_type (parser->scope, identifier, tf_error);
!
/* Look up a qualified name in the usual way. */
if (parser->scope)
{
*************** cp_parser_class_name (cp_parser *parser,
*** 11558,11565 ****
/* If this is a typename, create a TYPENAME_TYPE. */
if (typename_p && decl != error_mark_node)
! decl = TYPE_NAME (make_typename_type (scope, decl,
! /*complain=*/1));
/* Check to see that it is really the name of a class. */
if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
--- 11556,11562 ----
/* If this is a typename, create a TYPENAME_TYPE. */
if (typename_p && decl != error_mark_node)
! decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
/* Check to see that it is really the name of a class. */
if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
*************** cp_parser_class_name (cp_parser *parser,
*** 11575,11582 ****
standard does not seem to be definitive, but there is no other
valid interpretation of the following `::'. Therefore, those
names are considered class-names. */
! decl = TYPE_NAME (make_typename_type (scope, decl,
! tf_error | tf_parsing));
else if (decl == error_mark_node
|| TREE_CODE (decl) != TYPE_DECL
|| !IS_AGGR_TYPE (TREE_TYPE (decl)))
--- 11572,11578 ----
standard does not seem to be definitive, but there is no other
valid interpretation of the following `::'. Therefore, those
names are considered class-names. */
! decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
else if (decl == error_mark_node
|| TREE_CODE (decl) != TYPE_DECL
|| !IS_AGGR_TYPE (TREE_TYPE (decl)))
*************** cp_parser_lookup_name (cp_parser *parser
*** 13481,13487 ****
dependent. */
decl = TYPE_NAME (make_typename_type (parser->scope,
name,
! /*complain=*/1));
}
else
{
--- 13477,13483 ----
dependent. */
decl = TYPE_NAME (make_typename_type (parser->scope,
name,
! tf_error));
}
else
{
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Fri Jan 17 19:13:59 2003
--- gcc-main-new/gcc/cp/pt.c Sat Jan 18 23:11:35 2003
*************** instantiate_class_template (type)
*** 5192,5197 ****
--- 5192,5201 ----
the process of being defined. */
TYPE_BEING_DEFINED (type) = 1;
+ /* We may be in the middle of deferred access check. Disable
+ it now. */
+ push_deferring_access_checks (false);
+
maybe_push_to_top_level (uses_template_parms (type));
if (t)
*************** instantiate_class_template (type)
*** 5521,5526 ****
--- 5525,5531 ----
popclass ();
pop_from_top_level ();
+ pop_deferring_access_checks ();
pop_tinst_level ();
if (TYPE_CONTAINS_VPTR_P (type))
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/access8.C gcc-main-new/gcc/testsuite/g++.dg/template/access8.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/access8.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/access8.C Sat Jan 18 23:33:10 2003
***************
*** 0 ****
--- 1,16 ----
+ // Copyright (C) 2003 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ // Template instantiate during deferred access check
+
+ template <class T> struct C {
+ typedef typename T::X Y;
+ };
+
+ class A {
+ typedef int X;
+ template <class T> friend struct C;
+ };
+
+ C<A>::Y f(int);
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/access9.C gcc-main-new/gcc/testsuite/g++.dg/template/access9.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/access9.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/access9.C Sat Jan 18 23:33:14 2003
***************
*** 0 ****
--- 1,19 ----
+ // Copyright (C) 2003 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+ // { dg-do compile }
+
+ // Template instantiate during deferred access check
+
+ template <void (*)(int)> struct C {
+ typedef int Y;
+ };
+
+ template <class T> void f(typename T::X) {
+ }
+
+ class A {
+ typedef int X;
+ template <class T> friend void f(typename T::X);
+ };
+
+ C<&f<A> >::Y g(int);
More information about the Gcc-patches
mailing list