Skip to content

Commit f2d215f

Browse files
authored
[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 #95100.
1 parent b1de42a commit f2d215f

File tree

1 file changed

+133
-77
lines changed

1 file changed

+133
-77
lines changed

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 133 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,128 @@ TypeSystemClang::GetDeclContextForType(clang::QualType type) {
25742574
return nullptr;
25752575
}
25762576

2577+
/// Returns the clang::RecordType of the specified \ref qual_type. This
2578+
/// function will try to complete the type if necessary (and allowed
2579+
/// by the specified \ref allow_completion). If we fail to return a *complete*
2580+
/// type, returns nullptr.
2581+
static const clang::RecordType *GetCompleteRecordType(clang::ASTContext *ast,
2582+
clang::QualType qual_type,
2583+
bool allow_completion) {
2584+
assert(qual_type->isRecordType());
2585+
2586+
const auto *tag_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
2587+
2588+
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
2589+
2590+
// RecordType with no way of completing it, return the plain
2591+
// TagType.
2592+
if (!cxx_record_decl || !cxx_record_decl->hasExternalLexicalStorage())
2593+
return tag_type;
2594+
2595+
const bool is_complete = cxx_record_decl->isCompleteDefinition();
2596+
const bool fields_loaded =
2597+
cxx_record_decl->hasLoadedFieldsFromExternalStorage();
2598+
2599+
// Already completed this type, nothing to be done.
2600+
if (is_complete && fields_loaded)
2601+
return tag_type;
2602+
2603+
if (!allow_completion)
2604+
return nullptr;
2605+
2606+
// Call the field_begin() accessor to for it to use the external source
2607+
// to load the fields...
2608+
//
2609+
// TODO: if we need to complete the type but have no external source,
2610+
// shouldn't we error out instead?
2611+
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
2612+
if (external_ast_source) {
2613+
external_ast_source->CompleteType(cxx_record_decl);
2614+
if (cxx_record_decl->isCompleteDefinition()) {
2615+
cxx_record_decl->field_begin();
2616+
cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
2617+
}
2618+
}
2619+
2620+
return tag_type;
2621+
}
2622+
2623+
/// Returns the clang::EnumType of the specified \ref qual_type. This
2624+
/// function will try to complete the type if necessary (and allowed
2625+
/// by the specified \ref allow_completion). If we fail to return a *complete*
2626+
/// type, returns nullptr.
2627+
static const clang::EnumType *GetCompleteEnumType(clang::ASTContext *ast,
2628+
clang::QualType qual_type,
2629+
bool allow_completion) {
2630+
assert(qual_type->isEnumeralType());
2631+
assert(ast);
2632+
2633+
const clang::EnumType *enum_type =
2634+
llvm::cast<clang::EnumType>(qual_type.getTypePtr());
2635+
2636+
auto *tag_decl = enum_type->getAsTagDecl();
2637+
assert(tag_decl);
2638+
2639+
// Already completed, nothing to be done.
2640+
if (tag_decl->getDefinition())
2641+
return enum_type;
2642+
2643+
if (!allow_completion)
2644+
return nullptr;
2645+
2646+
// No definition but can't complete it, error out.
2647+
if (!tag_decl->hasExternalLexicalStorage())
2648+
return nullptr;
2649+
2650+
// We can't complete the type without an external source.
2651+
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
2652+
if (!external_ast_source)
2653+
return nullptr;
2654+
2655+
external_ast_source->CompleteType(tag_decl);
2656+
return enum_type;
2657+
}
2658+
2659+
/// Returns the clang::ObjCObjectType of the specified \ref qual_type. This
2660+
/// function will try to complete the type if necessary (and allowed
2661+
/// by the specified \ref allow_completion). If we fail to return a *complete*
2662+
/// type, returns nullptr.
2663+
static const clang::ObjCObjectType *
2664+
GetCompleteObjCObjectType(clang::ASTContext *ast, QualType qual_type,
2665+
bool allow_completion) {
2666+
assert(qual_type->isObjCObjectType());
2667+
assert(ast);
2668+
2669+
const clang::ObjCObjectType *objc_class_type =
2670+
llvm::cast<clang::ObjCObjectType>(qual_type);
2671+
2672+
clang::ObjCInterfaceDecl *class_interface_decl =
2673+
objc_class_type->getInterface();
2674+
// We currently can't complete objective C types through the newly added
2675+
// ASTContext because it only supports TagDecl objects right now...
2676+
if (!class_interface_decl)
2677+
return objc_class_type;
2678+
2679+
// Already complete, nothing to be done.
2680+
if (class_interface_decl->getDefinition())
2681+
return objc_class_type;
2682+
2683+
if (!allow_completion)
2684+
return nullptr;
2685+
2686+
// No definition but can't complete it, error out.
2687+
if (!class_interface_decl->hasExternalLexicalStorage())
2688+
return nullptr;
2689+
2690+
// We can't complete the type without an external source.
2691+
clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
2692+
if (!external_ast_source)
2693+
return nullptr;
2694+
2695+
external_ast_source->CompleteType(class_interface_decl);
2696+
return objc_class_type;
2697+
}
2698+
25772699
static bool GetCompleteQualType(clang::ASTContext *ast,
25782700
clang::QualType qual_type,
25792701
bool allow_completion = true) {
@@ -2591,92 +2713,26 @@ static bool GetCompleteQualType(clang::ASTContext *ast,
25912713
allow_completion);
25922714
} break;
25932715
case clang::Type::Record: {
2594-
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
2595-
if (cxx_record_decl) {
2596-
if (cxx_record_decl->hasExternalLexicalStorage()) {
2597-
const bool is_complete = cxx_record_decl->isCompleteDefinition();
2598-
const bool fields_loaded =
2599-
cxx_record_decl->hasLoadedFieldsFromExternalStorage();
2600-
if (is_complete && fields_loaded)
2601-
return true;
2716+
if (const auto *RT =
2717+
GetCompleteRecordType(ast, qual_type, allow_completion))
2718+
return !RT->isIncompleteType();
26022719

2603-
if (!allow_completion)
2604-
return false;
2605-
2606-
// Call the field_begin() accessor to for it to use the external source
2607-
// to load the fields...
2608-
clang::ExternalASTSource *external_ast_source =
2609-
ast->getExternalSource();
2610-
if (external_ast_source) {
2611-
external_ast_source->CompleteType(cxx_record_decl);
2612-
if (cxx_record_decl->isCompleteDefinition()) {
2613-
cxx_record_decl->field_begin();
2614-
cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
2615-
}
2616-
}
2617-
}
2618-
}
2619-
const clang::TagType *tag_type =
2620-
llvm::cast<clang::TagType>(qual_type.getTypePtr());
2621-
return !tag_type->isIncompleteType();
2720+
return false;
26222721
} break;
26232722

26242723
case clang::Type::Enum: {
2625-
const clang::TagType *tag_type =
2626-
llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
2627-
if (tag_type) {
2628-
clang::TagDecl *tag_decl = tag_type->getDecl();
2629-
if (tag_decl) {
2630-
if (tag_decl->getDefinition())
2631-
return true;
2632-
2633-
if (!allow_completion)
2634-
return false;
2635-
2636-
if (tag_decl->hasExternalLexicalStorage()) {
2637-
if (ast) {
2638-
clang::ExternalASTSource *external_ast_source =
2639-
ast->getExternalSource();
2640-
if (external_ast_source) {
2641-
external_ast_source->CompleteType(tag_decl);
2642-
return !tag_type->isIncompleteType();
2643-
}
2644-
}
2645-
}
2646-
return false;
2647-
}
2648-
}
2724+
if (const auto *ET = GetCompleteEnumType(ast, qual_type, allow_completion))
2725+
return !ET->isIncompleteType();
26492726

2727+
return false;
26502728
} break;
26512729
case clang::Type::ObjCObject:
26522730
case clang::Type::ObjCInterface: {
2653-
const clang::ObjCObjectType *objc_class_type =
2654-
llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
2655-
if (objc_class_type) {
2656-
clang::ObjCInterfaceDecl *class_interface_decl =
2657-
objc_class_type->getInterface();
2658-
// We currently can't complete objective C types through the newly added
2659-
// ASTContext because it only supports TagDecl objects right now...
2660-
if (class_interface_decl) {
2661-
if (class_interface_decl->getDefinition())
2662-
return true;
2663-
2664-
if (!allow_completion)
2665-
return false;
2731+
if (const auto *OT =
2732+
GetCompleteObjCObjectType(ast, qual_type, allow_completion))
2733+
return !OT->isIncompleteType();
26662734

2667-
if (class_interface_decl->hasExternalLexicalStorage()) {
2668-
if (ast) {
2669-
clang::ExternalASTSource *external_ast_source =
2670-
ast->getExternalSource();
2671-
if (external_ast_source) {
2672-
external_ast_source->CompleteType(class_interface_decl);
2673-
return !objc_class_type->isIncompleteType();
2674-
}
2675-
}
2676-
}
2677-
return false;
2678-
}
2679-
}
2735+
return false;
26802736
} break;
26812737

26822738
case clang::Type::Attributed:

0 commit comments

Comments
 (0)