Enable "missing prototypes" warning for gcc, clang
Missing prototypes for exported functions cause a really huge issue on Windows. Enabling the "missing prototypes" warning makes it much easier to catch this problem. Naturally, any warnings caused by this have been fixed. Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
a4d8aba4f9
commit
32b683bf37
26 changed files with 92 additions and 304 deletions
|
@ -230,6 +230,7 @@ DDS_EXPORT nn_plist_t *nn_plist_dup (const nn_plist_t *src);
|
|||
*/
|
||||
DDS_EXPORT dds_return_t nn_plist_init_frommsg (nn_plist_t *dest, char **nextafterplist, uint64_t pwanted, uint64_t qwanted, const nn_plist_src_t *src);
|
||||
DDS_EXPORT void nn_plist_fini (nn_plist_t *ps);
|
||||
DDS_EXPORT void nn_plist_unalias (nn_plist_t *plist);
|
||||
DDS_EXPORT void nn_plist_addtomsg (struct nn_xmsg *m, const nn_plist_t *ps, uint64_t pwanted, uint64_t qwanted);
|
||||
DDS_EXPORT void nn_plist_init_default_participant (nn_plist_t *plist);
|
||||
|
||||
|
|
|
@ -120,23 +120,8 @@ void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, Sub
|
|||
void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t);
|
||||
void nn_xmsg_add_entityid (struct nn_xmsg * m);
|
||||
void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len);
|
||||
void nn_xmsg_addpar_string (struct nn_xmsg *m, nn_parameterid_t pid, const char *str);
|
||||
void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_octetseq_t *oseq);
|
||||
void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_stringseq_t *sseq);
|
||||
void nn_xmsg_addpar_guid (struct nn_xmsg *m, nn_parameterid_t pid, const nn_guid_t *guid);
|
||||
void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x);
|
||||
void nn_xmsg_addpar_4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x);
|
||||
void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata);
|
||||
void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, uint32_t statusinfo);
|
||||
void nn_xmsg_addpar_reliability (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_reliability_qospolicy *rq);
|
||||
void nn_xmsg_addpar_duration (struct nn_xmsg *m, nn_parameterid_t pid, const dds_duration_t dur);
|
||||
void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_subscription_keys_qospolicy *rq);
|
||||
void nn_xmsg_addpar_durability_service (struct nn_xmsg *m, nn_parameterid_t pid, const dds_durability_service_qospolicy_t *rq);
|
||||
void nn_xmsg_addpar_reader_lifespan (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_lifespan_qospolicy_t *rq);
|
||||
void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_data_lifecycle_qospolicy_t *rq);
|
||||
void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq);
|
||||
|
||||
void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi);
|
||||
void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo);
|
||||
void nn_xmsg_addpar_sentinel (struct nn_xmsg *m);
|
||||
int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m);
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ static struct ddsi_serdata *serdata_default_from_ser_nokey (const struct ddsi_se
|
|||
return fix_serdata_default_nokey (d, tpcmn->serdata_basehash);
|
||||
}
|
||||
|
||||
struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash)
|
||||
static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash)
|
||||
{
|
||||
/* FIXME: not quite sure this is correct, though a check against a specially hacked OpenSplice suggests it is */
|
||||
const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn;
|
||||
|
@ -360,7 +360,7 @@ struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *
|
|||
}
|
||||
}
|
||||
|
||||
struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash)
|
||||
static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash)
|
||||
{
|
||||
const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn;
|
||||
struct ddsi_serdata_default *d = serdata_default_new(tp, SDK_KEY);
|
||||
|
|
|
@ -408,7 +408,7 @@ static void ddsi_udp_release_conn (ddsi_tran_conn_t conn)
|
|||
ddsrt_free (conn);
|
||||
}
|
||||
|
||||
void ddsi_udp_fini (void)
|
||||
static void ddsi_udp_fini (void)
|
||||
{
|
||||
if(ddsrt_atomic_dec32_nv (&ddsi_udp_init_g) == 0) {
|
||||
free_group_membership(ddsi_udp_config_g.mship);
|
||||
|
|
|
@ -384,24 +384,6 @@ void copy_addrset_into_addrset_no_ssm (struct addrset *as, const struct addrset
|
|||
copy_addrset_into_addrset_uc (as, asadd);
|
||||
copy_addrset_into_addrset_no_ssm_mc (as, asadd);
|
||||
}
|
||||
|
||||
void addrset_purge_ssm (struct addrset *as)
|
||||
{
|
||||
struct addrset_node *n;
|
||||
LOCK (as);
|
||||
n = ddsrt_avl_cfind_min (&addrset_treedef, &as->mcaddrs);
|
||||
while (n)
|
||||
{
|
||||
struct addrset_node *n1 = n;
|
||||
n = ddsrt_avl_cfind_succ (&addrset_treedef, &as->mcaddrs, n);
|
||||
if (ddsi_is_ssm_mcaddr (&n1->loc))
|
||||
{
|
||||
ddsrt_avl_cdelete (&addrset_treedef, &as->mcaddrs, n1);
|
||||
ddsrt_free (n1);
|
||||
}
|
||||
}
|
||||
UNLOCK (as);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t addrset_count (const struct addrset *as)
|
||||
|
|
|
@ -190,7 +190,7 @@ static void entity_common_fini (struct entity_common *e)
|
|||
ddsrt_mutex_destroy (&e->lock);
|
||||
}
|
||||
|
||||
void local_reader_ary_init (struct local_reader_ary *x)
|
||||
static void local_reader_ary_init (struct local_reader_ary *x)
|
||||
{
|
||||
ddsrt_mutex_init (&x->rdary_lock);
|
||||
x->valid = 1;
|
||||
|
@ -200,13 +200,13 @@ void local_reader_ary_init (struct local_reader_ary *x)
|
|||
x->rdary[0] = NULL;
|
||||
}
|
||||
|
||||
void local_reader_ary_fini (struct local_reader_ary *x)
|
||||
static void local_reader_ary_fini (struct local_reader_ary *x)
|
||||
{
|
||||
ddsrt_free (x->rdary);
|
||||
ddsrt_mutex_destroy (&x->rdary_lock);
|
||||
}
|
||||
|
||||
void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd)
|
||||
static void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd)
|
||||
{
|
||||
ddsrt_mutex_lock (&x->rdary_lock);
|
||||
x->n_readers++;
|
||||
|
@ -216,7 +216,7 @@ void local_reader_ary_insert (struct local_reader_ary *x, struct reader *rd)
|
|||
ddsrt_mutex_unlock (&x->rdary_lock);
|
||||
}
|
||||
|
||||
void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd)
|
||||
static void local_reader_ary_remove (struct local_reader_ary *x, struct reader *rd)
|
||||
{
|
||||
uint32_t i;
|
||||
ddsrt_mutex_lock (&x->rdary_lock);
|
||||
|
@ -242,7 +242,7 @@ void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_
|
|||
ddsrt_mutex_unlock (&x->rdary_lock);
|
||||
}
|
||||
|
||||
void local_reader_ary_setinvalid (struct local_reader_ary *x)
|
||||
static void local_reader_ary_setinvalid (struct local_reader_ary *x)
|
||||
{
|
||||
ddsrt_mutex_lock (&x->rdary_lock);
|
||||
x->valid = 0;
|
||||
|
|
|
@ -46,7 +46,7 @@ extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts
|
|||
|
||||
static struct thread_state1 *init_thread_state (const char *tname, enum thread_state state);
|
||||
|
||||
void *ddsrt_malloc_aligned_cacheline (size_t size)
|
||||
static void *ddsrt_malloc_aligned_cacheline (size_t size)
|
||||
{
|
||||
/* This wastes some space, but we use it only once and it isn't a
|
||||
huge amount of memory, just a little over a cache line.
|
||||
|
|
|
@ -147,7 +147,7 @@ typedef struct {
|
|||
ddsrt_cond_t cv;
|
||||
} ddsi_sem_t;
|
||||
|
||||
dds_return_t
|
||||
static dds_return_t
|
||||
ddsi_sem_init (ddsi_sem_t *sem, uint32_t value)
|
||||
{
|
||||
sem->value = value;
|
||||
|
@ -156,7 +156,7 @@ ddsi_sem_init (ddsi_sem_t *sem, uint32_t value)
|
|||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
static dds_return_t
|
||||
ddsi_sem_destroy (ddsi_sem_t *sem)
|
||||
{
|
||||
ddsrt_cond_destroy (&sem->cv);
|
||||
|
@ -164,7 +164,7 @@ ddsi_sem_destroy (ddsi_sem_t *sem)
|
|||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
static dds_return_t
|
||||
ddsi_sem_post (ddsi_sem_t *sem)
|
||||
{
|
||||
ddsrt_mutex_lock (&sem->mtx);
|
||||
|
@ -174,7 +174,7 @@ ddsi_sem_post (ddsi_sem_t *sem)
|
|||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
static dds_return_t
|
||||
ddsi_sem_wait (ddsi_sem_t *sem)
|
||||
{
|
||||
ddsrt_mutex_lock (&sem->mtx);
|
||||
|
@ -763,41 +763,6 @@ void nn_xmsg_setwriterseq_fragid (struct nn_xmsg *msg, const nn_guid_t *wrguid,
|
|||
msg->kindspecific.data.wrfragid = wrfragid;
|
||||
}
|
||||
|
||||
size_t nn_xmsg_add_string_padded(unsigned char *buf, char *str)
|
||||
{
|
||||
size_t len = strlen (str) + 1;
|
||||
assert (len <= UINT32_MAX);
|
||||
if (buf) {
|
||||
/* Add cdr string */
|
||||
struct cdrstring *p = (struct cdrstring *) buf;
|
||||
p->length = (uint32_t)len;
|
||||
memcpy (p->contents, str, len);
|
||||
/* clear padding */
|
||||
if (len < align4u (len)) {
|
||||
memset (p->contents + len, 0, align4u (len) - len);
|
||||
}
|
||||
}
|
||||
len = 4 + /* cdr string len arg + */
|
||||
align4u(len); /* strlen + possible padding */
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t nn_xmsg_add_octseq_padded(unsigned char *buf, ddsi_octetseq_t *seq)
|
||||
{
|
||||
uint32_t len = seq->length;
|
||||
if (buf) {
|
||||
/* Add cdr octet seq */
|
||||
*((uint32_t *) buf) = len;
|
||||
buf += sizeof (uint32_t);
|
||||
memcpy (buf, seq->value, len);
|
||||
/* clear padding */
|
||||
if (len < align4u (len)) {
|
||||
memset (buf + len, 0, align4u (len) - len);
|
||||
}
|
||||
}
|
||||
return 4 + align4u (len);
|
||||
}
|
||||
|
||||
void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len)
|
||||
{
|
||||
const size_t len4 = (len + 3) & ~(size_t)3; /* must alloc a multiple of 4 */
|
||||
|
@ -816,43 +781,6 @@ void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len)
|
|||
return p;
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_string (struct nn_xmsg *m, nn_parameterid_t pid, const char *str)
|
||||
{
|
||||
struct cdrstring *p;
|
||||
size_t len = strlen (str) + 1;
|
||||
p = nn_xmsg_addpar (m, pid, 4 + len);
|
||||
p->length = (uint32_t) len;
|
||||
memcpy (p->contents, str, len);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_octetseq_t *oseq)
|
||||
{
|
||||
char *p = nn_xmsg_addpar (m, pid, 4 + oseq->length);
|
||||
*((unsigned *) p) = oseq->length;
|
||||
memcpy (p + sizeof (int), oseq->value, oseq->length);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, nn_parameterid_t pid, const ddsi_stringseq_t *sseq)
|
||||
{
|
||||
unsigned char *tmp;
|
||||
uint32_t i;
|
||||
size_t len = 0;
|
||||
|
||||
for (i = 0; i < sseq->n; i++)
|
||||
{
|
||||
len += nn_xmsg_add_string_padded(NULL, sseq->strs[i]);
|
||||
}
|
||||
|
||||
tmp = nn_xmsg_addpar (m, pid, 4 + len);
|
||||
|
||||
*((uint32_t *) tmp) = sseq->n;
|
||||
tmp += sizeof (uint32_t);
|
||||
for (i = 0; i < sseq->n; i++)
|
||||
{
|
||||
tmp += nn_xmsg_add_string_padded(tmp, sseq->strs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata)
|
||||
{
|
||||
if (serdata->kind != SDK_EMPTY)
|
||||
|
@ -863,78 +791,7 @@ void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serda
|
|||
}
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_guid (struct nn_xmsg *m, nn_parameterid_t pid, const nn_guid_t *guid)
|
||||
{
|
||||
unsigned *pu;
|
||||
int i;
|
||||
pu = nn_xmsg_addpar (m, pid, 16);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
pu[i] = toBE4u (guid->prefix.u[i]);
|
||||
}
|
||||
pu[i] = toBE4u (guid->entityid.u);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_reliability (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_reliability_qospolicy *rq)
|
||||
{
|
||||
struct dds_external_reliability_qospolicy *p;
|
||||
p = nn_xmsg_addpar (m, pid, sizeof (*p));
|
||||
switch (rq->kind)
|
||||
{
|
||||
case DDS_RELIABILITY_BEST_EFFORT:
|
||||
p->kind = DDS_EXTERNAL_RELIABILITY_BEST_EFFORT;
|
||||
break;
|
||||
case DDS_RELIABILITY_RELIABLE:
|
||||
p->kind = DDS_EXTERNAL_RELIABILITY_RELIABLE;
|
||||
break;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
p->max_blocking_time = nn_to_ddsi_duration (rq->max_blocking_time);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_duration (struct nn_xmsg *m, nn_parameterid_t pid, const dds_duration_t rq)
|
||||
{
|
||||
ddsi_duration_t *p = nn_xmsg_addpar (m, pid, sizeof (*p));
|
||||
*p = nn_to_ddsi_duration (rq);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_durability_service (struct nn_xmsg *m, nn_parameterid_t pid, const dds_durability_service_qospolicy_t *rq)
|
||||
{
|
||||
dds_external_durability_service_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p));
|
||||
p->history = rq->history;
|
||||
p->resource_limits = rq->resource_limits;
|
||||
p->service_cleanup_delay = nn_to_ddsi_duration (rq->service_cleanup_delay);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_reader_lifespan (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_lifespan_qospolicy_t *rq)
|
||||
{
|
||||
dds_external_reader_lifespan_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p));
|
||||
p->use_lifespan = rq->use_lifespan;
|
||||
p->duration = nn_to_ddsi_duration (rq->duration);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_reader_data_lifecycle (struct nn_xmsg *m, nn_parameterid_t pid, const dds_reader_data_lifecycle_qospolicy_t *rq)
|
||||
{
|
||||
dds_external_reader_data_lifecycle_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p));
|
||||
p->autopurge_disposed_samples_delay = nn_to_ddsi_duration (rq->autopurge_disposed_samples_delay);
|
||||
p->autopurge_nowriter_samples_delay = nn_to_ddsi_duration (rq->autopurge_nowriter_samples_delay);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_liveliness (struct nn_xmsg *m, nn_parameterid_t pid, const dds_liveliness_qospolicy_t *rq)
|
||||
{
|
||||
dds_external_liveliness_qospolicy_t *p = nn_xmsg_addpar (m, pid, sizeof (*p));
|
||||
p->kind = rq->kind;
|
||||
p->lease_duration = nn_to_ddsi_duration (rq->lease_duration);
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x)
|
||||
{
|
||||
unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x));
|
||||
*p = x;
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x)
|
||||
static void nn_xmsg_addpar_BE4u (struct nn_xmsg *m, nn_parameterid_t pid, uint32_t x)
|
||||
{
|
||||
unsigned *p = nn_xmsg_addpar (m, pid, sizeof (x));
|
||||
*p = toBE4u (x);
|
||||
|
@ -956,40 +813,6 @@ void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo)
|
|||
}
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_subscription_keys (struct nn_xmsg *m, nn_parameterid_t pid, const struct dds_subscription_keys_qospolicy *q)
|
||||
{
|
||||
unsigned char *tmp;
|
||||
size_t len = 8; /* use_key_list, length of key_list */
|
||||
|
||||
for (uint32_t i = 0; i < q->key_list.n; i++)
|
||||
{
|
||||
size_t len1 = strlen (q->key_list.strs[i]) + 1;
|
||||
len += 4 + align4u (len1);
|
||||
}
|
||||
|
||||
tmp = nn_xmsg_addpar (m, pid, len);
|
||||
|
||||
tmp[0] = q->use_key_list;
|
||||
for (uint32_t i = 1; i < sizeof (int); i++)
|
||||
{
|
||||
tmp[i] = 0;
|
||||
}
|
||||
tmp += sizeof (int);
|
||||
*((uint32_t *) tmp) = q->key_list.n;
|
||||
tmp += sizeof (uint32_t);
|
||||
for (uint32_t i = 0; i < q->key_list.n; i++)
|
||||
{
|
||||
struct cdrstring *p = (struct cdrstring *) tmp;
|
||||
size_t len1 = strlen (q->key_list.strs[i]) + 1;
|
||||
assert (len1 <= UINT32_MAX);
|
||||
p->length = (uint32_t)len1;
|
||||
memcpy (p->contents, q->key_list.strs[i], len1);
|
||||
if (len1 < align4u (len1))
|
||||
memset (p->contents + len1, 0, align4u (len1) - len1);
|
||||
tmp += 4 + align4u (len1);
|
||||
}
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_sentinel (struct nn_xmsg * m)
|
||||
{
|
||||
nn_xmsg_addpar (m, PID_SENTINEL, 0);
|
||||
|
@ -1005,27 +828,6 @@ int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg * m)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void nn_xmsg_addpar_parvinfo (struct nn_xmsg *m, nn_parameterid_t pid, const struct nn_prismtech_participant_version_info *pvi)
|
||||
{
|
||||
int i;
|
||||
unsigned slen;
|
||||
unsigned *pu;
|
||||
struct cdrstring *ps;
|
||||
|
||||
/* pvi->internals cannot be NULL here */
|
||||
slen = (unsigned) strlen(pvi->internals) + 1; /* +1 for '\0' terminator */
|
||||
pu = nn_xmsg_addpar (m, pid, NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE + slen);
|
||||
pu[0] = pvi->version;
|
||||
pu[1] = pvi->flags;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
pu[i+2] = (pvi->unused[i]);
|
||||
}
|
||||
ps = (struct cdrstring *)&pu[5];
|
||||
ps->length = slen;
|
||||
memcpy(ps->contents, pvi->internals, slen);
|
||||
}
|
||||
|
||||
/* XMSG_CHAIN ----------------------------------------------------------
|
||||
|
||||
Xpacks refer to xmsgs and need to release these after having been
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue