Patchwork C++0x, teach the parser to parse virt-specifier-seq for member functions

login
register
mail settings
Submitter ville
Date April 25, 2011, 11:03 a.m.
Message ID <87ei4qbnkk.wl%ville@ville-laptop>
Download mbox | patch
Permalink /patch/92724/
State New
Headers show

Comments

ville - April 25, 2011, 11:03 a.m.
This is just for the parser, the semantic analysis of virt-specifiers
will be done later. Also, these changes don't yet support a final
specifier on class.
Gabriel Dos Reis - April 25, 2011, 3:32 p.m.
On Mon, Apr 25, 2011 at 6:03 AM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>
> This is just for the parser, the semantic analysis of virt-specifiers
> will be done later. Also, these changes don't yet support a final
> specifier on class.
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index e538825..08d939f 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -4420,6 +4420,11 @@ extern GTY(()) operator_name_info_t assignment_operator_name_info
>
>  typedef int cp_cv_quals;
>
> +/* A type-qualifier, or bitmask therefore, using the VIRT_SPEC
> +   constants.  */
> +
> +typedef int cp_virt_specifiers;

could we use enums instead?

-- Gaby
ville - April 25, 2011, 3:34 p.m.
On 25 April 2011 18:32, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>>  typedef int cp_cv_quals;
>> +/* A type-qualifier, or bitmask therefore, using the VIRT_SPEC
>> +   constants.  */
>> +typedef int cp_virt_specifiers;
> could we use enums instead?

No reason not to, except that we don't for the cp_cv_quals above. :) I followed
the same approach.
Jason Merrill - April 25, 2011, 4:45 p.m.
On 04/25/2011 07:03 AM, Ville Voutilainen wrote:
> This is just for the parser, the semantic analysis of virt-specifiers
> will be done later. Also, these changes don't yet support a final
> specifier on class.

I mentioned the minor formatting issues in personal mail; also, please 
include ChangeLog entries in patches sent to gcc-patches.

To avoid user confusion like we had with constexpr, I'd like to wait 
until the semantic analysis is ready before applying this patch.

Jason
Jason Merrill - April 25, 2011, 5:06 p.m.
On 04/25/2011 11:34 AM, Ville Voutilainen wrote:
> On 25 April 2011 18:32, Gabriel Dos Reis<gdr@integrable-solutions.net>  wrote:
>>>   typedef int cp_cv_quals;
>>> +/* A type-qualifier, or bitmask therefore, using the VIRT_SPEC
>>> +   constants.  */
>>> +typedef int cp_virt_specifiers;
>> could we use enums instead?
>
> No reason not to, except that we don't for the cp_cv_quals above. :) I followed
> the same approach.

Sure, let's use enums for the named values.  But I think we still want 
to use the int typedef for variables and parameters.

Jason
ville - April 25, 2011, 5:23 p.m.
On 25 April 2011 20:06, Jason Merrill <jason@redhat.com> wrote:
>>> could we use enums instead?
>> No reason not to, except that we don't for the cp_cv_quals above. :) I
>> followed
>> the same approach.
> Sure, let's use enums for the named values.  But I think we still want to
> use the int typedef for variables and parameters.

Would you like me to convert the cp_cv_quals values to enums in the same go?

Where should I put the flags for semantic analysis? DECL_LANG_FLAG?
Or TREE_LANG_FLAG?
Jason Merrill - April 25, 2011, 6:08 p.m.
On 04/25/2011 01:23 PM, Ville Voutilainen wrote:
> Would you like me to convert the cp_cv_quals values to enums in the same go?

Sure.

> Where should I put the flags for semantic analysis? DECL_LANG_FLAG?
> Or TREE_LANG_FLAG?

Use a two-bit bit-field in lang_decl_fn.  To avoid a size increase for 
that struct, since it seems (oddly) that we haven't been using 
TREE_LANG_FLAG at all for functions, let's move thunk_p and this_thunk_p 
to TREE_LANG_FLAG.

