1 //
2 // Copyright 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 "compiler/preprocessor/Token.h"
9
10 namespace angle
11 {
12
13 class IfTest : public SimplePreprocessorTest
14 {};
15
TEST_F(IfTest,If_0)16 TEST_F(IfTest, If_0)
17 {
18 const char *str =
19 "pass_1\n"
20 "#if 0\n"
21 "fail\n"
22 "#endif\n"
23 "pass_2\n";
24 const char *expected =
25 "pass_1\n"
26 "\n"
27 "\n"
28 "\n"
29 "pass_2\n";
30
31 preprocess(str, expected);
32 }
33
TEST_F(IfTest,If_1)34 TEST_F(IfTest, If_1)
35 {
36 const char *str =
37 "pass_1\n"
38 "#if 1\n"
39 "pass_2\n"
40 "#endif\n"
41 "pass_3\n";
42 const char *expected =
43 "pass_1\n"
44 "\n"
45 "pass_2\n"
46 "\n"
47 "pass_3\n";
48
49 preprocess(str, expected);
50 }
51
TEST_F(IfTest,If_0_Else)52 TEST_F(IfTest, If_0_Else)
53 {
54 const char *str =
55 "pass_1\n"
56 "#if 0\n"
57 "fail\n"
58 "#else\n"
59 "pass_2\n"
60 "#endif\n"
61 "pass_3\n";
62 const char *expected =
63 "pass_1\n"
64 "\n"
65 "\n"
66 "\n"
67 "pass_2\n"
68 "\n"
69 "pass_3\n";
70
71 preprocess(str, expected);
72 }
73
TEST_F(IfTest,If_1_Else)74 TEST_F(IfTest, If_1_Else)
75 {
76 const char *str =
77 "pass_1\n"
78 "#if 1\n"
79 "pass_2\n"
80 "#else\n"
81 "fail\n"
82 "#endif\n"
83 "pass_3\n";
84 const char *expected =
85 "pass_1\n"
86 "\n"
87 "pass_2\n"
88 "\n"
89 "\n"
90 "\n"
91 "pass_3\n";
92
93 preprocess(str, expected);
94 }
95
TEST_F(IfTest,If_0_Elif)96 TEST_F(IfTest, If_0_Elif)
97 {
98 const char *str =
99 "pass_1\n"
100 "#if 0\n"
101 "fail_1\n"
102 "#elif 0\n"
103 "fail_2\n"
104 "#elif 1\n"
105 "pass_2\n"
106 "#elif 1\n"
107 "fail_3\n"
108 "#else\n"
109 "fail_4\n"
110 "#endif\n"
111 "pass_3\n";
112 const char *expected =
113 "pass_1\n"
114 "\n"
115 "\n"
116 "\n"
117 "\n"
118 "\n"
119 "pass_2\n"
120 "\n"
121 "\n"
122 "\n"
123 "\n"
124 "\n"
125 "pass_3\n";
126
127 preprocess(str, expected);
128 }
129
TEST_F(IfTest,If_1_Elif)130 TEST_F(IfTest, If_1_Elif)
131 {
132 const char *str =
133 "pass_1\n"
134 "#if 1\n"
135 "pass_2\n"
136 "#elif 0\n"
137 "fail_1\n"
138 "#elif 1\n"
139 "fail_2\n"
140 "#else\n"
141 "fail_4\n"
142 "#endif\n"
143 "pass_3\n";
144 const char *expected =
145 "pass_1\n"
146 "\n"
147 "pass_2\n"
148 "\n"
149 "\n"
150 "\n"
151 "\n"
152 "\n"
153 "\n"
154 "\n"
155 "pass_3\n";
156
157 preprocess(str, expected);
158 }
159
TEST_F(IfTest,If_Elif_Else)160 TEST_F(IfTest, If_Elif_Else)
161 {
162 const char *str =
163 "pass_1\n"
164 "#if 0\n"
165 "fail_1\n"
166 "#elif 0\n"
167 "fail_2\n"
168 "#elif 0\n"
169 "fail_3\n"
170 "#else\n"
171 "pass_2\n"
172 "#endif\n"
173 "pass_3\n";
174 const char *expected =
175 "pass_1\n"
176 "\n"
177 "\n"
178 "\n"
179 "\n"
180 "\n"
181 "\n"
182 "\n"
183 "pass_2\n"
184 "\n"
185 "pass_3\n";
186
187 preprocess(str, expected);
188 }
189
TEST_F(IfTest,If_0_Nested)190 TEST_F(IfTest, If_0_Nested)
191 {
192 const char *str =
193 "pass_1\n"
194 "#if 0\n"
195 "fail_1\n"
196 "#if 1\n"
197 "fail_2\n"
198 "#else\n"
199 "fail_3\n"
200 "#endif\n"
201 "#else\n"
202 "pass_2\n"
203 "#endif\n"
204 "pass_3\n";
205 const char *expected =
206 "pass_1\n"
207 "\n"
208 "\n"
209 "\n"
210 "\n"
211 "\n"
212 "\n"
213 "\n"
214 "\n"
215 "pass_2\n"
216 "\n"
217 "pass_3\n";
218
219 preprocess(str, expected);
220 }
221
TEST_F(IfTest,If_1_Nested)222 TEST_F(IfTest, If_1_Nested)
223 {
224 const char *str =
225 "pass_1\n"
226 "#if 1\n"
227 "pass_2\n"
228 "#if 1\n"
229 "pass_3\n"
230 "#else\n"
231 "fail_1\n"
232 "#endif\n"
233 "#else\n"
234 "fail_2\n"
235 "#endif\n"
236 "pass_4\n";
237 const char *expected =
238 "pass_1\n"
239 "\n"
240 "pass_2\n"
241 "\n"
242 "pass_3\n"
243 "\n"
244 "\n"
245 "\n"
246 "\n"
247 "\n"
248 "\n"
249 "pass_4\n";
250
251 preprocess(str, expected);
252 }
253
TEST_F(IfTest,OperatorPrecedence)254 TEST_F(IfTest, OperatorPrecedence)
255 {
256 const char *str =
257 "#if 1 + 2 * 3 + - (26 % 17 - + 4 / 2)\n"
258 "fail_1\n"
259 "#else\n"
260 "pass_1\n"
261 "#endif\n";
262 const char *expected =
263 "\n"
264 "\n"
265 "\n"
266 "pass_1\n"
267 "\n";
268
269 preprocess(str, expected);
270 }
271
TEST_F(IfTest,OperatorDefined)272 TEST_F(IfTest, OperatorDefined)
273 {
274 const char *str =
275 "#if defined foo\n"
276 "fail_1\n"
277 "#else\n"
278 "pass_1\n"
279 "#endif\n"
280 "#define foo\n"
281 "#if defined(foo)\n"
282 "pass_2\n"
283 "#else\n"
284 "fail_2\n"
285 "#endif\n"
286 "#undef foo\n"
287 "#if defined ( foo ) \n"
288 "fail_3\n"
289 "#else\n"
290 "pass_3\n"
291 "#endif\n";
292 const char *expected =
293 "\n"
294 "\n"
295 "\n"
296 "pass_1\n"
297 "\n"
298 "\n"
299 "\n"
300 "pass_2\n"
301 "\n"
302 "\n"
303 "\n"
304 "\n"
305 "\n"
306 "\n"
307 "\n"
308 "pass_3\n"
309 "\n";
310
311 preprocess(str, expected);
312 }
313
TEST_F(IfTest,OperatorEQ)314 TEST_F(IfTest, OperatorEQ)
315 {
316 const char *str =
317 "#if 4 - 1 == 2 + 1\n"
318 "pass\n"
319 "#else\n"
320 "fail\n"
321 "#endif\n";
322 const char *expected =
323 "\n"
324 "pass\n"
325 "\n"
326 "\n"
327 "\n";
328
329 preprocess(str, expected);
330 }
331
TEST_F(IfTest,OperatorNE)332 TEST_F(IfTest, OperatorNE)
333 {
334 const char *str =
335 "#if 1 != 2\n"
336 "pass\n"
337 "#else\n"
338 "fail\n"
339 "#endif\n";
340 const char *expected =
341 "\n"
342 "pass\n"
343 "\n"
344 "\n"
345 "\n";
346
347 preprocess(str, expected);
348 }
349
TEST_F(IfTest,OperatorLess)350 TEST_F(IfTest, OperatorLess)
351 {
352 const char *str =
353 "#if 1 < 2\n"
354 "pass\n"
355 "#else\n"
356 "fail\n"
357 "#endif\n";
358 const char *expected =
359 "\n"
360 "pass\n"
361 "\n"
362 "\n"
363 "\n";
364
365 preprocess(str, expected);
366 }
367
TEST_F(IfTest,OperatorGreater)368 TEST_F(IfTest, OperatorGreater)
369 {
370 const char *str =
371 "#if 2 > 1\n"
372 "pass\n"
373 "#else\n"
374 "fail\n"
375 "#endif\n";
376 const char *expected =
377 "\n"
378 "pass\n"
379 "\n"
380 "\n"
381 "\n";
382
383 preprocess(str, expected);
384 }
385
TEST_F(IfTest,OperatorLE)386 TEST_F(IfTest, OperatorLE)
387 {
388 const char *str =
389 "#if 1 <= 2\n"
390 "pass_1\n"
391 "#else\n"
392 "fail_1\n"
393 "#endif\n"
394 "#if 2 <= 2\n"
395 "pass_2\n"
396 "#else\n"
397 "fail_2\n"
398 "#endif\n";
399 const char *expected =
400 "\n"
401 "pass_1\n"
402 "\n"
403 "\n"
404 "\n"
405 "\n"
406 "pass_2\n"
407 "\n"
408 "\n"
409 "\n";
410
411 preprocess(str, expected);
412 }
413
TEST_F(IfTest,OperatorGE)414 TEST_F(IfTest, OperatorGE)
415 {
416 const char *str =
417 "#if 2 >= 1\n"
418 "pass_1\n"
419 "#else\n"
420 "fail_1\n"
421 "#endif\n"
422 "#if 2 >= 2\n"
423 "pass_2\n"
424 "#else\n"
425 "fail_2\n"
426 "#endif\n";
427 const char *expected =
428 "\n"
429 "pass_1\n"
430 "\n"
431 "\n"
432 "\n"
433 "\n"
434 "pass_2\n"
435 "\n"
436 "\n"
437 "\n";
438
439 preprocess(str, expected);
440 }
441
TEST_F(IfTest,OperatorBitwiseOR)442 TEST_F(IfTest, OperatorBitwiseOR)
443 {
444 const char *str =
445 "#if (0xaaaaaaaa | 0x55555555) == 0xffffffff\n"
446 "pass\n"
447 "#else\n"
448 "fail\n"
449 "#endif\n";
450 const char *expected =
451 "\n"
452 "pass\n"
453 "\n"
454 "\n"
455 "\n";
456
457 preprocess(str, expected);
458 }
459
TEST_F(IfTest,OperatorBitwiseAND)460 TEST_F(IfTest, OperatorBitwiseAND)
461 {
462 const char *str =
463 "#if (0xaaaaaaa & 0x5555555) == 0\n"
464 "pass\n"
465 "#else\n"
466 "fail\n"
467 "#endif\n";
468 const char *expected =
469 "\n"
470 "pass\n"
471 "\n"
472 "\n"
473 "\n";
474
475 preprocess(str, expected);
476 }
477
TEST_F(IfTest,OperatorBitwiseXOR)478 TEST_F(IfTest, OperatorBitwiseXOR)
479 {
480 const char *str =
481 "#if (0xaaaaaaa ^ 0x5555555) == 0xfffffff\n"
482 "pass\n"
483 "#else\n"
484 "fail\n"
485 "#endif\n";
486 const char *expected =
487 "\n"
488 "pass\n"
489 "\n"
490 "\n"
491 "\n";
492
493 preprocess(str, expected);
494 }
495
TEST_F(IfTest,OperatorBitwiseComplement)496 TEST_F(IfTest, OperatorBitwiseComplement)
497 {
498 const char *str =
499 "#if (~ 0xdeadbeef) == -3735928560\n"
500 "pass\n"
501 "#else\n"
502 "fail\n"
503 "#endif\n";
504 const char *expected =
505 "\n"
506 "pass\n"
507 "\n"
508 "\n"
509 "\n";
510
511 preprocess(str, expected);
512 }
513
TEST_F(IfTest,OperatorLeft)514 TEST_F(IfTest, OperatorLeft)
515 {
516 const char *str =
517 "#if (1 << 12) == 4096\n"
518 "pass\n"
519 "#else\n"
520 "fail\n"
521 "#endif\n";
522 const char *expected =
523 "\n"
524 "pass\n"
525 "\n"
526 "\n"
527 "\n";
528
529 preprocess(str, expected);
530 }
531
TEST_F(IfTest,OperatorRight)532 TEST_F(IfTest, OperatorRight)
533 {
534 const char *str =
535 "#if (31762 >> 8) == 124\n"
536 "pass\n"
537 "#else\n"
538 "fail\n"
539 "#endif\n";
540 const char *expected =
541 "\n"
542 "pass\n"
543 "\n"
544 "\n"
545 "\n";
546
547 preprocess(str, expected);
548 }
549
TEST_F(IfTest,ExpressionWithMacros)550 TEST_F(IfTest, ExpressionWithMacros)
551 {
552 const char *str =
553 "#define one 1\n"
554 "#define two 2\n"
555 "#define three 3\n"
556 "#if one + two == three\n"
557 "pass\n"
558 "#else\n"
559 "fail\n"
560 "#endif\n";
561 const char *expected =
562 "\n"
563 "\n"
564 "\n"
565 "\n"
566 "pass\n"
567 "\n"
568 "\n"
569 "\n";
570
571 preprocess(str, expected);
572 }
573
TEST_F(IfTest,JunkInsideExcludedBlockIgnored)574 TEST_F(IfTest, JunkInsideExcludedBlockIgnored)
575 {
576 const char *str =
577 "#if 0\n"
578 "foo !@#$%^&* .1bar\n"
579 "#foo\n"
580 "#if bar\n"
581 "fail\n"
582 "#endif\n"
583 "#else\n"
584 "pass\n"
585 "#endif\n";
586 const char *expected =
587 "\n"
588 "\n"
589 "\n"
590 "\n"
591 "\n"
592 "\n"
593 "\n"
594 "pass\n"
595 "\n";
596
597 preprocess(str, expected);
598 }
599
TEST_F(IfTest,Ifdef)600 TEST_F(IfTest, Ifdef)
601 {
602 const char *str =
603 "#define foo\n"
604 "#ifdef foo\n"
605 "pass_1\n"
606 "#else\n"
607 "fail_1\n"
608 "#endif\n"
609 "#undef foo\n"
610 "#ifdef foo\n"
611 "fail_2\n"
612 "#else\n"
613 "pass_2\n"
614 "#endif\n";
615 const char *expected =
616 "\n"
617 "\n"
618 "pass_1\n"
619 "\n"
620 "\n"
621 "\n"
622 "\n"
623 "\n"
624 "\n"
625 "\n"
626 "pass_2\n"
627 "\n";
628
629 preprocess(str, expected);
630 }
631
TEST_F(IfTest,Ifndef)632 TEST_F(IfTest, Ifndef)
633 {
634 const char *str =
635 "#define foo\n"
636 "#ifndef foo\n"
637 "fail_1\n"
638 "#else\n"
639 "pass_1\n"
640 "#endif\n"
641 "#undef foo\n"
642 "#ifndef foo\n"
643 "pass_2\n"
644 "#else\n"
645 "fail_2\n"
646 "#endif\n";
647 const char *expected =
648 "\n"
649 "\n"
650 "\n"
651 "\n"
652 "pass_1\n"
653 "\n"
654 "\n"
655 "\n"
656 "pass_2\n"
657 "\n"
658 "\n"
659 "\n";
660
661 preprocess(str, expected);
662 }
663
TEST_F(IfTest,MissingExpression)664 TEST_F(IfTest, MissingExpression)
665 {
666 const char *str =
667 "#if\n"
668 "#endif\n";
669
670 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_EXPRESSION,
671 pp::SourceLocation(0, 1), "syntax error"));
672
673 preprocess(str);
674 }
675
TEST_F(IfTest,DivisionByZero)676 TEST_F(IfTest, DivisionByZero)
677 {
678 const char *str =
679 "#if 1 / (3 - (1 + 2))\n"
680 "#endif\n";
681
682 EXPECT_CALL(mDiagnostics,
683 print(pp::Diagnostics::PP_DIVISION_BY_ZERO, pp::SourceLocation(0, 1), "1 / 0"));
684
685 preprocess(str);
686 }
687
TEST_F(IfTest,ModuloByZero)688 TEST_F(IfTest, ModuloByZero)
689 {
690 const char *str =
691 "#if 1 % (3 - (1 + 2))\n"
692 "#endif\n";
693
694 EXPECT_CALL(mDiagnostics,
695 print(pp::Diagnostics::PP_DIVISION_BY_ZERO, pp::SourceLocation(0, 1), "1 % 0"));
696
697 preprocess(str);
698 }
699
TEST_F(IfTest,DecIntegerOverflow)700 TEST_F(IfTest, DecIntegerOverflow)
701 {
702 const char *str =
703 "#if 4294967296\n"
704 "#endif\n";
705
706 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INTEGER_OVERFLOW, pp::SourceLocation(0, 1),
707 "4294967296"));
708
709 preprocess(str);
710 }
711
TEST_F(IfTest,OctIntegerOverflow)712 TEST_F(IfTest, OctIntegerOverflow)
713 {
714 const char *str =
715 "#if 077777777777\n"
716 "#endif\n";
717
718 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INTEGER_OVERFLOW, pp::SourceLocation(0, 1),
719 "077777777777"));
720
721 preprocess(str);
722 }
723
TEST_F(IfTest,HexIntegerOverflow)724 TEST_F(IfTest, HexIntegerOverflow)
725 {
726 const char *str =
727 "#if 0xfffffffff\n"
728 "#endif\n";
729
730 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INTEGER_OVERFLOW, pp::SourceLocation(0, 1),
731 "0xfffffffff"));
732
733 preprocess(str);
734 }
735
TEST_F(IfTest,UndefinedMacro)736 TEST_F(IfTest, UndefinedMacro)
737 {
738 const char *str =
739 "#if UNDEFINED\n"
740 "#endif\n";
741
742 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
743 pp::SourceLocation(0, 1), "UNDEFINED"));
744
745 preprocess(str);
746 }
747
TEST_F(IfTest,InvalidExpressionIgnoredForExcludedElif)748 TEST_F(IfTest, InvalidExpressionIgnoredForExcludedElif)
749 {
750 const char *str =
751 "#if 1\n"
752 "pass\n"
753 "#elif UNDEFINED\n"
754 "fail\n"
755 "#endif\n";
756 const char *expected =
757 "\n"
758 "pass\n"
759 "\n"
760 "\n"
761 "\n";
762
763 // No error or warning.
764 using testing::_;
765 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
766
767 preprocess(str, expected);
768 }
769
TEST_F(IfTest,ElseWithoutIf)770 TEST_F(IfTest, ElseWithoutIf)
771 {
772 const char *str = "#else\n";
773
774 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
775 pp::SourceLocation(0, 1), "else"));
776
777 preprocess(str);
778 }
779
TEST_F(IfTest,ElifWithoutIf)780 TEST_F(IfTest, ElifWithoutIf)
781 {
782 const char *str = "#elif 1\n";
783
784 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
785 pp::SourceLocation(0, 1), "elif"));
786
787 preprocess(str);
788 }
789
TEST_F(IfTest,EndifWithoutIf)790 TEST_F(IfTest, EndifWithoutIf)
791 {
792 const char *str = "#endif\n";
793
794 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
795 pp::SourceLocation(0, 1), "endif"));
796
797 preprocess(str);
798 }
799
TEST_F(IfTest,ElseAfterElse)800 TEST_F(IfTest, ElseAfterElse)
801 {
802 const char *str =
803 "#if 1\n"
804 "#else\n"
805 "#else\n"
806 "#endif\n";
807
808 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
809 pp::SourceLocation(0, 3), "else"));
810
811 preprocess(str);
812 }
813
TEST_F(IfTest,ElifAfterElse)814 TEST_F(IfTest, ElifAfterElse)
815 {
816 const char *str =
817 "#if 1\n"
818 "#else\n"
819 "#elif 0\n"
820 "#endif\n";
821
822 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
823 pp::SourceLocation(0, 3), "elif"));
824
825 preprocess(str);
826 }
827
TEST_F(IfTest,UnterminatedIf)828 TEST_F(IfTest, UnterminatedIf)
829 {
830 const char *str = "#if 1\n";
831
832 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED,
833 pp::SourceLocation(0, 1), "if"));
834
835 preprocess(str);
836 }
837
TEST_F(IfTest,UnterminatedIfdef)838 TEST_F(IfTest, UnterminatedIfdef)
839 {
840 const char *str = "#ifdef foo\n";
841
842 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNTERMINATED,
843 pp::SourceLocation(0, 1), "ifdef"));
844
845 preprocess(str);
846 }
847
848 // The preprocessor only allows one expression to follow an #if directive.
849 // Supplying two integer expressions should be an error.
TEST_F(IfTest,ExtraIntExpression)850 TEST_F(IfTest, ExtraIntExpression)
851 {
852 const char *str =
853 "#if 1 1\n"
854 "#endif\n";
855
856 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
857 pp::SourceLocation(0, 1), "1"));
858
859 preprocess(str);
860 }
861
862 // The preprocessor only allows one expression to follow an #if directive.
863 // Supplying two expressions where one uses a preprocessor define should be an error.
TEST_F(IfTest,ExtraIdentifierExpression)864 TEST_F(IfTest, ExtraIdentifierExpression)
865 {
866 const char *str =
867 "#define one 1\n"
868 "#if 1 one\n"
869 "#endif\n";
870
871 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
872 pp::SourceLocation(0, 2), "1"));
873
874 preprocess(str);
875 }
876
877 // Divide by zero that's not evaluated because of short-circuiting should not cause an error.
TEST_F(IfTest,ShortCircuitedDivideByZero)878 TEST_F(IfTest, ShortCircuitedDivideByZero)
879 {
880 const char *str =
881 "#if 1 || (2 / 0)\n"
882 "pass\n"
883 "#endif\n";
884 const char *expected =
885 "\n"
886 "pass\n"
887 "\n";
888
889 preprocess(str, expected);
890 }
891
892 // Undefined identifier that's not evaluated because of short-circuiting should not cause an error.
TEST_F(IfTest,ShortCircuitedUndefined)893 TEST_F(IfTest, ShortCircuitedUndefined)
894 {
895 const char *str =
896 "#if 1 || UNDEFINED\n"
897 "pass\n"
898 "#endif\n";
899 const char *expected =
900 "\n"
901 "pass\n"
902 "\n";
903
904 preprocess(str, expected);
905 }
906
907 // Defined operator produced by macro expansion has undefined behavior according to C++ spec,
908 // which the GLSL spec references (see C++14 draft spec section 16.1.4), but this behavior is
909 // needed for passing dEQP tests, which enforce stricter compatibility between implementations.
TEST_F(IfTest,DefinedOperatorValidAfterMacroExpansion)910 TEST_F(IfTest, DefinedOperatorValidAfterMacroExpansion)
911 {
912 const char *str =
913 "#define foo defined\n"
914 "#if !foo bar\n"
915 "pass\n"
916 "#endif\n";
917
918 preprocess(str, "\n\npass\n\n");
919 }
920
921 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_F(IfTest,DefinedOperatorValidWhenUsed)922 TEST_F(IfTest, DefinedOperatorValidWhenUsed)
923 {
924 constexpr char str[] = R"(#define BBB 1
925 #define AAA defined(BBB)
926 #undef BBB
927
928 #if !AAA
929 pass
930 #endif
931 )";
932
933 preprocess(str, "\n\n\n\n\npass\n\n");
934 }
935
936 // Validate the defined operator is evaluated when the macro is called, not when defined.
TEST_F(IfTest,DefinedOperatorAfterMacro)937 TEST_F(IfTest, DefinedOperatorAfterMacro)
938 {
939 constexpr char str[] = R"(#define AAA defined(BBB)
940 #define BBB 1
941
942 #if AAA
943 pass
944 #endif
945 )";
946
947 preprocess(str, "\n\n\n\npass\n\n");
948 }
949
950 // Test generating "defined" by concatenation when a macro is called. This is not allowed.
TEST_F(IfTest,DefinedInMacroConcatenationNotAllowed)951 TEST_F(IfTest, DefinedInMacroConcatenationNotAllowed)
952 {
953 constexpr char str[] = R"(#define BBB 1
954 #define AAA(defi, ned) defi ## ned(BBB)
955
956 #if !AAA(defi, ned)
957 pass
958 #endif
959 )";
960
961 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
962 pp::SourceLocation(0, 4), "defi"));
963 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
964 pp::SourceLocation(0, 4), "#"));
965
966 preprocess(str);
967 }
968
969 // Test using defined in a macro parameter name. This is not allowed.
TEST_F(IfTest,DefinedAsParameterNameNotAllowed)970 TEST_F(IfTest, DefinedAsParameterNameNotAllowed)
971 {
972 constexpr char str[] = R"(#define BBB 1
973 #define AAA(defined) defined(BBB)
974
975 #if AAA(defined)
976 pass
977 #endif
978 )";
979
980 EXPECT_CALL(mDiagnostics,
981 print(pp::Diagnostics::PP_UNEXPECTED_TOKEN, pp::SourceLocation(0, 0), ""));
982
983 preprocess(str);
984 }
985
986 // This behavour is disabled in WebGL.
TEST_F(IfTest,DefinedOperatorInvalidAfterMacroExpansionInWebGL)987 TEST_F(IfTest, DefinedOperatorInvalidAfterMacroExpansionInWebGL)
988 {
989 const char *str =
990 "#define foo defined\n"
991 "#if !foo bar\n"
992 "pass\n"
993 "#endif\n";
994
995 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
996 pp::SourceLocation(0, 2), "defined"));
997 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
998 pp::SourceLocation(0, 2), "bar"));
999
1000 preprocess(str, pp::PreprocessorSettings(SH_WEBGL_SPEC));
1001 }
1002
1003 // Defined operator produced by macro expansion has undefined behavior according to C++ spec,
1004 // which the GLSL spec references (see C++14 draft spec section 16.1.4). Some edge case
1005 // behaviours with defined are not portable between implementations and thus are not required
1006 // to pass dEQP Tests.
TEST_F(IfTest,UnterminatedDefinedInMacro)1007 TEST_F(IfTest, UnterminatedDefinedInMacro)
1008 {
1009 const char *str =
1010 "#define foo defined(\n"
1011 "#if foo\n"
1012 "#endif\n";
1013
1014 EXPECT_CALL(mDiagnostics,
1015 print(pp::Diagnostics::PP_UNEXPECTED_TOKEN, pp::SourceLocation(0, 2), "\n"));
1016 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_EXPRESSION,
1017 pp::SourceLocation(0, 2), "syntax error"));
1018
1019 preprocess(str);
1020 }
1021
1022 // Defined operator produced by macro expansion has undefined behavior according to C++ spec,
1023 // which the GLSL spec references (see C++14 draft spec section 16.1.4). Some edge case
1024 // behaviours with defined are not portable between implementations and thus are not required
1025 // to pass dEQP Tests.
TEST_F(IfTest,UnterminatedDefinedInMacro2)1026 TEST_F(IfTest, UnterminatedDefinedInMacro2)
1027 {
1028 const char *str =
1029 "#define foo defined(bar\n"
1030 "#if foo\n"
1031 "#endif\n";
1032
1033 EXPECT_CALL(mDiagnostics,
1034 print(pp::Diagnostics::PP_UNEXPECTED_TOKEN, pp::SourceLocation(0, 2), "\n"));
1035 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_EXPRESSION,
1036 pp::SourceLocation(0, 2), "syntax error"));
1037
1038 preprocess(str);
1039 }
1040
1041 // Undefined shift: negative shift offset.
TEST_F(IfTest,BitShiftLeftOperatorNegativeOffset)1042 TEST_F(IfTest, BitShiftLeftOperatorNegativeOffset)
1043 {
1044 const char *str =
1045 "#if 2 << -1 == 1\n"
1046 "foo\n"
1047 "#endif\n";
1048
1049 EXPECT_CALL(mDiagnostics,
1050 print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 << -1"));
1051
1052 preprocess(str);
1053 }
1054
1055 // Undefined shift: shift offset is out of range.
TEST_F(IfTest,BitShiftLeftOperatorOffset32)1056 TEST_F(IfTest, BitShiftLeftOperatorOffset32)
1057 {
1058 const char *str =
1059 "#if 2 << 32 == 1\n"
1060 "foo\n"
1061 "#endif\n";
1062
1063 EXPECT_CALL(mDiagnostics,
1064 print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 << 32"));
1065
1066 preprocess(str);
1067 }
1068
1069 // Left hand side of shift is negative.
TEST_F(IfTest,BitShiftLeftOperatorNegativeLHS)1070 TEST_F(IfTest, BitShiftLeftOperatorNegativeLHS)
1071 {
1072 const char *str =
1073 "#if (-2) << 1 == -4\n"
1074 "pass\n"
1075 "#endif\n";
1076 const char *expected =
1077 "\n"
1078 "pass\n"
1079 "\n";
1080
1081 preprocess(str, expected);
1082 }
1083
1084 // Left shift overflows. Note that the intended result is not explicitly specified, but we assume it
1085 // to do the same operation on the 2's complement bit representation as unsigned shift in C++.
TEST_F(IfTest,BitShiftLeftOverflow)1086 TEST_F(IfTest, BitShiftLeftOverflow)
1087 {
1088 const char *str =
1089 "#if (0x10000 + 0x1) << 28 == 0x10000000\n"
1090 "pass\n"
1091 "#endif\n";
1092 const char *expected =
1093 "\n"
1094 "pass\n"
1095 "\n";
1096
1097 preprocess(str, expected);
1098 }
1099
1100 // Left shift of a negative number overflows. Note that the intended result is not explicitly
1101 // specified, but we assume it to do the same operation on the 2's complement bit representation as
1102 // unsigned shift in C++.
TEST_F(IfTest,BitShiftLeftNegativeOverflow)1103 TEST_F(IfTest, BitShiftLeftNegativeOverflow)
1104 {
1105 // The bit representation of -5 is 11111111 11111111 11111111 11111011.
1106 // Shifting by 30 leaves: 11000000 00000000 00000000 00000000.
1107 const char *str =
1108 "#if (-5) << 30 == -1073741824\n"
1109 "pass\n"
1110 "#endif\n";
1111 const char *expected =
1112 "\n"
1113 "pass\n"
1114 "\n";
1115
1116 preprocess(str, expected);
1117 }
1118
1119 // Undefined shift: shift offset is out of range.
TEST_F(IfTest,BitShiftRightOperatorNegativeOffset)1120 TEST_F(IfTest, BitShiftRightOperatorNegativeOffset)
1121 {
1122 const char *str =
1123 "#if 2 >> -1 == 4\n"
1124 "foo\n"
1125 "#endif\n";
1126
1127 EXPECT_CALL(mDiagnostics,
1128 print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 >> -1"));
1129
1130 preprocess(str);
1131 }
1132
1133 // Undefined shift: shift offset is out of range.
TEST_F(IfTest,BitShiftRightOperatorOffset32)1134 TEST_F(IfTest, BitShiftRightOperatorOffset32)
1135 {
1136 const char *str =
1137 "#if 2 >> 32 == 0\n"
1138 "foo\n"
1139 "#endif\n";
1140
1141 EXPECT_CALL(mDiagnostics,
1142 print(pp::Diagnostics::PP_UNDEFINED_SHIFT, pp::SourceLocation(0, 1), "2 >> 32"));
1143
1144 preprocess(str);
1145 }
1146
1147 // Left hand side of shift is negative.
TEST_F(IfTest,BitShiftRightOperatorNegativeLHS)1148 TEST_F(IfTest, BitShiftRightOperatorNegativeLHS)
1149 {
1150 const char *str =
1151 "#if (-2) >> 1 == 0x7fffffff\n"
1152 "pass\n"
1153 "#endif\n";
1154 const char *expected =
1155 "\n"
1156 "pass\n"
1157 "\n";
1158
1159 preprocess(str, expected);
1160 }
1161
1162 } // namespace angle
1163