-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[lldb][TypeSystemClang][NFCI] Factor completion logic for individual types out of GetCompleteQualType #95402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][TypeSystemClang][NFCI] Factor completion logic for individual types out of GetCompleteQualType #95402
Conversation
…ypes in GetCompleteQualType 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 llvm#95100.
@llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) ChangesThis 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 This is mainly motivated by the type-completion rework proposed in #95100. Full diff: https://github.com/llvm/llvm-project/pull/95402.diff 1 Files Affected:
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:
|
/// 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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const before object type (is this some swift style or something?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hehe just a habit of mine. I'll change it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
…types out of GetCompleteQualType (llvm#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 llvm#95100.
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 inGetCompleteQualType
).This is mainly motivated by the type-completion rework proposed in #95100.