diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/compiler/preprocessor/ExpressionParser.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/compiler/preprocessor/ExpressionParser.cpp | 555 |
1 files changed, 370 insertions, 185 deletions
diff --git a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/ExpressionParser.cpp b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/ExpressionParser.cpp index 1fae00945..a8df2351e 100644 --- a/Source/ThirdParty/ANGLE/src/compiler/preprocessor/ExpressionParser.cpp +++ b/Source/ThirdParty/ANGLE/src/compiler/preprocessor/ExpressionParser.cpp @@ -1,10 +1,10 @@ -/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of the BSD license. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* A Bison parser, made by GNU Bison 3.0.1. */ +/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of the BSD license. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +46,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.1" +#define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -88,7 +88,7 @@ #pragma GCC diagnostic ignored "-Wuninitialized" #endif #elif defined(_MSC_VER) -#pragma warning(disable: 4065 4701) +#pragma warning(disable: 4065 4244 4701 4702) #endif #include "ExpressionParser.h" @@ -101,17 +101,16 @@ #include <cassert> #include <sstream> +#include <stdint.h> #include "DiagnosticsBase.h" #include "Lexer.h" #include "Token.h" +#include "common/mathutil.h" + +typedef int32_t YYSTYPE; +typedef uint32_t UNSIGNED_TYPE; -#if defined(_MSC_VER) -typedef __int64 YYSTYPE; -#else -#include <stdint.h> -typedef intmax_t YYSTYPE; -#endif // _MSC_VER #define YYENABLE_NLS 0 #define YYLTYPE_IS_TRIVIAL 1 #define YYSTYPE_IS_TRIVIAL 1 @@ -124,6 +123,17 @@ struct Context pp::Lexer* lexer; pp::Token* token; int* result; + bool parsePresetToken; + + pp::ExpressionParser::ErrorSettings errorSettings; + bool *valid; + + void startIgnoreErrors() { ++ignoreErrors; } + void endIgnoreErrors() { --ignoreErrors; } + + bool isIgnoringErrors() { return ignoreErrors > 0; } + + int ignoreErrors; }; } // namespace @@ -164,15 +174,16 @@ extern int ppdebug; enum yytokentype { TOK_CONST_INT = 258, - TOK_OP_OR = 259, - TOK_OP_AND = 260, - TOK_OP_EQ = 261, - TOK_OP_NE = 262, - TOK_OP_LE = 263, - TOK_OP_GE = 264, - TOK_OP_LEFT = 265, - TOK_OP_RIGHT = 266, - TOK_UNARY = 267 + TOK_IDENTIFIER = 259, + TOK_OP_OR = 260, + TOK_OP_AND = 261, + TOK_OP_EQ = 262, + TOK_OP_NE = 263, + TOK_OP_LE = 264, + TOK_OP_GE = 265, + TOK_OP_LEFT = 266, + TOK_OP_RIGHT = 267, + TOK_UNARY = 268 }; #endif @@ -431,23 +442,23 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 14 +#define YYFINAL 15 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 175 +#define YYLAST 176 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 27 +#define YYNTOKENS 28 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 3 +#define YYNNTS 5 /* YYNRULES -- Number of rules. */ -#define YYNRULES 26 +#define YYNRULES 29 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 52 +#define YYNSTATES 55 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 267 +#define YYMAXUTOK 268 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -459,16 +470,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 23, 2, 2, 2, 21, 8, 2, - 25, 26, 19, 17, 2, 18, 2, 20, 2, 2, + 2, 2, 2, 24, 2, 2, 2, 22, 9, 2, + 26, 27, 20, 18, 2, 19, 2, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 11, 2, 12, 2, 2, 2, 2, 2, 2, 2, + 12, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 6, 2, 24, 2, 2, 2, + 2, 2, 2, 2, 7, 2, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -482,16 +493,16 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 9, 10, 13, 14, 15, 16, 22 + 5, 6, 10, 11, 14, 15, 16, 17, 23 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint8 yyrline[] = +static const yytype_uint16 yyrline[] = { - 0, 97, 97, 104, 105, 108, 111, 114, 117, 120, - 123, 126, 129, 132, 135, 138, 141, 144, 147, 150, - 163, 176, 179, 182, 185, 188, 191 + 0, 108, 108, 115, 116, 127, 127, 148, 148, 169, + 172, 175, 178, 181, 184, 187, 190, 193, 196, 221, + 246, 249, 252, 272, 299, 302, 305, 308, 320, 323 }; #endif @@ -500,11 +511,11 @@ static const yytype_uint8 yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_OP_OR", - "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_EQ", "TOK_OP_NE", "'<'", - "'>'", "TOK_OP_LE", "TOK_OP_GE", "TOK_OP_LEFT", "TOK_OP_RIGHT", "'+'", - "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('", "')'", - "$accept", "input", "expression", YY_NULLPTR + "$end", "error", "$undefined", "TOK_CONST_INT", "TOK_IDENTIFIER", + "TOK_OP_OR", "TOK_OP_AND", "'|'", "'^'", "'&'", "TOK_OP_EQ", "TOK_OP_NE", + "'<'", "'>'", "TOK_OP_LE", "TOK_OP_GE", "TOK_OP_LEFT", "TOK_OP_RIGHT", + "'+'", "'-'", "'*'", "'/'", "'%'", "TOK_UNARY", "'!'", "'~'", "'('", + "')'", "$accept", "input", "expression", "$@1", "$@2", YY_NULLPTR }; #endif @@ -513,16 +524,16 @@ static const char *const yytname[] = (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { - 0, 256, 257, 258, 259, 260, 124, 94, 38, 261, - 262, 60, 62, 263, 264, 265, 266, 43, 45, 42, - 47, 37, 267, 33, 126, 40, 41 + 0, 256, 257, 258, 259, 260, 261, 124, 94, 38, + 262, 263, 60, 62, 264, 265, 266, 267, 43, 45, + 42, 47, 37, 268, 33, 126, 40, 41 }; # endif -#define YYPACT_NINF -11 +#define YYPACT_NINF -12 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-11))) + (!!((Yystate) == (-12))) #define YYTABLE_NINF -1 @@ -533,12 +544,12 @@ static const yytype_uint16 yytoknum[] = STATE-NUM. */ static const yytype_int16 yypact[] = { - 46, -11, 46, 46, 46, 46, 46, 12, 68, -11, - -11, -11, -11, 27, -11, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, -11, 85, 101, 116, 130, 143, 154, - 154, -10, -10, -10, -10, 37, 37, 31, 31, -11, - -11, -11 + 31, -12, -12, 31, 31, 31, 31, 31, 51, 76, + -12, -12, -12, -12, 53, -12, -12, -12, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, -12, 31, 31, 124, 138, 26, + 149, 149, -11, -11, -11, -11, 154, 154, -8, -8, + -12, -12, -12, 93, 109 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -546,24 +557,24 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 3, 0, 0, 0, 0, 0, 0, 2, 25, - 24, 22, 23, 0, 1, 0, 0, 0, 0, 0, + 0, 3, 4, 0, 0, 0, 0, 0, 0, 2, + 28, 27, 25, 26, 0, 1, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 26, 4, 5, 6, 7, 8, 10, - 9, 14, 13, 12, 11, 16, 15, 18, 17, 21, - 20, 19 + 0, 0, 0, 0, 29, 0, 0, 9, 10, 11, + 13, 12, 17, 16, 15, 14, 19, 18, 21, 20, + 24, 23, 22, 6, 8 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -11, -11, -2 + -12, -12, -3, -12, -12 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 7, 8 + -1, 8, 9, 35, 36 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -571,74 +582,74 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { - 9, 10, 11, 12, 13, 26, 27, 28, 29, 30, - 31, 32, 14, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, - 30, 31, 32, 33, 28, 29, 30, 31, 32, 0, - 0, 0, 0, 2, 3, 0, 0, 0, 0, 4, - 5, 6, 15, 16, 17, 18, 19, 20, 21, 22, + 10, 11, 12, 13, 14, 27, 28, 29, 30, 31, + 32, 33, 31, 32, 33, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 0, 53, 54, 1, 2, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 3, + 4, 15, 0, 0, 0, 5, 6, 7, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 0, 0, 0, 0, + 34, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32 + 33, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 29, 30, 31, 32, 33 }; static const yytype_int8 yycheck[] = { - 2, 3, 4, 5, 6, 15, 16, 17, 18, 19, - 20, 21, 0, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 3, - 19, 20, 21, 26, 17, 18, 19, 20, 21, -1, - -1, -1, -1, 17, 18, -1, -1, -1, -1, 23, - 24, 25, 4, 5, 6, 7, 8, 9, 10, 11, + 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, + 21, 22, 20, 21, 22, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, -1, 35, 36, 3, 4, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 18, + 19, 0, -1, -1, -1, 24, 25, 26, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, -1, -1, -1, -1, + 27, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21 + 22, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 18, 19, 20, 21, 22 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 17, 18, 23, 24, 25, 28, 29, 29, - 29, 29, 29, 29, 0, 4, 5, 6, 7, 8, + 0, 3, 4, 18, 19, 24, 25, 26, 29, 30, + 30, 30, 30, 30, 30, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 26, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29 + 19, 20, 21, 22, 27, 31, 32, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 27, 28, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29 + 0, 28, 29, 30, 30, 31, 30, 32, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 1, 1, 3, 3, 3, 3, 3, 3, + 0, 2, 1, 1, 1, 0, 4, 0, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 2, 2, 2, 2, 3 + 3, 3, 3, 3, 3, 2, 2, 2, 2, 3 }; @@ -1332,7 +1343,15 @@ yyreduce: case 4: { - (yyval) = (yyvsp[-2]) || (yyvsp[0]); + if (!context->isIgnoringErrors()) + { + // This rule should be applied right after the token is lexed, so we can + // refer to context->token in the error message. + context->diagnostics->report(context->errorSettings.unexpectedIdentifier, + context->token->location, context->token->text); + *(context->valid) = false; + } + (yyval) = (yyvsp[0]); } break; @@ -1340,7 +1359,15 @@ yyreduce: case 5: { - (yyval) = (yyvsp[-2]) && (yyvsp[0]); + if ((yyvsp[-1]) != 0) + { + // Ignore errors in the short-circuited part of the expression. + // ESSL3.00 section 3.4: + // If an operand is not evaluated, the presence of undefined identifiers + // in the operand will not cause an error. + // Unevaluated division by zero should not cause an error either. + context->startIgnoreErrors(); + } } break; @@ -1348,7 +1375,15 @@ yyreduce: case 6: { - (yyval) = (yyvsp[-2]) | (yyvsp[0]); + if ((yyvsp[-3]) != 0) + { + context->endIgnoreErrors(); + (yyval) = static_cast<YYSTYPE>(1); + } + else + { + (yyval) = (yyvsp[-3]) || (yyvsp[0]); + } } break; @@ -1356,7 +1391,15 @@ yyreduce: case 7: { - (yyval) = (yyvsp[-2]) ^ (yyvsp[0]); + if ((yyvsp[-1]) == 0) + { + // Ignore errors in the short-circuited part of the expression. + // ESSL3.00 section 3.4: + // If an operand is not evaluated, the presence of undefined identifiers + // in the operand will not cause an error. + // Unevaluated division by zero should not cause an error either. + context->startIgnoreErrors(); + } } break; @@ -1364,7 +1407,15 @@ yyreduce: case 8: { - (yyval) = (yyvsp[-2]) & (yyvsp[0]); + if ((yyvsp[-3]) == 0) + { + context->endIgnoreErrors(); + (yyval) = static_cast<YYSTYPE>(0); + } + else + { + (yyval) = (yyvsp[-3]) && (yyvsp[0]); + } } break; @@ -1372,7 +1423,7 @@ yyreduce: case 9: { - (yyval) = (yyvsp[-2]) != (yyvsp[0]); + (yyval) = (yyvsp[-2]) | (yyvsp[0]); } break; @@ -1380,7 +1431,7 @@ yyreduce: case 10: { - (yyval) = (yyvsp[-2]) == (yyvsp[0]); + (yyval) = (yyvsp[-2]) ^ (yyvsp[0]); } break; @@ -1388,7 +1439,7 @@ yyreduce: case 11: { - (yyval) = (yyvsp[-2]) >= (yyvsp[0]); + (yyval) = (yyvsp[-2]) & (yyvsp[0]); } break; @@ -1396,7 +1447,7 @@ yyreduce: case 12: { - (yyval) = (yyvsp[-2]) <= (yyvsp[0]); + (yyval) = (yyvsp[-2]) != (yyvsp[0]); } break; @@ -1404,7 +1455,7 @@ yyreduce: case 13: { - (yyval) = (yyvsp[-2]) > (yyvsp[0]); + (yyval) = (yyvsp[-2]) == (yyvsp[0]); } break; @@ -1412,7 +1463,7 @@ yyreduce: case 14: { - (yyval) = (yyvsp[-2]) < (yyvsp[0]); + (yyval) = (yyvsp[-2]) >= (yyvsp[0]); } break; @@ -1420,7 +1471,7 @@ yyreduce: case 15: { - (yyval) = (yyvsp[-2]) >> (yyvsp[0]); + (yyval) = (yyvsp[-2]) <= (yyvsp[0]); } break; @@ -1428,7 +1479,7 @@ yyreduce: case 16: { - (yyval) = (yyvsp[-2]) << (yyvsp[0]); + (yyval) = (yyvsp[-2]) > (yyvsp[0]); } break; @@ -1436,7 +1487,7 @@ yyreduce: case 17: { - (yyval) = (yyvsp[-2]) - (yyvsp[0]); + (yyval) = (yyvsp[-2]) < (yyvsp[0]); } break; @@ -1444,7 +1495,29 @@ yyreduce: case 18: { - (yyval) = (yyvsp[-2]) + (yyvsp[0]); + if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31) + { + if (!context->isIgnoringErrors()) + { + std::ostringstream stream; + stream << (yyvsp[-2]) << " >> " << (yyvsp[0]); + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT, + context->token->location, + text.c_str()); + *(context->valid) = false; + } + (yyval) = static_cast<YYSTYPE>(0); + } + else if ((yyvsp[-2]) < 0) + { + // Logical shift right. + (yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) >> (yyvsp[0])); + } + else + { + (yyval) = (yyvsp[-2]) >> (yyvsp[0]); + } } break; @@ -1452,16 +1525,28 @@ yyreduce: case 19: { - if ((yyvsp[0]) == 0) { - std::ostringstream stream; - stream << (yyvsp[-2]) << " % " << (yyvsp[0]); - std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, - context->token->location, - text.c_str()); - YYABORT; - } else { - (yyval) = (yyvsp[-2]) % (yyvsp[0]); + if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31) + { + if (!context->isIgnoringErrors()) + { + std::ostringstream stream; + stream << (yyvsp[-2]) << " << " << (yyvsp[0]); + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT, + context->token->location, + text.c_str()); + *(context->valid) = false; + } + (yyval) = static_cast<YYSTYPE>(0); + } + else if ((yyvsp[-2]) < 0) + { + // Logical shift left. + (yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) << (yyvsp[0])); + } + else + { + (yyval) = (yyvsp[-2]) << (yyvsp[0]); } } @@ -1470,17 +1555,7 @@ yyreduce: case 20: { - if ((yyvsp[0]) == 0) { - std::ostringstream stream; - stream << (yyvsp[-2]) << " / " << (yyvsp[0]); - std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, - context->token->location, - text.c_str()); - YYABORT; - } else { - (yyval) = (yyvsp[-2]) / (yyvsp[0]); - } + (yyval) = gl::WrappingDiff<YYSTYPE>((yyvsp[-2]), (yyvsp[0])); } break; @@ -1488,7 +1563,7 @@ yyreduce: case 21: { - (yyval) = (yyvsp[-2]) * (yyvsp[0]); + (yyval) = gl::WrappingSum<YYSTYPE>((yyvsp[-2]), (yyvsp[0])); } break; @@ -1496,7 +1571,24 @@ yyreduce: case 22: { - (yyval) = ! (yyvsp[0]); + if ((yyvsp[0]) == 0) + { + if (!context->isIgnoringErrors()) + { + std::ostringstream stream; + stream << (yyvsp[-2]) << " % " << (yyvsp[0]); + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, + context->token->location, + text.c_str()); + *(context->valid) = false; + } + (yyval) = static_cast<YYSTYPE>(0); + } + else + { + (yyval) = (yyvsp[-2]) % (yyvsp[0]); + } } break; @@ -1504,7 +1596,31 @@ yyreduce: case 23: { - (yyval) = ~ (yyvsp[0]); + if ((yyvsp[0]) == 0) + { + if (!context->isIgnoringErrors()) + { + std::ostringstream stream; + stream << (yyvsp[-2]) << " / " << (yyvsp[0]); + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, + context->token->location, + text.c_str()); + *(context->valid) = false; + } + (yyval) = static_cast<YYSTYPE>(0); + } + else if ((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min() && (yyvsp[0]) == -1) + { + // Check for the special case where the minimum representable number is + // divided by -1. If left alone this leads to integer overflow in C++, which + // has undefined results. + (yyval) = std::numeric_limits<YYSTYPE>::max(); + } + else + { + (yyval) = (yyvsp[-2]) / (yyvsp[0]); + } } break; @@ -1512,7 +1628,7 @@ yyreduce: case 24: { - (yyval) = - (yyvsp[0]); + (yyval) = gl::WrappingMul((yyvsp[-2]), (yyvsp[0])); } break; @@ -1520,7 +1636,7 @@ yyreduce: case 25: { - (yyval) = + (yyvsp[0]); + (yyval) = ! (yyvsp[0]); } break; @@ -1528,6 +1644,39 @@ yyreduce: case 26: { + (yyval) = ~ (yyvsp[0]); + } + + break; + + case 27: + + { + // Check for negation of minimum representable integer to prevent undefined signed int + // overflow. + if ((yyvsp[0]) == std::numeric_limits<YYSTYPE>::min()) + { + (yyval) = std::numeric_limits<YYSTYPE>::min(); + } + else + { + (yyval) = -(yyvsp[0]); + } + } + + break; + + case 28: + + { + (yyval) = + (yyvsp[0]); + } + + break; + + case 29: + + { (yyval) = (yyvsp[-1]); } @@ -1765,79 +1914,115 @@ yyreturn: -int yylex(YYSTYPE* lvalp, Context* context) +int yylex(YYSTYPE *lvalp, Context *context) { + pp::Token *token = context->token; + if (!context->parsePresetToken) + { + context->lexer->lex(token); + } + context->parsePresetToken = false; + int type = 0; - pp::Token* token = context->token; switch (token->type) { - case pp::Token::CONST_INT: - { + case pp::Token::CONST_INT: { unsigned int val = 0; - if (!token->uValue(&val)) + int testVal = 0; + if (!token->uValue(&val) || (!token->iValue(&testVal) && + context->errorSettings.integerLiteralsMustFit32BitSignedRange)) { - context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, + context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); + *(context->valid) = false; } *lvalp = static_cast<YYSTYPE>(val); type = TOK_CONST_INT; break; } - case pp::Token::OP_OR: type = TOK_OP_OR; break; - case pp::Token::OP_AND: type = TOK_OP_AND; break; - case pp::Token::OP_NE: type = TOK_OP_NE; break; - case pp::Token::OP_EQ: type = TOK_OP_EQ; break; - case pp::Token::OP_GE: type = TOK_OP_GE; break; - case pp::Token::OP_LE: type = TOK_OP_LE; break; - case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break; - case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break; - case '|': type = '|'; break; - case '^': type = '^'; break; - case '&': type = '&'; break; - case '>': type = '>'; break; - case '<': type = '<'; break; - case '-': type = '-'; break; - case '+': type = '+'; break; - case '%': type = '%'; break; - case '/': type = '/'; break; - case '*': type = '*'; break; - case '!': type = '!'; break; - case '~': type = '~'; break; - case '(': type = '('; break; - case ')': type = ')'; break; + case pp::Token::IDENTIFIER: + *lvalp = static_cast<YYSTYPE>(-1); + type = TOK_IDENTIFIER; + break; + case pp::Token::OP_OR: + type = TOK_OP_OR; + break; + case pp::Token::OP_AND: + type = TOK_OP_AND; + break; + case pp::Token::OP_NE: + type = TOK_OP_NE; + break; + case pp::Token::OP_EQ: + type = TOK_OP_EQ; + break; + case pp::Token::OP_GE: + type = TOK_OP_GE; + break; + case pp::Token::OP_LE: + type = TOK_OP_LE; + break; + case pp::Token::OP_RIGHT: + type = TOK_OP_RIGHT; + break; + case pp::Token::OP_LEFT: + type = TOK_OP_LEFT; + break; + case '|': + case '^': + case '&': + case '>': + case '<': + case '-': + case '+': + case '%': + case '/': + case '*': + case '!': + case '~': + case '(': + case ')': + type = token->type; + break; - default: break; + default: + break; } - // Advance to the next token if the current one is valid. - if (type != 0) context->lexer->lex(token); - return type; } -void yyerror(Context* context, const char* reason) +void yyerror(Context *context, const char *reason) { - context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, + context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION, context->token->location, reason); } namespace pp { -ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) : - mLexer(lexer), - mDiagnostics(diagnostics) +ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics) + : mLexer(lexer), + mDiagnostics(diagnostics) { } -bool ExpressionParser::parse(Token* token, int* result) +bool ExpressionParser::parse(Token *token, + int *result, + bool parsePresetToken, + const ErrorSettings &errorSettings, + bool *valid) { Context context; context.diagnostics = mDiagnostics; context.lexer = mLexer; context.token = token; context.result = result; + context.ignoreErrors = 0; + context.parsePresetToken = parsePresetToken; + context.errorSettings = errorSettings; + context.valid = valid; int ret = yyparse(&context); switch (ret) { @@ -1846,12 +2031,12 @@ bool ExpressionParser::parse(Token* token, int* result) break; case 2: - mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); + mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, ""); break; default: assert(false); - mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); + mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, ""); break; } |