glsl/glcpp: Fix for macros that expand to include "defined" operators
authorCarl Worth <cworth@cworth.org>
Wed, 2 Jul 2014 19:52:33 +0000 (12:52 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 7 Aug 2014 23:08:29 +0000 (16:08 -0700)
commit218e878b5491210dd0bc27a9171f88fa23278f4e
treeba848c26d0ae7f1c7dfa9f615205fa9b04322e28
parenta48ff781c1cac00ad432edf88fafa44e667fa90f
glsl/glcpp: Fix for macros that expand to include "defined" operators

Prior to this commit, the following snippet would trigger an error in glcpp:

#define FOO defined BAR
#if FOO
        #endif

The problem was that support for the "defined" operator was implemented within
the grammar, (where the parser was parsing the tokens of the condition
itself). But what is required is to interpret the "defined" operator that
results after macro expansion is performed.

I could not find any fix for this case by modifying the grammar alone. The
difficulty is that outside of the grammar we already have a recursive function
that performs macro expansion (_glcpp_parser_expand_token_list) and that
function itself must be augmented to be made aware of the semantics of the
"defined" operator.

The reason we can't simply handle "defined" outside of the recursive expansion
function is that not only must we scan for any "defined" operators in the
original condition (before any macro expansion occurs); but at each level of
the recursive expansion, we must again scan the list of tokens resulting from
expansion and handle "defined" before entering the next level of recursion to
further expand macros.

And of course, all of this is context dependent. The evaluation of "defined"
operators must only happen when we are handling preprocessor conditionals,
(#if and #elif) and not when performing any other expansion, (such as in the
main body).

To implement this, we add a new "mode" parameter to all of the expansion
functions to specify whether resulting DEFINED tokens should be evaluated or
ignored.

One side benefit of this change is that an ugly wart in the grammar is
removed. We previously had "conditional_token" and "conditional_tokens"
productions that were basically copies of "pp_token" and "pp_tokens" but with
added productions for the various forms of DEFINED operators. With the new
code here, those ugly copy-and-paste productions are eliminated from the
grammar.

A new "make check" test is added to stress-test the code here.

This commit fixes the following Khronos GLES3 CTS tests:

conditional_inclusion.basic_2_vertex
conditional_inclusion.basic_2_fragment

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/glcpp/glcpp-parse.y
src/glsl/glcpp/tests/142-defined-within-macro.c [new file with mode: 0644]
src/glsl/glcpp/tests/142-defined-within-macro.c.expected [new file with mode: 0644]