From 0c1659403d376c136dc3e7198dbbbde8524cceb7 Mon Sep 17 00:00:00 2001
From: Grant Jurgensen <grant@jurgensen.dev>
Date: Fri, 6 Nov 2026 12:40:32 -0600
Subject: [PATCH v1] Rename regexec.c's struct vars to struct exec_vars

regcomp.c and regexec.c each define their own, unrelated struct vars.
That alone is harmless, but struct colormap in regguts.h has a member of
type struct vars *, so struct colormap is a different type in each of
the two translation units.  Since commit c54159d44ce, both translation
units also declare (via regguts.h) and call the external function
pg_reg_getcolor(struct colormap *, chr), whose two declarations
therefore have incompatible types.  That is undefined behavior per C17
6.2.7p2.  No diagnostic is required, and compilers accept it, but tools
that check declarations across translation units may reject it.

The struct vars pointer in struct colormap exists only for error
reporting during regex compilation, and the executor never uses it.  So
rename the executor's struct (in regexec.c and rege_dfa.c, which
regexec.c includes), leaving struct vars an incomplete type there.  This
is a pure rename; the generated code is unchanged.
---
 src/backend/regex/rege_dfa.c | 22 +++++-----
 src/backend/regex/regexec.c  | 84 ++++++++++++++++++------------------
 2 files changed, 53 insertions(+), 53 deletions(-)

diff --git a/src/backend/regex/rege_dfa.c b/src/backend/regex/rege_dfa.c
index 5b57fed..f780857 100644
--- a/src/backend/regex/rege_dfa.c
+++ b/src/backend/regex/rege_dfa.c
@@ -39,7 +39,7 @@
  * Internal errors also return NULL, with v->err set.
  */
 static chr *
