Track the flow-control (and {}) nesting level to prevent case statements from being a different nesting level than their switch statement.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24355 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
3a53006e0e
commit
7fd9e1189b
@ -8,7 +8,10 @@ ERROR: 0:63: 'case' : duplicated value
|
|||||||
ERROR: 0:65: 'case' : scalar integer expression required
|
ERROR: 0:65: 'case' : scalar integer expression required
|
||||||
ERROR: 0:67: 'case' : constant expression required
|
ERROR: 0:67: 'case' : constant expression required
|
||||||
ERROR: 0:89: '' : break statement only allowed in switch and loops
|
ERROR: 0:89: '' : break statement only allowed in switch and loops
|
||||||
ERROR: 9 compilation errors. No code generated.
|
ERROR: 0:99: 'case' : cannot be nested inside control flow
|
||||||
|
ERROR: 0:104: 'case' : cannot be nested inside control flow
|
||||||
|
ERROR: 0:108: 'case' : cannot be nested inside control flow
|
||||||
|
ERROR: 12 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
ERROR: node is still EOpNull!
|
ERROR: node is still EOpNull!
|
||||||
@ -189,6 +192,77 @@ ERROR: node is still EOpNull!
|
|||||||
0:86 tangent (highp float)
|
0:86 tangent (highp float)
|
||||||
0:86 'x' (smooth in highp float)
|
0:86 'x' (smooth in highp float)
|
||||||
0:89 Branch: Break
|
0:89 Branch: Break
|
||||||
|
0:91 switch
|
||||||
|
0:91 condition
|
||||||
|
0:91 'c' (uniform mediump int)
|
||||||
|
0:91 body
|
||||||
|
0:91 Sequence
|
||||||
|
0:92 case: with expression
|
||||||
|
0:92 Constant:
|
||||||
|
0:92 1 (const int)
|
||||||
|
0:? Sequence
|
||||||
|
0:93 move second child to first child (highp float)
|
||||||
|
0:93 'f' (highp float)
|
||||||
|
0:93 sine (highp float)
|
||||||
|
0:93 'x' (smooth in highp float)
|
||||||
|
0:94 Branch: Break
|
||||||
|
0:95 case: with expression
|
||||||
|
0:95 Constant:
|
||||||
|
0:95 2 (const int)
|
||||||
|
0:? Sequence
|
||||||
|
0:96 switch
|
||||||
|
0:96 condition
|
||||||
|
0:96 'd' (uniform mediump int)
|
||||||
|
0:96 body
|
||||||
|
0:96 Sequence
|
||||||
|
0:97 case: with expression
|
||||||
|
0:97 Constant:
|
||||||
|
0:97 1 (const int)
|
||||||
|
0:99 case: with expression
|
||||||
|
0:99 Constant:
|
||||||
|
0:99 4 (const int)
|
||||||
|
0:104 case: with expression
|
||||||
|
0:104 Constant:
|
||||||
|
0:104 2 (const int)
|
||||||
|
0:? Sequence
|
||||||
|
0:? Sequence
|
||||||
|
0:100 Branch: Break
|
||||||
|
0:102 move second child to first child (highp float)
|
||||||
|
0:102 'f' (highp float)
|
||||||
|
0:102 component-wise multiply (highp float)
|
||||||
|
0:102 component-wise multiply (highp float)
|
||||||
|
0:102 'x' (smooth in highp float)
|
||||||
|
0:102 'x' (smooth in highp float)
|
||||||
|
0:102 'x' (smooth in highp float)
|
||||||
|
0:103 Test condition and select (void)
|
||||||
|
0:103 Condition
|
||||||
|
0:103 Compare Less Than (bool)
|
||||||
|
0:103 'c' (uniform mediump int)
|
||||||
|
0:103 'd' (uniform mediump int)
|
||||||
|
0:103 true case
|
||||||
|
0:? Sequence
|
||||||
|
0:105 move second child to first child (highp float)
|
||||||
|
0:105 'f' (highp float)
|
||||||
|
0:105 component-wise multiply (highp float)
|
||||||
|
0:105 'x' (smooth in highp float)
|
||||||
|
0:105 'x' (smooth in highp float)
|
||||||
|
0:107 Test condition and select (void)
|
||||||
|
0:107 Condition
|
||||||
|
0:107 Compare Less Than (bool)
|
||||||
|
0:107 'd' (uniform mediump int)
|
||||||
|
0:107 'c' (uniform mediump int)
|
||||||
|
0:107 true case
|
||||||
|
0:108 case: with expression
|
||||||
|
0:108 Constant:
|
||||||
|
0:108 3 (const int)
|
||||||
|
0:109 Branch: Break
|
||||||
|
0:111 Branch: Break
|
||||||
|
0:112 default:
|
||||||
|
0:? Sequence
|
||||||
|
0:113 move second child to first child (highp float)
|
||||||
|
0:113 'f' (highp float)
|
||||||
|
0:113 tangent (highp float)
|
||||||
|
0:113 'x' (smooth in highp float)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'c' (uniform mediump int)
|
0:? 'c' (uniform mediump int)
|
||||||
0:? 'd' (uniform mediump int)
|
0:? 'd' (uniform mediump int)
|
||||||
|
@ -87,4 +87,30 @@ void main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
break; // ERROR
|
break; // ERROR
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 1:
|
||||||
|
f = sin(x);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (d) {
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
case 4: // ERROR
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
f = x * x * x;
|
||||||
|
if (c < d) {
|
||||||
|
case 2: // ERROR
|
||||||
|
f = x * x;
|
||||||
|
}
|
||||||
|
if (d < c)
|
||||||
|
case 3: // ERROR
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
f = tan(x);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,5 @@
|
|||||||
// source have to figure out how to create revision.h just to get a build
|
// 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.
|
// going. However, if it is not updated, it can be a version behind.
|
||||||
|
|
||||||
#define GLSLANG_REVISION "24349"
|
#define GLSLANG_REVISION "24353"
|
||||||
#define GLSLANG_DATE "2013/12/04 13:41:33"
|
#define GLSLANG_DATE "2013/12/04 14:01:32"
|
||||||
|
@ -51,7 +51,7 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb,
|
|||||||
bool fc, EShMessages m) :
|
bool fc, EShMessages m) :
|
||||||
intermediate(interm), symbolTable(symt), infoSink(is), language(L),
|
intermediate(interm), symbolTable(symt), infoSink(is), language(L),
|
||||||
version(v), profile(p), forwardCompatible(fc), messages(m),
|
version(v), profile(p), forwardCompatible(fc), messages(m),
|
||||||
contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0),
|
contextPragma(true, false), loopNestingLevel(0), controlFlowNestingLevel(0), structNestingLevel(0),
|
||||||
tokensBeforeEOF(false), limits(resources.limits), currentScanner(0),
|
tokensBeforeEOF(false), limits(resources.limits), currentScanner(0),
|
||||||
numErrors(0), parsingBuiltins(pb), afterEOF(false),
|
numErrors(0), parsingBuiltins(pb), afterEOF(false),
|
||||||
anyIndexLimits(false)
|
anyIndexLimits(false)
|
||||||
@ -813,6 +813,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(TSourceLoc loc, TFunct
|
|||||||
}
|
}
|
||||||
intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
|
intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
|
||||||
loopNestingLevel = 0;
|
loopNestingLevel = 0;
|
||||||
|
controlFlowNestingLevel = 0;
|
||||||
|
|
||||||
return paramNodes;
|
return paramNodes;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,9 @@ public:
|
|||||||
struct TPragma contextPragma;
|
struct TPragma contextPragma;
|
||||||
int loopNestingLevel; // 0 if outside all loops
|
int loopNestingLevel; // 0 if outside all loops
|
||||||
int structNestingLevel; // 0 if outside blocks and structures
|
int structNestingLevel; // 0 if outside blocks and structures
|
||||||
|
int controlFlowNestingLevel; // 0 if outside all flow control or compound statements; also counts compound statements
|
||||||
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
|
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
|
||||||
|
TList<int> switchLevel; // the controlFlowNestingLevel the current switch statement is at, which must match the level of its case statements
|
||||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
||||||
bool functionReturnsValue; // true if a non-void function has a return
|
bool functionReturnsValue; // true if a non-void function has a return
|
||||||
const TString* blockName;
|
const TString* blockName;
|
||||||
|
@ -2148,8 +2148,14 @@ simple_statement
|
|||||||
|
|
||||||
compound_statement
|
compound_statement
|
||||||
: LEFT_BRACE RIGHT_BRACE { $$ = 0; }
|
: LEFT_BRACE RIGHT_BRACE { $$ = 0; }
|
||||||
| LEFT_BRACE { parseContext.symbolTable.push(); }
|
| LEFT_BRACE {
|
||||||
statement_list { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); }
|
parseContext.symbolTable.push();
|
||||||
|
++parseContext.controlFlowNestingLevel;
|
||||||
|
}
|
||||||
|
statement_list {
|
||||||
|
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||||
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
}
|
||||||
RIGHT_BRACE {
|
RIGHT_BRACE {
|
||||||
if ($3 != 0)
|
if ($3 != 0)
|
||||||
$3->setOperator(EOpSequence);
|
$3->setOperator(EOpSequence);
|
||||||
@ -2164,7 +2170,15 @@ statement_no_new_scope
|
|||||||
|
|
||||||
statement_scoped
|
statement_scoped
|
||||||
: compound_statement { $$ = $1; }
|
: compound_statement { $$ = $1; }
|
||||||
| { parseContext.symbolTable.push(); } simple_statement { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); } { $$ = $2; }
|
| {
|
||||||
|
parseContext.symbolTable.push();
|
||||||
|
++parseContext.controlFlowNestingLevel;
|
||||||
|
}
|
||||||
|
simple_statement {
|
||||||
|
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||||
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
|
||||||
compound_statement_no_new_scope
|
compound_statement_no_new_scope
|
||||||
// Statement that doesn't create a new scope, for selection_statement, iteration_statement
|
// Statement that doesn't create a new scope, for selection_statement, iteration_statement
|
||||||
@ -2242,11 +2256,13 @@ switch_statement
|
|||||||
: SWITCH LEFT_PAREN expression RIGHT_PAREN {
|
: SWITCH LEFT_PAREN expression RIGHT_PAREN {
|
||||||
// start new switch sequence on the switch stack
|
// start new switch sequence on the switch stack
|
||||||
parseContext.switchSequenceStack.push_back(new TIntermSequence);
|
parseContext.switchSequenceStack.push_back(new TIntermSequence);
|
||||||
|
parseContext.switchLevel.push_back(parseContext.controlFlowNestingLevel);
|
||||||
}
|
}
|
||||||
LEFT_BRACE switch_statement_list RIGHT_BRACE {
|
LEFT_BRACE switch_statement_list RIGHT_BRACE {
|
||||||
$$ = parseContext.addSwitch($1.loc, $3, $7);
|
$$ = parseContext.addSwitch($1.loc, $3, $7);
|
||||||
delete parseContext.switchSequenceStack.back();
|
delete parseContext.switchSequenceStack.back();
|
||||||
parseContext.switchSequenceStack.pop_back();
|
parseContext.switchSequenceStack.pop_back();
|
||||||
|
parseContext.switchLevel.pop_back();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -2261,6 +2277,10 @@ switch_statement_list
|
|||||||
|
|
||||||
case_label
|
case_label
|
||||||
: CASE expression COLON {
|
: CASE expression COLON {
|
||||||
|
if (parseContext.switchLevel.size() == 0)
|
||||||
|
parseContext.error($1.loc, "cannot appear outside switch statement", "case", "");
|
||||||
|
else if (parseContext.switchLevel.back() != parseContext.controlFlowNestingLevel)
|
||||||
|
parseContext.error($1.loc, "cannot be nested inside control flow", "case", "");
|
||||||
parseContext.constantValueCheck($2, "case");
|
parseContext.constantValueCheck($2, "case");
|
||||||
parseContext.integerCheck($2, "case");
|
parseContext.integerCheck($2, "case");
|
||||||
$$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc);
|
$$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc);
|
||||||
@ -2276,13 +2296,19 @@ iteration_statement
|
|||||||
parseContext.error($1.loc, "while loops not available", "limitation", "");
|
parseContext.error($1.loc, "while loops not available", "limitation", "");
|
||||||
parseContext.symbolTable.push();
|
parseContext.symbolTable.push();
|
||||||
++parseContext.loopNestingLevel;
|
++parseContext.loopNestingLevel;
|
||||||
|
++parseContext.controlFlowNestingLevel;
|
||||||
}
|
}
|
||||||
condition RIGHT_PAREN statement_no_new_scope {
|
condition RIGHT_PAREN statement_no_new_scope {
|
||||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||||
$$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc);
|
$$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc);
|
||||||
--parseContext.loopNestingLevel;
|
--parseContext.loopNestingLevel;
|
||||||
|
--parseContext.controlFlowNestingLevel;
|
||||||
}
|
}
|
||||||
| DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
|
| DO {
|
||||||
|
++parseContext.loopNestingLevel;
|
||||||
|
++parseContext.controlFlowNestingLevel;
|
||||||
|
}
|
||||||
|
statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
|
||||||
if (! parseContext.limits.whileLoops)
|
if (! parseContext.limits.whileLoops)
|
||||||
parseContext.error($1.loc, "do-while loops not available", "limitation", "");
|
parseContext.error($1.loc, "do-while loops not available", "limitation", "");
|
||||||
|
|
||||||
@ -2290,10 +2316,12 @@ iteration_statement
|
|||||||
|
|
||||||
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
|
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
|
||||||
--parseContext.loopNestingLevel;
|
--parseContext.loopNestingLevel;
|
||||||
|
--parseContext.controlFlowNestingLevel;
|
||||||
}
|
}
|
||||||
| FOR LEFT_PAREN {
|
| FOR LEFT_PAREN {
|
||||||
parseContext.symbolTable.push();
|
parseContext.symbolTable.push();
|
||||||
++parseContext.loopNestingLevel;
|
++parseContext.loopNestingLevel;
|
||||||
|
++parseContext.controlFlowNestingLevel;
|
||||||
}
|
}
|
||||||
for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
|
for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
|
||||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||||
@ -2304,6 +2332,7 @@ iteration_statement
|
|||||||
$$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
|
$$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
|
||||||
$$->getAsAggregate()->setOperator(EOpSequence);
|
$$->getAsAggregate()->setOperator(EOpSequence);
|
||||||
--parseContext.loopNestingLevel;
|
--parseContext.loopNestingLevel;
|
||||||
|
--parseContext.controlFlowNestingLevel;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user