public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Support cfg expansions predicates
@ 2022-06-08 12:03 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-08 12:03 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9f36d99b4067df98608dc3535e6c786d1897837e

commit 9f36d99b4067df98608dc3535e6c786d1897837e
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Thu Feb 3 15:37:06 2022 +0000

    Support cfg expansions predicates
    
    Config expansion can be not, any, or all predicate to enforce the config
    expansion logic.
    
    This patch refactors the MacroParser to be named AttributeParser as it is
    only used to parse attributes into MetaItems that we can work with and
    do expansion logic upon. This handles the case of parsing the
    inner-meta-item of not(A) to parse it into MetaListNameValueStr and tidies
    up some of the code in the area.
    
    Fixes #901

Diff:
---
 gcc/rust/ast/rust-ast-full-test.cc         | 100 +++++++++++++----------------
 gcc/rust/ast/rust-ast.h                    |   2 +-
 gcc/rust/ast/rust-macro.h                  |  10 +--
 gcc/testsuite/rust/compile/cfg2.rs         |  13 ++++
 gcc/testsuite/rust/compile/cfg3.rs         |  11 ++++
 gcc/testsuite/rust/compile/cfg4.rs         |  11 ++++
 gcc/testsuite/rust/execute/torture/cfg4.rs |  38 +++++++++++
 7 files changed, 124 insertions(+), 61 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index aff148abadf..68f6f8c1ab7 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -3886,6 +3886,7 @@ MetaItemInner::~MetaItemInner () = default;
 std::unique_ptr<MetaNameValueStr>
 MetaItemInner::to_meta_name_value_str () const
 {
+  // TODO parse foo = bar
   return nullptr;
 }
 
@@ -4103,8 +4104,8 @@ Attribute::parse_attr_to_meta_item ()
   if (!has_attr_input () || is_parsed_to_meta_item ())
     return;
 
-  std::unique_ptr<AttrInput> converted_input (
-    attr_input->parse_to_meta_item ());
+  auto res = attr_input->parse_to_meta_item ();
+  std::unique_ptr<AttrInput> converted_input (res);
 
   if (converted_input != nullptr)
     attr_input = std::move (converted_input);
@@ -4121,7 +4122,7 @@ DelimTokenTree::parse_to_meta_item () const
    * to token stream */
   std::vector<std::unique_ptr<Token> > token_stream = to_token_stream ();
 
-  MacroParser parser (std::move (token_stream));
+  AttributeParser parser (std::move (token_stream));
   std::vector<std::unique_ptr<MetaItemInner> > meta_items (
     parser.parse_meta_item_seq ());
 
@@ -4129,7 +4130,7 @@ DelimTokenTree::parse_to_meta_item () const
 }
 
 std::unique_ptr<MetaItemInner>
-MacroParser::parse_meta_item_inner ()
+AttributeParser::parse_meta_item_inner ()
 {
   // if first tok not identifier, not a "special" case one
   if (peek_token ()->get_id () != IDENTIFIER)
@@ -4144,15 +4145,15 @@ MacroParser::parse_meta_item_inner ()
 	case FLOAT_LITERAL:
 	case TRUE_LITERAL:
 	case FALSE_LITERAL:
-	  // stream_pos++;
 	  return parse_meta_item_lit ();
+
 	case SUPER:
 	case SELF:
 	case CRATE:
 	case DOLLAR_SIGN:
-	  case SCOPE_RESOLUTION: {
-	    return parse_path_meta_item ();
-	  }
+	case SCOPE_RESOLUTION:
+	  return parse_path_meta_item ();
+
 	default:
 	  rust_error_at (peek_token ()->get_locus (),
 			 "unrecognised token '%s' in meta item",
@@ -4208,10 +4209,13 @@ MacroParser::parse_meta_item_inner ()
       return nullptr;
     }
 
-  /* HACK: parse parenthesised sequence, and then try conversions to other
-   * stuff */
-  std::vector<std::unique_ptr<MetaItemInner> > meta_items
-    = parse_meta_item_seq ();
+  // is it one of those special cases like not?
+  if (peek_token ()->get_id () == IDENTIFIER)
+    {
+      return parse_path_meta_item ();
+    }
+
+  auto meta_items = parse_meta_item_seq ();
 
   // pass for meta name value str
   std::vector<MetaNameValueStr> meta_name_value_str_items;
@@ -4234,23 +4238,25 @@ MacroParser::parse_meta_item_inner ()
 				  std::move (meta_name_value_str_items)));
     }
 
