diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2002-02-22 11:57:52 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2002-02-22 11:57:52 +0000 |
commit | 4f2b0fb25ec488b47631bf988c8d099524caddb5 (patch) | |
tree | 15da02c0132151ee69a9aaeb4e66a7b7b3df0c9e | |
parent | 54fec3d54ad98245f71154255bd77099f39f9edb (diff) | |
download | gcc-4f2b0fb25ec488b47631bf988c8d099524caddb5.zip gcc-4f2b0fb25ec488b47631bf988c8d099524caddb5.tar.gz gcc-4f2b0fb25ec488b47631bf988c8d099524caddb5.tar.bz2 |
PR c++/2645, DR 295
cp:
PR c++/2645, DR 295
* cp-tree.h (tsubst_flags_t): Add tf_ignore_bad_quals,
tf_keep_type_decl.
(make_typename_type): Use tsubst_flags_t.
* decl.c (make_typename_type): Adjust. Return non-artificial
TYPE_DECLs, if required.
(grokdeclarator): Simplify CVR qualification handling. Allow bad
qualifiers on typedef types.
* decl2.c (handle_class_head): Adjust make_typename_type call.
* parse.y (nested_name_specifier): Likewise.
(typename_sub0): Likewise.
(typename_sub1): Likewise.
* pt.c (convert_template_argument): Adjust make_typename_type
return value.
(tsubst): Adjust cp_build_qualified_type_real calls.
(check_cv_quals_for_unify): Cope with alowing bad qualifications
on template type parms.
(instantiate_decl): Recheck substitutions to give warnings on bad
qualifications.
* tree.c (cp_build_qualified_type_real): Use tf_allow_bad_quals.
testsuite:
* g++.dg/template/qualttp19.C: New test.
* g++.dg/template/qualttp20.C: New test.
* g++.old-deja/g++.jason/report.C: Adjust expected errors
* g++.old-deja/g++.other/qual1.C: Likewise.
From-SVN: r49961
-rw-r--r-- | gcc/cp/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 99 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/cp/parse.y | 18 | ||||
-rw-r--r-- | gcc/cp/pt.c | 64 | ||||
-rw-r--r-- | gcc/cp/tree.c | 78 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/qualttp19.C | 41 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/qualttp20.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.jason/report.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/qual1.C | 5 |
12 files changed, 287 insertions, 95 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 69e2332..31fc320 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,26 @@ +2002-02-22 Nathan Sidwell <nathan@codesourcery.com> + + PR c++/2645, DR 295 + * cp-tree.h (tsubst_flags_t): Add tf_ignore_bad_quals, + tf_keep_type_decl. + (make_typename_type): Use tsubst_flags_t. + * decl.c (make_typename_type): Adjust. Return non-artificial + TYPE_DECLs, if required. + (grokdeclarator): Simplify CVR qualification handling. Allow bad + qualifiers on typedef types. + * decl2.c (handle_class_head): Adjust make_typename_type call. + * parse.y (nested_name_specifier): Likewise. + (typename_sub0): Likewise. + (typename_sub1): Likewise. + * pt.c (convert_template_argument): Adjust make_typename_type + return value. + (tsubst): Adjust cp_build_qualified_type_real calls. + (check_cv_quals_for_unify): Cope with alowing bad qualifications + on template type parms. + (instantiate_decl): Recheck substitutions to give warnings on bad + qualifications. + * tree.c (cp_build_qualified_type_real): Use tf_allow_bad_quals. + 2002-02-21 Aldy Hernandez <aldyh@redhat.com> * cp/decl.c (duplicate_decls): Merge always_inline attribute. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 169d1a2..ad82612 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3070,7 +3070,10 @@ typedef enum tsubst_flags_t { tf_warning = 1 << 1, /* give warnings too */ tf_no_attributes = 1 << 2, /* ignore attributes on comparisons (instantiate_type use) */ - tf_ptrmem_ok = 1 << 3 /* pointers to member ok (internal + 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; @@ -3693,7 +3696,7 @@ extern tree namespace_binding PARAMS ((tree, tree)); extern void set_namespace_binding PARAMS ((tree, tree, tree)); extern tree lookup_namespace_name PARAMS ((tree, tree)); extern tree build_typename_type PARAMS ((tree, tree, tree, tree)); -extern tree make_typename_type PARAMS ((tree, tree, int)); +extern tree make_typename_type PARAMS ((tree, tree, tsubst_flags_t)); extern tree make_unbound_class_template PARAMS ((tree, tree, int)); extern tree lookup_name_nonclass PARAMS ((tree)); extern tree lookup_function_nonclass PARAMS ((tree, tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a91b3da..4d912cd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5609,12 +5609,15 @@ build_typename_type (context, name, fullname, base_type) /* Resolve `typename CONTEXT::NAME'. Returns an appropriate type, unless an error occurs, in which case error_mark_node is returned. - If COMPLAIN zero, don't complain about any errors that occur. */ + If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is + set, we return that, rather than the _TYPE it corresponds to, in + other cases we look through the type decl. If TF_ERROR is set, + complain about errors, otherwise be quiet. */ tree make_typename_type (context, name, complain) tree context, name; - int complain; + tsubst_flags_t complain; { tree fullname; @@ -5653,7 +5656,7 @@ make_typename_type (context, name, complain) { /* We can get here from typename_sub0 in the explicit_template_type expansion. Just fail. */ - if (complain) + if (complain & tf_error) error ("no class template named `%#T' in `%#T'", name, context); return error_mark_node; @@ -5669,7 +5672,7 @@ make_typename_type (context, name, complain) tmpl = lookup_field (context, name, 0, 0); if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) { - if (complain) + if (complain & tf_error) error ("no class template named `%#T' in `%#T'", name, context); return error_mark_node; @@ -5687,14 +5690,18 @@ make_typename_type (context, name, complain) if (!IS_AGGR_TYPE (context)) { - if (complain) + if (complain & tf_error) error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } t = lookup_field (context, name, 0, 1); if (t) - return TREE_TYPE (t); + { + if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl)) + t = TREE_TYPE (t); + return t; + } } } @@ -5702,7 +5709,7 @@ make_typename_type (context, name, complain) there now or its never going to be. */ if (!uses_template_parms (context)) { - if (complain) + if (complain & tf_error) error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } @@ -5713,7 +5720,9 @@ make_typename_type (context, name, complain) /* Resolve `CONTEXT::template NAME'. Returns an appropriate type, unless an error occurs, in which case error_mark_node is returned. - If COMPLAIN zero, don't complain about any errors that occur. */ + If we locate a TYPE_DECL, we return that, rather than the _TYPE it + corresponds to. If COMPLAIN zero, don't complain about any errors + that occur. */ tree make_unbound_class_template (context, name, complain) @@ -9606,9 +9615,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) tree spec; tree type = NULL_TREE; int longlong = 0; - int constp; - int restrictp; - int volatilep; int type_quals; int virtualp, explicitp, friendp, inlinep, staticp; int explicit_int = 0; @@ -10314,26 +10320,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) type = build_complex_type (type); } - if (sfk == sfk_conversion - && (RIDBIT_SETP (RID_CONST, specbits) - || RIDBIT_SETP (RID_VOLATILE, specbits) - || RIDBIT_SETP (RID_RESTRICT, specbits))) + type_quals = TYPE_UNQUALIFIED; + if (RIDBIT_SETP (RID_CONST, specbits)) + type_quals |= TYPE_QUAL_CONST; + if (RIDBIT_SETP (RID_VOLATILE, specbits)) + type_quals |= TYPE_QUAL_VOLATILE; + if (RIDBIT_SETP (RID_RESTRICT, specbits)) + type_quals |= TYPE_QUAL_RESTRICT; + if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED) error ("qualifiers are not allowed on declaration of `operator %T'", ctor_return_type); - /* Set CONSTP if this declaration is `const', whether by - explicit specification or via a typedef. - Likewise for VOLATILEP. */ - - constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type); - restrictp = - !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type); - volatilep = - !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type); - type_quals = ((constp ? TYPE_QUAL_CONST : 0) - | (restrictp ? TYPE_QUAL_RESTRICT : 0) - | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - type = cp_build_qualified_type (type, type_quals); + type_quals |= cp_type_quals (type); + type = cp_build_qualified_type_real + (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl) + ? tf_ignore_bad_quals : 0) | tf_error | tf_warning)); + /* We might have ignored or rejected some of the qualifiers. */ + type_quals = cp_type_quals (type); + staticp = 0; inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); @@ -10826,21 +10830,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) { register tree typemodlist; int erred = 0; - - constp = 0; - volatilep = 0; - restrictp = 0; + int constp = 0; + int volatilep = 0; + int restrictp = 0; + for (typemodlist = TREE_TYPE (declarator); typemodlist; typemodlist = TREE_CHAIN (typemodlist)) { tree qualifier = TREE_VALUE (typemodlist); if (qualifier == ridpointers[(int) RID_CONST]) - constp++; + { + constp++; + type_quals |= TYPE_QUAL_CONST; + } else if (qualifier == ridpointers[(int) RID_VOLATILE]) - volatilep++; + { + volatilep++; + type_quals |= TYPE_QUAL_VOLATILE; + } else if (qualifier == ridpointers[(int) RID_RESTRICT]) - restrictp++; + { + restrictp++; + type_quals |= TYPE_QUAL_RESTRICT; + } else if (!erred) { erred = 1; @@ -10853,20 +10866,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) pedwarn ("duplicate `volatile'"); if (restrictp > 1) pedwarn ("duplicate `restrict'"); - - type_quals = ((constp ? TYPE_QUAL_CONST : 0) - | (restrictp ? TYPE_QUAL_RESTRICT : 0) - | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - if (TREE_CODE (declarator) == ADDR_EXPR - && (constp || volatilep)) - { - if (constp) - pedwarn ("discarding `const' applied to a reference"); - if (volatilep) - pedwarn ("discarding `volatile' applied to a reference"); - type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); - } type = cp_build_qualified_type (type, type_quals); + type_quals = cp_type_quals (type); } declarator = TREE_OPERAND (declarator, 0); ctype = NULL_TREE; @@ -11110,7 +11111,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) else if (type_quals & TYPE_QUAL_CONST) { error ("const `%s' cannot be declared `mutable'", name); - RIDBIT_RESET (RID_MUTABLE, specbits); + RIDBIT_RESET (RID_MUTABLE, specbits); } } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0cbb321..ea1d297 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -5219,7 +5219,7 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p) { /* According to the suggested resolution of core issue 180, 'typename' is assumed after a class-key. */ - decl = make_typename_type (scope, id, 1); + decl = make_typename_type (scope, id, tf_error); if (decl != error_mark_node) decl = TYPE_MAIN_DECL (decl); else diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 54a6823..e6bdc9a 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -3029,14 +3029,14 @@ nested_name_specifier: { $$ = $2; } | nested_name_specifier TEMPLATE explicit_template_type SCOPE { got_scope = $$ - = make_typename_type ($1, $3, /*complain=*/1); } + = make_typename_type ($1, $3, tf_error); } /* Error handling per Core 125. */ | nested_name_specifier IDENTIFIER SCOPE { got_scope = $$ - = make_typename_type ($1, $2, /*complain=*/1); } + = make_typename_type ($1, $2, tf_error); } | nested_name_specifier PTYPENAME SCOPE { got_scope = $$ - = make_typename_type ($1, $2, /*complain=*/1); } + = make_typename_type ($1, $2, tf_error); } ; /* Why the @#$%^& do type_name and notype_identifier need to be expanded @@ -3078,7 +3078,7 @@ typename_sub0: typename_sub1 identifier %prec EMPTY { if (TYPE_P ($1)) - $$ = make_typename_type ($1, $2, /*complain=*/1); + $$ = make_typename_type ($1, $2, tf_error); else if (TREE_CODE ($2) == IDENTIFIER_NODE) error ("`%T' is not a class or namespace", $2); else @@ -3091,9 +3091,9 @@ typename_sub0: | typename_sub1 template_type %prec EMPTY { $$ = TREE_TYPE ($2); } | typename_sub1 explicit_template_type %prec EMPTY - { $$ = make_typename_type ($1, $2, /*complain=*/1); } + { $$ = make_typename_type ($1, $2, tf_error); } | typename_sub1 TEMPLATE explicit_template_type %prec EMPTY - { $$ = make_typename_type ($1, $3, /*complain=*/1); } + { $$ = make_typename_type ($1, $3, tf_error); } ; typename_sub1: @@ -3107,7 +3107,7 @@ typename_sub1: | typename_sub1 typename_sub2 { if (TYPE_P ($1)) - $$ = make_typename_type ($1, $2, /*complain=*/1); + $$ = make_typename_type ($1, $2, tf_error); else if (TREE_CODE ($2) == IDENTIFIER_NODE) error ("`%T' is not a class or namespace", $2); else @@ -3119,10 +3119,10 @@ typename_sub1: } | typename_sub1 explicit_template_type SCOPE { got_scope = $$ - = make_typename_type ($1, $2, /*complain=*/1); } + = make_typename_type ($1, $2, tf_error); } | typename_sub1 TEMPLATE explicit_template_type SCOPE { got_scope = $$ - = make_typename_type ($1, $3, /*complain=*/1); } + = make_typename_type ($1, $3, tf_error); } ; /* This needs to return a TYPE_DECL for simple names so that we don't diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4a57dd3..152ac0e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3335,8 +3335,6 @@ convert_template_argument (parm, arg, args, complain, i, in_decl) arg = make_typename_type (TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1), complain & tf_error); - if (TREE_CODE (arg) == TYPE_DECL) - arg = TREE_TYPE (arg); is_type = 1; } if (is_type != requires_type) @@ -6407,7 +6405,7 @@ tsubst (t, args, complain, in_decl) my_friendly_assert (TYPE_P (arg), 0); return cp_build_qualified_type_real (arg, cp_type_quals (arg) | cp_type_quals (t), - complain); + complain | tf_ignore_bad_quals); } else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) { @@ -6459,8 +6457,10 @@ tsubst (t, args, complain, in_decl) if (cp_type_quals (t)) { r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl); - r = cp_build_qualified_type_real - (r, cp_type_quals (t), complain); + r = cp_build_qualified_type_real + (r, cp_type_quals (t), + complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM + ? tf_ignore_bad_quals : 0)); } else { @@ -6785,11 +6785,18 @@ tsubst (t, args, complain, in_decl) } } - f = make_typename_type (ctx, f, complain & tf_error); + f = make_typename_type (ctx, f, + (complain & tf_error) | tf_keep_type_decl); if (f == error_mark_node) return f; - return cp_build_qualified_type_real - (f, cp_type_quals (f) | cp_type_quals (t), complain); + if (TREE_CODE (f) == TYPE_DECL) + { + complain |= tf_ignore_bad_quals; + f = TREE_TYPE (f); + } + + return cp_build_qualified_type_real + (f, cp_type_quals (f) | cp_type_quals (t), complain); } case UNBOUND_CLASS_TEMPLATE: @@ -8463,12 +8470,28 @@ check_cv_quals_for_unify (strict, arg, parm) tree arg; tree parm; { + int arg_quals = cp_type_quals (arg); + int parm_quals = cp_type_quals (parm); + + if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM) + { + /* If the cvr quals of parm will not unify with ARG, they'll be + ignored in instantiation, so we have to do the same here. */ + if (TREE_CODE (arg) == REFERENCE_TYPE + || TREE_CODE (arg) == FUNCTION_TYPE + || TREE_CODE (arg) == METHOD_TYPE) + parm_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); + if (!POINTER_TYPE_P (arg) && + TREE_CODE (arg) != TEMPLATE_TYPE_PARM) + parm_quals &= ~TYPE_QUAL_RESTRICT; + } + if (!(strict & (UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_OUTER_MORE_CV_QUAL)) - && !at_least_as_qualified_p (arg, parm)) + && (arg_quals & parm_quals) != parm_quals) return 0; if (!(strict & (UNIFY_ALLOW_LESS_CV_QUAL | UNIFY_ALLOW_OUTER_LESS_CV_QUAL)) - && !at_least_as_qualified_p (parm, arg)) + && (parm_quals & arg_quals) != arg_quals) return 0; return 1; @@ -9930,6 +9953,27 @@ instantiate_decl (d, defer_ok) import_export_decl (d); } + if (!defer_ok) + { + /* Recheck the substitutions to obtain any warning messages + about ignoring cv qualifiers. */ + tree gen = DECL_TEMPLATE_RESULT (gen_tmpl); + tree type = TREE_TYPE (gen); + + if (TREE_CODE (gen) == FUNCTION_DECL) + { + tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d); + tsubst (TYPE_RAISES_EXCEPTIONS (type), args, + tf_error | tf_warning, d); + /* Don't simply tsubst the function type, as that will give + duplicate warnings about poor parameter qualifications. + The function arguments are the same as the decl_arguments + without the top level cv qualifiers. */ + type = TREE_TYPE (type); + } + tsubst (type, args, tf_error | tf_warning, d); + } + if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d) && DECL_INITIAL (d) == NULL_TREE) /* We should have set up DECL_INITIAL in instantiate_class_template. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 62f67e7..8b0a198 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -506,9 +506,23 @@ build_cplus_array_type (elt_type, index_type) /* 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. - Errors are emitted under control of COMPLAIN. If COMPLAIN is zero, - error_mark_node is returned for bad qualifiers. */ - + + FLAGS determines how to deal with illformed qualifications. If + tf_ignore_bad_quals is set, then bad qualifications are dropped + (this is permitted if TYPE was introduced via a typedef or template + type parameter). If bad qualifications are dropped and tf_warning + is set, then a warning is issued for non-const qualifications. If + tf_ignore_bad_quals is not set and tf_error is not set, we + return error_mark_node. Otherwise, we issue an error, and ignore + the qualifications. + + Qualification of a reference type is valid when the reference came + via a typedef or template type argument. [dcl.ref] No such + dispensation is provided for qualifying a function type. [dcl.fct] + DR 295 queries this and the proposed resolution brings it into line + with qualifiying a reference. We implement the DR. We also behave + in a similar manner for restricting non-pointer types. */ + tree cp_build_qualified_type_real (type, type_quals, complain) tree type; @@ -516,6 +530,7 @@ cp_build_qualified_type_real (type, type_quals, complain) tsubst_flags_t complain; { tree result; + int bad_quals = TYPE_UNQUALIFIED; if (type == error_mark_node) return type; @@ -523,32 +538,51 @@ cp_build_qualified_type_real (type, type_quals, complain) if (type_quals == cp_type_quals (type)) return type; - /* A restrict-qualified pointer type must be a pointer (or reference) + /* A reference, fucntion or method type shall not be cv qualified. + [dcl.ref], [dct.fct] */ + if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE) + && (TREE_CODE (type) == REFERENCE_TYPE + || TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE)) + { + bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); + type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); + } + + /* A restrict-qualified 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)) + && TREE_CODE (type) != TYPENAME_TYPE + && !POINTER_TYPE_P (type)) { - if (complain & tf_error) - error ("`%T' cannot be `restrict'-qualified", type); - else - return error_mark_node; - + bad_quals |= TYPE_QUAL_RESTRICT; type_quals &= ~TYPE_QUAL_RESTRICT; } - if (type_quals != TYPE_UNQUALIFIED - && TREE_CODE (type) == FUNCTION_TYPE) + if (bad_quals == TYPE_UNQUALIFIED) + /*OK*/; + else if (!(complain & (tf_error | tf_ignore_bad_quals))) + return error_mark_node; + else { - if (complain & tf_error) - error ("`%T' cannot be `const'-, `volatile'-, or `restrict'-qualified", type); - else - return error_mark_node; - type_quals = TYPE_UNQUALIFIED; + if (complain & tf_ignore_bad_quals) + /* We're not going to warn about constifying things that can't + be constified. */ + bad_quals &= ~TYPE_QUAL_CONST; + if (bad_quals) + { + tree bad_type = build_qualified_type (ptr_type_node, bad_quals); + + if (!(complain & tf_ignore_bad_quals)) + error ("`%V' qualifiers cannot be applied to `%T'", + bad_type, type); + else if (complain & tf_warning) + warning ("ignoring `%V' qualifiers on `%T'", bad_type, type); + } } - else if (TREE_CODE (type) == ARRAY_TYPE) + + if (TREE_CODE (type) == ARRAY_TYPE) { /* In C++, the qualification really applies to the array element type. Obtain the appropriately qualified element type. */ @@ -590,7 +624,7 @@ cp_build_qualified_type_real (type, type_quals, complain) { /* For a pointer-to-member type, we can't just return a cv-qualified version of the RECORD_TYPE. If we do, we - haven't change the field that contains the actual pointer to + haven't changed the field that contains the actual pointer to a method, and so TYPE_PTRMEMFUNC_FN_TYPE will be wrong. */ tree t; @@ -598,7 +632,7 @@ cp_build_qualified_type_real (type, type_quals, complain) t = cp_build_qualified_type_real (t, type_quals, complain); return build_ptrmemfunc_type (t); } - + /* Retrieve (or create) the appropriately qualified variant. */ result = build_qualified_type (type, type_quals); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 12b65ee..6785c53 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2002-02-22 Nathan Sidwell <nathan@codesourcery.com> + + * g++.dg/template/qualttp19.C: New test. + * g++.dg/template/qualttp20.C: New test. + * g++.old-deja/g++.jason/report.C: Adjust expected errors + * g++.old-deja/g++.other/qual1.C: Likewise. + 2002-02-21 Aldy Hernandez <aldyh@redhat.com> * gcc.dg/attr-alwaysinline.c: New. diff --git a/gcc/testsuite/g++.dg/template/qualttp19.C b/gcc/testsuite/g++.dg/template/qualttp19.C new file mode 100644 index 0000000..be6676c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/qualttp19.C @@ -0,0 +1,41 @@ +// { dg-do compile } + +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 15 Dec 2001 <nathan@codesourcery.com> + +// PR 2645 + +template <typename T> +struct call_traits +{ + public: + typedef T type_less_spec; +}; + +template <typename T> +struct call_traits<T&> +{ + typedef T type_more_spec; +}; + + +int main() +{ + int num; + + // Two typedefs lead to the instant. of the less spec. ("wrong") template + typedef int& r_type; + typedef const r_type cr_type; + call_traits<cr_type>::type_less_spec var = num; // { dg-error "" "" } + + // The explicit type leads to the instantiation of the "correct" one + call_traits<const int&>::type_more_spec var2 = num; + + // As happen with a single typedef! + typedef const int& std_cr_type; + call_traits<std_cr_type>::type_more_spec var3 = num; + + + // As happen, indeed, without the cv-qualifier + call_traits<r_type>::type_more_spec var4; +} diff --git a/gcc/testsuite/g++.dg/template/qualttp20.C b/gcc/testsuite/g++.dg/template/qualttp20.C new file mode 100644 index 0000000..2c6c714 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/qualttp20.C @@ -0,0 +1,33 @@ +// { dg-do compile } + +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 15 Dec 2001 <nathan@codesourcery.com> + +// PR 2645 + +struct AS +{ + typedef void (myT) (); + struct L {}; + +}; + + +template <typename T> struct B1 : T +{ + typedef typename T::L __restrict__ r;// { dg-error "`__restrict' qualifiers cannot" "" } + typedef typename T::myT __restrict__ p;// { dg-warning "ignoring `__restrict'" "" } + + typedef typename T::myT volatile *myvolatile; // { dg-warning "ignoring `volatile'" "" } + typename T::myT volatile *a; // { dg-warning "ignoring `volatile'" "" } + myvolatile b; // { dg-bogus "ignoring `volatile'" "" { xfail *-*-* } } +}; +template <typename T> struct B2 : T +{ + typedef typename T::myT const *myconst; + typename T::myT const *a; + myconst b; +}; + +B1<AS> b1; // { dg-error "instantiated" "" } +B2<AS> b2; diff --git a/gcc/testsuite/g++.old-deja/g++.jason/report.C b/gcc/testsuite/g++.old-deja/g++.jason/report.C index 4599409..14bc9d8 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/report.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/report.C @@ -2,6 +2,8 @@ // GROUPS passed error-reporting // Special g++ Options: -Wreturn-type +// DR 295 allows qualification via typedef + template <char C> class badoo { @@ -44,7 +46,8 @@ class X{ }; typedef int const * bart (); -typedef bart const * const * bar2; // ERROR - qualifiers +typedef bart const * const * bar2; // ok - constifying qualifiers +typedef bart volatile * const * bar2v; // WARNING - qualifiers bar2 baz (X::Y y) { // ERROR - in this context diff --git a/gcc/testsuite/g++.old-deja/g++.other/qual1.C b/gcc/testsuite/g++.old-deja/g++.other/qual1.C index 6120dae..fa2d33f 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/qual1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/qual1.C @@ -2,13 +2,16 @@ // Origin: Benjamin Pflugmann <philemon@spin.de> // Special g++ Options: -O +// DR 295 allows qualification via typedef + typedef const char *(func_type)(); class { public: func_type *Function; - const func_type* function(void) { return Function; } // ERROR - qualifiers + const func_type* function(void) { return Function; } // ok constifying + volatile func_type* functionv(void); // WARNING - qualifier } action; void work(const char *source) |