1 /* Copyright (C) 2000 Free Software Foundation, Inc.  */
2 
3 /* { dg-do run } */
4 
5 /* Tests various macro abuse is correctly expanded.  */
6 
7 #if DEBUG
8 extern int puts (const char *);
9 #else
10 #define puts(X)
11 #endif
12 extern void abort (void);
13 extern int strcmp(const char *s1, const char *s2);
14 
15 #define err(str) do { puts(str); abort(); } while (0)
16 #define j(x, y) x + y
17 #define k(x, y) j(x + 2, y +
18 #define glue(x, y) x ## y
19 #define xglue(x, y) glue(x, y)
20 
21 /* Functions called when macros are left unexpanded.  */
q(int x)22 int q(int x)		{return x + 40;}
B(int x)23 int B(int x)		{return x + 20;}
foo(int x)24 int foo(int x)		{return x + 10;}
bar(int x,int y)25 int bar(int x, int y)	{return x + y;}
baz(int x,int y)26 int baz(int x, int y)	{return x + y;}
toupper(int x)27 int toupper(int x)	{return x + 32;}
M(int x)28 int M(int x)		{return x * 2;}
29 
main(int argc,char * argv[])30 int main (int argc, char *argv[])
31 {
32 #define q(x) x
33   if (q(q)(2) != 42)
34     err ("q");
35 
36 #define A(x) B(x)
37   if (A(A(2)) != 42)
38     err ("A");
39 
40 #define E(x) A x
41 #define F (22)
42   if (E(F) != 42)
43     err ("E(F)");
44 
45 #define COMMA ,
46 #define NASTY(a) j(a 37)
47   if (NASTY (5 COMMA) != 42)
48     err ("NASTY");
49 
50 #define bar(x, y) foo(x(y, 0))
51 #define apply(x, y) foo(x(y, 22))
52 #define bam bar
53   if (bar(bar, 32) != 42)	/* foo(bar(32, 0)).  */
54     err ("bar bar");
55   if (bar(bam, 32) != 42)	/* Same.  */
56     err ("bar bam");
57   if (apply(bar, baz) != 42)	/* foo(foo(baz(22, 0))).  */
58     err ("apply bar baz");
59 
60   /* Taken from glibc.  */
61 #define __tobody(c, f) f (c)
62 #define toupper(c) __tobody (c, toupper)
63   if (toupper (10) != 42)	/* toupper (10). */
64     err ("toupper");
65 
66   /* This tests that M gets expanded the right no. of times.  Too many
67      times, and we get excess "2 +"s and the wrong sum.  Derived from
68      nested stpcpy in dggettext.c.  */
69 #define M(x) 2 + M(x)
70 #define stpcpy(a) M(a)
71   if (stpcpy (stpcpy (9)) != 42) /*  2 + M (2 + M (9)) */
72     err ("stpcpy");
73 
74   /* Another test derived from nested stpcpy's of dggettext.c.  Uses
75      macro A(x) and function B(x) as defined above.  The problem was
76      the same - excess "1 +"s and the wrong sum.  */
77 #define B(x) 1 + B(x)
78 #define C(x) A(x)
79   if (C(B(0)) != 42)		/* 1 + B (1 + B (0)) */
80     err ("C");
81 
82   /* More tests derived from gcc itself - the use of XEXP and COST.
83      These first two should both expand to the same thing.  */
84   {
85     int insn = 6, i = 2, b = 2;
86 #define XEXP(RTX, N)  (RTX * N + 2)
87 #define PATTERN(INSN) XEXP(INSN, 3)
88     if (XEXP (PATTERN (insn), i) != 42)	/* ((insn * 3 + 2) * i + 2) */
89       err ("XEXP (PATTERN)");
90     if (XEXP (XEXP (insn, 3), i) != 42)	/* ((insn * 3 + 2) * i + 2) */
91       err ("XEXP (XEXP)");
92 
93 #define COST(X) XEXP (XEXP (X, 4), 4)
94     if (COST (b) != 42)		/* ((b * 4 + 2) * 4 + 2) */
95       err ("COST");
96   }
97 
98   /* This tests macro recursion and expand-after-paste.  */
99 #define FORTYTWO "forty"
100 #define TWO TWO "-two"
101   if (strcmp (glue(FORTY, TWO), "forty"))
102     err ("glue");
103   if (strcmp (xglue(FORTY, TWO), "forty-two"))
104     err ("xglue");
105 
106   /* Test ability to call macro over multiple logical lines.  */
107   if (q
108       (42) != 42
109       || q (
110 	 42) != 42
111       || q (42
112 	    ) != 42
113       || q
114       (
115        42
116        )
117       != 42)
118     err ("q over multiple lines");
119 
120   /* Corner case.  Test that macro expansion is turned off for later
121      q, when not at start but at end of argument context, and supplied
122      with the '(' necessary for expansion.  */
123   if (q(1 + q)(1) != 42)	/* 1 + q(1) */
124     err ("Nested q");
125 
126   /* This looks like it has too many ')', but it hasn't.  */
127   if (k(1, 4) 35) != 42)
128     err ("k");
129 
130   /* Phew! */
131   return 0;
132 }
133