Add more allowances for relaxed error checking mode: Warn instead of error on use...
authorJohn Kessenich <cepheus@frii.com>
Wed, 18 Jun 2014 23:02:00 +0000 (23:02 +0000)
committerJohn Kessenich <cepheus@frii.com>
Wed, 18 Jun 2014 23:02:00 +0000 (23:02 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@27113 e7fa87d3-cd2b-0410-9028-fcbf551c1848

glslang/MachineIndependent/Scan.cpp
glslang/MachineIndependent/Scan.h
glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/Versions.cpp
glslang/MachineIndependent/preprocessor/PpScanner.cpp

index 3d675df..5f92ba7 100644 (file)
@@ -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 (    c != 'v' ||
-        get() != 'e' ||
-        get() != 'r' ||
-        get() != 's' ||
-        get() != 'i' ||
-        get() != 'o' ||
-        get() != 'n')
-        return true;
+        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;
+
+        // 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;
+
+        // "#"
+        if (get() != '#') {
+            versionNotFirst = true;
+            continue;
+        }
 
-    // whitespace
-    do {
-        c = get();
-    } while (c == ' ' || c == '\t');
+        // whitespace
+        do {
+            c = get();
+        } while (c == ' ' || c == '\t');
+
+        // "version"
+        if (    c != 'v' ||
+            get() != 'e' ||
+            get() != 'r' ||
+            get() != 's' ||
+            get() != 'i' ||
+            get() != 'o' ||
+            get() != 'n') {
+            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 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;
+        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 foundNonSpaceTab;
+        return versionNotFirst;
+    } while (true);
 }
 
 // Fill this in when doing glslang-level scanning, to hand back to the parser.
index 6a8d0ff..67e6193 100644 (file)
@@ -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:
 
index 73b6276..b7c89f8 100644 (file)
@@ -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();
 
index eea1302..4ba3319 100644 (file)
@@ -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;
index 879031f..4fa7ad5 100644 (file)
@@ -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)