-longest(struct vars *v,
+longest(struct exec_vars *v,
 		struct dfa *d,
 		chr *start,				/* where the match should start */
 		chr *stop,				/* match must end at or before here */
@@ -201,7 +201,7 @@ longest(struct vars *v,
  * Internal errors also return NULL, with v->err set.
  */
 static chr *
-shortest(struct vars *v,
+shortest(struct exec_vars *v,
 		 struct dfa *d,
 		 chr *start,			/* where the match should start */
 		 chr *min,				/* match must end at or after here */
@@ -368,7 +368,7 @@ shortest(struct vars *v,
  * Internal errors also return 0, with v->err set.
  */
 static int
-matchuntil(struct vars *v,
+matchuntil(struct exec_vars *v,
 		   struct dfa *d,
 		   chr *probe,			/* we want to know if a match ends here */
 		   struct sset **lastcss,	/* state storage across calls */
@@ -503,7 +503,7 @@ matchuntil(struct vars *v,
  * of checking a match to a predetermined section of the string.
  */
 static chr *
-dfa_backref(struct vars *v,
+dfa_backref(struct exec_vars *v,
 			struct dfa *d,
 			chr *start,			/* where the match should start */
 			chr *min,			/* match must end at or after here */
@@ -582,7 +582,7 @@ dfa_backref(struct vars *v,
  * lastcold - determine last point at which no progress had been made
  */
 static chr *					/* endpoint, or NULL */
-lastcold(struct vars *v,
+lastcold(struct exec_vars *v,
 		 struct dfa *d)
 {
 	struct sset *ss;
@@ -604,7 +604,7 @@ lastcold(struct vars *v,
  * Returns NULL (and sets v->err) on failure.
  */
 static struct dfa *
-newdfa(struct vars *v,
+newdfa(struct exec_vars *v,
 	   struct cnfa *cnfa,
 	   struct colormap *cm,
 	   struct smalldfa *sml)	/* preallocated space, may be NULL */
@@ -737,7 +737,7 @@ hash(unsigned *uv,
  * initialize - hand-craft a cache entry for startup, otherwise get ready
  */
 static struct sset *
-initialize(struct vars *v,
+initialize(struct exec_vars *v,
 		   struct dfa *d,
 		   chr *start)
 {
@@ -783,7 +783,7 @@ initialize(struct vars *v,
  * Internal errors also return NULL, with v->err set.
  */
 static struct sset *
-miss(struct vars *v,
+miss(struct exec_vars *v,
 	 struct dfa *d,
 	 struct sset *css,
 	 color co,
@@ -922,7 +922,7 @@ miss(struct vars *v,
  * lacon - lookaround-constraint checker for miss()
  */
 static int						/* predicate:  constraint satisfied? */
-lacon(struct vars *v,
+lacon(struct exec_vars *v,
 	  struct cnfa *pcnfa,		/* parent cnfa */
 	  chr *cp,
 	  color co)					/* "color" of the lookaround constraint */
@@ -979,7 +979,7 @@ lacon(struct vars *v,
  * clear the innards of the state set -- that's up to the caller.
  */
 static struct sset *
-getvacant(struct vars *v,
+getvacant(struct exec_vars *v,
 		  struct dfa *d,
 		  chr *cp,
 		  chr *start)
@@ -1050,7 +1050,7 @@ getvacant(struct vars *v,
  * pickss - pick the next stateset to be used
  */
 static struct sset *
-pickss(struct vars *v,
+pickss(struct exec_vars *v,
 	   struct dfa *d,
 	   chr *cp,
 	   chr *start)
diff --git a/src/backend/regex/regexec.c b/src/backend/regex/regexec.c
index 665aa31..0783a82 100644
--- a/src/backend/regex/regexec.c
+++ b/src/backend/regex/regexec.c
@@ -103,7 +103,7 @@ struct smalldfa
 
 
 /* internal variables, bundled for easy passing around */
-struct vars
+struct exec_vars
 {
 	regex_t    *re;
 	struct guts *g;
@@ -137,44 +137,44 @@ struct vars
  * forward declarations
  */
 /* === regexec.c === */
-static struct dfa *getsubdfa(struct vars *v, struct subre *t);
-static struct dfa *getladfa(struct vars *v, int n);
-static int	find(struct vars *v, struct cnfa *cnfa, struct colormap *cm);
-static int	cfind(struct vars *v, struct cnfa *cnfa, struct colormap *cm);
-static int	cfindloop(struct vars *v, struct cnfa *cnfa, struct colormap *cm,
+static struct dfa *getsubdfa(struct exec_vars *v, struct subre *t);
+static struct dfa *getladfa(struct exec_vars *v, int n);
+static int	find(struct exec_vars *v, struct cnfa *cnfa, struct colormap *cm);
+static int	cfind(struct exec_vars *v, struct cnfa *cnfa, struct colormap *cm);
+static int	cfindloop(struct exec_vars *v, struct cnfa *cnfa, struct colormap *cm,
 					  struct dfa *d, struct dfa *s, chr **coldp);
 static void zapallsubs(regmatch_t *p, size_t n);
-static void zaptreesubs(struct vars *v, struct subre *t);
-static void subset(struct vars *v, struct subre *sub, chr *begin, chr *end);
-static int	cdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
-static int	ccondissect(struct vars *v, struct subre *t, chr *begin, chr *end);
-static int	crevcondissect(struct vars *v, struct subre *t, chr *begin, chr *end);
-static int	cbrdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
-static int	caltdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
-static int	citerdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
-static int	creviterdissect(struct vars *v, struct subre *t, chr *begin, chr *end);
+static void zaptreesubs(struct exec_vars *v, struct subre *t);
+static void subset(struct exec_vars *v, struct subre *sub, chr *begin, chr *end);
+static int	cdissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
+static int	ccondissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
+static int	crevcondissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
+static int	cbrdissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
+static int	caltdissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
+static int	citerdissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
+static int	creviterdissect(struct exec_vars *v, struct subre *t, chr *begin, chr *end);
 
 /* === rege_dfa.c === */
-static chr *longest(struct vars *v, struct dfa *d,
+static chr *longest(struct exec_vars *v, struct dfa *d,
 					chr *start, chr *stop, int *hitstopp);
-static chr *shortest(struct vars *v, struct dfa *d, chr *start, chr *min,
+static chr *shortest(struct exec_vars *v, struct dfa *d, chr *start, chr *min,
 					 chr *max, chr **coldp, int *hitstopp);
-static int	matchuntil(struct vars *v, struct dfa *d, chr *probe,
+static int	matchuntil(struct exec_vars *v, struct dfa *d, chr *probe,
 					   struct sset **lastcss, chr **lastcp);
-static chr *dfa_backref(struct vars *v, struct dfa *d, chr *start,
+static chr *dfa_backref(struct exec_vars *v, struct dfa *d, chr *start,
 						chr *min, chr *max, bool shortest);
-static chr *lastcold(struct vars *v, struct dfa *d);
-static struct dfa *newdfa(struct vars *v, struct cnfa *cnfa,
+static chr *lastcold(struct exec_vars *v, struct dfa *d);
+static struct dfa *newdfa(struct exec_vars *v, struct cnfa *cnfa,
 						  struct colormap *cm, struct smalldfa *sml);
 static void freedfa(struct dfa *d);
 static unsigned hash(unsigned *uv, int n);
-static struct sset *initialize(struct vars *v, struct dfa *d, chr *start);
-static struct sset *miss(struct vars *v, struct dfa *d, struct sset *css,
+static struct sset *initialize(struct exec_vars *v, struct dfa *d, chr *start);
+static struct sset *miss(struct exec_vars *v, struct dfa *d, struct sset *css,
 						 color co, chr *cp, chr *start);
-static int	lacon(struct vars *v, struct cnfa *pcnfa, chr *cp, color co);
-static struct sset *getvacant(struct vars *v, struct dfa *d, chr *cp,
+static int	lacon(struct exec_vars *v, struct cnfa *pcnfa, chr *cp, color co);
+static struct sset *getvacant(struct exec_vars *v, struct dfa *d, chr *cp,
 							  chr *start);
-static struct sset *pickss(struct vars *v, struct dfa *d, chr *cp,
+static struct sset *pickss(struct exec_vars *v, struct dfa *d, chr *cp,
 						   chr *start);
 
 
@@ -191,8 +191,8 @@ pg_regexec(regex_t *re,
 		   regmatch_t pmatch[],
 		   int flags)
 {
-	struct vars var;
-	struct vars *v = &var;
+	struct exec_vars var;
+	struct exec_vars *v = &var;
 	int			st;
 	size_t		n;
 	size_t		i;
@@ -371,7 +371,7 @@ cleanup:
  * The DFA will be freed by the cleanup step in pg_regexec().
  */
 static struct dfa *
-getsubdfa(struct vars *v,
+getsubdfa(struct exec_vars *v,
 		  struct subre *t)
 {
 	struct dfa *d = v->subdfas[t->id];
@@ -399,7 +399,7 @@ getsubdfa(struct vars *v,
  * Same as above, but for LACONs.
  */
 static struct dfa *
-getladfa(struct vars *v,
+getladfa(struct exec_vars *v,
 		 int n)
 {
 	assert(n > 0 && n < v->g->nlacons && v->g->lacons != NULL);
@@ -418,7 +418,7 @@ getladfa(struct vars *v,
  * find - find a match for the main NFA (no-complications case)
  */
 static int
-find(struct vars *v,
+find(struct exec_vars *v,
 	 struct cnfa *cnfa,
 	 struct colormap *cm)
 {
@@ -508,7 +508,7 @@ find(struct vars *v,
  * cfind - find a match for the main NFA (with complications)
  */
 static int
-cfind(struct vars *v,
+cfind(struct exec_vars *v,
 	  struct cnfa *cnfa,
 	  struct colormap *cm)
 {
@@ -548,7 +548,7 @@ cfind(struct vars *v,
  * cfindloop - the heart of cfind
  */
 static int
-cfindloop(struct vars *v,
+cfindloop(struct exec_vars *v,
 		  struct cnfa *cnfa,
 		  struct colormap *cm,
 		  struct dfa *d,
@@ -678,7 +678,7 @@ zapallsubs(regmatch_t *p,
  * zaptreesubs - initialize subexpressions within subtree to "no match"
  */
 static void
-zaptreesubs(struct vars *v,
+zaptreesubs(struct exec_vars *v,
 			struct subre *t)
 {
 	int			n = t->capno;
@@ -701,7 +701,7 @@ zaptreesubs(struct vars *v,
  * subset - set subexpression match data for a successful subre
  */
 static void
-subset(struct vars *v,
+subset(struct exec_vars *v,
 	   struct subre *sub,
 	   chr *begin,
 	   chr *end)
@@ -755,7 +755,7 @@ subset(struct vars *v,
  * start of each cdissect level.
  */
 static int						/* regexec return code */
-cdissect(struct vars *v,
+cdissect(struct exec_vars *v,
 		 struct subre *t,
 		 chr *begin,			/* beginning of relevant substring */
 		 chr *end)				/* end of same */
@@ -828,7 +828,7 @@ cdissect(struct vars *v,
  * ccondissect - dissect match for concatenation node
  */
 static int						/* regexec return code */
-ccondissect(struct vars *v,
+ccondissect(struct exec_vars *v,
 			struct subre *t,
 			chr *begin,			/* beginning of relevant substring */
 			chr *end)			/* end of same */
@@ -909,7 +909,7 @@ ccondissect(struct vars *v,
  * crevcondissect - dissect match for concatenation node, shortest-first
  */
 static int						/* regexec return code */
-crevcondissect(struct vars *v,
+crevcondissect(struct exec_vars *v,
 			   struct subre *t,
 			   chr *begin,		/* beginning of relevant substring */
 			   chr *end)		/* end of same */
@@ -993,7 +993,7 @@ crevcondissect(struct vars *v,
  * but we don't know that for sure so must check it here.
  */
 static int						/* regexec return code */
-cbrdissect(struct vars *v,
+cbrdissect(struct exec_vars *v,
 		   struct subre *t,
 		   chr *begin,			/* beginning of relevant substring */
 		   chr *end)			/* end of same */
@@ -1075,7 +1075,7 @@ cbrdissect(struct vars *v,
  * caltdissect - dissect match for alternation node
  */
 static int						/* regexec return code */
-caltdissect(struct vars *v,
+caltdissect(struct exec_vars *v,
 			struct subre *t,
 			chr *begin,			/* beginning of relevant substring */
 			chr *end)			/* end of same */
@@ -1116,7 +1116,7 @@ caltdissect(struct vars *v,
  * citerdissect - dissect match for iteration node
  */
 static int						/* regexec return code */
-citerdissect(struct vars *v,
+citerdissect(struct exec_vars *v,
 			 struct subre *t,
 			 chr *begin,		/* beginning of relevant substring */
 			 chr *end)			/* end of same */
@@ -1320,7 +1320,7 @@ backtrack:
  * creviterdissect - dissect match for iteration node, shortest-first
  */
 static int						/* regexec return code */
-creviterdissect(struct vars *v,
+creviterdissect(struct exec_vars *v,
 				struct subre *t,
 				chr *begin,		/* beginning of relevant substring */
 				chr *end)		/* end of same */

base-commit: 72b9498df9a369e747f8d96efb5a6cd33c2451e2
-- 
2.53.0

