summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/tests/preprocessor_tests/define_test.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /gfx/angle/src/tests/preprocessor_tests/define_test.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/angle/src/tests/preprocessor_tests/define_test.cpp')
-rwxr-xr-xgfx/angle/src/tests/preprocessor_tests/define_test.cpp988
1 files changed, 988 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/preprocessor_tests/define_test.cpp b/gfx/angle/src/tests/preprocessor_tests/define_test.cpp
new file mode 100755
index 000000000..e074d1982
--- /dev/null
+++ b/gfx/angle/src/tests/preprocessor_tests/define_test.cpp
@@ -0,0 +1,988 @@
+//
+// 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"
+
+using testing::_;
+
+class DefineTest : public PreprocessorTest
+{
+};
+
+TEST_F(DefineTest, NonIdentifier)
+{
+ const char* input = "#define 2 foo\n"
+ "2\n";
+ const char* expected = "\n"
+ "2\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_UNEXPECTED_TOKEN,
+ pp::SourceLocation(0, 1),
+ "2"));
+
+ preprocess(input, expected);
+};
+
+TEST_F(DefineTest, RedefinePredefined)
+{
+ const char* input = "#define __LINE__ 10\n"
+ "__LINE__\n"
+ "#define __FILE__ 20\n"
+ "__FILE__\n"
+ "#define __VERSION__ 200\n"
+ "__VERSION__\n"
+ "#define GL_ES 0\n"
+ "GL_ES\n";
+ const char* expected = "\n"
+ "2\n"
+ "\n"
+ "0\n"
+ "\n"
+ "100\n"
+ "\n"
+ "1\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+ pp::SourceLocation(0, 1),
+ "__LINE__"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+ pp::SourceLocation(0, 3),
+ "__FILE__"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+ pp::SourceLocation(0, 5),
+ "__VERSION__"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
+ pp::SourceLocation(0, 7),
+ "GL_ES"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ReservedUnderScore1)
+{
+ const char* input = "#define __foo bar\n"
+ "__foo\n";
+ const char* expected = "\n"
+ "bar\n";
+
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_WARNING_MACRO_NAME_RESERVED,
+ pp::SourceLocation(0, 1), "__foo"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ReservedUnderScore2)
+{
+ const char* input = "#define foo__bar baz\n"
+ "foo__bar\n";
+ const char* expected = "\n"
+ "baz\n";
+
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_WARNING_MACRO_NAME_RESERVED,
+ pp::SourceLocation(0, 1), "foo__bar"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ReservedGL)
+{
+ const char* input = "#define GL_foo bar\n"
+ "GL_foo\n";
+ const char* expected = "\n"
+ "GL_foo\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_NAME_RESERVED,
+ pp::SourceLocation(0, 1),
+ "GL_foo"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjRedefineValid)
+{
+ const char* input = "#define foo (1-1)\n"
+ "#define foo /* whitespace */ (1-1) /* other */ \n"
+ "foo\n";
+ const char* expected = "\n"
+ "\n"
+ "(1-1)\n";
+ // No error or warning.
+ using testing::_;
+ EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjRedefineInvalid)
+{
+ const char* input = "#define foo (0)\n"
+ "#define foo (1-1)\n"
+ "foo\n";
+ const char* expected = "\n"
+ "\n"
+ "(0)\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_REDEFINED,
+ pp::SourceLocation(0, 2),
+ "foo"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncRedefineValid)
+{
+ const char* input = "#define foo(a) ( a )\n"
+ "#define foo( a )( /* whitespace */ a /* other */ )\n"
+ "foo(b)\n";
+ const char* expected = "\n"
+ "\n"
+ "( b )\n";
+ // No error or warning.
+ using testing::_;
+ EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncRedefineInvalid)
+{
+ const char* input = "#define foo(b) ( a )\n"
+ "#define foo(b) ( b )\n"
+ "foo(1)\n";
+ const char* expected = "\n"
+ "\n"
+ "( a )\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_REDEFINED,
+ pp::SourceLocation(0, 2),
+ "foo"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjBasic)
+{
+ const char* input = "#define foo 1\n"
+ "foo\n";
+ const char* expected = "\n"
+ "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjEmpty)
+{
+ const char* input = "#define foo\n"
+ "foo\n";
+ const char* expected = "\n"
+ "\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjChain)
+{
+ const char* input = "#define foo 1\n"
+ "#define bar foo\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjChainReverse)
+{
+ const char* input = "#define bar foo\n"
+ "#define foo 1\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjRecursive)
+{
+ const char* input = "#define foo bar\n"
+ "#define bar baz\n"
+ "#define baz foo\n"
+ "foo\n"
+ "bar\n"
+ "baz\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "foo\n"
+ "bar\n"
+ "baz\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjCompositeChain)
+{
+ const char* input = "#define foo 1\n"
+ "#define bar a foo\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "a 1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjCompositeChainReverse)
+{
+ const char* input = "#define bar a foo\n"
+ "#define foo 1\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "a 1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjCompositeRecursive)
+{
+ const char* input = "#define foo a bar\n"
+ "#define bar b baz\n"
+ "#define baz c foo\n"
+ "foo\n"
+ "bar\n"
+ "baz\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "a b c foo\n"
+ "b c a bar\n"
+ "c a b baz\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjChainSelfRecursive)
+{
+ const char* input = "#define foo foo\n"
+ "#define bar foo\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "foo\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjectLikeWithParens)
+{
+ const char* input = "#define foo ()1\n"
+ "foo()\n"
+ "#define bar ()2\n"
+ "bar()\n";
+ const char* expected = "\n"
+ "()1()\n"
+ "\n"
+ "()2()\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncEmpty)
+{
+ const char* input = "#define foo()\n"
+ "foo()\n";
+ const char* expected = "\n"
+ "\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncNoArgs)
+{
+ const char* input = "#define foo() bar\n"
+ "foo()\n";
+ const char* expected = "\n"
+ "bar\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncOneArgUnused)
+{
+ const char* input = "#define foo(x) 1\n"
+ "foo(bar)\n";
+ const char* expected = "\n"
+ "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncTwoArgsUnused)
+{
+ const char* input = "#define foo(x,y) 1\n"
+ "foo(bar,baz)\n";
+ const char* expected = "\n"
+ "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncOneArg)
+{
+ const char* input = "#define foo(x) ((x)+1)\n"
+ "foo(bar)\n";
+ const char* expected = "\n"
+ "((bar)+1)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncTwoArgs)
+{
+ const char* input = "#define foo(x,y) ((x)*(y))\n"
+ "foo(bar,baz)\n";
+ const char* expected = "\n"
+ "((bar)*(baz))\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncEmptyArgs)
+{
+ const char* input = "#define zero() pass\n"
+ "#define one(x) pass\n"
+ "#define two(x,y) pass\n"
+ "zero()\n"
+ "one()\n"
+ "two(,)\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "pass\n"
+ "pass\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncMacroAsParam)
+{
+ const char* input = "#define x 0\n"
+ "#define foo(x) x\n"
+ "foo(1)\n";
+ const char* expected = "\n"
+ "\n"
+ "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncOneArgMulti)
+{
+ const char* input = "#define foo(x) (x)\n"
+ "foo(this is a multi-word argument)\n";
+ const char* expected = "\n"
+ "(this is a multi-word argument)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncTwoArgsMulti)
+{
+ const char* input = "#define foo(x,y) x,two fish,red fish,y\n"
+ "foo(one fish, blue fish)\n";
+ const char* expected = "\n"
+ "one fish,two fish,red fish,blue fish\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncCompose)
+{
+ const char* input = "#define bar(x) (1+(x))\n"
+ "#define foo(y) (2*(y))\n"
+ "foo(bar(3))\n";
+ const char* expected = "\n"
+ "\n"
+ "(2*((1+(3))))\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncArgWithParens)
+{
+ const char* input = "#define foo(x) (x)\n"
+ "foo(argument(with parens) FTW)\n";
+ const char* expected = "\n"
+ "(argument(with parens) FTW)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncMacroAsNonMacro)
+{
+ const char* input = "#define foo(bar) bar\n"
+ "foo bar\n";
+ const char* expected = "\n"
+ "foo bar\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncExtraNewlines)
+{
+ const char* input = "#define foo(a) (a)\n"
+ "foo\n"
+ "(\n"
+ "1\n"
+ ")\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "\n"
+ "(1)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFunc)
+{
+ const char* input = "#define foo() pass\n"
+ "#define bar foo()\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToNonFunc)
+{
+ const char* input = "#define pass() fail\n"
+ "#define bar pass\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncWithArgs)
+{
+ const char* input = "#define foo(fail) fail\n"
+ "#define bar foo(pass)\n"
+ "bar\n";
+ const char* expected = "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncCompose)
+{
+ const char* input = "#define baz(fail) fail\n"
+ "#define bar(fail) fail\n"
+ "#define foo bar(baz(pass))\n"
+ "foo\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncParensInText1)
+{
+ const char* input = "#define fail() pass\n"
+ "#define foo fail\n"
+ "foo()\n";
+ const char* expected = "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncParensInText2)
+{
+ const char* input = "#define bar with,embedded,commas\n"
+ "#define func(x) pass\n"
+ "#define foo func\n"
+ "foo(bar)\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainObjToFuncMultiLevel)
+{
+ const char* input = "#define foo(x) pass\n"
+ "#define bar foo\n"
+ "#define baz bar\n"
+ "#define joe baz\n"
+ "joe (fail)\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ObjToFuncRecursive)
+{
+ const char* input = "#define A(a,b) B(a,b)\n"
+ "#define C A(0,C)\n"
+ "C\n";
+ const char* expected = "\n"
+ "\n"
+ "B(0,C)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, ChainFuncToFuncCompose)
+{
+ const char* input = "#define baz(fail) fail\n"
+ "#define bar(fail) fail\n"
+ "#define foo() bar(baz(pass))\n"
+ "foo()\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfRecursive)
+{
+ const char* input = "#define foo(a) foo(2*(a))\n"
+ "foo(3)\n";
+ const char* expected = "\n"
+ "foo(2*(3))\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfCompose)
+{
+ const char* input = "#define foo(a) foo(2*(a))\n"
+ "foo(foo(3))\n";
+ const char* expected = "\n"
+ "foo(2*(foo(2*(3))))\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfComposeNonFunc)
+{
+ const char* input = "#define foo(bar) bar\n"
+ "foo(foo)\n";
+ const char* expected = "\n"
+ "foo\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncSelfComposeNonFuncMultiTokenArg)
+{
+ const char* input = "#define foo(bar) bar\n"
+ "foo(1+foo)\n";
+ const char* expected = "\n"
+ "1+foo\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FinalizeUnexpandedMacro)
+{
+ const char* input = "#define expand(x) expand(x once)\n"
+ "#define foo(x) x\n"
+ "foo(expand(just))\n";
+ const char* expected = "\n"
+ "\n"
+ "expand(just once)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncArgWithCommas)
+{
+ const char* input = "#define foo(x) pass\n"
+ "foo(argument (with,embedded, commas) -- baz)\n";
+ const char* expected = "\n"
+ "pass\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncArgObjMaroWithComma)
+{
+ const char* input = "#define foo(a) (a)\n"
+ "#define bar two,words\n"
+ "foo(bar)\n";
+ const char* expected = "\n"
+ "\n"
+ "(two,words)\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncLeftParenInMacroRightParenInText)
+{
+ const char* input = "#define bar(a) a*2\n"
+ "#define foo bar(\n"
+ "foo b)\n";
+ const char* expected = "\n"
+ "\n"
+ "b*2\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, RepeatedArg)
+{
+ const char* input = "#define double(x) x x\n"
+ "double(1)\n";
+ const char* expected = "\n"
+ "1 1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncMissingRightParen)
+{
+ const char* input = "#define foo(x) (2*(x))\n"
+ "foo(3\n";
+ const char* expected = "\n"
+ "\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION,
+ pp::SourceLocation(0, 2),
+ "foo"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, FuncIncorrectArgCount)
+{
+ const char* input = "#define foo(x,y) ((x)+(y))\n"
+ "foo()\n"
+ "foo(1)\n"
+ "foo(1,2,3)\n";
+ const char* expected = "\n"
+ "\n"
+ "\n"
+ "\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_TOO_FEW_ARGS,
+ pp::SourceLocation(0, 2),
+ "foo"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_TOO_FEW_ARGS,
+ pp::SourceLocation(0, 3),
+ "foo"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_TOO_MANY_ARGS,
+ pp::SourceLocation(0, 4),
+ "foo"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Undef)
+{
+ const char* input = "#define foo 1\n"
+ "foo\n"
+ "#undef foo\n"
+ "foo\n";
+ const char* expected = "\n"
+ "1\n"
+ "\n"
+ "foo\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, UndefPredefined)
+{
+ const char* input = "#undef __LINE__\n"
+ "__LINE__\n"
+ "#undef __FILE__\n"
+ "__FILE__\n"
+ "#undef __VERSION__\n"
+ "__VERSION__\n"
+ "#undef GL_ES\n"
+ "GL_ES\n";
+ const char* expected = "\n"
+ "2\n"
+ "\n"
+ "0\n"
+ "\n"
+ "100\n"
+ "\n"
+ "1\n";
+
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+ pp::SourceLocation(0, 1),
+ "__LINE__"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+ pp::SourceLocation(0, 3),
+ "__FILE__"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+ pp::SourceLocation(0, 5),
+ "__VERSION__"));
+ EXPECT_CALL(mDiagnostics,
+ print(pp::Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
+ pp::SourceLocation(0, 7),
+ "GL_ES"));
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, UndefRedefine)
+{
+ const char* input = "#define foo 1\n"
+ "foo\n"
+ "#undef foo\n"
+ "foo\n"
+ "#define foo 2\n"
+ "foo\n";
+ const char* expected = "\n"
+ "1\n"
+ "\n"
+ "foo\n"
+ "\n"
+ "2\n";
+
+ preprocess(input, expected);
+}
+
+// Example from C99 standard section 6.10.3.5 Scope of macro definitions
+TEST_F(DefineTest, C99Example)
+{
+ const char* input =
+ "#define x 3 \n"
+ "#define f(a) f(x * (a)) \n"
+ "#undef x \n"
+ "#define x 2 \n"
+ "#define g f \n"
+ "#define z z[0] \n"
+ "#define h g(~ \n"
+ "#define m(a) a(w) \n"
+ "#define w 0,1 \n"
+ "#define t(a) a \n"
+ "#define p() int \n"
+ "#define q(x) x \n"
+ " \n"
+ "f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n"
+ "g(x+(3,4)-w) | h 5) & m\n"
+ " (f)^m(m);\n"
+ "p() i[q()] = { q(1), 23, 4, 5, };\n";
+ const char* expected =
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);\n"
+ "f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) &\n"
+ " f(2 * (0,1))^m(0,1);\n"
+ "int i[] = { 1, 23, 4, 5, };\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Predefined_GL_ES)
+{
+ const char* input = "GL_ES\n";
+ const char* expected = "1\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Predefined_VERSION)
+{
+ const char* input = "__VERSION__\n";
+ const char* expected = "100\n";
+
+ preprocess(input, expected);
+}
+
+TEST_F(DefineTest, Predefined_LINE1)
+{
+ const char* str = "\n\n__LINE__";
+ ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
+ pp::Token token;
+ mPreprocessor.lex(&token);
+ EXPECT_EQ(pp::Token::CONST_INT, token.type);
+ EXPECT_EQ("3", token.text);
+}
+
+TEST_F(DefineTest, Predefined_LINE2)
+{
+ const char* str = "#line 10\n"
+ "__LINE__\n";
+ ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
+ pp::Token token;
+ mPreprocessor.lex(&token);
+ EXPECT_EQ(pp::Token::CONST_INT, token.type);
+ EXPECT_EQ("10", token.text);
+}
+
+TEST_F(DefineTest, Predefined_FILE1)
+{
+ const char* const str[] = {"", "", "__FILE__"};
+ ASSERT_TRUE(mPreprocessor.init(3, str, NULL));
+
+ pp::Token token;
+ mPreprocessor.lex(&token);
+ EXPECT_EQ(pp::Token::CONST_INT, token.type);
+ EXPECT_EQ("2", token.text);
+}
+
+TEST_F(DefineTest, Predefined_FILE2)
+{
+ const char* const str[] = {"#line 10 20\n", "__FILE__"};
+ ASSERT_TRUE(mPreprocessor.init(2, str, NULL));
+
+ pp::Token token;
+ mPreprocessor.lex(&token);
+ EXPECT_EQ(pp::Token::CONST_INT, token.type);
+ EXPECT_EQ("21", token.text);
+}
+
+// Defined operator produced by macro expansion should be parsed inside #if directives
+TEST_F(DefineTest, ExpandedDefinedParsedInsideIf)
+{
+ const char *input =
+ "#define bar 1\n"
+ "#define foo defined(bar)\n"
+ "#if foo\n"
+ "bar\n"
+ "#endif\n";
+ const char *expected =
+ "\n"
+ "\n"
+ "\n"
+ "1\n"
+ "\n";
+ preprocess(input, expected);
+}
+
+// Defined operator produced by macro expansion should not be parsed outside #if directives
+TEST_F(DefineTest, ExpandedDefinedNotParsedOutsideIf)
+{
+ const char *input =
+ "#define foo defined(bar)\n"
+ "foo\n";
+ const char *expected =
+ "\n"
+ "defined(bar)\n";
+ preprocess(input, expected);
+}
+
+// Test that line directive expressions give errors on negative or undefined shifts.
+TEST_F(DefineTest, NegativeShiftInLineDirective)
+{
+ const char *input =
+ "#line 1 << -1\n"
+ "#line 1 >> -1\n"
+ "#line 1 << x\n"
+ "#line 1 >> x\n";
+ const char *expected =
+ "\n"
+ "\n"
+ "\n"
+ "\n";
+
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_UNDEFINED_SHIFT, _, _)).Times(4);
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_LINE_NUMBER, _, _)).Times(2);
+ preprocess(input, expected);
+}
+
+// Undefining a macro in its invocation parameters produces and error
+TEST_F(DefineTest, UndefineInInvocation)
+{
+ const char *input =
+ "#define G(a, b) a b\n"
+ "G(\n"
+ "#undef G\n"
+ "1, 2)\n";
+ const char *expected = "\n\n\n1 2\n";
+
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED,
+ pp::SourceLocation(0, 3), _));
+
+ preprocess(input, expected);
+}
+
+// Undefining a macro before its invocation parameters produces and error
+TEST_F(DefineTest, UndefineInInvocationPreLParen)
+{
+ const char *input =
+ "#define G(a, b) a b\n"
+ "G\n"
+ "#undef G\n"
+ "(1, 2)\n";
+ const char *expected = "\n\n\n1 2\n";
+
+ EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED,
+ pp::SourceLocation(0, 3), _));
+
+ preprocess(input, expected);
+}
+
+// The name of the macro "a" is inside an incomplete macro invocation of macro "m()" in its own
+// expansion. This should not result in infinite recursion.
+TEST_F(DefineTest, RecursiveMacroNameInsideIncompleteMacroInvocationInMacroExpansion)
+{
+ const char *input =
+ "#define m(a)\n"
+ "#define a m((a)\n"
+ "a)\n";
+ const char *expected =
+ "\n"
+ "\n"
+ "\n";
+ preprocess(input, expected);
+}