Jason
Gabriel Dos Reis - April 26, 2011, 1:43 a.m.
On Mon, Apr 25, 2011 at 10:34 AM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 25 April 2011 18:32, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>>>  typedef int cp_cv_quals;
>>> +/* A type-qualifier, or bitmask therefore, using the VIRT_SPEC
>>> +   constants.  */
>>> +typedef int cp_virt_specifiers;
>> could we use enums instead?
>
> No reason not to, except that we don't for the cp_cv_quals above. :) I followed
> the same approach.

yes, I know but you have the opportunity to take a right step :-)
Gabriel Dos Reis - April 26, 2011, 2:15 a.m.
On Mon, Apr 25, 2011 at 12:23 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 25 April 2011 20:06, Jason Merrill <jason@redhat.com> wrote:
>>>> could we use enums instead?
>>> No reason not to, except that we don't for the cp_cv_quals above. :) I
>>> followed
>>> the same approach.
>> Sure, let's use enums for the named values.  But I think we still want to
>> use the int typedef for variables and parameters.
>
> Would you like me to convert the cp_cv_quals values to enums in the same go?

when you do, could you test a bootstrap with a C++ compiler? (Just to make sure
that no implicit conversion int -> enum slips in.
Gabriel Dos Reis - April 27, 2011, 9:56 p.m.
On Wed, Apr 27, 2011 at 4:05 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 27 April 2011 10:14, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>> The -fpermissive because there are conversions from literals to char*,
>> and c++ nowadays doesn't like that. I'm not at the build machine right
>> now, so I'll check
>> later how it fared.
>
> Seems to fall over itself in a bunch of places. C++ bootstrap smells
> like a red herring
> to me at this point.
>

Hmm, do you mean GCC fails to bootstrap with C++ a compiler before your mods?


-- Gaby
ville - April 27, 2011, 9:58 p.m.
On 28 April 2011 00:56, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>> Seems to fall over itself in a bunch of places. C++ bootstrap smells
>> like a red herring
>> to me at this point.
> Hmm, do you mean GCC fails to bootstrap with C++ a compiler before your mods?

I did make distclean, followed by
CC=g++ GCC=g++ CFLAGS=-fpermissive ../configure --prefix=/usr
--enable-languages=c,c++
and then make. Before my mods. And it doesn't seem to get very far.
Gabriel Dos Reis - April 27, 2011, 10:40 p.m.
On Wed, Apr 27, 2011 at 4:58 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 28 April 2011 00:56, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>>> Seems to fall over itself in a bunch of places. C++ bootstrap smells
>>> like a red herring
>>> to me at this point.
>> Hmm, do you mean GCC fails to bootstrap with C++ a compiler before your mods?
>
> I did make distclean, followed by
> CC=g++ GCC=g++ CFLAGS=-fpermissive ../configure --prefix=/usr
> --enable-languages=c,c++
> and then make. Before my mods. And it doesn't seem to get very far.
>

My configuration command line is:

 /home/gdr/src/gcc.svn/configure --enable-languages=c,c++
--enable-build-with-cxx --disable-multilib --disable-nls

and the builds is progressing quite very well with "g++".
There is no need for manual setting of -fpermissive.

-- Gaby
ville - April 28, 2011, 1:57 p.m.
On 28 April 2011 01:40, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> My configuration command line is:
>  /home/gdr/src/gcc.svn/configure --enable-languages=c,c++
> --enable-build-with-cxx --disable-multilib --disable-nls
> and the builds is progressing quite very well with "g++".
> There is no need for manual setting of -fpermissive.

It goes quite far, but fails at stage1. This is without any patches of mine...

libbackend.a(gimple.o): In function `internal_fn_flags':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:46:
undefined reference to `internal_fn_flags_array'
libbackend.a(gimple-pretty-print.o): In function `internal_fn_name':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
undefined reference to `internal_fn_name_array'
libbackend.a(tree-ssa-dom.o): In function `internal_fn_name':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
undefined reference to `internal_fn_name_array'
collect2: ld returned 1 exit status
make[3]: *** [cc1] Error 1
make[3]: *** Waiting for unfinished jobs....
libbackend.a(gimple.o): In function `internal_fn_flags':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:46:
undefined reference to `internal_fn_flags_array'
libbackend.a(gimple-pretty-print.o): In function `internal_fn_name':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
undefined reference to `internal_fn_name_array'
libbackend.a(tree-ssa-dom.o): In function `internal_fn_name':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
undefined reference to `internal_fn_name_array'
collect2: ld returned 1 exit status
make[3]: *** [lto1] Error 1
libbackend.a(gimple.o): In function `internal_fn_flags':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:46:
undefined reference to `internal_fn_flags_array'
libbackend.a(gimple-pretty-print.o): In function `internal_fn_name':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
undefined reference to `internal_fn_name_array'
libbackend.a(tree-ssa-dom.o): In function `internal_fn_name':
/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
undefined reference to `internal_fn_name_array'
collect2: ld returned 1 exit status
make[3]: *** [cc1plus] Error 1
rm gcov.pod gfdl.pod cpp.pod fsf-funding.pod gcc.pod
make[3]: Leaving directory `/home/ville/projects/c++/gcc-git/gcc/villebuild/gcc'
make[2]: *** [all-stage1-gcc] Error 2
make[2]: Leaving directory `/home/ville/projects/c++/gcc-git/gcc/villebuild'
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory `/home/ville/projects/c++/gcc-git/gcc/villebuild'
make: *** [all] Error 2
Gabriel Dos Reis - April 28, 2011, 2:01 p.m.
On Thu, Apr 28, 2011 at 8:57 AM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 28 April 2011 01:40, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>> My configuration command line is:
>>  /home/gdr/src/gcc.svn/configure --enable-languages=c,c++
>> --enable-build-with-cxx --disable-multilib --disable-nls
>> and the builds is progressing quite very well with "g++".
>> There is no need for manual setting of -fpermissive.
>
> It goes quite far, but fails at stage1. This is without any patches of mine...
>
> libbackend.a(gimple.o): In function `internal_fn_flags':
> /home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:46:
> undefined reference to `internal_fn_flags_array'
> libbackend.a(gimple-pretty-print.o): In function `internal_fn_name':
> /home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
> undefined reference to `internal_fn_name_array'
> libbackend.a(tree-ssa-dom.o): In function `internal_fn_name':
> /home/ville/projects/c++/gcc-git/gcc/villebuild/gcc/../../gcc/internal-fn.h:37:
> undefined reference to `internal_fn_name_array'
> collect2: ld returned 1 exit status

Thanks.  Fixed yesterday evening.

-- Gaby

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e538825..08d939f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4420,6 +4420,11 @@  extern GTY(()) operator_name_info_t assignment_operator_name_info
 
 typedef int cp_cv_quals;
 
+/* A type-qualifier, or bitmask therefore, using the VIRT_SPEC
+   constants.  */
+
+typedef int cp_virt_specifiers;
+
 /* A storage class.  */
 
 typedef enum cp_storage_class {
@@ -4562,6 +4567,8 @@  struct cp_declarator {
       tree parameters;
       /* The cv-qualifiers for the function.  */
       cp_cv_quals qualifiers;
+      /* The virt-specifiers for the function.  */
+      cp_virt_specifiers virt_specifiers;
       /* The exception-specification for the function.  */
       tree exception_specification;
       /* The late-specified return type, if any.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7d3121c..bf28172 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -936,7 +936,7 @@  clear_decl_specs (cp_decl_specifier_seq *decl_specs)
    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
 
 static cp_declarator *make_call_declarator
-  (cp_declarator *, tree, cp_cv_quals, tree, tree);
+  (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree);
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
@@ -1101,6 +1101,7 @@  cp_declarator *
 make_call_declarator (cp_declarator *target,
 		      tree parms,
 		      cp_cv_quals cv_qualifiers,
+		      cp_virt_specifiers virt_specifiers,
 		      tree exception_specification,
 		      tree late_return_type)
 {
@@ -1110,6 +1111,7 @@  make_call_declarator (cp_declarator *target,
   declarator->declarator = target;
   declarator->u.function.parameters = parms;
   declarator->u.function.qualifiers = cv_qualifiers;
+  declarator->u.function.virt_specifiers = virt_specifiers;
   declarator->u.function.exception_specification = exception_specification;
   declarator->u.function.late_return_type = late_return_type;
   if (target)
@@ -1689,6 +1691,8 @@  static enum tree_code cp_parser_ptr_operator
   (cp_parser *, tree *, cp_cv_quals *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
+static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
+  (cp_parser *);
 static tree cp_parser_late_return_type_opt
   (cp_parser *);
 static tree cp_parser_declarator_id
@@ -7648,6 +7652,7 @@  cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
     quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
 	     ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
     declarator = make_call_declarator (declarator, param_list, quals,
+				       VIRT_SPEC_UNSPECIFIED,
 				       exception_spec,
                                        /*late_return_type=*/NULL_TREE);
     declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
@@ -14860,6 +14865,7 @@  cp_parser_direct_declarator (cp_parser* parser,
 	      if (member_p || cp_parser_parse_definitely (parser))
 		{
 		  cp_cv_quals cv_quals;
+		  cp_virt_specifiers virt_specifiers;
 		  tree exception_specification;
 		  tree late_return;
 
@@ -14876,6 +14882,8 @@  cp_parser_direct_declarator (cp_parser* parser,
 		  /* And the exception-specification.  */
 		  exception_specification
 		    = cp_parser_exception_specification_opt (parser);
+		  /* Parse the virt-specifier-seq.  */
+		  virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
 
 		  late_return
 		    = cp_parser_late_return_type_opt (parser);
@@ -14884,6 +14892,7 @@  cp_parser_direct_declarator (cp_parser* parser,
 		  declarator = make_call_declarator (declarator,
 						     params,
 						     cv_quals,
+						     virt_specifiers,
 						     exception_specification,
 						     late_return);
 		  /* Any subsequent parameter lists are to do with
@@ -15391,6 +15400,62 @@  cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
   return cv_quals;
 }
 
+/* Parse an (optional) virt-specifier-seq.
+
+   virt-specifier-seq:
+     virt-specifier virt-specifier-seq [opt]
+
+   virt-specifier:
+     override
+     final
+
+   Returns a bitmask representing the virt-specifiers.  */
+
+static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
+  (cp_parser* parser)
+{
+  cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
+
+  while (true)
+    {
+      cp_token *token;
+      cp_virt_specifiers virt_specifier;
+
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's a virt-specifier-qualifier.  */
+      if (token->type != CPP_NAME)
+        break;
+      if (!strcmp(IDENTIFIER_POINTER(token->u.value), "override"))
+        {
+          virt_specifier = VIRT_SPEC_OVERRIDE;
+        }
+      else if (!strcmp(IDENTIFIER_POINTER(token->u.value), "final"))
+        {
+          virt_specifier = VIRT_SPEC_FINAL;
+        }
+      else
+        {
+          virt_specifier = VIRT_SPEC_UNSPECIFIED;
+        }
+
+      if (!virt_specifier)
+	break;
+
+      if (virt_specifiers & virt_specifier)
+	{
+	  error_at (token->location, "duplicate virt-specifier");
+	  cp_lexer_purge_token (parser->lexer);
+	}
+      else
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  virt_specifiers |= virt_specifier;
+	}
+    }
+  return virt_specifiers;
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 0bc98cd..e6a66fa 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2259,6 +2259,15 @@  extern enum machine_mode vector_type_mode (const_tree);
 #define TYPE_QUAL_VOLATILE 0x2
 #define TYPE_QUAL_RESTRICT 0x4
 
+/* Non-static member functions have an optional virt-specifier-seq.
+   There is a VIRT_SPEC value for each virt-specifier.
+   They can be combined by bitwise-or to form the complete set of
+   virt-specifiers for a member function.  */
+
+#define VIRT_SPEC_UNSPECIFIED   0x0
+#define VIRT_SPEC_FINAL         0x1
+#define VIRT_SPEC_OVERRIDE      0x2
+
 /* Encode/decode the named memory support as part of the qualifier.  If more
    than 8 qualifiers are added, these macros need to be adjusted.  */
 #define ENCODE_QUAL_ADDR_SPACE(NUM) ((NUM & 0xFF) << 8)