zequanwu updated this revision to Diff 391454.
zequanwu added a comment.

Add test with `lldb-test symbols --dump-ast` though it printed the methods 
twice. It is considered a separate bug that could be fixed later.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113930

Files:
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/test/Shell/SymbolFile/NativePDB/ast-methods.cpp
  lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp

Index: lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
+++ lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
@@ -1,7 +1,7 @@
 // clang-format off
 // REQUIRES: lld, x86
 
-// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s
+// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /GR- /Fo%t.obj -- %s
 // RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb
 
 // RUN: lldb-test symbols --find=function --name=main --function-flags=full %t.exe \
@@ -13,6 +13,46 @@
 // RUN: lldb-test symbols --find=function --name=varargs_fn --function-flags=full %t.exe \
 // RUN:     | FileCheck %s --check-prefix=FIND-VAR
 
+// RUN: lldb-test symbols --find=function --name=Struct::simple_method --function-flags=full %t.exe \
+// RUN:     | FileCheck %s --check-prefix=FIND-SIMPLE
+
+// RUN: lldb-test symbols --find=function --name=Struct::virtual_method --function-flags=full %t.exe \
+// RUN:     | FileCheck %s --check-prefix=FIND-VIRTUAL
+
+// RUN: lldb-test symbols --find=function --name=Struct::static_method --function-flags=full %t.exe \
+// RUN:     | FileCheck %s --check-prefix=FIND-STATIC-METHOD
+
+// RUN: lldb-test symbols --find=function --name=Struct::overloaded_method --function-flags=full %t.exe \
+// RUN:     | FileCheck %s --check-prefix=FIND-OVERLOAD
+
+struct Struct {
+  int simple_method() {
+    return 1;
+  }
+
+  virtual int virtual_method() {
+    return 2;
+  }
+
+  static int static_method() {
+    return 3;
+  }
+
+  int overloaded_method() {
+    return 4 + overloaded_method('a') + overloaded_method('a', 1);
+  }
+protected:
+  virtual int overloaded_method(char c) {
+    return 5;
+  }
+private:
+  static int overloaded_method(char c, int i, ...) {
+    return 6;
+  }
+};
+
+Struct s;
+
 static int static_fn() {
   return 42;
 }
@@ -22,7 +62,8 @@
 }
 
 int main(int argc, char **argv) {
-  return static_fn() + varargs_fn(argc, argc);
+  return static_fn() + varargs_fn(argc, argc) + s.simple_method() +
+  Struct::static_method() + s.virtual_method() + s.overloaded_method();
 }
 
 // FIND-MAIN:      Function: id = {{.*}}, name = "main"
@@ -33,3 +74,17 @@
 
 // FIND-VAR:      Function: id = {{.*}}, name = "{{.*}}varargs_fn{{.*}}"
 // FIND-VAR-NEXT: FuncType: id = {{.*}}, compiler_type = "int (int, int, ...)"
+
+// FIND-SIMPLE:      Function: id = {{.*}}, name = "{{.*}}Struct::simple_method{{.*}}"
+// FIND-SIMPLE-NEXT: FuncType: id = {{.*}}, compiler_type = "int (void)"
+
+// FIND-VIRTUAL:      Function: id = {{.*}}, name = "{{.*}}Struct::virtual_method{{.*}}"
+// FIND-VIRTUAL-NEXT: FuncType: id = {{.*}}, compiler_type = "int (void)"
+
+// FIND-STATIC-METHOD:      Function: id = {{.*}}, name = "{{.*}}Struct::static_method{{.*}}"
+// FIND-STATIC-METHOD-NEXT: FuncType: id = {{.*}}, compiler_type = "int (void)"
+
+// FIND-OVERLOAD: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
+// FIND-OVERLOAD: FuncType: id = {{.*}}, compiler_type = "int (void)"
+// FIND-OVERLOAD: FuncType: id = {{.*}}, compiler_type = "int (char)"
+// FIND-OVERLOAD: FuncType: id = {{.*}}, compiler_type = "int (char, int, ...)"
Index: lldb/test/Shell/SymbolFile/NativePDB/ast-methods.cpp
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/ast-methods.cpp
+++ lldb/test/Shell/SymbolFile/NativePDB/ast-methods.cpp
@@ -4,7 +4,9 @@
 // RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -GR- -c /Fo%t.obj -- %s
 // RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb
 // RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
