[C++] PR 84636 ("internal compiler error: Segmentation fault (identifier_p()/grokdeclarator())")

Message ID 7e0b3ae8-3c74-f2a3-29f3-351b1d105a4b@oracle.com
State New
Headers show
Series
  • [C++] PR 84636 ("internal compiler error: Segmentation fault (identifier_p()/grokdeclarator())")
Related show

Commit Message

Paolo Carlini Nov. 19, 2018, 7:03 p.m.
Hi,

while working on some additional location fixes to grokbitfield - 
preparing testcases - I stumbled into this ICE on invalid, where in 
grokdeclarator we try to use identifier_p on a null unqualified_id. In 
practice, clang and edg behave in different ways and since I couldn't 
decide which one I liked best I prepared two different patches which, 
respectively, implement similar behaviors: the former avoids the 
grokdeclarator ICE and delegates to the checks in grokbitfield for the 
diagnostics; the latter issues a specific error about the missing 
identifier after a function type (note, in any case we want to do that 
when staticp == 2 too, otherwise we crash later for a static version of 
the declaration). Tested both onx86_64-linux, as usual.

Thanks, Paolo.

////////////////

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 266268)
+++ cp/decl.c	(working copy)
@@ -12164,15 +12164,24 @@ grokdeclarator (const cp_declarator *declarator,
 	type = build_pointer_type (type);
     }
 
