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, int, const location_t*);
+ (special_function_kind, tree, tree, int, const cp_declarator**,
+ 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);
return smallest_type_location (type_quals, declspecs->locations);
}
-/* 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 whether DECLARATOR represented a pointer or a reference and if so,
+ strip out the pointer/reference declarator(s). */
+
+static bool
+maybe_strip_indirect_ref (const cp_declarator** declarator)
+{
+ bool indirect_ref_p = false;
+ while (declarator && *declarator
+ && ((*declarator)->kind == cdk_pointer
+ || (*declarator)->kind == cdk_reference))
+ {
+ indirect_ref_p = true;
+ *declarator = (*declarator)->declarator;
+ }
+ return indirect_ref_p;
+}
+
+/* Check that it's OK to declare a function with the indicated TYPE, TYPE_QUALS
+ and DECLARATOR. 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. */
tree type,
tree optype,
int type_quals,
+ const cp_declarator** declarator,
const location_t* locations)
{
+ gcc_assert (declarator);
+ location_t rettype_loc = (type
+ ? smallest_type_location (type_quals, locations)
+ : (*declarator)->id_loc);
switch (sfk)
{
case sfk_constructor:
- if (type)
- error_at (smallest_type_location (type_quals, locations),
+ if (maybe_strip_indirect_ref (declarator) || type)
+ error_at (rettype_loc,
"return type specification for constructor invalid");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
break;
case sfk_destructor:
- if (type)
- error_at (smallest_type_location (type_quals, locations),
+ if (maybe_strip_indirect_ref (declarator) || type)
+ error_at (rettype_loc,
"return type specification for destructor invalid");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
break;
case sfk_conversion:
- if (type)
- error_at (smallest_type_location (type_quals, locations),
+ if (maybe_strip_indirect_ref (declarator) || type)
+ error_at (rettype_loc,
"return type specified for %<operator %T%>", optype);
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
break;
case sfk_deduction_guide:
- if (type)
- error_at (smallest_type_location (type_quals, locations),
+ if (maybe_strip_indirect_ref (declarator) || type)
+ error_at (rettype_loc,
"return type specified for deduction guide");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
type = check_special_function_return_type (sfk, type,
ctor_return_type,
type_quals,
+ &declarator,
declspecs->locations);
type_quals = TYPE_UNQUALIFIED;
}
--- /dev/null
+// PR c++/118306
+// { dg-do "compile" }
+
+// Constructors.
+struct A {
+ *A (); // { dg-error "return type specification" }
+};
+struct B {
+ **B (); // { dg-error "return type specification" }
+};
+struct C {
+ ***C (); // { dg-error "return type specification" }
+};
+struct D {
+ &D (); // { dg-error "return type specification|reference to" }
+};
+struct E {
+ *&E (); // { dg-error "return type specification|reference to" }
+};
+struct F {
+ **&F (); // { dg-error "return type specification|reference to" }
+};
+struct G {
+ *G (const G&); // { dg-error "return type specification" }
+};
+struct H {
+ **H (const H&); // { dg-error "return type specification" }
+};
+struct I {
+ &I (const I&); // { dg-error "return type specification|reference to" }
+};
+struct J {
+ const J(); // { dg-error "expected unqualified-id" }
+};
+
+// Destructors.
+struct K {
+ * ~K (); // { dg-error "return type specification" }
+};
+struct L {
+ ** ~L (); // { dg-error "return type specification" }
+};
+struct M {
+ & ~M (); // { dg-error "return type specification|reference to" }
+};
+struct N {
+ virtual * ~N (); // { dg-error "return type specification" }
+};
+struct O {
+ virtual & ~O (); // { dg-error "return type specification|reference to" }
+};
+struct P {
+ volatile ~P(); // { dg-error "qualifiers are not allowed" }
+};
--- /dev/null
+// PR c++/118304
+// { dg-do "compile" { target c++11 } }
+
+// Constructors.
+struct A {
+ *A () = default; // { dg-error "return type specification" }
+};
+struct B {
+ int* B () = default; // { dg-error "return type specification" }
+};
+struct C {
+ const int& C () = default; // { dg-error "return type specification" }
+};
+struct D {
+ **D () = default; // { dg-error "return type specification" }
+};
+struct E {
+ &E () = default; // { dg-error "return type specification|reference to" }
+};
+struct F {
+ *&F () = default; // { dg-error "return type specification|reference to" }
+};
+struct G {
+ **&G () = default; // { dg-error "return type specification|reference to" }
+};
+struct H {
+ *H (const H&) = default; // { dg-error "return type specification" }
+};
+struct I {
+ **I (const I&) = default; // { dg-error "return type specification" }
+};
+struct J {
+ &J (const J&) = default; // { dg-error "return type specification|reference to" }
+};
+struct K {
+ const K() = default; // { dg-error "expected unqualified-id" }
+};
+
+// Destructors.
+struct L {
+ * ~L () = default; // { dg-error "return type specification" }
+};
+struct M {
+ ** ~M () = default; // { dg-error "return type specification" }
+};
+struct N {
+ & ~N () = default; // { dg-error "return type specification|reference to" }
+};
--- /dev/null
+// PR c++/118306 - "Document" various behaviours wrt. defaulting types to int.
+// { dg-do "compile" }
+// { dg-additional-options "-fpermissive" }
+
+// Members.
+struct K {
+ * mem1; // { dg-warning "forbids declaration" }
+ * mem2; // { dg-warning "forbids declaration" }
+ const * mem3; // { dg-warning "forbids declaration" }
+ const ** mem4; // { dg-warning "forbids declaration" }
+ & mem5; // { dg-warning "forbids declaration" }
+ volatile & mem6; // { dg-warning "forbids declaration" }
+
+ void foo (const& permissive_fine, // { dg-warning "forbids declaration" }
+ volatile* permissive_fine_as_well); // { dg-warning "forbids declaration" }
+
+ * bar () { return 0; } // { dg-warning "forbids declaration" }
+ const& baz (); // { dg-warning "forbids declaration" }
+
+ void bazz () {
+ try {}
+ catch (const *i) {} // { dg-warning "forbids" }
+ catch (const &i) {} // { dg-warning "forbids" }
+ }
+};
+
+// Template parameters.
+template<const *i, const &j> // { dg-warning "forbids" }
+void baz() {}
+
+// Functions.
+foo(int) { return 42; } // { dg-warning "forbids declaration" }
+*bar(int) { return 0; } // { dg-warning "forbids declaration" }
+**bazz(int) { return 0; } // { dg-warning "forbids declaration" }
+*&bazzz(int) { return 0; } // { dg-warning "forbids declaration|bind non-const" }
+const bazzzz (int) { return 0; } // { dg-warning "forbids declaration" }
+const* bazzzzz (int) { return 0; } // { dg-warning "forbids declaration" }