clayborg created this revision.
clayborg added reviewers: jingham, davide, aprantl, labath, lldb-commits.

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.


https://reviews.llvm.org/D46128

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

Index: source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
===================================================================
--- source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -861,13 +861,16 @@
 
     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) {
Index: source/Core/Module.cpp
===================================================================
--- source/Core/Module.cpp
+++ source/Core/Module.cpp
@@ -1019,17 +1019,23 @@
   } 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)
Index: packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
===================================================================
--- packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
+++ packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
@@ -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
+}
Index: packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py
===================================================================
--- packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py
+++ packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestTypeLookup.py
@@ -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 accedentally 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 accedentally 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)
Index: packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile
===================================================================
--- packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile
+++ packages/Python/lldbsuite/test/lang/cpp/type_lookup/Makefile
@@ -0,0 +1,3 @@
+LEVEL = ../../../make
+C_SOURCES := main.c
+include $(LEVEL)/Makefile.rules
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to