Preprocessor: Add short-circuit logic so ES errors are not given on undefined variables that are short circuited in && and || preprocessing expressions.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24390 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
e28beee891
commit
7fc3669195
@ -11,11 +11,22 @@ ERROR: 0:94: 'macro expansion' : unexpected '#' foobar
|
||||
ERROR: 0:95: 'preprocessor evaluation' : bad expression
|
||||
ERROR: 0:100: 'preprocessor evaluation' : bad expression
|
||||
ERROR: 0:100: '#if' : unexpected tokens following directive
|
||||
ERROR: 0:103: 'macro expansion' : unexpected '#' foobar
|
||||
ERROR: 0:103: 'preprocessor evaluation' : undefined macro in expression
|
||||
ERROR: 0:103: '#if' : unexpected tokens following directive
|
||||
ERROR: 0:104: '' : missing #endif
|
||||
ERROR: 16 compilation errors. No code generated.
|
||||
ERROR: 0:102: 'macro expansion' : unexpected '#' foobar
|
||||
ERROR: 0:102: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile endif
|
||||
ERROR: 0:108: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF
|
||||
ERROR: 0:111: '#error' : good 0
|
||||
ERROR: 0:115: '#error' : good 1
|
||||
ERROR: 0:120: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF
|
||||
ERROR: 0:123: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF
|
||||
ERROR: 0:129: '#error' : good 1
|
||||
ERROR: 0:133: '#error' : good 3
|
||||
ERROR: 0:139: '#error' : good 4
|
||||
ERROR: 0:144: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF
|
||||
ERROR: 0:153: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF
|
||||
ERROR: 0:156: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF2
|
||||
ERROR: 0:159: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF2
|
||||
ERROR: 0:10002: '' : missing #endif
|
||||
ERROR: 27 compilation errors. No code generated.
|
||||
|
||||
|
||||
ERROR: node is still EOpNull!
|
||||
|
@ -99,6 +99,66 @@ float c = foobar(1.1, 2.2
|
||||
#if foobar(1.1, 2.2
|
||||
)
|
||||
#if foobar(1.1, 2.2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define VAL0 0
|
||||
#define VAL1 1
|
||||
|
||||
#if UNDEF
|
||||
#error bad 0
|
||||
#else
|
||||
#error good 0
|
||||
#endif
|
||||
|
||||
#if VAL1 || UNDEF
|
||||
#error good 1
|
||||
#else
|
||||
#error bad 1
|
||||
#endif
|
||||
|
||||
#if VAL1 && UNDEF // UNDEF ERROR
|
||||
#endif
|
||||
|
||||
#if VAL0 || UNDEF // UNDEF ERROR
|
||||
#endif
|
||||
|
||||
#if VAL0 && UNDEF
|
||||
#error bad 2
|
||||
#else
|
||||
#error good 1
|
||||
#endif
|
||||
|
||||
#if VAL1 || (VAL1 && UNDEF)
|
||||
#error good 3
|
||||
#else
|
||||
#error bad 3
|
||||
#endif
|
||||
|
||||
#if VAL1 && (VAL1 || UNDEF)
|
||||
#error good 4
|
||||
#else
|
||||
#error bad 4
|
||||
#endif
|
||||
|
||||
#if VAL1 < VAL1 || VAL1 > VAL1 || UNDEF // UNDEF ERROR
|
||||
#endif
|
||||
|
||||
#if VAL1 < VAL1 || VAL1 > VAL1 && UNDEF
|
||||
#endif
|
||||
|
||||
#if VAL1 || UNDEF && UNDEF2
|
||||
#endif
|
||||
|
||||
#if VAL0 || UNDEF && UNDEF2 // UNDEF ERROR
|
||||
#endif
|
||||
|
||||
#if (VAL1 || UNDEF) && UNDEF2 // UNDEF2 ERROR
|
||||
#endif
|
||||
|
||||
#if (VAL0 && UNDEF) || UNDEF2 // UNDEF2 ERROR
|
||||
#endif
|
||||
|
||||
#line 10000
|
||||
#if 0
|
||||
// ERROR, EOF
|
@ -9,5 +9,5 @@
|
||||
// source have to figure out how to create revision.h just to get a build
|
||||
// going. However, if it is not updated, it can be a version behind.
|
||||
|
||||
#define GLSLANG_REVISION "24378"
|
||||
#define GLSLANG_DATE "2013/12/05 14:51:40"
|
||||
#define GLSLANG_REVISION "24387"
|
||||
#define GLSLANG_DATE "2013/12/06 09:13:47"
|
||||
|
@ -408,7 +408,7 @@ namespace {
|
||||
|
||||
};
|
||||
|
||||
struct Tbinops {
|
||||
struct {
|
||||
int token, precedence, (*op)(int, int);
|
||||
} binop[] = {
|
||||
{ CPP_OR_OP, LOGOR, op_logor },
|
||||
@ -431,7 +431,7 @@ struct Tbinops {
|
||||
{ '%', MUL, op_mod },
|
||||
};
|
||||
|
||||
struct tunops {
|
||||
struct {
|
||||
int token, (*op)(int);
|
||||
} unop[] = {
|
||||
{ '+', op_pos },
|
||||
@ -440,13 +440,10 @@ struct tunops {
|
||||
{ '!', op_not },
|
||||
};
|
||||
|
||||
#define ALEN(A) (sizeof(A)/sizeof(A[0]))
|
||||
#define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0]))
|
||||
|
||||
int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* ppToken)
|
||||
int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
|
||||
{
|
||||
int i, val;
|
||||
Symbol *s;
|
||||
|
||||
if (token == CPP_IDENTIFIER) {
|
||||
if (ppToken->atom == definedAtom) {
|
||||
bool needclose = 0;
|
||||
@ -462,6 +459,7 @@ int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* p
|
||||
|
||||
return token;
|
||||
}
|
||||
Symbol* s;
|
||||
res = (s = LookUpSymbol(ppToken->atom)) ? !s->mac.undef : 0;
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
if (needclose) {
|
||||
@ -484,19 +482,18 @@ int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* p
|
||||
return token;
|
||||
} else {
|
||||
if (macroReturn == -1) {
|
||||
if (parseContext.profile == EEsProfile) {
|
||||
if (! shortCircuit && parseContext.profile == EEsProfile) {
|
||||
const char* message = "undefined macro in expression not allowed in es profile";
|
||||
const char* name = GetAtomString(ppToken->atom);
|
||||
if (parseContext.messages & EShMsgRelaxedErrors)
|
||||
parseContext.warn(ppToken->loc, "undefined macro in expression not allowed in es profile", "preprocessor evaluation", "");
|
||||
else {
|
||||
parseContext.error(ppToken->loc, "undefined macro in expression", "preprocessor evaluation", "");
|
||||
|
||||
err = true;
|
||||
}
|
||||
parseContext.warn(ppToken->loc, message, "preprocessor evaluation", name);
|
||||
else
|
||||
parseContext.error(ppToken->loc, message, "preprocessor evaluation", name);
|
||||
}
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
|
||||
return eval(token, precedence, res, err, ppToken);
|
||||
return eval(token, precedence, shortCircuit, res, err, ppToken);
|
||||
}
|
||||
}
|
||||
} else if (token == CPP_INTCONSTANT) {
|
||||
@ -504,7 +501,7 @@ int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* p
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
} else if (token == '(') {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = eval(token, MIN_PRECEDENCE, res, err, ppToken);
|
||||
token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken);
|
||||
if (! err) {
|
||||
if (token != ')') {
|
||||
parseContext.error(ppToken->loc, "expected ')'", "preprocessor evaluation", "");
|
||||
@ -516,14 +513,15 @@ int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* p
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
}
|
||||
} else {
|
||||
for (i = ALEN(unop) - 1; i >= 0; i--) {
|
||||
if (unop[i].token == token)
|
||||
int op;
|
||||
for (op = NUM_ELEMENTS(unop) - 1; op >= 0; op--) {
|
||||
if (unop[op].token == token)
|
||||
break;
|
||||
}
|
||||
if (i >= 0) {
|
||||
if (op >= 0) {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = eval(token, UNARY, res, err, ppToken);
|
||||
res = unop[i].op(res);
|
||||
token = eval(token, UNARY, shortCircuit, res, err, ppToken);
|
||||
res = unop[op].op(res);
|
||||
} else {
|
||||
parseContext.error(ppToken->loc, "bad expression", "preprocessor evaluation", "");
|
||||
err = true;
|
||||
@ -535,16 +533,26 @@ int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* p
|
||||
while (! err) {
|
||||
if (token == ')' || token == '\n')
|
||||
break;
|
||||
for (i = ALEN(binop) - 1; i >= 0; i--) {
|
||||
if (binop[i].token == token)
|
||||
int op;
|
||||
for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) {
|
||||
if (binop[op].token == token)
|
||||
break;
|
||||
}
|
||||
if (i < 0 || binop[i].precedence <= precedence)
|
||||
if (op < 0 || binop[op].precedence <= precedence)
|
||||
break;
|
||||
val = res;
|
||||
int leftSide = res;
|
||||
|
||||
// Setup short-circuiting, needed for ES, unless already in a short circuit.
|
||||
// (Once in a short-circuit, can't turn off again, until that whole subexpression is done.
|
||||
if (! shortCircuit) {
|
||||
if ((token == CPP_OR_OP && leftSide == 1) ||
|
||||
(token == CPP_AND_OP && leftSide == 0))
|
||||
shortCircuit = true;
|
||||
}
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = eval(token, binop[i].precedence, res, err, ppToken);
|
||||
res = binop[i].op(val, res);
|
||||
token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken);
|
||||
res = binop[op].op(leftSide, res);
|
||||
}
|
||||
|
||||
return token;
|
||||
@ -563,7 +571,7 @@ int TPpContext::CPPif(TPpToken* ppToken)
|
||||
}
|
||||
int res = 0;
|
||||
bool err = false;
|
||||
token = eval(token, MIN_PRECEDENCE, res, err, ppToken);
|
||||
token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken);
|
||||
token = extraTokenCheck(ifAtom, ppToken, token);
|
||||
if (!res && !err)
|
||||
token = CPPelse(1, ppToken);
|
||||
@ -612,7 +620,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
|
||||
|
||||
int lineRes = 0;
|
||||
bool lineErr = false;
|
||||
token = eval(token, MIN_PRECEDENCE, lineRes, lineErr, ppToken);
|
||||
token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
|
||||
if (! lineErr) {
|
||||
if (token == '\n')
|
||||
++lineRes;
|
||||
@ -620,7 +628,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
|
||||
if (token != '\n') {
|
||||
int fileRes = 0;
|
||||
bool fileErr = false;
|
||||
token = eval(token, MIN_PRECEDENCE, fileRes, fileErr, ppToken);
|
||||
token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken);
|
||||
if (! fileErr)
|
||||
parseContext.setCurrentString(fileRes);
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ protected:
|
||||
int CPPundef(TPpToken * ppToken);
|
||||
int CPPelse(int matchelse, TPpToken * ppToken);
|
||||
int extraTokenCheck(int atom, TPpToken* ppToken, int token);
|
||||
int eval(int token, int precedence, int& res, bool& err, TPpToken * ppToken);
|
||||
int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
|
||||
int CPPif (TPpToken * ppToken);
|
||||
int CPPifdef(int defined, TPpToken * ppToken);
|
||||
int CPPline(TPpToken * ppToken);
|
||||
|
Loading…
x
Reference in New Issue
Block a user