-  if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
-      && !(identifier_p (unqualified_id)
-	   && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
+  if (ctype && TREE_CODE (type) == FUNCTION_TYPE)
     {
-      cp_cv_quals real_quals = memfn_quals;
-      if (cxx_dialect < cxx14 && constexpr_p
-	  && sfk != sfk_constructor && sfk != sfk_destructor)
-	real_quals |= TYPE_QUAL_CONST;
-      type = build_memfn_type (type, ctype, real_quals, rqual);
+      if (!unqualified_id)
+	{
+	  error_at (declspecs->locations[ds_type_spec],
+		    "declarator requires an identifier");
+	  type = error_mark_node;
+	}
+      else if (staticp < 2
+	       && !(identifier_p (unqualified_id)
+		    && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
+	{
+	  cp_cv_quals real_quals = memfn_quals;
+	  if (cxx_dialect < cxx14 && constexpr_p
+	      && sfk != sfk_constructor && sfk != sfk_destructor)
+	    real_quals |= TYPE_QUAL_CONST;
+	  type = build_memfn_type (type, ctype, real_quals, rqual);
+	}
     }
 
   {
Index: testsuite/g++.dg/parse/bitfield6.C
===================================================================
--- testsuite/g++.dg/parse/bitfield6.C	(nonexistent)
+++ testsuite/g++.dg/parse/bitfield6.C	(working copy)
@@ -0,0 +1,6 @@
+// PR c++/84636
+
+typedef void a();
+struct A {
+  a: 1;  // { dg-error "3:declarator requires an identifier" }
+};

Comments

Marek Polacek Nov. 19, 2018, 10:24 p.m. | #1
On Mon, Nov 19, 2018 at 08:03:24PM +0100, Paolo Carlini wrote:
> @@ -12245,8 +12246,9 @@ grokdeclarator (const cp_declarator *declarator,

>  	    error ("invalid use of %<::%>");

>  	    return error_mark_node;

>  	  }

> -	else if (TREE_CODE (type) == FUNCTION_TYPE

> -		 || TREE_CODE (type) == METHOD_TYPE)

> +	else if ((TREE_CODE (type) == FUNCTION_TYPE

> +		  || TREE_CODE (type) == METHOD_TYPE)


I know it's preexisting but we have FUNC_OR_METHOD_TYPE_P for this.

Marek
Paolo Carlini Nov. 20, 2018, 9:25 a.m. | #2
Hi,

On 19/11/18 23:24, Marek Polacek wrote:
> On Mon, Nov 19, 2018 at 08:03:24PM +0100, Paolo Carlini wrote:

>> @@ -12245,8 +12246,9 @@ grokdeclarator (const cp_declarator *declarator,

>>   	    error ("invalid use of %<::%>");

>>   	    return error_mark_node;

>>   	  }

>> -	else if (TREE_CODE (type) == FUNCTION_TYPE

>> -		 || TREE_CODE (type) == METHOD_TYPE)

>> +	else if ((TREE_CODE (type) == FUNCTION_TYPE

>> +		  || TREE_CODE (type) == METHOD_TYPE)

> I know it's preexisting but we have FUNC_OR_METHOD_TYPE_P for this.


Ah, thanks! I guess I didn't notice that because the macro is defined in 
tree.h. I adjusted my first patch and I'll send a separate one for all 
the remaining instances (many!) in a separate patch. Thanks again,

Paolo.

////////////////////////
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 266268)
+++ cp/decl.c	(working copy)
@@ -12165,7 +12165,8 @@ grokdeclarator (const cp_declarator *declarator,
     }
 
   if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
-      && !(identifier_p (unqualified_id)
+      && !(unqualified_id
+	   && identifier_p (unqualified_id)
 	   && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
     {
       cp_cv_quals real_quals = memfn_quals;
@@ -12245,8 +12246,7 @@ grokdeclarator (const cp_declarator *declarator,
 	    error ("invalid use of %<::%>");
 	    return error_mark_node;
 	  }
-	else if (TREE_CODE (type) == FUNCTION_TYPE
-		 || TREE_CODE (type) == METHOD_TYPE)
+	else if (FUNC_OR_METHOD_TYPE_P (type) && !bitfield)
 	  {
 	    int publicp = 0;
 	    tree function_context;
Index: testsuite/g++.dg/parse/bitfield3.C
===================================================================
--- testsuite/g++.dg/parse/bitfield3.C	(revision 266263)
+++ testsuite/g++.dg/parse/bitfield3.C	(working copy)
@@ -5,5 +5,5 @@ typedef void (func_type)();
 
 struct A
 {
-  friend func_type f : 2; /* { dg-error "with non-integral type" } */
+  friend func_type f : 2; /* { dg-error "20:.f. is neither function nor member function" } */
 };
Index: testsuite/g++.dg/parse/bitfield6.C
===================================================================
--- testsuite/g++.dg/parse/bitfield6.C	(nonexistent)
+++ testsuite/g++.dg/parse/bitfield6.C	(working copy)
@@ -0,0 +1,6 @@
+// PR c++/84636
+
+typedef void a();
+struct A {
+a: 1;  // { dg-error "bit-field .\\<anonymous\\>. with non-integral type" }
+};
Paolo Carlini Nov. 22, 2018, 12:03 a.m. | #3
... in fact I'm thinking that the below - which directly checks for 
unqualified_id to be non-null in both places - may be a better variant: 
among other things it means that for related testcases like:
typedef void a();
struct A
{ a a1: 1; };
we get the location of a1 right (we could also change the diagnostics in 
grokbitfield to use DECL_SOURCE_LOCATION and exploit it), and the 
testsuite doesn't need adjustments. Tested x86_64-linux.

Thanks, Paolo.

////////////////
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 266339)
+++ cp/decl.c	(working copy)
@@ -12165,7 +12165,8 @@ grokdeclarator (const cp_declarator *declarator,
     }
 
   if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
-      && !(identifier_p (unqualified_id)
+      && !(unqualified_id
+	   && identifier_p (unqualified_id)
 	   && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
     {
       cp_cv_quals real_quals = memfn_quals;
@@ -12245,8 +12246,7 @@ grokdeclarator (const cp_declarator *declarator,
 	    error ("invalid use of %<::%>");
 	    return error_mark_node;
 	  }
-	else if (TREE_CODE (type) == FUNCTION_TYPE
-		 || TREE_CODE (type) == METHOD_TYPE)
+	else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id)
 	  {
 	    int publicp = 0;
 	    tree function_context;
Index: testsuite/g++.dg/parse/bitfield6.C
===================================================================
--- testsuite/g++.dg/parse/bitfield6.C	(nonexistent)
+++ testsuite/g++.dg/parse/bitfield6.C	(working copy)
@@ -0,0 +1,6 @@
+// PR c++/84636
+
+typedef void a();
+struct A {
+a: 1;  // { dg-error "bit-field .\\<anonymous\\>. with non-integral type" }
+};
Jason Merrill Dec. 2, 2018, 4:25 a.m. | #4
On 11/21/18 7:03 PM, Paolo Carlini wrote:
> ... in fact I'm thinking that the below - which directly checks for 

> unqualified_id to be non-null in both places - may be a better variant: 

> among other things it means that for related testcases like:

> typedef void a();

> struct A

> { a a1: 1; };

> we get the location of a1 right (we could also change the diagnostics in 

> grokbitfield to use DECL_SOURCE_LOCATION and exploit it), and the 

> testsuite doesn't need adjustments. Tested x86_64-linux.


> -	else if (TREE_CODE (type) == FUNCTION_TYPE

> -		 || TREE_CODE (type) == METHOD_TYPE)

> +	else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id)


Maybe change this to

else if (funcdecl_p)

?

OK either way.

Jason

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 266268)
+++ cp/decl.c	(working copy)
@@ -12165,7 +12165,8 @@  grokdeclarator (const cp_declarator *declarator,
     }
 
   if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
-      && !(identifier_p (unqualified_id)
+      && !(unqualified_id
+	   && identifier_p (unqualified_id)
 	   && IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
     {
       cp_cv_quals real_quals = memfn_quals;
@@ -12245,8 +12246,9 @@  grokdeclarator (const cp_declarator *declarator,
 	    error ("invalid use of %<::%>");
 	    return error_mark_node;
 	  }
-	else if (TREE_CODE (type) == FUNCTION_TYPE
-		 || TREE_CODE (type) == METHOD_TYPE)
+	else if ((TREE_CODE (type) == FUNCTION_TYPE
+		  || TREE_CODE (type) == METHOD_TYPE)
+		 && !bitfield)
 	  {
 	    int publicp = 0;
 	    tree function_context;
Index: testsuite/g++.dg/parse/bitfield3.C
===================================================================
--- testsuite/g++.dg/parse/bitfield3.C	(revision 266263)
+++ testsuite/g++.dg/parse/bitfield3.C	(working copy)
@@ -5,5 +5,5 @@  typedef void (func_type)();
 
 struct A
 {
-  friend func_type f : 2; /* { dg-error "with non-integral type" } */
+  friend func_type f : 2; /* { dg-error "20:.f. is neither function nor member function" } */
 };
Index: testsuite/g++.dg/parse/bitfield6.C
===================================================================
--- testsuite/g++.dg/parse/bitfield6.C	(nonexistent)
+++ testsuite/g++.dg/parse/bitfield6.C	(working copy)
@@ -0,0 +1,6 @@ 
+// PR c++/84636
+
+typedef void a();
+struct A {
+a: 1;  // { dg-error "bit-field .\\<anonymous\\>. with non-integral type" }
+};