1 /*
2  * Copyright 2016, 2017 Tobias Grosser. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *    1. Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *
11  *    2. Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY TOBIAS GROSSER ''AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * The views and conclusions contained in the software and documentation
29  * are those of the authors and should not be interpreted as
30  * representing official policies, either expressed or implied, of
31  * Tobias Grosser.
32  */
33 
34 #include <cstdarg>
35 #include <cstdio>
36 #include <iostream>
37 #include <map>
38 #include <sstream>
39 #include <string>
40 #include <vector>
41 
42 #include "cpp.h"
43 #include "isl_config.h"
44 
45 /* Print string formatted according to "fmt" to ostream "os".
46  *
47  * This osprintf method allows us to use printf style formatting constructs when
48  * writing to an ostream.
49  */
50 static void osprintf(ostream &os, const char *format, ...)
51 {
52 	va_list arguments;
53 	char *string_pointer;
54 	size_t size;
55 
56 	va_start(arguments, format);
57 	size = vsnprintf(NULL, 0, format, arguments);
58 	string_pointer = new char[size + 1];
59 	va_end(arguments);
60 	va_start(arguments, format);
61 	vsnprintf(string_pointer, size + 1, format, arguments);
62 	va_end(arguments);
63 	os << string_pointer;
64 	delete[] string_pointer;
65 }
66 
67 /* Convert "l" to a string.
68  */
69 static std::string to_string(long l)
70 {
71 	std::ostringstream strm;
72 	strm << l;
73 	return strm.str();
74 }
75 
76 /* Generate a cpp interface based on the extracted types and functions.
77  *
78  * Print first a set of forward declarations for all isl wrapper
79  * classes, then the declarations of the classes, and at the end all
80  * implementations.
81  *
82  * If checked C++ bindings are being generated,
83  * then wrap them in a namespace to avoid conflicts
84  * with the default C++ bindings (with automatic checks using exceptions).
85  */
86 void cpp_generator::generate()
87 {
88 	ostream &os = cout;
89 
90 	osprintf(os, "\n");
91 	osprintf(os, "namespace isl {\n\n");
92 	if (checked)
93 		osprintf(os, "namespace checked {\n\n");
94 
95 	print_forward_declarations(os);
96 	osprintf(os, "\n");
97 	print_declarations(os);
98 	osprintf(os, "\n");
99 	print_implementations(os);
100 
101 	if (checked)
102 		osprintf(os, "} // namespace checked\n");
103 	osprintf(os, "} // namespace isl\n");
104 }
105 
106 /* Print forward declarations for all classes to "os".
107 */
108 void cpp_generator::print_forward_declarations(ostream &os)
109 {
110 	map<string, isl_class>::iterator ci;
111 
112 	osprintf(os, "// forward declarations\n");
113 
114 	for (ci = classes.begin(); ci != classes.end(); ++ci)
115 		print_class_forward_decl(os, ci->second);
116 }
117 
118 /* Print all declarations to "os".
119  */
120 void cpp_generator::print_declarations(ostream &os)
121 {
122 	map<string, isl_class>::iterator ci;
123 	bool first = true;
124 
125 	for (ci = classes.begin(); ci != classes.end(); ++ci) {
126 		if (first)
127 			first = false;
128 		else
129 			osprintf(os, "\n");
130 
131 		print_class(os, ci->second);
132 	}
133 }
134 
135 /* Print all implementations to "os".
136  */
137 void cpp_generator::print_implementations(ostream &os)
138 {
139 	map<string, isl_class>::iterator ci;
140 	bool first = true;
141 
142 	for (ci = classes.begin(); ci != classes.end(); ++ci) {
143 		if (first)
144 			first = false;
145 		else
146 			osprintf(os, "\n");
147 
148 		print_class_impl(os, ci->second);
149 	}
150 }
151 
152 /* Print declarations for class "clazz" to "os".
153  */
154 void cpp_generator::print_class(ostream &os, const isl_class &clazz)
155 {
156 	const char *name = clazz.name.c_str();
157 	std::string cppstring = type2cpp(clazz);
158 	const char *cppname = cppstring.c_str();
159 
160 	osprintf(os, "// declarations for isl::%s\n", cppname);
161 
162 	print_class_factory_decl(os, clazz);
163 	osprintf(os, "\n");
164 	osprintf(os, "class %s {\n", cppname);
165 	print_class_factory_decl(os, clazz, "  friend ");
166 	osprintf(os, "\n");
167 	osprintf(os, "  %s *ptr = nullptr;\n", name);
168 	osprintf(os, "\n");
169 	print_private_constructors_decl(os, clazz);
170 	osprintf(os, "\n");
171 	osprintf(os, "public:\n");
172 	print_public_constructors_decl(os, clazz);
173 	print_constructors_decl(os, clazz);
174 	print_copy_assignment_decl(os, clazz);
175 	print_destructor_decl(os, clazz);
176 	print_ptr_decl(os, clazz);
177 	print_get_ctx_decl(os);
178 	osprintf(os, "\n");
179 	print_methods_decl(os, clazz);
180 
181 	osprintf(os, "};\n");
182 }
183 
184 /* Print forward declaration of class "clazz" to "os".
185  */
186 void cpp_generator::print_class_forward_decl(ostream &os,
187 	const isl_class &clazz)
188 {
189 	std::string cppstring = type2cpp(clazz);
190 	const char *cppname = cppstring.c_str();
191 
192 	osprintf(os, "class %s;\n", cppname);
193 }
194 
195 /* Print global factory functions to "os".
196  *
197  * Each class has two global factory functions:
198  *
199  * 	set manage(__isl_take isl_set *ptr);
200  * 	set manage_copy(__isl_keep isl_set *ptr);
201  *
202  * A user can construct isl C++ objects from a raw pointer and indicate whether
203  * they intend to take the ownership of the object or not through these global
204  * factory functions. This ensures isl object creation is very explicit and
205  * pointers are not converted by accident. Thanks to overloading, manage() and
206  * manage_copy() can be called on any isl raw pointer and the corresponding
207  * object is automatically created, without the user having to choose the right
208  * isl object type.
209  */
210 void cpp_generator::print_class_factory_decl(ostream &os,
211 	const isl_class &clazz, const std::string &prefix)
212 {
213 	const char *name = clazz.name.c_str();
214 	std::string cppstring = type2cpp(clazz);
215 	const char *cppname = cppstring.c_str();
216 
217 	os << prefix;
218 	osprintf(os, "inline %s manage(__isl_take %s *ptr);\n", cppname, name);
219 	os << prefix;
220 	osprintf(os, "inline %s manage_copy(__isl_keep %s *ptr);\n",
221 		cppname, name);
222 }
223 
224 /* Print declarations of private constructors for class "clazz" to "os".
225  *
226  * Each class has currently one private constructor:
227  *
228  * 	1) Constructor from a plain isl_* C pointer
229  *
230  * Example:
231  *
232  * 	set(__isl_take isl_set *ptr);
233  *
234  * The raw pointer constructor is kept private. Object creation is only
235  * possible through manage() or manage_copy().
236  */
237 void cpp_generator::print_private_constructors_decl(ostream &os,
238 	const isl_class &clazz)
239 {
240 	const char *name = clazz.name.c_str();
241 	std::string cppstring = type2cpp(clazz);
242 	const char *cppname = cppstring.c_str();
243 
244 	osprintf(os, "  inline explicit %s(__isl_take %s *ptr);\n", cppname,
245 		 name);
246 }
247 
248 /* Print declarations of public constructors for class "clazz" to "os".
249  *
250  * Each class currently has two public constructors:
251  *
252  * 	1) A default constructor
253  * 	2) A copy constructor
254  *
255  * Example:
256  *
257  *	set();
258  *	set(const set &set);
259  */
260 void cpp_generator::print_public_constructors_decl(ostream &os,
261 	const isl_class &clazz)
262 {
263 	std::string cppstring = type2cpp(clazz);
264 	const char *cppname = cppstring.c_str();
265 	osprintf(os, "  inline /* implicit */ %s();\n", cppname);
266 
267 	osprintf(os, "  inline /* implicit */ %s(const %s &obj);\n",
268 		 cppname, cppname);
269 }
270 
271 /* Print declarations for constructors for class "class" to "os".
272  *
273  * For each isl function that is marked as __isl_constructor,
274  * add a corresponding C++ constructor.
275  *
276  * Example:
277  *
278  * 	inline /\* implicit *\/ union_set(basic_set bset);
279  * 	inline /\* implicit *\/ union_set(set set);
280  * 	inline explicit val(ctx ctx, long i);
281  * 	inline explicit val(ctx ctx, const std::string &str);
282  */
283 void cpp_generator::print_constructors_decl(ostream &os,
284        const isl_class &clazz)
285 {
286 	set<FunctionDecl *>::const_iterator in;
287 	const set<FunctionDecl *> &constructors = clazz.constructors;
288 
289 	for (in = constructors.begin(); in != constructors.end(); ++in) {
290 		FunctionDecl *cons = *in;
291 
292 		print_method_decl(os, clazz, cons, function_kind_constructor);
293 	}
294 }
295 
296 /* Print declarations of copy assignment operator for class "clazz"
297  * to "os".
298  *
299  * Each class has one assignment operator.
300  *
301  * 	isl:set &set::operator=(set obj)
302  *
303  */
304 void cpp_generator::print_copy_assignment_decl(ostream &os,
305 	const isl_class &clazz)
306 {
307 	std::string cppstring = type2cpp(clazz);
308 	const char *cppname = cppstring.c_str();
309 
310 	osprintf(os, "  inline %s &operator=(%s obj);\n", cppname, cppname);
311 }
312 
313 /* Print declaration of destructor for class "clazz" to "os".
314  */
315 void cpp_generator::print_destructor_decl(ostream &os, const isl_class &clazz)
316 {
317 	std::string cppstring = type2cpp(clazz);
318 	const char *cppname = cppstring.c_str();
319 
320 	osprintf(os, "  inline ~%s();\n", cppname);
321 }
322 
323 /* Print declaration of pointer functions for class "clazz" to "os".
324  *
325  * To obtain a raw pointer three functions are provided:
326  *
327  * 	1) __isl_give isl_set *copy()
328  *
329  * 	  Returns a pointer to a _copy_ of the internal object
330  *
331  * 	2) __isl_keep isl_set *get()
332  *
333  * 	  Returns a pointer to the internal object
334  *
335  * 	3) __isl_give isl_set *release()
336  *
337  * 	  Returns a pointer to the internal object and resets the
338  * 	  internal pointer to nullptr.
339  *
340  * We also provide functionality to explicitly check if a pointer is
341  * currently managed by this object.
342  *
343  * 	4) bool is_null()
344  *
345  * 	  Check if the current object is a null pointer.
346  *
347  * The functions get() and release() model the value_ptr proposed in
348  * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3339.pdf.
349  * The copy() function is an extension to allow the user to explicitly
350  * copy the underlying object.
351  *
352  * Also generate a declaration to delete copy() for r-values, for
353  * r-values release() should be used to avoid unnecessary copies.
354  */
355 void cpp_generator::print_ptr_decl(ostream &os, const isl_class &clazz)
356 {
357 	const char *name = clazz.name.c_str();
358 
359 	osprintf(os, "  inline __isl_give %s *copy() const &;\n", name);
360 	osprintf(os, "  inline __isl_give %s *copy() && = delete;\n", name);
361 	osprintf(os, "  inline __isl_keep %s *get() const;\n", name);
362 	osprintf(os, "  inline __isl_give %s *release();\n", name);
363 	osprintf(os, "  inline bool is_null() const;\n");
364 }
365 
366 /* Print the declaration of the get_ctx method.
367  */
368 void cpp_generator::print_get_ctx_decl(ostream &os)
369 {
370 	osprintf(os, "  inline ctx get_ctx() const;\n");
371 }
372 
373 /* Print declarations for methods in class "clazz" to "os".
374  */
375 void cpp_generator::print_methods_decl(ostream &os, const isl_class &clazz)
376 {
377 	map<string, set<FunctionDecl *> >::const_iterator it;
378 
379 	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
380 		print_method_group_decl(os, clazz, it->second);
381 }
382 
383 /* Print declarations for methods "methods" in class "clazz" to "os".
384  */
385 void cpp_generator::print_method_group_decl(ostream &os, const isl_class &clazz,
386 	const set<FunctionDecl *> &methods)
387 {
388 	set<FunctionDecl *>::const_iterator it;
389 
390 	for (it = methods.begin(); it != methods.end(); ++it) {
391 		function_kind kind = get_method_kind(clazz, *it);
392 		print_method_decl(os, clazz, *it, kind);
393 	}
394 }
395 
396 /* Print declarations for "method" in class "clazz" to "os".
397  *
398  * "kind" specifies the kind of method that should be generated.
399  */
400 void cpp_generator::print_method_decl(ostream &os, const isl_class &clazz,
401 	FunctionDecl *method, function_kind kind)
402 {
403 	print_method_header(os, clazz, method, true, kind);
404 }
405 
406 /* Print implementations for class "clazz" to "os".
407  */
408 void cpp_generator::print_class_impl(ostream &os, const isl_class &clazz)
409 {
410 	std::string cppstring = type2cpp(clazz);
411 	const char *cppname = cppstring.c_str();
412 
413 	osprintf(os, "// implementations for isl::%s\n", cppname);
414 
415 	print_class_factory_impl(os, clazz);
416 	osprintf(os, "\n");
417 	print_public_constructors_impl(os, clazz);
418 	osprintf(os, "\n");
419 	print_private_constructors_impl(os, clazz);
420 	osprintf(os, "\n");
421 	print_constructors_impl(os, clazz);
422 	osprintf(os, "\n");
423 	print_copy_assignment_impl(os, clazz);
424 	osprintf(os, "\n");
425 	print_destructor_impl(os, clazz);
426 	osprintf(os, "\n");
427 	print_ptr_impl(os, clazz);
428 	osprintf(os, "\n");
429 	print_get_ctx_impl(os, clazz);
430 	osprintf(os, "\n");
431 	print_methods_impl(os, clazz);
432 }
433 
434 /* Print code for throwing an exception corresponding to the last error
435  * that occurred on "ctx".
436  * This assumes that a valid isl::ctx is available in the "ctx" variable,
437  * e.g., through a prior call to print_save_ctx.
438  */
439 static void print_throw_last_error(ostream &os)
440 {
441 	osprintf(os, "    exception::throw_last_error(ctx);\n");
442 }
443 
444 /* Print code for throwing an exception on NULL input.
445  */
446 static void print_throw_NULL_input(ostream &os)
447 {
448 	osprintf(os, "    exception::throw_NULL_input(__FILE__, __LINE__);\n");
449 }
450 
451 /* Print code that checks that "ptr" is not NULL at input.
452  *
453  * Omit the check if checked C++ bindings are being generated.
454  */
455 void cpp_generator::print_check_ptr(ostream &os, const char *ptr)
456 {
457 	if (checked)
458 		return;
459 
460 	osprintf(os, "  if (!%s)\n", ptr);
461 	print_throw_NULL_input(os);
462 }
463 
464 /* Print code that checks that "ptr" is not NULL at input and
465  * that saves a copy of the isl_ctx of "ptr" for a later check.
466  *
467  * Omit the check if checked C++ bindings are being generated.
468  */
469 void cpp_generator::print_check_ptr_start(ostream &os, const isl_class &clazz,
470 	const char *ptr)
471 {
472 	if (checked)
473 		return;
474 
475 	print_check_ptr(os, ptr);
476 	osprintf(os, "  auto ctx = %s_get_ctx(%s);\n", clazz.name.c_str(), ptr);
477 	print_on_error_continue(os);
478 }
479 
480 /* Print code that checks that "ptr" is not NULL at the end.
481  * A copy of the isl_ctx is expected to have been saved by
482  * code generated by print_check_ptr_start.
483  *
484  * Omit the check if checked C++ bindings are being generated.
485  */
486 void cpp_generator::print_check_ptr_end(ostream &os, const char *ptr)
487 {
488 	if (checked)
489 		return;
490 
491 	osprintf(os, "  if (!%s)\n", ptr);
492 	print_throw_last_error(os);
493 }
494 
495 /* Print implementation of global factory functions to "os".
496  *
497  * Each class has two global factory functions:
498  *
499  * 	set manage(__isl_take isl_set *ptr);
500  * 	set manage_copy(__isl_keep isl_set *ptr);
501  *
502  * Unless checked C++ bindings are being generated,
503  * both functions require the argument to be non-NULL.
504  * An exception is thrown if anything went wrong during the copying
505  * in manage_copy.
506  * During the copying, isl is made not to print any error message
507  * because the error message is included in the exception.
508  */
509 void cpp_generator::print_class_factory_impl(ostream &os,
510 	const isl_class &clazz)
511 {
512 	const char *name = clazz.name.c_str();
513 	std::string cppstring = type2cpp(clazz);
514 	const char *cppname = cppstring.c_str();
515 
516 	osprintf(os, "%s manage(__isl_take %s *ptr) {\n", cppname, name);
517 	print_check_ptr(os, "ptr");
518 	osprintf(os, "  return %s(ptr);\n", cppname);
519 	osprintf(os, "}\n");
520 
521 	osprintf(os, "%s manage_copy(__isl_keep %s *ptr) {\n", cppname,
522 		name);
523 	print_check_ptr_start(os, clazz, "ptr");
524 	osprintf(os, "  ptr = %s_copy(ptr);\n", name);
525 	print_check_ptr_end(os, "ptr");
526 	osprintf(os, "  return %s(ptr);\n", cppname);
527 	osprintf(os, "}\n");
528 }
529 
530 /* Print implementations of private constructors for class "clazz" to "os".
531  */
532 void cpp_generator::print_private_constructors_impl(ostream &os,
533 	const isl_class &clazz)
534 {
535 	const char *name = clazz.name.c_str();
536 	std::string cppstring = type2cpp(clazz);
537 	const char *cppname = cppstring.c_str();
538 
539 	osprintf(os, "%s::%s(__isl_take %s *ptr)\n    : ptr(ptr) {}\n",
540 		 cppname, cppname, name);
541 }
542 
543 /* Print implementations of public constructors for class "clazz" to "os".
544  *
545  * Throw an exception from the copy constructor if anything went wrong
546  * during the copying or if the input is NULL.
547  * During the copying, isl is made not to print any error message
548  * because the error message is included in the exception.
549  * No exceptions are thrown if checked C++ bindings
550  * are being generated,
551  */
552 void cpp_generator::print_public_constructors_impl(ostream &os,
553 	const isl_class &clazz)
554 {
555 	std::string cppstring = type2cpp(clazz);
556 	const char *cppname = cppstring.c_str();
557 
558 	osprintf(os, "%s::%s()\n    : ptr(nullptr) {}\n\n", cppname, cppname);
559 	osprintf(os, "%s::%s(const %s &obj)\n    : ptr(nullptr)\n",
560 		 cppname, cppname, cppname);
561 	osprintf(os, "{\n");
562 	print_check_ptr_start(os, clazz, "obj.ptr");
563 	osprintf(os, "  ptr = obj.copy();\n");
564 	print_check_ptr_end(os, "ptr");
565 	osprintf(os, "}\n");
566 }
567 
568 /* Print implementations of constructors for class "clazz" to "os".
569  */
570 void cpp_generator::print_constructors_impl(ostream &os,
571        const isl_class &clazz)
572 {
573 	set<FunctionDecl *>::const_iterator in;
574 	const set<FunctionDecl *> constructors = clazz.constructors;
575 
576 	for (in = constructors.begin(); in != constructors.end(); ++in) {
577 		FunctionDecl *cons = *in;
578 
579 		print_method_impl(os, clazz, cons, function_kind_constructor);
580 	}
581 }
582 
583 /* Print implementation of copy assignment operator for class "clazz" to "os".
584  */
585 void cpp_generator::print_copy_assignment_impl(ostream &os,
586 	const isl_class &clazz)
587 {
588 	const char *name = clazz.name.c_str();
589 	std::string cppstring = type2cpp(clazz);
590 	const char *cppname = cppstring.c_str();
591 
592 	osprintf(os, "%s &%s::operator=(%s obj) {\n", cppname,
593 		 cppname, cppname);
594 	osprintf(os, "  std::swap(this->ptr, obj.ptr);\n", name);
595 	osprintf(os, "  return *this;\n");
596 	osprintf(os, "}\n");
597 }
598 
599 /* Print implementation of destructor for class "clazz" to "os".
600  */
601 void cpp_generator::print_destructor_impl(ostream &os,
602 	const isl_class &clazz)
603 {
604 	const char *name = clazz.name.c_str();
605 	std::string cppstring = type2cpp(clazz);
606 	const char *cppname = cppstring.c_str();
607 
608 	osprintf(os, "%s::~%s() {\n", cppname, cppname);
609 	osprintf(os, "  if (ptr)\n");
610 	osprintf(os, "    %s_free(ptr);\n", name);
611 	osprintf(os, "}\n");
612 }
613 
614 /* Print implementation of ptr() functions for class "clazz" to "os".
615  */
616 void cpp_generator::print_ptr_impl(ostream &os, const isl_class &clazz)
617 {
618 	const char *name = clazz.name.c_str();
619 	std::string cppstring = type2cpp(clazz);
620 	const char *cppname = cppstring.c_str();
621 
622 	osprintf(os, "__isl_give %s *%s::copy() const & {\n", name, cppname);
623 	osprintf(os, "  return %s_copy(ptr);\n", name);
624 	osprintf(os, "}\n\n");
625 	osprintf(os, "__isl_keep %s *%s::get() const {\n", name, cppname);
626 	osprintf(os, "  return ptr;\n");
627 	osprintf(os, "}\n\n");
628 	osprintf(os, "__isl_give %s *%s::release() {\n", name, cppname);
629 	osprintf(os, "  %s *tmp = ptr;\n", name);
630 	osprintf(os, "  ptr = nullptr;\n");
631 	osprintf(os, "  return tmp;\n");
632 	osprintf(os, "}\n\n");
633 	osprintf(os, "bool %s::is_null() const {\n", cppname);
634 	osprintf(os, "  return ptr == nullptr;\n");
635 	osprintf(os, "}\n");
636 }
637 
638 /* Print the implementation of the get_ctx method.
639  */
640 void cpp_generator::print_get_ctx_impl(ostream &os, const isl_class &clazz)
641 {
642 	const char *name = clazz.name.c_str();
643 	std::string cppstring = type2cpp(clazz);
644 	const char *cppname = cppstring.c_str();
645 
646 	osprintf(os, "ctx %s::get_ctx() const {\n", cppname);
647 	osprintf(os, "  return ctx(%s_get_ctx(ptr));\n", name);
648 	osprintf(os, "}\n");
649 }
650 
651 /* Print definitions for methods of class "clazz" to "os".
652  */
653 void cpp_generator::print_methods_impl(ostream &os, const isl_class &clazz)
654 {
655 	map<string, set<FunctionDecl *> >::const_iterator it;
656 	bool first = true;
657 
658 	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it) {
659 		if (first)
660 			first = false;
661 		else
662 			osprintf(os, "\n");
663 		print_method_group_impl(os, clazz, it->second);
664 	}
665 }
666 
667 /* Print definitions for methods "methods" in class "clazz" to "os".
668  *
669  * "kind" specifies the kind of method that should be generated.
670  */
671 void cpp_generator::print_method_group_impl(ostream &os, const isl_class &clazz,
672 	const set<FunctionDecl *> &methods)
673 {
674 	set<FunctionDecl *>::const_iterator it;
675 	bool first = true;
676 
677 	for (it = methods.begin(); it != methods.end(); ++it) {
678 		function_kind kind;
679 		if (first)
680 			first = false;
681 		else
682 			osprintf(os, "\n");
683 		kind = get_method_kind(clazz, *it);
684 		print_method_impl(os, clazz, *it, kind);
685 	}
686 }
687 
688 /* Print the use of "param" to "os".
689  *
690  * "load_from_this_ptr" specifies whether the parameter should be loaded from
691  * the this-ptr.  In case a value is loaded from a this pointer, the original
692  * value must be preserved and must consequently be copied.  Values that are
693  * loaded from parameters do not need to be preserved, as such values will
694  * already be copies of the actual parameters.  It is consequently possible
695  * to directly take the pointer from these values, which saves
696  * an unnecessary copy.
697  *
698  * In case the parameter is a callback function, two parameters get printed,
699  * a wrapper for the callback function and a pointer to the actual
700  * callback function.  The wrapper is expected to be available
701  * in a previously declared variable <name>_lambda, while
702  * the actual callback function is expected to be stored
703  * in a structure called <name>_data.
704  * The caller of this function must ensure that these variables exist.
705  */
706 void cpp_generator::print_method_param_use(ostream &os, ParmVarDecl *param,
707 	bool load_from_this_ptr)
708 {
709 	string name = param->getName().str();
710 	const char *name_str = name.c_str();
711 	QualType type = param->getOriginalType();
712 
713 	if (type->isIntegerType()) {
714 		osprintf(os, "%s", name_str);
715 		return;
716 	}
717 
718 	if (is_string(type)) {
719 		osprintf(os, "%s.c_str()", name_str);
720 		return;
721 	}
722 
723 	if (is_callback(type)) {
724 		osprintf(os, "%s_lambda, ", name_str);
725 		osprintf(os, "&%s_data", name_str);
726 		return;
727 	}
728 
729 	if (!load_from_this_ptr && !is_callback(type))
730 		osprintf(os, "%s.", name_str);
731 
732 	if (keeps(param)) {
733 		osprintf(os, "get()");
734 	} else {
735 		if (load_from_this_ptr)
736 			osprintf(os, "copy()");
737 		else
738 			osprintf(os, "release()");
739 	}
740 }
741 
742 /* Print code that checks that all isl object arguments to "method" are valid
743  * (not NULL) and throws an exception if they are not.
744  * "kind" specifies the kind of method that is being generated.
745  *
746  * If checked bindings are being generated,
747  * then no such check is performed.
748  */
749 void cpp_generator::print_argument_validity_check(ostream &os,
750 	FunctionDecl *method, function_kind kind)
751 {
752 	int n;
753 	bool first = true;
754 
755 	if (checked)
756 		return;
757 
758 	n = method->getNumParams();
759 	for (int i = 0; i < n; ++i) {
760 		bool is_this;
761 		ParmVarDecl *param = method->getParamDecl(i);
762 		string name = param->getName().str();
763 		const char *name_str = name.c_str();
764 		QualType type = param->getOriginalType();
765 
766 		is_this = i == 0 && kind == function_kind_member_method;
767 		if (!is_this && (is_isl_ctx(type) || !is_isl_type(type)))
768 			continue;
769 
770 		if (first)
771 			osprintf(os, "  if (");
772 		else
773 			osprintf(os, " || ");
774 
775 		if (is_this)
776 			osprintf(os, "!ptr");
777 		else
778 			osprintf(os, "%s.is_null()", name_str);
779 
780 		first = false;
781 	}
782 	if (first)
783 		return;
784 	osprintf(os, ")\n");
785 	print_throw_NULL_input(os);
786 }
787 
788 /* Print code for saving a copy of the isl::ctx available at the start
789  * of the method "method" in a "ctx" variable, for use in exception handling.
790  * "kind" specifies what kind of method "method" is.
791  *
792  * If checked bindings are being generated,
793  * then the "ctx" variable is not needed.
794  * If "method" is a member function, then obtain the isl_ctx from
795  * the "this" object.
796  * If the first argument of the method is an isl::ctx, then use that one,
797  * assuming it is not already called "ctx".
798  * Otherwise, save a copy of the isl::ctx associated to the first argument
799  * of isl object type.
800  */
801 void cpp_generator::print_save_ctx(ostream &os, FunctionDecl *method,
802 	function_kind kind)
803 {
804 	int n;
805 	ParmVarDecl *param = method->getParamDecl(0);
806 	QualType type = param->getOriginalType();
807 
808 	if (checked)
809 		return;
810 	if (kind == function_kind_member_method) {
811 		osprintf(os, "  auto ctx = get_ctx();\n");
812 		return;
813 	}
814 	if (is_isl_ctx(type)) {
815 		const char *name;
816 
817 		name = param->getName().str().c_str();
818 		if (strcmp(name, "ctx") != 0)
819 			osprintf(os, "  auto ctx = %s;\n", name);
820 		return;
821 	}
822 	n = method->getNumParams();
823 	for (int i = 0; i < n; ++i) {
824 		ParmVarDecl *param = method->getParamDecl(i);
825 		QualType type = param->getOriginalType();
826 
827 		if (!is_isl_type(type))
828 			continue;
829 		osprintf(os, "  auto ctx = %s.get_ctx();\n",
830 			param->getName().str().c_str());
831 		return;
832 	}
833 }
834 
835 /* Print code to make isl not print an error message when an error occurs
836  * within the current scope (if exceptions are available),
837  * since the error message will be included in the exception.
838  * If exceptions are not available, then exception::on_error
839  * is set to ISL_ON_ERROR_ABORT and isl is therefore made to abort instead.
840  *
841  * If checked bindings are being generated,
842  * then leave it to the user to decide what isl should do on error.
843  * Otherwise, assume that a valid isl::ctx is available in the "ctx" variable,
844  * e.g., through a prior call to print_save_ctx.
845  */
846 void cpp_generator::print_on_error_continue(ostream &os)
847 {
848 	if (checked)
849 		return;
850 	osprintf(os, "  options_scoped_set_on_error saved_on_error(ctx, "
851 		     "exception::on_error);\n");
852 }
853 
854 /* Print code that checks whether the execution of the core of "method"
855  * was successful.
856  *
857  * If checked bindings are being generated,
858  * then no checks are performed.
859  *
860  * Otherwise, first check if any of the callbacks failed with
861  * an exception.  If so, the "eptr" in the corresponding data structure
862  * contains the exception that was caught and that needs to be rethrown.
863  * Then check if the function call failed in any other way and throw
864  * the appropriate exception.
865  * In particular, if the return type is isl_stat or isl_bool,
866  * then a negative value indicates a failure.  If the return type
867  * is an isl type, then a NULL value indicates a failure.
868  * Assume print_save_ctx has made sure that a valid isl::ctx
869  * is available in the "ctx" variable.
870  */
871 void cpp_generator::print_exceptional_execution_check(ostream &os,
872 	FunctionDecl *method)
873 {
874 	int n;
875 	bool check_null, check_neg;
876 	QualType return_type = method->getReturnType();
877 
878 	if (checked)
879 		return;
880 
881 	n = method->getNumParams();
882 	for (int i = 0; i < n; ++i) {
883 		ParmVarDecl *param = method->getParamDecl(i);
884 		const char *name;
885 
886 		if (!is_callback(param->getOriginalType()))
887 			continue;
888 		name = param->getName().str().c_str();
889 		osprintf(os, "  if (%s_data.eptr)\n", name);
890 		osprintf(os, "    std::rethrow_exception(%s_data.eptr);\n",
891 			name);
892 	}
893 
894 	check_neg = is_isl_stat(return_type) || is_isl_bool(return_type);
895 	check_null = is_isl_type(return_type);
896 	if (!check_null && !check_neg)
897 		return;
898 
899 	if (check_neg)
900 		osprintf(os, "  if (res < 0)\n");
901 	else
902 		osprintf(os, "  if (!res)\n");
903 	print_throw_last_error(os);
904 }
905 
906 /* Print the return statement of the C++ method corresponding
907  * to the C function "method" in class "clazz" to "os".
908  *
909  * The result of the isl function is returned as a new
910  * object if the underlying isl function returns an isl_* ptr, as a bool
911  * if the isl function returns an isl_bool, as void if the isl functions
912  * returns an isl_stat,
913  * as std::string if the isl function returns 'const char *', and as
914  * unmodified return value otherwise.
915  * If checked C++ bindings are being generated,
916  * then an isl_bool return type is transformed into a boolean and
917  * an isl_stat into a stat since no exceptions can be generated
918  * on negative results from the isl function.
919  */
920 void cpp_generator::print_method_return(ostream &os, const isl_class &clazz,
921 	FunctionDecl *method)
922 {
923 	QualType return_type = method->getReturnType();
924 
925 	if (is_isl_type(return_type) ||
926 		    (checked &&
927 		     (is_isl_bool(return_type) || is_isl_stat(return_type)))) {
928 		osprintf(os, "  return manage(res);\n");
929 	} else if (is_isl_stat(return_type)) {
930 		osprintf(os, "  return;\n");
931 	} else if (is_string(return_type)) {
932 		osprintf(os, "  std::string tmp(res);\n");
933 		if (gives(method))
934 			osprintf(os, "  free(res);\n");
935 		osprintf(os, "  return tmp;\n");
936 	} else {
937 		osprintf(os, "  return res;\n");
938 	}
939 }
940 
941 /* Print definition for "method" in class "clazz" to "os".
942  *
943  * "kind" specifies the kind of method that should be generated.
944  *
945  * This method distinguishes three kinds of methods: member methods, static
946  * methods, and constructors.
947  *
948  * Member methods call "method" by passing to the underlying isl function the
949  * isl object belonging to "this" as first argument and the remaining arguments
950  * as subsequent arguments.
951  *
952  * Static methods call "method" by passing all arguments to the underlying isl
953  * function, as no this-pointer is available. The result is a newly managed
954  * isl C++ object.
955  *
956  * Constructors create a new object from a given set of input parameters. They
957  * do not return a value, but instead update the pointer stored inside the
958  * newly created object.
959  *
960  * If the method has a callback argument, we reduce the number of parameters
961  * that are exposed by one to hide the user pointer from the interface. On
962  * the C++ side no user pointer is needed, as arguments can be forwarded
963  * as part of the std::function argument which specifies the callback function.
964  *
965  * Unless checked C++ bindings are being generated,
966  * the inputs of the method are first checked for being valid isl objects and
967  * a copy of the associated isl::ctx is saved (if needed).
968  * If any failure occurs, either during the check for the inputs or
969  * during the isl function call, an exception is thrown.
970  * During the function call, isl is made not to print any error message
971  * because the error message is included in the exception.
972  */
973 void cpp_generator::print_method_impl(ostream &os, const isl_class &clazz,
974 	FunctionDecl *method, function_kind kind)
975 {
976 	string methodname = method->getName();
977 	int num_params = method->getNumParams();
978 
979 	print_method_header(os, clazz, method, false, kind);
980 	osprintf(os, "{\n");
981 	print_argument_validity_check(os, method, kind);
982 	print_save_ctx(os, method, kind);
983 	print_on_error_continue(os);
984 
985 	for (int i = 0; i < num_params; ++i) {
986 		ParmVarDecl *param = method->getParamDecl(i);
987 		if (is_callback(param->getType())) {
988 			num_params -= 1;
989 			print_callback_local(os, param);
990 		}
991 	}
992 
993 	osprintf(os, "  auto res = %s(", methodname.c_str());
994 
995 	for (int i = 0; i < num_params; ++i) {
996 		ParmVarDecl *param = method->getParamDecl(i);
997 		bool load_from_this_ptr = false;
998 
999 		if (i == 0 && kind == function_kind_member_method)
1000 			load_from_this_ptr = true;
1001 
1002 		print_method_param_use(os, param, load_from_this_ptr);
1003 
1004 		if (i != num_params - 1)
1005 			osprintf(os, ", ");
1006 	}
1007 	osprintf(os, ");\n");
1008 
1009 	print_exceptional_execution_check(os, method);
1010 	if (kind == function_kind_constructor) {
1011 		osprintf(os, "  ptr = res;\n");
1012 	} else {
1013 		print_method_return(os, clazz, method);
1014 	}
1015 
1016 	osprintf(os, "}\n");
1017 }
1018 
1019 /* Print the header for "method" in class "clazz" to "os".
1020  *
1021  * Print the header of a declaration if "is_declaration" is set, otherwise print
1022  * the header of a method definition.
1023  *
1024  * "kind" specifies the kind of method that should be generated.
1025  *
1026  * This function prints headers for member methods, static methods, and
1027  * constructors, either for their declaration or definition.
1028  *
1029  * Member functions are declared as "const", as they do not change the current
1030  * object, but instead create a new object. They always retrieve the first
1031  * parameter of the original isl function from the this-pointer of the object,
1032  * such that only starting at the second parameter the parameters of the
1033  * original function become part of the method's interface.
1034  *
1035  * A function
1036  *
1037  * 	__isl_give isl_set *isl_set_intersect(__isl_take isl_set *s1,
1038  * 		__isl_take isl_set *s2);
1039  *
1040  * is translated into:
1041  *
1042  * 	inline set intersect(set set2) const;
1043  *
1044  * For static functions and constructors all parameters of the original isl
1045  * function are exposed.
1046  *
1047  * Parameters that are defined as __isl_keep or are of type string, are passed
1048  * as const reference, which allows the compiler to optimize the parameter
1049  * transfer.
1050  *
1051  * Constructors are marked as explicit using the C++ keyword 'explicit' or as
1052  * implicit using a comment in place of the explicit keyword. By annotating
1053  * implicit constructors with a comment, users of the interface are made
1054  * aware of the potential danger that implicit construction is possible
1055  * for these constructors, whereas without a comment not every user would
1056  * know that implicit construction is allowed in absence of an explicit keyword.
1057  */
1058 void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
1059 	FunctionDecl *method, bool is_declaration, function_kind kind)
1060 {
1061 	string cname = clazz.method_name(method);
1062 	string rettype_str = type2cpp(method->getReturnType());
1063 	string classname = type2cpp(clazz);
1064 	int num_params = method->getNumParams();
1065 	int first_param = 0;
1066 
1067 	cname = rename_method(cname);
1068 	if (kind == function_kind_member_method)
1069 		first_param = 1;
1070 
1071 	if (is_declaration) {
1072 		osprintf(os, "  ");
1073 
1074 		if (kind == function_kind_static_method)
1075 			osprintf(os, "static ");
1076 
1077 		osprintf(os, "inline ");
1078 
1079 		if (kind == function_kind_constructor) {
1080 			if (is_implicit_conversion(clazz, method))
1081 				osprintf(os, "/* implicit */ ");
1082 			else
1083 				osprintf(os, "explicit ");
1084 		}
1085 	}
1086 
1087 	if (kind != function_kind_constructor)
1088 		osprintf(os, "%s ", rettype_str.c_str());
1089 
1090 	if (!is_declaration)
1091 		osprintf(os, "%s::", classname.c_str());
1092 
1093 	if (kind != function_kind_constructor)
1094 		osprintf(os, "%s", cname.c_str());
1095 	else
1096 		osprintf(os, "%s", classname.c_str());
1097 
1098 	osprintf(os, "(");
1099 
1100 	for (int i = first_param; i < num_params; ++i) {
1101 		ParmVarDecl *param = method->getParamDecl(i);
1102 		QualType type = param->getOriginalType();
1103 		string cpptype = type2cpp(type);
1104 
1105 		if (is_callback(type))
1106 			num_params--;
1107 
1108 		if (keeps(param) || is_string(type) || is_callback(type))
1109 			osprintf(os, "const %s &%s", cpptype.c_str(),
1110 				 param->getName().str().c_str());
1111 		else
1112 			osprintf(os, "%s %s", cpptype.c_str(),
1113 				 param->getName().str().c_str());
1114 
1115 		if (i != num_params - 1)
1116 			osprintf(os, ", ");
1117 	}
1118 
1119 	osprintf(os, ")");
1120 
1121 	if (kind == function_kind_member_method)
1122 		osprintf(os, " const");
1123 
1124 	if (is_declaration)
1125 		osprintf(os, ";");
1126 	osprintf(os, "\n");
1127 }
1128 
1129 /* Generate the list of argument types for a callback function of
1130  * type "type".  If "cpp" is set, then generate the C++ type list, otherwise
1131  * the C type list.
1132  *
1133  * For a callback of type
1134  *
1135  *      isl_stat (*)(__isl_take isl_map *map, void *user)
1136  *
1137  * the following C++ argument list is generated:
1138  *
1139  *      map
1140  */
1141 string cpp_generator::generate_callback_args(QualType type, bool cpp)
1142 {
1143 	std::string type_str;
1144 	const FunctionProtoType *callback;
1145 	int num_params;
1146 
1147 	callback = extract_prototype(type);
1148 	num_params = callback->getNumArgs();
1149 	if (cpp)
1150 		num_params--;
1151 
1152 	for (long i = 0; i < num_params; i++) {
1153 		QualType type = callback->getArgType(i);
1154 
1155 		if (cpp)
1156 			type_str += type2cpp(type);
1157 		else
1158 			type_str += type.getAsString();
1159 
1160 		if (!cpp)
1161 			type_str += "arg_" + ::to_string(i);
1162 
1163 		if (i != num_params - 1)
1164 			type_str += ", ";
1165 	}
1166 
1167 	return type_str;
1168 }
1169 
1170 /* Generate the full cpp type of a callback function of type "type".
1171  *
1172  * For a callback of type
1173  *
1174  *      isl_stat (*)(__isl_take isl_map *map, void *user)
1175  *
1176  * the following type is generated:
1177  *
1178  *      std::function<stat(map)>
1179  */
1180 string cpp_generator::generate_callback_type(QualType type)
1181 {
1182 	std::string type_str;
1183 	const FunctionProtoType *callback = extract_prototype(type);
1184 	QualType return_type = callback->getReturnType();
1185 	string rettype_str = type2cpp(return_type);
1186 
1187 	type_str = "std::function<";
1188 	type_str += rettype_str;
1189 	type_str += "(";
1190 	type_str += generate_callback_args(type, true);
1191 	type_str += ")>";
1192 
1193 	return type_str;
1194 }
1195 
1196 /* Print the call to the C++ callback function "call", wrapped
1197  * for use inside the lambda function that is used as the C callback function,
1198  * in the case where checked C++ bindings are being generated.
1199  *
1200  * In particular, print
1201  *
1202  *        stat ret = @call@;
1203  *        return ret.release();
1204  */
1205 void cpp_generator::print_wrapped_call_checked(ostream &os,
1206 	const string &call)
1207 {
1208 	osprintf(os, "    stat ret = %s;\n", call.c_str());
1209 	osprintf(os, "    return ret.release();\n");
1210 }
1211 
1212 /* Print the call to the C++ callback function "call", wrapped
1213  * for use inside the lambda function that is used as the C callback function.
1214  *
1215  * In particular, print
1216  *
1217  *        ISL_CPP_TRY {
1218  *          @call@;
1219  *          return isl_stat_ok;
1220  *        } ISL_CPP_CATCH_ALL {
1221  *          data->eptr = std::current_exception();
1222  *          return isl_stat_error;
1223  *        }
1224  *
1225  * where ISL_CPP_TRY is defined to "try" and ISL_CPP_CATCH_ALL to "catch (...)"
1226  * (if exceptions are available).
1227  *
1228  * If checked C++ bindings are being generated, then
1229  * the call is wrapped differently.
1230  */
1231 void cpp_generator::print_wrapped_call(ostream &os, const string &call)
1232 {
1233 	if (checked)
1234 		return print_wrapped_call_checked(os, call);
1235 
1236 	osprintf(os, "    ISL_CPP_TRY {\n");
1237 	osprintf(os, "      %s;\n", call.c_str());
1238 	osprintf(os, "      return isl_stat_ok;\n");
1239 	osprintf(os, "    } ISL_CPP_CATCH_ALL {\n"
1240 		     "      data->eptr = std::current_exception();\n");
1241 	osprintf(os, "      return isl_stat_error;\n");
1242 	osprintf(os, "    }\n");
1243 }
1244 
1245 /* Print the local variables that are needed for a callback argument,
1246  * in particular, print a lambda function that wraps the callback and
1247  * a pointer to the actual C++ callback function.
1248  *
1249  * For a callback of the form
1250  *
1251  *      isl_stat (*fn)(__isl_take isl_map *map, void *user)
1252  *
1253  * the following lambda function is generated:
1254  *
1255  *      auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
1256  *        auto *data = static_cast<struct fn_data *>(arg_1);
1257  *        try {
1258  *          stat ret = (*data->func)(manage(arg_0));
1259  *          return isl_stat_ok;
1260  *        } catch (...) {
1261  *          data->eptr = std::current_exception();
1262  *          return isl_stat_error;
1263  *        }
1264  *      };
1265  *
1266  * The pointer to the std::function C++ callback function is stored in
1267  * a fn_data data structure for passing to the C callback function,
1268  * along with an std::exception_ptr that is used to store any
1269  * exceptions thrown in the C++ callback.
1270  *
1271  *      struct fn_data {
1272  *        const std::function<stat(map)> *func;
1273  *        std::exception_ptr eptr;
1274  *      } fn_data = { &fn };
1275  *
1276  * This std::function object represents the actual user
1277  * callback function together with the locally captured state at the caller.
1278  *
1279  * The lambda function is expected to be used as a C callback function
1280  * where the lambda itself is provided as the function pointer and
1281  * where the user void pointer is a pointer to fn_data.
1282  * The std::function object is extracted from the pointer to fn_data
1283  * inside the lambda function.
1284  *
1285  * The std::exception_ptr object is not added to fn_data
1286  * if checked C++ bindings are being generated.
1287  * The body of the generated lambda function then is as follows:
1288  *
1289  *        stat ret = (*data->func)(manage(arg_0));
1290  *        return isl_stat(ret);
1291  *
1292  * If the C callback does not take its arguments, then
1293  * manage_copy is used instead of manage.
1294  */
1295 void cpp_generator::print_callback_local(ostream &os, ParmVarDecl *param)
1296 {
1297 	string pname;
1298 	QualType ptype;
1299 	string call, c_args, cpp_args, rettype, last_idx;
1300 	const FunctionProtoType *callback;
1301 	int num_params;
1302 
1303 	pname = param->getName().str();
1304 	ptype = param->getType();
1305 
1306 	c_args = generate_callback_args(ptype, false);
1307 	cpp_args = generate_callback_type(ptype);
1308 
1309 	callback = extract_prototype(ptype);
1310 	rettype = callback->getReturnType().getAsString();
1311 	num_params = callback->getNumArgs();
1312 
1313 	last_idx = ::to_string(num_params - 1);
1314 
1315 	call = "(*data->func)(";
1316 	for (long i = 0; i < num_params - 1; i++) {
1317 		if (!callback_takes_argument(param, i))
1318 			call += "manage_copy";
1319 		else
1320 			call += "manage";
1321 		call += "(arg_" + ::to_string(i) + ")";
1322 		if (i != num_params - 2)
1323 			call += ", ";
1324 	}
1325 	call += ")";
1326 
1327 	osprintf(os, "  struct %s_data {\n", pname.c_str());
1328 	osprintf(os, "    const %s *func;\n", cpp_args.c_str());
1329 	if (!checked)
1330 		osprintf(os, "    std::exception_ptr eptr;\n");
1331 	osprintf(os, "  } %s_data = { &%s };\n", pname.c_str(), pname.c_str());
1332 	osprintf(os, "  auto %s_lambda = [](%s) -> %s {\n",
1333 		 pname.c_str(), c_args.c_str(), rettype.c_str());
1334 	osprintf(os,
1335 		 "    auto *data = static_cast<struct %s_data *>(arg_%s);\n",
1336 		 pname.c_str(), last_idx.c_str());
1337 	print_wrapped_call(os, call);
1338 	osprintf(os, "  };\n");
1339 }
1340 
1341 /* An array listing functions that must be renamed and the function name they
1342  * should be renamed to. We currently rename functions in case their name would
1343  * match a reserved C++ keyword, which is not allowed in C++.
1344  */
1345 static const char *rename_map[][2] = {
1346 	{ "union", "unite" },
1347 };
1348 
1349 /* Rename method "name" in case the method name in the C++ bindings should not
1350  * match the name in the C bindings. We do this for example to avoid
1351  * C++ keywords.
1352  */
1353 std::string cpp_generator::rename_method(std::string name)
1354 {
1355 	for (size_t i = 0; i < sizeof(rename_map) / sizeof(rename_map[0]); i++)
1356 		if (name.compare(rename_map[i][0]) == 0)
1357 			return rename_map[i][1];
1358 
1359 	return name;
1360 }
1361 
1362 /* Translate isl class "clazz" to its corresponding C++ type.
1363  */
1364 string cpp_generator::type2cpp(const isl_class &clazz)
1365 {
1366 	return type2cpp(clazz.name);
1367 }
1368 
1369 /* Translate type string "type_str" to its C++ name counterpart.
1370 */
1371 string cpp_generator::type2cpp(string type_str)
1372 {
1373 	return type_str.substr(4);
1374 }
1375 
1376 /* Translate QualType "type" to its C++ name counterpart.
1377  *
1378  * An isl_bool return type is translated into "bool",
1379  * while an isl_stat is translated into "void".
1380  * The exceptional cases are handled through exceptions.
1381  * If checked C++ bindings are being generated, then
1382  * C++ counterparts of isl_bool and isl_stat need to be used instead.
1383  */
1384 string cpp_generator::type2cpp(QualType type)
1385 {
1386 	if (is_isl_type(type))
1387 		return type2cpp(type->getPointeeType().getAsString());
1388 
1389 	if (is_isl_bool(type))
1390 		return checked ? "boolean" : "bool";
1391 
1392 	if (is_isl_stat(type))
1393 		return checked ? "stat" : "void";
1394 
1395 	if (type->isIntegerType())
1396 		return type.getAsString();
1397 
1398 	if (is_string(type))
1399 		return "std::string";
1400 
1401 	if (is_callback(type))
1402 		return generate_callback_type(type);
1403 
1404 	die("Cannot convert type to C++ type");
1405 }
1406 
1407 /* Check if "subclass_type" is a subclass of "class_type".
1408  */
1409 bool cpp_generator::is_subclass(QualType subclass_type,
1410 	const isl_class &class_type)
1411 {
1412 	std::string type_str = subclass_type->getPointeeType().getAsString();
1413 	std::vector<std::string> superclasses;
1414 	std::vector<const isl_class *> parents;
1415 	std::vector<std::string>::iterator ci;
1416 
1417 	superclasses = generator::find_superclasses(classes[type_str].type);
1418 
1419 	for (ci = superclasses.begin(); ci < superclasses.end(); ci++)
1420 		parents.push_back(&classes[*ci]);
1421 
1422 	while (!parents.empty()) {
1423 		const isl_class *candidate = parents.back();
1424 
1425 		parents.pop_back();
1426 
1427 		if (&class_type == candidate)
1428 			return true;
1429 
1430 		superclasses = generator::find_superclasses(candidate->type);
1431 
1432 		for (ci = superclasses.begin(); ci < superclasses.end(); ci++)
1433 			parents.push_back(&classes[*ci]);
1434 	}
1435 
1436 	return false;
1437 }
1438 
1439 /* Check if "cons" is an implicit conversion constructor of class "clazz".
1440  *
1441  * An implicit conversion constructor is generated in case "cons" has a single
1442  * parameter, where the parameter type is a subclass of the class that is
1443  * currently being generated.
1444  */
1445 bool cpp_generator::is_implicit_conversion(const isl_class &clazz,
1446 	FunctionDecl *cons)
1447 {
1448 	ParmVarDecl *param = cons->getParamDecl(0);
1449 	QualType type = param->getOriginalType();
1450 
1451 	int num_params = cons->getNumParams();
1452 	if (num_params != 1)
1453 		return false;
1454 
1455 	if (is_isl_type(type) && !is_isl_ctx(type) && is_subclass(type, clazz))
1456 		return true;
1457 
1458 	return false;
1459 }
1460 
1461 /* Get kind of "method" in "clazz".
1462  *
1463  * Given the declaration of a static or member method, returns its kind.
1464  */
1465 cpp_generator::function_kind cpp_generator::get_method_kind(
1466 	const isl_class &clazz, FunctionDecl *method)
1467 {
1468 	if (is_static(clazz, method))
1469 		return function_kind_static_method;
1470 	else
1471 		return function_kind_member_method;
1472 }
1473