This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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â??" }
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]