mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-19 04:18:56 +08:00
PR c++/7347, c++/7348
PR c++/7347, c++/7348 * cp-tree.h (tsubst_flags_t): Add tf_parsing. * decl.c (make_typename_type): Use it. (make_unbound_class_template): Likewise. (lookup_name_real): Don't call type_access_control if scope is template parameter dependent. * parse.y (template_arg): Call make_unbound_class_template with tf_parsing set. (nest_name_specifier): Call make_typename_type with tf_parsing set. (typename_sub0): Likewise. (typename_sub1): Likewise. (instantiate_decl): Push class scope. * pt.c (regenerate_decl_from_template): Call pushclass and popclass for both static variable and member function template. (instantiate_decl) Call pushclass and popclass when tsubst'ing type and arguments. * search.c (type_access_control): Do type access for TEMPLATE_DECL too. * g++.dg/template/access4.C: New test. * g++.dg/template/access5.C: New test. * g++.old-deja/g++.pt/memtemp85.C: Fix access problem. * g++.old-deja/g++.pt/memtemp86.C: Likewise. * g++.old-deja/g++.pt/ttp58.C: Likewise. * g++.old-deja/g++.pt/memtemp89.C: Remove XFAIL. From-SVN: r55649
This commit is contained in:
parent
0d541696aa
commit
0e902d98ae
gcc
@ -1,3 +1,24 @@
|
||||
2002-07-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/7347, c++/7348
|
||||
* cp-tree.h (tsubst_flags_t): Add tf_parsing.
|
||||
* decl.c (make_typename_type): Use it.
|
||||
(make_unbound_class_template): Likewise.
|
||||
(lookup_name_real): Don't call type_access_control if scope is
|
||||
template parameter dependent.
|
||||
* parse.y (template_arg): Call make_unbound_class_template with
|
||||
tf_parsing set.
|
||||
(nest_name_specifier): Call make_typename_type with tf_parsing set.
|
||||
(typename_sub0): Likewise.
|
||||
(typename_sub1): Likewise.
|
||||
(instantiate_decl): Push class scope.
|
||||
* pt.c (regenerate_decl_from_template): Call pushclass and popclass
|
||||
for both static variable and member function template.
|
||||
(instantiate_decl) Call pushclass and popclass when tsubst'ing type
|
||||
and arguments.
|
||||
* search.c (type_access_control): Do type access for TEMPLATE_DECL
|
||||
too.
|
||||
|
||||
2002-07-20 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* decl2.c (cxx_decode_option): Simplify -fhandle-exceptions
|
||||
|
@ -3187,8 +3187,10 @@ typedef enum tsubst_flags_t {
|
||||
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
|
||||
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. */
|
||||
|
@ -5659,8 +5659,10 @@ make_typename_type (context, name, complain)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (!enforce_access (context, tmpl))
|
||||
return error_mark_node;
|
||||
if (complain & tf_parsing)
|
||||
type_access_control (context, tmpl);
|
||||
else
|
||||
enforce_access (context, tmpl);
|
||||
|
||||
return lookup_template_class (tmpl,
|
||||
TREE_OPERAND (fullname, 1),
|
||||
@ -5682,8 +5684,10 @@ make_typename_type (context, name, complain)
|
||||
t = lookup_field (context, name, 0, 1);
|
||||
if (t)
|
||||
{
|
||||
if (!enforce_access (context, t))
|
||||
return error_mark_node;
|
||||
if (complain & tf_parsing)
|
||||
type_access_control (context, t);
|
||||
else
|
||||
enforce_access (context, t);
|
||||
|
||||
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
|
||||
t = TREE_TYPE (t);
|
||||
@ -5712,7 +5716,6 @@ make_typename_type (context, name, complain)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
|
||||
return build_typename_type (context, name, fullname, NULL_TREE);
|
||||
}
|
||||
|
||||
@ -5752,8 +5755,10 @@ make_unbound_class_template (context, name, complain)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (!enforce_access (context, tmpl))
|
||||
return error_mark_node;
|
||||
if (complain & tf_parsing)
|
||||
type_access_control (context, tmpl);
|
||||
else
|
||||
enforce_access (context, tmpl);
|
||||
|
||||
return tmpl;
|
||||
}
|
||||
@ -6078,7 +6083,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
|
||||
else
|
||||
{
|
||||
val = lookup_member (type, name, 0, prefer_type);
|
||||
type_access_control (type, val);
|
||||
if (!uses_template_parms (type))
|
||||
type_access_control (type, val);
|
||||
|
||||
/* Restore the containing TYPENAME_TYPE if we looked
|
||||
through it before. */
|
||||
|
@ -1159,7 +1159,7 @@ template_arg:
|
||||
$$ = error_mark_node;
|
||||
}
|
||||
else
|
||||
$$ = make_unbound_class_template ($1, $3, 1);
|
||||
$$ = make_unbound_class_template ($1, $3, tf_error | tf_parsing);
|
||||
}
|
||||
;
|
||||
|
||||
@ -3071,14 +3071,14 @@ nested_name_specifier:
|
||||
{ $$ = $2; }
|
||||
| nested_name_specifier TEMPLATE explicit_template_type SCOPE
|
||||
{ got_scope = $$
|
||||
= make_typename_type ($1, $3, tf_error); }
|
||||
= make_typename_type ($1, $3, tf_error | tf_parsing); }
|
||||
/* Error handling per Core 125. */
|
||||
| nested_name_specifier IDENTIFIER SCOPE
|
||||
{ got_scope = $$
|
||||
= make_typename_type ($1, $2, tf_error); }
|
||||
= make_typename_type ($1, $2, tf_error | tf_parsing); }
|
||||
| nested_name_specifier PTYPENAME SCOPE
|
||||
{ got_scope = $$
|
||||
= make_typename_type ($1, $2, tf_error); }
|
||||
= make_typename_type ($1, $2, tf_error | tf_parsing); }
|
||||
;
|
||||
|
||||
/* Why the @#$%^& do type_name and notype_identifier need to be expanded
|
||||
@ -3120,7 +3120,7 @@ typename_sub0:
|
||||
typename_sub1 identifier %prec EMPTY
|
||||
{
|
||||
if (TYPE_P ($1))
|
||||
$$ = make_typename_type ($1, $2, tf_error);
|
||||
$$ = make_typename_type ($1, $2, tf_error | tf_parsing);
|
||||
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
||||
error ("`%T' is not a class or namespace", $2);
|
||||
else
|
||||
@ -3133,9 +3133,9 @@ typename_sub0:
|
||||
| typename_sub1 template_type %prec EMPTY
|
||||
{ $$ = TREE_TYPE ($2); }
|
||||
| typename_sub1 explicit_template_type %prec EMPTY
|
||||
{ $$ = make_typename_type ($1, $2, tf_error); }
|
||||
{ $$ = make_typename_type ($1, $2, tf_error | tf_parsing); }
|
||||
| typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
|
||||
{ $$ = make_typename_type ($1, $3, tf_error); }
|
||||
{ $$ = make_typename_type ($1, $3, tf_error | tf_parsing); }
|
||||
;
|
||||
|
||||
typename_sub1:
|
||||
@ -3149,7 +3149,7 @@ typename_sub1:
|
||||
| typename_sub1 typename_sub2
|
||||
{
|
||||
if (TYPE_P ($1))
|
||||
$$ = make_typename_type ($1, $2, tf_error);
|
||||
$$ = make_typename_type ($1, $2, tf_error | tf_parsing);
|
||||
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
||||
error ("`%T' is not a class or namespace", $2);
|
||||
else
|
||||
@ -3161,10 +3161,10 @@ typename_sub1:
|
||||
}
|
||||
| typename_sub1 explicit_template_type SCOPE
|
||||
{ got_scope = $$
|
||||
= make_typename_type ($1, $2, tf_error); }
|
||||
= make_typename_type ($1, $2, tf_error | tf_parsing); }
|
||||
| typename_sub1 TEMPLATE explicit_template_type SCOPE
|
||||
{ got_scope = $$
|
||||
= make_typename_type ($1, $3, tf_error); }
|
||||
= make_typename_type ($1, $3, tf_error | tf_parsing); }
|
||||
;
|
||||
|
||||
/* This needs to return a TYPE_DECL for simple names so that we don't
|
||||
|
18
gcc/cp/pt.c
18
gcc/cp/pt.c
@ -9844,10 +9844,10 @@ regenerate_decl_from_template (decl, tmpl)
|
||||
register_specialization for it. */
|
||||
my_friendly_assert (unregistered, 0);
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
if (DECL_CLASS_SCOPE_P (decl))
|
||||
/* Make sure that we can see identifiers, and compute access
|
||||
correctly, for the class members used in the declaration of
|
||||
this static variable. */
|
||||
this static variable or function. */
|
||||
pushclass (DECL_CONTEXT (decl), 2);
|
||||
|
||||
/* Do the substitution to get the new declaration. */
|
||||
@ -9859,8 +9859,6 @@ regenerate_decl_from_template (decl, tmpl)
|
||||
DECL_INITIAL (new_decl) =
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tf_error, DECL_TI_TEMPLATE (decl));
|
||||
/* Pop the class context we pushed above. */
|
||||
popclass ();
|
||||
}
|
||||
else if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
@ -9871,6 +9869,10 @@ regenerate_decl_from_template (decl, tmpl)
|
||||
DECL_INITIAL (decl) = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Pop the class context we pushed above. */
|
||||
if (DECL_CLASS_SCOPE_P (decl))
|
||||
popclass ();
|
||||
|
||||
/* The immediate parent of the new template is still whatever it was
|
||||
before, even though tsubst sets DECL_TI_TEMPLATE up as the most
|
||||
general template. We also reset the DECL_ASSEMBLER_NAME since
|
||||
@ -10052,6 +10054,11 @@ instantiate_decl (d, defer_ok)
|
||||
tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
|
||||
tree type = TREE_TYPE (gen);
|
||||
|
||||
/* Make sure that we can see identifiers, and compute access
|
||||
correctly. */
|
||||
if (DECL_CLASS_SCOPE_P (d))
|
||||
pushclass (DECL_CONTEXT (d), 1);
|
||||
|
||||
if (TREE_CODE (gen) == FUNCTION_DECL)
|
||||
{
|
||||
tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d);
|
||||
@ -10064,6 +10071,9 @@ instantiate_decl (d, defer_ok)
|
||||
type = TREE_TYPE (type);
|
||||
}
|
||||
tsubst (type, args, tf_error | tf_warning, d);
|
||||
|
||||
if (DECL_CLASS_SCOPE_P (d))
|
||||
popclass ();
|
||||
}
|
||||
|
||||
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
|
||||
|
@ -971,8 +971,8 @@ friend_accessible_p (scope, decl, binfo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform access control on TYPE_DECL VAL, which was looked up in TYPE.
|
||||
This is fairly complex, so here's the design:
|
||||
/* Perform access control on TYPE_DECL or TEMPLATE_DECL VAL, which was
|
||||
looked up in TYPE. This is fairly complex, so here's the design:
|
||||
|
||||
The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
|
||||
start to process a top-level declaration.
|
||||
@ -995,7 +995,8 @@ void
|
||||
type_access_control (type, val)
|
||||
tree type, val;
|
||||
{
|
||||
if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL
|
||||
if (val == NULL_TREE
|
||||
|| (TREE_CODE (val) != TEMPLATE_DECL && TREE_CODE (val) != TYPE_DECL)
|
||||
|| ! DECL_CLASS_SCOPE_P (val))
|
||||
return;
|
||||
|
||||
|
@ -1,3 +1,13 @@
|
||||
2002-07-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/7347, c++/7348
|
||||
* g++.dg/template/access4.C: New test.
|
||||
* g++.dg/template/access5.C: New test.
|
||||
* g++.old-deja/g++.pt/memtemp85.C: Fix access problem.
|
||||
* g++.old-deja/g++.pt/memtemp86.C: Likewise.
|
||||
* g++.old-deja/g++.pt/ttp58.C: Likewise.
|
||||
* g++.old-deja/g++.pt/memtemp89.C: Remove XFAIL.
|
||||
|
||||
2002-07-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.dg/gnu89-init-2.c: New test.
|
||||
|
18
gcc/testsuite/g++.dg/template/access4.C
Normal file
18
gcc/testsuite/g++.dg/template/access4.C
Normal file
@ -0,0 +1,18 @@
|
||||
// { dg-do compile }
|
||||
// Origin: Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
|
||||
|
||||
// PR c++/7347
|
||||
// Access control for typename during instantiation
|
||||
|
||||
template <int dim> class Base {
|
||||
protected:
|
||||
typedef int T;
|
||||
};
|
||||
|
||||
template <int dim> class D : public Base<dim> {
|
||||
public:
|
||||
typedef typename Base<dim>::T T1;
|
||||
D (T1 t);
|
||||
};
|
||||
|
||||
D<2> d(1);
|
21
gcc/testsuite/g++.dg/template/access5.C
Normal file
21
gcc/testsuite/g++.dg/template/access5.C
Normal file
@ -0,0 +1,21 @@
|
||||
// { dg-do compile }
|
||||
// Origin: Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
|
||||
|
||||
// PR c++/7348
|
||||
// Access control for typename in function return type
|
||||
|
||||
class Outer {
|
||||
template <int dim> struct Inner {
|
||||
typedef int T;
|
||||
T foo ();
|
||||
};
|
||||
public:
|
||||
Outer();
|
||||
};
|
||||
|
||||
template <int dim>
|
||||
typename Outer::Inner<dim>::T Outer::Inner<dim>::foo () {
|
||||
return 1;
|
||||
};
|
||||
|
||||
template Outer::Inner<2>;
|
@ -4,7 +4,7 @@
|
||||
// by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc.
|
||||
// Copyright (C) 1999 Free Software Foundation
|
||||
|
||||
class Q {
|
||||
struct Q {
|
||||
template<class>
|
||||
class X {
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
// by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc.
|
||||
// Copyright (C) 1999 Free Software Foundation
|
||||
|
||||
class Q {
|
||||
struct Q {
|
||||
template<class>
|
||||
class X {
|
||||
};
|
||||
|
@ -5,11 +5,11 @@
|
||||
|
||||
class Q {
|
||||
template<class T>
|
||||
class X {
|
||||
class X { // ERROR - Q::X private
|
||||
};
|
||||
};
|
||||
template<template<class> class XX>
|
||||
class Y {
|
||||
XX<int> x_; // ERROR - Q::X inaccessible XFAIL *-*-*
|
||||
XX<int> x_;
|
||||
};
|
||||
Y<Q::X> y; // ERROR - instantiated from here XFAIL *-*-*
|
||||
Y<Q::X> y; // ERROR - instantiated from here
|
||||
|
@ -15,7 +15,7 @@ struct Z
|
||||
const static int value_ = false;
|
||||
};
|
||||
|
||||
class Outer
|
||||
struct Outer
|
||||
{
|
||||
template <class T>
|
||||
struct A :
|
||||
|
Loading…
Reference in New Issue
Block a user