[Lldb-commits] [lldb] r365698 - [lldb] Fix handling of dollar characters in expr command

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 10 14:04:01 PDT 2019


Author: teemperor
Date: Wed Jul 10 14:04:01 2019
New Revision: 365698

URL: http://llvm.org/viewvc/llvm-project?rev=365698&view=rev
Log:
[lldb] Fix handling of dollar characters in expr command

Added:
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/TestDollarInVariable.py
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/main.c
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/TestUnicodeInVariable.py
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/main.cpp
Modified:
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/Makefile?rev=365698&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/Makefile Wed Jul 10 14:04:01 2019
@@ -0,0 +1,3 @@
+LEVEL = ../../make
+C_SOURCES := main.c
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/TestDollarInVariable.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/TestDollarInVariable.py?rev=365698&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/TestDollarInVariable.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/TestDollarInVariable.py Wed Jul 10 14:04:01 2019
@@ -0,0 +1,4 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(), None)

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/main.c?rev=365698&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/main.c (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/dollar-in-variable/main.c Wed Jul 10 14:04:01 2019
@@ -0,0 +1,21 @@
+// Make sure we correctly handle $ in variable names.
+
+int main() {
+  // Some variables that might conflict with our variables below.
+  int __lldb_expr_result = 2;
+  int $$foo = 1;
+  int R0 = 2;
+
+  // Some variables with dollar signs that should work (and shadow
+  // any built-in LLDB variables).
+  int $__lldb_expr_result = 11;
+  int $foo = 12;
+  int $R0 = 13;
+  int $0 = 14;
+
+  //%self.expect("expr $__lldb_expr_result", substrs=['(int) $0 = 11'])
+  //%self.expect("expr $foo", substrs=['(int)', ' = 12'])
+  //%self.expect("expr $R0", substrs=['(int)', ' = 13'])
+  //%self.expect("expr int $foo = 123", error=True, substrs=["declaration conflicts"])
+  return 0; //%self.expect("expr $0", substrs=['(int)', ' = 14'])
+}

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/Makefile?rev=365698&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/Makefile Wed Jul 10 14:04:01 2019
@@ -0,0 +1,4 @@
+LEVEL = ../../make
+CXX_SOURCES := main.cpp
+CXX_FLAGS_EXTRA := -finput-charset=UTF-8 -fextended-identifiers
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/TestUnicodeInVariable.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/TestUnicodeInVariable.py?rev=365698&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/TestUnicodeInVariable.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/TestUnicodeInVariable.py Wed Jul 10 14:04:01 2019
@@ -0,0 +1,4 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(), None)

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/main.cpp?rev=365698&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/unicode-in-variable/main.cpp Wed Jul 10 14:04:01 2019
@@ -0,0 +1,17 @@
+// Make sure we correctly handle unicode in variable names.
+
+struct A {
+  // We need a member variable in the context that could shadow our local
+  // variable. If our optimization code fails to handle this, then we won't
+  // correctly inject our local variable so that it won't get shadowed.
+  int foob\u00E1r = 2;
+  int foo() {
+    int foob\u00E1r = 3;
+    return foob\u00E1r; //%self.expect("expr foobár", substrs=['(int)', ' = 3'])
+  }
+};
+
+int main() {
+  A a;
+  return a.foo();
+}

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp?rev=365698&r1=365697&r2=365698&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp Wed Jul 10 14:04:01 2019
@@ -9,6 +9,8 @@
 #include "ClangExpressionSourceCode.h"
 
 #include "clang/Basic/CharInfo.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
 #include "llvm/ADT/StringRef.h"
 
 #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
@@ -164,44 +166,90 @@ static void AddMacros(const DebugMacros
   }
 }
 
