From f0fce80aa79455eb8135fb4972d5ef812401102c Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Wed, 8 Oct 2014 21:29:29 +0000 Subject: [PATCH] Do qualifier-based checking independent of declaring a variable. Bug 11903. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@28502 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/100.frag | 4 ++- Test/300.frag | 4 +++ Test/baseResults/100.frag.out | 23 +++++++++------ Test/baseResults/300.frag.out | 11 ++++++-- Test/baseResults/300.vert.out | 2 +- Test/baseResults/430.vert.out | 3 +- Test/baseResults/specExamples.frag.out | 2 +- Test/baseResults/switch.frag.out | 4 +-- glslang/MachineIndependent/ParseHelper.cpp | 33 +++++++++++++--------- glslang/MachineIndependent/ParseHelper.h | 6 ++-- glslang/MachineIndependent/glslang.y | 13 ++++----- 11 files changed, 63 insertions(+), 42 deletions(-) diff --git a/Test/100.frag b/Test/100.frag index 672e969a7..ddf7ba0c6 100644 --- a/Test/100.frag +++ b/Test/100.frag @@ -46,7 +46,7 @@ float fa[]; // ERROR float f13; invariant f13; // ERROR struct S { int a; }; -invariant S; +invariant S; // ERROR, not an input or output invariant float fi; // ERROR varying vec4 av; invariant av; // okay in v100 @@ -194,4 +194,6 @@ void badswizzle() a.method(); // ERROR } +#pragma STDGL invariant(all) + uniform samplerExternalOES badExt; // syntax ERROR diff --git a/Test/300.frag b/Test/300.frag index 28e030aee..ff2da1fc0 100644 --- a/Test/300.frag +++ b/Test/300.frag @@ -153,5 +153,9 @@ layout(early_fragment_tests) in; // ERROR #error missing GL_FRAGMENT_PRECISION_HIGH #endif +invariant in; // ERROR +invariant in vec4; // ERROR +invariant in vec4 fooinv; // ERROR + float imageBuffer; // ERROR, reserved float uimage2DRect; // ERROR, reserved diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out index c3a0402fa..e4a5b7a16 100644 --- a/Test/baseResults/100.frag.out +++ b/Test/baseResults/100.frag.out @@ -23,26 +23,31 @@ ERROR: 0:38: 'array comparison' : not supported for this version or the enabled ERROR: 0:40: 'switch' : Reserved word. ERROR: 0:40: 'switch statements' : not supported for this version or the enabled extensions ERROR: 0:45: '' : array size required -ERROR: 0:47: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:47: 'invariant' : can only apply to an output, or to an input in a non-vertex stage -ERROR: 0:50: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:49: 'invariant' : can only apply to an output, or to an input in a non-vertex stage + +ERROR: 0:50: 'invariant' : can only apply to an output, or to an input in a non-vertex stage ERROR: 0:56: 'invariant' : not allowed in nested scope -ERROR: 0:56: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:56: 'invariant' : can only apply to an output, or to an input in a non-vertex stage ERROR: 0:57: 'invariant' : not allowed in nested scope -ERROR: 0:57: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:57: 'invariant' : can only apply to an output, or to an input in a non-vertex stage ERROR: 0:59: 'invariant' : not allowed in nested scope -ERROR: 0:59: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:59: 'invariant' : can only apply to an output, or to an input in a non-vertex stage -ERROR: 0:63: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:63: 'invariant' : can only apply to an output, or to an input in a non-vertex stage -ERROR: 0:64: 'invariant' : can only apply to an output or an input in a non-vertex stage +ERROR: 0:64: 'invariant' : can only apply to an output, or to an input in a non-vertex stage ERROR: 0:66: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: glob2D ERROR: 0:69: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: v2D ERROR: 0:71: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: vary2D +ERROR: 0:75: 'in for stage inputs' : not supported for this version or the enabled extensions +ERROR: 0:77: 'invariant' : can only apply to an output, or to an input in a non-vertex stage + ERROR: 0:75: 'g' : cannot use storage or interpolation qualifiers on structure members ERROR: 0:76: 'h' : cannot use storage or interpolation qualifiers on structure members ERROR: 0:77: 'i' : cannot use invariant qualifier on structure members @@ -77,8 +82,8 @@ ERROR: 0:192: '.' : cannot apply to an array: nothing ERROR: 0:193: '.length' : not supported for this version or the enabled extensions ERROR: 0:194: '.' : cannot apply to an array: method ERROR: 0:194: 'a' : can't use function syntax on variable -ERROR: 0:197: '' : syntax error -ERROR: 72 compilation errors. No code generated. +ERROR: 0:199: '' : syntax error +ERROR: 75 compilation errors. No code generated. Shader version: 100 diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out index 5e33407d7..cbaa7c484 100644 --- a/Test/baseResults/300.frag.out +++ b/Test/baseResults/300.frag.out @@ -36,9 +36,12 @@ ERROR: 0:129: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, ERROR: 0:129: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset] ERROR: 0:148: 'qualifier' : cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type) ERROR: 0:150: 'early_fragment_tests' : not supported for this version or the enabled extensions -ERROR: 0:156: 'imageBuffer' : Reserved word. -ERROR: 0:156: '' : syntax error -ERROR: 39 compilation errors. No code generated. +ERROR: 0:156: 'invariant' : can only apply to an output +ERROR: 0:157: 'invariant' : can only apply to an output +ERROR: 0:158: 'invariant' : can only apply to an output +ERROR: 0:160: 'imageBuffer' : Reserved word. +ERROR: 0:160: '' : syntax error +ERROR: 42 compilation errors. No code generated. Shader version: 300 @@ -390,6 +393,7 @@ ERROR: node is still EOpNull! 0:? 'colors' (out 4-element array of lowp 4-component vector of float) 0:? 'st1' (uniform structure{mediump int i, lowp sampler2D s}) 0:? 'st2' (uniform structure{mediump int i, lowp sampler2D s}) +0:? 'fooinv' (invariant smooth in lowp 4-component vector of float) Linked fragment stage: @@ -745,4 +749,5 @@ ERROR: node is still EOpNull! 0:? 'colors' (out 4-element array of lowp 4-component vector of float) 0:? 'st1' (uniform structure{mediump int i, lowp sampler2D s}) 0:? 'st2' (uniform structure{mediump int i, lowp sampler2D s}) +0:? 'fooinv' (invariant smooth in lowp 4-component vector of float) diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out index 87f630e9e..f27a399df 100644 --- a/Test/baseResults/300.vert.out +++ b/Test/baseResults/300.vert.out @@ -20,7 +20,7 @@ ERROR: 0:64: '' : array size required ERROR: 0:65: 'implicitly-sized array in a block' : not supported with this profile: es ERROR: 0:67: '' : array size required ERROR: 0:76: 'invariant' : cannot change qualification after use -ERROR: 0:78: 'invariant' : can only apply to an output: invIn +ERROR: 0:78: 'invariant' : can only apply to an output ERROR: 0:88: 'ub2' : Cannot reuse block name within the same interface: uniform ERROR: 0:92: 'ub2' : Cannot reuse block name within the same interface: uniform ERROR: 0:96: 'ub2' : Cannot reuse block name within the same interface: uniform diff --git a/Test/baseResults/430.vert.out b/Test/baseResults/430.vert.out index b3cb9b2d7..5f1c35c2f 100644 --- a/Test/baseResults/430.vert.out +++ b/Test/baseResults/430.vert.out @@ -4,6 +4,7 @@ ERROR: 0:3: 'location' : can only appy to uniform, buffer, in, or out storage qu ERROR: 0:7: 'in' : cannot declare an input block in a vertex shader ERROR: 0:7: 'location qualifier on in/out block' : not supported for this version or the enabled extensions ERROR: 0:8: 'location qualifier on in/out block' : not supported for this version or the enabled extensions +ERROR: 0:23: 'invariant' : can only apply to an output ERROR: 0:21: 'g' : cannot use storage or interpolation qualifiers on structure members ERROR: 0:22: 'h' : cannot use storage or interpolation qualifiers on structure members ERROR: 0:23: 'i' : cannot use invariant qualifier on structure members @@ -58,7 +59,7 @@ ERROR: 0:168: 'textureSamples and imageSamples' : not supported for this version ERROR: 0:169: 'textureSamples and imageSamples' : not supported for this version or the enabled extensions ERROR: 0:170: 'textureSamples and imageSamples' : not supported for this version or the enabled extensions ERROR: 0:171: 'textureSamples and imageSamples' : not supported for this version or the enabled extensions -ERROR: 58 compilation errors. No code generated. +ERROR: 59 compilation errors. No code generated. Shader version: 430 diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index 6dfa4b850..7da8523a9 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -4,7 +4,7 @@ ERROR: 0:6: '=' : cannot convert from 'const uint' to 'int' ERROR: 0:20: '' : numeric literal too big ERROR: 0:21: '' : hexidecimal literal too big ERROR: 0:37: 'view' : redefinition -ERROR: 0:63: 'invariant' : can only apply to an output: Color +ERROR: 0:63: 'invariant' : can only apply to an output ERROR: 0:68: 'lightPosition' : redefinition ERROR: 0:75: 'Atten' : member storage qualifier cannot contradict block storage qualifier ERROR: 0:87: 'Color' : redefinition diff --git a/Test/baseResults/switch.frag.out b/Test/baseResults/switch.frag.out index 6df32d266..65650dd36 100644 --- a/Test/baseResults/switch.frag.out +++ b/Test/baseResults/switch.frag.out @@ -1,7 +1,7 @@ switch.frag ERROR: 0:11: 'switch' : condition must be a scalar integer expression ERROR: 0:14: 'switch' : condition must be a scalar integer expression -WARNING: 0:21: 'switch' : last case/default label not be followed by statements +WARNING: 0:21: 'switch' : last case/default label not followed by statements ERROR: 0:28: 'switch' : cannot have statements before first case/default label ERROR: 0:43: 'default' : duplicate label ERROR: 0:63: 'case' : duplicated value @@ -15,7 +15,7 @@ ERROR: 0:115: 'default' : cannot be nested inside control flow ERROR: 0:119: 'case' : cannot appear outside switch statement ERROR: 0:120: 'default' : cannot appear outside switch statement ERROR: 0:126: 'onlyInSwitch' : undeclared identifier -WARNING: 0:128: 'switch' : last case/default label not be followed by statements +WARNING: 0:128: 'switch' : last case/default label not followed by statements ERROR: 0:140: 'nestedX' : undeclared identifier ERROR: 0:156: 'nestedZ' : undeclared identifier ERROR: 17 compilation errors. No code generated. diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index affef6cd4..6510c8f5a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -1983,10 +1983,11 @@ void TParseContext::atomicUintCheck(TSourceLoc loc, const TType& type, const TSt } // -// move from parameter/unknown qualifiers to pipeline in/out qualifiers +// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. // -void TParseContext::pipeInOutFix(TSourceLoc loc, TQualifier& qualifier) +void TParseContext::globalQualifierFixCheck(TSourceLoc loc, TQualifier& qualifier) { + // move from parameter/unknown qualifiers to pipeline in/out qualifiers switch (qualifier.storage) { case EvqIn: profileRequires(loc, ENoProfile, 130, 0, "in for stage inputs"); @@ -2005,9 +2006,14 @@ void TParseContext::pipeInOutFix(TSourceLoc loc, TQualifier& qualifier) default: break; } + + invariantCheck(loc, qualifier); } -void TParseContext::globalQualifierCheck(TSourceLoc loc, const TQualifier& qualifier, const TPublicType& publicType) +// +// Check a full qualifier and type (no variable yet) at global level. +// +void TParseContext::globalQualifierTypeCheck(TSourceLoc loc, const TQualifier& qualifier, const TPublicType& publicType) { if (! symbolTable.atGlobalLevel()) return; @@ -3598,7 +3604,7 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type) error(loc, "image variables not declared 'writeonly' must have a format layout qualifier", "", ""); } -// Do layout error checking that can be done within a qualifier proper, not needing to know +// Do layout error checking that can be done within a layout qualifier proper, not needing to know // if there are blocks, atomic counters, variables, etc. void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& qualifier) { @@ -3896,7 +3902,6 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, else nonInitConstCheck(loc, identifier, type); - invariantCheck(loc, type, identifier); samplerCheck(loc, type, identifier); atomicUintCheck(loc, type, identifier); @@ -4409,7 +4414,7 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr TType& memberType = *typeList[member].type; TQualifier& memberQualifier = memberType.getQualifier(); TSourceLoc memberLoc = typeList[member].loc; - pipeInOutFix(memberLoc, memberQualifier); + globalQualifierFixCheck(memberLoc, memberQualifier); if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), ""); memberQualifier.storage = currentBlockQualifier.storage; @@ -4750,7 +4755,7 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, if (intermediate.inIoAccessed(identifier)) error(loc, "cannot change qualification after use", "invariant", ""); symbol->getWritableType().getQualifier().invariant = true; - invariantCheck(loc, symbol->getType(), identifier); + invariantCheck(loc, symbol->getType().getQualifier()); } else warn(loc, "unknown requalification", "", ""); } @@ -4761,19 +4766,19 @@ void TParseContext::addQualifierToExisting(TSourceLoc loc, TQualifier qualifier, addQualifierToExisting(loc, qualifier, *identifiers[i]); } -void TParseContext::invariantCheck(TSourceLoc loc, const TType& type, const TString& identifier) +void TParseContext::invariantCheck(TSourceLoc loc, const TQualifier& qualifier) { - if (! type.getQualifier().invariant) + if (! qualifier.invariant) return; - bool pipeOut = type.getQualifier().isPipeOutput(); - bool pipeIn = type.getQualifier().isPipeInput(); + bool pipeOut = qualifier.isPipeOutput(); + bool pipeIn = qualifier.isPipeInput(); if (version >= 300 || profile != EEsProfile && version >= 420) { if (! pipeOut) - error(loc, "can only apply to an output:", "invariant", identifier.c_str()); + error(loc, "can only apply to an output", "invariant", ""); } else { if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn)) - error(loc, "can only apply to an output or an input in a non-vertex stage\n", "invariant", ""); + error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", ""); } } @@ -5002,7 +5007,7 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression, return expression; if (lastStatements == 0) { - warn(loc, "last case/default label not be followed by statements", "switch", ""); + warn(loc, "last case/default label not followed by statements", "switch", ""); return expression; } diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 5fc676dc9..c678e4221 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -130,8 +130,8 @@ public: void boolCheck(TSourceLoc, const TPublicType&); void samplerCheck(TSourceLoc, const TType&, const TString& identifier); void atomicUintCheck(TSourceLoc, const TType&, const TString& identifier); - void pipeInOutFix(TSourceLoc, TQualifier&); - void globalQualifierCheck(TSourceLoc, const TQualifier&, const TPublicType&); + void globalQualifierFixCheck(TSourceLoc, TQualifier&); + void globalQualifierTypeCheck(TSourceLoc, const TQualifier&, const TPublicType&); bool structQualifierErrorCheck(TSourceLoc, const TPublicType& pType); void mergeQualifiers(TSourceLoc, TQualifier& dst, const TQualifier& src, bool force); void setDefaultPrecision(TSourceLoc, TPublicType&, TPrecisionQualifier); @@ -180,7 +180,7 @@ public: void fixBlockUniformOffsets(TSourceLoc, TQualifier&, TTypeList&); void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier); void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&); - void invariantCheck(TSourceLoc, const TType&, const TString& identifier); + void invariantCheck(TSourceLoc, const TQualifier&); void updateStandaloneQualifierDefaults(TSourceLoc, const TPublicType&); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); TIntermNode* addSwitch(TSourceLoc, TIntermTyped* expression, TIntermAggregate* body); diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index c33656431..3ee28c323 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -696,18 +696,16 @@ declaration $$ = 0; } | type_qualifier SEMICOLON { - parseContext.pipeInOutFix($1.loc, $1.qualifier); + parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.updateStandaloneQualifierDefaults($1.loc, $1); $$ = 0; } | type_qualifier IDENTIFIER SEMICOLON { - parseContext.pipeInOutFix($1.loc, $1.qualifier); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string); $$ = 0; } | type_qualifier IDENTIFIER identifier_list SEMICOLON { - parseContext.pipeInOutFix($1.loc, $1.qualifier); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); $3->push_back($2.string); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3); @@ -719,7 +717,7 @@ block_structure : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { --parseContext.structNestingLevel; parseContext.blockName = $2.string; - parseContext.pipeInOutFix($1.loc, $1.qualifier); + parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.currentBlockQualifier = $1.qualifier; $$.loc = $1.loc; @@ -943,7 +941,7 @@ fully_specified_type : type_specifier { $$ = $1; - parseContext.globalQualifierCheck($1.loc, $1.qualifier, $$); + parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $$); if ($1.arraySizes) { parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type"); parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); @@ -952,8 +950,8 @@ fully_specified_type parseContext.precisionQualifierCheck($$.loc, $$); } | type_qualifier type_specifier { - parseContext.pipeInOutFix($1.loc, $1.qualifier); - parseContext.globalQualifierCheck($1.loc, $1.qualifier, $2); + parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); + parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2); if ($2.arraySizes) { parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type"); @@ -1965,6 +1963,7 @@ struct_declaration } } | type_qualifier type_specifier struct_declarator_list SEMICOLON { + parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); if ($2.arraySizes) { parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type"); parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type"); -- GitLab