This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] PR c++/13101
Mark Mitchell a écrit :
I don't think the logic is correct here, since I don't see anything that
ever clears is_function_pointer, and we might well have an array of
pointers to functions. I think you need to check that the innermost
declarator is a pointer-to-function.
Yes, you are right.
Please find attached an updated patch that should address the issue raised.
Regards,
Dodji.
gcc/cp/ChangeLog:
2008-07-02 Dodji Seketeli <dseketel@redhat.com>
PR c++/13101
* decl.c (grokdeclarator): For pointer to function declarations,
take cv quals of the declarator-id in account before warning
about initializing variables of storage class 'extern'.
gcc/testsuite/ChangeLog:
2008-07-02 Dodji Seketeli <dseketel@redhat.com>
PR c++/13101
* g++.dg/parse/func-ptr-decl.C: New test.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c6ae93e..9e70530 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -104,6 +104,8 @@ static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
+static bool is_innermost_decl_a_pointer (const cp_declarator *,
+ const cp_declarator **);
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
@@ -7312,6 +7314,32 @@ check_var_type (tree identifier, tree type)
return type;
}
+/* Returns true if the innermost declarator of DECL is a pointer.
+ If it is and if THE_PTR_DECL is not NULL then *THE_PTR_DECL is set
+ to that innermost declarator.
+ Otherwise, THE_PTR_DECL is left untouched. */
+static bool
+is_innermost_decl_a_pointer (const cp_declarator *decl,
+ const cp_declarator **the_ptr_decl)
+{
+ const cp_declarator *decl_iter;
+
+ for (decl_iter = decl;
+ decl_iter;
+ decl_iter = decl_iter->declarator)
+ {
+ if (decl_iter->kind == cdk_pointer
+ && decl_iter->declarator
+ && decl_iter->declarator->kind == cdk_id)
+ {
+ if (the_ptr_decl)
+ *the_ptr_decl = decl_iter;
+ return true;
+ }
+ }
+ return false;
+}
+
/* Given declspecs and a declarator (abstract or otherwise), determine
the name and type of the object declared and construct a DECL node
for it.
@@ -7418,6 +7446,10 @@ grokdeclarator (const cp_declarator *declarator,
bool type_was_error_mark_node = false;
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool set_no_warning = false;
+ bool is_function_pointer = false;
+ /* cv-qualifiers that apply to the type, when it's a pointer to function,
+ like in: void (*const ptr) (). */
+ cp_cv_quals ptr_to_function_quals = TYPE_UNQUALIFIED;
signed_p = declspecs->specs[(int)ds_signed];
unsigned_p = declspecs->specs[(int)ds_unsigned];
@@ -7445,13 +7477,25 @@ grokdeclarator (const cp_declarator *declarator,
switch (id_declarator->kind)
{
case cdk_function:
- if (id_declarator->declarator
- && id_declarator->declarator->kind == cdk_id)
- {
- sfk = id_declarator->declarator->u.id.sfk;
- if (sfk == sfk_destructor)
- flags = DTOR_FLAG;
- }
+ {
+ const cp_declarator *ptr_decl = NULL;
+ if (id_declarator->declarator
+ && id_declarator->declarator->kind == cdk_id)
+ {
+ sfk = id_declarator->declarator->u.id.sfk;
+ if (sfk == sfk_destructor)
+ flags = DTOR_FLAG;
+ }
+ else if (is_innermost_decl_a_pointer (id_declarator, &ptr_decl))
+ {
+ /* This is a function pointer declaration.
+ We need to record the cv quals of the declarator id.
+ Those will be used later in this function. */
+ is_function_pointer = true;
+ ptr_to_function_quals =
+ ptr_decl->u.pointer.qualifiers;
+ }
+ }
break;
case cdk_id:
@@ -7985,7 +8029,9 @@ grokdeclarator (const cp_declarator *declarator,
{
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
- if (!(type_quals & TYPE_QUAL_CONST))
+ if (!(type_quals & TYPE_QUAL_CONST)
+ && !(is_function_pointer
+ && ptr_to_function_quals & TYPE_QUAL_CONST))
warning (0, "%qs initialized and declared %<extern%>", name);
}
else
diff --git a/gcc/testsuite/g++.dg/parse/func-ptr-decl.C b/gcc/testsuite/g++.dg/parse/func-ptr-decl.C
new file mode 100644
index 0000000..1e93275
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/func-ptr-decl.C
@@ -0,0 +1,13 @@
+// Contributed by Dodji Seketeli <dseketel@redhat.com>
+// Origin: PR C++/13101
+// { dg-do compile }
+
+extern void(*bad_ptr0)() = 0; // { dg-warning "initialized and declared 'extern'" }
+extern void(*const good_ptr0)() = 0; // { dg-bogus "initialized and declared â??externâ??" }
+
+extern void(**bad_ptr1)() = 0; // { dg-warning "initialized and declared 'extern'" }
+extern void(** const good_ptr1)() = 0;//{ dg-bogus "initialized and declared â??externâ??" }
+
+extern void(** const* bad_ptr2)() = 0; // { dg-warning "initialized and declared 'extern'" }
+extern void(*** const good_ptr2)() = 0; // { dg-bogus "initialized and declared â??externâ??" }
+