diff --git a/Test/numeral.frag b/Test/numeral.frag new file mode 100644 index 00000000..379da126 --- /dev/null +++ b/Test/numeral.frag @@ -0,0 +1,96 @@ +#version 400 + +void main() +{ + int o00 = 00; + int o000 = 000; + int o0000 = 0000; + int o5 = 05; + int o05 = 005; + int o006 = 0006; + int o7 = 07; + int o58 = 072; + int omax = 037777777777; + int o8 = 08; // ERROR + int o08 = 008; // ERROR + int o009 = 0009; // ERROR + int obig = 07324327323472347234; // ERROR + int omax1 = 040000000000; // ERROR + + uint uo5 = 05u; + uint uo6 = 06u; + uint uo7 = 07u; + uint uo8 = 08u; // ERROR + uint uo9 = 09u; // ERROR + + int h0 = 0x0; + int h00 = 0x00; + int h000 = 0x000; + int h1 = 0x1; + int h2 = 0x00000002; + int h300 = 0x000300; + int hABCDEF = 0xAbCdEF; + int hFFFFFFFF = 0xFFFFFFFF; + int h12345678 = 0xBC614E; + int hToBeOrNotToBe = 0x2b | ~0x2B; + + uint uh0 = 0x0u; + uint uhg = (0xcu); + uint uh000 = 0x000u; + uint uh1 = 0x1u; + uint uh2 = 0x00000002u; + uint uh300 = 0x000300u; + uint uhABCDEF = 0xAbCdEFu; + uint uhFFFFFFFF = 0xFFFFFFFFu; + uint uh12345678 = 0xBC614Eu; + uint uhToBeOrNotToBe = 0x2bu | ~0x2BU; + + //int he1 = 0xG; // ERROR + int he2 = 0x; // ERROR + int hbig = 0xFFFFFFFF1; // ERROR + + float f1 = 1.0; + float f2 = 2.; + float f3 = 3e0; + float f4 = 40e-1; + float f5 = 05.; + float f6 = 006.; + float f7 = .7e1; + float f8 = 08e0; + float f9 = .9e+1; + float f10 = 10.0; + float f11 = .011e+3; + float f12 = .0012e4; + float f543 = 000000543.; + float f6789 = 00006789.; + float f88 = 0000088.; + + float g1 = 5.3876e4; + float g2 = 4000000000e-11; + float g3 = 1e+5; + float g4 = 7.321E-3; + float g5 = 3.2E+4; + float g6 = 0.5e-5; + float g7 = 0.45; + float g8 = 6.e10; + + double gf1 = 1.0lf; + double gf2 = 2.Lf; + double gf3 = .3e1lF; + double gf4 = .4e1LF; + float gf5 = 5.f; + float gf6 = 6.F; + + //float e1 = 1..; // ERROR + //float e2 = 2.l; // ERROR + //float e3 = ..3; // ERROR + //float e4 = 4ee1; // ERROR + float e5 = 5f; // ERROR +} + +layout (location = 2) out vec4 c2; +layout (location = 3u) out vec4 c3; +layout (location = 04) out vec4 c4; +layout (location = 005u) out vec4 c5; +layout (location = 0x6) out vec4 c6; +layout (location = 0x7u) out vec4 c7; diff --git a/Test/runtests b/Test/runtests index c3e17467..02104db3 100644 --- a/Test/runtests +++ b/Test/runtests @@ -1,12 +1,11 @@ #!/usr/bin/env bash -RUNCMD=../Build/Debug/glslang.exe TARGETDIR=localout BASEDIR=localbase while read t; do echo Running $t... b=`basename $t` - ./StandAlone -i $t > $TARGETDIR/$b.out + ./glslangValidator.exe -i $t > $TARGETDIR/$b.out diff $BASEDIR/$b.out $TARGETDIR/$b.out done < testlist diff --git a/Test/testlist b/Test/testlist index 6e4e0a64..3dcc6097 100644 --- a/Test/testlist +++ b/Test/testlist @@ -43,3 +43,4 @@ tokenLength.vert 420.vert 430scope.vert lineContinuation.vert +numeral.frag diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 9a470f51..2335c3e6 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -1561,6 +1561,10 @@ layout_qualifier_id $$.init($1.loc); parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3.i); } + | IDENTIFIER EQUAL UINTCONSTANT { + $$.init($1.loc); + parseContext.setLayoutQualifier($1.loc, $$, *$1.string, (int)$3.u); + } | SHARED { // because "shared" is both an identifier and a keyword $$.init($1.loc); TString strShared("shared"); diff --git a/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/glslang/MachineIndependent/preprocessor/PpScanner.cpp index cc7f277f..9da73d84 100644 --- a/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ b/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -190,23 +190,23 @@ int TPpContext::ScanFromString(char *s) /* * lFloatConst() - Scan a single- or double-precision floating point constant. Assumes that the scanner * has seen at least one digit, followed by either a decimal '.' or the -* letter 'e'. +* letter 'e', or a precision ending (e.g., F or LF). */ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp) { - int HasDecimal, declen, exp, ExpSign; + bool HasDecimalOrExponent = false; + int declen, exp, ExpSign; int str_len; int isDouble = 0; - HasDecimal = 0; declen = 0; exp = 0; str_len=len; if (ch == '.') { + HasDecimalOrExponent = true; str[len++]=ch; - HasDecimal = 1; ch = currentInput->getch(this, currentInput, yylvalpp); while (ch >= '0' && ch <= '9') { if (len < TPpToken::maxTokenLength) { @@ -217,7 +217,7 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp) } ch = currentInput->getch(this, currentInput, yylvalpp); } else { - parseContext.error(yylvalpp->loc,"float literal too long", "", ""); + parseContext.error(yylvalpp->loc, "float literal too long", "", ""); len = 1,str_len=1; } } @@ -226,8 +226,9 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp) // Exponent: if (ch == 'e' || ch == 'E') { + HasDecimalOrExponent = true; if (len >= TPpToken::maxTokenLength) { - parseContext.error(yylvalpp->loc,"float literal too long", "", ""); + parseContext.error(yylvalpp->loc, "float literal too long", "", ""); len = 1,str_len=1; } else { ExpSign = 1; @@ -248,12 +249,12 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp) str[len++]=ch; ch = currentInput->getch(this, currentInput, yylvalpp); } else { - parseContext.error(yylvalpp->loc,"float literal too long", "", ""); + parseContext.error(yylvalpp->loc, "float literal too long", "", ""); len = 1,str_len=1; } } } else { - parseContext.error(yylvalpp->loc,"bad character in float exponent", "", ""); + parseContext.error(yylvalpp->loc, "bad character in float exponent", "", ""); } exp *= ExpSign; } @@ -264,6 +265,8 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp) strcpy(str, "0.0"); } else { if (ch == 'l' || ch == 'L') { + if (! HasDecimalOrExponent) + parseContext.error(yylvalpp->loc, "float literal needs a decimal point or exponent", "", ""); int ch2 = currentInput->getch(this, currentInput, yylvalpp); if (ch2 != 'f' && ch2 != 'F') { currentInput->ungetch(this, currentInput, ch2, yylvalpp); @@ -274,15 +277,17 @@ int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * yylvalpp) str[len++] = ch2; isDouble = 1; } else { - parseContext.error(yylvalpp->loc,"float literal too long", "", ""); + parseContext.error(yylvalpp->loc, "float literal too long", "", ""); len = 1,str_len=1; } } } else if (ch == 'f' || ch == 'F') { + if (! HasDecimalOrExponent) + parseContext.error(yylvalpp->loc, "float literal needs a decimal point or exponent", "", ""); if (len < TPpToken::maxTokenLength) str[len++] = ch; else { - parseContext.error(yylvalpp->loc,"float literal too long", "", ""); + parseContext.error(yylvalpp->loc, "float literal too long", "", ""); len = 1,str_len=1; } } else @@ -351,13 +356,13 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) else ch = nextch; } else - pp->parseContext.error(yylvalpp->loc,"can only escape newlines", "\\", ""); + pp->parseContext.error(yylvalpp->loc, "can only escape newlines", "\\", ""); } else if (len < TPpToken::maxTokenLength) { tokenText[len++] = ch; ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); } else { if (! AlreadyComplained) { - pp->parseContext.error(yylvalpp->loc,"name too long", "", ""); + pp->parseContext.error(yylvalpp->loc, "name too long", "", ""); AlreadyComplained = 1; } ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); @@ -377,7 +382,9 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) yylvalpp->name[len++] = ch; ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); if (ch == 'x' || ch == 'X') { - int uint = 0; + // must be hexidecimal + + bool isUnsigned = false; yylvalpp->name[len++] = ch; ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); if ((ch >= '0' && ch <= '9') || @@ -395,11 +402,11 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) } else if (ch >= 'a' && ch <= 'f') { ii = ch - 'a' + 10; } else - pp->parseContext.error(yylvalpp->loc,"bad digit in hexidecimal literal", "", ""); + pp->parseContext.error(yylvalpp->loc, "bad digit in hexidecimal literal", "", ""); ival = (ival << 4) | ii; } else { if (! AlreadyComplained) { - pp->parseContext.error(yylvalpp->loc,"hexidecimal literal too big literal", "", ""); + pp->parseContext.error(yylvalpp->loc, "hexidecimal literal too big", "", ""); AlreadyComplained = 1; } ival = 0xffffffff; @@ -409,75 +416,98 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')); } else { - pp->parseContext.error(yylvalpp->loc,"bad digit in hexidecimal literal", "", ""); + pp->parseContext.error(yylvalpp->loc, "bad digit in hexidecimal literal", "", ""); } if (ch == 'u' || ch == 'U') { if (len < TPpToken::maxTokenLength) yylvalpp->name[len++] = ch; - uint = 1; + isUnsigned = true; } else pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp); yylvalpp->name[len] = '\0'; yylvalpp->ival = (int)ival; - if (uint) - return CPP_UINTCONSTANT; - else - return CPP_INTCONSTANT; - } else if (ch >= '0' && ch <= '7') { // octal integer constants - int uint = 0; - ival = 0; - do { - if (ival <= 0x1fffffff) { - yylvalpp->name[len++] = ch; - ii = ch - '0'; - ival = (ival << 3) | ii; - } else { - if (!AlreadyComplained) { - pp->parseContext.error(yylvalpp->loc,"octal literal too big", "", ""); - AlreadyComplained = 1; - } - ival = 0xffffffff; - } - ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); - } while (ch >= '0' && ch <= '7'); - if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') - return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp); - else if (ch == 'u' || ch == 'U') { - if (len < TPpToken::maxTokenLength) - yylvalpp->name[len++] = ch; - uint = 1; - } else - pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp); - yylvalpp->name[len] = '\0'; - yylvalpp->ival = (int)ival; - - if (uint) + if (isUnsigned) return CPP_UINTCONSTANT; else return CPP_INTCONSTANT; } else { - pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp); - ch = '0'; - } - // Fall through... - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - do { - if (len < TPpToken::maxTokenLength) { - if (len > 0 || ch != '0') { - yylvalpp->name[len] = ch; - len++; - } - } else { - if (! AlreadyComplained) { - pp->parseContext.error(yylvalpp->loc,"numeric literal too long", "", ""); + // could be octal integer or floating point, speculative pursue octal until it must be floating point + + bool isUnsigned = false; + bool octalOverflow = false; + bool nonOctal = false; + ival = 0; + + // see how much octal-like stuff we can read + while (ch >= '0' && ch <= '7') { + if (len < TPpToken::maxTokenLength) + yylvalpp->name[len++] = ch; + else if (! AlreadyComplained) { + pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", ""); AlreadyComplained = 1; } + if (ival <= 0x1fffffff) { + ii = ch - '0'; + ival = (ival << 3) | ii; + } else + octalOverflow = true; + ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); + } + + // could be part of a float... + if (ch == '8' || ch == '9') { + nonOctal = true; + do { + if (len < TPpToken::maxTokenLength) + yylvalpp->name[len++] = ch; + else if (! AlreadyComplained) { + pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", ""); + AlreadyComplained = 1; + } + ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); + } while (ch >= '0' && ch <= '9'); + } + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') + return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp); + + // wasn't a float, so must be octal... + if (nonOctal) + pp->parseContext.error(yylvalpp->loc, "octal literal digit too large", "", ""); + + if (ch == 'u' || ch == 'U') { + if (len < TPpToken::maxTokenLength) + yylvalpp->name[len++] = ch; + isUnsigned = true; + } else + pp->currentInput->ungetch(pp, pp->currentInput, ch, yylvalpp); + yylvalpp->name[len] = '\0'; + + if (octalOverflow) + pp->parseContext.error(yylvalpp->loc, "octal literal too big", "", ""); + + yylvalpp->ival = (int)ival; + + if (isUnsigned) + return CPP_UINTCONSTANT; + else + return CPP_INTCONSTANT; + } + break; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + // can't be hexidecimal or octal, is either decimal or floating point + + do { + if (len < TPpToken::maxTokenLength) + yylvalpp->name[len++] = ch; + else if (! AlreadyComplained) { + pp->parseContext.error(yylvalpp->loc, "numeric literal too long", "", ""); + AlreadyComplained = 1; } ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); } while (ch >= '0' && ch <= '9'); - if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') { + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') { return pp->lFloatConst(yylvalpp->name, len, ch, yylvalpp); } else { // Finish handling signed and unsigned integers @@ -495,7 +525,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) for (ii = 0; ii < numericLen; ii++) { ch = yylvalpp->name[ii] - '0'; if ((ival > 429496729) || (ival == 429496729 && ch >= 6)) { - pp->parseContext.error(yylvalpp->loc,"numeric literal too big", "", ""); + pp->parseContext.error(yylvalpp->loc, "numeric literal too big", "", ""); ival = -1; break; } else @@ -687,7 +717,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) if (ch == '\n') nlcount++; if (ch == EOF) { - pp->parseContext.error(yylvalpp->loc,"EOF in comment", "comment", ""); + pp->parseContext.error(yylvalpp->loc, "EOF in comment", "comment", ""); return EOF; } @@ -695,7 +725,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) } ch = pp->currentInput->getch(pp, pp->currentInput, yylvalpp); if (ch == EOF) { - pp->parseContext.error(yylvalpp->loc,"EOF in comment", "comment", ""); + pp->parseContext.error(yylvalpp->loc, "EOF in comment", "comment", ""); return EOF; } @@ -731,7 +761,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * yylvalpp) yylvalpp->atom = pp->LookUpAddString(&pp->atomTable, tokenText); return CPP_STRCONSTANT; } else { - pp->parseContext.error(yylvalpp->loc,"end of line in string", "string", ""); + pp->parseContext.error(yylvalpp->loc, "end of line in string", "string", ""); return CPP_ERROR_SY; } } @@ -756,7 +786,7 @@ const char* TPpContext::tokenize(TPpToken* yylvalpp) return 0; continue; } else { - parseContext.error(yylvalpp->loc,"preprocessor directive cannot be preceded by another token", "#", ""); + parseContext.error(yylvalpp->loc, "preprocessor directive cannot be preceded by another token", "#", ""); return 0; } }