mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-08 17:37:43 +08:00
cp-tree.def (LOOKUP_EXPR): Document.
* cp-tree.def (LOOKUP_EXPR): Document. Remove second argument. * cp-tree.h (DECL_TI_TEMPLATE): Improve documentation. * lex.c (do_identifier): Don't use a second argument, or a type, when building LOOKUP_EXPRs. (do_identifier): Likewise. (do_scoped_id): Likewise. * method.c (hack_identifier): Improve error message. * pt.c (lookup_template_function): Don't needlessly call copy_to_permanent or build_min. (tsubst_copy): Remove #if 0'd code. Tsubst into LOOKUP_EXPRs if necessary. (do_decl_instantiation): Improve error message. * tree.c (mapcar, case LOOKUP_EXPR): Don't be sorry; make a copy. (build_min): Copy the type to the permanent obstack, too. From-SVN: r21544
This commit is contained in:
parent
151ab2f29e
commit
672476cbdf
@ -1,3 +1,20 @@
|
||||
1998-08-02 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* cp-tree.def (LOOKUP_EXPR): Document. Remove second argument.
|
||||
* cp-tree.h (DECL_TI_TEMPLATE): Improve documentation.
|
||||
* lex.c (do_identifier): Don't use a second argument, or a type,
|
||||
when building LOOKUP_EXPRs.
|
||||
(do_identifier): Likewise.
|
||||
(do_scoped_id): Likewise.
|
||||
* method.c (hack_identifier): Improve error message.
|
||||
* pt.c (lookup_template_function): Don't needlessly call
|
||||
copy_to_permanent or build_min.
|
||||
(tsubst_copy): Remove #if 0'd code. Tsubst into LOOKUP_EXPRs if
|
||||
necessary.
|
||||
(do_decl_instantiation): Improve error message.
|
||||
* tree.c (mapcar, case LOOKUP_EXPR): Don't be sorry; make a copy.
|
||||
(build_min): Copy the type to the permanent obstack, too.
|
||||
|
||||
1998-08-01 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* init.c (init_init_processing): Remove BI* handling.
|
||||
|
@ -182,9 +182,14 @@ DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
|
||||
/* A node to remember a source position. */
|
||||
DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
|
||||
|
||||
/* Used to represent deferred name lookup for dependent names while
|
||||
parsing a template declaration. The first argument is an
|
||||
IDENTIFIER_NODE for the name in question. The TREE_TYPE is
|
||||
unused. */
|
||||
DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 1)
|
||||
|
||||
/* A whole bunch of tree codes for the initial, superficial parsing of
|
||||
templates. */
|
||||
DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 2)
|
||||
DEFTREECODE (MODOP_EXPR, "modop_expr", 'e', 3)
|
||||
DEFTREECODE (CAST_EXPR, "cast_expr", '1', 1)
|
||||
DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", '1', 1)
|
||||
|
@ -1265,8 +1265,8 @@ struct lang_decl
|
||||
|
||||
As a special case, for a member friend template of a template
|
||||
class, this value will not be a TEMPLATE_DECL, but rather a
|
||||
LOOKUP_EXPR indicating the name of the template and any explicit
|
||||
template arguments provided. For example, in:
|
||||
LOOKUP_EXPR or IDENTIFIER_NODE indicating the name of the template
|
||||
and any explicit template arguments provided. For example, in:
|
||||
|
||||
template <class T> struct S { friend void f<int>(int, double); }
|
||||
|
||||
|
29
gcc/cp/lex.c
29
gcc/cp/lex.c
@ -2891,7 +2891,7 @@ do_identifier (token, parsing, args)
|
||||
}
|
||||
|
||||
if (current_template_parms)
|
||||
return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
|
||||
return build_min_nt (LOOKUP_EXPR, token);
|
||||
else if (IDENTIFIER_OPNAME_P (token))
|
||||
{
|
||||
if (token != ansi_opname[ERROR_MARK])
|
||||
@ -2988,21 +2988,12 @@ do_identifier (token, parsing, args)
|
||||
else
|
||||
id = hack_identifier (id, token);
|
||||
|
||||
if (current_template_parms)
|
||||
{
|
||||
if (is_overloaded_fn (id))
|
||||
{
|
||||
tree t = build_min (LOOKUP_EXPR, unknown_type_node,
|
||||
token, get_first_fn (id));
|
||||
if (id != IDENTIFIER_NAMESPACE_VALUE (token))
|
||||
TREE_OPERAND (t, 1) = error_mark_node;
|
||||
id = t;
|
||||
}
|
||||
else if (! TREE_PERMANENT (id) || TREE_CODE (id) == PARM_DECL
|
||||
|| TREE_CODE (id) == USING_DECL)
|
||||
id = build_min (LOOKUP_EXPR, TREE_TYPE (id), token, error_mark_node);
|
||||
/* else just use the decl */
|
||||
}
|
||||
if (current_template_parms
|
||||
&& (is_overloaded_fn (id)
|
||||
|| !TREE_PERMANENT (id)
|
||||
|| TREE_CODE (id) == PARM_DECL
|
||||
|| TREE_CODE (id) == USING_DECL))
|
||||
id = build_min_nt (LOOKUP_EXPR, token);
|
||||
|
||||
return id;
|
||||
}
|
||||
@ -3031,7 +3022,7 @@ do_scoped_id (token, parsing)
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
|
||||
id = build_min_nt (LOOKUP_EXPR, token);
|
||||
LOOKUP_EXPR_GLOBAL (id) = 1;
|
||||
return id;
|
||||
}
|
||||
@ -3068,9 +3059,9 @@ do_scoped_id (token, parsing)
|
||||
{
|
||||
if (is_overloaded_fn (id))
|
||||
{
|
||||
id = build_min (LOOKUP_EXPR, unknown_type_node,
|
||||
token, get_first_fn (id));
|
||||
id = build_min_nt (LOOKUP_EXPR, token);
|
||||
LOOKUP_EXPR_GLOBAL (id) = 1;
|
||||
return id;
|
||||
}
|
||||
/* else just use the decl */
|
||||
}
|
||||
|
@ -1845,8 +1845,16 @@ hack_identifier (value, name)
|
||||
{
|
||||
if (current_class_ptr == NULL_TREE)
|
||||
{
|
||||
error ("request for member `%s' in static member function",
|
||||
IDENTIFIER_POINTER (DECL_NAME (value)));
|
||||
if (current_function_decl
|
||||
&& DECL_STATIC_FUNCTION_P (current_function_decl))
|
||||
cp_error ("invalid use of member `%D' in static member function",
|
||||
value);
|
||||
else
|
||||
/* We can get here when processing a bad default
|
||||
argument, like:
|
||||
struct S { int a; void f(int i = a); } */
|
||||
cp_error ("invalid use of member `%D'", value);
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
TREE_USED (current_class_ptr) = 1;
|
||||
|
42
gcc/cp/pt.c
42
gcc/cp/pt.c
@ -2999,14 +2999,14 @@ lookup_template_function (fns, arglist)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (arglist != NULL_TREE && !TREE_PERMANENT (arglist))
|
||||
copy_to_permanent (arglist);
|
||||
|
||||
type = TREE_TYPE (fns);
|
||||
if (TREE_CODE (fns) == OVERLOAD || !type)
|
||||
type = unknown_type_node;
|
||||
|
||||
return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
|
||||
if (processing_template_decl)
|
||||
return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
|
||||
else
|
||||
return build (TEMPLATE_ID_EXPR, type, fns, arglist);
|
||||
}
|
||||
|
||||
/* Within the scope of a template class S<T>, the name S gets bound
|
||||
@ -5469,11 +5469,25 @@ tsubst_copy (t, args, in_decl)
|
||||
else
|
||||
return t;
|
||||
|
||||
#if 0
|
||||
case IDENTIFIER_NODE:
|
||||
return do_identifier (t, 0);
|
||||
#endif
|
||||
|
||||
case LOOKUP_EXPR:
|
||||
{
|
||||
/* We must tsbust into a LOOKUP_EXPR in case the names to
|
||||
which it refers is a conversion operator; in that case the
|
||||
name will change. We avoid making unnecessary copies,
|
||||
however. */
|
||||
|
||||
tree id = tsubst_copy (TREE_OPERAND (t, 0), args, in_decl);
|
||||
|
||||
if (id != TREE_OPERAND (t, 0))
|
||||
{
|
||||
tree r = build_nt (LOOKUP_EXPR, id);
|
||||
LOOKUP_EXPR_GLOBAL (r) = LOOKUP_EXPR_GLOBAL (t);
|
||||
t = r;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
case CAST_EXPR:
|
||||
case REINTERPRET_CAST_EXPR:
|
||||
case CONST_CAST_EXPR:
|
||||
@ -7236,6 +7250,16 @@ do_decl_instantiation (declspecs, declarator, storage)
|
||||
cp_error ("explicit instantiation of `%#D'", decl);
|
||||
return;
|
||||
}
|
||||
else if (DECL_TEMPLATE_SPECIALIZATION (decl))
|
||||
/* [temp.spec]
|
||||
|
||||
No program shall both explicit instantiation and explicit
|
||||
specialize a template. */
|
||||
{
|
||||
cp_error ("explicit instantiation of `%#D' after", decl);
|
||||
cp_error_at ("explicit specialization here", decl);
|
||||
return;
|
||||
}
|
||||
else if (DECL_TEMPLATE_INSTANTIATION (decl))
|
||||
result = decl;
|
||||
|
||||
|
@ -1784,6 +1784,11 @@ mapcar (t, func)
|
||||
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
|
||||
return t;
|
||||
|
||||
case LOOKUP_EXPR:
|
||||
t = copy_node (t);
|
||||
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
|
||||
return t;
|
||||
|
||||
case RECORD_TYPE:
|
||||
if (TYPE_PTRMEMFUNC_P (t))
|
||||
return build_ptrmemfunc_type
|
||||
@ -2022,7 +2027,7 @@ build_min VPROTO((enum tree_code code, tree tt, ...))
|
||||
|
||||
t = make_node (code);
|
||||
length = tree_code_length[(int) code];
|
||||
TREE_TYPE (t) = tt;
|
||||
TREE_TYPE (t) = copy_to_permanent (tt);
|
||||
TREE_COMPLEXITY (t) = lineno;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
|
15
gcc/testsuite/g++.old-deja/g++.pt/conv2.C
Normal file
15
gcc/testsuite/g++.old-deja/g++.pt/conv2.C
Normal file
@ -0,0 +1,15 @@
|
||||
// Build don't link:
|
||||
|
||||
template<class T>
|
||||
class A {
|
||||
public:
|
||||
operator const T*() const;
|
||||
const T* cast() const;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
const T* A<T>::cast() const {
|
||||
return operator const T*();
|
||||
}
|
||||
|
||||
template class A<char>;
|
5
gcc/testsuite/g++.old-deja/g++.pt/spec19.C
Normal file
5
gcc/testsuite/g++.old-deja/g++.pt/spec19.C
Normal file
@ -0,0 +1,5 @@
|
||||
// Build don't link:
|
||||
|
||||
template<class T> T f(T o) { return o; }
|
||||
template<> int f(int o) { return o; } // ERROR - after specialization
|
||||
template int f(int); // ERROR - explicit instantiation
|
Loading…
Reference in New Issue
Block a user