-// RUN:     %p/Inputs/ast-methods.lldbinit 2>&1 | FileCheck %s
+// RUN:     %p/Inputs/ast-methods.lldbinit 2>&1 | FileCheck %s --check-prefix=AST
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols --dump-ast %t.exe | FileCheck %s --check-prefix=SYMBOL
 
 struct Struct {
   void simple_method() {}
@@ -21,17 +23,42 @@
 Struct s;
 
 int main(int argc, char **argv) {
+  s.simple_method();
+  s.static_method();
+  s.virtual_method();
+  s.overloaded_method();
+  s.overloaded_method('a');
+  s.overloaded_method('a', 1);
   return 0;
 }
 
-// CHECK: TranslationUnitDecl
-// CHECK: |-CXXRecordDecl {{.*}} struct Struct definition
-// CHECK: | |-CXXMethodDecl {{.*}} simple_method 'void (){{.*}}'
-// CHECK: | |-CXXMethodDecl {{.*}} virtual_method 'void (){{.*}}' virtual
-// CHECK: | |-CXXMethodDecl {{.*}} static_method 'void ()' static
-// CHECK: | |-CXXMethodDecl {{.*}} overloaded_method 'int (){{.*}}'
-// CHECK: | |-CXXMethodDecl {{.*}} overloaded_method 'int (char){{.*}}'
-// CHECK: | | `-ParmVarDecl {{.*}} 'char'
-// CHECK: | `-CXXMethodDecl {{.*}} overloaded_method 'int (char, int, ...)'
-// CHECK: |   |-ParmVarDecl {{.*}} 'char'
-// CHECK: |   `-ParmVarDecl {{.*}} 'int'
+// AST: TranslationUnitDecl
+// AST: |-CXXRecordDecl {{.*}} struct Struct definition
+// AST: | |-CXXMethodDecl {{.*}} simple_method 'void (){{.*}}'
+// AST: | |-CXXMethodDecl {{.*}} virtual_method 'void (){{.*}}' virtual
+// AST: | |-CXXMethodDecl {{.*}} static_method 'void ()' static
+// AST: | |-CXXMethodDecl {{.*}} overloaded_method 'int (){{.*}}'
+// AST: | |-CXXMethodDecl {{.*}} overloaded_method 'int (char){{.*}}'
+// AST: | | `-ParmVarDecl {{.*}} 'char'
+// AST: | `-CXXMethodDecl {{.*}} overloaded_method 'int (char, int, ...)'
+// AST: |   |-ParmVarDecl {{.*}} 'char'
+// AST: |   `-ParmVarDecl {{.*}} 'int'
+
+// FIXME: Note that it prints the methods two times. One is from ParseFunctions
+// and aother one is from ParseTypes. The method decls should be deduplicated. 
+// Remove those extra methods after fixing the issue.
+// SYMBOL:      int main(int argc, char **argv);
+// SYMBOL-NEXT: struct Struct {
+// SYMBOL-NEXT:     void simple_method();
+// SYMBOL-NEXT:     static void static_method();
+// SYMBOL-NEXT:     virtual void virtual_method();
+// SYMBOL-NEXT:     int overloaded_method();
+// SYMBOL-NEXT:     int overloaded_method(char);
+// SYMBOL-NEXT:     int overloaded_method(char, int, ...);
+// SYMBOL-NEXT:     void simple_method();
+// SYMBOL-NEXT:     virtual void virtual_method();
+// SYMBOL-NEXT:     static void static_method();
+// SYMBOL-NEXT:     int overloaded_method();
+// SYMBOL-NEXT:     int overloaded_method(char);
+// SYMBOL-NEXT:     int overloaded_method(char, int, ...);
+// SYMBOL-NEXT: };
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -30,6 +30,70 @@
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
+namespace {
+struct CreateMethodDecl : public TypeVisitorCallbacks {
+  CreateMethodDecl(PdbIndex &m_index, TypeSystemClang &m_clang,
+                   TypeIndex func_type_index,
+                   clang::FunctionDecl *&function_decl,
+                   lldb::opaque_compiler_type_t parent_ty,
+                   llvm::StringRef proc_name, CompilerType func_ct)
+      : m_index(m_index), m_clang(m_clang), func_type_index(func_type_index),
+        function_decl(function_decl), parent_ty(parent_ty),
+        proc_name(proc_name), func_ct(func_ct) {}
+  PdbIndex &m_index;
+  TypeSystemClang &m_clang;
+  TypeIndex func_type_index;
+  clang::FunctionDecl *&function_decl;
+  lldb::opaque_compiler_type_t parent_ty;
+  llvm::StringRef proc_name;
+  CompilerType func_ct;
+
+  llvm::Error visitKnownMember(CVMemberRecord &cvr,
+                               OverloadedMethodRecord &overloaded) override {
+    TypeIndex method_list_idx = overloaded.MethodList;
+
+    CVType method_list_type = m_index.tpi().getType(method_list_idx);
+    assert(method_list_type.kind() == LF_METHODLIST);
+
+    MethodOverloadListRecord method_list;
+    llvm::cantFail(TypeDeserializer::deserializeAs<MethodOverloadListRecord>(
+        method_list_type, method_list));
+
+    for (const OneMethodRecord &method : method_list.Methods) {
+      if (method.getType().getIndex() == func_type_index.getIndex())
+        AddMethod(overloaded.Name, method.getAccess(), method.getOptions(),
+                  method.Attrs);
+    }
+
+    return llvm::Error::success();
+  }
+
+  llvm::Error visitKnownMember(CVMemberRecord &cvr,
+                               OneMethodRecord &record) override {
+    AddMethod(record.getName(), record.getAccess(), record.getOptions(),
+              record.Attrs);
+    return llvm::Error::success();
+  }
+
+  void AddMethod(llvm::StringRef name, MemberAccess access,
+                 MethodOptions options, MemberAttributes attrs) {
+    if (name != proc_name || function_decl)
+      return;
+    lldb::AccessType access_type = TranslateMemberAccess(access);
+    bool is_virtual = attrs.isVirtual();
+    bool is_static = attrs.isStatic();
+    bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
+                         MethodOptions::CompilerGenerated;
+    function_decl = m_clang.AddMethodToCXXRecordType(
+        parent_ty, proc_name,
+        /*mangled_name=*/nullptr, func_ct, /*access=*/access_type,
+        /*is_virtual=*/is_virtual, /*is_static=*/is_static,
+        /*is_inline=*/false, /*is_explicit=*/false,
+        /*is_attr_used=*/false, /*is_artificial=*/is_artificial);
+  }
+};
+} // namespace
+
 static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index,
                                                          PdbCompilandSymId id) {
   CVSymbol sym = index.ReadSymbolRecord(id);
@@ -1014,8 +1078,53 @@
   proc_name.consume_front(context_name);
   proc_name.consume_front("::");
 
-  clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration(
-      parent, OptionalClangModuleID(), proc_name, func_ct, storage, false);
+  clang::FunctionDecl *function_decl = nullptr;
+  if (parent->isRecord()) {
+    clang::QualType parent_qt = llvm::dyn_cast<clang::TypeDecl>(parent)
+                                    ->getTypeForDecl()
+                                    ->getCanonicalTypeInternal();
+    lldb::opaque_compiler_type_t parent_opaque_ty =
+        ToCompilerType(parent_qt).GetOpaqueQualType();
+
+    CVType cvt = m_index.tpi().getType(type_id.index);
+    MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind()));
+    llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(
+        cvt, func_record));
+    TypeIndex class_index = func_record.getClassType();
+    CVType parent_cvt = m_index.tpi().getType(class_index);
+    ClassRecord class_record = CVTagRecord::create(parent_cvt).asClass();
+    // If it's a forward reference, try to get the real TypeIndex.
+    if (class_record.isForwardRef()) {
+      llvm::Expected<TypeIndex> eti =
+          m_index.tpi().findFullDeclForForwardRef(class_index);
+      if (eti) {
+        class_record =
+            CVTagRecord::create(m_index.tpi().getType(*eti)).asClass();
+      }
+    }
+    if (!class_record.FieldList.isSimple()) {
+      CVType field_list = m_index.tpi().getType(class_record.FieldList);
+      CreateMethodDecl process(m_index, m_clang, type_id.index, function_decl,
+                               parent_opaque_ty, proc_name, func_ct);
+      if (llvm::Error err = visitMemberRecordStream(field_list.data(), process))
+        llvm::consumeError(std::move(err));
+    }
+
+    if (!function_decl) {
+      function_decl = m_clang.AddMethodToCXXRecordType(
+          parent_opaque_ty, proc_name,
+          /*mangled_name=*/nullptr, func_ct,
+          /*access=*/lldb::AccessType::eAccessPublic,
+          /*is_virtual=*/false, /*is_static=*/false,
+          /*is_inline=*/false, /*is_explicit=*/false,
+          /*is_attr_used=*/false, /*is_artificial=*/false);
+    }
+  } else {
+    function_decl = m_clang.CreateFunctionDeclaration(
+        parent, OptionalClangModuleID(), proc_name, func_ct, storage, false);
+    CreateFunctionParameters(func_id, *function_decl,
+                             func_type->getNumParams());
+  }
 
   lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
   m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
@@ -1024,8 +1133,6 @@
   status.uid = toOpaqueUid(func_id);
   m_decl_to_status.insert({function_decl, status});
 
-  CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams());
-
   return function_decl;
 }
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to