ROSE 0.11.145.210
sageInterfaceAda.C
1#include "sageInterfaceAda.h"
2#include "sageInterface.h"
3#include "sageGeneric.h"
4#include "sageBuilder.h"
5
6#include <iostream>
7#include <limits>
8#include <cmath>
9#include <exception>
10
11#include <boost/lexical_cast.hpp>
12#include <boost/algorithm/string.hpp>
13#include <boost/algorithm/string/predicate.hpp>
14
15#include "Rose/Diagnostics.h"
16
17namespace si = SageInterface;
18namespace sb = SageBuilder;
19
20namespace SageInterface
21{
22namespace Ada
23{
24 // workaround to get the scope of package standard more easily
25 // set in AdaType.C:initializePkgStandard
26 SgAdaPackageSpecDecl* stdpkg = nullptr;
27}
28}
29
30
31namespace
32{
33 bool stringeq(const std::string& lhs, const std::string& rhs)
34 {
35 return boost::iequals(lhs, rhs);
36 }
37
38 //
39 // convenience functions to identify Ada attributes
40 bool isClassAttribute(const SgAdaAttributeExp& attr)
41 {
42 const std::string attrname = "class";
43
44 return ::si::Ada::isAttribute(attr, attrname);
45 }
46
47 inline
48 bool isClassAttribute(const SgAdaAttributeExp* attr)
49 {
50 return attr && isClassAttribute(*attr);
51 }
52
53 bool isRangeAttribute(const SgAdaAttributeExp& attr)
54 {
55 const std::string attrname = "range";
56
57 return ::si::Ada::isAttribute(attr, attrname);
58 }
59
60 bool isRangeAttribute(const SgAdaAttributeExp* attr)
61 {
62 return attr && isRangeAttribute(*attr);
63 }
64
65
69 dominant_declaration(const SgTypedefType& n)
70 {
71 const SgTypedefDeclaration* dcl = isSgTypedefDeclaration(n.get_declaration());
72 ASSERT_not_null(dcl);
73 const SgTypedefDeclaration* defdcl = isSgTypedefDeclaration(dcl->get_definingDeclaration());
74
75 if (defdcl != nullptr) dcl = defdcl;
76 return *dcl;
77 }
78
83 SgType& base_type(const SgTypedefType& n)
84 {
85 return SG_DEREF(dominant_declaration(n).get_base_type());
86 }
87
88
89 struct ArrayType : sg::DispatchHandler<SgArrayType*>
90 {
91 static
92 SgArrayType* find(SgType* n);
93 //~ find(SgType* n, TypeSkip skipWhat = skipNone);
94
95 ReturnType descend(SgType* n);
96
97 // invalid case
98 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
99
100 // base cases
101 void handle(SgType&) { res = nullptr; }
102 void handle(SgArrayType& n) { res = &n; }
103
104 // possibly skipped types
105 void handle(SgAdaSubtype& n) { res = descend(n.get_base_type()); }
106 void handle(SgAdaDerivedType& n) { res = descend(n.get_base_type()); }
107 void handle(SgTypedefType& n) { res = descend(&base_type(n)); }
108 void handle(SgModifierType& n) { res = descend(n.get_base_type()); }
109 void handle(SgAdaFormalType& n) { res = descend(n.get_formal_type()); }
110
111 // \todo SUPPORT_RANGE_TYPES
112 // current impl. preserves compatibility with previous implementation.
113 // not sure if this needs to change.
114 void handle(SgRangeType& n) { res = descend(n.get_base_type()); }
115
116
117 //~ void handle(SgPointerType& n) { res = descend(n.get_base_type()); }
118 //~ void handle(SgReferenceType& n) { res = descend(n.get_base_type()); }
119 //~ void handle(SgRvalueReferenceType& n) { res = descend(n.get_base_type()); }
120 //~ void handle(SgAdaAccessType& n) { res = descend(n.get_base_type()); }
121 };
122
124 ArrayType::find(SgType* n)
125 {
126 SgArrayType* res = sg::dispatch(ArrayType{}, n);
127
128 return res;
129 }
130
131 ArrayType::ReturnType
132 ArrayType::descend(SgType* n)
133 {
134 return ArrayType::find(n);
135 }
136
137 struct DimRange : sg::DispatchHandler<SgExpression*>
138 {
139 static
140 SgExpression& find(SgNode* n);
141
142 static
143 ReturnType descend(SgNode* n); // may return null
144
145 // invalid case
146 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
147
148 // allow all expressions, to test if an expr. denotes a range
149 void handle(SgExpression&) { /* do nothing -> returns nullptr */ }
150
151 void handle(SgRangeExp& n) { res = &n; }
152
153 void handle(SgAdaAttributeExp& n)
154 {
155 if (isRangeAttribute(n))
156 res = &n;
157 }
158
159 // switch from expression to types
160 void handle(SgTypeExpression& n)
161 {
162 // try to extract the range from the type
163 res = descend(n.get_type());
164
165 // if that did not work, return the type expression
166 if (res == nullptr)
167 res = &n;
168 }
169
170 // base case for types
171 void handle(SgType&) { /* do nothing to return the type-expression */ }
172
173 // type expressions
174 void handle(SgTypedefType& n) { res = descend(&base_type(n)); }
175 void handle(SgAdaFormalType& n) { res = descend(n.get_formal_type()); }
176
177 // \todo SUPPORT_RANGE_TYPES
178 void handle(SgRangeType& n) { res = descend(n.get_base_type()); }
179
180 void handle(SgAdaSubtype& n)
181 {
182 if (SgAdaRangeConstraint* range = isSgAdaRangeConstraint(n.get_constraint()))
183 {
184 res = descend(range->get_range());
185 return;
186 }
187
188 ASSERT_not_null(isSgAdaNullConstraint(n.get_constraint()));
189 res = descend(n.get_base_type());
190 }
191 };
192
194 DimRange::find(SgNode* n)
195 {
196 return SG_DEREF(descend(n));
197 }
198
199 DimRange::ReturnType
200 DimRange::descend(SgNode* n)
201 {
202 return sg::dispatch(DimRange{}, n);
203 }
204
205 struct ArrayBounds : sg::DispatchHandler<si::Ada::FlatArrayType>
206 {
208 using base::base;
209
210 static
211 ReturnType
212 find(SgType* n, SgArrayType* baseType);
213
214 ReturnType
215 descend(SgType* n);
216
217 // invalid case
218 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
219
220 // base cases
221 //~ void handle(SgType&) { /* do nothing */; }
222
223 // skipped types
224 void handle(SgAdaDerivedType& n) { res = descend(n.get_base_type()); }
225 void handle(SgTypedefType& n) { res = descend(&base_type(n)); }
226 void handle(SgModifierType& n) { res = descend(n.get_base_type()); }
227 void handle(SgAdaFormalType& n) { res = descend(n.get_formal_type()); }
228
229 // \todo SUPPORT_RANGE_TYPES
230 void handle(SgRangeType& n) { res = descend(n.get_base_type()); }
231
232 // subtype -> get the dimension info for each
233 void handle(SgAdaSubtype& n)
234 {
235 SgAdaTypeConstraint* constraint = n.get_constraint();
236
237 // if the subtype is unconstrained, then the real array types
238 // must be located underneath.
239 if (isSgAdaNullConstraint(constraint))
240 {
241 res = descend(n.get_base_type());
242 return;
243 }
244
245 // the first subtype must be an index constraint
246 SgAdaIndexConstraint& idx = SG_DEREF(isSgAdaIndexConstraint(constraint));
247 SgExpressionPtrList& idxlst = idx.get_indexRanges();
248
249 for (size_t i = 0; i < idxlst.size(); ++i)
250 {
251 SgExpression* expr = idxlst[i];
252
253 res.dims().push_back(&DimRange::find(expr));
254 }
255
256 res.constrained(true);
257 }
258
259 void handle(SgArrayType& n)
260 {
261 SgExprListExp& idx = SG_DEREF(n.get_dim_info());
262 SgExpressionPtrList& idxlst = idx.get_expressions();
263
264 res.dims().insert(res.dims().end(), idxlst.begin(), idxlst.end());
265 res.constrained(!n.get_is_variable_length_array());
266 }
267 };
268
269 // static
270 ArrayBounds::ReturnType
271 ArrayBounds::find(SgType* n, SgArrayType* baseType)
272 {
273 if (!baseType)
274 return ArrayBounds::ReturnType{};
275
276 ArrayBounds::ReturnType res{baseType, {}, false};
277
278 return sg::dispatch(ArrayBounds{std::move(res)}, n);
279 }
280
281 ArrayBounds::ReturnType
282 ArrayBounds::descend(SgType* n)
283 {
284 return sg::dispatch(ArrayBounds{std::move(res)}, n);
285 }
286
287 struct IntegralValue : sg::DispatchHandler<long long int>
288 {
289 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
290
291 void handle(const SgExpression& n)
292 {
293 static const char* const msg = "sageInterface::ada: Expected constant integral value, got ";
294
295 throw std::runtime_error(msg + n.unparseToString());
296 }
297
298 void handle(const SgShortVal& n) { res = n.get_value(); }
299 void handle(const SgIntVal& n) { res = n.get_value(); }
300 void handle(const SgLongIntVal& n) { res = n.get_value(); }
301 void handle(const SgLongLongIntVal& n) { res = n.get_value(); }
302
303 void handle(const SgUnsignedCharVal& n) { res = n.get_value(); }
304 void handle(const SgUnsignedIntVal& n) { res = n.get_value(); }
305 void handle(const SgUnsignedLongLongIntVal& n) { res = n.get_value(); }
306 void handle(const SgUnsignedLongVal& n) { res = n.get_value(); }
307 void handle(const SgUnsignedShortVal& n) { res = n.get_value(); }
308 };
309
310 struct RangeExp : sg::DispatchHandler<SgRangeExp*>
311 {
313
314 explicit
315 RangeExp(size_t whichDimension)
316 : base(), dim(whichDimension)
317 {}
318
319 static
320 ReturnType
321 find(SgNode* n, size_t dim);
322
323 ReturnType
324 descend(SgNode* n);
325
326 void notFound() const { ROSE_ASSERT(!res); }
327
328 size_t dimension() const
329 {
330 ASSERT_require(dim > 0);
331
332 return dim-1;
333 }
334
335 //
336 // handlers
337
338 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
339
340 // success
341 void handle(SgRangeExp& n) { res = &n; }
342
343 // not found
344 void handle(SgType&) { notFound(); }
345
346 // For any expressions, try with the expression's type
347 // \note the ROSE AST may not yet compute the correct type for all
348 // Ada expressions. Rather than putting on band aid here,
349 // this would need to be fixed in the AST (if this is an issue).
350 void handle(SgExpression& n) { res = descend(n.get_type()); }
351
352 void handle(SgAdaAttributeExp& n) { res = ::si::Ada::range(n); }
353
354 void handle(SgAdaRangeConstraint& n) { res = descend(n.get_range()); }
355
356 void handle(SgAdaIndexConstraint& n)
357 {
358 res = find(n.get_indexRanges().at(dimension()), 1);
359 }
360
361 void handle(SgAdaSubtype& n)
362 {
363 SgNode* constraint = n.get_constraint();
364
365 res = descend(constraint ? constraint : n.get_base_type());
366 }
367
368 void handle(SgArrayType& n)
369 {
370 if (::si::Ada::unconstrained(n))
371 return notFound();
372
373 SgExprListExp& exprlst = SG_DEREF(n.get_dim_info());
374
375 res = find(exprlst.get_expressions().at(dimension()), 1);
376 }
377
378 void handle(SgAdaDerivedType& n) { res = descend(n.get_base_type()); }
379 void handle(SgTypedefType& n) { res = descend(&base_type(n)); }
380
381 // \todo SUPPORT_RANGE_TYPES
382 void handle(SgRangeType& n) { res = descend(n.get_base_type()); }
383
384 private:
385 size_t dim;
386 };
387
388 RangeExp::ReturnType
389 RangeExp::find(SgNode* n, size_t dim)
390 {
391 return sg::dispatch(RangeExp(dim), n);
392 }
393
394 RangeExp::ReturnType
395 RangeExp::descend(SgNode* n)
396 {
397 return find(n, dim);
398 }
399
400 struct BaseTypeDecl : sg::DispatchHandler<SgDeclarationStatement*>
401 {
402 static
403 ReturnType find(SgType* n);
404
405 ReturnType
406 descend(SgType* n);
407
408 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
409 void handle(const SgType&) { /* not found */ }
410
411 void handle(const SgNamedType& n) { res = n.get_declaration(); }
412
413 void handle(const SgAdaSubtype& n) { res = descend(n.get_base_type()); }
414 void handle(const SgModifierType& n) { res = descend(n.get_base_type()); }
415 void handle(const SgAdaDerivedType& n) { res = descend(n.get_base_type()); }
416 void handle(const SgRangeType& n) { res = descend(n.get_base_type()); }
417 };
418
419 BaseTypeDecl::ReturnType
420 BaseTypeDecl::find(SgType* n)
421 {
422 return sg::dispatch(BaseTypeDecl{}, n);
423 }
424
425 BaseTypeDecl::ReturnType
426 BaseTypeDecl::descend(SgType* n)
427 {
428 return find(n);
429 }
430
431 void convertSymbolTablesToCaseSensitive_internal(SgNode* node)
432 {
433 using SymbolTableEntry = std::pair<const SgName, SgSymbol*>;
434 using TmpSymbolTableEntry = std::pair<SgName, SgSymbol*>;
435
436 SgScopeStatement* scopestmt = isSgScopeStatement(node);
437 if (!scopestmt) return;
438
439 SgSymbolTable& sytable = SG_DEREF(scopestmt->get_symbol_table());
440 ASSERT_require(sytable.isCaseInsensitive());
441
442 rose_hash_multimap& symap = SG_DEREF(sytable.get_table());
443 const size_t mapsize = symap.size();
444
445 // store all entries for later use
446 std::vector<TmpSymbolTableEntry> tmp;
447
448 // std::for_each(symap.begin(), symap.end(), std::back_inserter(tmp));
449 for (SymbolTableEntry& el : symap)
450 tmp.push_back(el);
451
452 symap.clear();
453 sytable.setCaseInsensitive(false);
454
455 //~ std::for_each(tmp.begin(), tmp.end(), boost::inserter(symap, symap.end()));
456 for (TmpSymbolTableEntry& elTmp : tmp)
457 symap.insert(elTmp);
458
459 ASSERT_require(symap.size() == mapsize);
460 }
461
462 template <class SageDeclarationStatement, class SageScopeStatement>
463 auto
464 getSpecFromBody(const SageScopeStatement& defn)
465 -> decltype(std::declval<SageDeclarationStatement>().get_spec()->get_definition())
466 {
467 const SageDeclarationStatement* bodyDecl = dynamic_cast<const SageDeclarationStatement*>(defn.get_parent());
468 ASSERT_not_null(bodyDecl);
469
470 const auto* specDecl = bodyDecl->get_spec();
471 ASSERT_not_null(specDecl); // for a body the spec must exist
472
473 return specDecl->get_definition();
474 }
475
476 template <class SageDeclarationStatement, class SageScopeStatement>
477 auto
478 getBodyFromSpec(const SageScopeStatement& defn)
479 -> decltype(std::declval<SageDeclarationStatement>().get_body()->get_definition())
480 {
481 const SageDeclarationStatement* specDecl = dynamic_cast<const SageDeclarationStatement*>(defn.get_parent());
482 ASSERT_not_null(specDecl);
483
484 const auto* bodyDecl = specDecl->get_body();
485
486 // for a spec the body may have not been seen
487 return bodyDecl ? bodyDecl->get_definition() : nullptr;
488 }
489
490
491 struct CanonicalScope : sg::DispatchHandler<const SgScopeStatement*>
492 {
493 static
494 ReturnType find(const SgScopeStatement* n);
495
496 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
497 void handle(const SgScopeStatement& n) { res = &n; }
498 void handle(const SgAdaPackageBody& n) { res = getSpecFromBody<SgAdaPackageBodyDecl>(n); }
499 void handle(const SgAdaProtectedBody& n) { res = n.get_spec(); }
500 void handle(const SgAdaTaskBody& n) { res = n.get_spec(); }
501 };
502
503 CanonicalScope::ReturnType
504 CanonicalScope::find(const SgScopeStatement* n)
505 {
506 return sg::dispatch(CanonicalScope{}, n);
507 }
508
509 bool isPrivate(const SgDeclarationStatement& dcl)
510 {
511 return dcl.get_declarationModifier().get_accessModifier().isPrivate();
512 }
513}
514
515namespace SageInterface
516{
517namespace Ada
518{
519 const std::string roseOperatorPrefix = "operator";
520 const std::string packageStandardName = "Standard";
521 const std::string durationTypeName = "Duration";
522 const std::string exceptionName = "Exception";
523
525 {
526 SgEnumDeclaration& dcl = SG_DEREF(n.get_declaration());
527 SgInitializedNamePtrList& lst = dcl.get_enumerators();
528
529 const auto lim = lst.end();
530 const auto pos = std::find_if( lst.begin(), lim,
531 [&n](sg::NotNull<SgInitializedName> nm)->bool
532 {
533 return stringeq(nm->get_name(), n.get_name());
534 }
535 );
536
537 ASSERT_require(pos != lim);
538 return SG_DEREF(*pos);
539 }
540
542 {
543 return CanonicalScope::find(scope);
544 }
545
547 {
548 return SG_DEREF(canonicalScope(&scope));
549 }
550
552 {
553 ASSERT_not_null(lhs);
554 ASSERT_not_null(rhs);
555
556 return ( (lhs == rhs) // short-cut
557 || (canonicalScope(lhs) == canonicalScope(rhs))
558 );
559 }
560
561 long long int
563 {
564 return sg::dispatch(IntegralValue{}, n);
565 }
566
567 int
569 {
570 SgExpressionPtrList& exprlst = args.get_expressions();
571
572 if (exprlst.size() == 0)
573 return 1;
574
575 ASSERT_require(exprlst.size() == 1);
576 long long res = staticIntegralValue(exprlst[0]);
577
578 ASSERT_require(res <= std::numeric_limits<int>::max());
579 return res;
580 }
581
582 int
584 {
585 ASSERT_not_null(args);
586 return firstLastDimension(*args);
587 }
588
589
591 {
592 // return false if dcl is already private
593 if (isPrivate(dcl))
594 return false;
595
597
598 return def && isPrivate(*def);
599 }
600
602 {
603 return withPrivateDefinition(SG_DEREF(n));
604 }
605
606 FlatArrayType
608 {
609 if (atype == nullptr)
610 return { nullptr, {}, false };
611
612 return getArrayTypeInfo(*atype);
613 }
614
615 FlatArrayType
617 {
618 return ArrayBounds::find(&atype, ArrayType::find(&atype));
619 }
620
621 namespace
622 {
623 SgSymbol& originalSymbol(const SgAliasSymbol& sym)
624 {
625 SgSymbol* orig = sym.get_alias();
626
627 if (const SgAliasSymbol* alisy = isSgAliasSymbol(orig))
628 return originalSymbol(*alisy);
629
630 return SG_DEREF(orig);
631 }
632
633 const SgSymbol& originalSymbol(const SgSymbol& sym)
634 {
635 if (const SgAliasSymbol* alisy = isSgAliasSymbol(&sym))
636 return originalSymbol(*alisy);
637
638 return sym;
639 }
640
641 void appendAllVariableSymbols(const SgScopeStatement& scope, std::vector<RecordField>& res)
642 {
643 SgSymbolTable& symtbl = SG_DEREF(scope.get_symbol_table());
644 const rose_hash_multimap& allsyms = SG_DEREF(symtbl.get_table());
645
646 for (const auto& entry : allsyms)
647 {
648 const SgSymbol& sym = SG_DEREF(entry.second);
649 const SgSymbol& orig = originalSymbol(sym);
650
651 if (/*SgVariableSymbol* varsy =*/ isSgVariableSymbol(&orig))
652 res.emplace_back(&sym);
653 }
654 }
655
656 void appendAllDiscriminantsFromParents(const SgClassDefinition&, std::vector<RecordField>&)
657 {
658 using namespace Rose::Diagnostics;
659
660 // FIXME \todo
661 mlog[TRACE] << "collecting discriminants from parents not implemented.."
662 << std::endl;
663 }
664 }
665
666 const SgClassDefinition&
667 RecordField::record() const
668 {
669 const SgVariableSymbol& sym = SG_DEREF( isSgVariableSymbol(&originalSymbol()) );
670 const SgInitializedName& var = SG_DEREF( sym.get_declaration() );
671
672 return SG_DEREF( isSgClassDefinition(var.get_scope()) );
673 }
674
675 const SgSymbol&
676 RecordField::originalSymbol() const
677 {
678 return SageInterface::Ada::originalSymbol(symbol());
679 }
680
681 const SgSymbol&
682 RecordField::symbol() const
683 {
684 // symbols are never null - checked where RecordField are created
685 return *std::get<0>(*this);
686 }
687
688 bool
689 RecordField::discriminant() const
690 {
691 // not yet implemented
692 ROSE_ABORT();
693 }
694
695 std::vector<RecordField>
697 {
698 // look through the symbol table and collect all fields
699 // (variants or otherwise).
700
701 std::vector<RecordField> res;
702
703 appendAllVariableSymbols(rec, res);
704
705 if (const SgAdaDiscriminatedTypeDecl* disc = sg::ancestor_path<SgClassDeclaration, SgAdaDiscriminatedTypeDecl>(rec))
706 {
707 appendAllVariableSymbols(SG_DEREF(disc->get_discriminantScope()), res);
708 appendAllDiscriminantsFromParents(rec, res);
709 }
710
711 return res;
712 }
713
714 std::vector<RecordField>
716 {
717 if (rec == nullptr) return {};
718
719 return getAllRecordFields(*rec);
720 }
721
722
723
724 std::vector<IfExpressionInfo>
726 {
727 std::vector<IfExpressionInfo> res;
728 const SgConditionalExp* next = &n;
729 const SgConditionalExp* cond = nullptr;
730 bool last = false;
731
732 // flatten a sequence of unparenthesized conditional expressions
733 // c0 ? x : c1 ? y : z => { <c0, x>, <c1, y>, <null, z> }
734 do
735 {
736 cond = next;
737 res.emplace_back(cond->get_conditional_exp(), cond->get_true_exp());
738
739 next = isSgConditionalExp(cond->get_false_exp());
740 last = !next || next->get_need_paren();
741 } while (!last);
742
743 res.emplace_back(nullptr, SG_DEREF(cond).get_false_exp());
744 return res;
745 }
746
748 {
749 const SgExprStatement* es = isSgExprStatement(s);
750
751 return SG_DEREF(es).get_expression();
752 }
753
754 std::vector<IfStatementInfo>
756 {
757 std::vector<IfStatementInfo> res;
758 const SgIfStmt* next = &n;
759 const SgIfStmt* cond = nullptr;
760
761 // flatten a sequence of if a then A (else if b then B (else if c then C else D)) if statements
762 // into <a, A>, <b, B>, <c, C>, <nullptr, D>
763 do
764 {
765 cond = next;
766 res.emplace_back(underlyingExpr(cond->get_conditional()), cond->get_true_body());
767
768 next = isSgIfStmt(cond->get_false_body());
769 } while (next);
770
771 if (SgStatement* falseBranch = cond->get_false_body())
772 res.emplace_back(nullptr, falseBranch);
773
774 return res;
775 }
776
777
780 {
781 if (!isRangeAttribute(n))
782 return nullptr;
783
784 const int dim = si::Ada::firstLastDimension(SG_DEREF(n.get_args()));
785
786 return RangeExp::find(n.get_object(), dim);
787 }
788
791 {
792 if (n == nullptr)
793 return nullptr;
794
795 return range(*n);
796 }
797
799 {
800 return ( isRangeAttribute(isSgAdaAttributeExp(e))
801 || isSgTypeExpression(e)
802 || isSgRangeExp(e)
803 );
804 }
805
807 {
808 return denotesRange(&e);
809 }
810
811
813 {
814 return ty.get_is_variable_length_array();
815 }
816
818 {
819 return ty && unconstrained(*ty);
820 }
821
822 bool anonymousAccess(const SgType* ty)
823 {
824 return ty && anonymousAccess(*ty);
825 }
826
827 bool anonymousAccess(const SgType& ty)
828 {
829 const SgAdaAccessType* accty = isSgAdaAccessType(ty.stripType(SgType::STRIP_MODIFIER_TYPE));
830
831 if (accty && !accty->get_is_anonymous())
832 {
833 using namespace Rose::Diagnostics;
834
835 mlog[TRACE] << "surprising non-anonymous access type." << std::endl;
836 }
837
838 return accty != nullptr;
839 }
840
841
844 {
845 if (!bodyDecl) return nullptr;
846
847 return bodyDecl->get_spec();
848 }
849
852 {
853 return SG_DEREF(bodyDecl.get_spec());
854 }
855
857 {
858 return SG_DEREF(bodyDecl.get_specificationDeclaration());
859 }
860
862 {
863 return bodyDecl ? &getSpecificationDeclaration(*bodyDecl) : nullptr;
864 }
865
867 {
868 return SG_DEREF(bodyDecl.get_specificationDeclaration());
869 }
870
872 {
873 return bodyDecl ? &getSpecificationDeclaration(*bodyDecl) : nullptr;
874 }
875
878 {
879 if (!specDecl) return nullptr;
880
881 return specDecl->get_body();
882 }
883
886 {
887 return SG_DEREF(specDecl.get_body());
888 }
889
891 {
892 return SG_DEREF(getSpecFromBody<SgAdaPackageBodyDecl>(body));
893 }
894
896 {
897 if (!body) return nullptr;
898
899 return getSpecFromBody<SgAdaPackageBodyDecl>(*body);
900 }
901
903 {
904 return SG_DEREF(getBodyFromSpec<SgAdaPackageSpecDecl>(spec));
905 }
906
908 {
909 if (!spec) return nullptr;
910
911 return getBodyFromSpec<SgAdaPackageSpecDecl>(*spec);
912 }
913
914
915 namespace
916 {
917 struct CorrespondingBodyFinder : sg::DispatchHandler<const SgScopeStatement*>
918 {
919 void handle(const SgNode&) { /* nothing to be done */ }
920 void handle(const SgAdaPackageSpec& n) { res = getBodyFromSpec<SgAdaPackageSpecDecl>(n); }
921 void handle(const SgAdaPackageBody& n) { res = &n; /* n is the body */ }
922
923 void handle(const SgAdaTaskSpec& n) { res = n.get_body(); }
924 void handle(const SgAdaTaskBody& n) { res = &n; }
925
926 void handle(const SgAdaProtectedSpec& n) { res = n.get_body(); }
927 void handle(const SgAdaProtectedBody& n) { res = &n; }
928 };
929 }
930
931 const SgScopeStatement*
933 {
934 ASSERT_not_null(scope);
935
936 return sg::dispatch(CorrespondingBodyFinder{}, scope);
937 }
938
939
940 namespace
941 {
942 bool isNormalStatement(const SgStatement* s)
943 {
944 return isSgDeclarationStatement(s) == nullptr;
945 }
946
947 bool isNondeclarativePragma(const SgStatement* s)
948 {
949 const SgPragmaDeclaration* pdcl = isSgPragmaDeclaration(s);
950 if (pdcl == nullptr) return false;
951
952 const SgPragma& prgm = SG_DEREF(pdcl->get_pragma());
953 std::string prgName = boost::to_lower_copy(prgm.get_pragma());
954
955 return ( (prgName != "import")
956 && (prgName != "export")
957 && (prgName != "priority")
958 && (prgName != "volatile")
959 );
960 }
961
962 template <class SageStatementPtrList>
963 auto findDeclarationLimit(SageStatementPtrList& list) -> decltype(list.begin())
964 {
965 using IteratorType = decltype(list.begin());
966
967 IteratorType beg = list.begin();
968 IteratorType lim = list.end();
969 IteratorType pos = std::find_if(beg, lim, isNormalStatement);
970 IteratorType prv = std::prev(pos);
971
972 // read back over pragmas in order not to introduce spurious declare sections
973 while ((pos != beg) && isNondeclarativePragma(*prv))
974 {
975 pos = prv;
976 prv = std::prev(pos);
977 }
978
979 return pos;
980 }
981 }
982
983 SgStatementPtrList::const_iterator
984 declarationLimit(const SgStatementPtrList& list)
985 {
986 return findDeclarationLimit(list);
987 }
988
989 SgStatementPtrList::const_iterator
991 {
992 return declarationLimit(block.get_statements());
993 }
994
995 SgStatementPtrList::const_iterator
997 {
998 return declarationLimit(SG_DEREF(block));
999 }
1000
1001 SgStatementPtrList::iterator
1002 declarationLimit(SgStatementPtrList& list)
1003 {
1004 return findDeclarationLimit(list);
1005 }
1006
1007 SgStatementPtrList::iterator
1009 {
1010 return declarationLimit(block.get_statements());
1011 }
1012
1013 SgStatementPtrList::iterator
1015 {
1016 return declarationLimit(SG_DEREF(block));
1017 }
1018
1020 {
1021 SgBasicBlock* blk = isSgBasicBlock(n.get_parent());
1022 if (blk == nullptr) return false;
1023
1024 //~ SgFunctionDefinition* def = isSgFunctionDefinition(blk->get_parent());
1025 //~ if (def == nullptr) return false;
1026
1027 SgStatementPtrList& stmts = blk->get_statements();
1028 SgStatementPtrList::iterator dcllimit = declarationLimit(stmts);
1029
1030 // return true iff n is the only stmt within the block
1031 return std::distance(dcllimit, stmts.end()) == 1;
1032 }
1033
1035 {
1036 return n && tryFollowsDeclarativeBlock(*n);
1037 }
1038
1040 {
1041 return isSgAdaPackageBody(n.get_parent());
1042 }
1043
1044
1046 {
1047 return n && isPackageTryBlock(*n);
1048 }
1049
1050 namespace
1051 {
1052 SgAdaGenericDecl& getRenamedGenericDecl(SgDeclarationStatement* n)
1053 {
1054 if (SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(n))
1055 return *gendcl;
1056
1057 SgAdaRenamingDecl* rendcl = isSgAdaRenamingDecl(n);
1058 ASSERT_not_null(rendcl);
1059
1060 SgExpression* renexp = rendcl->get_renamed();
1061
1062 if (SgFunctionRefExp* funref = isSgFunctionRefExp(renexp))
1063 return SG_DEREF(isGenericDecl(funref->getAssociatedFunctionDeclaration()));
1064
1065 if (SgAdaUnitRefExp* untref = isSgAdaUnitRefExp(renexp))
1066 {
1067 SgDeclarationStatement* refdcl = untref->get_decl();
1068
1069 if (SgAdaPackageSpecDecl* pkgdcl = isSgAdaPackageSpecDecl(refdcl))
1070 return SG_DEREF(isGenericDecl(*pkgdcl));
1071
1072 if (SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(refdcl))
1073 return *gendcl;
1074
1075 ROSE_ABORT();
1076 }
1077
1078 if (SgAdaRenamingRefExp* renref = isSgAdaRenamingRefExp(renexp))
1079 return getRenamedGenericDecl(renref->get_decl());
1080
1081 ROSE_ABORT();
1082 }
1083 }
1084
1085
1087 {
1088 return getRenamedGenericDecl(n.get_genericDeclaration());
1089 }
1090
1092 {
1093 ASSERT_not_null(n);
1094
1095 return &getGenericDecl(*n);
1096 }
1097
1099 {
1100 if (SgAdaGenericDefn* defn = isSgAdaGenericDefn(n.get_parent()))
1101 return isSgAdaGenericDecl(defn->get_parent());
1102
1103 return nullptr;
1104 }
1105
1107 {
1108 if (n == nullptr) return nullptr;
1109
1110 return isGenericDecl(*n);
1111 }
1112
1113 //~ bool isDispatching(const SgFunctionCallExpr& n)
1114 //~ {
1115 //~ // an argument is of type 'class
1116 //~ // and the argument is of tagged type
1117 //~ // and the target is a primitive operation of that type
1118 //~ return false;
1119 //~ }
1120
1121 //~ bool isDispatching(const SgFunctionCallExpr* n)
1122 //~ {
1123 //~ return n && isDispatching(*n);
1124 //~ }
1125
1126
1127 namespace
1128 {
1129 bool isLogicalChildScopeOfDecl(const SgScopeStatement* scope, const SgDeclarationStatement* decl)
1130 {
1131 if (scope == nullptr) return false;
1132 if (scope->get_parent() == decl) return true;
1133
1134 return isLogicalChildScopeOfDecl(logicalParentScope(*scope), decl);
1135 }
1136
1137 bool isLogicalChildOfDecl(const SgNode* n, const SgDeclarationStatement* decl)
1138 {
1139 if (n == nullptr) return false;
1140
1141 return isLogicalChildScopeOfDecl(sg::ancestor<SgScopeStatement>(n), decl);
1142 }
1143 }
1144
1146 {
1147 SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(n.get_decl());
1148
1149 return gendcl && isLogicalChildOfDecl(&n, gendcl);
1150 }
1151
1153 {
1154 return n && unitRefDenotesGenericInstance(*n);
1155 }
1156
1158 {
1159 return SG_DEREF(n.get_discriminants()).get_parameters().size() == 0;
1160 }
1161
1163 {
1164 return n && hasUnknownDiscriminants(*n);
1165 }
1166
1169 {
1170 return isSgAdaDiscriminatedTypeDecl(n.get_parent());
1171 }
1172
1175 {
1176 return n ? getAdaDiscriminatedTypeDecl(*n) : nullptr;
1177 }
1178
1180 {
1181 using Iterator = SgExpressionPtrList::const_iterator;
1182
1183 const SgExpressionPtrList& exprs = lst.get_expressions();
1184 Iterator aa = exprs.begin();
1185 Iterator zz = exprs.end();
1186 SgAdaAncestorInitializer* ini = nullptr;
1187
1188 if (aa != zz)
1189 {
1190 ini = isSgAdaAncestorInitializer(*aa);
1191
1192 if (ini) ++aa;
1193 }
1194
1195 return AggregateInfo{ ini, aa, zz };
1196 }
1197
1199 {
1200 return splitAggregate(SG_DEREF(exp));
1201 }
1202
1203
1205 {
1206 SgExpression* ren = n.get_renamed();
1207
1208 // multiple levels of renaming declarations
1209 if (SgAdaRenamingRefExp* renref = isSgAdaRenamingRefExp(ren))
1210 return renamedPackage(renref->get_decl());
1211
1212 //~ if (SgAdaRenamingSymbol* rensym = isSgAdaRenamingSymbol(sym))
1213 //~ return renamedPackageSymbol(rensym->get_declaration());
1214
1215 if (SgAdaUnitRefExp* unitref = isSgAdaUnitRefExp(ren))
1216 return isSgAdaPackageSpecDecl(unitref->get_decl());
1217
1218 return nullptr;
1219 }
1220
1222 {
1223 return n ? renamedPackage(*n) : nullptr;
1224 }
1225
1227 {
1228 return isSgTypeVoid(ty.get_return_type()) == nullptr;
1229 }
1230
1232 {
1233 return ty ? isFunction(*ty) : false;
1234 }
1235
1237 {
1238 return isSgTypeVoid(ty.get_return_type()) == nullptr;
1239 }
1240
1242 {
1243 return ty ? isFunction(*ty) : false;
1244 }
1245
1247 {
1248 return funsy ? &functionType(*funsy) : nullptr;
1249 }
1250
1252 {
1253 const SgAdaInheritedFunctionSymbol* inhsy = isSgAdaInheritedFunctionSymbol(&funsy);
1254 const SgFunctionType* res = inhsy ? inhsy->get_derivedFunctionType()
1255 : isSgFunctionType(funsy.get_type());
1256
1257 return SG_DEREF(res);
1258 }
1259
1260
1261 namespace
1262 {
1263 bool definedInStandard(const SgDeclarationStatement& n)
1264 {
1265 return pkgStandardScope() == n.get_scope();
1266/*
1267 const SgAdaPackageSpec* pkgspec = isSgAdaPackageSpec(n.get_scope());
1268
1269 if (pkgspec == nullptr) return false;
1270
1271 const SgAdaPackageSpecDecl* pkgdecl = isSgAdaPackageSpecDecl(pkgspec->get_parent());
1272 // test for properties of package standard, which is a top-level package
1273 // and has the name "Standard".
1274 // \note The comparison is case sensitive, but as long as the creation
1275 // of the fictitious package uses the same constant, this is fine.
1276 return ( (pkgdecl != nullptr)
1277 && (pkgdecl->get_name() == packageStandardName)
1278 && (isSgGlobal(pkgdecl->get_scope()))
1279 );
1280*/
1281 }
1282
1283 bool isExceptionType(const SgType& n)
1284 {
1285 const SgTypedefType* ty = isSgTypedefType(&n);
1286 if (ty == nullptr || (!stringeq(ty->get_name().getString(), exceptionName)))
1287 return false;
1288
1289 SgTypedefDeclaration* dcl = isSgTypedefDeclaration(ty->get_declaration());
1290
1291 return definedInStandard(SG_DEREF(dcl));
1292 }
1293 }
1294
1296 {
1297 const SgType* ty = dcl.get_type();
1298
1299 return ty && (!isSgTypeVoid(ty)) && (!isExceptionType(*ty));
1300 }
1301
1303 {
1304 return dcl && isObjectRenaming(*dcl);
1305 }
1306
1310 {
1311 const SgType* ty = dcl.get_type();
1312
1313 return ty && isExceptionType(*ty);
1314 }
1315
1316
1318 {
1319 return dcl && isExceptionRenaming(*dcl);
1320 }
1322
1323
1324 bool isModularType(const SgType& ty)
1325 {
1326 return isModularType(&ty);
1327 }
1328
1329 bool isModularType(const SgType* ty)
1330 {
1331 return isSgAdaModularType(ty);
1332 }
1333
1334
1335 bool isIntegerType(const SgType& ty)
1336 {
1337 return isIntegerType(&ty);
1338 }
1339
1340 bool isIntegerType(const SgType* ty)
1341 {
1342 return isSgTypeLongLong(ty);
1343 }
1344
1346 {
1347 return isFloatingPointType(&ty);
1348 }
1349
1351 {
1352 return isSgTypeLongDouble(ty);
1353 }
1354
1355 bool isDiscreteType(const SgType& ty)
1356 {
1357 return isDiscreteType(&ty);
1358 }
1359
1360 bool isDiscreteType(const SgType* ty)
1361 {
1362 return isSgAdaDiscreteType(ty);
1363 }
1364
1365 bool isFixedType(const SgType& ty)
1366 {
1367 return isFixedType(&ty);
1368 }
1369
1370 bool isFixedType(const SgType* ty)
1371 {
1372 return isSgTypeFixed(ty);
1373 }
1374
1375 bool isBooleanType(const SgType& ty)
1376 {
1377 return isBooleanType(&ty);
1378 }
1379
1380 bool isBooleanType(const SgType* ty)
1381 {
1382 const SgEnumType* boolTy = isSgEnumType(ty);
1383 if (!boolTy) return false;
1384
1385 const SgEnumDeclaration* boolDcl = isSgEnumDeclaration(boolTy->get_declaration());
1386
1387 return ( (boolDcl != nullptr)
1388 && (stringeq(boolDcl->get_name().getString(), "BOOLEAN"))
1389 && definedInStandard(*boolDcl)
1390 );
1391 }
1392
1393 namespace
1394 {
1395 bool isScalarGenericType(const SgType& ty)
1396 {
1397 const SgAdaFormalType* formTy = isSgAdaFormalType(&ty);
1398
1399 return formTy && isScalarType(formTy->get_formal_type());
1400 }
1401 }
1402
1403 bool isScalarType(const SgType* ty)
1404 {
1405 ty = si::Ada::typeRoot(const_cast<SgType*>(ty)).typerep();
1406
1407 if (!ty) return false;
1408
1409 if (const SgTypedefType* tydef = isSgTypedefType(ty))
1410 return isScalarType(&base_type(*tydef));
1411
1412 return ( isModularType(*ty)
1413 || isIntegerType(*ty)
1414 || isFloatingPointType(*ty)
1415 || isDiscreteType(*ty)
1416 || isFixedType(*ty)
1417 || isDecimalFixedType(*ty)
1418 || isSgEnumType(ty)
1419 || isScalarGenericType(*ty)
1420 );
1421 }
1422
1423 bool isScalarType(const SgType& ty)
1424 {
1425 return isScalarType(&ty);
1426 }
1427
1429 {
1430 si::Ada::FlatArrayType arrinfo = si::Ada::getArrayTypeInfo(const_cast<SgType*>(ty));
1431 SgArrayType const* arrty = arrinfo.type();
1432
1433 if ((arrty == nullptr) || (arrinfo.dims().size() > 1))
1434 return false;
1435
1436 SgType const* elmty = si::Ada::typeRoot(arrty->get_base_type()).typerep();
1437
1438 if (elmty == nullptr) return false;
1439
1440 return ( si::Ada::isModularType(*elmty)
1441 || si::Ada::isIntegerType(*elmty)
1442 //~ || si::Ada::isFloatingPointType(*elmty)
1443 || si::Ada::isDiscreteType(*elmty)
1444 //~ || si::Ada::isFixedType(*elmty)
1445 //~ || si::Ada::isDecimalFixedType(*elmty)
1446 || isSgEnumType(elmty)
1447 );
1448 }
1449
1451 {
1452 return isDiscreteArrayType(&ty);
1453 }
1454
1455
1456 namespace
1457 {
1458 struct TypeResolver : sg::DispatchHandler<bool>
1459 {
1460 using base = sg::DispatchHandler<bool>;
1461
1462 explicit
1463 TypeResolver(std::function<bool (const SgType&)> typetest)
1464 : base(), checker(typetest)
1465 {}
1466
1467 bool descend(const SgType*);
1468
1469 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
1470
1471 //
1472 // expression based types
1473 // ...
1474
1475 //
1476 // types
1477
1478 void handle(SgType& n) { res = checker(n); }
1479 void handle(SgModifierType& n) { res = descend(n.get_base_type()); }
1480 void handle(SgAdaSubtype& n) { res = descend(n.get_base_type()); }
1481 void handle(SgAdaDerivedType& n) { res = descend(n.get_base_type()); }
1482 void handle(SgTypedefType& n) { res = descend(&base_type(n)); }
1483
1484 // \todo SUPPORT_RANGE_TYPES
1485 void handle(SgRangeType& n) { res = descend(n.get_base_type()); }
1486
1487 // void handle(SgAdaFormalType& n) { checkChild(n.get_base_type()); } // \todo enable??
1488
1489 private:
1490 std::function<bool (const SgType&)> checker;
1491 };
1492
1493 bool TypeResolver::descend(const SgType* ty)
1494 {
1495 return ty && sg::dispatch(TypeResolver{std::move(checker)}, ty);
1496 }
1497 }
1498
1500 {
1501 return sg::dispatch(TypeResolver{[](const SgType& t)->bool { return isFixedType(t); }}, &ty);
1502 }
1503
1505 {
1506 return ty && resolvesToFixedType(*ty);
1507 }
1508
1509 namespace
1510 {
1511 bool isDecimalConstraint(SgAdaTypeConstraint* constr)
1512 {
1513 SgAdaDeltaConstraint* delta = isSgAdaDeltaConstraint(constr);
1514
1515 return delta && delta->get_isDecimal();
1516 }
1517 }
1518
1520 {
1521 if (const SgAdaSubtype* sub = isSgAdaSubtype(ty))
1522 return isFixedType(sub->get_base_type()) && isDecimalConstraint(sub->get_constraint());
1523
1524 return false;
1525 }
1526
1528 {
1529 return isDecimalFixedType(&ty);
1530 }
1531
1532
1534 {
1535 return dcl.get_declarationModifier().isAdaSeparate();
1536 }
1537
1539 {
1540 return dcl && hasSeparatedBody(*dcl);
1541 }
1542
1547
1549 {
1550 return n && isSeparatedBody(*n);
1551 }
1552
1553 namespace
1554 {
1555 template <class SageNodeSequence>
1557 findSecondaryFunctionDecl(const SageNodeSequence& seq, const SgFunctionDeclaration* key)
1558 {
1559 using iterator = typename SageNodeSequence::const_reverse_iterator;
1560
1561 auto sameFirstNondefining = [key](typename SageNodeSequence::value_type ptr) -> bool
1562 {
1563 const SgFunctionDeclaration* fndcl = isSgFunctionDeclaration(ptr);
1564
1565 return fndcl && (fndcl->get_firstNondefiningDeclaration() == key);
1566 };
1567
1568 iterator lim = seq.rend();
1569 iterator pos = std::find_if(seq.rbegin(), lim, sameFirstNondefining);
1570
1571 return pos != lim ? isSgFunctionDeclaration(*pos) : nullptr;
1572 }
1573
1575 findSecondaryFunctionDecl(const SgScopeStatement& scope, const SgFunctionDeclaration* key)
1576 {
1577 return scope.containsOnlyDeclarations()
1578 ? findSecondaryFunctionDecl(scope.getDeclarationList(), key)
1579 : findSecondaryFunctionDecl(scope.getStatementList(), key);
1580 }
1581 }
1582
1583 bool hasSeparatedDefinition(const SgFunctionDeclaration* nondef)
1584 {
1585 ASSERT_not_null(nondef);
1586
1587 const SgScopeStatement* nondefScope = nondef->get_scope();
1588
1589 // \note should we look for the package spec or package body scope parent?
1590 if (const SgAdaGenericDefn* genScope = isSgAdaGenericDefn(nondefScope))
1591 nondefScope = logicalParentScope(*genScope);
1592
1593 if (const SgScopeStatement* bodyScope = correspondingBody(nondefScope))
1594 if (const SgFunctionDeclaration* secondary = findSecondaryFunctionDecl(*bodyScope, nondef))
1595 nondef = secondary;
1596
1597 return nondef->get_declarationModifier().isAdaSeparate();
1598 }
1599
1601 {
1602 return ( (n.get_definition() != nullptr)
1603 && hasSeparatedDefinition(isSgFunctionDeclaration(n.get_firstNondefiningDeclaration()))
1604 );
1605 }
1606
1608 {
1609 return n && isSeparatedDefinition(*n);
1610 }
1611
1612 namespace
1613 {
1614 // root types as implemented by AdaMaker.C
1615 SgType& integralType() { return SG_DEREF(sb::buildLongLongType()); }
1616 SgType& realType() { return SG_DEREF(sb::buildLongDoubleType()); }
1617 SgType& fixedType() { return SG_DEREF(sb::buildFixedType(nullptr, nullptr)); }
1618 SgType& pointerType() { return SG_DEREF(sb::buildNullptrType()); }
1619
1620 SgType& arrayType(SgType* base)
1621 {
1622 // poor man's type unifier
1623 static std::map<SgType*, SgArrayType*> m;
1624
1625 SgArrayType*& res = m[base];
1626
1627 // \todo this is missing a dimension value
1628 // check mkArrayType in AdaMaker.C for details.
1629 if (res == nullptr) res = sb::buildArrayType(base);
1630
1631 return SG_DEREF(res);
1632 }
1633
1634 bool denotesRange(const SgExpression* exp)
1635 {
1636 return sg::dispatch(DimRange{}, exp) != nullptr;
1637 }
1638
1639 bool containsRange(const SgExpression& arglst)
1640 {
1641 const SgExprListExp* args = isSgExprListExp(&arglst);
1642 if (args == nullptr) return false;
1643
1644 const SgExpressionPtrList& lst = args->get_expressions();
1645 const auto lim = lst.end();
1646
1647 return lim != std::find_if(lst.begin(), lim, denotesRange);
1648 }
1649
1650 template <class ResolverT>
1651 struct TypeDescResolver : sg::DispatchHandler<TypeDescription>
1652 {
1653 TypeDescription descend(SgType* ty)
1654 {
1655 return static_cast<ResolverT&>(*this).descend(ty);
1656 }
1657
1658 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
1659
1660 // could be enabled as fallback, but generally indicates an error..
1661 //~ void handle(SgType& n) { res = TypeDescription{n}; }
1662
1663 // get the real typedefed type, which can be an access type
1664 void handle(SgTypedefType& n) { res = descend(&base_type(n)); }
1665
1666 // a modifier type can be an access type ??
1667 void handle(SgModifierType& n) { res = descend(n.get_base_type()); }
1668
1669 // a derived type can be an access type
1670 void handle(SgAdaDerivedType& n) { res = descend(n.get_base_type()); }
1671 void handle(SgRangeType& n) { res = descend(n.get_base_type()); }
1672
1673 // a subtype could be an access type with range constraints whose subtype is an array
1674 void handle(SgAdaSubtype& n)
1675 {
1676 TypeDescription dt = descend(n.get_base_type());
1677 std::vector<SgAdaTypeConstraint*> constr = std::move(dt).toplevelConstraints();
1678
1679 constr.insert(constr.begin(), n.get_constraint());
1680
1681 res = TypeDescription{dt.typerep_ref(), dt.polymorphic(), std::move(constr)};
1682 }
1683
1684 // a formal type can be an access type
1685 void handle(SgAdaFormalType& n) { res = descend(n.get_formal_type()); }
1686 };
1687
1688
1689
1690 struct DerefedType : TypeDescResolver<DerefedType>
1691 {
1692 using base = TypeDescResolver<DerefedType>;
1693
1694 TypeDescription descend(SgType* ty);
1695
1696 using base::handle;
1697
1698 // deref one level of access types
1699 void handle(SgAdaAccessType& n) { res = TypeDescription{n.get_base_type()}; }
1700
1701 // \todo should not be reached in Ada NO_POINTER_IN_ADA
1702 void handle(SgPointerType& n) { res = TypeDescription{n.get_base_type()}; }
1703 };
1704
1705 TypeDescription
1706 DerefedType::descend(SgType* ty)
1707 {
1708 return sg::dispatch(DerefedType{}, ty);
1709 }
1710
1711
1712 bool isElementaryInteger(const SgType* ty) { return isSgTypeLongLong(ty) != nullptr; }
1713 bool isElementaryReal (const SgType* ty) { return isSgTypeLongDouble(ty) != nullptr; }
1714
1715 bool isElementaryFixed (const SgType* ty)
1716 {
1717 const SgTypeFixed* fx = isSgTypeFixed(ty);
1718
1719 return fx && (fx->get_fraction() == nullptr) && (fx->get_scale() == nullptr);
1720 }
1721
1722 // bool isElementaryAccess(const SgType* ty) { return isNullptrType(ty); }
1723
1724 bool isElementaryType(const SgType* ty)
1725 {
1726 return ( isElementaryInteger(ty)
1727 || isElementaryReal(ty)
1728 || isElementaryFixed(ty)
1729 //~ || isElementaryAccess(ty)
1730 );
1731 }
1732
1733 SgType*
1734 simpleCommonDenominator(SgType* lhs, SgType* rhs)
1735 {
1736 // failure cases
1737 if (lhs == nullptr) return rhs;
1738 if (rhs == nullptr) return lhs;
1739
1740 // no type available
1741 if (isSgTypeDefault(lhs)) return rhs;
1742 if (isSgTypeDefault(rhs)) return lhs;
1743
1744 // \todo check that the elementary value can be converted
1745 // to the other type.
1746 if (isElementaryType(lhs)) return rhs;
1747 if (isElementaryType(rhs)) return lhs;
1748
1749 // this should be a deep test..
1750 if (lhs == rhs) return lhs;
1751
1752 return nullptr;
1753 }
1754
1755 SgType*
1756 commonDenominator(SgType* lhs, SgType* rhs)
1757 {
1758 if (SgType* com = simpleCommonDenominator(lhs, rhs))
1759 return com;
1760
1761 TypeDescription lhsDesc = typeRoot(lhs);
1762 TypeDescription rhsDesc = typeRoot(rhs);
1763
1764 if (SgType* com = simpleCommonDenominator(lhsDesc.typerep(), rhsDesc.typerep()))
1765 return com;
1766
1767 {
1768 using namespace Rose::Diagnostics;
1769 SgNamedType* lhsty = isSgNamedType(lhs);
1770 SgNamedType* rhsty = isSgNamedType(rhs);
1771
1772 mlog[WARN] << "*FLAW* commonDenominator: type mismatch "
1773 << lhs << " " << typeid(*lhs).name() << " " << (lhsty ? lhsty->get_name() : SgName{})
1774 << " :: "
1775 << rhs << " " << typeid(*rhs).name() << " " << (rhsty ? rhsty->get_name() : SgName{})
1776 << std::endl;
1777 }
1778
1779 return lhsDesc.typerep();
1780 }
1781
1782
1783 // \todo should this be moved into the Sage class hierarchy?
1784 struct ExprTypeFinder : sg::DispatchHandler<TypeDescription>
1785 {
1786 SgType* arrayBaseType(SgType* ty)
1787 {
1788 if (SgArrayType* arrty = getArrayTypeInfo(ty).type())
1789 return arrty->get_base_type();
1790
1791 // should not happen
1792 return nullptr;
1793 }
1794
1795
1796 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
1797
1798 // by default use the expression's type
1799 void handle(const SgExpression& n) { res = TypeDescription{n.get_type()}; }
1800
1801 // If a var is just constant, take the type from the initializer
1802 // NOTE: this is not correct, as the type should be determined by the context
1803 void handle(const SgVarRefExp& n)
1804 {
1805 res = TypeDescription{n.get_type()};
1806
1807 if (isSgAutoType(res.typerep()))
1808 {
1809 // if this is an auto constant, check the initializer
1810 SgVariableSymbol& sy = SG_DEREF(n.get_symbol());
1811 SgInitializedName& var = SG_DEREF(sy.get_declaration());
1812
1813 if (SgAssignInitializer* init = isSgAssignInitializer(var.get_initializer()))
1814 res = typeRoot(SG_DEREF(init->get_operand()).get_type());
1815 }
1816 }
1817
1818 void handle(const SgNewExp& n)
1819 {
1820 SgType* accessTy = new SgAdaAccessType(n.get_type(), false /*generalAccess*/, true /* its anonymous at this point */);
1821 // SgType* accessTy = &mkAdaAccessType(n.get_type(), false /*generalAccess*/, true /* its anonymous at this point */);
1822
1823 res = TypeDescription{accessTy};
1824 }
1825
1826 void handle(const SgPointerDerefExp& n)
1827 {
1828 const SgExpression& op = SG_DEREF(n.get_operand());
1829
1830 res = sg::dispatch(DerefedType{}, typeOfExpr(op).typerep());
1831 }
1832
1833 void handle(const SgPntrArrRefExp& n)
1834 {
1835 const SgExpression& arr = SG_DEREF(n.get_lhs_operand());
1836 SgType* resty = typeOfExpr(arr).typerep();
1837 const SgExpression& idx = SG_DEREF(n.get_rhs_operand());
1838 const bool slice = containsRange(idx);
1839
1840 if (!slice) resty = arrayBaseType(resty); // resolve to element type
1841
1842 res = TypeDescription{resty};
1843 }
1844
1845 // SgRangeExp::get_type returns TypeDefault
1846 // returning the type of the range elements seems more appropriate
1847 // \todo it seems appropriate to introduce a RangeType with underlying type?
1848 void handle(const SgRangeExp& n)
1849 {
1850 const SgExpression& lhs = SG_DEREF(n.get_start());
1851
1852 res = TypeDescription{lhs.get_type()};
1853 }
1854
1855 void handle(const SgTypeExpression& n)
1856 {
1857 res = TypeDescription{n.get_type()};
1858 }
1859
1860 void handle(const SgIntVal&) { res = TypeDescription{ integralType() }; }
1861 void handle(const SgLongIntVal&) { res = TypeDescription{ integralType() }; }
1862 void handle(const SgLongLongIntVal&) { res = TypeDescription{ integralType() }; }
1863
1864 // SgTypeString does not preserve the 'wideness', so let's just get
1865 // this info from the literal.
1866 void handle(const SgStringVal& n)
1867 {
1868 SgType* strty = nullptr;
1869
1870 if (n.get_is16bitString()) strty = &standardType("Wide_String");
1871 else if (n.get_is32bitString()) strty = &standardType("Wide_Wide_String");
1872 else strty = &standardType("String");
1873
1874 ASSERT_not_null(strty);
1875 //~ std::cerr << typeid(*strty).name() << std::endl;
1876 res = TypeDescription{strty};
1877 }
1878
1879 void handle(const SgConditionalExp& n)
1880 {
1881 // \todo implement Ada type resolution
1882 // http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-4-5-7.html#I2901
1883 TypeDescription truDesc = typeOfExpr(n.get_true_exp());
1884 TypeDescription falDesc = typeOfExpr(n.get_false_exp());
1885
1886 res = TypeDescription{ commonDenominator(truDesc.typerep(), falDesc.typerep()) };
1887 }
1888
1889 // Currently, we have no concept of class-wide type,
1890 // thus the information is returned as flag.
1891 // \todo it seems appropriate to introduce a AdaClassType with underlying type?
1892 void handle(const SgAdaAttributeExp& n)
1893 {
1894 const bool polymorph = isClassAttribute(n);
1895
1896 res = TypeDescription{ SG_DEREF(n.get_type()), polymorph };
1897 }
1898
1899 // an actual argument expression could have one of the special cases
1900 // underneath. => use typeOfExpr..
1901 void handle(const SgActualArgumentExpression& n)
1902 {
1903 res = typeOfExpr(n.get_expression());
1904 }
1905
1906 void handle(const SgOrOp&) { res = TypeDescription{ &standardType("BOOLEAN") }; }
1907 void handle(const SgAndOp&) { res = TypeDescription{ &standardType("BOOLEAN") }; }
1908 void handle(const SgMembershipOp&) { res = TypeDescription{ &standardType("BOOLEAN") }; }
1909 void handle(const SgNonMembershipOp&) { res = TypeDescription{ &standardType("BOOLEAN") }; }
1910 };
1911
1912 bool fromRootType(SgAdaSubtype* ty)
1913 {
1914 return ty && ty->get_fromRootType();
1915 }
1916
1917 struct RootTypeFinder : sg::DispatchHandler<TypeDescription>
1918 {
1919 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
1920
1921 //~ void handle(SgType& n) { res = &n; }
1922
1923 // all root types (according to the three builder function in AdaMaker.C)
1924 void handle(SgTypeLongLong&) { res = TypeDescription{integralType()}; }
1925 void handle(SgTypeLongDouble&) { res = TypeDescription{realType()}; }
1926 void handle(SgTypeFixed&) { res = TypeDescription{fixedType()}; }
1927
1928 // plus discrete type indicator for Ada generics
1929 void handle(SgAdaDiscreteType& n) { res = TypeDescription{n}; }
1930
1931 // modular type: handle like int?
1932 void handle(SgAdaModularType&) { res = TypeDescription{integralType()}; }
1933
1934 // are subroutines their own root type?
1935 void handle(SgAdaSubroutineType& n) { res = TypeDescription{n}; }
1936
1937 // plus types used by AdaMaker but that do not have a direct correspondence
1938 // in the Ada Standard.
1939 void handle(SgTypeVoid& n) { res = TypeDescription{n}; }
1940 void handle(SgTypeUnknown& n) { res = TypeDescription{n}; }
1941 void handle(SgAutoType& n) { res = TypeDescription{n}; }
1942
1943 void handle(SgTypeDefault& n)
1944 {
1945 // this is a type used by a opaque declaration.
1946 // \todo maybe needs replacement with the actual type.
1947 res = TypeDescription{n};
1948 }
1949
1950 // the package standard uses an enumeration to define boolean, so include the
1951 // ROSE bool type also.
1952 // \todo remove BOOL_IS_ENUM_IN_ADA
1953 void handle(SgTypeBool& n) { res = TypeDescription{n}; }
1954
1955 // plus: map all other fundamental types introduced by initializeStandardPackage in AdaType.C
1956 // onto the root types defined by AdaMaker.C
1957 // \todo eventually all types in initializeStandardPackage should be rooted in
1958 // the root types as defined by AdaMaker.C.
1959 void handle(SgTypeInt&) { res = TypeDescription{integralType()}; }
1960 void handle(SgTypeLong&) { res = TypeDescription{integralType()}; }
1961 void handle(SgTypeShort&) { res = TypeDescription{integralType()}; }
1962
1963 void handle(SgTypeFloat&) { res = TypeDescription{realType()}; }
1964 void handle(SgTypeDouble&) { res = TypeDescription{realType()}; }
1965 void handle(SgTypeFloat128&) { res = TypeDescription{realType()}; }
1966
1967 // \todo remove CHARS_ARE_ENUM_IN_ADA
1968 void handle(SgTypeChar& n) { res = TypeDescription{n}; } // \todo find the type in Standard.
1969 void handle(SgTypeChar16& n) { res = TypeDescription{n}; } // \todo find the type in Standard.
1970 void handle(SgTypeChar32& n) { res = TypeDescription{n}; } // \todo find the type in Standard.
1971
1972 // true fundamental types
1973 void handle(SgClassType& n) { res = TypeDescription{n}; /* \todo check if this is a derived class */ }
1974 void handle(SgEnumType& n) { res = TypeDescription{n}; /* \todo check if this is a derived enum */ }
1975 void handle(SgAdaTaskType& n) { res = TypeDescription{n}; }
1976 void handle(SgAdaProtectedType& n) { res = TypeDescription{n}; }
1977 void handle(SgAdaFormalType& n) { res = TypeDescription{n}; /* what else? */ }
1978
1979
1980 // an array is fundamental - its underlying type may not be, so it may be discovered if needed
1981 void handle(SgArrayType& n)
1982 {
1983 res = TypeDescription{arrayType(find(n.get_base_type()).typerep())};
1984 }
1985
1986 void handle(SgTypeString&)
1987 {
1988 // can be reached from any string literal, which stores the character type is attribute...
1989 // since we have no info about the character type, just return the standard string type
1990 res = TypeDescription{arrayType(sb::buildCharType())};
1991 }
1992
1993 // pointer types
1994 void handle(SgTypeNullptr&) { res = TypeDescription{pointerType()}; } // \todo correct?
1995 void handle(SgPointerType&) { res = TypeDescription{pointerType()}; } // \todo NO_POINTER_IN_ADA
1996 void handle(SgAdaAccessType&) { res = TypeDescription{pointerType()}; }
1997
1998
1999 // \todo add string types as introduced by initializeStandardPackage in AdaType.C
2000 // \todo add other fundamental types as introduced by initializeStandardPackage in AdaType.C
2001
2002 // all type indirections that do not define fundamental types
2003 void handle(SgModifierType& n) { res = find(n.get_base_type()); }
2004 void handle(SgAdaSubtype& n) { res = find(n.get_base_type()); }
2005 void handle(SgAdaDerivedType& n) { res = find(n.get_base_type()); }
2006
2007 // \todo SUPPORT_RANGE_TYPES
2008 // just return the range type n?
2009 void handle(SgRangeType& n) { res = find(n.get_base_type()); }
2010
2011 void handle(SgTypedefType& n)
2012 {
2013 SgType* basety = base_type(n).stripType(SgType::STRIP_MODIFIER_TYPE);
2014
2015 const bool useThisDecl = ( isSgAdaDerivedType(basety)
2016 || isSgAdaAccessType(basety)
2017 || isSgAdaModularType(basety)
2018 || isSgArrayType(basety)
2019 || fromRootType(isSgAdaSubtype(basety))
2020 );
2021
2022 // end copied code
2023 res = useThisDecl ? TypeDescription{n} : find(basety);
2024 }
2025
2026 void handle(SgAdaDiscriminatedType& n)
2027 {
2028 // \todo not sure..
2029 res = TypeDescription{n};
2030 }
2031
2032 void handle(SgDeclType& n)
2033 {
2034 // \todo not sure..
2035 //~ std::cerr << typeid(*n.get_base_expression()).name() << ' '
2036 //~ << n.get_base_expression()->unparseToString()
2037 //~ << std::endl;
2038 res = typeRoot(typeOfExpr(n.get_base_expression()).typerep());
2039 }
2040
2041 static
2042 TypeDescription find(SgType* ty);
2043 };
2044
2045 TypeDescription
2046 RootTypeFinder::find(SgType* ty)
2047 {
2048 return sg::dispatch(RootTypeFinder{}, ty);
2049 }
2050
2051 struct DeclScopeFinder : sg::DispatchHandler<SgScopeStatement*>
2052 {
2054
2055 static
2056 SgScopeStatement* find(const SgNode*);
2057
2058 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
2059
2060 //
2061 // expression based types
2062
2063 // base case, do nothing
2064 void handle(const SgExpression&) {}
2065
2066 void handle(const SgAdaAttributeExp& n)
2067 {
2068 res = pkgStandardScope();
2069
2070 if (isClassAttribute(n))
2071 if (SgTypeExpression* tyex = isSgTypeExpression(n.get_object()))
2072 res = find(tyex->get_type());
2073 }
2074
2075 void handle(const SgVarRefExp& n) { res = declOf(n).get_scope(); }
2076
2077 //
2078 // types
2079
2080 void handle(const SgType&) { /* \todo do nothing for now; should disappear and raise error */ }
2081
2082 // all root types (according to the three builder function in AdaMaker.C)
2083 void handle(const SgTypeLongLong&) { res = pkgStandardScope(); }
2084 void handle(const SgTypeLongDouble&) { res = pkgStandardScope(); }
2085 void handle(const SgTypeFixed&) { res = pkgStandardScope(); }
2086
2087 // modular type: handle like int?
2088 void handle(const SgAdaModularType&) { res = pkgStandardScope(); }
2089
2090 // are subroutines their own root type?
2091 void handle(const SgAdaSubroutineType&) { res = pkgStandardScope(); }
2092
2093 // plus types used by AdaMaker but that do not have a direct correspondence
2094 // in the Ada Standard.
2095 void handle(const SgTypeVoid&) { res = pkgStandardScope(); }
2096 void handle(const SgTypeUnknown&) { res = pkgStandardScope(); }
2097 void handle(const SgAutoType&) { res = pkgStandardScope(); }
2098 void handle(const SgTypeDefault&) { res = pkgStandardScope(); }
2099
2100 // the package standard uses an enumeration to define boolean, so include the
2101 // ROSE bool type also.
2102 // \todo remove BOOL_IS_ENUM_IN_ADA
2103 void handle(const SgTypeBool&) { res = pkgStandardScope(); }
2104
2105 // plus composite type of literals in the AST
2106 void handle(const SgTypeString&) { res = pkgStandardScope(); }
2107
2108
2109 // \todo implement generics based on test cases
2110 // void handle(const SgAdaFormalType& n) { res = &n; }
2111 // void handle(const SgAdaDiscreteType& n) { res = pkgStandardScope(); } // \todo
2112
2113 // plus: map all other fundamental types introduced by AdaType.C:initializePkgStandard
2114 // onto the root types defined by AdaMaker.C
2115 // \todo eventually all types in initializePkgStandard should be rooted in
2116 // the root types as defined by AdaMaker.C.
2117 void handle(const SgTypeInt&) { res = pkgStandardScope(); }
2118 void handle(const SgTypeLong&) { res = pkgStandardScope(); }
2119 void handle(const SgTypeShort&) { res = pkgStandardScope(); }
2120
2121 void handle(const SgTypeFloat&) { res = pkgStandardScope(); }
2122 void handle(const SgTypeDouble&) { res = pkgStandardScope(); }
2123
2124 void handle(const SgTypeChar&) { res = pkgStandardScope(); }
2125 void handle(const SgTypeChar16&) { res = pkgStandardScope(); }
2126 void handle(const SgTypeChar32&) { res = pkgStandardScope(); }
2127
2128
2129 // Ada kind of fundamental types
2130 void handle(const SgArrayType&) { res = pkgStandardScope(); }
2131 void handle(const SgTypeNullptr&) { res = pkgStandardScope(); }
2132
2133 void handle(const SgPointerType& n) { res = find(n.get_base_type()); } // \todo NO_POINTER_IN_ADA
2134 void handle(const SgAdaAccessType& n) { res = find(n.get_base_type()); } // \todo or scope of underlying type?
2135
2136 // \todo add string types as introduced by AdaType.C:initializePkgStandard
2137 // \todo add other fundamental types as introduced by AdaType.C:initializePkgStandard
2138
2139 // all type indirections that do not have a separate declaration associated
2140 // \todo may need to be reconsidered
2141 void handle(const SgModifierType& n) { res = find(n.get_base_type()); }
2142 void handle(const SgAdaSubtype& n) { res = find(n.get_base_type()); }
2143 void handle(const SgAdaDerivedType& n) { res = find(n.get_base_type()); }
2144 void handle(const SgRangeType& n) { res = find(n.get_base_type()); }
2145 // void handle(const SgDeclType& n) { res = pkgStandardScope(); }
2146
2147 // for records, enums, typedefs, discriminated types, and types with a real declarations
2148 // => return the scope where they were defined.
2149 void handle(const SgNamedType& n) { res = SG_DEREF(n.get_declaration()).get_scope(); }
2150
2151 void handle(const SgTypedefType& n)
2152 {
2153 SgType* basety = base_type(n).stripType(SgType::STRIP_MODIFIER_TYPE);
2154
2155 const bool useThisDecl = ( isSgAdaDerivedType(basety)
2156 || isSgAdaAccessType(basety)
2157 || isSgAdaModularType(basety)
2158 || isSgArrayType(basety)
2159 || fromRootType(isSgAdaSubtype(basety))
2160 );
2161
2162 //~ std::cerr << "DeclScopeFinder: " << (basety ? typeid(*basety).name() : std::string{"0"})
2163 //~ << ": " << n.get_name() << " " << useThisDecl
2164 //~ << std::endl;
2165
2166 if (useThisDecl)
2167 res = dominant_declaration(n).get_scope();
2168 else
2169 res = find(basety);
2170 }
2171
2172 //
2173 void handle(const SgDeclType& n) { res = find(n.get_base_expression()); }
2174 };
2175
2176 SgScopeStatement* DeclScopeFinder::find(const SgNode* n)
2177 {
2178 return sg::dispatch(DeclScopeFinder{}, n);
2179 }
2180
2182 associatedDeclaration_internal(const SgType* ty, int skipNumAccessTypes = -1);
2183
2185 struct DeclFinder : sg::DispatchHandler<SgDeclarationStatement*>
2186 {
2187 explicit
2188 DeclFinder(int skipLayers)
2189 : skipAccessLayers(skipLayers)
2190 {}
2191
2192 SgDeclarationStatement* fromBaseType(SgType*);
2193
2194 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
2195
2196 void handle(SgType&) { /* \todo do nothing for now; should disappear and raise error */ }
2197
2198 // \todo may need to be reconsidered
2199 void handle(SgModifierType& n) { res = associatedDeclaration_internal(n.get_base_type(), skipAccessLayers); }
2200 void handle(SgAdaSubtype& n) { res = associatedDeclaration_internal(n.get_base_type(), skipAccessLayers); }
2201 void handle(SgAdaDerivedType& n) { res = associatedDeclaration_internal(n.get_base_type(), skipAccessLayers); }
2202 void handle(SgPointerType& n) { res = fromBaseType(n.get_base_type()); } // \todo NO_POINTER_IN_ADA
2203 void handle(SgAdaAccessType& n) { res = fromBaseType(n.get_base_type()); }
2204 void handle(SgRangeType& n) { res = fromBaseType(n.get_base_type()); }
2205
2206 //~ void handle(SgArrayType& n) { res = associatedDeclaration(n.get_base_type()); }
2207 // void handle(SgDeclType& n) { res = pkgStandardScope(); }
2208
2209 // for records, enums, typedefs, discriminated types, and types with a real declarations
2210 // => return the associated declaration.
2211 void handle(SgNamedType& n) { res = n.get_declaration(); }
2212
2213 private:
2214 const int skipAccessLayers;
2215 };
2216
2218 DeclFinder::fromBaseType(SgType* baseTy)
2219 {
2220 if (skipAccessLayers == 0)
2221 return nullptr;
2222
2223 return associatedDeclaration_internal(baseTy, (skipAccessLayers > 0) ? skipAccessLayers-1 : skipAccessLayers);
2224 }
2225
2227 associatedDeclaration_internal(const SgType* ty, int skipNumAccessTypes)
2228 {
2229 return sg::dispatch(DeclFinder{ skipNumAccessTypes }, ty);
2230 }
2231
2232
2233 struct ImportedUnit : sg::DispatchHandler<ImportedUnitResult>
2234 {
2236
2237 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
2238
2239 void handle(const SgFunctionRefExp& n)
2240 {
2241 res = ReturnType{ nameOf(n), &declOf(n), nullptr, &n };
2242 }
2243
2244 void handle(const SgAdaUnitRefExp& n)
2245 {
2246 const SgDeclarationStatement* dcl = &declOf(n);
2247
2248 if (const SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(dcl))
2249 dcl = gendcl->get_declaration();
2250
2251 ASSERT_not_null(dcl);
2252 res = ReturnType{ nameOf(n), dcl, nullptr, &n };
2253 }
2254
2255 void handle(const SgAdaRenamingRefExp& n)
2256 {
2257 res = ReturnType{ nameOf(n), n.get_decl(), n.get_decl(), &n};
2258 }
2259 };
2260 } // end anonymous namespace
2261
2263 {
2264 return SG_DEREF(stdpkg).get_definition();
2265 }
2266
2268 {
2269 ScopePath path = pathToGlobal(n);
2270 const SgAdaPackageSpec* toplevel = isSgAdaPackageSpec(path.back());
2271 if (!toplevel) return false;
2272
2273 const SgAdaPackageSpecDecl* pkgdcl = isSgAdaPackageSpecDecl(toplevel->get_parent());
2274 if (!pkgdcl) return false;
2275
2276 const std::string pkgname = boost::to_upper_copy(pkgdcl->get_name().getString());
2277
2278 return ( pkgname == "ADA"
2279 || pkgname == "INTERFACES"
2280 || pkgname == "SYSTEM"
2281 || pkgname == "STANDARD"
2282 );
2283 }
2284
2286 {
2287 return n && systemPackage(*n);
2288 }
2289
2290 SgType& TypeDescription::typerep_ref() const
2291 {
2292 return SG_DEREF(typerep());
2293 }
2294
2296 {
2297 //~ std::cerr << typeid(ty).name() << std::endl;
2298 return RootTypeFinder::find(&ty);
2299 }
2300
2302 {
2303 return ty ? typeRoot(*ty) : TypeDescription{nullptr};
2304 }
2305
2307 {
2308 return sg::dispatch(ExprTypeFinder{}, &exp);
2309 }
2310
2312 {
2313 return exp ? typeOfExpr(*exp) : TypeDescription{nullptr};
2314 }
2315
2317 {
2318 if (const SgAdaAccessType* acc = isSgAdaAccessType(ty))
2319 return acc->get_base_type();
2320
2321 if (const SgAdaDerivedType* drv = isSgAdaDerivedType(ty))
2322 return baseOfAccessType(drv->get_base_type());
2323
2324 if (const SgAdaSubtype* sub = isSgAdaSubtype(ty))
2325 return baseOfAccessType(sub->get_base_type());
2326
2327 if (const SgPointerType* ptr = isSgPointerType(ty))
2328 return ptr->get_base_type();
2329
2330 if (const SgTypedefType* tydef = isSgTypedefType(ty))
2331 return baseOfAccessType(base_type(*tydef));
2332
2333 if (const SgModifierType* modty = isSgModifierType(ty))
2334 return baseOfAccessType(modty->get_base_type());
2335
2336 if (const SgAdaFormalType* frmty = isSgAdaFormalType(ty))
2337 return baseOfAccessType(frmty->get_formal_type());
2338
2339 return nullptr;
2340 }
2341
2343 {
2344 return baseOfAccessType(&ty);
2345 }
2346
2347 namespace
2348 {
2349 // function checks if opname requires special handling for fixed types
2350 // \note PP
2351 // operator scope for fixed types is weirdly bizarre.
2352 // behavior re-engineered from ACATS tests.
2353 // see types_operators.adb for some test cases.
2354 bool isFixedSpecialOperator(const std::string& opname)
2355 {
2356 return opname == "*" || opname == "/";
2357 }
2358
2359 // function checks if operator opname(argtypes.front(), argtypes.back())
2360 // needs to be placed in package standard.
2361 bool isFixedSpecial(const std::string& opname, const SgTypePtrList& argtypes)
2362 {
2363 if (!isFixedSpecialOperator(opname))
2364 return false;
2365
2366 ROSE_ASSERT(argtypes.size() >= 1);
2367 return resolvesToFixedType(argtypes.front()) && resolvesToFixedType(argtypes.back());
2368 }
2369
2370 // function checks if operator opname(argtypes.front(), argtypes.back())
2371 // needs to be placed in package standard.
2372 bool isFixedSpecial(const std::string& opname, const SgType& ty)
2373 {
2374 return isFixedSpecial(opname, { const_cast<SgType*>(&ty) });
2375 }
2376 }
2377
2378 DominantArgInfo
2379 operatorArgumentWithNamedRootIfAvail(const SgTypePtrList& argtypes)
2380 {
2381 ROSE_ASSERT(argtypes.size() == 1 || argtypes.size() == 2);
2382
2383 SgType* lhsty = argtypes.front();
2384
2385 //~ std::cerr << "l: " << typeid(*lhsty).name() << std::endl;
2386
2387 if (argtypes.size() == 1 || isSgNamedType(typeRoot(lhsty).typerep()))
2388 return { lhsty, 0 };
2389
2390 SgType* rhsty = argtypes.back();
2391
2392 //~ std::cerr << "r: " << typeid(*rhsty).name() << std::endl;
2393
2394 if (isSgNamedType(typeRoot(rhsty).typerep()))
2395 return { rhsty, argtypes.size()-1 };
2396
2397 return { lhsty, 0 };
2398 }
2399
2400
2401 OperatorScopeInfo
2402 operatorScope(const std::string& opname, const SgTypePtrList& argtypes)
2403 {
2404 ROSE_ASSERT(argtypes.size());
2405
2406 if (isFixedSpecial(opname, argtypes))
2407 {
2408 // fixedSpecial requires both arguments to be of fixed type
2409 return { pkgStandardScope(), 0 };
2410 }
2411
2412 DominantArgInfo dominantType = operatorArgumentWithNamedRootIfAvail(argtypes);
2413
2414 return { declarationScope(dominantType.type()), dominantType.pos() };
2415 }
2416
2418 operatorScope(const std::string& opname, const SgType& ty)
2419 {
2420 if (isFixedSpecial(opname, ty))
2421 return SG_DEREF(pkgStandardScope());
2422
2423 return SG_DEREF(declarationScope(ty));
2424 }
2425
2427 operatorScope(const std::string& opname, const SgType* ty)
2428 {
2429 if (ty == nullptr) return nullptr;
2430
2431 return &operatorScope(opname, *ty);
2432 }
2433
2434
2436 {
2437 return DeclScopeFinder::find(ty);
2438 }
2439
2441 {
2442 return declarationScope(&ty);
2443 }
2444
2446 {
2447 return associatedDeclaration_internal(&ty);
2448 }
2449
2451 {
2452 return ty ? associatedDeclaration(*ty) : nullptr;
2453 }
2454
2455
2456 std::vector<ImportedUnitResult>
2458 {
2459 std::vector<ImportedUnitResult> res;
2460 const SgExpressionPtrList& lst = impdcl.get_import_list();
2461
2462 std::transform( lst.begin(), lst.end(),
2463 std::back_inserter(res),
2464 [](const SgExpression* exp) -> ImportedUnitResult
2465 {
2466 return sg::dispatch(ImportedUnit{}, exp);
2467 }
2468 );
2469
2470 return res;
2471 }
2472
2473
2474
2475/*
2476 std::set<std::string> adaOperatorNames()
2477 {
2478 std::string elems[] =
2479
2480 return std::set<std::string>(elems, elems + sizeof(elems) / sizeof(elems[0]));
2481 }
2482(/
2483*/
2484
2485 namespace
2486 {
2487 bool isOperatorName(const std::string& id)
2488 {
2489 static std::set<std::string> adaops =
2490 { "+", "-", "*", "/", "**", "REM", "MOD", "ABS"
2491 , "=", "/=", "<", ">", "<=", ">="
2492 , "NOT", "AND", "OR", "XOR", "&"
2493 };
2494
2495 const std::string canonicalname = boost::to_upper_copy(id);
2496
2497 return adaops.find(canonicalname) != adaops.end();
2498 }
2499 }
2500
2501 std::string convertRoseOperatorNameToAdaOperator(const std::string& name)
2502 {
2503 if (name.rfind(si::Ada::roseOperatorPrefix, 0) != 0)
2504 return {};
2505
2506 const std::string op = name.substr(si::Ada::roseOperatorPrefix.size());
2507
2508 if (!isOperatorName(op))
2509 return {};
2510
2511 return op;
2512 }
2513
2514 std::string convertRoseOperatorNameToAdaName(const std::string& name)
2515 {
2516 static const std::string quotes = "\"";
2517
2518 if (name.rfind(si::Ada::roseOperatorPrefix, 0) != 0)
2519 return name;
2520
2521 const std::string op = name.substr(si::Ada::roseOperatorPrefix.size());
2522
2523 if (!isOperatorName(op))
2524 return name;
2525
2526 return quotes + op + quotes;
2527 }
2528
2529 // Model after Ada unparser: 05/11/2024
2531 {
2532 void add(SgNode* n) { res.push_back(n); }
2533 void add_opt(SgNode* n) { if (n) add(n); }
2534
2535 template <class SageNode>
2536 void handleWithGetType(SageNode& n)
2537 {
2538 handle(sg::asBaseType(n));
2539
2540 add(n.get_type());
2541 }
2542
2543 void handle(SgNode& n) { SG_UNEXPECTED_NODE(n); }
2544
2545 // expressions with types
2546 void handle(SgExpression& n) { res = n.get_traversalSuccessorContainer(); }
2547 void handle(SgCastExp& n) { handleWithGetType(n); }
2548 void handle(SgTypeExpression& n) { handleWithGetType(n); }
2549
2550 void handle(SgNewExp& n)
2551 {
2552 handle(sg::asBaseType(n));
2553
2554 add(n.get_specified_type());
2555 }
2556
2557 // statements/declarations with types
2558 void handle(SgStatement& n) { res = n.get_traversalSuccessorContainer(); }
2559 void handle(SgAdaRenamingDecl& n) { handleWithGetType(n); }
2560 void handle(SgFunctionDeclaration&& n) { handleWithGetType(n); }
2561
2562 void handle(SgAdaRepresentationClause& n)
2563 {
2564 handle(sg::asBaseType(n));
2565
2566 add(n.get_recordType());
2567 }
2568
2569 void handle(SgAdaEnumRepresentationClause& n)
2570 {
2571 handle(sg::asBaseType(n));
2572
2573 add(n.get_enumType());
2574 }
2575
2576 void handle(SgVariableDeclaration& n)
2577 {
2578 ASSERT_require(n.get_variables().size() > 0);
2579
2580 handle(sg::asBaseType(n));
2581
2582 add(SG_DEREF(n.get_variables().front()).get_type());
2583 }
2584
2585 void handle(SgTypedefDeclaration& n)
2586 {
2587 handle(sg::asBaseType(n));
2588
2589 add(n.get_base_type());
2590 }
2591
2592 void handle(SgAdaFormalTypeDecl& n)
2593 {
2594 handle(sg::asBaseType(n));
2595
2596 add(SG_DEREF(n.get_type()).get_formal_type());
2597 }
2598
2599 // types
2600
2601 void handle(SgType&) { /* do nothing */ }
2602
2603 void handle(SgAdaDerivedType& n) { add(n.get_base_type()); }
2604 void handle(SgAdaModularType& n) { add(n.get_modexpr()); }
2605 void handle(SgDeclType& n) { add(n.get_base_expression()); }
2606 void handle(SgFunctionType& n) { add(n.get_return_type()); }
2607 void handle(SgRangeType& n) { add(n.get_base_type()); }
2608 void handle(SgAdaAccessType& n) { add(n.get_base_type()); }
2609 void handle(SgPointerType& n) { add(n.get_base_type()); } // \todo remove
2610
2611 void handle(SgAdaSubtype& n)
2612 {
2613 add(n.get_base_type());
2614 add_opt(n.get_constraint());
2615 }
2616
2617 void handle(SgTypeTuple& n)
2618 {
2619 SgTypePtrList& lst = n.get_types();
2620
2621 std::copy( lst.begin(), lst.end(), std::back_inserter(res) );
2622 }
2623
2624 void handle(SgArrayType& n)
2625 {
2626 add(n.get_dim_info());
2627 add(n.get_base_type());
2628 }
2629
2630
2631 // other nodes
2632
2633 void handle(SgLocatedNodeSupport& n) { res = n.get_traversalSuccessorContainer(); }
2634
2635 void handle(SgAdaRangeConstraint& n) { res.push_back(n.get_range()); }
2636
2637 void handle(SgAdaDigitsConstraint& n)
2638 {
2639 add(n.get_digits());
2640 add_opt(n.get_subConstraint());
2641 }
2642
2643 void handle(SgAdaDeltaConstraint& n)
2644 {
2645 add(n.get_delta());
2646 add_opt(n.get_subConstraint());
2647 }
2648
2649 void handle(SgAdaIndexConstraint& n)
2650 {
2651 SgExpressionPtrList& lst = n.get_indexRanges();
2652
2653 std::copy( lst.begin(), lst.end(), std::back_inserter(res) );
2654 }
2655
2656 void handle(SgAdaDiscriminantConstraint& n)
2657 {
2658 SgExpressionPtrList& lst = n.get_discriminants();
2659
2660 std::copy( lst.begin(), lst.end(), std::back_inserter(res) );
2661 }
2662 };
2663
2664
2666 {
2667 explicit
2668 SimpleTraversal(std::function<void(SgNode*)>&& conversionFn)
2669 : AstSimpleProcessing(), fn(std::move(conversionFn))
2670 {}
2671
2672 void visit(SgNode*) override;
2673
2674 private:
2675 std::function<void(SgNode*)> fn;
2676
2677 SimpleTraversal() = delete;
2678 SimpleTraversal(const SimpleTraversal&) = delete;
2679 SimpleTraversal(SimpleTraversal&&) = delete;
2680 SimpleTraversal& operator=(SimpleTraversal&&) = delete;
2681 SimpleTraversal& operator=(const SimpleTraversal&) = delete;
2682 };
2683
2684 void SimpleTraversal::visit(SgNode* n)
2685 {
2686 fn(n);
2687 }
2688
2689 StatementRange
2690 declsInPackage(SgGlobal& globalScope, const std::string& mainFile)
2691 {
2692 auto declaredInMainFile = [&mainFile](const SgDeclarationStatement* dcl)->bool
2693 {
2694 ASSERT_not_null(dcl);
2695
2696 const Sg_File_Info& fileInfo = SG_DEREF(dcl->get_startOfConstruct());
2697
2698 return fileInfo.get_filenameString() == mainFile;
2699 };
2700 auto notDeclaredInMainFile = [&declaredInMainFile](const SgDeclarationStatement* dcl)->bool
2701 {
2702 return !declaredInMainFile(dcl);
2703 };
2704
2705 SgDeclarationStatementPtrList& lst = globalScope.get_declarations();
2706 SgDeclarationStatementPtrList::iterator zz = lst.end();
2707 SgDeclarationStatementPtrList::iterator first = std::find_if(lst.begin(), zz, declaredInMainFile);
2708 SgDeclarationStatementPtrList::iterator limit = std::find_if(first, zz, notDeclaredInMainFile);
2709
2710 return std::make_pair(first, limit);
2711 }
2712
2713
2714 StatementRange
2715 declsInPackage(SgGlobal& globalScope, const SgSourceFile& mainFile)
2716 {
2717 return declsInPackage(globalScope, mainFile.getFileName());
2718 }
2719
2720
2721
2724 {
2725 explicit
2726 CommentCxxifier(bool useLineComments)
2727 : prefix(useLineComments ? "//" : "/*"),
2728 suffix(useLineComments ? "" : "*/"),
2729 commentKind(useLineComments ? PreprocessingInfo::CplusplusStyleComment : PreprocessingInfo:: C_StyleComment)
2730 {}
2731
2732 CommentCxxifier(CommentCxxifier&&) = default;
2733 CommentCxxifier(const CommentCxxifier&) = default;
2734
2735 void operator()(SgNode*) const;
2736
2737 private:
2738 //~ bool lineComments;
2739 const std::string prefix;
2740 const std::string suffix;
2741 const PreprocessingInfo::DirectiveType commentKind;
2742
2743 CommentCxxifier() = delete;
2744 CommentCxxifier& operator=(const CommentCxxifier&) = delete;
2745 CommentCxxifier& operator=(CommentCxxifier&&) = delete;
2746 };
2747
2748
2749 void CommentCxxifier::operator()(SgNode* n) const
2750 {
2751 SgLocatedNode* node = isSgLocatedNode(n);
2752 if (node == nullptr) return;
2753
2754 AttachedPreprocessingInfoType* prepInfo = node->getAttachedPreprocessingInfo();
2755 if (prepInfo == nullptr) return;
2756
2757 for (PreprocessingInfo* ppinfo : *prepInfo)
2758 {
2759 ASSERT_not_null(ppinfo);
2760
2761 if (ppinfo->getTypeOfDirective() != PreprocessingInfo::AdaStyleComment) continue;
2762
2763 std::string comment = ppinfo->getString();
2764
2765 ROSE_ASSERT(comment.rfind("--", 0) == 0);
2766 comment.replace(0, 2, prefix);
2767 comment.append(suffix);
2768 ppinfo->setString(comment);
2769 ppinfo->setTypeOfDirective(commentKind);
2770 }
2771 }
2772
2774 {
2775 FunctionCallToOperatorConverter(bool convOperatorCalls, bool convNamedArgs)
2776 : convertOperatorCalls(convOperatorCalls), convertNamedArguments(convNamedArgs)
2777 {}
2778
2779 ~FunctionCallToOperatorConverter() { executeTransformations(); }
2780
2781 void executeTransformations() const;
2782
2783 void operator()(SgNode*);
2784
2785 private:
2786 using replacement_t = std::tuple<SgFunctionCallExp*, std::string>;
2787
2788 std::vector<replacement_t> work;
2789 const bool convertOperatorCalls;
2790 const bool convertNamedArguments;
2791
2793 //~ FunctionCallToOperatorConverter& operator=(const FunctionCallToOperatorConverter&) = delete;
2794 //~ FunctionCallToOperatorConverter& operator=(FunctionCallToOperatorConverter&&) = delete;
2795 };
2796
2797
2798 int arity(const SgFunctionCallExp& fncall)
2799 {
2800 SgExprListExp* args = fncall.get_args();
2801
2802 return SG_DEREF(args).get_expressions().size();
2803 }
2804
2805 inline
2806 bool hasNullArg(const SgFunctionCallExp& fncall)
2807 {
2808 SgExprListExp* args = fncall.get_args();
2809
2810 return isSgNullExpression(SG_DEREF(args).get_expressions().at(0));
2811 }
2812
2813 void FunctionCallToOperatorConverter::operator()(SgNode* n)
2814 {
2815 SgFunctionCallExp* fncall = isSgFunctionCallExp(n);
2816 if ( (fncall == nullptr)
2817 || ((!convertOperatorCalls) && (!fncall->get_uses_operator_syntax()))
2818 || (arity(*fncall) > 2)
2819 //~ || (hasNullArg(*fncall))
2820 )
2821 return;
2822
2824 if (fndecl == nullptr || (!definedInStandard(*fndecl))) return;
2825
2826 // only consider function names that map onto operators
2827 std::string op = convertRoseOperatorNameToAdaOperator(fndecl->get_name());
2828 if (op.empty()) return;
2829
2830 // none of the functions in Standard should be defined.
2831 ROSE_ASSERT(fndecl->get_definingDeclaration() == nullptr);
2832 work.emplace_back(fncall, std::move(op));
2833 }
2834
2835 using CallToOperatorTransformer = std::function<SgExpression&(SgExpressionPtrList)>;
2836
2837 template <class BinaryBuilderFn>
2838 CallToOperatorTransformer tf2(BinaryBuilderFn fn)
2839 {
2840 return [fn](SgExpressionPtrList operands) -> SgExpression&
2841 {
2842 ROSE_ASSERT(operands.size() == 2);
2843 SgExpression* lhs = operands[0];
2844 SgExpression* rhs = operands[1];
2845
2846 ASSERT_not_null(lhs);
2847 ASSERT_not_null(rhs);
2850
2851 si::replaceExpression(lhs, lhs_dummy, true /* keep */);
2852 si::replaceExpression(rhs, rhs_dummy, true /* keep */);
2853
2854 return SG_DEREF(fn(lhs, rhs));
2855 };
2856 }
2857
2858 template <class UnaryBuilderFn>
2859 CallToOperatorTransformer tf1(UnaryBuilderFn fn)
2860 {
2861 return [fn](SgExpressionPtrList operands) -> SgExpression&
2862 {
2863 ROSE_ASSERT(operands.size() == 1);
2864 SgExpression* arg = operands[0];
2865
2866 ASSERT_not_null(arg);
2868
2869 si::replaceExpression(arg, arg_dummy, true /* keep */);
2870 return SG_DEREF(fn(arg));
2871 };
2872 }
2873
2874 SgExpressionPtrList
2875 simpleArgumentExtractor(const SgFunctionCallExp& n, bool /* dummy */)
2876 {
2877 return SG_DEREF(n.get_args()).get_expressions();
2878 }
2879
2880 std::size_t
2881 namedArgumentPosition(const SgInitializedNamePtrList& paramList, const std::string& name)
2882 {
2883 SgInitializedNamePtrList::const_iterator aaa = paramList.begin();
2884 SgInitializedNamePtrList::const_iterator zzz = paramList.end();
2885 SgInitializedNamePtrList::const_iterator pos = std::find_if( aaa, zzz,
2886 [&name](const SgInitializedName* n) -> bool
2887 {
2888 ASSERT_not_null(n);
2889 return stringeq(name, n->get_name().getString());
2890 }
2891 );
2892
2893 if (pos == zzz)
2894 {
2895 // \todo this currently occurs for derived types, where the publicly
2896 // declared ancestor type differs from the actual parent.
2897 // see test case: ancestors.adb
2898 throw std::logic_error(std::string{"unable to find argument position for "} + name);
2899 }
2900
2901 return std::distance(aaa, pos);
2902 }
2903
2905 void extend(SgExpressionPtrList& container, std::size_t pos, SgExpression* val = nullptr)
2906 {
2907 const std::size_t sz = pos; // pos needs to be a valid index
2908
2909 if (container.size() < sz) container.resize(sz, val);
2910 }
2911
2912 void FunctionCallToOperatorConverter::executeTransformations() const
2913 {
2914 using OperandExtractor = decltype(&simpleArgumentExtractor);
2915 using BuilderMap = std::map<std::string, CallToOperatorTransformer>;
2916
2917 static const BuilderMap tfFn2 = { { "=", tf2(&sb::buildEqualityOp) }
2918 , { "/=", tf2(&sb::buildNotEqualOp) }
2919 , { "<", tf2(&sb::buildLessThanOp) }
2920 , { "<=", tf2(&sb::buildLessOrEqualOp) }
2921 , { ">", tf2(&sb::buildGreaterThanOp) }
2922 , { ">=", tf2(&sb::buildGreaterOrEqualOp) }
2923 , { "and", tf2(&sb::buildBitAndOp) }
2924 , { "or", tf2(&sb::buildBitOrOp) }
2925 , { "xor", tf2(&sb::buildBitXorOp) }
2926 , { "+", tf2(&sb::buildAddOp) }
2927 , { "-", tf2(&sb::buildSubtractOp) }
2928 , { "*", tf2(&sb::buildMultiplyOp) }
2929 , { "/", tf2(&sb::buildDivideOp) }
2930 , { "rem", tf2(&sb::buildRemOp) }
2931 , { "mod", tf2(&sb::buildModOp) }
2932 , { "**", tf2(&sb::buildExponentiationOp) }
2933 , { "&", tf2(&sb::buildConcatenationOp) }
2934 };
2935
2936 static const BuilderMap tfFn1 = { { "not", tf1(&sb::buildNotOp) }
2937 , { "abs", tf1(&sb::buildAbsOp) }
2938 , { "+", tf1(&sb::buildUnaryAddOp) }
2939 //~ , { "-", tf1(&sb::buildMinusOp) }
2940 , { "-", tf1(&sb::buildUnaryExpression<SgMinusOp>) }
2941 };
2942
2943 OperandExtractor operandExtractor = convertNamedArguments ? normalizedCallArguments
2944 : simpleArgumentExtractor;
2945
2946 for (const replacement_t& r : work)
2947 {
2948 SgFunctionCallExp& orig = SG_DEREF(std::get<0>(r));
2949 const int numargs = arity(orig);
2950 ROSE_ASSERT(numargs == 1 || numargs == 2);
2951 std::string const key = boost::to_lower_copy(std::get<1>(r));
2952 SgExpression& repl = numargs == 1 ? tfFn1.at(key)(operandExtractor(orig, false))
2953 : tfFn2.at(key)(operandExtractor(orig, false));
2954
2955 //~ if (orig.get_parent() == nullptr)
2956 //~ std::cerr << "parent is null: " << orig->unparseToString() << std::endl;
2957
2958 repl.set_need_paren(orig.get_need_paren());
2959 si::replaceExpression(&orig, &repl, false /* delete orig sub-tree */ );
2960 }
2961 }
2962
2963 namespace
2964 {
2965 bool declaresException(const SgVariableDeclaration& n)
2966 {
2967 const SgInitializedNamePtrList& varlst = n.get_variables();
2968 const SgInitializedName* first = varlst.at(0);
2969 if (!first) return false;
2970
2971 const SgTypedefType* ty = isSgTypedefType(first->get_type());
2972
2973 return ty && (stringeq(ty->get_name().getString(), si::Ada::exceptionName));
2974 }
2975 }
2976
2977
2980 {
2981 return declaresException(n) ? &n : nullptr;
2982 }
2983
2986 {
2987 return (n && declaresException(*n)) ? n : nullptr;
2988 }
2989
2992 {
2993 return declaresException(n) ? &n : nullptr;
2994 }
2995
2998 {
2999 return (n && declaresException(*n)) ? n : nullptr;
3000 }
3001
3004 {
3006 return assocfn->get_parameterList();
3007
3008 const SgExpression& target = SG_DEREF(n.get_function());
3009
3010 if (const SgAdaRenamingRefExp* renex = isSgAdaRenamingRefExp(&target))
3011 {
3012 const SgAdaRenamingDecl& rendcl = SG_DEREF(renex->get_decl());
3013
3014 if (const SgAdaSubroutineType* routty = isSgAdaSubroutineType(rendcl.get_type()))
3015 return routty->get_parameterList();
3016
3017 // return nullptr;
3018 }
3019 else if (const SgPointerDerefExp* drfexp = isSgPointerDerefExp(&target))
3020 {
3021 if (const SgAdaSubroutineType* routty = isSgAdaSubroutineType(drfexp->get_type()))
3022 return routty->get_parameterList();
3023 }
3024
3025 return nullptr;
3026 }
3027
3030 {
3031 return n ? calleeParameterList(*n) : nullptr;
3032 }
3033
3034 namespace
3035 {
3039 SgType*
3040 baseTypeOfClass(const SgClassType& n, bool publicInfoPreferred = false)
3041 {
3042 // \todo this requires revision
3043 // do we want to get the base type constraint from get_adaParentType
3044 // or the precise base class from the definition?
3045 SgType* res = nullptr;
3046 SgClassDeclaration& cldcl = SG_DEREF(isSgClassDeclaration(n.get_declaration()));
3047 SgClassDeclaration& nondefdcl = SG_DEREF(isSgClassDeclaration(cldcl.get_firstNondefiningDeclaration()));
3048 SgClassDeclaration& defdcl = SG_DEREF(isSgClassDeclaration(nondefdcl.get_definingDeclaration()));
3049 SgBaseClass* basecl = nullptr;
3050
3051 // the specific parent is known by the defining declaration
3052 const bool privateDecl = isPrivate(nondefdcl);
3053 const bool privateDefn = isPrivate(defdcl);
3054
3055 // get the direct inheritance if both decls are public, both decls are private,
3056 // or if publicInfoPreferred was not set.
3057 if ((privateDecl == privateDefn) || !publicInfoPreferred)
3058 {
3059 SgClassDefinition& cldef = SG_DEREF(defdcl.get_definition());
3060 SgBaseClassPtrList& bases = cldef.get_inheritances();
3061
3062 if (bases.size()) basecl = bases.front();
3063 }
3064
3065 // when publicInfoPreferred was requested or when the previous method failed.
3066 // \todo maybe this should just be an else branch of the previous condition..
3067 if (basecl == nullptr)
3068 {
3069 basecl = nondefdcl.get_adaParentType();
3070 }
3071
3072 if (const SgExpBaseClass* basexp = isSgExpBaseClass(basecl))
3073 {
3074 //~ std::cerr << "BaseTypeFinder: found expression base class" << std::endl;
3075 res = typeOfExpr(basexp->get_base_class_exp()).typerep();
3076 }
3077 else if (basecl)
3078 {
3079 SgClassDeclaration& basedcl = SG_DEREF(basecl->get_base_class());
3080
3081 res = basedcl.get_type();
3082 }
3083
3084 return res;
3085 }
3086
3087
3088
3090 bool
3091 isVisibleFrom(const SgDeclarationStatement& dcl, const SgScopeStatement& scope)
3092 {
3093 ScopePath path = pathToGlobal(scope);
3094 auto lim = path.end();
3095
3096 return lim != std::find(path.begin(), lim, dcl.get_scope());
3097 }
3098
3099
3100
3101
3102#if 0
3103 SgNamedType& assertNamedType(SgType* ty)
3104 {
3105 SgNamedType* res = isSgNamedType(ty);
3106 ASSERT_not_null(res);
3107
3108 return *res;
3109 }
3110
3116 extractBaseTypeFromSignature(const SgFunctionType& orig, const SgFunctionType& derv)
3117 {
3118 if (orig.get_return_type() != derv.get_return_type())
3119 return assertNamedType(orig.get_return_type());
3120
3121 SgTypePtrList& origParams = SG_DEREF(orig.get_argument_list()).get_arguments();
3122 SgTypePtrList& dervParams = SG_DEREF(derv.get_argument_list()).get_arguments();
3123 ASSERT_require(origParams.size() == dervParams.size());
3124
3125 auto iterpair = std::mismatch( origParams.begin(), origParams.end(), dervParams.begin() );
3126 ASSERT_require(iterpair.first != origParams.end());
3127
3128 return assertNamedType(*iterpair.first);
3129 }
3130
3132 std::vector<const SgType*>
3133 linearizePublicAncestors(const SgClassDeclaration& cldcl, const SgScopeStatement* /*scope_opt*/ = nullptr)
3134 {
3135 std::vector<const SgType*> res;
3136 SgClassType* clsty = cldcl.get_type();
3137
3138 while (clsty)
3139 {
3140 res.push_back(clsty);
3141
3142 // \todo passing true (only public) is not entirely correct
3143 // b/c whether private or public is needed depends on
3144 // whether the FULL decl associated with clsty is
3145 // visible from scope \ref scope_opt.
3146 clsty = isSgClassType(baseTypeOfClass(*clsty, true /* only public */));
3147 }
3148
3149 return res;
3150 }
3151
3153 bool isPublicAncestorOf(const SgNamedType& basety, const SgNamedType& drvty)
3154 {
3155 // find the most derived public declaration of drvty
3156 SgDeclarationStatement& drvdeclany = SG_DEREF(drvty.get_declaration());
3157
3158 // if the def is public => immediate parent is public => basetype is a public ancestor
3159 SgDeclarationStatement* drvdeclDef = drvdeclany.get_definingDeclaration();
3160 if (drvdeclDef && (!isPrivate(*drvdeclDef)))
3161 return true;
3162
3163 SgDeclarationStatement& drvdeclNondef = SG_DEREF(drvdeclany.get_firstNondefiningDeclaration());
3164 SgClassDeclaration* drvclssNondef = isSgClassDeclaration(&drvdeclNondef);
3165
3166 // PP believes that only classes can have distinct public and private ancestor/parent
3167 // specification.
3168 if (drvclssNondef == nullptr)
3169 return isPrivate(drvdeclNondef);
3170
3171 // check if basety is an ancestor of the most derived public declaration inheritance spec
3172 std::vector<const SgType*> ancestors = linearizePublicAncestors(*drvclssNondef);
3173 auto lim = ancestors.end();
3174
3175 return lim != std::find(ancestors.begin(), lim, &basety);
3176 }
3177#endif /* 0 */
3178
3179
3180 bool overridesBase(const SgFunctionType& dervFunTy, const SgType& dervTy, const SgFunctionType& baseFunTy, const SgType& baseTy)
3181 {
3182 auto validBaseOverriderType =
3183 [&dervTy, &baseTy](const SgType* drv, const SgType* bas) -> bool
3184 {
3185 return ( ((drv == &dervTy) && (bas == &baseTy))
3186 || ((drv != &dervTy) && (bas == drv))
3187 );
3188 };
3189
3190 const SgTypePtrList& dervArgs = SG_DEREF(dervFunTy.get_argument_list()).get_arguments();
3191 const SgTypePtrList& baseArgs = SG_DEREF(baseFunTy.get_argument_list()).get_arguments();
3192
3193 return ( validBaseOverriderType(dervFunTy.get_return_type(), baseFunTy.get_return_type())
3194 && std::equal( dervArgs.begin(), dervArgs.end(),
3195 baseArgs.begin(), baseArgs.end(),
3196 validBaseOverriderType
3197 )
3198 );
3199 }
3200
3202 symbolForBaseFunction(SgSymbol& sym, const SgFunctionType& dervFunTy, const SgType& baseTy, const SgType& dervTy)
3203 {
3204 SgFunctionSymbol* res = nullptr;
3205
3206 if (SgFunctionType* candty = isSgFunctionType(sym.get_type()))
3207 {
3208 if (overridesBase(dervFunTy, dervTy, *candty, baseTy))
3209 {
3210 res = isSgFunctionSymbol(&sym);
3211 ASSERT_not_null(res);
3212 }
3213 }
3214
3215 return res;
3216 }
3217
3218
3223 findFunctionSymbolForType( const SgClassType& basety,
3224 const SgType& dervty,
3225 std::string fnname,
3226 const SgFunctionType& drvFunType
3227 )
3228 {
3229 const SgClassDeclaration& clsdcl = SG_DEREF(isSgClassDeclaration(basety.get_declaration()));
3230 const SgScopeStatement& scope = SG_DEREF(clsdcl.get_scope());
3231 SgSymbol* sym = scope.lookup_symbol(fnname, nullptr, nullptr);
3232 SgFunctionSymbol* res = nullptr;
3233
3234 while (sym && !res)
3235 {
3236 res = symbolForBaseFunction(*sym, drvFunType, basety, dervty);
3237 sym = scope.next_any_symbol();
3238 }
3239
3240 return res;
3241 }
3242
3244 instantiatedDeclaration(const SgAdaGenericInstanceDecl& n)
3245 {
3246 SgScopeStatement& scope = SG_DEREF(n.get_instantiatedScope());
3247 SgDeclarationStatement* res = isSgDeclarationStatement(scope.firstStatement());
3248
3249 ASSERT_not_null(res);
3250 ASSERT_require(res == scope.lastStatement()); // any instantiation contains one decl
3251 return *res;
3252 }
3253
3254 struct AccessibleArgumentListFinder : sg::DispatchHandler<SgFunctionParameterList*>
3255 {
3257
3258 explicit
3259 AccessibleArgumentListFinder(const SgFunctionCallExp& callexp)
3260 : base(), call(&callexp)
3261 {}
3262
3263 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
3264
3265 //
3266 // types
3267
3268 void handle(const SgAdaSubroutineType& n) { res = n.get_parameterList(); }
3269
3270 //
3271 // declarations
3272 void handle(const SgFunctionDeclaration& n) { res = n.get_parameterList(); }
3273 void handle(const SgAdaGenericInstanceDecl& n) { res = find(&instantiatedDeclaration(n)); }
3274
3275 //
3276 // expressions
3277
3278 void handle(const SgPointerDerefExp& n) { res = find(n.get_type()); }
3279 void handle(const SgFunctionRefExp& n) { res = find(n.get_symbol()); }
3280 void handle(const SgAdaUnitRefExp& n) { res = find(n.get_decl()); }
3281
3282 void handle(const SgAdaRenamingRefExp& n)
3283 {
3284 // \todo give AdaRenamingRefExp a proper type
3285 // res = find(n.get_type());
3286
3287 res = find( SG_DEREF(n.get_decl()).get_type() );
3288 }
3289
3290 //
3291 // symbols
3292
3293 // trust Asis for directly linked functions -> no visibility check
3294 void handle(const SgFunctionSymbol& n)
3295 {
3296 res = find(n.get_declaration());
3297 }
3298
3299 void handle(const SgAdaInheritedFunctionSymbol& n)
3300 {
3301 SgFunctionDeclaration& fndcl = SG_DEREF(n.get_declaration());
3302
3303 if (isVisibleFrom(fndcl, sg::ancestor<const SgScopeStatement>(*call)))
3304 {
3305 res = find(&fndcl);
3306 return;
3307 }
3308
3309 res = find(n.get_publiclyVisibleFunctionSymbol());
3310 }
3311
3312 //
3313 // helpers
3314
3316 {
3317 return find(n, *call);
3318 }
3319
3320 static
3321 SgFunctionParameterList* find(SgNode* n, const SgFunctionCallExp& call);
3322
3323 private:
3324 const SgFunctionCallExp* call;
3325 };
3326
3328 AccessibleArgumentListFinder::find(SgNode* n, const SgFunctionCallExp& call)
3329 {
3330 return sg::dispatch(AccessibleArgumentListFinder{call}, n);
3331 }
3332
3334 getInitializerExpr(const SgInitializedName* var)
3335 {
3336 ASSERT_not_null(var);
3337
3338 SgExpression* res = var->get_initializer();
3339
3340 if (SgAssignInitializer* init = isSgAssignInitializer(res))
3341 res = init->get_operand();
3342
3343 return SG_DEREF(res);
3344 }
3345 }
3346
3349 const SgFunctionType& drvFunTy,
3350 const SgNamedType& dervTy
3351 )
3352 {
3353 // note: the function returns fnsym in many cases for which it was
3354 // not written.
3355
3356 //~ std::cerr << dervTy.get_name() << " " << &dervTy << std::endl;
3357
3358 const SgDeclarationStatement& dervDcl = SG_DEREF(dervTy.get_declaration());
3359 const SgDeclarationStatement& firstDervDcl = SG_DEREF(dervDcl.get_firstNondefiningDeclaration());
3360 if (isPrivate(firstDervDcl))
3361 return &fnsym; // nullptr
3362
3363 const SgDeclarationStatement* defnDervDcl = firstDervDcl.get_definingDeclaration();
3364
3365 if (defnDervDcl == nullptr || (!isPrivate(*defnDervDcl)))
3366 return &fnsym;
3367
3368 const SgClassDeclaration* firstClsDcl = isSgClassDeclaration(&firstDervDcl);
3369 if (firstClsDcl == nullptr)
3370 return &fnsym;
3371
3372 SgFunctionSymbol* res = &fnsym; // nullptr
3373 const SgClassType& clsty = SG_DEREF(firstClsDcl->get_type());
3374
3375 if (const SgClassType* basety = isSgClassType(baseTypeOfClass(clsty, true /* public ancestor preferred*/)))
3376 {
3377 res = findFunctionSymbolForType(*basety, dervTy, fnsym.get_name(), drvFunTy);
3378 }
3379
3380 return res ? res : &fnsym;
3381 }
3382
3383
3384
3385 SgExpressionPtrList
3386 normalizedCallArguments2(const SgFunctionCallExp& n, const SgFunctionParameterList& arglist, bool withDefaultArguments)
3387 {
3388 SgExpressionPtrList res;
3389 SgExpressionPtrList& orig = SG_DEREF(n.get_args()).get_expressions();
3390 const size_t posArgLimit = positionalArgumentLimit(orig);
3391 SgExpressionPtrList::iterator aaa = orig.begin();
3392 SgExpressionPtrList::iterator pos = aaa + posArgLimit;
3393 SgExpressionPtrList::iterator zzz = orig.end();
3394
3395 res.reserve(orig.size());
3396 std::copy(aaa, pos, std::back_inserter(res));
3397
3398 const SgInitializedNamePtrList& parmList = arglist.get_args();
3399
3400 ROSE_ASSERT(res.size() <= parmList.size());
3401 extend(res, parmList.size()); // make arglist as long as function parameter list
3402
3403 std::for_each( pos, zzz,
3404 [&parmList, &res](SgExpression* e) -> void
3405 {
3406 SgActualArgumentExpression& arg = SG_DEREF(isSgActualArgumentExpression(e));
3407 const std::size_t pos = namedArgumentPosition(parmList, arg.get_argument_name());
3408
3409 ASSERT_require(res[pos] == nullptr); // do not overwrite a valid arg
3410 res[pos] = arg.get_expression();
3411 }
3412 );
3413
3414 if (!withDefaultArguments)
3415 return res;
3416
3417 const auto resbeg = res.begin();
3418 const auto reslim = res.end();
3419 auto respos = std::find(resbeg, reslim, nullptr);
3420
3421 while (respos != reslim)
3422 {
3423 *respos = &getInitializerExpr(parmList.at(std::distance(resbeg, respos)));
3424
3425 respos = std::find(resbeg, reslim, nullptr);
3426 }
3427
3428 return res;
3429 }
3430
3431 SgExpressionPtrList
3432 normalizedCallArguments(const SgFunctionCallExp& n, bool withDefaultArguments)
3433 {
3434 SgFunctionParameterList* fnparms = AccessibleArgumentListFinder::find(n.get_function(), n);
3435 if (fnparms == nullptr)
3436 throw std::logic_error("unable to retrieve associated function parameter list");
3437
3438 return normalizedCallArguments2(n, *fnparms, withDefaultArguments);
3439 }
3440
3441 namespace
3442 {
3443 SgExpression const&
3444 unwrapActualArgumentExpression(const SgExpression& arg)
3445 {
3446 if (SgActualArgumentExpression const* namedarg = isSgActualArgumentExpression(&arg))
3447 return SG_DEREF(namedarg->get_expression());
3448
3449 return arg;
3450 }
3451 }
3452
3453 std::size_t
3455 {
3456 SgExpression const& actarg = unwrapActualArgumentExpression(arg);
3457 SgExpressionPtrList const normargs = si::Ada::normalizedCallArguments(call);
3458 SgExpressionPtrList::const_iterator const beg = normargs.begin();
3459 SgExpressionPtrList::const_iterator const lim = normargs.end();
3460 SgExpressionPtrList::const_iterator const pos = std::find(beg, lim, &actarg);
3461
3462 if (pos == lim) throw std::logic_error{"si::Ada::normalizedArgumentPosition: unable to find argument position"};
3463
3464 return std::distance(beg, pos);
3465 }
3466
3468 {
3469 const SgFunctionParameterList* fnparms = AccessibleArgumentListFinder::find(call.get_function(), call);
3470 if (fnparms == nullptr)
3471 throw std::logic_error("unable to retrieve associated function parameter list");
3472
3473 std::size_t const pos = normalizedArgumentPosition(call, arg);
3474 SgInitializedName const& parm = SG_DEREF(fnparms->get_args().at(pos));
3475 SgDeclarationStatement const& parmdcl = SG_DEREF(parm.get_declptr());
3476 SgTypeModifier const& tymod = parmdcl.get_declarationModifier().get_typeModifier();
3477
3478 return tymod.isIntent_out() || tymod.isIntent_inout();
3479 }
3480
3482 {
3483 return ( (call != nullptr)
3484 && (arg != nullptr)
3485 && isOutInoutArgument(*call, *arg)
3486 );
3487 }
3488
3489
3490 SgType& standardType(const std::string& name)
3491 {
3492 ASSERT_not_null(pkgStandardScope());
3493
3494 if (SgTypedefSymbol* tysy = pkgStandardScope()->lookup_typedef_symbol(name))
3495 {
3496 SgTypedefDeclaration& tydcl = SG_DEREF(tysy->get_declaration());
3497 return SG_DEREF(tydcl.get_type());
3498 }
3499
3500 SgEnumSymbol& ensy = SG_DEREF(pkgStandardScope()->lookup_enum_symbol(name));
3501 SgDeclarationStatement& nondef = SG_DEREF(ensy.get_declaration());
3502 SgEnumDeclaration& defdcl = SG_DEREF(isSgEnumDeclaration(nondef.get_definingDeclaration()));
3503
3504 //~ std::cerr << "e" << &endcl << " " << endcl.get_firstNondefiningDeclaration() << std::endl;
3505 return SG_DEREF(defdcl.get_type());
3506 }
3507
3508
3509 namespace
3510 {
3511 bool
3512 nodeProperty(const Sg_File_Info* n, bool (Sg_File_Info::*property)() const)
3513 {
3514 return n && (n->*property)();
3515 }
3516
3517 bool
3518 nodeProperty(const SgLocatedNode& n, bool (Sg_File_Info::*property)() const)
3519 {
3520 return ( nodeProperty(n.get_file_info(), property)
3521 || nodeProperty(n.get_startOfConstruct(), property)
3522 || nodeProperty(n.get_endOfConstruct(), property)
3523 );
3524 }
3525 }
3526
3527
3529 {
3530 if (nodeProperty(n, &Sg_File_Info::isCompilerGenerated))
3531 return false;
3532
3533 const SgNode* par = n.get_parent();
3534
3535 bool blockIsFrontendGenerated = ( isSgFunctionDefinition(par)
3536 || isSgTryStmt(par)
3537 || isSgIfStmt(par)
3538 || isSgSwitchStatement(par)
3539 || isSgForStatement(par)
3540 || isSgWhileStmt(par)
3541 || isSgAdaLoopStmt(par)
3542 || isSgAdaAcceptStmt(par)
3543 || isSgCatchOptionStmt(par)
3544 || isSgAdaGenericInstanceDecl(par)
3545 || isSgAdaFormalPackageDecl(par)
3546 || isSgAdaRepresentationClause(par)
3547 // \todo AdaSelectStmt, AdaGenericInstance, ..
3548 );
3549
3550 return !blockIsFrontendGenerated;
3551 }
3552
3554 {
3555 return n && blockExistsInSource(*n);
3556 }
3557
3559 {
3560 ScopePath res;
3561 const SgScopeStatement* curr = &n;
3562
3564 while (!isSgGlobal(curr))
3565 {
3566 // check for circular scopes
3567 // ASSERT_require(std::find(res.rbegin(), res.rend(), curr) == res.rend());
3568 res.push_back(curr);
3569 curr = logicalParentScope(*curr);
3570 }
3571
3572 return res;
3573 }
3574
3575 SgNodePtrList unparsedChildren(SgNode& n)
3576 {
3577 return sg::dispatch(UnparsedChildren{}, &n);
3578 }
3579
3580 void simpleTraversal(std::function<void(SgNode*)>&& fn, SgNode* root)
3581 {
3582 ASSERT_not_null(root);
3583
3584 SimpleTraversal tv(std::move(fn));
3585
3586 tv.traverse(root, preorder);
3587 }
3588
3589 void simpleTraversal(std::function<void(SgNode*)>&& fn, StatementRange roots)
3590 {
3591 SimpleTraversal tv(std::move(fn));
3592
3593 std::for_each( roots.first, roots.second,
3595 {
3596 tv.traverse(n, preorder);
3597 }
3598 );
3599 }
3600
3601 void conversionTraversal(std::function<void(SgNode*)>&& fn, SgNode* root)
3602 {
3603 simpleTraversal(std::move(fn), root);
3604 }
3605
3606 void conversionTraversal(std::function<void(SgNode*)>&& fn, StatementRange roots)
3607 {
3608 simpleTraversal(std::move(fn), std::move(roots));
3609 }
3610
3611 void convertAdaToCxxComments(SgNode* root, bool cxxLineComments)
3612 {
3613 simpleTraversal(CommentCxxifier{cxxLineComments}, root);
3614 }
3615
3617 {
3618 simpleTraversal(convertSymbolTablesToCaseSensitive_internal, root);
3619 }
3620
3621 void convertToOperatorRepresentation(SgNode* root, bool convertCallSyntax, bool convertNamedArguments)
3622 {
3623 simpleTraversal(FunctionCallToOperatorConverter{convertCallSyntax, convertNamedArguments}, root);
3624 }
3625
3626
3627 /*
3628 template<class T>
3629 T powInt(T num, size_t exp, size_t res = 1)
3630 {
3631 if (exp == 0)
3632 return res;
3633
3634 if ((exp % 2) == 0)
3635 return powInt(num*num, exp/2, res);
3636
3637 return powInt(num, exp-1, num*res);
3638 }
3639*/
3640
3641namespace
3642{
3643 bool
3644 isBasedDelimiter(char ch)
3645 {
3646 return ch == '#' || ch == ':';
3647 }
3648
3649 bool
3650 isExponentChar(char ch)
3651 {
3652 return ch == 'E' || ch == 'e';
3653 }
3654
3655 std::pair<int, bool>
3656 check(int s, int m)
3657 {
3658 return std::make_pair(s, s < m);
3659 }
3660
3661 std::pair<int, bool>
3662 char2Val(char c, int max)
3663 {
3664 using ResultType = std::pair<int, bool>;
3665
3666 if ((c >= '0') && (c <= '9'))
3667 return check(c - '0', max);
3668
3669 if ((c >= 'A') && (c <= 'F'))
3670 return check(c - 'A' + 10, max);
3671
3672 if ((c >= 'a') && (c <= 'f'))
3673 return check(c - 'a' + 10, max);
3674
3675 return ResultType{0, false};
3676 }
3677
3678 template <class T>
3679 std::pair<T, const char*>
3680 parseDec(const char* buf, int base = 10)
3681 {
3682 ROSE_ASSERT((*buf != '\0') && (base > 0));
3683
3684 // In constants folded by ASIS there can be a leading '-'
3685 // otherwise a '-' is represented as unary operator.
3686 const int negmul = (*buf == '-') ? -1 : 1;
3687
3688 if (negmul < 0) ++buf;
3689
3690 ROSE_ASSERT((*buf != '\0') && char2Val(*buf, base).second);
3691 T res = 0;
3692
3693 while (*buf != '\0')
3694 {
3695 const auto v = char2Val(*buf, base);
3696
3697 // \todo why is this exit needed?
3698 if (!v.second)
3699 return std::make_pair(res, buf);
3700
3701 // The digits cannot be summed all positive and negmul only applied once,
3702 // because this leads to an integer underflow for System.Min_Int.
3703 // While the underflow is likely benign (System.Min_Int == -System.Min_Int)
3704 // for a two's complement representation, it seems more prudent to avoid it
3705 // altogether.
3706 ROSE_ASSERT( (std::numeric_limits<T>::lowest() / base <= res)
3707 && (std::numeric_limits<T>::max() / base >= res)
3708 && ("arithmethic over-/underflow during literal parsing (mul)")
3709 );
3710 res = res*base;
3711
3712 ROSE_ASSERT( ((negmul < 0) && (std::numeric_limits<T>::lowest() + v.first <= res))
3713 || ((negmul > 0) && (std::numeric_limits<T>::max() - v.first >= res))
3714 || (!"arithmethic over-/underflow during literal parsing (add)")
3715 );
3716 res += (v.first * negmul);
3717
3718 ++buf;
3719
3720 // skip underscores
3721 // \note this is imprecise, since an underscore must be followed
3722 // by an integer.
3723 while (*buf == '_') ++buf;
3724 }
3725
3726 return std::make_pair(res, buf);
3727 }
3728
3729 template <class T>
3730 std::pair<T, const char*>
3731 parseFrac(const char* buf, size_t base = 10)
3732 {
3733 ROSE_ASSERT((*buf != '\0') && char2Val(*buf, base).second);
3734
3735 T res = 0;
3736 size_t divisor = 1*base;
3737
3738 while ((*buf != '\0') && (!isBasedDelimiter(*buf)))
3739 {
3740 const auto v = char2Val(*buf, base);
3741 ROSE_ASSERT(v.second);
3742
3743 T val = v.first;
3744
3745 if (val)
3746 {
3747 ROSE_ASSERT(!std::isnan(divisor));
3748
3749 T frac = val/divisor;
3750 ROSE_ASSERT(!std::isnan(frac));
3751
3752 res += frac;
3753 }
3754
3755 divisor = divisor*base;
3756
3757 ++buf;
3758
3759 // skip underscores
3760 // \note (this is imprecise, since an underscore must be followed
3761 // by an integer.
3762 while (*buf == '_') ++buf;
3763 }
3764
3765 return std::make_pair(res, buf);
3766 }
3767
3768
3769 std::pair<int, const char*>
3770 parseExp(const char* buf)
3771 {
3772 long int exp = 0;
3773
3774 if (isExponentChar(*buf))
3775 {
3776 ++buf;
3777 const bool positiveE = (*buf != '-');
3778
3779 // skip sign
3780 if (!positiveE || (*buf == '+')) ++buf;
3781
3782 std::tie(exp, buf) = parseDec<long int>(buf, 10);
3783
3784 if (!positiveE) exp = -exp;
3785 }
3786
3787 return std::make_pair(exp, buf);
3788 }
3789
3790 template <class T>
3791 T computeLiteral(T val, int base, int exp)
3792 {
3793 T res = val * std::pow(base, exp);
3794
3795 // std::cerr << "complit: " << res << std::endl;
3796 return res;
3797 }
3798
3799
3800 long long int
3801 basedLiteral(long long int res, const char* cur, int base)
3802 {
3803 int exp = 0;
3804
3805 ROSE_ASSERT(isBasedDelimiter(*cur));
3806
3807 ++cur;
3808 ROSE_ASSERT( (res >= std::numeric_limits<decltype(base)>::min())
3809 && (res <= std::numeric_limits<decltype(base)>::max())
3810 );
3811 base = res;
3812
3813 std::tie(res, cur) = parseDec<long long int>(cur, base);
3814
3815 if (isBasedDelimiter(*cur))
3816 {
3817 ++cur;
3818
3819 std::tie(exp, cur) = parseExp(cur);
3820 }
3821
3822 return computeLiteral(res, base, exp);
3823 }
3824
3825 bool isNamedArgument(const SgExpression* expr)
3826 {
3827 return isSgActualArgumentExpression(expr);
3828 }
3829} // anonymous
3830
3831
3832long long int convertIntegerLiteral(const char* img)
3833{
3834 long long int res = 0;
3835 int base = 10;
3836 int exp = 0;
3837 const char* cur = img;
3838
3839 std::tie(res, cur) = parseDec<long long int>(cur);
3840
3841 if (isBasedDelimiter(*cur))
3842 {
3843 return basedLiteral(res, cur, base);
3844 }
3845
3846 if (*cur == '.')
3847 {
3848 throw std::logic_error("SageInterfaceAda.C: Ada decimal literals not yet handled");
3849
3850 //~ long int decimal = 0;
3851
3852 //~ ++cur;
3853 //~ std::tie(decimal, cur) = parseDec<long int>(cur);
3854 }
3855
3856 std::tie(exp, cur) = parseExp(cur);
3857
3858 //~ logWarn() << "r: "
3859 //~ << res << ' ' << base << '^' << exp << '\n'
3860 //~ << std::endl;
3861
3862 return computeLiteral(res, base, exp);
3863}
3864
3865std::string convertStringLiteral(const char* textrep)
3866{
3867 ASSERT_not_null(textrep);
3868
3869 std::stringstream buf;
3870 const char delimiter = *textrep;
3871 ROSE_ASSERT(delimiter == '"' || delimiter == '%');
3872
3873 ++textrep;
3874 while (*(textrep+1))
3875 {
3876 // a delimiter within a text requires special handling
3877 // -> skip the first occurrence if the delimiter is doubled
3878 if (*textrep == delimiter)
3879 {
3880 ++textrep;
3881 ROSE_ASSERT(*textrep == delimiter);
3882 }
3883
3884 buf << *textrep;
3885 ++textrep;
3886 }
3887
3888 return std::move(buf).str();
3889}
3890
3891
3892long double convertRealLiteral(const char* img)
3893{
3894 std::string litText{img};
3895
3896 boost::replace_all(litText, "_", "");
3897
3898 // handle 'normal' real literals
3899 if (litText.find_first_of("#:") == std::string::npos)
3900 {
3901 // logWarn() << "R: " << conv<long double>(litText) << std::endl;
3902 return boost::lexical_cast<long double>(litText);
3903 }
3904
3905 // handle based real literals
3906 long double dec = 0;
3907 long double frac = 0;
3908 int base = 10;
3909 int exp = 0;
3910 const char* cur = img;
3911
3912 std::tie(base, cur) = parseDec<long int>(cur);
3913 ASSERT_require(isBasedDelimiter(*cur));
3914
3915 ++cur;
3916 std::tie(dec, cur) = parseDec<long double>(cur, base);
3917
3918 if (*cur == '.')
3919 {
3920 ++cur;
3921 std::tie(frac, cur) = parseFrac<long double>(cur, base);
3922 }
3923
3924 const long double res = dec + frac;
3925
3926 ASSERT_require(isBasedDelimiter(*cur));
3927 ++cur;
3928
3929 std::tie(exp, cur) = parseExp(cur);
3930
3931/*
3932 logWarn() << "r: "
3933 << res << ' ' << dec << '+' << frac << ' ' << base << ' ' << exp << '\n'
3934 << res * base
3935 << std::endl;
3936*/
3937 return computeLiteral(res, base, exp);
3938}
3939
3940char convertCharLiteral(const char* img)
3941{
3942 // recognized form: 'l' -> l
3943 ASSERT_not_null(img);
3944
3945 const char delimiter = *img;
3946 ROSE_ASSERT(delimiter == '\'');
3947
3948 const char res = img[1];
3949 // \todo could we have a null character in quotes?
3950 ROSE_ASSERT(res && img[2] == '\'');
3951 return res;
3952}
3953
3954namespace
3955{
3957 primitiveInScope(const SgType* ty, const SgScopeStatement* scope)
3958 {
3959 // PP: note to self: BaseTypeDecl::find does NOT skip the initial typedef decl
3960 const SgDeclarationStatement* tydcl = associatedDeclaration_internal(ty, 1);
3961
3962 // currently the primitive test only tests if the two scopes match
3963 // the test whether the function is declared in a package scope is missing,
3964 // b/c if the function is implicitly or explicitly overriding, the
3965 // test would need to be performed on the first function declaration
3966 // in the hierarchy.
3967 if (tydcl && (tydcl->get_scope() == scope))
3968 return tydcl;
3969
3970 return nullptr;
3971 }
3972}
3973
3974
3975std::vector<PrimitiveParameterDesc>
3977{
3978 std::vector<PrimitiveParameterDesc> res;
3979 size_t parmpos = 0;
3980 const SgScopeStatement* scope = dcl.get_scope();
3981
3982 for (const SgInitializedName* parm : SG_DEREF(dcl.get_parameterList()).get_args())
3983 {
3984 ASSERT_not_null(parm);
3985
3986 if (const SgDeclarationStatement* tydcl = primitiveInScope(parm->get_type(), scope))
3987 res.emplace_back(parmpos, parm, tydcl);
3988
3989 ++parmpos;
3990 }
3991
3992 return res;
3993}
3994
3995std::vector<PrimitiveParameterDesc>
3997{
3998 ASSERT_not_null(dcl);
3999
4000 return primitiveParameterPositions(*dcl);
4001}
4002
4003PrimitiveSignatureElementsDesc
4005{
4006 const SgFunctionType* fnty = dcl.get_type();
4007 ASSERT_not_null(fnty);
4008
4009 return { primitiveInScope(fnty->get_return_type(), dcl.get_scope())
4011 };
4012}
4013
4014PrimitiveSignatureElementsDesc
4016{
4017 ASSERT_not_null(dcl);
4018
4019 return primitiveSignatureElements(*dcl);
4020}
4021
4022
4023
4024size_t
4025positionalArgumentLimit(const SgExpressionPtrList& arglst)
4026{
4027 SgExpressionPtrList::const_iterator aaa = arglst.begin();
4028 SgExpressionPtrList::const_iterator pos = std::find_if(aaa, arglst.end(), isNamedArgument);
4029
4030 return std::distance(aaa, pos);
4031}
4032
4033size_t
4035{
4036 return positionalArgumentLimit(args.get_expressions());
4037}
4038
4039size_t
4041{
4042 ASSERT_not_null(args);
4043
4044 return positionalArgumentLimit(*args);
4045}
4046
4047
4049overridingScope(const SgExprListExp& args, const std::vector<PrimitiveParameterDesc>& primitiveArgs)
4050{
4051 using PrimitiveParmIterator = std::vector<PrimitiveParameterDesc>::const_iterator;
4052 using ArgumentIterator = SgExpressionPtrList::const_iterator;
4053
4054 if (primitiveArgs.size() == 0)
4055 return nullptr;
4056
4057 const SgExpressionPtrList& arglst = args.get_expressions();
4058 const size_t posArgLimit = positionalArgumentLimit(args);
4059 PrimitiveParmIterator aa = primitiveArgs.begin();
4060 PrimitiveParmIterator zz = primitiveArgs.end();
4061
4062 // check all positional arguments
4063 while ((aa != zz) && (aa->pos() < posArgLimit))
4064 {
4065 const SgExpression* arg = arglst.at(aa->pos());
4066
4067 if (const SgDeclarationStatement* tydcl = associatedDeclaration(arg->get_type()))
4068 return tydcl->get_scope();
4069
4070 ++aa;
4071 }
4072
4073 ROSE_ASSERT(posArgLimit <= arglst.size());
4074 ArgumentIterator firstNamed = arglst.begin() + posArgLimit;
4075 ArgumentIterator argLimit = arglst.end();
4076
4077 // check all named arguments
4078 while (aa != zz)
4079 {
4080 const std::string parmName = SG_DEREF(aa->name()).get_name();
4081 auto sameNamePred = [&parmName](const SgExpression* arg) -> bool
4082 {
4083 const SgActualArgumentExpression* actarg = isSgActualArgumentExpression(arg);
4084
4085 ASSERT_not_null(actarg);
4086 return parmName == std::string{actarg->get_argument_name()};
4087 };
4088 ArgumentIterator argpos = std::find_if(firstNamed, argLimit, sameNamePred);
4089
4090 ++aa;
4091
4092 if (argpos == argLimit)
4093 continue;
4094
4095 if (const SgDeclarationStatement* tydcl = associatedDeclaration((*argpos)->get_type()))
4096 return tydcl->get_scope();
4097 }
4098
4099 // not found
4100 return nullptr;
4101}
4102
4103
4105overridingScope(const SgExprListExp* args, const std::vector<PrimitiveParameterDesc>& primitiveArgs)
4106{
4107 ASSERT_not_null(args);
4108
4109 return overridingScope(*args, primitiveArgs);
4110}
4111
4112namespace
4113{
4114 struct BaseTypeFinder : sg::DispatchHandler<SgType*>
4115 {
4116 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
4117
4118 // \todo not sure if this should be reachable..
4119 // void handle(const SgType& n) { }
4120
4121 // base cases
4122/*
4123 void handle(const SgAdaDerivedType& n) { res = { &n }; }
4124 void handle(const SgLongLongType& n) { res = { &n }; }
4125 void handle(const SgLongDoubleType& n) { res = { &n }; }
4126 void handle(const SgFixedType& n) { res = { &n }; }
4127 void handle(const SgAdaAccessType& n) { res = { &n }; }
4128 void handle(const SgArrayType& n) { res = { &n }; }
4129
4130 // reachable?
4131 void handle(const SgPointerType& n) { res = { &n }; }
4132*/
4133
4134 // non-base cases
4135 void handle(const SgTypedefType& n)
4136 {
4137 res = &base_type(n);
4138 }
4139
4140 void handle(const SgAdaFormalType& n)
4141 {
4142 res = n.get_formal_type();
4143 }
4144
4145 void handle(const SgAdaDiscriminatedType& n)
4146 {
4147 const SgAdaDiscriminatedTypeDecl& dcl = SG_DEREF(isSgAdaDiscriminatedTypeDecl(n.get_declaration()));
4148 const SgDeclarationStatement& subdcl = SG_DEREF(dcl.get_discriminatedDecl());
4149
4150 res = baseType(si::getDeclaredType(&subdcl));
4151 }
4152
4153 void handle(const SgClassType& n)
4154 {
4155 res = baseTypeOfClass(n);
4156 }
4157
4158 void handle(const SgEnumType& n)
4159 {
4160 // \todo baseEnumDeclaration may skips some intermediate types...
4161 if (SgEnumDeclaration* enmdcl = baseEnumDeclaration(const_cast<SgEnumType&>(n)))
4162 {
4163 SgEnumDeclaration* defdecl = isSgEnumDeclaration(enmdcl->get_definingDeclaration());
4164
4165 if (defdecl == nullptr) defdecl = enmdcl;
4166
4167 res = defdecl->get_adaParentType();
4168 }
4169 }
4170
4171 // \todo should this handle SgAdaSubtype also? void handle(const SgAdaSubtype& n) ..
4172 };
4173}
4174
4175SgType*
4177{
4178 return baseType(&ty);
4179}
4180
4181SgType*
4183{
4184 //~ std::cerr << (ty ? typeid(*ty).name() : std::string{"<0>"}) << std::endl;
4185 return sg::dispatch(BaseTypeFinder{}, ty);
4186}
4187
4190{
4191 return baseEnumDeclaration(&ty);
4192}
4193
4196{
4197 SgDeclarationStatement* basedcl = associatedDeclaration_internal(ty, 0);
4198
4199 if (SgTypedefDeclaration* tydcl = isSgTypedefDeclaration(basedcl))
4200 return baseEnumDeclaration(tydcl->get_base_type());
4201
4202 return isSgEnumDeclaration(basedcl);
4203}
4204
4205
4208{
4209 return characterBaseType(&ty);
4210}
4211
4214{
4215 auto baseEnumDecl =
4216 [](SgEnumType* ty) -> SgEnumType*
4217 {
4218 if (SgType* baseTy = baseType(ty))
4219 if (SgEnumDeclaration* enumdcl = isSgEnumDeclaration(BaseTypeDecl::find(baseTy)))
4220 return enumdcl->get_type();
4221
4222 return nullptr;
4223 };
4224
4225 while (SgEnumType* curr = baseEnumDecl(last))
4226 {
4227 last = curr;
4228 }
4229
4230 SgEnumDeclaration* enumdcl = isSgEnumDeclaration(BaseTypeDecl::find(last));
4231 if (enumdcl == nullptr) return nullptr;
4232
4233 const bool isCharType = ( (enumdcl->get_scope() == pkgStandardScope())
4234 && (boost::algorithm::ends_with(enumdcl->get_name().getString(), "Character"))
4235 );
4236
4237 return isCharType ? enumdcl->get_type() : nullptr;
4238}
4239
4240
4241bool
4243{
4244 const SgBasicBlock& body = SG_DEREF(fndef.get_body());
4245
4246 return body.get_statements().empty();
4247}
4248
4249bool
4251{
4252 return recdef.get_members().empty();
4253}
4254
4255bool
4257{
4258 return isSgMinusMinusOp(n.get_increment());
4259}
4260
4261bool
4263{
4264 return n && isReverseForLoop(*n);
4265}
4266
4267bool
4269{
4270 return isReverseForLoop(isSgForStatement(n.get_parent()));
4271}
4272
4273bool
4275{
4276 return n && isReverseForLoop(*n);
4277}
4278
4279
4280
4281boost::optional<bool>
4283{
4284 if (const SgEnumVal* enumval = isSgEnumVal(e))
4285 if (isBooleanType(enumval->get_type()))
4286 return stringeq(enumval->get_name().getString(), "True"); // spelling in AdaType.C
4287
4288 return boost::none; // std::nullopt;
4289}
4290
4291boost::optional<bool>
4293{
4294 return booleanConstant(&e);
4295}
4296
4297
4298namespace
4299{
4300 // In contrast to si::getEnclosingScope, which seems to return the actual parent scope
4301 // in the AST, this returns the logical parent.
4302 // e.g., a separate function has the package as logical parent, but
4303 // the global scope as the actual parent scope.
4304 struct LogicalParent : sg::DispatchHandler<SgScopeStatement*>
4305 {
4306 void handle(const SgNode& n) { SG_UNEXPECTED_NODE(n); }
4307
4308 void handle(const SgAdaPackageSpecDecl& n) { res = n.get_scope(); }
4309 void handle(const SgAdaTaskSpecDecl& n) { res = n.get_scope(); }
4310 void handle(const SgAdaTaskTypeDecl& n) { res = n.get_scope(); }
4311 void handle(const SgAdaProtectedSpecDecl& n) { res = n.get_scope(); }
4312 void handle(const SgAdaProtectedTypeDecl& n) { res = n.get_scope(); }
4313 void handle(const SgFunctionDeclaration& n) { res = n.get_scope(); }
4314 void handle(const SgAdaGenericDecl& n) { res = n.get_scope(); }
4315 void handle(const SgClassDeclaration& n) { res = n.get_scope(); }
4316
4317 // do not look beyond global
4318 // (during AST construction the parents of global may not yet be properly linked).
4319 void handle(const SgGlobal&) { res = nullptr; }
4320
4321 // For Ada features that have a spec/body combination
4322 // we define the logical parent to be the spec.
4323 // This way, both scopes are on the path for identifying overloaded symbols.
4324 void handle(const SgAdaPackageBody& n) { res = getSpecFromBody<SgAdaPackageBodyDecl>(n); }
4325 void handle(const SgAdaTaskBody& n) { res = n.get_spec(); }
4326 void handle(const SgAdaProtectedBody& n) { res = n.get_spec(); }
4327
4328 void handle(const SgAdaPackageSpec& n) { res = fromParent(n); }
4329 void handle(const SgAdaTaskSpec& n) { res = fromParent(n); }
4330 void handle(const SgAdaProtectedSpec& n) { res = fromParent(n); }
4331 void handle(const SgFunctionDefinition& n) { res = fromParent(n); }
4332 void handle(const SgAdaGenericDefn& n) { res = fromParent(n); }
4333 void handle(const SgClassDefinition& n) { res = fromParent(n); }
4334
4335 void handle(const SgScopeStatement& n)
4336 {
4337 const SgNode* node = &n;
4338
4339 res = si::getEnclosingScope(const_cast<SgNode*>(node));
4340 }
4341
4342 static
4344 fromParent(const SgNode& n);
4345 };
4346
4348 LogicalParent::fromParent(const SgNode& n)
4349 {
4350 return sg::dispatch(LogicalParent{}, n.get_parent());
4351 }
4352
4353
4354 struct DeclFromSymbol : sg::DispatchHandler<SgDeclarationStatement*>
4355 {
4356 // for any valid return
4357 ReturnType filterReturnType(ReturnType v) { return v; }
4358
4359 // for non-declaration statements (e.g., InitializedName) and other unhandled symbols
4360 ReturnType filterReturnType(const SgNode*) { return nullptr; }
4361
4362 // all non-symbols
4363 auto handlesyms(const SgNode& n, const SgNode&) -> const SgNode* { SG_UNEXPECTED_NODE(n); }
4364
4365 // calls get_declaration on the most derived SgSymbol type
4366 // \note the second parameter is a tag to guarantee the type requirement.
4367 template <class SageSymbol>
4368 auto handlesyms(const SageSymbol& n, const SgSymbol&) -> decltype(n.get_declaration())
4369 {
4370 return n.get_declaration();
4371 }
4372
4373 //
4374 // special cases
4375 auto handlesyms(const SgSymbol& n, const SgSymbol&) -> const SgNode*
4376 {
4377 std::stringstream out;
4378
4379 out << "unhandled symbol kind: " << typeid(n).name() << std::endl;
4380 throw std::runtime_error{out.str()};
4381
4382 // return will be filtered out
4383 return &n;
4384 }
4385
4386 template <class SageNode>
4387 void handle(const SageNode& n)
4388 {
4389 res = filterReturnType(handlesyms(n, n));
4390 }
4391 };
4392
4393 template <class SageNode>
4394 Sg_File_Info& ensureFileInfo( SageNode& n,
4395 void (SageNode::*setter)(Sg_File_Info*),
4396 Sg_File_Info* (SageNode::*getter)() const
4397 )
4398 {
4399 Sg_File_Info* info = (n.*getter)();
4400
4401 if (info == nullptr)
4402 {
4404 ASSERT_not_null(info);
4405
4406 (n.*setter)(info);
4407 }
4408
4409 return SG_DEREF(info);
4410 }
4411
4412 template <class SageNode>
4413 void setFileInfo( SageNode& n,
4414 void (SageNode::*setter)(Sg_File_Info*),
4415 Sg_File_Info* (SageNode::*getter)() const,
4416 const Sg_File_Info& orig
4417 )
4418 {
4419 ensureFileInfo(n, setter, getter) = orig;
4420
4421 //~ info.set_parent(&n);
4422 //~ info.unsetCompilerGenerated();
4423 //~ info.unsetTransformation();
4424 //~ info.unsetShared();
4425 //~ info.set_physical_filename(filename);
4426 //~ info.set_filenameString(filename);
4427 //~ info.set_line(line);
4428 //~ info.set_physical_line(line);
4429 //~ info.set_col(col);
4430
4431 //~ info.setOutputInCodeGeneration();
4432 }
4433
4434 template <class SageLocatedNode>
4435 void cpyFileInfo( SageLocatedNode& n,
4436 void (SageLocatedNode::*setter)(Sg_File_Info*),
4437 Sg_File_Info* (SageLocatedNode::*getter)() const,
4438 const SageLocatedNode& src
4439 )
4440 {
4441 const Sg_File_Info* infox = (src.*getter)();
4442
4443 if (infox == nullptr)
4444 throw std::runtime_error("copied file location from node where Sg_File_Info == nullptr");
4445
4446 const Sg_File_Info& info = *infox;
4447
4448 setFileInfo(n, setter, getter, info);
4449 }
4450}
4451
4454{
4455 return sg::dispatch(LogicalParent{}, &curr);
4456}
4457
4460{
4461 return curr ? logicalParentScope(*curr) : nullptr;
4462}
4463
4464std::tuple<const SgScopeStatement*, const SgSymbol*>
4465findSymbolInContext(std::string id, const SgScopeStatement& scope, const SgScopeStatement* limit)
4466{
4467 constexpr SgTemplateParameterPtrList* templParams = nullptr;
4468 constexpr SgTemplateArgumentPtrList* templArgs = nullptr;
4469
4470 const SgScopeStatement* curr = &scope;
4471 const SgSymbol* sym = nullptr;
4472
4473 while ((curr != nullptr) && (curr != limit))
4474 {
4475 sym = curr->lookup_symbol(id, templParams, templArgs);
4476 if (sym) break;
4477
4478 curr = logicalParentScope(*curr);
4479 }
4480
4481 return {curr, sym};
4482}
4483
4485{
4486 return sg::dispatch(DeclFromSymbol{}, &n);
4487}
4488
4489bool isAttribute(const SgAdaAttributeExp& attr, const std::string& attrname)
4490{
4491 return stringeq(attr.get_attribute().getString(), attrname);
4492}
4493
4495{
4496 return ( isAttribute(attr, "access")
4497 || isAttribute(attr, "unchecked_access")
4498 || isAttribute(attr, "unrestricted_access")
4499 );
4500}
4501
4502
4504isPragma(const SgPragmaDeclaration& prgdcl, const std::string& prgname)
4505{
4506 SgPragma* pragma = prgdcl.get_pragma();
4507 if ((pragma == nullptr) || !stringeq(pragma->get_pragma(), prgname))
4508 return nullptr;
4509
4510 SgExprListExp* res = pragma->get_args();
4511 ASSERT_not_null(res);
4512 return res;
4513}
4514
4516{
4517 cpyFileInfo( tgt,
4519 src
4520 );
4521
4522 cpyFileInfo( tgt,
4524 src
4525 );
4526
4527 if (SgExpression* tgtexp = isSgExpression(&tgt))
4528 {
4529 if (const SgExpression* srcexp = isSgExpression(&src))
4530 {
4531 cpyFileInfo( *tgtexp,
4532 &SgExpression::set_operatorPosition, &SgExpression::get_operatorPosition,
4533 *srcexp
4534 );
4535 }
4536 else
4537 {
4538 throw std::runtime_error{"cannot assign set_operatorPosition from non-SgExpression."};
4539 }
4540 }
4541}
4542
4544{
4545 auto locSetter =
4546 [](SgNode* sgn) -> void
4547 {
4548 if (SgLocatedNode* l = isSgLocatedNode(sgn))
4549 l->setCompilerGenerated();
4550 };
4551
4552 simpleTraversal(locSetter, &n);
4553}
4554
4559
4560} // ada
4561} // SageInterface
4562
4563namespace sg
4564{
4565 [[noreturn]]
4566 void report_error(std::string desc, const char* file, size_t ln)
4567 {
4568 static const char* AT = " at ";
4569 static const char* SEP = " : ";
4570
4571 if (file)
4572 {
4573 const std::string filename(file);
4574 const std::string num(conv<std::string>(ln));
4575
4576 desc.reserve(desc.size() + num.size() + filename.size() + std::strlen(AT) + std::strlen(SEP)+1);
4577
4578 desc.append(AT);
4579 desc.append(filename);
4580 desc.append(SEP);
4581 desc.append(num);
4582 }
4583
4584 {
4585 using namespace Rose::Diagnostics;
4586
4587 //~ mlog[FATAL] << "[abort] " << desc << std::endl;
4588 //~ ROSE_ABORT();
4589
4590 mlog[FATAL] << "[throw] " << desc << std::endl;
4591 mlog[INFO] << "gdb: b sageInterfaceAda.C:" << __LINE__ << std::endl;
4592 throw std::runtime_error(desc);
4593
4594 //~ std::cerr << "[exit] [FATAL] " << desc << std::endl;
4595 //~ std::exit(1);
4596 }
4597 }
4598
4599 [[noreturn]]
4600 void unexpected_node(const SgNode& n, const char* file, size_t ln)
4601 {
4602 static const std::string msg = "assertion failed: unexpected node-type: ";
4603
4604 report_error(msg + typeid(n).name(), file, ln);
4605 }
4606}
Class for traversing the AST.
void traverse(SgNode *node, Order treeTraversalOrder)
traverse the entire AST. Order defines preorder (preorder) or postorder (postorder) traversal....
For preprocessing information including source comments, include , if, define, etc.
SgType * get_type() const override
unparsing support for pragmas
SgScopeStatement * get_scope() const override
Returns scope of current statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the rhs of a variable declaration which includes an optional assignment (e....
This class represents the concept of a block (not a basic block from control flow analysis).
const SgStatementPtrList & get_statements() const
Returns a const STL list by reference.
SgExpression * get_lhs_operand() const
returns SgExpression pointer to the lhs operand associated with this binary operator.
SgExpression * get_rhs_operand() const
returns SgExpression pointer to the rhs operand associated with this binary operator.
This class represents a cast of one type to another.
This class represents the concept of a class declaration statement. It includes the concept of an ins...
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a class definition in C++.
const SgBaseClassPtrList & get_inheritances() const
Returns a const list to the base classes.
const SgDeclarationStatementPtrList & get_members() const
Returns a const list to the data member declarations.
This class represents the concept of a C trinary conditional expression (e.g. "test ?...
SgExpression * get_true_exp() const
Access function for p_true_exp.
SgExpression * get_conditional_exp() const
Access function for p_conditional_exp.
SgExpression * get_false_exp() const
Access function for p_false_exp.
This class represents the concept of a declaration statement.
SgDeclarationStatement * get_definingDeclaration() const
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
SgDeclarationStatement * get_firstNondefiningDeclaration() const
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
This class represents the concept of an enum declaration.
SgScopeStatement * get_scope() const override
Access function for p_scope.
SgName get_name() const
Access function for p_name.
const SgInitializedNamePtrList & get_enumerators() const
Access function for p_enumerators.
SgEnumType * get_type() const
Access function for p_type.
This class represents the concept of a C and C++ expression list.
This class represents the concept of a C or C++ statement which contains a expression.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...
void set_need_paren(bool need_paren)
This function allows the p_need_paren flag to be set (used internally).
virtual SgType * get_type() const
unparsing support for pragmas
virtual std::vector< SgNode * > get_traversalSuccessorContainer() override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
bool get_need_paren() const
returns bool value if front-end considers parenthesis to be required.
std::string getFileName() const
associated filename
This class represents the variable declaration or variable initialization withn a for loop.
This class represents the concept of a for loop.
This class represents the concept of a C++ function call (which is an expression).
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
This class represents the concept of a function declaration statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
SgBasicBlock * get_body() const
Access function for p_body.
This class represents the concept of a declaration list.
const SgInitializedNamePtrList & get_args() const
Access function for p_args.
This class represents the function being called and must be assembled in the SgFunctionCall with the ...
SgName get_name() const override
Access function for getting name from declarations or types internally.
SgType * get_type() const override
This function returns the type associated with the named entity.
This class represents a type for all functions.
This class represents the concept of a namespace definition.
const SgDeclarationStatementPtrList & get_declarations() const
Returns a const list to the global scope declarations.
This class represents the concept of an "if" construct.
SgStatement * get_conditional() const
Access function for p_conditional.
SgStatement * get_true_body() const
Access function for p_true_body.
SgStatement * get_false_body() const
Access function for p_false_body.
This class represents the notion of a declared variable.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
This class represents the notion of an expression or statement which has a position within the source...
Sg_File_Info * get_endOfConstruct() const override
New function interface for Sg_File_Info data stores ending location of contruct (typically the closin...
void set_endOfConstruct(Sg_File_Info *endOfConstruct)
This function sets the current source location position of the end of the current construct.
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
void set_startOfConstruct(Sg_File_Info *startOfConstruct)
This function sets the current source location position of the start of the current construct.
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
AttachedPreprocessingInfoType *& getAttachedPreprocessingInfo(void)
Computes the number of nodes in the defined subtree of the AST.
This class represents strings within the IR nodes.
virtual SgName get_name() const
Gets name of the type (useful for debugging, unparsing, etc.)
This class represents the concept of a C++ call to the new operator.
SgType * get_type() const override
unparsing support for pragmas
This class represents the base class for all IR nodes within Sage III.
SgNode * get_parent() const
Access function for parent node.
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
SgType * get_type() const override
unparsing support for pragmas
This class represents the concept of a C Assembler statement (untested).
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
SgSymbol * next_any_symbol() const
Only use after lookup_XXX_symbol(const SgName&) or after first_XXX_symbol() These functions use the s...
SgSymbolTable * get_symbol_table() const
Returns a pointer to the locally strored SgSymbolTable.
SgDeclarationStatementPtrList & getDeclarationList()
Gets reference to internal STL list of pointers to SgDeclarationStatement objects (only defined for s...
bool containsOnlyDeclarations() const
This function is used to indicate if either the getDeclarationList() or getStatementList() can be cal...
This class represents the notion of a statement.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
virtual SgScopeStatement * get_scope(void) const
Returns scope of current statement.
This class represents the symbol tables used in both SgScopeStatement and the SgFunctionTypeSymbolTab...
bool isCaseInsensitive() const
Query of scope symbol table behavior (is symbol table behavior case sensitive (C/C++) or case insensi...
This class represents the concept of a name within the compiler.
virtual SgType * get_type() const =0
This function returns the type associated with the named entity.
This class represents the concept of try statement within the try-catch support for exception handlin...
This class represents a default type used for some IR nodes (see below).
SgType * get_type() const override
unparsing support for pragmas
This class represents a string type used for SgStringVal IR node.
This class represents the base class for all types.
SgType * stripType(unsigned char bit_array=STRIP_MODIFIER_TYPE|STRIP_REFERENCE_TYPE|STRIP_RVALUE_REFERENCE_TYPE|STRIP_POINTER_TYPE|STRIP_ARRAY_TYPE|STRIP_TYPEDEF_TYPE|STRIP_POINTER_MEMBER_TYPE) const
Returns hidden type beneath layers of typedefs, pointers, references, modifiers, array representation...
This class represents the notion of a typedef declaration.
SgName get_name() const override
Support for some classes which have pure virtual function in base classes.
SgExpression * get_operand() const
returns SgExpression pointer to the operand associated with this unary operator.
This class represents the variable refernece in expressions.
SgType * get_type() const override
Get the type associated with this expression.
This class represents the concept of a C or C++ variable declaration.
const SgInitializedNamePtrList & get_variables() const
Access function for p_variables.
This class represents the concept of a variable name within the compiler (a shared container for the ...
This class represents the location of the code associated with the IR node in the original source cod...
bool isCompilerGenerated() const
Returns true only if compiler generated (either by the front-end or by ROSE).
static Sg_File_Info * generateDefaultFileInfoForTransformationNode()
Static function to return new Sg_File_Info object set to default values appropriate for transformatio...
Hash table support for symbol tables within ROSE.
__when_T< checker_t > checker
Used by the -rose:ast:checker:XXX options.
Controls diagnostic messages from ROSE.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C:58
Functions that build an AST.
Definition sageBuilder.h:32
ROSE_DLL_API SgAddOp * buildAddOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgEqualityOp * buildEqualityOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgConcatenationOp * buildConcatenationOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgMultiplyOp * buildMultiplyOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgGreaterThanOp * buildGreaterThanOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgBitAndOp * buildBitAndOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgLessOrEqualOp * buildLessOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgSubtractOp * buildSubtractOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgBitOrOp * buildBitOrOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgArrayType * buildArrayType(SgType *base_type=nullptr, SgExpression *index=nullptr)
Build ArrayType.
ROSE_DLL_API SgTypeFixed * buildFixedType(SgExpression *fraction, SgExpression *scale)
Build a Jovial fixed type with a fraction specifier and a scale specifier.
ROSE_DLL_API SgTypeLongLong * buildLongLongType()
Built in simple types.
ROSE_DLL_API SgRemOp * buildRemOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgUnaryAddOp * buildUnaryAddOp(SgExpression *op=NULL)
ROSE_DLL_API SgNullExpression * buildNullExpression()
Build a null expression, set file info as the default one.
ROSE_DLL_API SgBitXorOp * buildBitXorOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgGreaterOrEqualOp * buildGreaterOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTypeLongDouble * buildLongDoubleType()
Built in simple types.
ROSE_DLL_API SgNotOp * buildNotOp(SgExpression *op=NULL)
ROSE_DLL_API SgNotEqualOp * buildNotEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTypeChar * buildCharType()
Built in simple types.
ROSE_DLL_API SgLessThanOp * buildLessThanOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgDivideOp * buildDivideOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTypeNullptr * buildNullptrType()
Built in simple types.
ROSE_DLL_API SgExponentiationOp * buildExponentiationOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgAbsOp * buildAbsOp(SgExpression *op=NULL)
ROSE_DLL_API SgModOp * buildModOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
bool tryFollowsDeclarativeBlock(const SgTryStmt &n)
returns true iff n is a try block following a declarative region
std::string convertRoseOperatorNameToAdaOperator(const std::string &nameInRose)
takes a function name as used in ROSE and converts it to an operator in Ada (i.e.,...
void conversionTraversal(std::function< void(SgNode *)> &&fn, SgNode *root)
bool systemPackage(const SgScopeStatement &n)
returns true if the scope n is part of a system package
bool isFixedType(const SgType *ty)
returns if the type ty is a fixed point type
SgAdaPackageBody & getBodyDefinition(const SgAdaPackageSpec &spec)
returns the body definition (scope) of the package specification
bool isBooleanType(const SgType *ty)
return if the type ty is the corresponding universal type representation in ROSE
SgScopeStatement * overridingScope(const SgExprListExp &args, const std::vector< PrimitiveParameterDesc > &primitiveArgs)
returns the overriding scope of a primitive function based on the associated arguments as defined by ...
PrimitiveSignatureElementsDesc primitiveSignatureElements(const SgFunctionDeclaration &)
returns the descriptions for result type and parameters that make an operation primitive.
FlatArrayType getArrayTypeInfo(SgType *atype)
returns a flattened representation of Ada array types.
SgInitializedName & declOf(const SgEnumVal &)
returns the declaration of the enum value
SgFunctionSymbol * findPubliclyVisibleFunction(SgFunctionSymbol &fnsym, const SgFunctionType &drvFunTy, const SgNamedType &dervTy)
finds the function symbol for a publicly accessible function.
bool denotesRange(const SgExpression &e)
returns true if the expression e denotes a range
bool resolvesToFixedType(const SgType *ty)
returns if the type ty resolves to a fixed point type
StatementRange declsInPackage(SgGlobal &globalScope, const std::string &mainFile)
returns all statements/declarations in the global scope that were defined in the source file.
SgExpressionPtrList normalizedCallArguments2(const SgFunctionCallExp &n, const SgFunctionParameterList &arglist, bool withDefaultArguments=false)
returns a list of arguments with named arguments placed at the correct position by taking into accoun...
std::string convertStringLiteral(const char *img)
converts text to constant values
std::vector< IfExpressionInfo > flattenIfExpressions(const SgConditionalExp &n)
returns a flat representation of if expressions
void convertToCaseSensitiveSymbolTables(SgNode *root)
converts all symbol tables from case insensitive to case sensitive
SgAdaDiscriminatedTypeDecl * getAdaDiscriminatedTypeDecl(const SgDeclarationStatement &n)
returns the SgAdaDiscriminatedTypeDecl iff n is discriminated null otherwise
void copyFileInfo(SgLocatedNode &tgt, const SgLocatedNode &src)
copies the source code location from src to tgt.
bool isObjectRenaming(const SgAdaRenamingDecl *dcl)
returns true iff ty refers to an object renaming
void setSourcePositionInSubtreeToCompilerGenerated(SgLocatedNode *n)
sets source position in entire subtree of n to compiler generated
AggregateInfo splitAggregate(const SgExprListExp &exp)
returns the ancestor initializer, if exp refers to an extension aggregate null otherwise
bool isFloatingPointType(const SgType &ty)
return if the type ty is the corresponding universal type representation in ROSE
const SgFunctionType * functionType(const SgFunctionSymbol *fnsy)
returns the static type of the function symbol fnsy
void simpleTraversal(std::function< void(SgNode *)> &&fn, SgNode *root)
Traverses all AST nodes in an unspecified order.
bool isAnyAccessAttribute(const SgAdaAttributeExp &attr)
tests if attr is an access attribute
size_t positionalArgumentLimit(const SgExpressionPtrList &arglst)
finds the one past the last positional argument (aka the first named argument position).
SgScopeStatement * logicalParentScope(const SgScopeStatement &s)
returns the logical parent scope of a scope s.
SgAdaPackageSpecDecl * renamedPackage(const SgAdaRenamingDecl &n)
returns a package spec decl if the declaration n renames a package returns nullptr otherwise
SgExprListExp * isPragma(const SgPragmaDeclaration &prgdcl, const std::string &pragmaname)
tests if prgdcl is a pragma with name pragmaname.
bool isSeparatedDefinition(const SgFunctionDeclaration &n)
returns true iff n is a separated function definition is separated
SgExpression * underlyingExpr(const SgStatement *s)
returns the expression of an expression statement, or nullptr if s is some other node
long long int convertIntegerLiteral(const char *img)
converts text to constant values
SgScopeStatement * pkgStandardScope()
do not use, this is temporary
bool isSeparatedBody(const SgDeclarationStatement &n)
returns true iff n is a unit definition that has been separated
bool isScalarType(const SgType *ty)
returns true if ty refers to a scalar type
void extend(SgExpressionPtrList &container, std::size_t pos, SgExpression *val=nullptr)
resize the container if pos is outside the valid index range
SgDeclarationStatement * associatedDeclaration(const SgSymbol &n)
returns the associated declaration for symbol n or nullptr if there is none.
const SgVariableDeclaration * exceptionTypeDecl(const SgVariableDeclaration &n)
returns n or a pointer to n if n declares an exception type.
bool explicitNullProcedure(const SgFunctionDefinition &fndef)
returns true, iff fndef is the body of an explicit null procedure
SgEnumType * characterBaseType(SgEnumType *ty)
checks if the type is based on one of the Standard character types.
bool isDiscreteType(const SgType *ty)
return if the type ty is the corresponding universal type representation in ROSE
bool explicitNullRecord(const SgClassDefinition &recdef)
returns true, iff recdef is the body of an explicit null record
OperatorScopeInfo operatorScope(const std::string &opname, const SgTypePtrList &argtypes)
returns the scope where an operator with name opname and argument types in argtypes shall be declared...
bool unconstrained(const SgArrayType *ty)
tests if ty is an unconstrained array
bool isDiscreteArrayType(const SgType &ty)
returns true if ty refers to a discrete array type
std::vector< PrimitiveParameterDesc > primitiveParameterPositions(const SgFunctionDeclaration &fn)
returns the descriptions for parameters that make an operation primitive.
std::tuple< const SgScopeStatement *, const SgSymbol * > findSymbolInContext(std::string id, const SgScopeStatement &scope, const SgScopeStatement *limit=nullptr)
finds the symbol with Naming tips in the context of scope or its logical parents in the range [scope,...
void convertToOperatorRepresentation(SgNode *root, bool convertCallSyntax=false, bool convertNamedArguments=false)
converts AST from a function call representation to operator form for fundamental operator declaratio...
SgFunctionParameterList * calleeParameterList(const SgFunctionCallExp &n)
returns the function parameter list of the associated callee (if available).
boost::optional< bool > booleanConstant(const SgExpression *e)
if e denotes an Ada boolean constant, it is returned; otherwise an empty result is returned.
bool isIntegerType(const SgType &ty)
return if the type ty is the corresponding universal type representation in ROSE
bool isReverseForLoop(const SgForStatement *n)
returns true, iff n is a reverse for loop; returns false otherwise
const SgScopeStatement * canonicalScope(const SgScopeStatement *scope)
returns the canonical scope of some Ada scope scope.
SgAdaGenericDecl & getGenericDecl(const SgAdaGenericInstanceDecl &n)
Returns SgAdaGenericDecl for a given SgAdaGenericInstanceDecl.
SgAdaGenericDecl * isGenericDecl(const SgDeclarationStatement &n)
Returns the SgAdaGenericDecl node that makes a declaration (either function/procedure or package) gen...
SgType & standardType(const std::string &name)
returns a type from the standard package with name name.
bool isModularType(const SgType &ty)
return if the type ty is the corresponding universal type representation in ROSE
bool unitRefDenotesGenericInstance(const SgAdaUnitRefExp &n)
returns true iff n refers to a generic declaration from inside said declaration false otherwise (e....
bool anonymousAccess(const SgType *ty)
tests if ty is an anonymous access type
bool isFunction(const SgFunctionType &ty)
returns true iff ty refers to a function type (as opposed to procedure)
bool isAttribute(const SgAdaAttributeExp &attr, const std::string &attrname)
tests if attr is an attribute with name attrname.
char convertCharLiteral(const char *img)
converts text to constant values
SgRangeExp * range(const SgAdaAttributeExp *rangeAttribute)
returns a range for the range attribute rangeAttribute.
long double convertRealLiteral(const char *img)
converts text to constant values
bool isExceptionRenaming(const SgAdaRenamingDecl *dcl)
returns true iff ty refers to an exception renaming
std::vector< IfStatementInfo > flattenIfStatements(const SgIfStmt &n)
returns a flat representation of if-elsif-else statements
bool isDecimalFixedType(const SgType *ty)
returns if the type ty is a decimal fixed point type
TypeDescription typeOfExpr(const SgExpression &)
returns the type of an expression corrects for some peculiarities in the AST
SgType * baseOfAccessType(const SgType *ty)
returns the base type if ty is an access type
bool blockExistsInSource(const SgBasicBlock *blk)
checks if the block blk is present in the Ada source code.
SgStatementPtrList::iterator declarationLimit(SgStatementPtrList &list)
returns the iterator to one past the last declaration (the limit) in the statement sequence.
std::vector< RecordField > getAllRecordFields(const SgClassDefinition &rec)
returns all fields (defined and inherited) of a record.
SgAdaPackageSpec & getSpecificationDefinition(const SgAdaPackageBody &body)
returns the specification definition (scope) of the package body
SgNodePtrList unparsedChildren(SgNode &n)
returns a container of children nodes that are relevant for unparsing.
bool isPackageTryBlock(const SgTryStmt &n)
returns true iff n is an Ada package try block
SgType * baseType(const SgType &ty)
returns the base type of a type ty
bool hasSeparatedBody(const SgDeclarationStatement &dcl)
tests if the declaration decl corresponds to a stub (aka separated unit)
std::size_t normalizedArgumentPosition(const SgFunctionCallExp &call, const SgExpression &arg)
returns the parameter position of arg in the callee, after the parameters have been normalized.
int firstLastDimension(SgExprListExp &args)
returns an integer value for args[0] as used by type attributes first and last
bool isOutInoutArgument(const SgFunctionCallExp &call, const SgExpression &arg)
returns true if arg is a used as l-value in the call
bool withPrivateDefinition(const SgDeclarationStatement *dcl)
tests if the declaration dcl defines a public type that is completed in a private section.
bool sameCanonicalScope(const SgScopeStatement *lhs, const SgScopeStatement *rhs)
tests if lhs and have the same canonical scope.
void convertAdaToCxxComments(SgNode *root, bool cxxLineComments=true)
/}
ScopePath pathToGlobal(const SgScopeStatement &n)
Constructs a path from a scope statement to the top-level (global) scope.
SgAdaPackageSpecDecl & getSpecificationDeclaration(const SgAdaPackageBodyDecl &bodyDecl)
returns the declaration node for the package specification
const SgScopeStatement * correspondingBody(const SgScopeStatement *scope)
returns the body scope (aka definition) of a task, package, or protected object.
std::vector< ImportedUnitResult > importedUnits(const SgImportStatement &impdcl)
queries properties of all units in an import statement
SgScopeStatement * declarationScope(const SgType *ty)
returns the scope where type ty has been declared
SgEnumDeclaration * baseEnumDeclaration(const SgType *ty)
finds the underlying enum declaration of a type ty
TypeDescription typeRoot(SgType &)
returns the most fundamental type after skipping subtypes, typedefs, etc.
SgAdaPackageBodyDecl & getPackageBodyDeclaration(const SgAdaPackageSpecDecl &specDecl)
returns the declaration node for the package body, if available
long long int staticIntegralValue(SgExpression *n)
integer constant folding
bool hasUnknownDiscriminants(const SgAdaDiscriminatedTypeDecl &n)
returns true iff n has an unknown discriminant part
std::string convertRoseOperatorNameToAdaName(const std::string &nameInRose)
takes a function name as used in ROSE and converts it to a name in Ada (i.e., '"' + operator_text + '...
SgExpressionPtrList normalizedCallArguments(const SgFunctionCallExp &n, bool withDefaultArguments=false)
attempts to identify the argument list automatically and uses it to invoke the preceding normalizedCa...
Functions that are useful when operating on the AST.
Definition sageBuilder.h:25
ROSE_DLL_API SgScopeStatement * getEnclosingScope(SgNode *n, const bool includingSelf=false)
Get the enclosing scope from a node n.
ROSE_DLL_API void replaceExpression(SgExpression *oldExp, SgExpression *newExp, bool keepOldExp=false)
Replace an expression with another, used for variable reference substitution and others....
SgNamedType * getDeclaredType(const SgDeclarationStatement *declaration)
Returns the type introduced by a declaration.
@ WARN
Warning messages that indicate an unusual situation from which the program was able to fully recover.
Definition Message.h:328
@ TRACE
Detailed tracing information useful to end-users that are trying to understand program internals.
Definition Message.h:317
@ INFO
Informative messages.
Definition Message.h:326
@ FATAL
Messages that indicate an abnormal situation from which the program was unable to recover.
Definition Message.h:332
This namespace contains template functions that operate on the ROSE AST.
Definition sageGeneric.h:38
std::remove_const< typenamestd::remove_reference< RoseVisitor >::type >::type dispatch(RoseVisitor &&rv, SgNode *n)
uncovers the type of SgNode and passes it to an function "handle" in RoseVisitor.
SageNode::base_node_type & asBaseType(SageNode &n)
returns the same node n upcasted to its base type
This file implements generic (template) sage query functions Currently this includes functions for:
Traversal to change the comment style from Ada to C++.
stores a path from an innermost scope to the global scope (not part of the path) in form of a sequenc...
void push_back(base::value_type ptr)
overload vector's push_back to check element validity
struct DispatchHandler
experimental class for returning non-null pointers