1//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#include "PreprocessorTest.h"
8#include "Token.h"
9
10class IfTest : public PreprocessorTest
11{
12};
13
14TEST_F(IfTest, If_0)
15{
16    const char* str = "pass_1\n"
17                      "#if 0\n"
18                      "fail\n"
19                      "#endif\n"
20                      "pass_2\n";
21    const char* expected = "pass_1\n"
22                           "\n"
23                           "\n"
24                           "\n"
25                           "pass_2\n";
26
27    preprocess(str, expected);
28}
29
30TEST_F(IfTest, If_1)
31{
32    const char* str = "pass_1\n"
33                      "#if 1\n"
34                      "pass_2\n"
35                      "#endif\n"
36                      "pass_3\n";
37    const char* expected = "pass_1\n"
38                           "\n"
39                           "pass_2\n"
40                           "\n"
41                           "pass_3\n";
42
43    preprocess(str, expected);
44}
45
46TEST_F(IfTest, If_0_Else)
47{
48    const char* str = "pass_1\n"
49                      "#if 0\n"
50                      "fail\n"
51                      "#else\n"
52                      "pass_2\n"
53                      "#endif\n"
54                      "pass_3\n";
55    const char* expected = "pass_1\n"
56                           "\n"
57                           "\n"
58                           "\n"
59                           "pass_2\n"
60                           "\n"
61                           "pass_3\n";
62
63    preprocess(str, expected);
64}
65
66TEST_F(IfTest, If_1_Else)
67{
68    const char* str = "pass_1\n"
69                      "#if 1\n"
70                      "pass_2\n"
71                      "#else\n"
72                      "fail\n"
73                      "#endif\n"
74                      "pass_3\n";
75    const char* expected = "pass_1\n"
76                           "\n"
77                           "pass_2\n"
78                           "\n"
79                           "\n"
80                           "\n"
81                           "pass_3\n";
82
83    preprocess(str, expected);
84}
85
86TEST_F(IfTest, If_0_Elif)
87{
88    const char* str = "pass_1\n"
89                      "#if 0\n"
90                      "fail_1\n"
91                      "#elif 0\n"
92                      "fail_2\n"
93                      "#elif 1\n"
94                      "pass_2\n"
95                      "#elif 1\n"
96                      "fail_3\n"
97                      "#else\n"
98                      "fail_4\n"
99                      "#endif\n"
100                      "pass_3\n";
101    const char* expected = "pass_1\n"
102                           "\n"
103                           "\n"
104                           "\n"
105                           "\n"
106                           "\n"
107                           "pass_2\n"
108                           "\n"
109                           "\n"
110                           "\n"
111                           "\n"
112                           "\n"
113                           "pass_3\n";
114
115    preprocess(str, expected);
116}
117
118TEST_F(IfTest, If_1_Elif)
119{
120    const char* str = "pass_1\n"
121                      "#if 1\n"
122                      "pass_2\n"
123                      "#elif 0\n"
124                      "fail_1\n"
125                      "#elif 1\n"
126                      "fail_2\n"
127                      "#else\n"
128                      "fail_4\n"
129                      "#endif\n"
130                      "pass_3\n";
131    const char* expected = "pass_1\n"
132                           "\n"
133                           "pass_2\n"
134                           "\n"
135                           "\n"
136                           "\n"
137                           "\n"
138                           "\n"
139                           "\n"
140                           "\n"
141                           "pass_3\n";
142
143    preprocess(str, expected);
144}
145
146TEST_F(IfTest, If_Elif_Else)
147{
148    const char* str = "pass_1\n"
149                      "#if 0\n"
150                      "fail_1\n"
151                      "#elif 0\n"
152                      "fail_2\n"
153                      "#elif 0\n"
154                      "fail_3\n"
155                      "#else\n"
156                      "pass_2\n"
157                      "#endif\n"
158                      "pass_3\n";
159    const char* expected = "pass_1\n"
160                           "\n"
161                           "\n"
162                           "\n"
163                           "\n"
164                           "\n"
165                           "\n"
166                           "\n"
167                           "pass_2\n"
168                           "\n"
169                           "pass_3\n";
170
171    preprocess(str, expected);
172}
173
174TEST_F(IfTest, If_0_Nested)
175{
176    const char* str = "pass_1\n"
177                      "#if 0\n"
178                      "fail_1\n"
179                      "#if 1\n"
180                      "fail_2\n"
181                      "#else\n"
182                      "fail_3\n"
183                      "#endif\n"
184                      "#else\n"
185                      "pass_2\n"
186                      "#endif\n"
187                      "pass_3\n";
188    const char* expected = "pass_1\n"
189                           "\n"
190                           "\n"
191                           "\n"
192                           "\n"
193                           "\n"
194                           "\n"
195                           "\n"
196                           "\n"
197                           "pass_2\n"
198                           "\n"
199                           "pass_3\n";
200
201    preprocess(str, expected);
202}
203
204TEST_F(IfTest, If_1_Nested)
205{
206    const char* str = "pass_1\n"
207                      "#if 1\n"
208                      "pass_2\n"
209                      "#if 1\n"
210                      "pass_3\n"
211                      "#else\n"
212                      "fail_1\n"
213                      "#endif\n"
214                      "#else\n"
215                      "fail_2\n"
216                      "#endif\n"
217                      "pass_4\n";
218    const char* expected = "pass_1\n"
219                           "\n"
220                           "pass_2\n"
221                           "\n"
222                           "pass_3\n"
223                           "\n"
224                           "\n"
225                           "\n"
226                           "\n"
227                           "\n"
228                           "\n"
229                           "pass_4\n";
230
231    preprocess(str, expected);
232}
233
234TEST_F(IfTest, OperatorPrecedence)
235{
236    const char* str = "#if 1 + 2 * 3 + - (26 % 17 - + 4 / 2)\n"
237                      "fail_1\n"
238                      "#else\n"
239                      "pass_1\n"
240                      "#endif\n";
241    const char* expected = "\n"
242                           "\n"
243                           "\n"
244                           "pass_1\n"
245                           "\n";
246
247    preprocess(str, expected);
248}
249
250TEST_F(IfTest, OperatorDefined)
251{
252    const char* str = "#if defined foo\n"
253                      "fail_1\n"
254                      "#else\n"
255                      "pass_1\n"
256                      "#endif\n"
257                      "#define foo\n"
258                      "#if defined(foo)\n"
259                      "pass_2\n"
260                      "#else\n"
261                      "fail_2\n"
262                      "#endif\n"
263                      "#undef foo\n"
264                      "#if defined ( foo ) \n"
265                      "fail_3\n"
266                      "#else\n"
267                      "pass_3\n"
268                      "#endif\n";
269    const char* expected = "\n"
270                           "\n"
271                           "\n"
272                           "pass_1\n"
273                           "\n"
274                           "\n"
275                           "\n"
276                           "pass_2\n"
277                           "\n"
278                           "\n"
279                           "\n"
280                           "\n"
281                           "\n"
282                           "\n"
283                           "\n"
284                           "pass_3\n"
285                           "\n";
286
287    preprocess(str, expected);
288}
289
290TEST_F(IfTest, OperatorEQ)
291{
292    const char* str = "#if 4 - 1 == 2 + 1\n"
293                      "pass\n"
294                      "#else\n"
295                      "fail\n"
296                      "#endif\n";
297    const char* expected = "\n"
298                           "pass\n"
299                           "\n"
300                           "\n"
301                           "\n";
302
303    preprocess(str, expected);
304}
305
306TEST_F(IfTest, OperatorNE)
307{
308    const char* str = "#if 1 != 2\n"
309                      "pass\n"
310                      "#else\n"
311                      "fail\n"
312                      "#endif\n";
313    const char* expected = "\n"
314                           "pass\n"
315                           "\n"
316                           "\n"
317                           "\n";
318
319    preprocess(str, expected);
320}
321
322TEST_F(IfTest, OperatorLess)
323{
324    const char* str = "#if 1 < 2\n"
325                      "pass\n"
326                      "#else\n"
327                      "fail\n"
328                      "#endif\n";
329    const char* expected = "\n"
330                           "pass\n"
331                           "\n"
332                           "\n"
333                           "\n";
334
335    preprocess(str, expected);
336}
337
338TEST_F(IfTest, OperatorGreater)
339{
340    const char* str = "#if 2 > 1\n"
341                      "pass\n"
342                      "#else\n"
343                      "fail\n"
344                      "#endif\n";
345    const char* expected = "\n"
346                           "pass\n"
347                           "\n"
348                           "\n"
349                           "\n";
350
351    preprocess(str, expected);
352}
353
354TEST_F(IfTest, OperatorLE)
355{
356    const char* str = "#if 1 <= 2\n"
357                      "pass_1\n"
358                      "#else\n"
359                      "fail_1\n"
360                      "#endif\n"
361                      "#if 2 <= 2\n"
362                      "pass_2\n"
363                      "#else\n"
364                      "fail_2\n"
365                      "#endif\n";
366    const char* expected = "\n"
367                           "pass_1\n"
368                           "\n"
369                           "\n"
370                           "\n"
371                           "\n"
372                           "pass_2\n"
373                           "\n"
374                           "\n"
375                           "\n";
376
377    preprocess(str, expected);
378}
379
380TEST_F(IfTest, OperatorGE)
381{
382    const char* str = "#if 2 >= 1\n"
383                      "pass_1\n"
384                      "#else\n"
385                      "fail_1\n"
386                      "#endif\n"
387                      "#if 2 >= 2\n"
388                      "pass_2\n"
389                      "#else\n"
390                      "fail_2\n"
391                      "#endif\n";
392    const char* expected = "\n"
393                           "pass_1\n"
394                           "\n"
395                           "\n"
396                           "\n"
397                           "\n"
398                           "pass_2\n"
399                           "\n"
400                           "\n"
401                           "\n";
402
403    preprocess(str, expected);
404}
405
406TEST_F(IfTest, OperatorBitwiseOR)
407{
408    const char* str = "#if (0xaaaaaaaa | 0x55555555) == 0xffffffff\n"
409                      "pass\n"
410                      "#else\n"
411                      "fail\n"
412                      "#endif\n";
413    const char* expected = "\n"
414                           "pass\n"
415                           "\n"
416                           "\n"
417                           "\n";
418
419    preprocess(str, expected);
420}
421
422TEST_F(IfTest, OperatorBitwiseAND)
423{
424    const char* str = "#if (0xaaaaaaa & 0x5555555) == 0\n"
425                      "pass\n"
426                      "#else\n"
427                      "fail\n"
428                      "#endif\n";
429    const char* expected = "\n"
430                           "pass\n"
431                           "\n"
432                           "\n"
433                           "\n";
434
435    preprocess(str, expected);
436}
437
438TEST_F(IfTest, OperatorBitwiseXOR)
439{
440    const char* str = "#if (0xaaaaaaa ^ 0x5555555) == 0xfffffff\n"
441                      "pass\n"
442                      "#else\n"
443                      "fail\n"
444                      "#endif\n";
445    const char* expected = "\n"
446                           "pass\n"
447                           "\n"
448                           "\n"
449                           "\n";
450
451    preprocess(str, expected);
452}
453
454TEST_F(IfTest, OperatorBitwiseComplement)
455{
456    const char* str = "#if (~ 0xdeadbeef) == -3735928560\n"
457                      "pass\n"
458                      "#else\n"
459                      "fail\n"
460                      "#endif\n";
461    const char* expected = "\n"
462                           "pass\n"
463                           "\n"
464                           "\n"
465                           "\n";
466
467    preprocess(str, expected);
468}
469
470TEST_F(IfTest, OperatorLeft)
471{
472    const char* str = "#if (1 << 12) == 4096\n"
473                      "pass\n"
474                      "#else\n"
475                      "fail\n"
476                      "#endif\n";
477    const char* expected = "\n"
478                           "pass\n"
479                           "\n"
480                           "\n"
481                           "\n";
482
483    preprocess(str, expected);
484}
485
486TEST_F(IfTest, OperatorRight)
487{
488    const char* str = "#if (31762 >> 8) == 124\n"
489                      "pass\n"
490                      "#else\n"
491                      "fail\n"
492                      "#endif\n";
493    const char* expected = "\n"
494                           "pass\n"
495                           "\n"
496                           "\n"
497                           "\n";
498
499    preprocess(str, expected);
500}
501
502TEST_F(IfTest, ExpressionWithMacros)
503{
504    const char* str = "#define one 1\n"
505                      "#define two 2\n"
506                      "#define three 3\n"
507                      "#if one + two == three\n"
508                      "pass\n"
509                      "#else\n"
510                      "fail\n"
511                      "#endif\n";
512    const char* expected = "\n"
513                           "\n"
514                           "\n"
515                           "\n"
516                           "pass\n"
517                           "\n"
518                           "\n"
519                           "\n";
520
521    preprocess(str, expected);
522}
523
524TEST_F(IfTest, JunkInsideExcludedBlockIgnored)
525{
526    const char* str = "#if 0\n"
527                      "foo !@#$%^&* .1bar\n"
528                      "#foo\n"
529                      "#if bar\n"
530                      "fail\n"
531                      "#endif\n"
532                      "#else\n"
533                      "pass\n"
534                      "#endif\n";
535    const char* expected = "\n"
536                           "\n"
537                           "\n"
538                           "\n"
539                           "\n"
540                           "\n"
541                           "\n"
542                           "pass\n"
543                           "\n";
544
545    preprocess(str, expected);
546}
547
548TEST_F(IfTest, Ifdef)
549{
550    const char* str = "#define foo\n"
551                      "#ifdef foo\n"
552                      "pass_1\n"
553                      "#else\n"
554                      "fail_1\n"
555                      "#endif\n"
556                      "#undef foo\n"
557                      "#ifdef foo\n"
558                      "fail_2\n"
559                      "#else\n"
560                      "pass_2\n"
561                      "#endif\n";
562    const char* expected = "\n"
563                           "\n"
564                           "pass_1\n"
565                           "\n"
566                           "\n"
567                           "\n"
568                           "\n"
569                           "\n"
570                           "\n"
571                           "\n"
572                           "pass_2\n"
573                           "\n";
574
575    preprocess(str, expected);
576}
577
578TEST_F(IfTest, Ifndef)
579{
580    const char* str = "#define foo\n"
581                      "#ifndef foo\n"
582                      "fail_1\n"
583                      "#else\n"
584                      "pass_1\n"
585                      "#endif\n"
586                      "#undef foo\n"
587                      "#ifndef foo\n"
588                      "pass_2\n"
589                      "#else\n"
590                      "fail_2\n"
591                      "#endif\n";
592    const char* expected = "\n"
593                           "\n"
594                           "\n"
595                           "\n"
596                           "pass_1\n"
597                           "\n"
598                           "\n"
599                           "\n"
600                           "pass_2\n"
601                           "\n"
602                           "\n"
603                           "\n";
604
605    preprocess(str, expected);
606}
607
608TEST_F(IfTest, MissingExpression)
609{
610    const char* str = "#if\n"
611                      "#endif\n";
612    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
613
614    EXPECT_CALL(mDiagnostics,
615                print(pp::Diagnostics::PP_INVALID_EXPRESSION,
616                      pp::SourceLocation(0, 1),
617                      "syntax error"));
618
619    pp::Token token;
620    mPreprocessor.lex(&token);
621}
622
623TEST_F(IfTest, DivisionByZero)
624{
625    const char* str = "#if 1 / (3 - (1 + 2))\n"
626                      "#endif\n";
627    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
628
629    EXPECT_CALL(mDiagnostics,
630                print(pp::Diagnostics::PP_DIVISION_BY_ZERO,
631                      pp::SourceLocation(0, 1), "1 / 0"));
632
633    pp::Token token;
634    mPreprocessor.lex(&token);
635}
636
637TEST_F(IfTest, ModuloByZero)
638{
639    const char* str = "#if 1 % (3 - (1 + 2))\n"
640                      "#endif\n";
641    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
642
643    EXPECT_CALL(mDiagnostics,
644                print(pp::Diagnostics::PP_DIVISION_BY_ZERO,
645                      pp::SourceLocation(0, 1), "1 % 0"));
646
647    pp::Token token;
648    mPreprocessor.lex(&token);
649}
650
651TEST_F(IfTest, DecIntegerOverflow)
652{
653    const char* str = "#if 4294967296\n"
654                      "#endif\n";
655    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
656
657    EXPECT_CALL(mDiagnostics,
658                print(pp::Diagnostics::PP_INTEGER_OVERFLOW,
659                      pp::SourceLocation(0, 1), "4294967296"));
660
661    pp::Token token;
662    mPreprocessor.lex(&token);
663}
664
665TEST_F(IfTest, OctIntegerOverflow)
666{
667    const char* str = "#if 077777777777\n"
668                      "#endif\n";
669    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
670
671    EXPECT_CALL(mDiagnostics,
672                print(pp::Diagnostics::PP_INTEGER_OVERFLOW,
673                      pp::SourceLocation(0, 1), "077777777777"));
674
675    pp::Token token;
676    mPreprocessor.lex(&token);
677}
678
679TEST_F(IfTest, HexIntegerOverflow)
680{
681    const char* str = "#if 0xfffffffff\n"
682                      "#endif\n";
683    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
684
685    EXPECT_CALL(mDiagnostics,
686                print(pp::Diagnostics::PP_INTEGER_OVERFLOW,
687                      pp::SourceLocation(0, 1), "0xfffffffff"));
688
689    pp::Token token;
690    mPreprocessor.lex(&token);
691}
692
693TEST_F(IfTest, UndefinedMacro)
694{
695    const char* str = "#if UNDEFINED\n"
696                      "#endif\n";
697    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
698
699    EXPECT_CALL(mDiagnostics,
700                print(pp::Diagnostics::PP_INVALID_EXPRESSION,
701                      pp::SourceLocation(0, 1),
702                      "syntax error"));
703    EXPECT_CALL(mDiagnostics,
704                print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
705                      pp::SourceLocation(0, 1),
706                      "UNDEFINED"));
707
708    pp::Token token;
709    mPreprocessor.lex(&token);
710}
711
712TEST_F(IfTest, InvalidExpressionIgnoredForExcludedElif)
713{
714    const char* str = "#if 1\n"
715                      "pass\n"
716                      "#elif UNDEFINED\n"
717                      "fail\n"
718                      "#endif\n";
719    const char* expected = "\n"
720                           "pass\n"
721                           "\n"
722                           "\n"
723                           "\n";
724
725    // No error or warning.
726    using testing::_;
727    EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
728
729    preprocess(str, expected);
730}
731
732TEST_F(IfTest, ElseWithoutIf)
733{
734    const char* str = "#else\n";
735    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
736
737    EXPECT_CALL(mDiagnostics,
738                print(pp::Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
739                      pp::SourceLocation(0, 1),
740                      "else"));
741
742    pp::Token token;
743    mPreprocessor.lex(&token);
744}
745
746TEST_F(IfTest, ElifWithoutIf)
747{
748    const char* str = "#elif 1\n";
749    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
750
751    EXPECT_CALL(mDiagnostics,
752                print(pp::Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
753                      pp::SourceLocation(0, 1),
754                      "elif"));
755
756    pp::Token token;
757    mPreprocessor.lex(&token);
758}
759
760TEST_F(IfTest, EndifWithoutIf)
761{
762    const char* str = "#endif\n";
763    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
764
765    EXPECT_CALL(mDiagnostics,
766                print(pp::Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
767                      pp::SourceLocation(0, 1),
768                      "endif"));
769
770    pp::Token token;
771    mPreprocessor.lex(&token);
772}
773
774TEST_F(IfTest, ElseAfterElse)
775{
776    const char* str = "#if 1\n"
777                      "#else\n"
778                      "#else\n"
779                      "#endif\n";
780    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
781
782    EXPECT_CALL(mDiagnostics,
783                print(pp::Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
784                      pp::SourceLocation(0, 3),
785                      "else"));
786
787    pp::Token token;
788    mPreprocessor.lex(&token);
789}
790
791TEST_F(IfTest, ElifAfterElse)
792{
793    const char* str = "#if 1\n"
794                      "#else\n"
795                      "#elif 0\n"
796                      "#endif\n";
797    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
798
799    EXPECT_CALL(mDiagnostics,
800                print(pp::Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
801                      pp::SourceLocation(0, 3),
802                      "elif"));
803
804    pp::Token token;
805    mPreprocessor.lex(&token);
806}
807
808TEST_F(IfTest, UnterminatedIf)
809{
810    const char* str = "#if 1\n";
811    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
812
813    EXPECT_CALL(mDiagnostics,
814                print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED,
815                      pp::SourceLocation(0, 1),
816                      "if"));
817
818    pp::Token token;
819    mPreprocessor.lex(&token);
820}
821
822TEST_F(IfTest, UnterminatedIfdef)
823{
824    const char* str = "#ifdef foo\n";
825    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
826
827    EXPECT_CALL(mDiagnostics,
828                print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED,
829                      pp::SourceLocation(0, 1),
830                      "ifdef"));
831
832    pp::Token token;
833    mPreprocessor.lex(&token);
834}
835
836