aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-10-04 17:14:59 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-10-04 17:15:29 -0400
commit707263542e571c9906549e196728ad39ecc0ca84 (patch)
tree2db731b1ed9f8eeb9b78d1d0a5cd41f542461600 /src/backend/parser
parent7e389f73d1556fb21487cd28fe56cba1a91126e6 (diff)
downloadpostgresql-707263542e571c9906549e196728ad39ecc0ca84.tar.gz
postgresql-707263542e571c9906549e196728ad39ecc0ca84.zip
Fix parse location tracking for lists that can be empty.
The previous coding of the YYLLOC_DEFAULT macro behaved strangely for empty productions, assigning the previous nonterminal's location as the parse location of the result. The usefulness of that was (at best) debatable already, but the real problem is that in list-generating nonterminals like OptFooList: /* EMPTY */ { ... } | OptFooList Foo { ... } ; the initially-identified location would get copied up, so that even a nonempty list would be given a bogus parse location. Document how to work around that, and do so for OptSchemaEltList, so that the error condition just added for CREATE SCHEMA IF NOT EXISTS produces a sane error cursor. So far as I can tell, there are currently no other cases where the situation arises, so we don't need other instances of this coding yet.
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y34
1 files changed, 29 insertions, 5 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7feadeac169..e4ff76e66e0 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -67,16 +67,34 @@
#include "utils/xml.h"
-/* Location tracking support --- simpler than bison's default */
+/*
+ * Location tracking support --- simpler than bison's default, since we only
+ * want to track the start position not the end position of each nonterminal.
+ */
#define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \
- if (N) \
+ if ((N) > 0) \
(Current) = (Rhs)[1]; \
else \
- (Current) = (Rhs)[0]; \
+ (Current) = (-1); \
} while (0)
/*
+ * The above macro assigns -1 (unknown) as the parse location of any
+ * nonterminal that was reduced from an empty rule. This is problematic
+ * for nonterminals defined like
+ * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ;
+ * because we'll set -1 as the location during the first reduction and then
+ * copy it during each subsequent reduction, leaving us with -1 for the
+ * location even when the list is not empty. To fix that, do this in the
+ * action for the nonempty rule(s):
+ * if (@$ < 0) @$ = @2;
+ * (Although we have many nonterminals that follow this pattern, we only
+ * bother with fixing @$ like this when the nonterminal's parse location
+ * is actually referenced in some rule.)
+ */
+
+/*
* Bison doesn't allocate anything that needs to live across parser calls,
* so we can easily have it use palloc instead of malloc. This prevents
* memory leaks if we error out during parsing. Note this only works with
@@ -1223,8 +1241,14 @@ OptSchemaName:
;
OptSchemaEltList:
- OptSchemaEltList schema_stmt { $$ = lappend($1, $2); }
- | /* EMPTY */ { $$ = NIL; }
+ OptSchemaEltList schema_stmt
+ {
+ if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
+ @$ = @2;
+ $$ = lappend($1, $2);
+ }
+ | /* EMPTY */
+ { $$ = NIL; }
;
/*