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
This commit is contained in:
Paolo Carlini 2015-09-01 08:39:47 +00:00 committed by Paolo Carlini
parent e071af96da
commit 6853b04cdd
4 changed files with 105 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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" }