* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@21544
138bc75d-0d04-0410-961f-
82ee72b054a4
+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.
/* 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)
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); }
}
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])
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;
}
{
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;
}
{
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 */
}
{
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;
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
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:
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;
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
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++)
--- /dev/null
+// 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>;
--- /dev/null
+// 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