-  // pass for meta list idents
-  /*std::vector<Identifier> ident_items;
-  for (const auto& item : meta_items) {
-      std::unique_ptr<Identifier> converted_ident(item->to_ident_item());
-      if (converted_ident == nullptr) {
-	  ident_items.clear();
-	  break;
-      }
-      ident_items.push_back(std::move(*converted_ident));
-  }
-  // if valid return this
-  if (!ident_items.empty()) {
-      return std::unique_ptr<MetaListIdents>(new
-  MetaListIdents(std::move(ident),
-  std::move(ident_items)));
-  }*/
-  // as currently no meta list ident, currently no path. may change in future
+  // // pass for meta list idents
+  // std::vector<Identifier> ident_items;
+  // for (const auto &item : meta_items)
+  //   {
+  //     std::unique_ptr<Identifier> converted_ident (item->to_ident_item ());
+  //     if (converted_ident == nullptr)
+  //       {
+  //         ident_items.clear ();
+  //         break;
+  //       }
+  //     ident_items.push_back (std::move (*converted_ident));
+  //   }
+  // // if valid return this
+  // if (!ident_items.empty ())
+  //   {
+  //     return std::unique_ptr<MetaListIdents> (
+  //       new MetaListIdents (std::move (ident), std::move (ident_items)));
+  //   }
+  // // as currently no meta list ident, currently no path. may change in future
 
   // pass for meta list paths
   std::vector<SimplePath> path_items;
@@ -4276,13 +4282,13 @@ MacroParser::parse_meta_item_inner ()
 }
 
 bool
-MacroParser::is_end_meta_item_tok (TokenId id) const
+AttributeParser::is_end_meta_item_tok (TokenId id) const
 {
   return id == COMMA || id == RIGHT_PAREN;
 }
 
 std::unique_ptr<MetaItem>
