glslang: Fix over 100 warnings from MSVC warning level 4.
[platform/upstream/glslang.git] / glslang / MachineIndependent / Scan.cpp
index 3d675df..6c56c1c 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] = (char)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.
@@ -236,6 +274,9 @@ public:
     explicit TParserToken(YYSTYPE& b) : sType(b) { }
 
     YYSTYPE& sType;
+protected:
+    TParserToken(TParserToken&);
+    TParserToken& operator=(TParserToken&);
 };
 
 } // end namespace glslang
@@ -476,6 +517,14 @@ void TScanContext::fillInKeywordMap()
     ReservedSet->insert("using");
 }
 
+void TScanContext::deleteKeywordMap()
+{
+    delete KeywordMap;
+    KeywordMap = 0;
+    delete ReservedSet;
+    ReservedSet = 0;
+}
+
 int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
 {
     do {
@@ -548,7 +597,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
                                    
         default:
             char buf[2];
-            buf[0] = ppToken.token;
+            buf[0] = (char)ppToken.token;
             buf[1] = 0;
             parseContext.error(loc, "unexpected token", buf, "");
             break;
@@ -630,29 +679,43 @@ int TScanContext::tokenizeIdentifier()
         return keyword;
 
     case BUFFER:
-        if (parseContext.version < 430)
+        if ((parseContext.profile == EEsProfile && parseContext.version < 310) || 
+            (parseContext.profile != EEsProfile && parseContext.version < 430))
             return identifierOrType();
         return keyword;
 
+    case ATOMIC_UINT:
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310 ||
+            parseContext.extensionsTurnedOn(1, &GL_ARB_shader_atomic_counters))
+            return keyword;
+        return es30ReservedFromGLSL(420);
+
     case COHERENT:
     case RESTRICT:
     case READONLY:
     case WRITEONLY:
-    case ATOMIC_UINT:
-        return es30ReservedFromGLSL(420);
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420);
 
     case VOLATILE:
-        if (parseContext.profile == EEsProfile || parseContext.version < 420)
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))))
             reservedWord();
         return keyword;
 
     case LAYOUT:
+    {
+        const int numLayoutExts = 2;
+        const char* layoutExts[numLayoutExts] = { GL_ARB_shading_language_420pack,
+                                                  GL_ARB_explicit_attrib_location };
         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
             (parseContext.profile != EEsProfile && parseContext.version < 140 &&
-            ! parseContext.extensionsTurnedOn(1, &GL_ARB_shading_language_420pack)))
+            ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts)))
             return identifierOrType();
         return keyword;
-
+    }
     case SHARED:
         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
             (parseContext.profile != EEsProfile && parseContext.version < 140))
@@ -703,32 +766,34 @@ int TScanContext::tokenizeIdentifier()
     case IMAGE1D:
     case IIMAGE1D:
     case UIMAGE1D:
+    case IMAGE1DARRAY:
+    case IIMAGE1DARRAY:
+    case UIMAGE1DARRAY:
+    case IMAGE2DRECT:
+    case IIMAGE2DRECT:
+    case UIMAGE2DRECT:
+    case IMAGEBUFFER:
+    case IIMAGEBUFFER:
+    case UIMAGEBUFFER:
+        return firstGenerationImage(false);
+
     case IMAGE2D:
     case IIMAGE2D:
     case UIMAGE2D:
     case IMAGE3D:
     case IIMAGE3D:
     case UIMAGE3D:
-    case IMAGE2DRECT:
-    case IIMAGE2DRECT:
-    case UIMAGE2DRECT:
     case IMAGECUBE:
     case IIMAGECUBE:
     case UIMAGECUBE:
-    case IMAGEBUFFER:
-    case IIMAGEBUFFER:
-    case UIMAGEBUFFER:
-    case IMAGE1DARRAY:
-    case IIMAGE1DARRAY:
-    case UIMAGE1DARRAY:
     case IMAGE2DARRAY:
     case IIMAGE2DARRAY:
     case UIMAGE2DARRAY:
-        return firstGenerationImage();
+        return firstGenerationImage(true);
 
     case IMAGECUBEARRAY:
     case IIMAGECUBEARRAY:
-    case UIMAGECUBEARRAY:
+    case UIMAGECUBEARRAY:        
     case IMAGE2DMS:
     case IIMAGE2DMS:
     case UIMAGE2DMS:
@@ -792,6 +857,11 @@ int TScanContext::tokenizeIdentifier()
     case SAMPLER2DMS:
     case ISAMPLER2DMS:
     case USAMPLER2DMS:
+        afterType = true;
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        return es30ReservedFromGLSL(150);
+
     case SAMPLER2DMSARRAY:
     case ISAMPLER2DMSARRAY:
     case USAMPLER2DMSARRAY:
@@ -824,8 +894,12 @@ int TScanContext::tokenizeIdentifier()
         afterType = true;
         if (parseContext.profile == EEsProfile)
             reservedWord();
-        else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionsTurnedOn(1, &GL_ARB_texture_rectangle))
-            reservedWord();
+        else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionsTurnedOn(1, &GL_ARB_texture_rectangle)) {
+            if (parseContext.messages & EShMsgRelaxedErrors)
+                parseContext.requireExtensions(loc, 1, &GL_ARB_texture_rectangle, "texture-rectangle sampler keyword");
+            else
+                reservedWord();
+        }
         return keyword;
 
     case SAMPLER1DARRAY:
@@ -865,7 +939,9 @@ int TScanContext::tokenizeIdentifier()
         return keyword;
 
     case PRECISE:
-        if (parseContext.profile == EEsProfile ||
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            reservedWord();
+        else if (parseContext.profile == EEsProfile ||
             (parseContext.profile != EEsProfile && parseContext.version < 400))
             return identifierOrType();
         return keyword;
@@ -951,6 +1027,9 @@ int TScanContext::identifierOrReserved(bool reserved)
 // but then got reserved by ES 3.0.
 int TScanContext::es30ReservedFromGLSL(int version)
 {
+    if (parseContext.symbolTable.atBuiltInLevel())
+        return keyword;
+
     if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
         (parseContext.profile != EEsProfile && parseContext.version < version)) {
             if (parseContext.forwardCompatible)
@@ -1021,11 +1100,13 @@ int TScanContext::dMat()
     return identifierOrType();
 }
 
-int TScanContext::firstGenerationImage()
+int TScanContext::firstGenerationImage(bool inEs310)
 {
     afterType = true;
 
-    if (parseContext.profile != EEsProfile && parseContext.version >= 420)
+    if (parseContext.symbolTable.atBuiltInLevel() || 
+        (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))) ||                                                     
+        (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
         return keyword;
 
     if ((parseContext.profile == EEsProfile && parseContext.version >= 300) ||
@@ -1045,7 +1126,12 @@ int TScanContext::secondGenerationImage()
 {
     afterType = true;
 
-    if (parseContext.profile != EEsProfile && parseContext.version >= 420)
+    if (parseContext.profile == EEsProfile && parseContext.version >= 310) {
+        reservedWord();
+        return keyword;
+    }
+
+    if (parseContext.symbolTable.atBuiltInLevel() || parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store)))
         return keyword;
 
     if (parseContext.forwardCompatible)