-/// Checks if the expression body contains the given variable as a token.
-/// \param body The expression body.
-/// \param var The variable token we are looking for.
-/// \return True iff the expression body containes the variable as a token.
-static bool ExprBodyContainsVar(llvm::StringRef body, llvm::StringRef var) {
-  assert(var.find_if([](char c) { return !clang::isIdentifierBody(c); }) ==
-             llvm::StringRef::npos &&
-         "variable contains non-identifier chars?");
-
-  size_t start = 0;
-  // Iterate over all occurences of the variable string in our expression.
-  while ((start = body.find(var, start)) != llvm::StringRef::npos) {
-    // We found our variable name in the expression. Check that the token
-    // that contains our needle is equal to our variable and not just contains
-    // the character sequence by accident.
-    // Prevents situations where we for example inlcude the variable 'FOO' in an
-    // expression like 'FOObar + 1'.
-    bool has_characters_before =
-        start != 0 && clang::isIdentifierBody(body[start - 1]);
-    bool has_characters_after =
-        start + var.size() < body.size() &&
-        clang::isIdentifierBody(body[start + var.size()]);
-
-    // Our token just contained the variable name as a substring. Continue
-    // searching the rest of the expression.
-    if (has_characters_before || has_characters_after) {
-      ++start;
+namespace {
+/// Allows checking if a token is contained in a given expression.
+class TokenVerifier {
+  /// The tokens we found in the expression.
+  llvm::StringSet<> m_tokens;
+
+public:
+  TokenVerifier(std::string body);
+  /// Returns true iff the given expression body contained a token with the
+  /// given content.
+  bool hasToken(llvm::StringRef token) const {
+    return m_tokens.find(token) != m_tokens.end();
+  }
+};
+} // namespace
+
+TokenVerifier::TokenVerifier(std::string body) {
+  using namespace clang;
+
+  // We only care about tokens and not their original source locations. If we
+  // move the whole expression to only be in one line we can simplify the
+  // following code that extracts the token contents.
+  std::replace(body.begin(), body.end(), '\n', ' ');
+  std::replace(body.begin(), body.end(), '\r', ' ');
+
+  FileSystemOptions file_opts;
+  FileManager file_mgr(file_opts,
+                       FileSystem::Instance().GetVirtualFileSystem());
+
+  // Let's build the actual source code Clang needs and setup some utility
+  // objects.
+  llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
+  llvm::IntrusiveRefCntPtr<DiagnosticOptions> diags_opts(
+      new DiagnosticOptions());
+  DiagnosticsEngine diags(diag_ids, diags_opts);
+  clang::SourceManager SM(diags, file_mgr);
+  auto buf = llvm::MemoryBuffer::getMemBuffer(body);
+
+  FileID FID = SM.createFileID(clang::SourceManager::Unowned, buf.get());
+
+  // Let's just enable the latest ObjC and C++ which should get most tokens
+  // right.
+  LangOptions Opts;
+  Opts.ObjC = true;
+  Opts.DollarIdents = true;
+  Opts.CPlusPlus17 = true;
+  Opts.LineComment = true;
+
+  Lexer lex(FID, buf.get(), SM, Opts);
+
+  Token token;
+  bool exit = false;
+  while (!exit) {
+    // Returns true if this is the last token we get from the lexer.
+    exit = lex.LexFromRawLexer(token);
+
+    // Extract the column number which we need to extract the token content.
+    // Our expression is just one line, so we don't need to handle any line
+    // numbers here.
+    bool invalid = false;
+    unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid);
+    if (invalid)
       continue;
-    }
-    return true;
+    // Column numbers start at 1, but indexes in our string start at 0.
+    --start;
+
+    // Annotations don't have a length, so let's skip them.
+    if (token.isAnnotation())
+      continue;
+
+    // Extract the token string from our source code and store it.
+    std::string token_str = body.substr(start, token.getLength());
+    if (token_str.empty())
+      continue;
+    m_tokens.insert(token_str);
   }
-  return false;
 }
 
 static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
                                   StreamString &stream,
                                   const std::string &expr,
                                   lldb::LanguageType wrapping_language) {
+  TokenVerifier tokens(expr);
+
   for (size_t i = 0; i < var_list_sp->GetSize(); i++) {
     lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
 
@@ -213,7 +261,7 @@ static void AddLocalVariableDecls(const
     if (!var_name || var_name == ".block_descriptor")
       continue;
 
-    if (!expr.empty() && !ExprBodyContainsVar(expr, var_name.GetStringRef()))
+    if (!expr.empty() && !tokens.hasToken(var_name.GetStringRef()))
       continue;
 
     if ((var_name == "self" || var_name == "_cmd") &&




More information about the lldb-commits mailing list