summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/cpp/macro1.c
blob: a2b1a38e295ebe2e910c0cf6953cb2bbcd000522 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Copyright (C) 2000 Free Software Foundation, Inc.  */

/* { dg-do run } */

/* Tests various macro abuse is correctly expanded.  */

#if DEBUG
extern int puts (const char *);
#else
#define puts(X)
#endif
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;
}