From a2af98a999f583677a2a7218cf129abca68697ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Sat, 1 Mar 2014 13:23:26 +0100
Subject: [PATCH] Compiler: Support modifier-style attributes in more places.

The syntaxes

  __attribute__("foo", mixed) x;

and

  __attribute__("foo") mixed x;

are now equivalent.
---
 src/compilation.h |  1 +
 src/language.yacc | 50 +++++++++++++++++++++++++++++++----------------
 src/lex.h         |  1 +
 src/program.c     | 11 +++++++++++
 4 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/src/compilation.h b/src/compilation.h
index 8582d8fa24..cfbff117ff 100644
--- a/src/compilation.h
+++ b/src/compilation.h
@@ -163,6 +163,7 @@
   ZMEMBER(int,local_class_counter,0)
   ZMEMBER(int,catch_level,0)
   ZMEMBER(INT32,current_modifiers,0)
+  ZMEMBER(node *,current_attributes,0)
   ZMEMBER(int,varargs,0)
   ZMEMBER(int, num_create_args, 0)
   ZMEMBER(int, num_inherits, 0)	/* Used during second pass. */
diff --git a/src/language.yacc b/src/language.yacc
index 4ee4dde4dd..aa30623fec 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -292,7 +292,6 @@ int yylex(YYSTYPE *yylval);
 %type <n> TOK_STRING
 %type <n> TOK_NUMBER
 %type <n> TOK_BITS
-%type <n> optional_attributes
 %type <n> optional_rename_inherit
 %type <n> optional_identifier
 %type <n> implicit_identifier
@@ -807,8 +806,8 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star
       push_type(T_FUNCTION);
     }
 
-    if ($2) {
-      node *n = $2;
+    if (Pike_compiler->current_attributes) {
+      node *n = Pike_compiler->current_attributes;
       while (n) {
 	push_type_attribute(CDR(n)->u.sval.u.string);
 	n = CAR(n);
@@ -962,9 +961,9 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star
     free_node($6);
     free_node($11);
     free_node($<n>12);
-    if ($2) free_node($2);
   }
-  | modifiers optional_attributes type_or_error optional_constant optional_stars TOK_IDENTIFIER push_compiler_frame0
+  | modifiers optional_attributes type_or_error
+  optional_constant optional_stars TOK_IDENTIFIER push_compiler_frame0
     error
   {
 #ifdef PIKE_DEBUG
@@ -977,13 +976,9 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star
 #endif
     pop_compiler_frame();
     free_node($6);
-    if ($2)
-      free_node($2);
   }
   | modifiers optional_attributes type_or_error optional_constant optional_stars bad_identifier
   {
-    if ($2)
-      free_node($2);
     compiler_discard_type();
   }
     '(' arguments ')' block_or_semi
@@ -991,12 +986,6 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star
     if ($11) free_node($11);
   }
   | modifiers optional_attributes type_or_error optional_constant name_list ';'
-  {
-    if ($2) {
-      yyerror("Invalid use of attributes in variable declaration.\n");
-      free_node($2);
-    }
-  }
   | inheritance {}
   | import {}
   | constant {}
@@ -1218,8 +1207,23 @@ attribute: TOK_ATTRIBUTE_ID '(' string_constant optional_comma ')'
   }
   ;
 
-optional_attributes: /* empty */ { $$ = 0; }
-  | optional_attributes attribute { $$ = mknode(F_ARG_LIST, $1, $2); }
+optional_attributes: /* empty */
+  {
+    if (Pike_compiler->current_attributes) {
+      free_node(Pike_compiler->current_attributes);
+    }
+    if ((Pike_compiler->current_attributes =
+	 THIS_COMPILATION->lex.attributes)) {
+      add_ref(Pike_compiler->current_attributes);
+    }
+  }
+  | optional_attributes attribute
+  {
+    if ($2) {
+      Pike_compiler->current_attributes =
+	mknode(F_ARG_LIST, Pike_compiler->current_attributes, $2);
+    }
+  }
   ;
 
 optional_stars: optional_stars '*' { $$=$1 + 1; }
@@ -1685,11 +1689,17 @@ name_list: new_name
 new_name: optional_stars TOK_IDENTIFIER
   {
     struct pike_type *type;
+    node *n;
     push_finished_type(Pike_compiler->compiler_frame->current_type);
     if ($1 && (Pike_compiler->compiler_pass == 2) && !TEST_COMPAT (0, 6)) {
       yywarning("The *-syntax in types is obsolete. Use array instead.");
     }
     while($1--) push_type(T_ARRAY);
+    n = Pike_compiler->current_attributes;
+    while(n) {
+      push_type_attribute(CDR(n)->u.sval.u.string);
+      n = CAR(n);
+    }
     type=compiler_pop_type();
     define_variable($2->u.sval.u.string, type,
 		    Pike_compiler->current_modifiers);
@@ -1700,11 +1710,17 @@ new_name: optional_stars TOK_IDENTIFIER
   | optional_stars TOK_IDENTIFIER '='
   {
     struct pike_type *type;
+    node *n;
     push_finished_type(Pike_compiler->compiler_frame->current_type);
     if ($1 && (Pike_compiler->compiler_pass == 2) && !TEST_COMPAT (0, 6)) {
       yywarning("The *-syntax in types is obsolete. Use array instead.");
     }
     while($1--) push_type(T_ARRAY);
+    n = Pike_compiler->current_attributes;
+    while(n) {
+      push_type_attribute(CDR(n)->u.sval.u.string);
+      n = CAR(n);
+    }
     type=compiler_pop_type();
     if ((Pike_compiler->current_modifiers & ID_EXTERN) &&
 	(Pike_compiler->compiler_pass == 1)) {
diff --git a/src/lex.h b/src/lex.h
index 603589c82d..c4cab609ec 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -24,6 +24,7 @@ struct lex
   char *end;
   INT_TYPE current_line;
   INT32 pragmas;
+  node *attributes;
   struct pike_string *current_file;
   int (*current_lexer)(struct lex *, YYSTYPE *);
 };
diff --git a/src/program.c b/src/program.c
index 9363cf8cda..bfe4d78ded 100644
--- a/src/program.c
+++ b/src/program.c
@@ -3398,6 +3398,11 @@ static void toss_compilation_resources(void)
     Pike_compiler->last_file=0;
   }
 
+  if (Pike_compiler->current_attributes) {
+    free_node(Pike_compiler->current_attributes);
+    Pike_compiler->current_attributes = NULL;
+  }
+
   unuse_modules(Pike_compiler->num_used_modules);
 
   free_all_nodes();
@@ -8776,6 +8781,10 @@ static void free_compilation(struct compilation *c)
     free_string(c->lex.current_file);
     c->lex.current_file = NULL;
   }
+  if(c->lex.attributes) {
+    free_node(c->lex.attributes);
+    c->lex.attributes = NULL;
+  }
   if (c->resolve_cache) {
     free_mapping(c->resolve_cache);
     c->resolve_cache = NULL;
@@ -8802,6 +8811,8 @@ static void run_init(struct compilation *c)
   free_string(c->lex.current_file);
   c->lex.current_file=make_shared_string("-");
 
+  c->lex.attributes = NULL;
+
   if (runtime_options & RUNTIME_STRICT_TYPES)
   {
     c->lex.pragmas = ID_STRICT_TYPES;
-- 
GitLab