[Lldb-commits] [lldb] f2d215f - [lldb][TypeSystemClang][NFCI] Factor completion logic for individual types out of GetCompleteQualType (#95402)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Jun 13 23:20:54 PDT 2024
Author: Michael Buch
Date: 2024-06-14T07:20:50+01:00
New Revision: f2d215f572affc9ad73da07763ce1831de7f2d4d
URL: https://github.com/llvm/llvm-project/commit/f2d215f572affc9ad73da07763ce1831de7f2d4d
DIFF: https://github.com/llvm/llvm-project/commit/f2d215f572affc9ad73da07763ce1831de7f2d4d.diff
LOG: [lldb][TypeSystemClang][NFCI] Factor completion logic for individual types out of GetCompleteQualType (#95402)
This patch factors out the completion logic for individual clang::Type's
into their own helper functions.
During the process I cleaned up a few assumptions (e.g., unnecessary
if-guards that could be asserts because these conditions are guaranteed
by the `clang::Type::TypeClass` switch in `GetCompleteQualType`).
This is mainly motivated by the type-completion rework proposed in
https://github.com/llvm/llvm-project/pull/95100.
Added:
Modified:
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 369ae46cf264a..dbe6238d4fe5a 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2574,6 +2574,128 @@ TypeSystemClang::GetDeclContextForType(clang::QualType type) {
return nullptr;
}
+/// Returns the clang::RecordType of the specified \ref qual_type. This
+/// function will try to complete the type if necessary (and allowed
+/// by the specified \ref allow_completion). If we fail to return a *complete*
+/// type, returns nullptr.
+static const clang::RecordType *GetCompleteRecordType(clang::ASTContext *ast,
+ clang::QualType qual_type,
+ bool allow_completion) {
+ assert(qual_type->isRecordType());
+
+ const auto *tag_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+
+ // RecordType with no way of completing it, return the plain
+ // TagType.
+ if (!cxx_record_decl || !cxx_record_decl->hasExternalLexicalStorage())
+ return tag_type;
+
+ const bool is_complete = cxx_record_decl->isCompleteDefinition();
+ const bool fields_loaded =
+ cxx_record_decl->hasLoadedFieldsFromExternalStorage();
+
+ // Already completed this type, nothing to be done.
+ if (is_complete && fields_loaded)
+ return tag_type;
+
+ if (!allow_completion)
+ return nullptr;
+
+ // Call the field_begin() accessor to for it to use the external source
+ // to load the fields...
+ //
+ // TODO: if we need to complete the type but have no external source,
+ // shouldn't we error out instead?
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+ if (external_ast_source) {
+ external_ast_source->CompleteType(cxx_record_decl);
+ if (cxx_record_decl->isCompleteDefinition()) {
+ cxx_record_decl->field_begin();
+ cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+ }
+ }
+
+ return tag_type;
+}
+
+/// Returns the clang::EnumType of the specified \ref qual_type. This
+/// function will try to complete the type if necessary (and allowed
+/// by the specified \ref allow_completion). If we fail to return a *complete*
+/// type, returns nullptr.
+static const clang::EnumType *GetCompleteEnumType(clang::ASTContext *ast,
+ clang::QualType qual_type,
+ bool allow_completion) {
+ assert(qual_type->isEnumeralType());
+ assert(ast);
+
+ const clang::EnumType *enum_type =
+ llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+
+ auto *tag_decl = enum_type->getAsTagDecl();
+ assert(tag_decl);
+
+ // Already completed, nothing to be done.
+ if (tag_decl->getDefinition())
+ return enum_type;
+
+ if (!allow_completion)
+ return nullptr;
+
+ // No definition but can't complete it, error out.
+ if (!tag_decl->hasExternalLexicalStorage())
+ return nullptr;
+
+ // We can't complete the type without an external source.
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+ if (!external_ast_source)
+ return nullptr;
+
+ external_ast_source->CompleteType(tag_decl);
+ return enum_type;
+}
+
+/// Returns the clang::ObjCObjectType of the specified \ref qual_type. This
+/// function will try to complete the type if necessary (and allowed
+/// by the specified \ref allow_completion). If we fail to return a *complete*
+/// type, returns nullptr.
+static const clang::ObjCObjectType *
+GetCompleteObjCObjectType(clang::ASTContext *ast, QualType qual_type,
+ bool allow_completion) {
+ assert(qual_type->isObjCObjectType());
+ assert(ast);
+
+ const clang::ObjCObjectType *objc_class_type =
+ llvm::cast<clang::ObjCObjectType>(qual_type);
+
+ clang::ObjCInterfaceDecl *class_interface_decl =
+ objc_class_type->getInterface();
+ // We currently can't complete objective C types through the newly added
+ // ASTContext because it only supports TagDecl objects right now...
+ if (!class_interface_decl)
+ return objc_class_type;
+
+ // Already complete, nothing to be done.
+ if (class_interface_decl->getDefinition())
+ return objc_class_type;
+
+ if (!allow_completion)
+ return nullptr;
+
+ // No definition but can't complete it, error out.
+ if (!class_interface_decl->hasExternalLexicalStorage())
+ return nullptr;
+
+ // We can't complete the type without an external source.
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+ if (!external_ast_source)
+ return nullptr;
+
+ external_ast_source->CompleteType(class_interface_decl);
+ return objc_class_type;
+}
+
static bool GetCompleteQualType(clang::ASTContext *ast,
clang::QualType qual_type,
bool allow_completion = true) {
@@ -2591,92 +2713,26 @@ static bool GetCompleteQualType(clang::ASTContext *ast,
allow_completion);
} break;
case clang::Type::Record: {
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- if (cxx_record_decl->hasExternalLexicalStorage()) {
- const bool is_complete = cxx_record_decl->isCompleteDefinition();
- const bool fields_loaded =
- cxx_record_decl->hasLoadedFieldsFromExternalStorage();
- if (is_complete && fields_loaded)
- return true;
+ if (const auto *RT =
+ GetCompleteRecordType(ast, qual_type, allow_completion))
+ return !RT->isIncompleteType();
- if (!allow_completion)
- return false;
-
- // Call the field_begin() accessor to for it to use the external source
- // to load the fields...
- clang::ExternalASTSource *external_ast_source =
- ast->getExternalSource();
- if (external_ast_source) {
- external_ast_source->CompleteType(cxx_record_decl);
- if (cxx_record_decl->isCompleteDefinition()) {
- cxx_record_decl->field_begin();
- cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
- }
- }
- }
- }
- const clang::TagType *tag_type =
- llvm::cast<clang::TagType>(qual_type.getTypePtr());
- return !tag_type->isIncompleteType();
+ return false;
} break;
case clang::Type::Enum: {
- 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) {
- if (tag_decl->getDefinition())
- return true;
-
- if (!allow_completion)
- return false;
-
- if (tag_decl->hasExternalLexicalStorage()) {
- if (ast) {
- clang::ExternalASTSource *external_ast_source =
- ast->getExternalSource();
- if (external_ast_source) {
- external_ast_source->CompleteType(tag_decl);
- return !tag_type->isIncompleteType();
- }
- }
- }
- return false;
- }
- }
+ if (const auto *ET = GetCompleteEnumType(ast, qual_type, allow_completion))
+ return !ET->isIncompleteType();
+ return false;
} break;
case clang::Type::ObjCObject:
case clang::Type::ObjCInterface: {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
- // We currently can't complete objective C types through the newly added
- // ASTContext because it only supports TagDecl objects right now...
- if (class_interface_decl) {
- if (class_interface_decl->getDefinition())
- return true;
-
- if (!allow_completion)
- return false;
+ if (const auto *OT =
+ GetCompleteObjCObjectType(ast, qual_type, allow_completion))
+ return !OT->isIncompleteType();
- if (class_interface_decl->hasExternalLexicalStorage()) {
- if (ast) {
- clang::ExternalASTSource *external_ast_source =
- ast->getExternalSource();
- if (external_ast_source) {
- external_ast_source->CompleteType(class_interface_decl);
- return !objc_class_type->isIncompleteType();
- }
- }
- }
- return false;
- }
- }
+ return false;
} break;
case clang::Type::Attributed:
More information about the lldb-commits
mailing list