C++ PATCH for restrict & templates
mark@codesourcery.com
mark@codesourcery.com
Fri May 21 15:54:00 GMT 1999
The following patch, inspired by Nathan's submission this morning,
allows the use of `restrict' with templates, and also improves our
handling of template argument deduction for better standards
compliance.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
1999-05-21 Mark Mitchell <mark@codesourcery.com>
Nathan Sidwell <nathan@acm.org>
* Make-lang.in (cc1plus): Make it depend on gxx.gperf.
* cp-tree.h: Fix typo in documentation on pointers-to-members.
(cp_build_qualified_type): Make it a macro.
(cp_build_qualified_type_real): Declare.
* decl.c (grokdeclarator): Remove misleading comment. Avoid
problem with template parameters and restrict-qualification.
* gxx.gperf: Replace NORID with RID_UNUSED throughout.
* hash.h: Regenerated.
* lex.h (rid): Move RID_FIRST_MODIFIER and RID_LAST_MODIFIER into
the enumeration.
(NORID): Remove definition.
* pt.c (tsubst_aggr_type): Use cp_build_qualified_type_real.
(tsubst): Likewise. Remove special handling for FUNCTION_TYPEs.
(fn_type_unification): Check that the function type resulting from
the deduction is legal.
(check_cv_quals_for_unify): Don't handle FUNCTION_TYPEs specially.
(unify): Use cp_build_qualified_type_real.
* tree.c (build_cplus_array_type_1): Handle error_marks as inputs.
(cp_build_qualified_type): Rename to ...
(cp_build_qualified_type_real): Add additional COMPLAIN parameter
and modify appropriately.
Index: cp/Make-lang.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Make-lang.in,v
retrieving revision 1.34
diff -u -p -r1.34 Make-lang.in
--- Make-lang.in 1999/04/26 23:50:36 1.34
+++ Make-lang.in 1999/05/21 22:29:15
@@ -120,7 +120,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)
$(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
- $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def hash.o
+ $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def $(srcdir)/cp/gxx.gperf hash.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
#
# Build hooks:
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.233
diff -u -p -r1.233 cp-tree.h
--- cp-tree.h 1999/05/20 10:44:33 1.233
+++ cp-tree.h 1999/05/21 22:29:17
@@ -1721,7 +1721,7 @@ extern int flag_new_for_scope;
non-virtual function. Of course, `&f__2B2' is the name of that
function.
- (Of course, the exactl values may differ depending on the mangling
+ (Of course, the exact values may differ depending on the mangling
scheme, sizes of types, and such.). */
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
@@ -2100,7 +2100,6 @@ extern void check_function_format PROTO
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
-extern tree cp_build_qualified_type PROTO((tree, int));
extern tree canonical_type_variant PROTO((tree));
extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */
@@ -3387,6 +3386,9 @@ extern int is_dummy_object PROTO((tree
extern tree search_tree PROTO((tree, tree (*)(tree)));
extern int cp_valid_lang_attribute PROTO((tree, tree, tree, tree));
extern tree make_ptrmem_cst PROTO((tree, tree));
+extern tree cp_build_qualified_type_real PROTO((tree, int, int));
+#define cp_build_qualified_type(TYPE, QUALS) \
+ cp_build_qualified_type_real ((TYPE), (QUALS), /*complain=*/1)
#define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.360
diff -u -p -r1.360 decl.c
--- decl.c 1999/05/20 18:10:25 1.360
+++ decl.c 1999/05/21 22:29:26
@@ -11650,9 +11650,11 @@ grokdeclarator (declarator, declspecs, d
if (RIDBIT_SETP (RID_STATIC, specbits))
DECL_THIS_STATIC (decl) = 1;
- /* Record constancy and volatility. */
- /* FIXME: Disallow `restrict' pointer-to-member declarations. */
- c_apply_type_quals_to_decl (type_quals, decl);
+ /* Record constancy and volatility. There's no need to do this
+ when processing a template; we'll do this for the instantiated
+ declaration based on the type of DECL. */
+ if (!processing_template_decl)
+ c_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
Index: cp/gxx.gperf
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/gxx.gperf,v
retrieving revision 1.8
diff -u -p -r1.8 gxx.gperf
--- gxx.gperf 1999/04/22 17:36:44 1.8
+++ gxx.gperf 1999/05/21 22:29:27
@@ -3,109 +3,109 @@
%}
struct resword { const char *name; short token; enum rid rid;};
%%
-__alignof, ALIGNOF, NORID
-__alignof__, ALIGNOF, NORID
-__asm, ASM_KEYWORD, NORID
-__asm__, ASM_KEYWORD, NORID
-__attribute, ATTRIBUTE, NORID
-__attribute__, ATTRIBUTE, NORID
+__alignof, ALIGNOF, RID_UNUSED
+__alignof__, ALIGNOF, RID_UNUSED
+__asm, ASM_KEYWORD, RID_UNUSED
+__asm__, ASM_KEYWORD, RID_UNUSED
+__attribute, ATTRIBUTE, RID_UNUSED
+__attribute__, ATTRIBUTE, RID_UNUSED
__complex, TYPESPEC, RID_COMPLEX
__complex__, TYPESPEC, RID_COMPLEX
__const, CV_QUALIFIER, RID_CONST
__const__, CV_QUALIFIER, RID_CONST
-__extension__, EXTENSION, NORID
-__imag, IMAGPART, NORID
-__imag__, IMAGPART, NORID
+__extension__, EXTENSION, RID_UNUSED
+__imag, IMAGPART, RID_UNUSED
+__imag__, IMAGPART, RID_UNUSED
__inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE
-__label__, LABEL, NORID
+__label__, LABEL, RID_UNUSED
__null, CONSTANT, RID_NULL
-__real, REALPART, NORID
-__real__, REALPART, NORID
+__real, REALPART, RID_UNUSED
+__real__, REALPART, RID_UNUSED
__restrict, CV_QUALIFIER, RID_RESTRICT
__restrict__, CV_QUALIFIER, RID_RESTRICT
__signature__, AGGR, RID_SIGNATURE /* Extension */,
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
-__sigof__, SIGOF, NORID /* Extension */,
-__typeof, TYPEOF, NORID
-__typeof__, TYPEOF, NORID
+__sigof__, SIGOF, RID_UNUSED /* Extension */,
+__typeof, TYPEOF, RID_UNUSED
+__typeof__, TYPEOF, RID_UNUSED
__volatile, CV_QUALIFIER, RID_VOLATILE
__volatile__, CV_QUALIFIER, RID_VOLATILE
__wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,
-asm, ASM_KEYWORD, NORID,
-and, ANDAND, NORID,
-and_eq, ASSIGN, NORID,
+asm, ASM_KEYWORD, RID_UNUSED,
+and, ANDAND, RID_UNUSED,
+and_eq, ASSIGN, RID_UNUSED,
auto, SCSPEC, RID_AUTO,
-bitand, '&', NORID,
-bitor, '|', NORID,
+bitand, '&', RID_UNUSED,
+bitor, '|', RID_UNUSED,
bool, TYPESPEC, RID_BOOL,
-break, BREAK, NORID,
-case, CASE, NORID,
-catch, CATCH, NORID,
+break, BREAK, RID_UNUSED,
+case, CASE, RID_UNUSED,
+catch, CATCH, RID_UNUSED,
char, TYPESPEC, RID_CHAR,
class, AGGR, RID_CLASS,
-compl, '~', NORID,
+compl, '~', RID_UNUSED,
const, CV_QUALIFIER, RID_CONST,
-const_cast, CONST_CAST, NORID,
-continue, CONTINUE, NORID,
-default, DEFAULT, NORID,
-delete, DELETE, NORID,
-do, DO, NORID,
+const_cast, CONST_CAST, RID_UNUSED,
+continue, CONTINUE, RID_UNUSED,
+default, DEFAULT, RID_UNUSED,
+delete, DELETE, RID_UNUSED,
+do, DO, RID_UNUSED,
double, TYPESPEC, RID_DOUBLE,
-dynamic_cast, DYNAMIC_CAST, NORID,
-else, ELSE, NORID,
-enum, ENUM, NORID,
+dynamic_cast, DYNAMIC_CAST, RID_UNUSED,
+else, ELSE, RID_UNUSED,
+enum, ENUM, RID_UNUSED,
explicit, SCSPEC, RID_EXPLICIT,
export, SCSPEC, RID_EXPORT,
extern, SCSPEC, RID_EXTERN,
-false, CXX_FALSE, NORID,
+false, CXX_FALSE, RID_UNUSED,
float, TYPESPEC, RID_FLOAT,
-for, FOR, NORID,
+for, FOR, RID_UNUSED,
friend, SCSPEC, RID_FRIEND,
-goto, GOTO, NORID,
-if, IF, NORID,
+goto, GOTO, RID_UNUSED,
+if, IF, RID_UNUSED,
inline, SCSPEC, RID_INLINE,
int, TYPESPEC, RID_INT,
long, TYPESPEC, RID_LONG,
mutable, SCSPEC, RID_MUTABLE,
-namespace, NAMESPACE, NORID,
-new, NEW, NORID,
-not, '!', NORID,
-not_eq, EQCOMPARE, NORID,
-operator, OPERATOR, NORID,
-or, OROR, NORID,
-or_eq, ASSIGN, NORID,
+namespace, NAMESPACE, RID_UNUSED,
+new, NEW, RID_UNUSED,
+not, '!', RID_UNUSED,
+not_eq, EQCOMPARE, RID_UNUSED,
+operator, OPERATOR, RID_UNUSED,
+or, OROR, RID_UNUSED,
+or_eq, ASSIGN, RID_UNUSED,
private, VISSPEC, RID_PRIVATE,
protected, VISSPEC, RID_PROTECTED,
public, VISSPEC, RID_PUBLIC,
register, SCSPEC, RID_REGISTER,
-reinterpret_cast, REINTERPRET_CAST, NORID,
-return, RETURN_KEYWORD, NORID,
+reinterpret_cast, REINTERPRET_CAST, RID_UNUSED,
+return, RETURN_KEYWORD, RID_UNUSED,
short, TYPESPEC, RID_SHORT,
signature, AGGR, RID_SIGNATURE /* Extension */,
signed, TYPESPEC, RID_SIGNED,
-sigof, SIGOF, NORID /* Extension */,
-sizeof, SIZEOF, NORID,
+sigof, SIGOF, RID_UNUSED /* Extension */,
+sizeof, SIZEOF, RID_UNUSED,
static, SCSPEC, RID_STATIC,
-static_cast, STATIC_CAST, NORID,
+static_cast, STATIC_CAST, RID_UNUSED,
struct, AGGR, RID_RECORD,
-switch, SWITCH, NORID,
+switch, SWITCH, RID_UNUSED,
template, TEMPLATE, RID_TEMPLATE,
-this, THIS, NORID,
-throw, THROW, NORID,
-true, CXX_TRUE, NORID,
-try, TRY, NORID,
+this, THIS, RID_UNUSED,
+throw, THROW, RID_UNUSED,
+true, CXX_TRUE, RID_UNUSED,
+try, TRY, RID_UNUSED,
typedef, SCSPEC, RID_TYPEDEF,
-typename, TYPENAME_KEYWORD, NORID,
-typeid, TYPEID, NORID,
-typeof, TYPEOF, NORID,
+typename, TYPENAME_KEYWORD, RID_UNUSED,
+typeid, TYPEID, RID_UNUSED,
+typeof, TYPEOF, RID_UNUSED,
union, AGGR, RID_UNION,
unsigned, TYPESPEC, RID_UNSIGNED,
-using, USING, NORID,
+using, USING, RID_UNUSED,
virtual, SCSPEC, RID_VIRTUAL,
void, TYPESPEC, RID_VOID,
volatile, CV_QUALIFIER, RID_VOLATILE,
-while, WHILE, NORID,
-xor, '^', NORID,
-xor_eq, ASSIGN, NORID,
+while, WHILE, RID_UNUSED,
+xor, '^', RID_UNUSED,
+xor_eq, ASSIGN, RID_UNUSED,
Index: cp/lex.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.h,v
retrieving revision 1.6
diff -u -p -r1.6 lex.h
--- lex.h 1998/12/16 21:15:40 1.6
+++ lex.h 1999/05/21 22:29:27
@@ -43,8 +43,9 @@ enum rid
/* This is where grokdeclarator starts its search when setting the specbits.
The first seven are in the order of most frequently used, as found
building libg++. */
+ RID_FIRST_MODIFIER,
- RID_EXTERN,
+ RID_EXTERN = RID_FIRST_MODIFIER,
RID_CONST,
RID_LONG,
RID_TYPEDEF,
@@ -66,6 +67,7 @@ enum rid
RID_COMPLEX,
RID_RESTRICT,
+ RID_LAST_MODIFIER = RID_RESTRICT,
/* This is where grokdeclarator ends its search when setting the
specbits. */
@@ -80,11 +82,6 @@ enum rid
will have to be changed a little. */
RID_MAX
};
-
-#define NORID RID_UNUSED
-
-#define RID_FIRST_MODIFIER RID_EXTERN
-#define RID_LAST_MODIFIER RID_COMPLEX
/* The type that can represent all values of RIDBIT. */
/* We assume that we can stick in at least 32 bits into this. */
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.302
diff -u -p -r1.302 pt.c
--- pt.c 1999/05/21 09:55:46 1.302
+++ pt.c 1999/05/21 22:29:32
@@ -5311,7 +5311,8 @@ tsubst_aggr_type (t, args, complain, in_
{
tree r = build_ptrmemfunc_type
(tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl));
- return cp_build_qualified_type (r, TYPE_QUALS (t));
+ return cp_build_qualified_type_real (r, TYPE_QUALS (t),
+ complain);
}
/* else fall through */
@@ -5349,7 +5350,8 @@ tsubst_aggr_type (t, args, complain, in_
entering_scope);
pop_momentary ();
- return cp_build_qualified_type (r, TYPE_QUALS (t));
+ return cp_build_qualified_type_real (r, TYPE_QUALS (t),
+ complain);
}
else
/* This is not a template type, so there's nothing to do. */
@@ -6208,18 +6210,9 @@ tsubst (t, args, complain, in_decl)
{
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
== 't', 0);
-
- /* If we're not COMPLAINing, don't let an attempt
- to qualify a FUNCTION_TYPE reach
- cp_build_qualified_type. That will result in
- an error message. */
- if (!complain
- && TREE_CODE (arg) == FUNCTION_TYPE
- && CP_TYPE_QUALS (t) != TYPE_UNQUALIFIED)
- return error_mark_node;
-
- return cp_build_qualified_type
- (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t));
+ return cp_build_qualified_type_real
+ (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t),
+ complain);
}
else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
{
@@ -6244,7 +6237,9 @@ tsubst (t, args, complain, in_decl)
argvec, in_decl,
DECL_CONTEXT (arg),
/*entering_scope=*/0);
- return cp_build_qualified_type (r, TYPE_QUALS (t));
+ return cp_build_qualified_type_real (r,
+ TYPE_QUALS (t),
+ complain);
}
else
/* We are processing a template argument list. */
@@ -6411,7 +6406,7 @@ tsubst (t, args, complain, in_decl)
r = build_pointer_type (type);
else
r = build_reference_type (type);
- r = cp_build_qualified_type (r, TYPE_QUALS (t));
+ r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
/* Will this ever be needed for TYPE_..._TO values? */
layout_type (r);
@@ -6553,9 +6548,10 @@ tsubst (t, args, complain, in_decl)
f = make_typename_type (ctx, f);
if (f == error_mark_node)
return f;
- return cp_build_qualified_type (f,
- CP_TYPE_QUALS (f)
- | CP_TYPE_QUALS (t));
+ return cp_build_qualified_type_real (f,
+ CP_TYPE_QUALS (f)
+ | CP_TYPE_QUALS (t),
+ complain);
}
case INDIRECT_REF:
@@ -7388,6 +7384,7 @@ fn_type_unification (fn, explicit_targs,
{
tree parms;
tree fntype;
+ int result;
my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
@@ -7446,9 +7443,25 @@ fn_type_unification (fn, explicit_targs,
because the standard doesn't seem to explicitly prohibit it. Our
callers must be ready to deal with unification failures in any
event. */
- return type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
- targs, parms, args, /*subr=*/0,
- strict, /*allow_incomplete*/1);
+ result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ targs, parms, args, /*subr=*/0,
+ strict, /*allow_incomplete*/1);
+
+ if (result == 0)
+ /* All is well so far. Now, check:
+
+ [temp.deduct]
+
+ When all template arguments have been deduced, all uses of
+ template parameters in nondeduced contexts are replaced with
+ the corresponding deduced argument values. If the
+ substitution results in an invalid type, as described above,
+ type deduction fails. */
+ if (tsubst (TREE_TYPE (fn), targs, /*complain=*/0, NULL_TREE)
+ == error_mark_node)
+ return 1;
+
+ return result;
}
/* Adjust types before performing type deduction, as described in
@@ -8040,11 +8053,6 @@ check_cv_quals_for_unify (strict, arg, p
&& !at_least_as_qualified_p (parm, arg))
return 0;
- /* Don't allow unification to create a qualified function type. */
- if (TREE_CODE (arg) == FUNCTION_TYPE
- && CP_TYPE_QUALS (parm) != TYPE_UNQUALIFIED)
- return 0;
-
return 1;
}
@@ -8198,9 +8206,12 @@ unify (tparms, targs, parm, arg, strict)
/* Consider the case where ARG is `const volatile int' and
PARM is `const T'. Then, T should be `volatile int'. */
arg =
- cp_build_qualified_type (arg,
- CP_TYPE_QUALS (arg)
- & ~CP_TYPE_QUALS (parm));
+ cp_build_qualified_type_real (arg,
+ CP_TYPE_QUALS (arg)
+ & ~CP_TYPE_QUALS (parm),
+ /*complain=*/0);
+ if (arg == error_mark_node)
+ return 1;
}
/* Simple cases: Value already set, does match or doesn't. */
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.113
diff -u -p -r1.113 tree.c
--- tree.c 1999/05/20 10:44:42 1.113
+++ tree.c 1999/05/21 22:29:34
@@ -406,6 +406,9 @@ build_cplus_array_type_1 (elt_type, inde
register struct obstack *ambient_saveable_obstack = saveable_obstack;
tree t;
+ if (elt_type == error_mark_node || index_type == error_mark_node)
+ return error_mark_node;
+
/* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent,
make this permanent too. */
if (TREE_PERMANENT (elt_type)
@@ -453,13 +456,18 @@ build_cplus_array_type (elt_type, index_
return t;
}
-/* Make a variant type in the proper way for C/C++, propagating qualifiers
- down to the element type of an array. */
+/* Make a variant of TYPE, qualified with the TYPE_QUALS. Handles
+ arrays correctly. In particular, if TYPE is an array of T's, and
+ TYPE_QUALS is non-empty, returns an array of qualified T's. If
+ at attempt is made to qualify a type illegally, and COMPLAIN is
+ non-zero, an error is issued. If COMPLAIN is zero, error_mark_node
+ is returned. */
tree
-cp_build_qualified_type (type, type_quals)
+cp_build_qualified_type_real (type, type_quals, complain)
tree type;
int type_quals;
+ int complain;
{
if (type == error_mark_node)
return type;
@@ -467,29 +475,40 @@ cp_build_qualified_type (type, type_qual
/* A restrict-qualified pointer type must be a pointer (or reference)
to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& (!POINTER_TYPE_P (type)
|| TYPE_PTRMEM_P (type)
|| TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
{
- cp_error ("`%T' cannot be `restrict'-qualified", type);
+ if (complain)
+ cp_error ("`%T' cannot be `restrict'-qualified", type);
+ else
+ return error_mark_node;
+
type_quals &= ~TYPE_QUAL_RESTRICT;
}
if (type_quals != TYPE_UNQUALIFIED
&& TREE_CODE (type) == FUNCTION_TYPE)
{
- cp_error ("`%T' cannot be `const'-, `volatile'-, or `restrict'-qualified", type);
+ if (complain)
+ cp_error ("`%T' cannot be `const'-, `volatile'-, or `restrict'-qualified", type);
+ else
+ return error_mark_node;
type_quals = TYPE_UNQUALIFIED;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
tree real_main_variant = TYPE_MAIN_VARIANT (type);
-
+ tree element_type = cp_build_qualified_type_real (TREE_TYPE (type),
+ type_quals,
+ complain);
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
- type = build_cplus_array_type_1 (cp_build_qualified_type
- (TREE_TYPE (type), type_quals),
+ type = build_cplus_array_type_1 (element_type,
TYPE_DOMAIN (type));
+ if (type == error_mark_node)
+ return error_mark_node;
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
make a copy. (TYPE might have come from the hash table and
More information about the Gcc-patches
mailing list