glsl/glcpp: Emit error for duplicate parameter name in function-like macro
authorCarl Worth <cworth@cworth.org>
Wed, 25 Jun 2014 20:41:47 +0000 (13:41 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 29 Jul 2014 22:11:50 +0000 (15:11 -0700)
This will emit an error for something like:

#define FOO(x,x) ...

Obviously, it's not a legal thing to do, and it's easy to check.

Add a "make check" test for this as well.

This fixes the following Khronos GLES3 CTS tests:

invalid_function_definitions.unique_param_name_vertex
invalid_function_definitions.unique_param_name_fragment

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/glsl/glcpp/glcpp-parse.y
src/glsl/glcpp/tests/135-duplicate-parameter.c [new file with mode: 0644]
src/glsl/glcpp/tests/135-duplicate-parameter.c.expected [new file with mode: 0644]

index f75834514f287039acdc0a74f07dcf5662b8376f..38d84046d5725b268a554ea104ec5733ac3431d4 100644 (file)
@@ -57,6 +57,9 @@ _string_list_append_item (string_list_t *list, const char *str);
 static int
 _string_list_contains (string_list_t *list, const char *member, int *index);
 
+static const char *
+_string_list_has_duplicate (string_list_t *list);
+
 static int
 _string_list_length (string_list_t *list);
 
@@ -794,6 +797,25 @@ _string_list_contains (string_list_t *list, const char *member, int *index)
        return 0;
 }
 
+/* Return duplicate string in list (if any), NULL otherwise. */
+const char *
+_string_list_has_duplicate (string_list_t *list)
+{
+       string_node_t *node, *dup;
+
+       if (list == NULL)
+               return NULL;
+
+       for (node = list->head; node; node = node->next) {
+               for (dup = node->next; dup; dup = dup->next) {
+                       if (strcmp (node->str, dup->str) == 0)
+                               return node->str;
+               }
+       }
+
+       return NULL;
+}
+
 int
 _string_list_length (string_list_t *list)
 {
@@ -1980,9 +2002,16 @@ _define_function_macro (glcpp_parser_t *parser,
                        token_list_t *replacements)
 {
        macro_t *macro, *previous;
+       const char *dup;
 
        _check_for_reserved_macro_name(parser, loc, identifier);
 
+        /* Check for any duplicate parameter names. */
+       if ((dup = _string_list_has_duplicate (parameters)) != NULL) {
+               glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"",
+                            dup);
+       }
+
        macro = ralloc (parser, macro_t);
        ralloc_steal (macro, parameters);
        ralloc_steal (macro, replacements);
diff --git a/src/glsl/glcpp/tests/135-duplicate-parameter.c b/src/glsl/glcpp/tests/135-duplicate-parameter.c
new file mode 100644 (file)
index 0000000..fd96bd6
--- /dev/null
@@ -0,0 +1,2 @@
+#define FOO(a,a) which a?
+#define BAR(x,y,z,x) so very x
diff --git a/src/glsl/glcpp/tests/135-duplicate-parameter.c.expected b/src/glsl/glcpp/tests/135-duplicate-parameter.c.expected
new file mode 100644 (file)
index 0000000..bc1a334
--- /dev/null
@@ -0,0 +1,4 @@
+0:1(9): preprocessor error: Duplicate macro parameter "a"
+0:2(9): preprocessor error: Duplicate macro parameter "x"
+
+