[Lldb-commits] [lldb] [lldb][TypeSystemClang][NFCI] Factor completion logic for individual types in GetCompleteQualType (PR #95402)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Jun 13 05:33:56 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Michael Buch (Michael137)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/95402.diff
1 Files Affected:
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+133-77)
``````````diff
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 369ae46cf264a..bef9263eaeafc 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 clang::RecordType const *GetCompleteRecordType(clang::ASTContext *ast,
+ clang::QualType qual_type,
+ bool allow_completion) {
+ assert(qual_type->isRecordType());
+
+ auto const *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 clang::EnumType const *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 clang::ObjCObjectType const *
+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 (auto const *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 (auto const *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 (auto const *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:
``````````
</details>
https://github.com/llvm/llvm-project/pull/95402
More information about the lldb-commits
mailing list