diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/tests/preprocessor_tests/if_test.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/tests/preprocessor_tests/if_test.cpp | 1048 |
1 files changed, 1048 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/src/tests/preprocessor_tests/if_test.cpp b/Source/ThirdParty/ANGLE/src/tests/preprocessor_tests/if_test.cpp new file mode 100644 index 000000000..7940b564a --- /dev/null +++ b/Source/ThirdParty/ANGLE/src/tests/preprocessor_tests/if_test.cpp @@ -0,0 +1,1048 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "PreprocessorTest.h" +#include "compiler/preprocessor/Token.h" + +class IfTest : public PreprocessorTest +{ +}; + +TEST_F(IfTest, If_0) +{ + const char* str = "pass_1\n" + "#if 0\n" + "fail\n" + "#endif\n" + "pass_2\n"; + const char* expected = "pass_1\n" + "\n" + "\n" + "\n" + "pass_2\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_1) +{ + const char* str = "pass_1\n" + "#if 1\n" + "pass_2\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "pass_2\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_0_Else) +{ + const char* str = "pass_1\n" + "#if 0\n" + "fail\n" + "#else\n" + "pass_2\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_1_Else) +{ + const char* str = "pass_1\n" + "#if 1\n" + "pass_2\n" + "#else\n" + "fail\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_0_Elif) +{ + const char* str = "pass_1\n" + "#if 0\n" + "fail_1\n" + "#elif 0\n" + "fail_2\n" + "#elif 1\n" + "pass_2\n" + "#elif 1\n" + "fail_3\n" + "#else\n" + "fail_4\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_1_Elif) +{ + const char* str = "pass_1\n" + "#if 1\n" + "pass_2\n" + "#elif 0\n" + "fail_1\n" + "#elif 1\n" + "fail_2\n" + "#else\n" + "fail_4\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_Elif_Else) +{ + const char* str = "pass_1\n" + "#if 0\n" + "fail_1\n" + "#elif 0\n" + "fail_2\n" + "#elif 0\n" + "fail_3\n" + "#else\n" + "pass_2\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_0_Nested) +{ + const char* str = "pass_1\n" + "#if 0\n" + "fail_1\n" + "#if 1\n" + "fail_2\n" + "#else\n" + "fail_3\n" + "#endif\n" + "#else\n" + "pass_2\n" + "#endif\n" + "pass_3\n"; + const char* expected = "pass_1\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "pass_3\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, If_1_Nested) +{ + const char* str = "pass_1\n" + "#if 1\n" + "pass_2\n" + "#if 1\n" + "pass_3\n" + "#else\n" + "fail_1\n" + "#endif\n" + "#else\n" + "fail_2\n" + "#endif\n" + "pass_4\n"; + const char* expected = "pass_1\n" + "\n" + "pass_2\n" + "\n" + "pass_3\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_4\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorPrecedence) +{ + const char* str = "#if 1 + 2 * 3 + - (26 % 17 - + 4 / 2)\n" + "fail_1\n" + "#else\n" + "pass_1\n" + "#endif\n"; + const char* expected = "\n" + "\n" + "\n" + "pass_1\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorDefined) +{ + const char* str = "#if defined foo\n" + "fail_1\n" + "#else\n" + "pass_1\n" + "#endif\n" + "#define foo\n" + "#if defined(foo)\n" + "pass_2\n" + "#else\n" + "fail_2\n" + "#endif\n" + "#undef foo\n" + "#if defined ( foo ) \n" + "fail_3\n" + "#else\n" + "pass_3\n" + "#endif\n"; + const char* expected = "\n" + "\n" + "\n" + "pass_1\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_3\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorEQ) +{ + const char* str = "#if 4 - 1 == 2 + 1\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorNE) +{ + const char* str = "#if 1 != 2\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorLess) +{ + const char* str = "#if 1 < 2\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorGreater) +{ + const char* str = "#if 2 > 1\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorLE) +{ + const char* str = "#if 1 <= 2\n" + "pass_1\n" + "#else\n" + "fail_1\n" + "#endif\n" + "#if 2 <= 2\n" + "pass_2\n" + "#else\n" + "fail_2\n" + "#endif\n"; + const char* expected = "\n" + "pass_1\n" + "\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorGE) +{ + const char* str = "#if 2 >= 1\n" + "pass_1\n" + "#else\n" + "fail_1\n" + "#endif\n" + "#if 2 >= 2\n" + "pass_2\n" + "#else\n" + "fail_2\n" + "#endif\n"; + const char* expected = "\n" + "pass_1\n" + "\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorBitwiseOR) +{ + const char* str = "#if (0xaaaaaaaa | 0x55555555) == 0xffffffff\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorBitwiseAND) +{ + const char* str = "#if (0xaaaaaaa & 0x5555555) == 0\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorBitwiseXOR) +{ + const char* str = "#if (0xaaaaaaa ^ 0x5555555) == 0xfffffff\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorBitwiseComplement) +{ + const char* str = "#if (~ 0xdeadbeef) == -3735928560\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorLeft) +{ + const char* str = "#if (1 << 12) == 4096\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, OperatorRight) +{ + const char* str = "#if (31762 >> 8) == 124\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, ExpressionWithMacros) +{ + const char* str = "#define one 1\n" + "#define two 2\n" + "#define three 3\n" + "#if one + two == three\n" + "pass\n" + "#else\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "\n" + "\n" + "\n" + "pass\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, JunkInsideExcludedBlockIgnored) +{ + const char* str = "#if 0\n" + "foo !@#$%^&* .1bar\n" + "#foo\n" + "#if bar\n" + "fail\n" + "#endif\n" + "#else\n" + "pass\n" + "#endif\n"; + const char* expected = "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, Ifdef) +{ + const char* str = "#define foo\n" + "#ifdef foo\n" + "pass_1\n" + "#else\n" + "fail_1\n" + "#endif\n" + "#undef foo\n" + "#ifdef foo\n" + "fail_2\n" + "#else\n" + "pass_2\n" + "#endif\n"; + const char* expected = "\n" + "\n" + "pass_1\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, Ifndef) +{ + const char* str = "#define foo\n" + "#ifndef foo\n" + "fail_1\n" + "#else\n" + "pass_1\n" + "#endif\n" + "#undef foo\n" + "#ifndef foo\n" + "pass_2\n" + "#else\n" + "fail_2\n" + "#endif\n"; + const char* expected = "\n" + "\n" + "\n" + "\n" + "pass_1\n" + "\n" + "\n" + "\n" + "pass_2\n" + "\n" + "\n" + "\n"; + + preprocess(str, expected); +} + +TEST_F(IfTest, MissingExpression) +{ + const char* str = "#if\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_INVALID_EXPRESSION, + pp::SourceLocation(0, 1), + "syntax error")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, DivisionByZero) +{ + const char* str = "#if 1 / (3 - (1 + 2))\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_DIVISION_BY_ZERO, + pp::SourceLocation(0, 1), "1 / 0")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, ModuloByZero) +{ + const char* str = "#if 1 % (3 - (1 + 2))\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_DIVISION_BY_ZERO, + pp::SourceLocation(0, 1), "1 % 0")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, DecIntegerOverflow) +{ + const char* str = "#if 4294967296\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_INTEGER_OVERFLOW, + pp::SourceLocation(0, 1), "4294967296")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, OctIntegerOverflow) +{ + const char* str = "#if 077777777777\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_INTEGER_OVERFLOW, + pp::SourceLocation(0, 1), "077777777777")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, HexIntegerOverflow) +{ + const char* str = "#if 0xfffffffff\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_INTEGER_OVERFLOW, + pp::SourceLocation(0, 1), "0xfffffffff")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, UndefinedMacro) +{ + const char* str = "#if UNDEFINED\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 1), + "UNDEFINED")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, InvalidExpressionIgnoredForExcludedElif) +{ + const char* str = "#if 1\n" + "pass\n" + "#elif UNDEFINED\n" + "fail\n" + "#endif\n"; + const char* expected = "\n" + "pass\n" + "\n" + "\n" + "\n"; + + // No error or warning. + using testing::_; + EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0); + + preprocess(str, expected); +} + +TEST_F(IfTest, ElseWithoutIf) +{ + const char* str = "#else\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF, + pp::SourceLocation(0, 1), + "else")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, ElifWithoutIf) +{ + const char* str = "#elif 1\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF, + pp::SourceLocation(0, 1), + "elif")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, EndifWithoutIf) +{ + const char* str = "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF, + pp::SourceLocation(0, 1), + "endif")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, ElseAfterElse) +{ + const char* str = "#if 1\n" + "#else\n" + "#else\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE, + pp::SourceLocation(0, 3), + "else")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, ElifAfterElse) +{ + const char* str = "#if 1\n" + "#else\n" + "#elif 0\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE, + pp::SourceLocation(0, 3), + "elif")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, UnterminatedIf) +{ + const char* str = "#if 1\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED, + pp::SourceLocation(0, 1), + "if")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +TEST_F(IfTest, UnterminatedIfdef) +{ + const char* str = "#ifdef foo\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED, + pp::SourceLocation(0, 1), + "ifdef")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// The preprocessor only allows one expression to follow an #if directive. +// Supplying two integer expressions should be an error. +TEST_F(IfTest, ExtraIntExpression) +{ + const char *str = + "#if 1 1\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 1), "1")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// The preprocessor only allows one expression to follow an #if directive. +// Supplying two expressions where one uses a preprocessor define should be an error. +TEST_F(IfTest, ExtraIdentifierExpression) +{ + const char *str = + "#define one 1\n" + "#if 1 one\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "1")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Divide by zero that's not evaluated because of short-circuiting should not cause an error. +TEST_F(IfTest, ShortCircuitedDivideByZero) +{ + const char *str = + "#if 1 || (2 / 0)\n" + "pass\n" + "#endif\n"; + const char *expected = + "\n" + "pass\n" + "\n"; + + preprocess(str, expected); +} + +// Undefined identifier that's not evaluated because of short-circuiting should not cause an error. +TEST_F(IfTest, ShortCircuitedUndefined) +{ + const char *str = + "#if 1 || UNDEFINED\n" + "pass\n" + "#endif\n"; + const char *expected = + "\n" + "pass\n" + "\n"; + + preprocess(str, expected); +} + +// Defined operator produced by macro expansion has undefined behavior according to C++ spec, +// which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is +// needed for passing dEQP tests, which enforce stricter compatibility between implementations. +TEST_F(IfTest, DefinedOperatorValidAfterMacroExpansion) +{ + const char *str = + "#define foo defined\n" + "#if !foo bar\n" + "pass\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "defined")); + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "bar")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Defined operator produced by macro expansion has undefined behavior according to C++ spec, +// which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is +// needed for passing dEQP tests, which enforce stricter compatibility between implementations. +TEST_F(IfTest, UnterminatedDefinedInMacro) +{ + const char *str = + "#define foo defined(\n" + "#if foo\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "defined")); + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "(")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Defined operator produced by macro expansion has undefined behavior according to C++ spec, +// which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is +// needed for passing dEQP tests, which enforce stricter compatibility between implementations. +TEST_F(IfTest, UnterminatedDefinedInMacro2) +{ + const char *str = + "#define foo defined(bar\n" + "#if foo\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "defined")); + EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, + pp::SourceLocation(0, 2), "(")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Undefined shift: negative shift offset. +TEST_F(IfTest, BitShiftLeftOperatorNegativeOffset) +{ + const char *str = + "#if 2 << -1 == 1\n" + "foo\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 << -1")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Undefined shift: shift offset is out of range. +TEST_F(IfTest, BitShiftLeftOperatorOffset32) +{ + const char *str = + "#if 2 << 32 == 1\n" + "foo\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 << 32")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Left hand side of shift is negative. +TEST_F(IfTest, BitShiftLeftOperatorNegativeLHS) +{ + const char *str = + "#if (-2) << 1 == -4\n" + "pass\n" + "#endif\n"; + const char *expected = + "\n" + "pass\n" + "\n"; + + preprocess(str, expected); +} + +// Undefined shift: shift offset is out of range. +TEST_F(IfTest, BitShiftRightOperatorNegativeOffset) +{ + const char *str = + "#if 2 >> -1 == 4\n" + "foo\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 >> -1")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Undefined shift: shift offset is out of range. +TEST_F(IfTest, BitShiftRightOperatorOffset32) +{ + const char *str = + "#if 2 >> 32 == 0\n" + "foo\n" + "#endif\n"; + ASSERT_TRUE(mPreprocessor.init(1, &str, 0)); + + EXPECT_CALL(mDiagnostics, + print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 >> 32")); + + pp::Token token; + mPreprocessor.lex(&token); +} + +// Left hand side of shift is negative. +TEST_F(IfTest, BitShiftRightOperatorNegativeLHS) +{ + const char *str = + "#if (-2) >> 1 == 0x7fffffff\n" + "pass\n" + "#endif\n"; + const char *expected = + "\n" + "pass\n" + "\n"; + + preprocess(str, expected); +} |