re PR c++/61753 (poor diagnostic for constructor definition that starts with 'const')
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 1 Sep 2015 08:39:47 +0000 (08:39 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 1 Sep 2015 08:39:47 +0000 (08:39 +0000)
/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

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/pr61753.C [new file with mode: 0644]

index 7cbfa6591f188fc0121b81927170bc9385cbd277..477bb209388b6aafe38ec5f328fabfd674d0a596 100644 (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
index 205febc1dad43d18162a4c02e70f95b161defd4a..96d735a36928a65023596d03d8f09fae0bf3df7b 100644 (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
index 15dc00dd211fcb49a51905c650cc8b7e85050767..b9d9f84ba749bf2d00425cbee273da38749b89ac 100644 (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.
diff --git a/gcc/testsuite/g++.dg/other/pr61753.C b/gcc/testsuite/g++.dg/other/pr61753.C
new file mode 100644 (file)
index 0000000..6c6a738
--- /dev/null
@@ -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" }