mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 20:10:06 +00:00
Add semantic checks for order of qualification and repetition within a class of qualifiers.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22145 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
f5c1075031
commit
01fc0645cb
@ -9,9 +9,9 @@ precision highp float;
|
||||
in vec4 i;
|
||||
out vec4 o;
|
||||
|
||||
in flat float fflat;
|
||||
in smooth float fsmooth;
|
||||
in noperspective float fnop;
|
||||
flat in float fflat;
|
||||
smooth in float fsmooth;
|
||||
noperspective in float fnop;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -5,9 +5,17 @@ uniform mat3x3 m33;
|
||||
uniform mat4x4 m44;
|
||||
|
||||
in vec3 v3;
|
||||
varying vec2 v2; // ERROR
|
||||
|
||||
in vec4 bad[10]; // ERROR
|
||||
varying vec2 v2; // ERROR, varying reserved
|
||||
in vec4 bad[10]; // ERROR, no arrayed inputs
|
||||
highp in vec4 badorder; // ERROR, incorrect qualifier order
|
||||
out invariant vec4 badorder2; // ERROR, incorrect qualifier order
|
||||
in centroid vec4 badorder4; // ERROR, incorrect qualifier order
|
||||
out flat vec4 badorder3; // ERROR, incorrect qualifier order
|
||||
void bar(in const float a); // ERROR, incorrect qualifier order
|
||||
void bar2(highp in float b); // ERROR, incorrect qualifier order
|
||||
smooth flat out vec4 rep; // ERROR, replicating interpolation qualification
|
||||
centroid sample out vec4 rep2; // ERROR, replicating auxiliary qualification
|
||||
in uniform vec4 rep3; // ERROR, replicating storage qualification
|
||||
|
||||
struct S {
|
||||
vec3 c;
|
||||
|
13
Test/420.vert
Normal file
13
Test/420.vert
Normal file
@ -0,0 +1,13 @@
|
||||
#version 420 core
|
||||
|
||||
varying vec2 v2; // ERROR, varying reserved
|
||||
in vec4 bad[10];
|
||||
highp in vec4 badorder;
|
||||
out invariant vec4 badorder2;
|
||||
in centroid vec4 badorder4; // ERROR, no centroid input to vertex stage
|
||||
out flat vec4 badorder3;
|
||||
void bar(in const float a);
|
||||
void bar2(highp in float b);
|
||||
smooth flat out vec4 rep; // ERROR, replicating interpolation qualification
|
||||
centroid sample out vec4 rep2; // ERROR, replicating auxiliary qualification
|
||||
in uniform vec4 rep3; // ERROR, replicating storage qualification
|
@ -1,7 +1,7 @@
|
||||
#version 300 es
|
||||
|
||||
uniform int c, d;
|
||||
highp in float x;
|
||||
in highp float x;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -39,4 +39,5 @@ uint.frag
|
||||
switch.frag
|
||||
tokenLength.vert
|
||||
300scope.vert
|
||||
420.vert
|
||||
430scope.vert
|
||||
|
@ -250,7 +250,7 @@ public:
|
||||
{
|
||||
return flat || smooth || nopersp;
|
||||
}
|
||||
bool isAuxillary() const
|
||||
bool isAuxiliary() const
|
||||
{
|
||||
return centroid || patch || sample;
|
||||
}
|
||||
|
@ -757,7 +757,7 @@ void TParseContext::globalQualifierFix(int line, TQualifier& qualifier, const TP
|
||||
}
|
||||
|
||||
if (language == EShLangVertex && qualifier.storage == EvqVaryingIn &&
|
||||
(qualifier.isAuxillary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)) {
|
||||
(qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)) {
|
||||
error(line, "vertex input cannot be further qualified", "", "");
|
||||
|
||||
return;
|
||||
@ -768,38 +768,62 @@ void TParseContext::globalQualifierFix(int line, TQualifier& qualifier, const TP
|
||||
// Merge characteristics of the 'src' qualifier into the 'dst'.
|
||||
// If there is duplication, issue error messages, unless 'force'
|
||||
// is specified, which means to just override default settings.
|
||||
//
|
||||
// Also, when force is false, it will be assumed that 'src' follows
|
||||
// 'dst', for the purpose of error checking order for versions
|
||||
// that require specific orderings of qualifiers.
|
||||
//
|
||||
void TParseContext::mergeQualifiers(int line, TPublicType& dst, const TPublicType& src, bool force)
|
||||
void TParseContext::mergeQualifiers(int line, TQualifier& dst, const TQualifier& src, bool force)
|
||||
{
|
||||
bool bad = false;
|
||||
// Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers')
|
||||
if (src.isAuxiliary() && dst.isAuxiliary())
|
||||
error(line, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", "");
|
||||
|
||||
// Multiple interpolation qualifiers (mostly done later by 'individual qualifiers')
|
||||
if (src.isInterpolation() && dst.isInterpolation())
|
||||
error(line, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", "");
|
||||
|
||||
// Ordering
|
||||
if (! force && version < 420) {
|
||||
// non-function parameters
|
||||
if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
|
||||
error(line, "invariant qualifier must appear first", "", "");
|
||||
else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
|
||||
error(line, "interpolation qualifiers must appear before storage and precision qualifiers", "", "");
|
||||
else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone))
|
||||
error(line, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", "");
|
||||
else if (src.storage != EvqTemporary && (dst.precision != EpqNone))
|
||||
error(line, "precision qualifier must appear as last qualifier", "", "");
|
||||
|
||||
// function parameters
|
||||
if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut))
|
||||
error(line, "in/out must appear before const", "", "");
|
||||
}
|
||||
|
||||
// Storage qualification
|
||||
if (dst.qualifier.storage == EvqTemporary || dst.qualifier.storage == EvqGlobal)
|
||||
dst.qualifier.storage = src.qualifier.storage;
|
||||
else if (dst.qualifier.storage == EvqIn && src.qualifier.storage == EvqOut ||
|
||||
dst.qualifier.storage == EvqOut && src.qualifier.storage == EvqIn)
|
||||
dst.qualifier.storage = EvqInOut;
|
||||
else if (dst.qualifier.storage == EvqIn && src.qualifier.storage == EvqConst ||
|
||||
dst.qualifier.storage == EvqConst && src.qualifier.storage == EvqIn)
|
||||
dst.qualifier.storage = EvqConstReadOnly;
|
||||
else if (src.qualifier.storage != EvqTemporary) {
|
||||
error(line, "too many storage qualifiers", getStorageQualifierString(src.qualifier.storage), "");
|
||||
bad = true;
|
||||
}
|
||||
if (dst.storage == EvqTemporary || dst.storage == EvqGlobal)
|
||||
dst.storage = src.storage;
|
||||
else if (dst.storage == EvqIn && src.storage == EvqOut ||
|
||||
dst.storage == EvqOut && src.storage == EvqIn)
|
||||
dst.storage = EvqInOut;
|
||||
else if (dst.storage == EvqIn && src.storage == EvqConst ||
|
||||
dst.storage == EvqConst && src.storage == EvqIn)
|
||||
dst.storage = EvqConstReadOnly;
|
||||
else if (src.storage != EvqTemporary)
|
||||
error(line, "too many storage qualifiers", getStorageQualifierString(src.storage), "");
|
||||
|
||||
// Precision qualifiers
|
||||
if (! force && src.qualifier.precision != EpqNone && dst.qualifier.precision != EpqNone) {
|
||||
error(line, "only one precision qualifier allowed", getPrecisionQualifierString(src.qualifier.precision), "");
|
||||
bad = true;
|
||||
}
|
||||
if (dst.qualifier.precision == EpqNone || force && src.qualifier.precision != EpqNone)
|
||||
dst.qualifier.precision = src.qualifier.precision;
|
||||
if (! force && src.precision != EpqNone && dst.precision != EpqNone)
|
||||
error(line, "only one precision qualifier allowed", getPrecisionQualifierString(src.precision), "");
|
||||
if (dst.precision == EpqNone || force && src.precision != EpqNone)
|
||||
dst.precision = src.precision;
|
||||
|
||||
// Layout qualifiers
|
||||
mergeLayoutQualifiers(line, dst.qualifier, src.qualifier);
|
||||
mergeLayoutQualifiers(line, dst, src);
|
||||
|
||||
// other qualifiers
|
||||
#define MERGE_SINGLETON(field) bad |= dst.qualifier.field && src.qualifier.field; dst.qualifier.field |= src.qualifier.field;
|
||||
// individual qualifiers
|
||||
bool repeated = false;
|
||||
#define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field;
|
||||
MERGE_SINGLETON(invariant);
|
||||
MERGE_SINGLETON(centroid);
|
||||
MERGE_SINGLETON(smooth);
|
||||
@ -814,7 +838,7 @@ void TParseContext::mergeQualifiers(int line, TPublicType& dst, const TPublicTyp
|
||||
MERGE_SINGLETON(readonly);
|
||||
MERGE_SINGLETON(writeonly);
|
||||
|
||||
if (bad)
|
||||
if (repeated)
|
||||
error(line, "replicated qualifiers", "", "");
|
||||
}
|
||||
|
||||
@ -1562,8 +1586,8 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
|
||||
TQualifier memberQualifier = typeList[member].type->getQualifier();
|
||||
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockDefaults.storage)
|
||||
error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||
if (currentBlockDefaults.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
|
||||
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||
if (currentBlockDefaults.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())
|
||||
error(line, "member of uniform block cannot have an auxiliary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||
|
||||
TBasicType basicType = typeList[member].type->getBasicType();
|
||||
if (basicType == EbtSampler)
|
||||
@ -1631,12 +1655,12 @@ void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, const
|
||||
return;
|
||||
}
|
||||
|
||||
if (qualifier.isAuxillary() ||
|
||||
if (qualifier.isAuxiliary() ||
|
||||
qualifier.isMemory() ||
|
||||
qualifier.isInterpolation() ||
|
||||
qualifier.storage != EvqTemporary ||
|
||||
qualifier.precision != EpqNone) {
|
||||
error(line, "cannot add storage, auxillary, memory, interpolation, or precision qualifier to an existing variable", identifier.c_str(), "");
|
||||
error(line, "cannot add storage, auxiliary, memory, interpolation, or precision qualifier to an existing variable", identifier.c_str(), "");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1676,11 +1700,11 @@ void TParseContext::updateQualifierDefaults(TQualifier qualifier)
|
||||
|
||||
void TParseContext::updateQualifierDefaults(int line, TQualifier qualifier)
|
||||
{
|
||||
if (qualifier.isAuxillary() ||
|
||||
if (qualifier.isAuxiliary() ||
|
||||
qualifier.isMemory() ||
|
||||
qualifier.isInterpolation() ||
|
||||
qualifier.precision != EpqNone)
|
||||
error(line, "cannot use auxillary, memory, interpolation, or precision qualifier in a standalone qualifier", "", "");
|
||||
error(line, "cannot use auxiliary, memory, interpolation, or precision qualifier in a standalone qualifier", "", "");
|
||||
|
||||
switch (qualifier.storage) {
|
||||
case EvqUniform:
|
||||
|
@ -128,7 +128,7 @@ struct TParseContext {
|
||||
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
|
||||
void globalQualifierFix(int line, TQualifier&, const TPublicType&);
|
||||
bool structQualifierErrorCheck(int line, const TPublicType& pType);
|
||||
void mergeQualifiers(int line, TPublicType& dst, const TPublicType& src, bool force);
|
||||
void mergeQualifiers(int line, TQualifier& dst, const TQualifier& src, bool force);
|
||||
void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);
|
||||
int computeSamplerTypeIndex(TSampler&);
|
||||
TPrecisionQualifier getDefaultPrecision(TPublicType&);
|
||||
|
@ -1487,7 +1487,7 @@ fully_specified_type
|
||||
if ($2.arraySizes && parseContext.arrayQualifierError($2.line, $1))
|
||||
$2.arraySizes = 0;
|
||||
|
||||
parseContext.mergeQualifiers($2.line, $2, $1, true);
|
||||
parseContext.mergeQualifiers($2.line, $2.qualifier, $1.qualifier, true);
|
||||
parseContext.precisionQualifierCheck($2.line, $2);
|
||||
|
||||
$$ = $2;
|
||||
@ -1575,7 +1575,7 @@ type_qualifier
|
||||
if ($$.basicType == EbtVoid)
|
||||
$$.basicType = $2.basicType;
|
||||
|
||||
parseContext.mergeQualifiers($$.line, $$, $2, false);
|
||||
parseContext.mergeQualifiers($$.line, $$.qualifier, $2.qualifier, false);
|
||||
}
|
||||
;
|
||||
|
||||
@ -2487,7 +2487,7 @@ struct_declaration
|
||||
$$ = $3;
|
||||
|
||||
parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2);
|
||||
parseContext.mergeQualifiers($2.line, $2, $1, true);
|
||||
parseContext.mergeQualifiers($2.line, $2.qualifier, $1.qualifier, true);
|
||||
parseContext.precisionQualifierCheck($2.line, $2);
|
||||
|
||||
for (unsigned int i = 0; i < $$->size(); ++i)
|
||||
|
Loading…
Reference in New Issue
Block a user