PR libstdc++/9527, PR libstdc++/8713
[official-gcc.git] / gcc / scan-decls.c
blob62afffbe9d796d04b03384cda9f4756fbb5521db
1 /* scan-decls.c - Extracts declarations from cpp output.
2 Copyright (C) 1993, 1995, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 Written by Per Bothner <bothner@cygnus.com>, July 1993. */
21 #include "bconfig.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cpplib.h"
26 #include "scan.h"
28 static void skip_to_closing_brace PARAMS ((cpp_reader *));
29 static const cpp_token *get_a_token PARAMS ((cpp_reader *));
31 int brace_nesting = 0;
33 /* The first extern_C_braces_length elements of extern_C_braces
34 indicate the (brace nesting levels of) left braces that were
35 prefixed by extern "C". */
36 int extern_C_braces_length = 0;
37 char extern_C_braces[20];
38 #define in_extern_C_brace (extern_C_braces_length>0)
40 /* True if the function declaration currently being scanned is
41 prefixed by extern "C". */
42 int current_extern_C = 0;
44 /* Get a token but skip padding. */
45 static const cpp_token *
46 get_a_token (pfile)
47 cpp_reader *pfile;
49 for (;;)
51 const cpp_token *result = cpp_get_token (pfile);
52 if (result->type != CPP_PADDING)
53 return result;
57 static void
58 skip_to_closing_brace (pfile)
59 cpp_reader *pfile;
61 int nesting = 1;
62 for (;;)
64 enum cpp_ttype token = get_a_token (pfile)->type;
66 if (token == CPP_EOF)
67 break;
68 if (token == CPP_OPEN_BRACE)
69 nesting++;
70 if (token == CPP_CLOSE_BRACE && --nesting == 0)
71 break;
75 /* This function scans a C source file (actually, the output of cpp),
76 reading from FP. It looks for function declarations, and
77 external variable declarations.
79 The following grammar (as well as some extra stuff) is recognized:
81 declaration:
82 (decl-specifier)* declarator ("," declarator)* ";"
83 decl-specifier:
84 identifier
85 keyword
86 extern "C"
87 declarator:
88 (ptr-operator)* dname [ "(" argument-declaration-list ")" ]
89 ptr-operator:
90 ("*" | "&") ("const" | "volatile")*
91 dname:
92 identifier
94 Here dname is the actual name being declared.
97 int
98 scan_decls (pfile, argc, argv)
99 cpp_reader *pfile;
100 int argc ATTRIBUTE_UNUSED;
101 char **argv ATTRIBUTE_UNUSED;
103 int saw_extern, saw_inline;
104 cpp_token prev_id;
105 const cpp_token *token;
107 new_statement:
108 token = get_a_token (pfile);
110 handle_statement:
111 current_extern_C = 0;
112 saw_extern = 0;
113 saw_inline = 0;
114 if (token->type == CPP_OPEN_BRACE)
116 /* Pop an 'extern "C"' nesting level, if appropriate. */
117 if (extern_C_braces_length
118 && extern_C_braces[extern_C_braces_length - 1] == brace_nesting)
119 extern_C_braces_length--;
120 brace_nesting--;
121 goto new_statement;
123 if (token->type == CPP_OPEN_BRACE)
125 brace_nesting++;
126 goto new_statement;
129 if (token->type == CPP_EOF)
130 return 0;
132 if (token->type == CPP_SEMICOLON)
133 goto new_statement;
134 if (token->type != CPP_NAME)
135 goto new_statement;
137 prev_id.type = CPP_EOF;
138 for (;;)
140 switch (token->type)
142 default:
143 goto handle_statement;
144 case CPP_MULT:
145 case CPP_AND:
146 /* skip */
147 break;
149 case CPP_COMMA:
150 case CPP_SEMICOLON:
151 if (prev_id.type != CPP_EOF && saw_extern)
153 recognized_extern (&prev_id);
155 if (token->type == CPP_COMMA)
156 break;
157 /* ... fall through ... */
158 case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE:
159 goto new_statement;
161 case CPP_EOF:
162 return 0;
164 case CPP_OPEN_PAREN:
165 /* Looks like this is the start of a formal parameter list. */
166 if (prev_id.type != CPP_EOF)
168 int nesting = 1;
169 int have_arg_list = 0;
170 for (;;)
172 token = get_a_token (pfile);
173 if (token->type == CPP_OPEN_PAREN)
174 nesting++;
175 else if (token->type == CPP_CLOSE_PAREN)
177 nesting--;
178 if (nesting == 0)
179 break;
181 else if (token->type == CPP_EOF)
182 break;
183 else if (token->type == CPP_NAME
184 || token->type == CPP_ELLIPSIS)
185 have_arg_list = 1;
187 recognized_function (&prev_id, token->line,
188 (saw_inline ? 'I'
189 : in_extern_C_brace || current_extern_C
190 ? 'F' : 'f'), have_arg_list);
191 token = get_a_token (pfile);
192 if (token->type == CPP_OPEN_BRACE)
194 /* skip body of (normally) inline function */
195 skip_to_closing_brace (pfile);
196 goto new_statement;
199 /* skip a possible __attribute__ or throw expression after the
200 parameter list */
201 while (token->type != CPP_SEMICOLON && token->type != CPP_EOF)
202 token = get_a_token (pfile);
203 goto new_statement;
205 break;
206 case CPP_NAME:
207 /* "inline" and "extern" are recognized but skipped */
208 if (cpp_ideq (token, "inline"))
210 saw_inline = 1;
212 else if (cpp_ideq (token, "extern"))
214 saw_extern = 1;
215 token = get_a_token (pfile);
216 if (token->type == CPP_STRING
217 && token->val.str.len == 1
218 && token->val.str.text[0] == 'C')
220 current_extern_C = 1;
221 token = get_a_token (pfile);
222 if (token->type == CPP_OPEN_BRACE)
224 brace_nesting++;
225 extern_C_braces[extern_C_braces_length++]
226 = brace_nesting;
227 goto new_statement;
230 else
231 continue;
232 break;
234 /* This may be the name of a variable or function. */
235 prev_id = *token;
236 break;
238 token = get_a_token (pfile);