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
6 changed files with 140 additions and 8 deletions
|
|
@ -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…
Add table
Add a link
Reference in a new issue