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:67: 'case' : constant expression required
|
||||
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!
|
||||
@ -189,6 +192,77 @@ ERROR: node is still EOpNull!
|
||||
0:86 tangent (highp float)
|
||||
0:86 'x' (smooth in highp float)
|
||||
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:? 'c' (uniform mediump int)
|
||||
0:? 'd' (uniform mediump int)
|
||||
|
@ -87,4 +87,30 @@ void main()
|
||||
}
|
||||
|
||||
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
|
||||
// going. However, if it is not updated, it can be a version behind.
|
||||
|
||||
#define GLSLANG_REVISION "24349"
|
||||
#define GLSLANG_DATE "2013/12/04 13:41:33"
|
||||
#define GLSLANG_REVISION "24353"
|
||||
#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) :
|
||||
intermediate(interm), symbolTable(symt), infoSink(is), language(L),
|
||||
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),
|
||||
numErrors(0), parsingBuiltins(pb), afterEOF(false),
|
||||
anyIndexLimits(false)
|
||||
@ -813,6 +813,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(TSourceLoc loc, TFunct
|
||||
}
|
||||
intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
|
||||
loopNestingLevel = 0;
|
||||
controlFlowNestingLevel = 0;
|
||||
|
||||
return paramNodes;
|
||||
}
|
||||
|
@ -219,7 +219,9 @@ public:
|
||||
struct TPragma contextPragma;
|
||||
int loopNestingLevel; // 0 if outside all loops
|
||||
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<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
|
||||
bool functionReturnsValue; // true if a non-void function has a return
|
||||
const TString* blockName;
|
||||
|
@ -2148,8 +2148,14 @@ simple_statement
|
||||
|
||||
compound_statement
|
||||
: LEFT_BRACE RIGHT_BRACE { $$ = 0; }
|
||||
| LEFT_BRACE { parseContext.symbolTable.push(); }
|
||||
statement_list { parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); }
|
||||
| LEFT_BRACE {
|
||||
parseContext.symbolTable.push();
|
||||
++parseContext.controlFlowNestingLevel;
|
||||
}
|
||||
statement_list {
|
||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||
--parseContext.controlFlowNestingLevel;
|
||||
}
|
||||
RIGHT_BRACE {
|
||||
if ($3 != 0)
|
||||
$3->setOperator(EOpSequence);
|
||||
@ -2164,7 +2170,15 @@ statement_no_new_scope
|
||||
|
||||
statement_scoped
|
||||
: 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
|
||||
// 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 {
|
||||
// start new switch sequence on the switch stack
|
||||
parseContext.switchSequenceStack.push_back(new TIntermSequence);
|
||||
parseContext.switchLevel.push_back(parseContext.controlFlowNestingLevel);
|
||||
}
|
||||
LEFT_BRACE switch_statement_list RIGHT_BRACE {
|
||||
$$ = parseContext.addSwitch($1.loc, $3, $7);
|
||||
delete parseContext.switchSequenceStack.back();
|
||||
parseContext.switchSequenceStack.pop_back();
|
||||
parseContext.switchLevel.pop_back();
|
||||
}
|
||||
;
|
||||
|
||||
@ -2261,6 +2277,10 @@ switch_statement_list
|
||||
|
||||
case_label
|
||||
: 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.integerCheck($2, "case");
|
||||
$$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc);
|
||||
@ -2276,13 +2296,19 @@ iteration_statement
|
||||
parseContext.error($1.loc, "while loops not available", "limitation", "");
|
||||
parseContext.symbolTable.push();
|
||||
++parseContext.loopNestingLevel;
|
||||
++parseContext.controlFlowNestingLevel;
|
||||
}
|
||||
condition RIGHT_PAREN statement_no_new_scope {
|
||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||
$$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc);
|
||||
--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)
|
||||
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.loopNestingLevel;
|
||||
--parseContext.controlFlowNestingLevel;
|
||||
}
|
||||
| FOR LEFT_PAREN {
|
||||
parseContext.symbolTable.push();
|
||||
++parseContext.loopNestingLevel;
|
||||
++parseContext.controlFlowNestingLevel;
|
||||
}
|
||||
for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
|
||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||
@ -2304,6 +2332,7 @@ iteration_statement
|
||||
$$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
|
||||
$$->getAsAggregate()->setOperator(EOpSequence);
|
||||
--parseContext.loopNestingLevel;
|
||||
--parseContext.controlFlowNestingLevel;
|
||||
}
|
||||
;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user