/* Copyright (C) 2000 Free Software Foundation, Inc. */ /* { dg-do run } */ /* Tests various macro abuse is correctly expanded. */ extern int puts (const char *); extern void abort (void); extern int strcmp(const char *s1, const char *s2); #define err(str) do { puts(str); abort(); } while (0) #define j(x, y) x + y #define k(x, y) j(x + 2, y + #define glue(x, y) x ## y #define xglue(x, y) glue(x, y) /* Functions called when macros are left unexpanded. */ int q(int x) {return x + 40;} int B(int x) {return x + 20;} int foo(int x) {return x + 10;} int bar(int x, int y) {return x + y;} int baz(int x, int y) {return x + y;} int toupper(int x) {return x + 32;} int M(int x) {return x * 2;} int main (int argc, char *argv[]) { #define q(x) x if (q(q)(2) != 42) err ("q"); #define A(x) B(x) if (A(A(2)) != 42) err ("A"); #define E(x) A x #define F (22) if (E(F) != 42) err ("E(F)"); #define COMMA , #define NASTY(a) j(a 37) if (NASTY (5 COMMA) != 42) err ("NASTY"); #define bar(x, y) foo(x(y, 0)) #define apply(x, y) foo(x(y, 22)) #define bam bar if (bar(bar, 32) != 42) /* foo(bar(32, 0)). */ err ("bar bar"); if (bar(bam, 32) != 42) /* Same. */ err ("bar bam"); if (apply(bar, baz) != 42) /* foo(foo(baz(22, 0))). */ err ("apply bar baz"); /* Taken from glibc. */ #define __tobody(c, f) f (c) #define toupper(c) __tobody (c, toupper) if (toupper (10) != 42) /* toupper (10). */ err ("toupper"); /* This tests that M gets expanded the right no. of times. Too many times, and we get excess "2 +"s and the wrong sum. Derived from nested stpcpy in dggettext.c. */ #define M(x) 2 + M(x) #define stpcpy(a) M(a) if (stpcpy (stpcpy (9)) != 42) /* 2 + M (2 + M (9)) */ err ("stpcpy"); /* Another test derived from nested stpcpy's of dggettext.c. Uses macro A(x) and function B(x) as defined above. The problem was the same - excess "1 +"s and the wrong sum. */ #define B(x) 1 + B(x) #define C(x) A(x) if (C(B(0)) != 42) /* 1 + B (1 + B (0)) */ err ("C"); /* More tests derived from gcc itself - the use of XEXP and COST. These first two should both expand to the same thing. */ { int insn = 6, i = 2, b = 2; #define XEXP(RTX, N) (RTX * N + 2) #define PATTERN(INSN) XEXP(INSN, 3) if (XEXP (PATTERN (insn), i) != 42) /* ((insn * 3 + 2) * i + 2) */ err ("XEXP (PATTERN)"); if (XEXP (XEXP (insn, 3), i) != 42) /* ((insn * 3 + 2) * i + 2) */ err ("XEXP (XEXP)"); #define COST(X) XEXP (XEXP (X, 4), 4) if (COST (b) != 42) /* ((b * 4 + 2) * 4 + 2) */ err ("COST"); } /* This tests macro recursion and expand-after-paste. */ #define FORTYTWO "forty" #define TWO TWO "-two" if (strcmp (glue(FORTY, TWO), "forty")) err ("glue"); if (strcmp (xglue(FORTY, TWO), "forty-two")) err ("xglue"); /* Test ability to call macro over multiple logical lines. */ if (q (42) != 42 || q ( 42) != 42 || q (42 ) != 42 || q ( 42 ) != 42) err ("q over multiple lines"); /* Corner case. Test that macro expansion is turned off for later q, when not at start but at end of argument context, and supplied with the '(' necessary for expansion. */ if (q(1 + q)(1) != 42) /* 1 + q(1) */ err ("Nested q"); /* This looks like it has too many ')', but it hasn't. */ if (k(1, 4) 35) != 42) err ("k"); /* Phew! */ return 0; }