Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions resect.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ typedef enum {
RESECT_CONSTRUCTOR_KIND_OTHER = 5,
} resect_constructor_kind;

typedef enum {
RESECT_REF_QUALIFIER_NONE = 0,
RESECT_REF_QUALIFIER_LVALUE = 1,
RESECT_REF_QUALIFIER_RVALUE = 2
} resect_ref_qualifier;

typedef struct P_resect_translation_unit *resect_translation_unit;
typedef struct P_resect_collection *resect_collection;
typedef struct P_resect_iterator *resect_iterator;
Expand Down Expand Up @@ -496,6 +502,8 @@ RESECT_API resect_bool resect_method_is_const(resect_decl decl);

RESECT_API resect_bool resect_method_is_deleted(resect_decl decl);

RESECT_API resect_bool resect_method_is_constructor(resect_decl decl);

/*
* MACRO
*/
Expand Down
55 changes: 54 additions & 1 deletion src/decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,19 @@ struct P_resect_decl {
resect_data_deallocator data_deallocator;
};

resect_decl_kind convert_cursor_kind(CXCursor cursor) {
enum CXCursorKind get_cursor_kind(CXCursor cursor) {
enum CXCursorKind clang_kind = clang_getTemplateCursorKind(cursor);

if (clang_kind == CXCursor_NoDeclFound) {
clang_kind = clang_getCursorKind(cursor);
}

return clang_kind;
}

resect_decl_kind convert_cursor_kind(CXCursor cursor) {
enum CXCursorKind clang_kind = get_cursor_kind(cursor);

switch (clang_kind) {
case CXCursor_MacroDefinition:
return RESECT_DECL_KIND_MACRO;
Expand Down Expand Up @@ -947,6 +953,7 @@ typedef struct P_resect_function_data {
resect_function_calling_convention calling_convention;
resect_type result_type;
resect_bool inlined;
resect_ref_qualifier ref_qualifier;
} *resect_function_data;

resect_type resect_function_get_result_type(resect_decl decl) {
Expand Down Expand Up @@ -1097,10 +1104,22 @@ resect_function_data resect_function_data_create(resect_visit_context visit_cont
data->variadic = clang_isFunctionTypeVariadic(functionType) != 0 ? resect_true : resect_false;
data->result_type = resect_type_create(visit_context, context, clang_getResultType(functionType));
data->inlined = convert_bool_from_uint(clang_Cursor_isFunctionInlined(cursor));
data->ref_qualifier = convert_ref_qualifier(clang_Type_getCXXRefQualifier(functionType));

return data;
}

resect_ref_qualifier convert_ref_qualifier(enum CXRefQualifierKind qual) {
switch (qual) {
case CXRefQualifier_LValue:
return RESECT_REF_QUALIFIER_LVALUE;
case CXRefQualifier_RValue:
return RESECT_REF_QUALIFIER_RVALUE;
default:
return RESECT_REF_QUALIFIER_NONE;
}
}

void resect_function_init(resect_visit_context visit_context, resect_translation_context context, resect_decl decl,
CXCursor cursor) {
resect_function_data function_data = resect_function_data_create(visit_context, context, cursor);
Expand Down Expand Up @@ -1376,6 +1395,9 @@ typedef struct P_resect_method_data {
resect_bool virtual;
resect_bool non_mutating;
resect_bool deleted;
resect_bool constructor;
resect_bool copy_constructor;
resect_bool copy_assign;
} *resect_method_data;

resect_type resect_method_get_result_type(resect_decl decl) {
Expand Down Expand Up @@ -1420,12 +1442,40 @@ resect_bool resect_method_is_deleted(resect_decl decl) {
return data->deleted;
}

resect_bool resect_method_is_constructor(resect_decl decl) {
assert(decl->kind == RESECT_DECL_KIND_METHOD);
resect_method_data data = decl->data;
return data->constructor;
}

resect_bool resect_method_is_copy_constructor(resect_decl decl) {
if (decl->kind != RESECT_DECL_KIND_METHOD || decl->data == NULL) {
return resect_false;
}
resect_method_data data = decl->data;
return data->copy_constructor;
}

resect_bool resect_method_is_copy_assignment(resect_decl decl) {
if (decl->kind != RESECT_DECL_KIND_METHOD || decl->data == NULL) {
return resect_false;
}
resect_method_data data = decl->data;
return data->copy_assign;
}

resect_collection resect_method_parameters(resect_decl decl) {
assert(decl->kind == RESECT_DECL_KIND_METHOD);
resect_method_data data = decl->data;
return data->function_data->parameters;
}

resect_ref_qualifier resect_method_get_ref_qualifier(resect_decl decl) {
assert(decl->kind == RESECT_DECL_KIND_METHOD);
resect_method_data data = decl->data;
return data->function_data->ref_qualifier;
}

enum CXChildVisitResult resect_visit_method_parameter(CXCursor cursor, CXCursor parent, CXClientData data) {
resect_decl_child_visit_data visit_data = data;
resect_method_data method_data = visit_data->parent->data;
Expand Down Expand Up @@ -1454,6 +1504,9 @@ void resect_method_init(resect_visit_context visit_context, resect_translation_c
data->pure_virtual = clang_CXXMethod_isPureVirtual(cursor) > 0;
data->non_mutating = clang_CXXMethod_isConst(cursor) > 0;
data->deleted = clang_CXXMethod_isDeleted(cursor) > 0;
data->constructor = get_cursor_kind(cursor) == CXCursor_Constructor;
data->copy_constructor = (data->constructor && clang_CXXConstructor_isCopyConstructor(cursor));
data->copy_assign = clang_CXXMethod_isCopyAssignmentOperator(cursor);

decl->data_deallocator = resect_method_data_free;
decl->data = data;
Expand Down
8 changes: 8 additions & 0 deletions src/resect_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ resect_bool resect_is_forward_declaration(CXCursor cursor);

resect_bool resect_is_specialized(CXCursor cursor);

enum CXCursorKind get_cursor_kind(CXCursor cursor);

resect_decl_kind convert_cursor_kind(CXCursor cursor);

bool is_cursor_anonymous(CXCursor cursor);
Expand All @@ -286,6 +288,12 @@ resect_decl_visit_data resect_decl_visit_data_create(resect_translation_context

void resect_visit_decl_data_free(resect_decl_visit_data data);

resect_ref_qualifier convert_ref_qualifier(enum CXRefQualifierKind qual);

resect_bool resect_method_is_copy_assignment(resect_decl decl);

resect_bool resect_method_is_copy_constructor(resect_decl decl);

/*
* TEMPLATE ARGUMENT
*/
Expand Down
3 changes: 0 additions & 3 deletions src/shaking.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,6 @@ static void resect_investigate_owner(resect_visit_context visit_context, resect_
CXCursor cursor);

static resect_access_level convert_access_level(CXCursor cursor) {
if (clang_getCursorKind(cursor) == CXCursor_CXXMethod && clang_CXXMethod_isDeleted(cursor)) {
return RESECT_ACCESS_LEVEL_INACCESSIBLE;
}
CXType cursor_type = clang_getCursorType(cursor);

// libclang cannot handle templated member-pointers
Expand Down
59 changes: 51 additions & 8 deletions src/type.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ struct P_resect_type {
resect_bool const_qualified;
resect_bool pod;
resect_bool undeclared;
resect_bool has_copy_constructor;
resect_bool copy_constructor_deleted;
resect_bool has_copy_assignment;
resect_bool copy_assignment_deleted;
resect_collection template_arguments;

resect_decl decl;
Expand Down Expand Up @@ -306,6 +310,22 @@ static enum CXVisitorResult visit_type_method(CXCursor cursor, CXClientData data
resect_type_method type_method = resect_method_create(visit_data->visit_context, visit_data->context, cursor);
if (type_method != NULL) {
resect_collection_add(visit_data->type->methods, type_method);
if (type_method->decl != NULL) {
if (resect_method_is_copy_constructor(type_method->decl)) {
if (resect_method_is_deleted(type_method->decl)) {
visit_data->type->copy_constructor_deleted = resect_true;
} else {
visit_data->type->has_copy_constructor = resect_true;
}
}
if (resect_method_is_copy_assignment(type_method->decl)) {
if (resect_method_is_deleted(type_method->decl)) {
visit_data->type->copy_assignment_deleted = resect_true;
} else {
visit_data->type->has_copy_assignment = resect_true;
}
}
}
}

return CXVisit_Continue;
Expand Down Expand Up @@ -603,9 +623,22 @@ resect_type_category get_type_category(resect_type_kind kind) {
*/
resect_type resect_type_create(resect_visit_context visit_context, resect_translation_context context,
CXType clang_type) {
resect_type type = resect_find_type(context, clang_type);
if (type != NULL) {
return type;
}

CXType original_clang_type = clang_type;
resect_bool is_const = false;
// Not sure this can be true more than once -- but just in case, we loop
while (clang_type.kind == CXType_Elaborated) {
if (clang_isConstQualifiedType(clang_type)) {
is_const = true;
}
// Can unwrap to an Unexposed
clang_type = clang_Type_getNamedType(clang_type);
}
switch (clang_type.kind) {
case CXType_Elaborated:
return resect_type_create(visit_context, context, clang_Type_getNamedType(clang_type));
case CXType_Unexposed: {
CXType canonical_type = clang_getCanonicalType(clang_type);
if (CXType_Unexposed != canonical_type.kind) {
Expand All @@ -619,11 +652,6 @@ resect_type resect_type_create(resect_visit_context visit_context, resect_transl
default: ;
}

resect_type type = resect_find_type(context, clang_type);
if (type != NULL) {
return type;
}

type = malloc(sizeof(struct P_resect_type));
type->initialized = false;
type->kind = convert_type_kind(clang_type.kind);
Expand All @@ -646,11 +674,15 @@ resect_type resect_type_create(resect_visit_context visit_context, resect_transl
type->pod = convert_bool_from_uint(clang_isPODType(clang_type));
type->template_arguments = resect_collection_create();
type->decl = NULL;
type->has_copy_constructor = resect_false;
type->copy_constructor_deleted = resect_false;
type->has_copy_assignment = resect_false;
type->copy_assignment_deleted = resect_false;

type->data_deallocator = NULL;
type->data = NULL;

resect_register_type(context, clang_type, type);
resect_register_type(context, original_clang_type, type);

CXCursor declaration_cursor = clang_getTypeDeclaration(clang_type);
if (declaration_cursor.kind == CXCursor_NoDeclFound) {
Expand Down Expand Up @@ -699,6 +731,9 @@ resect_type resect_type_create(resect_visit_context visit_context, resect_transl
}

type->initialized = true;
if (is_const) {
type->const_qualified = true;
}

if (type->decl != NULL) {
if (resect_context_diagnostics_level(context) >= RESECT_DIAGNOSTICS_WARNING
Expand Down Expand Up @@ -764,6 +799,14 @@ resect_decl resect_type_get_declaration(resect_type type) { return type->decl; }

resect_type_category resect_type_get_category(resect_type type) { return type->category; }

resect_bool resect_type_has_copy_constructor(resect_type type) { return type->has_copy_constructor; }

resect_bool resect_type_copy_constructor_deleted(resect_type type) { return type->copy_constructor_deleted; }

resect_bool resect_type_has_copy_assignment(resect_type type) { return type->has_copy_assignment; }

resect_bool resect_type_copy_assignment_deleted(resect_type type) { return type->copy_assignment_deleted; }

resect_collection resect_type_template_arguments(resect_type type) { return type->template_arguments; }

resect_string resect_type_pretty_print(resect_translation_context context, CXType type) {
Expand Down