Add more allowances for relaxed error checking mode: Warn instead of error on use of a disabled extension, allow 'f' suffix on floating point literals, and allow #version after tokens.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@27113 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
fd30542a0f
commit
7e991e7be1
@ -155,79 +155,117 @@ void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
|
||||
// or no #version was found; otherwise, returns false. There is no error case, it always
|
||||
// succeeds, but will leave version == 0 if no #version was found.
|
||||
//
|
||||
// Sets versionNotFirstToken based on whether tokens (beyond white space and comments)
|
||||
// appeared before the #version.
|
||||
//
|
||||
// N.B. does not attempt to leave input in any particular known state. The assumption
|
||||
// is that scanning will start anew, following the rules for the chosen version/profile,
|
||||
// and with a corresponding parsing context.
|
||||
//
|
||||
bool TInputScanner::scanVersion(int& version, EProfile& profile)
|
||||
bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken)
|
||||
{
|
||||
// This function doesn't have to get all the semantics correct,
|
||||
// just find the #version if there is a correct one present.
|
||||
// The preprocessor will have the responsibility of getting all the semantics right.
|
||||
|
||||
bool versionNotFirst = false; // means not first WRT comments and white space, nothing more
|
||||
notFirstToken = false; // means not first WRT to real tokens
|
||||
version = 0; // means not found
|
||||
profile = ENoProfile;
|
||||
|
||||
bool foundNonSpaceTab = false;
|
||||
consumeWhitespaceComment(foundNonSpaceTab);
|
||||
|
||||
// #
|
||||
if (get() != '#')
|
||||
return true;
|
||||
|
||||
// whitespace
|
||||
bool lookingInMiddle = false;
|
||||
int c;
|
||||
do {
|
||||
c = get();
|
||||
} while (c == ' ' || c == '\t');
|
||||
if (lookingInMiddle) {
|
||||
notFirstToken = true;
|
||||
// make forward progress by finishing off the current line plus extra new lines
|
||||
if (peek() == '\n' || peek() == '\r') {
|
||||
while (peek() == '\n' || peek() == '\r')
|
||||
get();
|
||||
} else
|
||||
do {
|
||||
c = get();
|
||||
} while (c > 0 && c != '\n' && c != '\r');
|
||||
while (peek() == '\n' || peek() == '\r')
|
||||
get();
|
||||
if (peek() < 0)
|
||||
return true;
|
||||
}
|
||||
lookingInMiddle = true;
|
||||
|
||||
if ( c != 'v' ||
|
||||
get() != 'e' ||
|
||||
get() != 'r' ||
|
||||
get() != 's' ||
|
||||
get() != 'i' ||
|
||||
get() != 'o' ||
|
||||
get() != 'n')
|
||||
return true;
|
||||
// Nominal start, skipping the desktop allowed comments and white space, but tracking if
|
||||
// something else was found for ES:
|
||||
consumeWhitespaceComment(foundNonSpaceTab);
|
||||
if (foundNonSpaceTab)
|
||||
versionNotFirst = true;
|
||||
|
||||
// whitespace
|
||||
do {
|
||||
c = get();
|
||||
} while (c == ' ' || c == '\t');
|
||||
// "#"
|
||||
if (get() != '#') {
|
||||
versionNotFirst = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// version number
|
||||
while (c >= '0' && c <= '9') {
|
||||
version = 10 * version + (c - '0');
|
||||
c = get();
|
||||
}
|
||||
if (version == 0)
|
||||
return true;
|
||||
|
||||
// whitespace
|
||||
while (c == ' ' || c == '\t')
|
||||
c = get();
|
||||
// whitespace
|
||||
do {
|
||||
c = get();
|
||||
} while (c == ' ' || c == '\t');
|
||||
|
||||
// profile
|
||||
const int maxProfileLength = 13; // not including any 0
|
||||
char profileString[maxProfileLength];
|
||||
int profileLength;
|
||||
for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
|
||||
if (c < 0 || c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
break;
|
||||
profileString[profileLength] = c;
|
||||
c = get();
|
||||
}
|
||||
if (c > 0 && c != ' ' && c != '\t' && c != '\n' && c != '\r')
|
||||
return true;
|
||||
// "version"
|
||||
if ( c != 'v' ||
|
||||
get() != 'e' ||
|
||||
get() != 'r' ||
|
||||
get() != 's' ||
|
||||
get() != 'i' ||
|
||||
get() != 'o' ||
|
||||
get() != 'n') {
|
||||
versionNotFirst = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
|
||||
profile = EEsProfile;
|
||||
else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
|
||||
profile = ECoreProfile;
|
||||
else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
|
||||
profile = ECompatibilityProfile;
|
||||
// whitespace
|
||||
do {
|
||||
c = get();
|
||||
} while (c == ' ' || c == '\t');
|
||||
|
||||
return foundNonSpaceTab;
|
||||
// version number
|
||||
while (c >= '0' && c <= '9') {
|
||||
version = 10 * version + (c - '0');
|
||||
c = get();
|
||||
}
|
||||
if (version == 0) {
|
||||
versionNotFirst = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// whitespace
|
||||
while (c == ' ' || c == '\t')
|
||||
c = get();
|
||||
|
||||
// profile
|
||||
const int maxProfileLength = 13; // not including any 0
|
||||
char profileString[maxProfileLength];
|
||||
int profileLength;
|
||||
for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
|
||||
if (c < 0 || c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
break;
|
||||
profileString[profileLength] = c;
|
||||
c = get();
|
||||
}
|
||||
if (c > 0 && c != ' ' && c != '\t' && c != '\n' && c != '\r') {
|
||||
versionNotFirst = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
|
||||
profile = EEsProfile;
|
||||
else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
|
||||
profile = ECoreProfile;
|
||||
else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
|
||||
profile = ECompatibilityProfile;
|
||||
|
||||
return versionNotFirst;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
// Fill this in when doing glslang-level scanning, to hand back to the parser.
|
||||
|
@ -112,7 +112,7 @@ public:
|
||||
void consumeWhiteSpace(bool& foundNonSpaceTab);
|
||||
bool consumeComment();
|
||||
void consumeWhitespaceComment(bool& foundNonSpaceTab);
|
||||
bool scanVersion(int& version, EProfile& profile);
|
||||
bool scanVersion(int& version, EProfile& profile, bool& notFirstToken);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -461,11 +461,19 @@ bool CompileDeferred(
|
||||
int version;
|
||||
EProfile profile;
|
||||
glslang::TInputScanner userInput(numStrings, &strings[1], &lengths[1]); // no preamble
|
||||
bool versionNotFirst = userInput.scanVersion(version, profile);
|
||||
bool versionNotFirstToken;
|
||||
bool versionNotFirst = userInput.scanVersion(version, profile, versionNotFirstToken);
|
||||
bool versionNotFound = version == 0;
|
||||
bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, version, profile);
|
||||
bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
|
||||
|
||||
bool warnVersionNotFirst = false;
|
||||
if (! versionWillBeError && versionNotFirstToken) {
|
||||
if (messages & EShMsgRelaxedErrors)
|
||||
warnVersionNotFirst = true;
|
||||
else
|
||||
versionWillBeError = true;
|
||||
}
|
||||
|
||||
intermediate.setVersion(version);
|
||||
intermediate.setProfile(profile);
|
||||
SetupBuiltinSymbolTable(version, profile);
|
||||
@ -496,6 +504,12 @@ bool CompileDeferred(
|
||||
parseContext.setLimits(*resources);
|
||||
if (! goodVersion)
|
||||
parseContext.addError();
|
||||
if (warnVersionNotFirst) {
|
||||
TSourceLoc loc;
|
||||
loc.line = 1;
|
||||
loc.string = 0;
|
||||
parseContext.warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
|
||||
}
|
||||
|
||||
parseContext.initializeExtensionBehavior();
|
||||
|
||||
|
@ -367,6 +367,10 @@ void TParseContext::requireExtensions(TSourceLoc loc, int numExtensions, const c
|
||||
bool warned = false;
|
||||
for (int i = 0; i < numExtensions; ++i) {
|
||||
TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
|
||||
if (behavior == EBhDisable && (messages & EShMsgRelaxedErrors)) {
|
||||
infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
|
||||
behavior = EBhWarn;
|
||||
}
|
||||
if (behavior == EBhWarn) {
|
||||
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
|
||||
warned = true;
|
||||
|
@ -205,7 +205,8 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
||||
}
|
||||
} else if (ch == 'f' || ch == 'F') {
|
||||
parseContext.profileRequires(ppToken->loc, EEsProfile, 300, 0, "floating-point suffix");
|
||||
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, 0, "floating-point suffix");
|
||||
if ((parseContext.messages & EShMsgRelaxedErrors) == 0)
|
||||
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, 0, "floating-point suffix");
|
||||
if (! HasDecimalOrExponent)
|
||||
parseContext.error(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
|
||||
if (len < TPpToken::maxTokenLength)
|
||||
|
Loading…
x
Reference in New Issue
Block a user