-MacroParser::parse_path_meta_item ()
+AttributeParser::parse_path_meta_item ()
 {
   SimplePath path = parse_simple_path ();
   if (path.is_empty ())
@@ -4334,15 +4340,8 @@ MacroParser::parse_path_meta_item ()
 /* Parses a parenthesised sequence of meta item inners. Parentheses are
  * required here. */
 std::vector<std::unique_ptr<MetaItemInner> >
-MacroParser::parse_meta_item_seq ()
+AttributeParser::parse_meta_item_seq ()
 {
-  if (stream_pos != 0)
-    {
-      // warning?
-      rust_debug ("WARNING: stream pos for parse_meta_item_seq is not 0!");
-    }
-
-  // int i = 0;
   int vec_length = token_stream.size ();
   std::vector<std::unique_ptr<MetaItemInner> > meta_items;
 
@@ -4414,7 +4413,7 @@ DelimTokenTree::to_token_stream () const
 }
 
 Literal
-MacroParser::parse_literal ()
+AttributeParser::parse_literal ()
 {
   const std::unique_ptr<Token> &tok = peek_token ();
   switch (tok->get_id ())
@@ -4453,7 +4452,7 @@ MacroParser::parse_literal ()
 }
 
 SimplePath
-MacroParser::parse_simple_path ()
+AttributeParser::parse_simple_path ()
 {
   bool has_opening_scope_res = false;
   if (peek_token ()->get_id () == SCOPE_RESOLUTION)
@@ -4494,7 +4493,7 @@ MacroParser::parse_simple_path ()
 }
 
 SimplePathSegment
-MacroParser::parse_simple_path_segment ()
+AttributeParser::parse_simple_path_segment ()
 {
   const std::unique_ptr<Token> &tok = peek_token ();
   switch (tok->get_id ())
@@ -4527,7 +4526,7 @@ MacroParser::parse_simple_path_segment ()
 }
 
 std::unique_ptr<MetaItemLitExpr>
-MacroParser::parse_meta_item_lit ()
+AttributeParser::parse_meta_item_lit ()
 {
   Location locus = peek_token ()->get_locus ();
   LiteralExpr lit_expr (parse_literal (), {}, locus);
@@ -4538,27 +4537,16 @@ MacroParser::parse_meta_item_lit ()
 bool
 AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const
 {
-  /* NOTE: assuming that only first item must be true - cfg should only have one
-   * item, and cfg_attr only has first item as predicate. TODO ensure that this
-   * is correct. */
   if (items.empty ())
     return false;
 
-  // DEBUG
-  rust_debug (
-    "asked to check cfg of attrinputmetaitemcontainer - delegating to "
-    "first item. container: '%s'",
-    as_string ().c_str ());
-
-  return items[0]->check_cfg_predicate (session);
-
-  /*for (const auto &inner_item : items)
+  for (const auto &inner_item : items)
     {
       if (!inner_item->check_cfg_predicate (session))
 	return false;
     }
 
-  return true;*/
+  return true;
 }
 
 bool
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 1847aea49e9..0c22c37903f 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -816,7 +816,7 @@ class MetaWord;
 class MetaListPaths;
 
 // Forward decl - defined in rust-macro.h
-struct MetaListNameValueStr;
+class MetaListNameValueStr;
 
 /* Base statement abstract class. Note that most "statements" are not allowed in
  * top-level module scope - only a subclass of statements called "items" are. */
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 44c0701d324..6ea7de821ad 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -610,6 +610,8 @@ class MetaListNameValueStr : public MetaItem
   Identifier ident;
   std::vector<MetaNameValueStr> strs;
 
+  // FIXME add location info
+
 public:
   MetaListNameValueStr (Identifier ident, std::vector<MetaNameValueStr> strs)
     : ident (std::move (ident)), strs (std::move (strs))
@@ -690,7 +692,7 @@ public:
 // Object that parses macros from a token stream.
 /* TODO: would "AttributeParser" be a better name? MetaItems are only for
  * attributes, I believe */
-struct MacroParser
+struct AttributeParser
 {
 private:
   // TODO: might as well rewrite to use lexer tokens
@@ -698,12 +700,12 @@ private:
   int stream_pos;
 
 public:
-  MacroParser (std::vector<std::unique_ptr<Token> > token_stream,
-	       int stream_start_pos = 0)
+  AttributeParser (std::vector<std::unique_ptr<Token> > token_stream,
+		   int stream_start_pos = 0)
     : token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
   {}
 
-  ~MacroParser () = default;
+  ~AttributeParser () = default;
 
   std::vector<std::unique_ptr<MetaItemInner> > parse_meta_item_seq ();
 
diff --git a/gcc/testsuite/rust/compile/cfg2.rs b/gcc/testsuite/rust/compile/cfg2.rs
new file mode 100644
index 00000000000..939384c5b7d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg2.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+struct Foo;
+impl Foo {
+    #[cfg(not(A))]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+    // { dg-error "failed to resolve method for .test." "" { target *-*-* } .-1 }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/cfg3.rs b/gcc/testsuite/rust/compile/cfg3.rs
new file mode 100644
index 00000000000..d6ffab6bfc6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg3.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w -frust-cfg=A -frust-cfg=B" }
+struct Foo;
+impl Foo {
+    #[cfg(all(A, B))]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/compile/cfg4.rs b/gcc/testsuite/rust/compile/cfg4.rs
new file mode 100644
index 00000000000..2834c277ddf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/cfg4.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+struct Foo;
+impl Foo {
+    #[cfg(any(A, B))]
+    fn test(&self) {}
+}
+
+fn main() {
+    let a = Foo;
+    a.test();
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg4.rs b/gcc/testsuite/rust/execute/torture/cfg4.rs
new file mode 100644
index 00000000000..d1c2a22a0ff
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg4.rs
@@ -0,0 +1,38 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\ntest2\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    #[cfg(A)]
+    fn test(&self) {
+        unsafe {
+            let a = "test1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+
+    #[cfg(not(B))]
+    fn test2(&self) {
+        unsafe {
+            let a = "test2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.test();
+    a.test2();
+
+    0
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-08 12:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 12:03 [gcc/devel/rust/master] Support cfg expansions predicates Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).