[Lldb-commits] [lldb] r331227 - Fix expression parser to not accept any type whose basename matches for a type that must exist at root level

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Mon Apr 30 14:06:30 PDT 2018


Author: gclayton
Date: Mon Apr 30 14:06:30 2018
New Revision: 331227

URL: http://llvm.org/viewvc/llvm-project?rev=331227&view=rev
Log:
Fix expression parser to not accept any type whose basename matches for a type that must exist at root level

This patch fixes an issue where we weren't looking for exact matches in the expression parser and also fixed the type lookup logic in the Module.cpp. Tests added to make sure we don't regress.

Differential Revision: https://reviews.llvm.org/D46128


Added:
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
Modified:
    lldb/trunk/source/Core/Module.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile?rev=331227&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile Mon Apr 30 14:06:30 2018
@@ -0,0 +1,3 @@
+LEVEL = ../../../make
+C_SOURCES := main.c
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py?rev=331227&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py Mon Apr 30 14:06:30 2018
@@ -0,0 +1,89 @@
+"""
+Test that we can lookup types correctly in the expression parser
+"""
+
+from __future__ import print_function
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import decorators
+
+class TestTypeLookup(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def check_value(self, value, ivar_name, ivar_value):
+        self.assertTrue(value.GetError().Success(),
+                        "Invalid valobj: %s" % (
+                                value.GetError().GetCString()))
+        ivar = value.GetChildMemberWithName(ivar_name)
+        self.assertTrue(ivar.GetError().Success(),
+                        "Failed to fetch ivar named '%s'" % (ivar_name))
+        self.assertEqual(ivar_value,
+                         ivar.GetValueAsSigned(),
+                         "Got the right value for ivar")
+
+    def test_namespace_only(self):
+        """
+            Test that we fail to lookup a struct type that exists only in a
+            namespace.
+        """
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("main.cpp")
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "Set a breakpoint here", self.main_source_file)
+
+        # Get frame for current thread
+        frame = thread.GetSelectedFrame()
+
+        # Make sure we don't accidentally accept structures that exist only
+        # in namespaces when evaluating expressions with top level types.
+        # Prior to the revision that added this test, we would accidentally
+        # accept types from namespaces, so this will ensure we don't regress
+        # to that behavior again
+        expr_result = frame.EvaluateExpression("*((namespace_only *)&i)")
+        self.assertTrue(expr_result.GetError().Fail(),
+                        "'namespace_only' exists in namespace only")
+
+        # Make sure we can find the correct type in a namespace "a"
+        expr_result = frame.EvaluateExpression("*((a::namespace_only *)&i)")
+        self.check_value(expr_result, "a", 123)
+        # Make sure we can find the correct type in a namespace "b"
+        expr_result = frame.EvaluateExpression("*((b::namespace_only *)&i)")
+        self.check_value(expr_result, "b", 123)
+
+        # Make sure we can find the correct type in the root namespace
+        expr_result = frame.EvaluateExpression("*((namespace_and_file *)&i)")
+        self.check_value(expr_result, "ff", 123)
+        # Make sure we can find the correct type in a namespace "a"
+        expr_result = frame.EvaluateExpression(
+                "*((a::namespace_and_file *)&i)")
+        self.check_value(expr_result, "aa", 123)
+        # Make sure we can find the correct type in a namespace "b"
+        expr_result = frame.EvaluateExpression(
+                "*((b::namespace_and_file *)&i)")
+        self.check_value(expr_result, "bb", 123)
+
+        # Make sure we don't accidentally accept structures that exist only
+        # in namespaces when evaluating expressions with top level types.
+        # Prior to the revision that added this test, we would accidentally
+        # accept types from namespaces, so this will ensure we don't regress
+        # to that behavior again
+        expr_result = frame.EvaluateExpression("*((in_contains_type *)&i)")
+        self.assertTrue(expr_result.GetError().Fail(),
+                        "'in_contains_type' exists in struct only")
+
+        # Make sure we can find the correct type in the root namespace
+        expr_result = frame.EvaluateExpression(
+                "*((contains_type::in_contains_type *)&i)")
+        self.check_value(expr_result, "fff", 123)
+        # Make sure we can find the correct type in a namespace "a"
+        expr_result = frame.EvaluateExpression(
+                "*((a::contains_type::in_contains_type *)&i)")
+        self.check_value(expr_result, "aaa", 123)
+        # Make sure we can find the correct type in a namespace "b"
+        expr_result = frame.EvaluateExpression(
+                "*((b::contains_type::in_contains_type *)&i)")
+        self.check_value(expr_result, "bbb", 123)

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp?rev=331227&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp Mon Apr 30 14:06:30 2018
@@ -0,0 +1,67 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In this test, we define struct that exist might exist at the different
+// levels in the code and test that we can properly locate these types with
+// a varienty of different expressions.
+
+namespace a {
+  struct namespace_only {
+    int a;
+  };
+  struct namespace_and_file {
+    int aa;
+  };
+  struct contains_type {
+    struct in_contains_type {
+      int aaa;
+    };
+  };
+};
+namespace b {
+  struct namespace_only {
+    int b;
+  };
+  struct namespace_and_file {
+    int bb;
+  };
+  struct contains_type {
+    struct in_contains_type {
+      int bbb;
+    };
+  };
+};
+
+struct namespace_and_file {
+  int ff;
+};
+
+struct contains_type {
+  struct in_contains_type {
+    int fff;
+  };
+};
+
+
+int main (int argc, char const *argv[]) {
+  a::namespace_only a_namespace_only = { 1 };
+  a::namespace_and_file a_namespace_and_file = { 2 };
+  a::contains_type::in_contains_type a_in_contains_type = { 3 };
+  b::namespace_only b_namespace_only = { 11 };
+  b::namespace_and_file b_namespace_and_file = { 22 };
+  b::contains_type::in_contains_type b_in_contains_type = { 33 };
+  namespace_and_file file_namespace_and_file = { 44 };
+  contains_type::in_contains_type file_in_contains_type = { 55 };
+  int i = 123; // Provide an integer that can be used for casting
+  // Take address of "i" to ensure it is in memory
+  if (&i == &argc) {
+    i = -1;
+  }
+  return i == -1; // Set a breakpoint here
+}

Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=331227&r1=331226&r2=331227&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Mon Apr 30 14:06:30 2018
@@ -1004,16 +1004,22 @@ size_t Module::FindTypes(
   } else {
     // The type is not in a namespace/class scope, just search for it by
     // basename
-    if (type_class != eTypeClassAny) {
+    if (type_class != eTypeClassAny && !type_basename.empty()) {
       // The "type_name_cstr" will have been modified if we have a valid type
       // class prefix (like "struct", "class", "union", "typedef" etc).
       FindTypes_Impl(sc, ConstString(type_basename), nullptr, append,
                      max_matches, searched_symbol_files, typesmap);
-      typesmap.RemoveMismatchedTypes(type_class);
+      typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
+                                     exact_match);
       num_matches = typesmap.GetSize();
     } else {
       num_matches = FindTypes_Impl(sc, name, nullptr, append, max_matches,
                                    searched_symbol_files, typesmap);
+      if (exact_match) {
+        std::string name_str(name.AsCString(""));
+        typesmap.RemoveMismatchedTypes(type_scope, name_str, type_class,
+                                       exact_match);
+      }
     }
   }
   if (num_matches > 0)

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp?rev=331227&r1=331226&r2=331227&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp Mon Apr 30 14:06:30 2018
@@ -861,13 +861,16 @@ void ClangASTSource::FindExternalVisible
 
     TypeList types;
     SymbolContext null_sc;
-    const bool exact_match = false;
+    const bool exact_match = true;
     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
     if (module_sp && namespace_decl)
       module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
-    else
-      m_target->GetImages().FindTypes(null_sc, name, exact_match, 1,
+    else {
+      SymbolContext sc;
+      sc.module_sp = module_sp;
+      m_target->GetImages().FindTypes(sc, name, exact_match, 1,
                                       searched_symbol_files, types);
+    }
 
     if (size_t num_types = types.GetSize()) {
       for (size_t ti = 0; ti < num_types; ++ti) {




More information about the lldb-commits mailing list