Mercurial > hg > CbC > CbC_gcc
comparison libcc1/libcp1.cc @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* The library used by gdb. | |
2 Copyright (C) 2014-2017 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include <cc1plugin-config.h> | |
21 #include <vector> | |
22 #include <string> | |
23 #include <sys/socket.h> | |
24 #include <sys/types.h> | |
25 #include <unistd.h> | |
26 #include <sys/wait.h> | |
27 #include <stdio.h> | |
28 #include <errno.h> | |
29 #include <sys/stat.h> | |
30 #include <stdlib.h> | |
31 #include <sstream> | |
32 #include "marshall-cp.hh" | |
33 #include "rpc.hh" | |
34 #include "connection.hh" | |
35 #include "names.hh" | |
36 #include "callbacks.hh" | |
37 #include "libiberty.h" | |
38 #include "xregex.h" | |
39 #include "findcomp.hh" | |
40 #include "cp-compiler-name.h" | |
41 #include "intl.h" | |
42 | |
43 struct libcp1; | |
44 | |
45 class libcp1_connection; | |
46 | |
47 // The C compiler context that we hand back to our caller. | |
48 struct libcp1 : public gcc_cp_context | |
49 { | |
50 libcp1 (const gcc_base_vtable *, const gcc_cp_fe_vtable *); | |
51 ~libcp1 (); | |
52 | |
53 // A convenience function to print something. | |
54 void print (const char *str) | |
55 { | |
56 this->print_function (this->print_datum, str); | |
57 } | |
58 | |
59 libcp1_connection *connection; | |
60 | |
61 gcc_cp_oracle_function *binding_oracle; | |
62 gcc_cp_symbol_address_function *address_oracle; | |
63 gcc_cp_enter_leave_user_expr_scope_function *enter_scope; | |
64 gcc_cp_enter_leave_user_expr_scope_function *leave_scope; | |
65 void *oracle_datum; | |
66 | |
67 void (*print_function) (void *datum, const char *message); | |
68 void *print_datum; | |
69 | |
70 std::vector<std::string> args; | |
71 std::string source_file; | |
72 | |
73 /* Non-zero as an equivalent to gcc driver option "-v". */ | |
74 bool verbose; | |
75 | |
76 /* Compiler to set by set_triplet_regexp or set_driver_filename. */ | |
77 class compiler | |
78 { | |
79 protected: | |
80 libcp1 *self_; | |
81 public: | |
82 compiler (libcp1 *self) : self_ (self) | |
83 { | |
84 } | |
85 virtual char *find (std::string &compiler) const; | |
86 virtual ~compiler () | |
87 { | |
88 } | |
89 } *compilerp; | |
90 | |
91 /* Compiler to set by set_triplet_regexp. */ | |
92 class compiler_triplet_regexp : public compiler | |
93 { | |
94 private: | |
95 std::string triplet_regexp_; | |
96 public: | |
97 virtual char *find (std::string &compiler) const; | |
98 compiler_triplet_regexp (libcp1 *self, std::string triplet_regexp) | |
99 : compiler (self), triplet_regexp_ (triplet_regexp) | |
100 { | |
101 } | |
102 virtual ~compiler_triplet_regexp () | |
103 { | |
104 } | |
105 }; | |
106 | |
107 /* Compiler to set by set_driver_filename. */ | |
108 class compiler_driver_filename : public compiler | |
109 { | |
110 private: | |
111 std::string driver_filename_; | |
112 public: | |
113 virtual char *find (std::string &compiler) const; | |
114 compiler_driver_filename (libcp1 *self, std::string driver_filename) | |
115 : compiler (self), driver_filename_ (driver_filename) | |
116 { | |
117 } | |
118 virtual ~compiler_driver_filename () | |
119 { | |
120 } | |
121 }; | |
122 }; | |
123 | |
124 // A local subclass of connection that holds a back-pointer to the | |
125 // gcc_c_context object that we provide to our caller. | |
126 class libcp1_connection : public cc1_plugin::connection | |
127 { | |
128 public: | |
129 | |
130 libcp1_connection (int fd, int aux_fd, libcp1 *b) | |
131 : connection (fd, aux_fd), | |
132 back_ptr (b) | |
133 { | |
134 } | |
135 | |
136 virtual void print (const char *buf) | |
137 { | |
138 back_ptr->print (buf); | |
139 } | |
140 | |
141 libcp1 *back_ptr; | |
142 }; | |
143 | |
144 libcp1::libcp1 (const gcc_base_vtable *v, | |
145 const gcc_cp_fe_vtable *cv) | |
146 : connection (NULL), | |
147 binding_oracle (NULL), | |
148 address_oracle (NULL), | |
149 oracle_datum (NULL), | |
150 print_function (NULL), | |
151 print_datum (NULL), | |
152 args (), | |
153 source_file (), | |
154 verbose (false), | |
155 compilerp (new libcp1::compiler (this)) | |
156 { | |
157 base.ops = v; | |
158 cp_ops = cv; | |
159 } | |
160 | |
161 libcp1::~libcp1 () | |
162 { | |
163 delete connection; | |
164 delete compilerp; | |
165 } | |
166 | |
167 | |
168 | |
169 // Enclose these functions in an anonymous namespace because they | |
170 // shouldn't be exported, but they can't be static because they're | |
171 // used as template arguments. | |
172 namespace { | |
173 // This is a wrapper function that is called by the RPC system and | |
174 // that then forwards the call to the library user. Note that the | |
175 // return value is not used; the type cannot be 'void' due to | |
176 // limitations in our simple RPC. | |
177 int | |
178 cp_call_binding_oracle (cc1_plugin::connection *conn, | |
179 enum gcc_cp_oracle_request request, | |
180 const char *identifier) | |
181 { | |
182 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; | |
183 | |
184 self->binding_oracle (self->oracle_datum, self, request, identifier); | |
185 return 1; | |
186 } | |
187 | |
188 // This is a wrapper function that is called by the RPC system and | |
189 // that then forwards the call to the library user. | |
190 gcc_address | |
191 cp_call_symbol_address (cc1_plugin::connection *conn, const char *identifier) | |
192 { | |
193 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; | |
194 | |
195 return self->address_oracle (self->oracle_datum, self, identifier); | |
196 } | |
197 | |
198 int | |
199 cp_call_enter_scope (cc1_plugin::connection *conn) | |
200 { | |
201 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; | |
202 | |
203 self->enter_scope (self->oracle_datum, self); | |
204 return 1; | |
205 } | |
206 | |
207 int | |
208 cp_call_leave_scope (cc1_plugin::connection *conn) | |
209 { | |
210 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; | |
211 | |
212 self->leave_scope (self->oracle_datum, self); | |
213 return 1; | |
214 } | |
215 } /* anonymous namespace */ | |
216 | |
217 | |
218 | |
219 static void | |
220 set_callbacks (struct gcc_cp_context *s, | |
221 gcc_cp_oracle_function *binding_oracle, | |
222 gcc_cp_symbol_address_function *address_oracle, | |
223 gcc_cp_enter_leave_user_expr_scope_function *enter_scope, | |
224 gcc_cp_enter_leave_user_expr_scope_function *leave_scope, | |
225 void *datum) | |
226 { | |
227 libcp1 *self = (libcp1 *) s; | |
228 | |
229 self->binding_oracle = binding_oracle; | |
230 self->address_oracle = address_oracle; | |
231 self->enter_scope = enter_scope; | |
232 self->leave_scope = leave_scope; | |
233 self->oracle_datum = datum; | |
234 } | |
235 | |
236 // Instances of these rpc<> template functions are installed into the | |
237 // "cp_vtable". These functions are parameterized by type and method | |
238 // name and forward the call via the connection. | |
239 | |
240 template<typename R, const char *&NAME> | |
241 R rpc (struct gcc_cp_context *s) | |
242 { | |
243 libcp1 *self = (libcp1 *) s; | |
244 R result; | |
245 | |
246 if (!cc1_plugin::call (self->connection, NAME, &result)) | |
247 return 0; | |
248 return result; | |
249 } | |
250 | |
251 template<typename R, const char *&NAME, typename A> | |
252 R rpc (struct gcc_cp_context *s, A arg) | |
253 { | |
254 libcp1 *self = (libcp1 *) s; | |
255 R result; | |
256 | |
257 if (!cc1_plugin::call (self->connection, NAME, &result, arg)) | |
258 return 0; | |
259 return result; | |
260 } | |
261 | |
262 template<typename R, const char *&NAME, typename A1, typename A2> | |
263 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2) | |
264 { | |
265 libcp1 *self = (libcp1 *) s; | |
266 R result; | |
267 | |
268 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2)) | |
269 return 0; | |
270 return result; | |
271 } | |
272 | |
273 template<typename R, const char *&NAME, typename A1, typename A2, typename A3> | |
274 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3) | |
275 { | |
276 libcp1 *self = (libcp1 *) s; | |
277 R result; | |
278 | |
279 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3)) | |
280 return 0; | |
281 return result; | |
282 } | |
283 | |
284 template<typename R, const char *&NAME, typename A1, typename A2, typename A3, | |
285 typename A4> | |
286 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4) | |
287 { | |
288 libcp1 *self = (libcp1 *) s; | |
289 R result; | |
290 | |
291 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3, | |
292 arg4)) | |
293 return 0; | |
294 return result; | |
295 } | |
296 | |
297 template<typename R, const char *&NAME, typename A1, typename A2, typename A3, | |
298 typename A4, typename A5> | |
299 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) | |
300 { | |
301 libcp1 *self = (libcp1 *) s; | |
302 R result; | |
303 | |
304 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3, | |
305 arg4, arg5)) | |
306 return 0; | |
307 return result; | |
308 } | |
309 | |
310 template<typename R, const char *&NAME, typename A1, typename A2, typename A3, | |
311 typename A4, typename A5, typename A6, typename A7> | |
312 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, | |
313 A6 arg6, A7 arg7) | |
314 { | |
315 libcp1 *self = (libcp1 *) s; | |
316 R result; | |
317 | |
318 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3, | |
319 arg4, arg5, arg6, arg7)) | |
320 return 0; | |
321 return result; | |
322 } | |
323 | |
324 static const struct gcc_cp_fe_vtable cp_vtable = | |
325 { | |
326 GCC_CP_FE_VERSION_0, | |
327 set_callbacks, | |
328 | |
329 #define GCC_METHOD0(R, N) \ | |
330 rpc<R, cc1_plugin::cp::N>, | |
331 #define GCC_METHOD1(R, N, A) \ | |
332 rpc<R, cc1_plugin::cp::N, A>, | |
333 #define GCC_METHOD2(R, N, A, B) \ | |
334 rpc<R, cc1_plugin::cp::N, A, B>, | |
335 #define GCC_METHOD3(R, N, A, B, C) \ | |
336 rpc<R, cc1_plugin::cp::N, A, B, C>, | |
337 #define GCC_METHOD4(R, N, A, B, C, D) \ | |
338 rpc<R, cc1_plugin::cp::N, A, B, C, D>, | |
339 #define GCC_METHOD5(R, N, A, B, C, D, E) \ | |
340 rpc<R, cc1_plugin::cp::N, A, B, C, D, E>, | |
341 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ | |
342 rpc<R, cc1_plugin::cp::N, A, B, C, D, E, F, G>, | |
343 | |
344 #include "gcc-cp-fe.def" | |
345 | |
346 #undef GCC_METHOD0 | |
347 #undef GCC_METHOD1 | |
348 #undef GCC_METHOD2 | |
349 #undef GCC_METHOD3 | |
350 #undef GCC_METHOD4 | |
351 #undef GCC_METHOD5 | |
352 #undef GCC_METHOD7 | |
353 }; | |
354 | |
355 | |
356 | |
357 // Construct an appropriate regexp to match the compiler name. | |
358 static std::string | |
359 make_regexp (const char *triplet_regexp, const char *compiler) | |
360 { | |
361 std::stringstream buf; | |
362 | |
363 buf << "^" << triplet_regexp << "-"; | |
364 | |
365 // Quote the compiler name in case it has something funny in it. | |
366 for (const char *p = compiler; *p; ++p) | |
367 { | |
368 switch (*p) | |
369 { | |
370 case '.': | |
371 case '^': | |
372 case '$': | |
373 case '*': | |
374 case '+': | |
375 case '?': | |
376 case '(': | |
377 case ')': | |
378 case '[': | |
379 case '{': | |
380 case '\\': | |
381 case '|': | |
382 buf << '\\'; | |
383 break; | |
384 } | |
385 buf << *p; | |
386 } | |
387 buf << "$"; | |
388 | |
389 return buf.str (); | |
390 } | |
391 | |
392 static void | |
393 libcp1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose) | |
394 { | |
395 libcp1 *self = (libcp1 *) s; | |
396 | |
397 self->verbose = verbose != 0; | |
398 } | |
399 | |
400 char * | |
401 libcp1::compiler::find (std::string &compiler ATTRIBUTE_UNUSED) const | |
402 { | |
403 return xstrdup (_("Compiler has not been specified")); | |
404 } | |
405 | |
406 char * | |
407 libcp1::compiler_triplet_regexp::find (std::string &compiler) const | |
408 { | |
409 std::string rx = make_regexp (triplet_regexp_.c_str (), CP_COMPILER_NAME); | |
410 if (self_->verbose) | |
411 fprintf (stderr, _("searching for compiler matching regex %s\n"), | |
412 rx.c_str()); | |
413 regex_t triplet; | |
414 int code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB); | |
415 if (code != 0) | |
416 { | |
417 size_t len = regerror (code, &triplet, NULL, 0); | |
418 char err[len]; | |
419 | |
420 regerror (code, &triplet, err, len); | |
421 | |
422 return concat ("Could not compile regexp \"", | |
423 rx.c_str (), | |
424 "\": ", | |
425 err, | |
426 (char *) NULL); | |
427 } | |
428 | |
429 if (!find_compiler (triplet, &compiler)) | |
430 { | |
431 regfree (&triplet); | |
432 return concat ("Could not find a compiler matching \"", | |
433 rx.c_str (), | |
434 "\"", | |
435 (char *) NULL); | |
436 } | |
437 regfree (&triplet); | |
438 if (self_->verbose) | |
439 fprintf (stderr, _("found compiler %s\n"), compiler.c_str()); | |
440 return NULL; | |
441 } | |
442 | |
443 char * | |
444 libcp1::compiler_driver_filename::find (std::string &compiler) const | |
445 { | |
446 // Simulate fnotice by fprintf. | |
447 if (self_->verbose) | |
448 fprintf (stderr, _("using explicit compiler filename %s\n"), | |
449 driver_filename_.c_str()); | |
450 compiler = driver_filename_; | |
451 return NULL; | |
452 } | |
453 | |
454 static char * | |
455 libcp1_set_arguments (struct gcc_base_context *s, | |
456 int argc, char **argv) | |
457 { | |
458 libcp1 *self = (libcp1 *) s; | |
459 | |
460 std::string compiler; | |
461 char *errmsg = self->compilerp->find (compiler); | |
462 if (errmsg != NULL) | |
463 return errmsg; | |
464 | |
465 self->args.push_back (compiler); | |
466 | |
467 for (int i = 0; i < argc; ++i) | |
468 self->args.push_back (argv[i]); | |
469 | |
470 return NULL; | |
471 } | |
472 | |
473 static char * | |
474 libcp1_set_triplet_regexp (struct gcc_base_context *s, | |
475 const char *triplet_regexp) | |
476 { | |
477 libcp1 *self = (libcp1 *) s; | |
478 | |
479 delete self->compilerp; | |
480 self->compilerp = new libcp1::compiler_triplet_regexp (self, triplet_regexp); | |
481 return NULL; | |
482 } | |
483 | |
484 static char * | |
485 libcp1_set_driver_filename (struct gcc_base_context *s, | |
486 const char *driver_filename) | |
487 { | |
488 libcp1 *self = (libcp1 *) s; | |
489 | |
490 delete self->compilerp; | |
491 self->compilerp = new libcp1::compiler_driver_filename (self, | |
492 driver_filename); | |
493 return NULL; | |
494 } | |
495 | |
496 static char * | |
497 libcp1_set_arguments_v0 (struct gcc_base_context *s, | |
498 const char *triplet_regexp, | |
499 int argc, char **argv) | |
500 { | |
501 char *errmsg = libcp1_set_triplet_regexp (s, triplet_regexp); | |
502 if (errmsg != NULL) | |
503 return errmsg; | |
504 | |
505 return libcp1_set_arguments (s, argc, argv); | |
506 } | |
507 | |
508 static void | |
509 libcp1_set_source_file (struct gcc_base_context *s, | |
510 const char *file) | |
511 { | |
512 libcp1 *self = (libcp1 *) s; | |
513 | |
514 self->source_file = file; | |
515 } | |
516 | |
517 static void | |
518 libcp1_set_print_callback (struct gcc_base_context *s, | |
519 void (*print_function) (void *datum, | |
520 const char *message), | |
521 void *datum) | |
522 { | |
523 libcp1 *self = (libcp1 *) s; | |
524 | |
525 self->print_function = print_function; | |
526 self->print_datum = datum; | |
527 } | |
528 | |
529 static int | |
530 fork_exec (libcp1 *self, char **argv, int spair_fds[2], int stderr_fds[2]) | |
531 { | |
532 pid_t child_pid = fork (); | |
533 | |
534 if (child_pid == -1) | |
535 { | |
536 close (spair_fds[0]); | |
537 close (spair_fds[1]); | |
538 close (stderr_fds[0]); | |
539 close (stderr_fds[1]); | |
540 return 0; | |
541 } | |
542 | |
543 if (child_pid == 0) | |
544 { | |
545 // Child. | |
546 dup2 (stderr_fds[1], 1); | |
547 dup2 (stderr_fds[1], 2); | |
548 close (stderr_fds[0]); | |
549 close (stderr_fds[1]); | |
550 close (spair_fds[0]); | |
551 | |
552 execvp (argv[0], argv); | |
553 _exit (127); | |
554 } | |
555 else | |
556 { | |
557 // Parent. | |
558 close (spair_fds[1]); | |
559 close (stderr_fds[1]); | |
560 | |
561 cc1_plugin::status result = cc1_plugin::FAIL; | |
562 if (self->connection->send ('H') | |
563 && ::cc1_plugin::marshall (self->connection, GCC_CP_FE_VERSION_0)) | |
564 result = self->connection->wait_for_query (); | |
565 | |
566 close (spair_fds[0]); | |
567 close (stderr_fds[0]); | |
568 | |
569 while (true) | |
570 { | |
571 int status; | |
572 | |
573 if (waitpid (child_pid, &status, 0) == -1) | |
574 { | |
575 if (errno != EINTR) | |
576 return 0; | |
577 } | |
578 | |
579 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) | |
580 return 0; | |
581 break; | |
582 } | |
583 | |
584 if (!result) | |
585 return 0; | |
586 return 1; | |
587 } | |
588 } | |
589 | |
590 static int | |
591 libcp1_compile (struct gcc_base_context *s, | |
592 const char *filename) | |
593 { | |
594 libcp1 *self = (libcp1 *) s; | |
595 | |
596 int fds[2]; | |
597 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0) | |
598 { | |
599 self->print ("could not create socketpair\n"); | |
600 return 0; | |
601 } | |
602 | |
603 int stderr_fds[2]; | |
604 if (pipe (stderr_fds) != 0) | |
605 { | |
606 self->print ("could not create pipe\n"); | |
607 close (fds[0]); | |
608 close (fds[1]); | |
609 return 0; | |
610 } | |
611 | |
612 self->args.push_back ("-fplugin=libcp1plugin"); | |
613 char buf[100]; | |
614 if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcp1plugin-fd=%d", fds[1]) | |
615 >= (long) sizeof (buf)) | |
616 abort (); | |
617 self->args.push_back (buf); | |
618 | |
619 self->args.push_back (self->source_file); | |
620 self->args.push_back ("-c"); | |
621 self->args.push_back ("-o"); | |
622 self->args.push_back (filename); | |
623 if (self->verbose) | |
624 self->args.push_back ("-v"); | |
625 | |
626 self->connection = new libcp1_connection (fds[0], stderr_fds[0], self); | |
627 | |
628 cc1_plugin::callback_ftype *fun | |
629 = cc1_plugin::callback<int, | |
630 enum gcc_cp_oracle_request, | |
631 const char *, | |
632 cp_call_binding_oracle>; | |
633 self->connection->add_callback ("binding_oracle", fun); | |
634 | |
635 fun = cc1_plugin::callback<gcc_address, | |
636 const char *, | |
637 cp_call_symbol_address>; | |
638 self->connection->add_callback ("address_oracle", fun); | |
639 | |
640 fun = cc1_plugin::callback<int, | |
641 cp_call_enter_scope>; | |
642 self->connection->add_callback ("enter_scope", fun); | |
643 | |
644 fun = cc1_plugin::callback<int, | |
645 cp_call_leave_scope>; | |
646 self->connection->add_callback ("leave_scope", fun); | |
647 | |
648 char **argv = new (std::nothrow) char *[self->args.size () + 1]; | |
649 if (argv == NULL) | |
650 return 0; | |
651 | |
652 for (unsigned int i = 0; i < self->args.size (); ++i) | |
653 argv[i] = const_cast<char *> (self->args[i].c_str ()); | |
654 argv[self->args.size ()] = NULL; | |
655 | |
656 return fork_exec (self, argv, fds, stderr_fds); | |
657 } | |
658 | |
659 static int | |
660 libcp1_compile_v0 (struct gcc_base_context *s, const char *filename, | |
661 int verbose) | |
662 { | |
663 libcp1_set_verbose (s, verbose); | |
664 return libcp1_compile (s, filename); | |
665 } | |
666 | |
667 static void | |
668 libcp1_destroy (struct gcc_base_context *s) | |
669 { | |
670 libcp1 *self = (libcp1 *) s; | |
671 | |
672 delete self; | |
673 } | |
674 | |
675 static const struct gcc_base_vtable vtable = | |
676 { | |
677 GCC_FE_VERSION_0, | |
678 libcp1_set_arguments_v0, | |
679 libcp1_set_source_file, | |
680 libcp1_set_print_callback, | |
681 libcp1_compile_v0, | |
682 libcp1_destroy, | |
683 libcp1_set_verbose, | |
684 libcp1_compile, | |
685 libcp1_set_arguments, | |
686 libcp1_set_triplet_regexp, | |
687 libcp1_set_driver_filename, | |
688 }; | |
689 | |
690 extern "C" gcc_cp_fe_context_function gcc_cp_fe_context; | |
691 | |
692 #ifdef __GNUC__ | |
693 #pragma GCC visibility push(default) | |
694 #endif | |
695 | |
696 extern "C" | |
697 struct gcc_cp_context * | |
698 gcc_cp_fe_context (enum gcc_base_api_version base_version, | |
699 enum gcc_cp_api_version cp_version) | |
700 { | |
701 if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1) | |
702 || cp_version != GCC_CP_FE_VERSION_0) | |
703 return NULL; | |
704 | |
705 return new libcp1 (&vtable, &cp_vtable); | |
706 } |