diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2015-09-01 08:39:47 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2015-09-01 08:39:47 +0000 |
commit | 6853b04cdd6269c596bf4dd24b41eee2170caef3 (patch) | |
tree | fe4cdc38ad1d9ae22dbdec61b95b211090f74d89 /gcc | |
parent | e071af96da90ec5e2d224cdd9522b428b21f7d2c (diff) | |
download | gcc-6853b04cdd6269c596bf4dd24b41eee2170caef3.zip gcc-6853b04cdd6269c596bf4dd24b41eee2170caef3.tar.gz gcc-6853b04cdd6269c596bf4dd24b41eee2170caef3.tar.bz2 |
re PR c++/61753 (poor diagnostic for constructor definition that starts with 'const')
/cp
2015-09-01 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/61753
* decl.c (smallest_type_quals_location): New.
(check_special_function_return_type): Use the latter; add int and
const location_t* parameters.
(grokdeclarator): Adjust check_special_function_return_type call.
/testsuite
2015-09-01 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/61753
* g++.dg/other/pr61753.C: New.
From-SVN: r227361
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 85 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/pr61753.C | 31 |
4 files changed, 105 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7cbfa65..477bb20 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2015-09-01 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/61753 + * decl.c (smallest_type_quals_location): New. + (check_special_function_return_type): Use the latter; add int and + const location_t* parameters. + (grokdeclarator): Adjust check_special_function_return_type call. + 2015-08-29 Markus Trippelsdorf <markus@trippelsdorf.de> PR c++/67371 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 205febc..96d735a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -113,7 +113,7 @@ static void end_cleanup_fn (void); static tree cp_make_fname_decl (location_t, tree, int); static void initialize_predefined_identifiers (void); static tree check_special_function_return_type - (special_function_kind, tree, tree); + (special_function_kind, tree, tree, int, const location_t*); static tree push_cp_library_fn (enum tree_code, tree, int); static tree build_cp_library_fn (tree, enum tree_code, tree, int); static void store_parm_decls (tree); @@ -8924,24 +8924,51 @@ create_array_type_for_decl (tree name, tree type, tree size) return build_cplus_array_type (type, itype); } -/* Check that it's OK to declare a function with the indicated TYPE. - SFK indicates the kind of special function (if any) that this - function is. OPTYPE is the type given in a conversion operator - declaration, or the class type for a constructor/destructor. - Returns the actual return type of the function; that - may be different than TYPE if an error occurs, or for certain - special functions. */ +/* Returns the smallest location != UNKNOWN_LOCATION among the + three stored in LOCATIONS[ds_const], LOCATIONS[ds_volatile], + and LOCATIONS[ds_restrict]. */ + +static location_t +smallest_type_quals_location (int type_quals, const location_t* locations) +{ + location_t loc = UNKNOWN_LOCATION; + + if (type_quals & TYPE_QUAL_CONST) + loc = locations[ds_const]; + + if ((type_quals & TYPE_QUAL_VOLATILE) + && (loc == UNKNOWN_LOCATION || locations[ds_volatile] < loc)) + loc = locations[ds_volatile]; + + if ((type_quals & TYPE_QUAL_RESTRICT) + && (loc == UNKNOWN_LOCATION || locations[ds_restrict] < loc)) + loc = locations[ds_restrict]; + + return loc; +} + +/* Check that it's OK to declare a function with the indicated TYPE + and TYPE_QUALS. SFK indicates the kind of special function (if any) + that this function is. OPTYPE is the type given in a conversion + operator declaration, or the class type for a constructor/destructor. + Returns the actual return type of the function; that may be different + than TYPE if an error occurs, or for certain special functions. */ static tree check_special_function_return_type (special_function_kind sfk, tree type, - tree optype) + tree optype, + int type_quals, + const location_t* locations) { switch (sfk) { case sfk_constructor: if (type) error ("return type specification for constructor invalid"); + else if (type_quals != TYPE_UNQUALIFIED) + error_at (smallest_type_quals_location (type_quals, locations), + "qualifiers are not allowed on constructor declaration"); if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype)) type = build_pointer_type (optype); @@ -8952,6 +8979,10 @@ check_special_function_return_type (special_function_kind sfk, case sfk_destructor: if (type) error ("return type specification for destructor invalid"); + else if (type_quals != TYPE_UNQUALIFIED) + error_at (smallest_type_quals_location (type_quals, locations), + "qualifiers are not allowed on destructor declaration"); + /* We can't use the proper return type here because we run into problems with ambiguous bases and covariant returns. Java classes are left unchanged because (void *) isn't a valid @@ -8964,7 +8995,12 @@ check_special_function_return_type (special_function_kind sfk, case sfk_conversion: if (type) - error ("return type specified for %<operator %T%>", optype); + error ("return type specified for %<operator %T%>", optype); + else if (type_quals != TYPE_UNQUALIFIED) + error_at (smallest_type_quals_location (type_quals, locations), + "qualifiers are not allowed on declaration of " + "%<operator %T%>", optype); + type = optype; break; @@ -9090,7 +9126,7 @@ grokdeclarator (const cp_declarator *declarator, a member function. */ cp_ref_qualifier rqual = REF_QUAL_NONE; /* cv-qualifiers that apply to the type specified by the DECLSPECS. */ - int type_quals; + int type_quals = TYPE_UNQUALIFIED; tree raises = NULL_TREE; int template_count = 0; tree returned_attrs = NULL_TREE; @@ -9137,6 +9173,13 @@ grokdeclarator (const cp_declarator *declarator, if (concept_p) constexpr_p = true; + if (decl_spec_seq_has_spec_p (declspecs, ds_const)) + type_quals |= TYPE_QUAL_CONST; + if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) + type_quals |= TYPE_QUAL_VOLATILE; + if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) + type_quals |= TYPE_QUAL_RESTRICT; + if (decl_context == FUNCDEF) funcdef_flag = true, decl_context = NORMAL; else if (decl_context == MEMFUNCDEF) @@ -9462,8 +9505,13 @@ grokdeclarator (const cp_declarator *declarator, ctor_return_type = ctype; if (sfk != sfk_none) - type = check_special_function_return_type (sfk, type, - ctor_return_type); + { + type = check_special_function_return_type (sfk, type, + ctor_return_type, + type_quals, + declspecs->locations); + type_quals = TYPE_UNQUALIFIED; + } else if (type == NULL_TREE) { int is_main; @@ -9648,17 +9696,6 @@ grokdeclarator (const cp_declarator *declarator, type = build_complex_type (type); } - type_quals = TYPE_UNQUALIFIED; - if (decl_spec_seq_has_spec_p (declspecs, ds_const)) - type_quals |= TYPE_QUAL_CONST; - if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) - type_quals |= TYPE_QUAL_VOLATILE; - if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) - 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); - /* If we're using the injected-class-name to form a compound type or a declaration, replace it with the underlying class so we don't get redundant typedefs in the debug output. But if we are returning the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 15dc00d..b9d9f84 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-09-01 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/61753 + * g++.dg/other/pr61753.C: New. + 2015-08-31 Marc Glisse <marc.glisse@inria.fr> * gcc.dg/tree-ssa/cmp-1.c: New file. diff --git a/gcc/testsuite/g++.dg/other/pr61753.C b/gcc/testsuite/g++.dg/other/pr61753.C new file mode 100644 index 0000000..6c6a738 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/pr61753.C @@ -0,0 +1,31 @@ +// PR c++/61753 + +class Rulec { + Rulec(); +}; + +const Rulec::Rulec() { } // { dg-error "1:qualifiers" } + +class Rulev { + Rulev(); +}; + +volatile Rulev::Rulev() { } // { dg-error "1:qualifiers" } + +class Ruler { + Ruler(); +}; + +__restrict Ruler::Ruler() { } // { dg-error "1:qualifiers" } + +class Rulecvr { + Rulecvr(); +}; + +const volatile __restrict Rulecvr::Rulecvr() { } // { dg-error "1:qualifiers" } + +class Rulervc { + Rulervc(); +}; + +__restrict volatile const Rulervc::Rulervc() { } // { dg-error "1:qualifiers" } |