Michael137 updated this revision to Diff 469282.
Michael137 added a comment.

- Add test case


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136306/new/

https://reviews.llvm.org/D136306

Files:
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
  lldb/test/API/functionalities/step-avoids-regexp/TestStepAvoidsRegexp.py
  lldb/test/API/functionalities/step-avoids-regexp/main.cpp
  lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp

Index: lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
===================================================================
--- lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
+++ lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
@@ -114,13 +114,55 @@
       {"llvm::Optional<llvm::MCFixupKind>::operator*() const volatile &&",
        "llvm::Optional<llvm::MCFixupKind>", "operator*", "()",
        "const volatile &&", "llvm::Optional<llvm::MCFixupKind>::operator*"},
+      {"void foo<Dummy<char [10]>>()",
+       "", "foo<Dummy<char [10]>>", "()", "", "foo<Dummy<char [10]>>"},
 
       // auto return type
       {"auto std::test_return_auto<int>() const", "std",
        "test_return_auto<int>", "()", "const", "std::test_return_auto<int>"},
       {"decltype(auto) std::test_return_auto<int>(int) const", "std",
        "test_return_auto<int>", "(int)", "const",
-       "std::test_return_auto<int>"}};
+       "std::test_return_auto<int>"},
+  
+      // abi_tag on class
+      {"v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>> "
+       "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>"
+       "::method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>>(int, v1::v2::Dummy<int>) const &&",
+       // Context
+       "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>",
+       // Basename
+       "method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>>", 
+       // Args, qualifiers
+       "(int, v1::v2::Dummy<int>)", "const &&",
+       // Full scope-qualified name without args
+       "v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>"
+       "::method2<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>>"},
+
+      // abi_tag on free function and template argument
+      {"v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>> "
+       "v1::v2::with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]"
+       "<v1::v2::Dummy[abi:c1][abi:c2]<int>>>(int, v1::v2::Dummy<int>) const &&",
+       // Context
+       "v1::v2",
+       // Basename
+       "with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>>",
+       // Args, qualifiers
+       "(int, v1::v2::Dummy<int>)", "const &&",
+       // Full scope-qualified name without args
+       "v1::v2::with_tag_in_ns[abi:f1][abi:f2]<v1::v2::Dummy[abi:c1][abi:c2]<v1::v2::Dummy[abi:c1][abi:c2]<int>>>"},
+
+      // abi_tag with special characters
+      {"auto ns::with_tag_in_ns[abi:special tag,0.0][abi:special tag,1.0]<Dummy<int>>"
+       "(float) const &&",
+       // Context
+       "ns",
+       // Basename
+       "with_tag_in_ns[abi:special tag,0.0][abi:special tag,1.0]<Dummy<int>>",
+       // Args, qualifiers
+       "(float)", "const &&",
+       // Full scope-qualified name without args
+       "ns::with_tag_in_ns[abi:special tag,0.0][abi:special tag,1.0]<Dummy<int>>"},
+  };
 
   for (const auto &test : test_cases) {
     CPlusPlusLanguage::MethodName method(ConstString(test.input));
Index: lldb/test/API/functionalities/step-avoids-regexp/main.cpp
===================================================================
--- lldb/test/API/functionalities/step-avoids-regexp/main.cpp
+++ lldb/test/API/functionalities/step-avoids-regexp/main.cpp
@@ -1,4 +1,6 @@
 namespace ignore {
+struct Dummy {};
+
 template <typename T> auto auto_ret(T x) { return 0; }
 [[gnu::abi_tag("test")]] int with_tag() { return 0; }
 template <typename T> [[gnu::abi_tag("test")]] int with_tag_template() {
@@ -8,9 +10,15 @@
 template <typename T> decltype(auto) decltype_auto_ret(T x) { return 0; }
 } // namespace ignore
 
+template <typename T>
+[[gnu::abi_tag("test")]] ignore::Dummy with_tag_template_returns_ignore(T x) {
+  return {};
+}
+
 int main() {
   auto v1 = ignore::auto_ret<int>(5);
   auto v2 = ignore::with_tag();
   auto v3 = ignore::decltype_auto_ret<int>(5);
   auto v4 = ignore::with_tag_template<int>();
+  auto v5 = with_tag_template_returns_ignore<int>(5);
 }
Index: lldb/test/API/functionalities/step-avoids-regexp/TestStepAvoidsRegexp.py
===================================================================
--- lldb/test/API/functionalities/step-avoids-regexp/TestStepAvoidsRegexp.py
+++ lldb/test/API/functionalities/step-avoids-regexp/TestStepAvoidsRegexp.py
@@ -37,13 +37,10 @@
         self.thread.StepInto()
         self.hit_correct_function("main")
 
-    @skipIfWindows
-    @expectedFailureAll(bugnumber="rdar://100645742")
-    def test_step_avoid_regex_abi_tagged_template(self):
-        """Tests stepping into an ABI tagged function that matches the avoid regex"""
-        self.build()
-        (_, _, self.thread, _) = lldbutil.run_to_source_breakpoint(self, "with_tag_template", lldb.SBFileSpec('main.cpp'))
-
         # Try to step into ignore::with_tag_template
         self.thread.StepInto()
         self.hit_correct_function("main")
+
+        # Step into with_tag_template_returns_ignore (outside 'ignore::' namespace)
+        self.thread.StepInto()
+        self.hit_correct_function("with_tag_template_returns_ignore")
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
@@ -117,6 +117,7 @@
   void Advance();
   void TakeBack();
   bool ConsumeToken(clang::tok::TokenKind kind);
+
   template <typename... Ts> bool ConsumeToken(Ts... kinds);
   Bookmark SetBookmark();
   size_t GetCurrentPosition();
@@ -164,6 +165,16 @@
   // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass'
   bool ConsumeTypename();
 
+  /// Consumes ABI tags enclosed within '[abi:' ... ']'
+  ///
+  /// Since there is no restriction on what the ABI tag
+  /// string may contain, this API supports parsing a small
+  /// set of special characters.
+  ///
+  /// The following regex describes the set of supported characters:
+  ///   [A-Za-z,.\s\d]+
+  bool ConsumeAbiTag();
+
   llvm::Optional<ParsedNameRanges> ParseFullNameImpl();
   llvm::StringRef GetTextForRange(const Range &range);
 
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
@@ -226,9 +226,15 @@
       Advance();
       break;
     case tok::l_square:
-      if (!ConsumeBrackets(tok::l_square, tok::r_square))
+      // Handle templates tagged with an ABI tag.
+      // An example demangled/prettified version is:
+      //   func[abi:tag1][abi:tag2]<type[abi:tag3]>(int)
+      if (ConsumeAbiTag())
+        can_open_template = true;
+      else if (ConsumeBrackets(tok::l_square, tok::r_square))
+        can_open_template = false;
+      else
         return false;
-      can_open_template = false;
       break;
     case tok::l_paren:
       if (!ConsumeArguments())
@@ -249,6 +255,34 @@
   return true;
 }
 
+bool CPlusPlusNameParser::ConsumeAbiTag() {
+  Bookmark start_position = SetBookmark();
+  if (!ConsumeToken(tok::l_square)) {
+    return false;
+  }
+
+  if (HasMoreTokens() && Peek().is(tok::raw_identifier)
+      && Peek().getRawIdentifier() == "abi") {
+      Advance();
+  } else {
+      return false;
+  }
+
+  if (!ConsumeToken(tok::colon))
+    return false;
+
+  // Consume the actual tag string (and allow some special characters)
+  while (ConsumeToken(tok::raw_identifier, tok::comma,
+                      tok::period, tok::numeric_constant))
+    ;
+
+  if (!ConsumeToken(tok::r_square))
+    return false;
+
+  start_position.Remove();
+  return true;
+}
+
 bool CPlusPlusNameParser::ConsumeAnonymousNamespace() {
   Bookmark start_position = SetBookmark();
   if (!ConsumeToken(tok::l_paren)) {
@@ -519,6 +553,19 @@
       Advance();
       state = State::AfterIdentifier;
       break;
+    case tok::l_square: // ABI tag
+      // Handles types or functions that were tagged
+      // with, e.g.,
+      //   [[gnu::abi_tag("tag1","tag2")]] func()
+      // and demangled/prettified into:
+      //   func[abi:tag1][abi:tag2]()
+      if (state == State::AfterIdentifier) {
+        // Anything other than an ABI tag is invalid at this point.
+        if (!ConsumeAbiTag()) {
+          continue_parsing = false;
+        }
+      }
+      break;
     case tok::l_paren: {
       if (state == State::Beginning || state == State::AfterTwoColons) {
         // (anonymous namespace)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to