Mesa (master): glsl: Implement GLSL 1.30' s literal integer range restrictions.

Eric Anholt anholt at kemper.freedesktop.org
Fri Oct 28 19:04:16 UTC 2011


Module: Mesa
Branch: master
Commit: 687e4446bf5c5d3bc4a56ad4e9291a9cf2a2958c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=687e4446bf5c5d3bc4a56ad4e9291a9cf2a2958c

Author: Eric Anholt <eric at anholt.net>
Date:   Mon Oct  3 16:59:01 2011 -0700

glsl: Implement GLSL 1.30's literal integer range restrictions.

>From page 22 (28 of PDF) of GLSL 1.30 spec:
    It is an error to provide a literal integer whose magnitude is too
    large to store in a variable of matching signed or unsigned type.

    Unsigned integers have exactly 32 bits of precision.  Signed integers
    use 32 bits, including a sign bit, in two's complement form.

Fixes piglit int-literal-too-large-0[123].frag.

v2: Take care with INT_MIN, use stroull, and make it a function.

Reviewed-by: Paul Berry <stereotype441 at gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

---

 src/glsl/glsl_lexer.ll |   53 ++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
index cfd8926..e444536 100644
--- a/src/glsl/glsl_lexer.ll
+++ b/src/glsl/glsl_lexer.ll
@@ -22,6 +22,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 #include <ctype.h>
+#include <limits.h>
 #include "strtod.h"
 #include "ast.h"
 #include "glsl_parser_extras.h"
@@ -43,8 +44,6 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
 
 #define YY_USER_INIT yylineno = 0; yycolumn = 0;
 
-#define IS_UINT (yytext[yyleng - 1] == 'u' || yytext[yyleng - 1] == 'U')
-
 /* A macro for handling reserved words and keywords across language versions.
  *
  * Certain words start out as identifiers, become reserved words in
@@ -81,6 +80,47 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
  * ...means the word is a legal keyword in GLSL ES 1.00.
  */
 #define ES yyextra->es_shader
+
+static int
+literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state,
+		YYSTYPE *lval, YYLTYPE *lloc, int base)
+{
+   bool is_uint = (text[len - 1] == 'u' ||
+		   text[len - 1] == 'U');
+   const char *digits = text;
+
+   /* Skip "0x" */
+   if (base == 16)
+      digits += 2;
+
+   unsigned long long value = strtoull(digits, NULL, base);
+
+   lval->n = (int)value;
+
+   if (value > UINT_MAX) {
+      /* Note that signed 0xffffffff is valid, not out of range! */
+      if (state->language_version >= 130) {
+	 _mesa_glsl_error(lloc, state,
+			  "Literal value `%s' out of range", text);
+      } else {
+	 _mesa_glsl_warning(lloc, state,
+			    "Literal value `%s' out of range", text);
+      }
+   } else if (base == 10 && !is_uint && (unsigned)value > (unsigned)INT_MAX + 1) {
+      /* Tries to catch unintentionally providing a negative value.
+       * Note that -2147483648 is parsed as -(2147483648), so we don't
+       * want to warn for INT_MAX.
+       */
+      _mesa_glsl_warning(lloc, state,
+			 "Signed literal value `%s' is interpreted as %d",
+			 text, lval->n);
+   }
+   return is_uint ? UINTCONSTANT : INTCONSTANT;
+}
+
+#define LITERAL_INTEGER(base) \
+   literal_integer(yytext, yyleng, yyextra, yylval, yylloc, base)
+
 %}
 
 %option bison-bridge bison-locations reentrant noyywrap
@@ -292,16 +332,13 @@ layout		{
 -=		return SUB_ASSIGN;
 
 [1-9][0-9]*[uU]?	{
-			    yylval->n = strtol(yytext, NULL, 10);
-			    return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+			    return LITERAL_INTEGER(10);
 			}
 0[xX][0-9a-fA-F]+[uU]?	{
-			    yylval->n = strtol(yytext + 2, NULL, 16);
-			    return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+			    return LITERAL_INTEGER(16);
 			}
 0[0-7]*[uU]?		{
-			    yylval->n = strtol(yytext, NULL, 8);
-			    return IS_UINT ? UINTCONSTANT : INTCONSTANT;
+			    return LITERAL_INTEGER(8);
 			}
 
 [0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]?	{




More information about the mesa-commit mailing list