aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2015-09-01 08:39:47 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2015-09-01 08:39:47 +0000
commit6853b04cdd6269c596bf4dd24b41eee2170caef3 (patch)
treefe4cdc38ad1d9ae22dbdec61b95b211090f74d89 /gcc
parente071af96da90ec5e2d224cdd9522b428b21f7d2c (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/cp/decl.c85
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/other/pr61753.C31
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" }