[Lldb-commits] [lldb] 681466f - Allow lldb-test to combine -find with -dump-clang-ast
Adrian Prantl via lldb-commits
lldb-commits at lists.llvm.org
Fri Apr 17 11:02:26 PDT 2020
Author: Adrian Prantl
Date: 2020-04-17T11:01:20-07:00
New Revision: 681466f5e6412350a0b066791450e72325c2c074
URL: https://github.com/llvm/llvm-project/commit/681466f5e6412350a0b066791450e72325c2c074
DIFF: https://github.com/llvm/llvm-project/commit/681466f5e6412350a0b066791450e72325c2c074.diff
LOG: Allow lldb-test to combine -find with -dump-clang-ast
This patch threads an lldb::DescriptionLevel through the typesystem to
allow dumping the full Clang AST (level=verbose) of any lldb::Type in
addition to the human-readable source description (default
level=full). This type dumping interface is currently not exposed
through the SBAPI.
The application is to let lldb-test dump the clang AST of search
results. I need this to test lazy type completion of clang types in
subsequent patches.
Differential Revision: https://reviews.llvm.org/D78329
Added:
Modified:
lldb/include/lldb/Symbol/CompilerType.h
lldb/include/lldb/Symbol/Type.h
lldb/include/lldb/Symbol/TypeMap.h
lldb/include/lldb/Symbol/TypeSystem.h
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
lldb/source/Symbol/CompilerType.cpp
lldb/source/Symbol/Type.cpp
lldb/source/Symbol/TypeMap.cpp
lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h
lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm
lldb/tools/lldb-test/lldb-test.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index b0a7953190f8..280966a327ec 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -371,9 +371,15 @@ class CompilerType {
size_t data_byte_size);
/// Dump to stdout.
- void DumpTypeDescription() const;
-
- void DumpTypeDescription(Stream *s) const;
+ void DumpTypeDescription(lldb::DescriptionLevel level =
+ lldb::eDescriptionLevelFull) const;
+
+ /// Print a description of the type to a stream. The exact implementation
+ /// varies, but the expectation is that eDescriptionLevelFull returns a
+ /// source-like representation of the type, whereas eDescriptionLevelVerbose
+ /// does a dump of the underlying AST if applicable.
+ void DumpTypeDescription(Stream *s, lldb::DescriptionLevel level =
+ lldb::eDescriptionLevelFull) const;
/// \}
bool GetValueAsScalar(const DataExtractor &data, lldb::offset_t data_offset,
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index dfff30029168..8735d016bb22 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -103,7 +103,8 @@ class Type : public std::enable_shared_from_this<Type>, public UserID {
// they get an error.
Type();
- void Dump(Stream *s, bool show_context);
+ void Dump(Stream *s, bool show_context,
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull);
void DumpTypeName(Stream *s);
diff --git a/lldb/include/lldb/Symbol/TypeMap.h b/lldb/include/lldb/Symbol/TypeMap.h
index dd9dbc69f404..67bb65b5faec 100644
--- a/lldb/include/lldb/Symbol/TypeMap.h
+++ b/lldb/include/lldb/Symbol/TypeMap.h
@@ -26,7 +26,8 @@ class TypeMap {
void Clear();
- void Dump(Stream *s, bool show_context);
+ void Dump(Stream *s, bool show_context,
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull);
TypeMap FindTypes(ConstString name);
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index ba2bbfaf4650..e188f29354b8 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -374,11 +374,18 @@ class TypeSystem : public PluginInterface {
uint32_t bitfield_bit_offset,
ExecutionContextScope *exe_scope) = 0;
- virtual void
- DumpTypeDescription(lldb::opaque_compiler_type_t type) = 0; // Dump to stdout
-
- virtual void DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) = 0;
+ /// Dump the type to stdout.
+ virtual void DumpTypeDescription(
+ lldb::opaque_compiler_type_t type,
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0;
+
+ /// Print a description of the type to a stream. The exact implementation
+ /// varies, but the expectation is that eDescriptionLevelFull returns a
+ /// source-like representation of the type, whereas eDescriptionLevelVerbose
+ /// does a dump of the underlying AST if applicable.
+ virtual void DumpTypeDescription(
+ lldb::opaque_compiler_type_t type, Stream *s,
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0;
// TODO: These methods appear unused. Should they be removed?
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index cbd8e78695f4..56c6e3502c0e 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -8787,9 +8787,10 @@ void TypeSystemClang::DumpSummary(lldb::opaque_compiler_type_t type,
}
}
-void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
+void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
+ lldb::DescriptionLevel level) {
StreamFile s(stdout, false);
- DumpTypeDescription(type, &s);
+ DumpTypeDescription(type, &s, level);
CompilerType ct(this, type);
const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr();
@@ -8800,7 +8801,8 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
}
void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) {
+ Stream *s,
+ lldb::DescriptionLevel level) {
if (type) {
clang::QualType qual_type =
RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
@@ -8814,24 +8816,31 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
case clang::Type::ObjCInterface: {
GetCompleteType(type);
- const clang::ObjCObjectType *objc_class_type =
+ auto *objc_class_type =
llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
assert(objc_class_type);
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
+ if (!objc_class_type)
+ break;
+ clang::ObjCInterfaceDecl *class_interface_decl =
objc_class_type->getInterface();
- if (class_interface_decl) {
- clang::PrintingPolicy policy = getASTContext().getPrintingPolicy();
- class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
- }
- }
+ if (!class_interface_decl)
+ break;
+ if (level == eDescriptionLevelVerbose)
+ class_interface_decl->dump(llvm_ostrm);
+ else
+ class_interface_decl->print(llvm_ostrm,
+ getASTContext().getPrintingPolicy(),
+ s->GetIndentLevel());
} break;
case clang::Type::Typedef: {
- const clang::TypedefType *typedef_type =
- qual_type->getAs<clang::TypedefType>();
- if (typedef_type) {
- const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+ auto *typedef_type = qual_type->getAs<clang::TypedefType>();
+ if (!typedef_type)
+ break;
+ const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+ if (level == eDescriptionLevelVerbose)
+ typedef_decl->dump(llvm_ostrm);
+ else {
std::string clang_typedef_name(
typedef_decl->getQualifiedNameAsString());
if (!clang_typedef_name.empty()) {
@@ -8844,31 +8853,39 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
case clang::Type::Record: {
GetCompleteType(type);
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ auto *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
const clang::RecordDecl *record_decl = record_type->getDecl();
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- if (cxx_record_decl)
- cxx_record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
- s->GetIndentLevel());
- else
- record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
- s->GetIndentLevel());
+ if (level == eDescriptionLevelVerbose)
+ record_decl->dump(llvm_ostrm);
+ else {
+ if (auto *cxx_record_decl =
+ llvm::dyn_cast<clang::CXXRecordDecl>(record_decl))
+ cxx_record_decl->print(llvm_ostrm,
+ getASTContext().getPrintingPolicy(),
+ s->GetIndentLevel());
+ else
+ record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
+ s->GetIndentLevel());
+ }
} break;
default: {
- const clang::TagType *tag_type =
- llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- tag_decl->print(llvm_ostrm, 0);
+ if (auto *tag_type =
+ llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr())) {
+ if (clang::TagDecl *tag_decl = tag_type->getDecl()) {
+ if (level == eDescriptionLevelVerbose)
+ tag_decl->dump(llvm_ostrm);
+ else
+ tag_decl->print(llvm_ostrm, 0);
+ }
} else {
- std::string clang_type_name(qual_type.getAsString());
- if (!clang_type_name.empty())
- s->PutCString(clang_type_name);
+ if (level == eDescriptionLevelVerbose)
+ qual_type->dump(llvm_ostrm);
+ else {
+ std::string clang_type_name(qual_type.getAsString());
+ if (!clang_type_name.empty())
+ s->PutCString(clang_type_name);
+ }
}
}
}
@@ -8876,7 +8893,7 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type,
if (buf.size() > 0) {
s->Write(buf.data(), buf.size());
}
- }
+}
}
void TypeSystemClang::DumpTypeName(const CompilerType &type) {
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index b326ee56cb8a..920d7cb4c23d 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -975,10 +975,12 @@ class TypeSystemClang : public TypeSystem {
lldb::offset_t data_offset, size_t data_byte_size) override;
void DumpTypeDescription(
- lldb::opaque_compiler_type_t type) override; // Dump to stdout
+ lldb::opaque_compiler_type_t type,
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override;
- void DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) override;
+ void DumpTypeDescription(
+ lldb::opaque_compiler_type_t type, Stream *s,
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override;
static void DumpTypeName(const CompilerType &type);
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index f24d9939e6cb..ce64763dd815 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -744,14 +744,15 @@ void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s,
data_byte_size);
}
-void CompilerType::DumpTypeDescription() const {
+void CompilerType::DumpTypeDescription(lldb::DescriptionLevel level) const {
if (IsValid())
- m_type_system->DumpTypeDescription(m_type);
+ m_type_system->DumpTypeDescription(m_type, level);
}
-void CompilerType::DumpTypeDescription(Stream *s) const {
+void CompilerType::DumpTypeDescription(Stream *s,
+ lldb::DescriptionLevel level) const {
if (IsValid()) {
- m_type_system->DumpTypeDescription(m_type, s);
+ m_type_system->DumpTypeDescription(m_type, s, level);
}
}
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 058d4c714634..307e99ac84b6 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -234,7 +234,7 @@ void Type::GetDescription(Stream *s, lldb::DescriptionLevel level,
}
}
-void Type::Dump(Stream *s, bool show_context) {
+void Type::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) {
s->Printf("%p: ", static_cast<void *>(this));
s->Indent();
*s << "Type" << static_cast<const UserID &>(*this) << ' ';
@@ -255,7 +255,7 @@ void Type::Dump(Stream *s, bool show_context) {
if (m_compiler_type.IsValid()) {
*s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' ';
- GetForwardCompilerType().DumpTypeDescription(s);
+ GetForwardCompilerType().DumpTypeDescription(s, level);
} else if (m_encoding_uid != LLDB_INVALID_UID) {
s->Format(", type_data = {0:x-16}", m_encoding_uid);
switch (m_encoding_uid_type) {
diff --git a/lldb/source/Symbol/TypeMap.cpp b/lldb/source/Symbol/TypeMap.cpp
index a7a29a30df12..e810d3020073 100644
--- a/lldb/source/Symbol/TypeMap.cpp
+++ b/lldb/source/Symbol/TypeMap.cpp
@@ -121,9 +121,9 @@ bool TypeMap::Remove(const lldb::TypeSP &type_sp) {
return false;
}
-void TypeMap::Dump(Stream *s, bool show_context) {
+void TypeMap::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) {
for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) {
- pos->second->Dump(s, show_context);
+ pos->second->Dump(s, show_context, level);
}
}
diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h
index 4b223cafdcba..0394d0a59de7 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h
+++ b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h
@@ -18,6 +18,7 @@ typedef enum Enum_e { a = 0 } Enum;
@interface SomeClass {
}
+ at property (readonly) int number;
@end
template <typename T> struct Template { T field; };
diff --git a/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm b/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm
index 6a876d1ea578..5fccc44c34ef 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm
+++ b/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm
@@ -1,17 +1,22 @@
// RUN: %clang --target=x86_64-apple-macosx -g -gmodules \
// RUN: -fmodules -fmodules-cache-path=%t.cache \
// RUN: -c -o %t.o %s -I%S/Inputs
-// RUN: lldb-test symbols -dump-clang-ast %t.o | FileCheck %s
// Verify that the owning module information from DWARF is preserved in the AST.
@import A;
Typedef t1;
-// CHECK-DAG: TypedefDecl {{.*}} imported in A Typedef
+// RUN: lldb-test symbols -dump-clang-ast -find type --language=ObjC++ \
+// RUN: -compiler-context 'Module:A,Typedef:Typedef' %t.o \
+// RUN: | FileCheck %s --check-prefix=CHECK-TYPEDEF
+// CHECK-TYPEDEF: TypedefDecl {{.*}} imported in A Typedef
TopLevelStruct s1;
-// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct TopLevelStruct
-// CHECK-DAG: -FieldDecl {{.*}} in A a 'int'
+// RUN: lldb-test symbols -dump-clang-ast -find type --language=ObjC++ \
+// RUN: -compiler-context 'Module:A,Struct:TopLevelStruct' %t.o \
+// RUN: | FileCheck %s --check-prefix=CHECK-TOPLEVELSTRUCT
+// CHECK-TOPLEVELSTRUCT: CXXRecordDecl {{.*}} imported in A struct TopLevelStruct
+// CHECK-TOPLEVELSTRUCT: -FieldDecl {{.*}} in A a 'int'
Struct s2;
// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct
@@ -29,7 +34,13 @@
// FIXME: -EnumConstantDecl {{.*}} imported in A a
SomeClass *obj1;
-// CHECK-DAG: ObjCInterfaceDecl {{.*}} imported in A {{.*}} SomeClass
+// RUN: lldb-test symbols -dump-clang-ast -find type --language=ObjC++ \
+// RUN: -compiler-context 'Module:A,Struct:SomeClass' %t.o \
+// RUN: | FileCheck %s --check-prefix=CHECK-OBJC
+// CHECK-OBJC: ObjCInterfaceDecl {{.*}} imported in A SomeClass
+// CHECK-OBJC: |-ObjCPropertyDecl {{.*}} imported in A number 'int' readonly
+// CHECK-OBJC: | `-getter ObjCMethod {{.*}} 'number'
+// CHECK-OBJC: `-ObjCMethodDecl {{.*}} imported in A implicit - number 'int'
// Template specializations are not yet supported, so they lack the ownership info:
Template<int> t2;
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 5b28afbf8972..6c765db8da5a 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -169,10 +169,13 @@ static FunctionNameType getFunctionNameFlags() {
static cl::opt<bool> DumpAST("dump-ast",
cl::desc("Dump AST restored from symbols."),
cl::sub(SymbolsSubcommand));
-static cl::opt<bool>
- DumpClangAST("dump-clang-ast",
- cl::desc("Dump clang AST restored from symbols."),
- cl::sub(SymbolsSubcommand));
+static cl::opt<bool> DumpClangAST(
+ "dump-clang-ast",
+ cl::desc("Dump clang AST restored from symbols. When used on its own this "
+ "will dump the entire AST of all loaded symbols. When combined "
+ "with -find, it changes the presentation of the search results "
+ "from pretty-printing the types to an AST dump."),
+ cl::sub(SymbolsSubcommand));
static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
cl::sub(SymbolsSubcommand));
@@ -192,7 +195,7 @@ static Error findTypes(lldb_private::Module &Module);
static Error findVariables(lldb_private::Module &Module);
static Error dumpModule(lldb_private::Module &Module);
static Error dumpAST(lldb_private::Module &Module);
-static Error dumpClangAST(lldb_private::Module &Module);
+static Error dumpEntireClangAST(lldb_private::Module &Module);
static Error verify(lldb_private::Module &Module);
static Expected<Error (*)(lldb_private::Module &)> getAction();
@@ -404,6 +407,10 @@ opts::symbols::getDeclContext(SymbolFile &Symfile) {
return List.GetVariableAtIndex(0)->GetDeclContext();
}
+static lldb::DescriptionLevel GetDescriptionLevel() {
+ return opts::symbols::DumpClangAST ? eDescriptionLevelVerbose : eDescriptionLevelFull;
+}
+
Error opts::symbols::findFunctions(lldb_private::Module &Module) {
SymbolFile &Symfile = *Module.GetSymbolFile();
SymbolContextList List;
@@ -534,7 +541,12 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) {
outs() << formatv("Found {0} types:\n", Map.GetSize());
StreamString Stream;
- Map.Dump(&Stream, false);
+ // Resolve types to force-materialize typedef types.
+ Map.ForEach([&](TypeSP &type) {
+ type->GetFullCompilerType();
+ return false;
+ });
+ Map.Dump(&Stream, false, GetDescriptionLevel());
outs() << Stream.GetData() << "\n";
return Error::success();
}
@@ -615,7 +627,7 @@ Error opts::symbols::dumpAST(lldb_private::Module &Module) {
return Error::success();
}
-Error opts::symbols::dumpClangAST(lldb_private::Module &Module) {
+Error opts::symbols::dumpEntireClangAST(lldb_private::Module &Module) {
Module.ParseAllDebugSymbols();
SymbolFile *symfile = Module.GetSymbolFile();
@@ -719,13 +731,17 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
}
if (DumpClangAST) {
- if (Find != FindType::None)
- return make_string_error("Cannot both search and dump clang AST.");
- if (Regex || !Context.empty() || !File.empty() || Line != 0)
- return make_string_error(
- "-regex, -context, -name, -file and -line options are not "
- "applicable for dumping clang AST.");
- return dumpClangAST;
+ if (Find == FindType::None) {
+ if (Regex || !Context.empty() || !File.empty() || Line != 0)
+ return make_string_error(
+ "-regex, -context, -name, -file and -line options are not "
+ "applicable for dumping the entire clang AST. Either combine with "
+ "-find, or use -dump-clang-ast as a standalone option.");
+ return dumpEntireClangAST;
+ }
+ if (Find != FindType::Type)
+ return make_string_error("This combination of -dump-clang-ast and -find "
+ "<kind> is not yet implemented.");
}
if (Regex && !Context.empty())
More information about the lldb-commits
mailing list