diff --git a/src/rinterface.c b/src/rinterface.c index dc9615cf157..4d1365f4a42 100644 --- a/src/rinterface.c +++ b/src/rinterface.c @@ -11272,7 +11272,7 @@ SEXP R_igraph_eulerian_cycle(SEXP graph) { if (0 != igraph_vector_int_init(&c_vertex_res, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_vertex_res); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_vertex_res); /* Call igraph */ IGRAPH_R_CHECK(igraph_eulerian_cycle(&c_graph, &c_edge_res, &c_vertex_res)); diff --git a/src/rinterface.h b/src/rinterface.h index b5438e58087..e80a49ff997 100644 --- a/src/rinterface.h +++ b/src/rinterface.h @@ -120,6 +120,24 @@ igraph_error_t R_SEXP_to_attr_comb(SEXP input, igraph_attribute_combination_t *c else if (__c != IGRAPH_SUCCESS) { R_igraph_error(); } \ } while (0) +// This is a variant of IGRAPH_FINALLY that satisfies UBSAN checks. +#define IGRAPH_FINALLY_PV(func, ptr) \ + do { \ + /* the following branch makes the compiler check the compatibility of \ + * func and ptr to detect cases when we are accidentally invoking an \ + * incorrect destructor function with the pointer */ \ + if (0) { func(ptr); } \ + IGRAPH_FINALLY_REAL((func##_pv), (ptr)); \ + } while (0) + +// These functions are never meant to be called directly, only through IGRAPH_FINALLY_PV. +void igraph_destroy_pv(void *pv_ptr); +void igraph_matrix_destroy_pv(void *pv_ptr); +void igraph_vector_destroy_pv(void *pv_ptr); +void igraph_vector_int_destroy_pv(void *pv_ptr); +void igraph_vector_bool_destroy_pv(void *pv_ptr); +void igraph_vector_int_list_destroy_pv(void *pv_ptr); + #define IGRAPH_R_CHECK_INT(v) R_check_int_scalar(v) #define IGRAPH_R_CHECK_REAL(v) R_check_real_scalar(v) #define IGRAPH_R_CHECK_BOOL(v) R_check_bool_scalar(v) diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 1722bebfd7b..821e92985cc 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -99,6 +99,38 @@ void R_check_bool_scalar(SEXP value) } } +// These functions are never meant to be called directly, only through IGRAPH_FINALLY_PV. + +void igraph_destroy_pv(void* pv_ptr) +{ + igraph_destroy((igraph_t*) pv_ptr); +} + +void igraph_matrix_destroy_pv(void *pv_ptr) +{ + igraph_matrix_destroy((igraph_matrix_t*) pv_ptr); +} + +void igraph_vector_destroy_pv(void *pv_ptr) +{ + igraph_vector_destroy((igraph_vector_t*) pv_ptr); +} + +void igraph_vector_int_destroy_pv(void* pv_ptr) +{ + igraph_vector_int_destroy((igraph_vector_int_t*) pv_ptr); +} + +void igraph_vector_bool_destroy_pv(void *pv_ptr) +{ + igraph_vector_bool_destroy((igraph_vector_bool_t*) pv_ptr); +} + +void igraph_vector_int_list_destroy_pv(void *pv_ptr) +{ + igraph_vector_int_list_destroy((igraph_vector_int_list_t*) pv_ptr); +} + igraph_error_t R_get_int_scalar(SEXP sexp, R_xlen_t index, igraph_integer_t *res) { if (Rf_xlength(sexp) <= index) @@ -586,7 +618,7 @@ igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t /* First add the new attributes, if any */ newattrs=0; if (igraph_vector_int_init(&news, 0)) Rf_error("Out of memory"); - IGRAPH_FINALLY(igraph_vector_int_destroy, &news); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &news); for (igraph_integer_t i=0; iname; @@ -906,7 +938,7 @@ igraph_error_t R_igraph_attribute_add_edges(igraph_t *graph, const igraph_vector int px = 0; if (igraph_vector_int_init(&news, 0)) Rf_error("Out of memory"); - IGRAPH_FINALLY(igraph_vector_int_destroy, &news); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &news); SEXP newattr = PROTECT(R_igraph_attribute_add_edges_dup(attr)); px++; attr=graph->attr=newattr; @@ -2792,11 +2824,11 @@ static igraph_error_t restore_pointer(SEXP graph, igraph_t *g) { igraph_vector_int_t from; R_SEXP_to_vector_int_copy(VECTOR_ELT(graph, igraph_t_idx_from), &from); - IGRAPH_FINALLY(igraph_vector_int_destroy, &from); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &from); igraph_vector_int_t to; R_SEXP_to_vector_int_copy(VECTOR_ELT(graph, igraph_t_idx_to), &to); - IGRAPH_FINALLY(igraph_vector_int_destroy, &to); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &to); igraph_vector_int_t edges; igraph_integer_t no_of_edges=igraph_vector_int_size(&from); @@ -2808,7 +2840,7 @@ static igraph_error_t restore_pointer(SEXP graph, igraph_t *g) { } IGRAPH_CHECK(igraph_empty(g, no_of_nodes, directed)); - IGRAPH_FINALLY(igraph_destroy, g); + IGRAPH_FINALLY_PV(igraph_destroy, g); IGRAPH_CHECK(igraph_add_edges(g, &edges, NULL)); igraph_vector_int_destroy(&from); @@ -3039,19 +3071,19 @@ SEXP R_igraph_hrg_to_SEXP(const igraph_hrg_t *hrg) { igraph_error_t R_SEXP_to_hrg_copy(SEXP shrg, igraph_hrg_t *hrg) { IGRAPH_CHECK(R_SEXP_to_vector_int_copy(VECTOR_ELT(shrg, 0), &hrg->left)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &hrg->left); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &hrg->left); IGRAPH_CHECK(R_SEXP_to_vector_int_copy(VECTOR_ELT(shrg, 1), &hrg->right)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &hrg->right); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &hrg->right); IGRAPH_CHECK(R_SEXP_to_vector_copy(VECTOR_ELT(shrg, 2), &hrg->prob)); - IGRAPH_FINALLY(igraph_vector_destroy, &hrg->prob); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &hrg->prob); IGRAPH_CHECK(R_SEXP_to_vector_int_copy(VECTOR_ELT(shrg, 3), &hrg->edges)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &hrg->edges); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &hrg->edges); IGRAPH_CHECK(R_SEXP_to_vector_int_copy(VECTOR_ELT(shrg, 4), &hrg->vertices)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &hrg->vertices); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &hrg->vertices); IGRAPH_FINALLY_CLEAN(5); @@ -3113,11 +3145,11 @@ SEXP R_igraph_arpack_unpack_complex(SEXP vectors, SEXP values, SEXP nev) { if (0 != R_SEXP_to_igraph_matrix_copy(vectors, &c_vectors)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_vectors); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_vectors); if (0 != R_SEXP_to_igraph_matrix_copy(values, &c_values)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_values); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_values); c_nev=REAL(nev)[0]; /* Call igraph */ IGRAPH_R_CHECK(igraph_arpack_unpack_complex(&c_vectors, &c_values, c_nev)); @@ -3199,13 +3231,13 @@ SEXP R_igraph_sparsemat_to_SEXP_triplet(const igraph_sparsemat_t *sp) { igraph_vector_int_t i, j; igraph_vector_t x; igraph_vector_int_init(&i, nz); - IGRAPH_FINALLY(igraph_vector_int_destroy, &i); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &i); igraph_vector_int_init(&j, nz); - IGRAPH_FINALLY(igraph_vector_int_destroy, &j); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &j); igraph_vector_init(&x, nz); - IGRAPH_FINALLY(igraph_vector_destroy, &x); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &x); igraph_sparsemat_getelements(sp, &j, &i, &x); SET_VECTOR_ELT(res, 2, R_igraph_vector_int_to_SEXP(&i)); @@ -3836,9 +3868,9 @@ SEXP R_igraph_add_edges_manual(SEXP graph, SEXP edges) { SEXP result; R_SEXP_to_vector_int_copy(edges, &v); - IGRAPH_FINALLY(igraph_vector_int_destroy, &v); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &v); R_SEXP_to_igraph_copy(graph, &g); - IGRAPH_FINALLY(igraph_destroy, &g); + IGRAPH_FINALLY_PV(igraph_destroy, &g); IGRAPH_R_CHECK(igraph_add_edges(&g, &v, 0)); PROTECT(result=R_igraph_to_SEXP(&g)); igraph_vector_int_destroy(&v); @@ -4295,7 +4327,7 @@ SEXP R_igraph_barabasi_game(SEXP pn, SEXP ppower, SEXP pm, SEXP poutseq, if (have_outseq) { R_SEXP_to_vector_int_copy(poutseq, &outseq); - IGRAPH_FINALLY(igraph_vector_int_destroy, &outseq); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &outseq); myoutseq = &outseq; } @@ -4344,7 +4376,7 @@ SEXP R_igraph_layout_fruchterman_reingold(SEXP graph, SEXP coords, } else { igraph_matrix_init(&c_coords, 0, 0); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_coords); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_coords); c_niter=(igraph_integer_t) REAL(niter)[0]; c_start_temp=REAL(start_temp)[0]; if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } @@ -4394,7 +4426,7 @@ SEXP R_igraph_layout_fruchterman_reingold_3d(SEXP graph, SEXP coords, } else { igraph_matrix_init(&c_coords, 0, 0); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_coords); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_coords); c_niter=(igraph_integer_t) REAL(niter)[0]; c_start_temp=REAL(start_temp)[0]; if (!Rf_isNull(weights)) { R_SEXP_to_vector(weights, &c_weights); } @@ -4444,7 +4476,7 @@ SEXP R_igraph_layout_kamada_kawai(SEXP graph, SEXP coords, SEXP maxiter, } else { igraph_matrix_init(&c_coords, 0, 0); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_coords); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_coords); c_maxiter=(igraph_integer_t) REAL(maxiter)[0]; c_epsilon=REAL(epsilon)[0]; c_kkconst=REAL(kkconst)[0]; @@ -4497,7 +4529,7 @@ SEXP R_igraph_layout_kamada_kawai_3d(SEXP graph, SEXP coords, SEXP maxiter, } else { igraph_matrix_init(&c_coords, 0, 0); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_coords); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_coords); c_maxiter=(igraph_integer_t) REAL(maxiter)[0]; c_epsilon=REAL(epsilon)[0]; c_kkconst=REAL(kkconst)[0]; @@ -4853,13 +4885,13 @@ SEXP R_igraph_degree_sequence_game(SEXP pout_seq, SEXP pin_seq, SEXP result; IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(pout_seq, &outseq)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &outseq); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &outseq); if (!Rf_isNull(pin_seq)) { IGRAPH_R_CHECK(R_SEXP_to_vector_int_copy(pin_seq, &inseq)); } else { IGRAPH_R_CHECK(igraph_vector_int_init(&inseq, 0)); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &inseq); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &inseq); IGRAPH_R_CHECK(igraph_degree_sequence_game(&g, &outseq, Rf_isNull(pin_seq) ? 0 : &inseq, (igraph_degseq_t) method)); PROTECT(result=R_igraph_to_SEXP(&g)); igraph_vector_int_destroy(&outseq); @@ -4880,7 +4912,7 @@ SEXP R_igraph_transitivity_local_undirected_all(SEXP graph, SEXP mode) { R_SEXP_to_igraph(graph, &g); IGRAPH_R_CHECK(igraph_vector_init(&res, 0)); - IGRAPH_FINALLY(igraph_vector_destroy, &res); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &res); IGRAPH_R_CHECK(igraph_transitivity_local_undirected(&g, &res, igraph_vss_all(), isolates)); @@ -5548,9 +5580,9 @@ SEXP R_igraph_compose(SEXP pleft, SEXP pright, SEXP pedgemaps) { R_SEXP_to_igraph(pright, &right); if (edgemaps) { igraph_vector_int_init(my_edgemap1, 0); - IGRAPH_FINALLY(igraph_vector_int_destroy, my_edgemap1); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, my_edgemap1); igraph_vector_int_init(my_edgemap2, 0); - IGRAPH_FINALLY(igraph_vector_int_destroy, my_edgemap2); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, my_edgemap2); } IGRAPH_R_CHECK(igraph_compose(&res, &left, &right, my_edgemap1, my_edgemap2)); PROTECT(result=NEW_LIST(3)); @@ -6571,7 +6603,7 @@ SEXP R_igraph_maximal_cliques(SEXP graph, SEXP psubset, } else { IGRAPH_R_CHECK(igraph_vector_int_init(&subset, 0)); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &subset); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &subset); igraph_vector_int_list_init(&list, 0); igraph_maximal_cliques_subset(&g, Rf_isNull(psubset) ? 0 : &subset, &list, /*no=*/ 0, /*file=*/ 0, @@ -6605,7 +6637,7 @@ SEXP R_igraph_maximal_cliques_file(SEXP graph, SEXP psubset, SEXP file, } else { IGRAPH_R_CHECK(igraph_vector_int_init(&subset, 0)); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &subset); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &subset); #if HAVE_OPEN_MEMSTREAM == 1 stream=open_memstream(&bp, &size); #else @@ -6649,7 +6681,7 @@ SEXP R_igraph_maximal_cliques_count(SEXP graph, SEXP psubset, } else { IGRAPH_R_CHECK(igraph_vector_int_init(&subset, 0)); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &subset); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &subset); c_min_size=REAL(min_size)[0]; c_max_size=REAL(max_size)[0]; /* Call igraph */ @@ -7025,7 +7057,7 @@ SEXP R_igraph_community_to_membership2(SEXP pmerges, SEXP pvcount, IGRAPH_FINALLY(igraph_matrix_int_destroy, &merges); IGRAPH_R_CHECK(igraph_vector_int_init(&membership, 0)); - IGRAPH_FINALLY(igraph_vector_int_destroy, &membership); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &membership); IGRAPH_R_CHECK(igraph_community_to_membership(&merges, vcount, steps, &membership, 0)); PROTECT(result=R_igraph_vector_int_to_SEXP(&membership)); @@ -7159,17 +7191,17 @@ SEXP R_igraph_arpack(SEXP function, SEXP extra, SEXP options, SEXP rho, if (0 != igraph_matrix_init(&vectors, 0, 0)) { igraph_error("Cannot run ARPACK", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &vectors); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &vectors); if (LOGICAL(sym)[0]) { if (0 != igraph_vector_init(&values, 0)) { igraph_error("Cannot run ARPACK", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_destroy, &values); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &values); } else { if (0 != igraph_matrix_init(&values2, 0, 0)) { igraph_error("Cannot run ARPACK", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &values2); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &values2); } data.fun=function; @@ -7231,7 +7263,7 @@ SEXP R_igraph_is_chordal(SEXP graph, SEXP alpha, SEXP alpham1, if (0 != igraph_vector_int_init(&c_fillin, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_fillin); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_fillin); } IGRAPH_R_CHECK(igraph_is_chordal(&c_graph, (Rf_isNull(alpha) ? 0 : &c_alpha), (Rf_isNull(alpham1) ? 0 : &c_alpham1), &c_chordal, (LOGICAL(pfillin)[0] ? &c_fillin : 0), (LOGICAL(pnewgraph)[0] ? &c_newgraph : 0))); @@ -7248,7 +7280,7 @@ SEXP R_igraph_is_chordal(SEXP graph, SEXP alpha, SEXP alpham1, PROTECT(fillin=R_NilValue); } if (LOGICAL(pnewgraph)[0]) { - IGRAPH_FINALLY(igraph_destroy, &c_newgraph); + IGRAPH_FINALLY_PV(igraph_destroy, &c_newgraph); PROTECT(newgraph=R_igraph_to_SEXP(&c_newgraph)); IGRAPH_I_DESTROY(&c_newgraph); IGRAPH_FINALLY_CLEAN(1); @@ -7333,37 +7365,37 @@ SEXP R_igraph_bfs(SEXP graph, SEXP proot, SEXP proots, SEXP pmode, } else { igraph_vector_int_init(&roots, 0); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &roots); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &roots); if (!Rf_isNull(prestricted)) { R_SEXP_to_vector_int_copy(prestricted, &restricted); } else { igraph_vector_int_init(&restricted, 0); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &restricted); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &restricted); if (LOGICAL(porder)[0]) { - igraph_vector_int_init(&order, 0); IGRAPH_FINALLY(igraph_vector_int_destroy, &order); + igraph_vector_int_init(&order, 0); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &order); p_order=ℴ } if (LOGICAL(prank)[0]) { - igraph_vector_int_init(&rank, 0); IGRAPH_FINALLY(igraph_vector_int_destroy, &rank); + igraph_vector_int_init(&rank, 0); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &rank); p_rank=&rank; } if (LOGICAL(pfather)[0]) { - igraph_vector_int_init(&father, 0); IGRAPH_FINALLY(igraph_vector_int_destroy, &father); + igraph_vector_int_init(&father, 0); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &father); p_father=&father; } if (LOGICAL(ppred)[0]) { - igraph_vector_int_init(&pred, 0); IGRAPH_FINALLY(igraph_vector_int_destroy, &pred); + igraph_vector_int_init(&pred, 0); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &pred); p_pred=&pred; } if (LOGICAL(psucc)[0]) { - igraph_vector_int_init(&succ, 0); IGRAPH_FINALLY(igraph_vector_int_destroy, &succ); + igraph_vector_int_init(&succ, 0); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &succ); p_succ=≻ } if (LOGICAL(pdist)[0]) { - igraph_vector_int_init(&dist, 0); IGRAPH_FINALLY(igraph_vector_int_destroy, &dist); + igraph_vector_int_init(&dist, 0); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &dist); p_dist=&dist; } @@ -7572,15 +7604,15 @@ SEXP R_igraph_cohesive_blocks(SEXP graph) { if (0 != igraph_vector_int_list_init(&c_blocks, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_blocks); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_blocks); if (0 != igraph_vector_int_init(&c_cohesion, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_cohesion); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_cohesion); if (0 != igraph_vector_int_init(&c_parent, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_parent); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_parent); IGRAPH_R_CHECK(igraph_cohesive_blocks(&c_graph, &c_blocks, &c_cohesion, &c_parent, &c_blockTree)); @@ -7595,7 +7627,7 @@ SEXP R_igraph_cohesive_blocks(SEXP graph) { PROTECT(parent=R_igraph_vector_int_to_SEXPp1(&c_parent)); igraph_vector_int_destroy(&c_parent); IGRAPH_FINALLY_CLEAN(1); - IGRAPH_FINALLY(igraph_destroy, &c_blockTree); + IGRAPH_FINALLY_PV(igraph_destroy, &c_blockTree); PROTECT(blockTree=R_igraph_to_SEXP(&c_blockTree)); IGRAPH_I_DESTROY(&c_blockTree); IGRAPH_FINALLY_CLEAN(1); @@ -7719,7 +7751,7 @@ SEXP R_igraph_community_leading_eigenvector(SEXP graph, SEXP steps, igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_membership); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_membership); c_steps=(igraph_integer_t) REAL(steps)[0]; R_SEXP_to_igraph_arpack_options(options, &c_options); if (0 != igraph_vector_init(&c_eigenvalues, 0)) { @@ -7825,7 +7857,7 @@ SEXP R_igraph_subisomorphic_lad(SEXP pattern, SEXP target, SEXP domains, } else { igraph_vector_int_list_init(&c_domains, 0); } - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_domains); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_domains); c_qmap=LOGICAL(pqmap)[0]; c_qall_maps=LOGICAL(pqall_maps)[0]; @@ -7833,7 +7865,7 @@ SEXP R_igraph_subisomorphic_lad(SEXP pattern, SEXP target, SEXP domains, if (0 != igraph_vector_int_init(&c_map, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_map); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_map); map=R_GlobalEnv; /* hack to have a non-NULL value */ } else { map=R_NilValue; @@ -7843,7 +7875,7 @@ SEXP R_igraph_subisomorphic_lad(SEXP pattern, SEXP target, SEXP domains, if (0 != igraph_vector_int_list_init(&c_maps, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_maps); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_maps); maps=R_GlobalEnv; /* hack to have a non-NULL value */ } else { maps=R_NilValue; @@ -7908,11 +7940,11 @@ SEXP R_igraph_graphlets(SEXP graph, SEXP weights, SEXP niter) { if (0 != igraph_vector_int_list_init(&c_cliques, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_cliques); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_cliques); if (0 != igraph_vector_init(&c_Mu, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_destroy, &c_Mu); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &c_Mu); c_niter=(igraph_integer_t) REAL(niter)[0]; /* Call igraph */ IGRAPH_R_CHECK(igraph_graphlets(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_cliques, &c_Mu, c_niter)); @@ -7957,11 +7989,11 @@ SEXP R_igraph_graphlets_candidate_basis(SEXP graph, SEXP weights) { if (0 != igraph_vector_int_list_init(&c_cliques, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_cliques); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_cliques); if (0 != igraph_vector_init(&c_thresholds, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_destroy, &c_thresholds); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &c_thresholds); /* Call igraph */ IGRAPH_R_CHECK(igraph_graphlets_candidate_basis(&c_graph, (Rf_isNull(weights) ? 0 : &c_weights), &c_cliques, &c_thresholds)); @@ -8013,11 +8045,11 @@ SEXP R_igraph_graphlets_project(SEXP graph, SEXP weights, SEXP cliques, } else { igraph_vector_int_list_init(&c_cliques, 0); } - IGRAPH_FINALLY(igraph_vector_int_list_destroy, &c_cliques); + IGRAPH_FINALLY_PV(igraph_vector_int_list_destroy, &c_cliques); if (0 != R_SEXP_to_vector_copy(Mu, &c_Mu)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_destroy, &c_Mu); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &c_Mu); c_niter=(igraph_integer_t) REAL(niter)[0]; /* TODO: Change igraph_i_graphlets_project to igraph_graphlets_project, because @@ -8075,17 +8107,17 @@ SEXP R_igraph_adjacency_spectral_embedding(SEXP graph, SEXP no, if (0 != igraph_matrix_init(&c_X, 0, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_X); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_X); if (directed) { if (0 != igraph_matrix_init(&c_Y, 0, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_Y); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_Y); } if (0 != igraph_vector_init(&c_D, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_destroy, &c_D); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &c_D); R_SEXP_to_vector(cvec, &c_cvec); R_SEXP_to_igraph_arpack_options(options, &c_options); @@ -8156,17 +8188,17 @@ SEXP R_igraph_laplacian_spectral_embedding(SEXP graph, SEXP no, if (0 != igraph_matrix_init(&c_X, 0, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_X); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_X); if (directed) { if (0 != igraph_matrix_init(&c_Y, 0, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_matrix_destroy, &c_Y); + IGRAPH_FINALLY_PV(igraph_matrix_destroy, &c_Y); } if (0 != igraph_vector_init(&c_D, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_destroy, &c_D); + IGRAPH_FINALLY_PV(igraph_vector_destroy, &c_D); R_SEXP_to_igraph_arpack_options(options, &c_options); /* Call igraph */ IGRAPH_R_CHECK(igraph_laplacian_spectral_embedding(&c_graph, c_no, (Rf_isNull(weights) ? 0 : &c_weights), c_which, c_type, c_scaled, &c_X, directed ? &c_Y : 0, &c_D, &c_options)); @@ -8228,12 +8260,12 @@ SEXP R_igraph_bipartite_projection(SEXP graph, SEXP types, SEXP probe1, if (0 != igraph_vector_int_init(&c_multiplicity1, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_multiplicity1); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_multiplicity1); multiplicity1 = R_GlobalEnv; /* hack to have a non-NULL value */ if (0 != igraph_vector_int_init(&c_multiplicity2, 0)) { igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); } - IGRAPH_FINALLY(igraph_vector_int_destroy, &c_multiplicity2); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &c_multiplicity2); multiplicity2=R_GlobalEnv; /* hack to have a non-NULL value */ c_probe1=REAL(probe1)[0]; /* Call igraph */ @@ -8243,7 +8275,7 @@ SEXP R_igraph_bipartite_projection(SEXP graph, SEXP types, SEXP probe1, PROTECT(result=NEW_LIST(4)); PROTECT(names=NEW_CHARACTER(4)); if (do_1) { - IGRAPH_FINALLY(igraph_destroy, &c_proj1); + IGRAPH_FINALLY_PV(igraph_destroy, &c_proj1); PROTECT(proj1=R_igraph_to_SEXP(&c_proj1)); IGRAPH_I_DESTROY(&c_proj1); IGRAPH_FINALLY_CLEAN(1); @@ -8251,7 +8283,7 @@ SEXP R_igraph_bipartite_projection(SEXP graph, SEXP types, SEXP probe1, PROTECT(proj1=R_NilValue); } if (do_2) { - IGRAPH_FINALLY(igraph_destroy, &c_proj2); + IGRAPH_FINALLY_PV(igraph_destroy, &c_proj2); PROTECT(proj2=R_igraph_to_SEXP(&c_proj2)); IGRAPH_I_DESTROY(&c_proj2); IGRAPH_FINALLY_CLEAN(1); @@ -8293,7 +8325,7 @@ SEXP R_igraph_adjacent_vertices(SEXP pgraph, SEXP pv, SEXP pmode) { R_SEXP_to_igraph(pgraph, &graph); R_SEXP_to_igraph_vs(pv, &graph, &vs, &vs_data); IGRAPH_FINALLY(igraph_vs_destroy, &vs); - IGRAPH_FINALLY(igraph_vector_int_destroy, &vs_data); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &vs_data); igraph_vit_create(&graph, vs, &vit); IGRAPH_FINALLY(igraph_vit_destroy, &vit); @@ -8339,7 +8371,7 @@ SEXP R_igraph_incident_edges(SEXP pgraph, SEXP pe, SEXP pmode) { R_SEXP_to_igraph(pgraph, &graph); R_SEXP_to_igraph_vs(pe, &graph, &vs, &vs_data); IGRAPH_FINALLY(igraph_vs_destroy, &vs); - IGRAPH_FINALLY(igraph_vector_int_destroy, &vs_data); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &vs_data); igraph_vit_create(&graph, vs, &vit); IGRAPH_FINALLY(igraph_vit_destroy, &vit); diff --git a/src/vendor/cigraph/interfaces/functions.yaml b/src/vendor/cigraph/interfaces/functions.yaml index 7f7f02ee21d..34f3b99384a 100644 --- a/src/vendor/cigraph/interfaces/functions.yaml +++ b/src/vendor/cigraph/interfaces/functions.yaml @@ -2524,7 +2524,7 @@ igraph_eulerian_path: DEPS: edge_res ON graph, vertex_res ON graph igraph_eulerian_cycle: - PARAMS: GRAPH graph, OPTIONAL OUT EDGE_INDICES edge_res, OPTIONAL OUT VERTEX_INDICES vertex_res + PARAMS: GRAPH graph, OPTIONAL OUT EDGE_INDICES edge_res, OPTIONAL OUT VERTEX_INDICES_PV vertex_res DEPS: edge_res ON graph, vertex_res ON graph ####################################### diff --git a/src/vendor/cigraph/interfaces/types.yaml b/src/vendor/cigraph/interfaces/types.yaml index 06d66dd4eeb..27fd70c03be 100644 --- a/src/vendor/cigraph/interfaces/types.yaml +++ b/src/vendor/cigraph/interfaces/types.yaml @@ -157,6 +157,13 @@ VERTEX_INDICES: CTYPE: igraph_vector_int_t FLAGS: BY_REF +# Temporary, for https://github.com/igraph/rigraph/pull/1630 +# We should call the `_PV` versions for all types in the future. +VERTEX_INDICES_PV: + # An integer vector containing vertex indices. + CTYPE: igraph_vector_int_t + FLAGS: BY_REF + VERTEX_INDEX_PAIRS: # An integer vector containing pairs of vertex indices, in a flattened # representation diff --git a/tools/stimulus/types-RC.yaml b/tools/stimulus/types-RC.yaml index 0b563a96489..8530ccbd4e1 100644 --- a/tools/stimulus/types-RC.yaml +++ b/tools/stimulus/types-RC.yaml @@ -536,6 +536,27 @@ VERTEX_INDICES: igraph_vector_int_destroy(&%C%); IGRAPH_FINALLY_CLEAN(1); +VERTEX_INDICES_PV: + CALL: '&%C%' + CTYPE: igraph_vector_int_t + INCONV: + IN: |- + R_SEXP_to_vector_int_copy(%I%, &%C%); + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &%C%); + OUT: |- + if (0 != igraph_vector_int_init(&%C%, 0)) { + igraph_error("", __FILE__, __LINE__, IGRAPH_ENOMEM); + } + IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &%C%); + OUTCONV: + IN: |- + igraph_vector_int_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + OUT: |- + PROTECT(%I%=R_igraph_vector_int_to_SEXPp1(&%C%)); + igraph_vector_int_destroy(&%C%); + IGRAPH_FINALLY_CLEAN(1); + VERTEX_INDEX_PAIRS: CALL: '&%C%' CTYPE: igraph_vector_int_t diff --git a/tools/stimulus/types-RR.yaml b/tools/stimulus/types-RR.yaml index c72ed787ded..c1becd741b2 100644 --- a/tools/stimulus/types-RR.yaml +++ b/tools/stimulus/types-RR.yaml @@ -141,6 +141,19 @@ VERTEX_INDICES: %I% <- create_vs(%I1%, %I%) } +# Temporary, for https://github.com/igraph/rigraph/pull/1630 +# We should call the `_PV` versions for all types in the future. +VERTEX_INDICES_PV: + CALL: '%I%-1' + DEFAULT: + ALL: V(%I1%) + INCONV: '%I% <- as_igraph_vs(%I1%, %I%)' + OUTCONV: + OUT: |- + if (igraph_opt("return.vs.es")) { + %I% <- create_vs(%I1%, %I%) + } + EDGE_INDICES: CALL: '%I%-1' DEFAULT: