ROSE 2.1.0
Loading...
Searching...
No Matches
sageInterface.C
1#include "sage3basic.h"
2#include "markLhsValues.h"
3#include "fixupNames.h"
4#include "FileUtility.h"
5#include <Sawyer/Message.h>
6
7#include "AstJSONGeneration.h"
8#include "SgNodeHelper.h" //Markus's helper functions
9
10#include "Rose/AST/Utility.h"
11#include "sageInterface.h"
12#include "Combinatorics.h"
13
14#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
15#include "replaceExpressionWithStatement.h"
16
17#include "constantFolding.h"
18#endif
19
20#include "sageBuilder.h"
21#include "sageGeneric.h"
22
23#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
24// For reusing some code from Qing's loop optimizer
25#include "AstInterface_ROSE.h"
26#include "LoopTransformInterface.h"
27
28#include "DepInfoAnal.h" // for AnalyzeStmtRefs()
29#include "ArrayAnnot.h"
30#include "ArrayInterface.h"
31
32#include "LoopUnroll.h"
33#include "abstract_handle.h"
34#include "roseAdapter.h"
35#endif
36
37#include <boost/lexical_cast.hpp>
38#include <boost/foreach.hpp>
39#include <sstream>
40#include <iostream>
41#include <algorithm> // for set operations
42#include <numeric> // for std::accumulate
43#include <map>
44#include <unordered_map>
45
46#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
47# include "jni.h"
48
49namespace Rose {
50 namespace Frontend {
51 namespace Java {
52 namespace Ecj {
53
54 extern jclass currentJavaTraversalClass;
55 extern JNIEnv *currentEnvironment;
56 extern jmethodID mainMethod;
57 extern jmethodID hasConflictsMethod;
58 extern jmethodID getTempDirectoryMethod;
59 extern jmethodID createTempFileMethod;
60 extern jmethodID createTempNamedFileMethod;
61 extern jmethodID createTempNamedDirectoryMethod;
62
63 } // ::Rose::Frontend::Java::Ecj
64 }// ::Rose::frontend::java
65 }// ::Rose::frontend
66}// ::Rose
67
68using namespace Rose::Frontend::Java::Ecj;
69
70#endif
71
72// We need this so that USE_CMAKE and ROSE_USE_CLANG_FRONTEND will be seen (set via configure).
73#include "rose_config.h"
74
75// DQ (11/5/2019): Added to support SageInterface::statementCanBeTransformed().
76namespace EDG_ROSE_Translation
77 {
78 // DQ (9/18/2018): Declare this map so that we can use it for the unparse header files option.
79#if defined(ROSE_BUILD_CXX_LANGUAGE_SUPPORT) && !defined(ROSE_USE_CLANG_FRONTEND)
80 // DQ (12/11/2018): Use the definition in the EDG edgRose.C file if C/C++ support IS defined.
81 extern std::map<std::string, SgIncludeFile*> edg_include_file_map;
82#else
83 // DQ (12/11/2018): Allow this to be the definition if C/C++ support is NOT defined.
84 std::map<std::string, SgIncludeFile*> edg_include_file_map;
85#endif
86 }
87
88#include "detectMacroOrIncludeFileExpansions.h"
89
90namespace SageInterface {
91 template<class T> void setSourcePositionToDefault( T* node );
92}
93
94
95#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
96 #include "transformationSupport.h"
97#endif
98
99#include "RoseAst.h"
100#include "AST_FILE_IO.h"
101
102// DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
103// The value of 0 allows the old implementation to be tested, and the value of 1 allows the new optimized implementation to be tested.
104#define OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS 1
105
108
110std::map<std::string,SgNode*> SageInterface::local_name_to_node_map;
111std::map<SgNode*,std::string> SageInterface::local_node_to_name_map;
112
113typedef std::set<SgLabelStatement*> SgLabelStatementPtrSet;
114
115namespace SageInterface
116{
117 Transformation_Record trans_records;
118}
119
120using namespace std;
121using namespace Rose;
122using namespace SageBuilder;
123
124namespace SageInterface
125 {
126 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
127 vector<SgBasicBlock*> addedBasicBlockNodes;
128 }
129
130
131#if 1
132// DQ (2/13/2022): Adding support to delete the whole AST (every SgNode).
133void
135 {
136 // This function uses a memory pool traversal specific to the SgFile IR nodes
137 class MyTraversal : public ROSE_VisitTraversal
138 {
139 public:
140 std::vector<SgNode*> resultlist;
141 void visit ( SgNode* node)
142 {
143 SgNode* result = dynamic_cast<SgNode*>(node);
144 ROSE_ASSERT(result != NULL);
145#if 0
146 if (result != NULL)
147 {
148 resultlist.push_back(result);
149 }
150#else
151 resultlist.push_back(result);
152#endif
153 };
154
155 virtual ~MyTraversal() {}
156 };
157
158 // For debugging, record the number of IR nodes before we delete the AST.
159 size_t numberOfNodes_before{numberOfNodes()};
160 MyTraversal my_traversal;
161 my_traversal.traverseMemoryPool();
162
163 vector<SgNode*>& nodeList = my_traversal.resultlist;
164 printf ("In SageInterface::deleteAllNodes(): get list of SgNode: nodeList.size() = %zu \n",nodeList.size());
165
166 vector<SgNode*>::iterator i = nodeList.begin();
167
168 // This loop will call the delete operator on all of the IR nodes in the AST.
169 while (i != nodeList.end())
170 {
171 SgNode* node = *i;
172 delete node;
173 node = NULL;
174
175 i++;
176 }
177
178 // Now we need to delete the memory pools (implemented by ROSETTA).
179 AST_FILE_IO::clearAllMemoryPools();
180
181 size_t numberOfNodes_after = numberOfNodes();
182 printf ("Leaving SageInterface::deleteAllNodes(): numberOfNodes_before = %zu numberOfNodes_after = %zu \n",numberOfNodes_before,numberOfNodes_after);
183 }
184#endif
185
186
187#if 0
188// DQ (3/5/2022): Adding support to check AST for invalide poionters.
189void
191 {
192 // This function uses a memory pool traversal to look for any pointers to invalid IR nodes.
193
194 // Step 1: is to build a map of the boundaries of the memory pools for each IR node kind.
195 // Step 2: traverse all of the IR nodes across all of the memory pools and check
196 // a) if the pointer to each node in the list of child IR nodes is in the map from step 1.
197 // b) if it is then we can expect to dereference the pointer and check the value of
198 // get_freepointer(), the value should be 0xffffffffffffffff, else it is an error
199 // (when it is an error it usually should be a value that is in the map from step 1, but it
200 // is a node that was previously deleted, so it is a stale pointer).
201
202 class BuildMapTraversal : public ROSE_VisitTraversal
203 {
204 public:
205 // std::vector<SgNode*> resultlist;
206 // std::map<enum VariantT,std::vector<std::pair<SgNode*,SgNode*>> mapOfMemoryPoolsBounds;
207
208 // We need to get the pools variable for each IR node.
209
210 void visit ( SgNode* node)
211 {
212 // Get list of all pointers to all IR nodes in the current node.
213
214 // $CLASSNAME::pools
216
217 resultlist.push_back(result);
218 };
219
220 virtual ~MyTraversal() {}
221 };
222
223 // For debugging, recode the number of IR nodes before we delete the AST.
224 size_t numberOfNodes_before = numberOfNodes();
225
226 MyTraversal my_traversal;
227
228 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
229 // NodeType::traverseMemoryPoolNodes(my_traversal);
230 my_traversal.traverseMemoryPool();
231 }
232#endif
233
234void
235SageInterface::DeclarationSets::addDeclaration(SgDeclarationStatement* decl)
236 {
237 // DQ (4/3/2014): This function either builds a new set or inserts declarations into an
238 // existing set based on if a set defined by the key (firstNondefiningDeclaration) is present.
239 ASSERT_not_null(decl);
240
241 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
242
243 if (firstNondefiningDeclaration == nullptr)
244 {
245 // It appears that some loop transformations (pass3.C) don't set the firstNondefiningDeclaration.
246 return;
247 }
248 ASSERT_not_null(firstNondefiningDeclaration);
249
250 if (decl == firstNondefiningDeclaration)
251 {
252 if (declarationMap.find(firstNondefiningDeclaration) == declarationMap.end())
253 {
254 // Add a new set.
255 declarationMap[decl] = new set<SgDeclarationStatement*>();
256
257 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
258 ROSE_ASSERT(declarationMap[decl] != nullptr);
259
260 // Add a declaration to an existing set.
261 declarationMap[firstNondefiningDeclaration]->insert(decl);
262 }
263 else
264 {
265 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
266 {
267 // Add a declaration to an existing set.
268 declarationMap[firstNondefiningDeclaration]->insert(decl);
269 }
270 else
271 {
272 // DQ (4/5/2014): The case of SgFunctionParameterList fails only for boost examples (e.g. test2014_240.C).
273 // Problem uses are associated with SgTemplateInstantiationFunctionDecl IR nodes.
274 bool ignore_error = (isSgFunctionParameterList(decl) != nullptr);
275
276 // DQ (4/17/2014): This is required for the EDG version 4.8 and I don't know why.
277 // Currently the priority is to pass our existing tests.
278 // An idea is that this is sharing introduced as a result of the use of default parameters.
279
280 // DQ (7/2/2014): I am seeing that this is required for a new application using GNU 4.4.7.
281 // It allows a boost issue specific to a revisited SgTypedefDeclaration pass, but I still
282 // don't understand the problem. so this needs a better fix.
283
285 bool isInTemplateFunctionDeclaration = enclosingFunction != nullptr && (isSgTemplateMemberFunctionDeclaration(enclosingFunction) || isSgTemplateFunctionDeclaration(enclosingFunction));
286
287 // Use short-circuit evaluation to improve performance.
288 SgClassDefinition* enclosingClassDefinition = isInTemplateFunctionDeclaration == true ? nullptr : getEnclosingClassDefinition(decl);
289 bool isInTemplateClassDefinition = enclosingClassDefinition != nullptr && isSgTemplateClassDefinition(enclosingClassDefinition);
290
291 bool isInTemplateDeclaration = isInTemplateFunctionDeclaration || isInTemplateClassDefinition;
292
293 ignore_error = ignore_error || (isSgTypedefDeclaration(decl) != nullptr) || (isSgTemplateInstantiationDecl(decl) != nullptr) || (isInTemplateDeclaration == true);
294
295 // DQ (2/5/2015): We need to ignore the case of un-named classes (or maybe those classes
296 // from unnamed classes with lambda member functions). See test2015_13.C for an example.
297 // Or maybe these should have been added to the declarationMap in the front-end?
298 if (isSgClassDeclaration(decl) != nullptr)
299 {
300 ignore_error = ignore_error || (isSgClassDeclaration(decl)->get_isUnNamed() == true);
301 }
302 }
303 }
304 }
305 else
306 {
307 // Add the declaration (make sure there is a set that exists).
308 if (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end())
309 {
310 // Make sure it does not already exist in the set.
311 ROSE_ASSERT (declarationMap[firstNondefiningDeclaration] != nullptr);
312 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
313 {
314 // Add a declaration to an existing set.
315 declarationMap[firstNondefiningDeclaration]->insert(decl);
316 }
317 }
318 else
319 {
320 // In this case the defining declaration might be the only declaration to be traversed and
321 // so a set has not been built yet.
322
323 // DQ (4/5/2014): Just build the set and don't insert the firstNondefiningDeclaration.
324 // If we were to do so then it would be an error to use the insert it later.
325 // Note recursive call.
326 declarationMap[firstNondefiningDeclaration] = new set<SgDeclarationStatement*>();
327 ASSERT_require(declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
328
329 // DQ (4/5/2014): We have to insert this since it is different from the firstNondefiningDeclaration.
330 // Add the declaration to the existing set.
331 declarationMap[firstNondefiningDeclaration]->insert(decl);
332
333 // DQ (4/5/2014): Added assertion.
334 ROSE_ASSERT(declarationMap[firstNondefiningDeclaration]->find(decl) != declarationMap[firstNondefiningDeclaration]->end());
335#if 0
336 printf ("SageInterface::DeclarationSets::addDeclaration(): No set exists for the firstNondefiningDeclaration = %p = %s = %s \n",firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
337 ROSE_ABORT();
338#endif
339 }
340 }
341 }
342
343const std::set<SgDeclarationStatement*>*
344SageInterface::DeclarationSets::getDeclarations(SgDeclarationStatement* decl)
345 {
346 // DQ (4/3/2014): This function returns the associated set of declarations.
347 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
348
349 ROSE_ASSERT(declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
350
351 const set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
352
353 // return this->declarationMap[firstNondefiningDeclaration];
354 return declarationSet;
355 }
356
357std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > &
358SageInterface::DeclarationSets::getDeclarationMap()
359 {
360 return declarationMap;
361 }
362
363bool
364SageInterface::DeclarationSets::isLocatedInDefiningScope(SgDeclarationStatement* decl)
365 {
366 // DQ (4/7/2014): This function assumes that the input is a friend declaration.
367
368 // The existence of a declaration in a named scope (if a friend function) will cause
369 // subsequent declarations to be qualified where name qualification is required.
370 // A couple of issues:
371 // We likely need to keep track of the order of the declarations in the more
372 // complex cases because name qualification will be required after the declaration
373 // that appears in the named scope; but will not be required before the declaration in
374 // the named scope.
375
376#define DEBUG_LOCATED_IN_DEFINING_SCOPE 0
377
378 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
379 ROSE_ASSERT(firstNondefiningDeclaration != nullptr);
380
381 set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
382 ROSE_ASSERT(declarationSet != nullptr);
383
384 set<SgDeclarationStatement*>::iterator i = declarationSet->begin();
385
386 bool isDefinedInNamedScope = false;
387
388#if DEBUG_LOCATED_IN_DEFINING_SCOPE
389 printf ("In DeclarationSets::isLocatedInDefiningScope(): decl = %p = %s \n",decl,decl->class_name().c_str());
390 printf (" --- declarationSet->size() = %" PRIuPTR " \n",declarationSet->size());
391#endif
392
393 while (isDefinedInNamedScope == false && i != declarationSet->end())
394 {
395 ROSE_ASSERT(*i != nullptr);
396#if DEBUG_LOCATED_IN_DEFINING_SCOPE
397 printf (" --- *i = %p = %s \n",*i,(*i)->class_name().c_str());
398#endif
399 // We want to know the structural position, not the semantic scope.
400 SgScopeStatement* semantic_scope = (*i)->get_scope();
401 SgScopeStatement* structural_scope = isSgScopeStatement((*i)->get_parent());
402
403#if DEBUG_LOCATED_IN_DEFINING_SCOPE
404 printf (" --- semantic_scope = %p = %s \n",semantic_scope,semantic_scope->class_name().c_str());
405 printf (" --- structural_scope = %p = %s \n",structural_scope,structural_scope->class_name().c_str());
406#endif
407 // DQ (4/7/2014): If it is a member of a class then we don't consider the structural scope, else it makes a difference,
408 SgScopeStatement* scope = isSgClassDefinition(semantic_scope) != nullptr ? semantic_scope : structural_scope;
409 ASSERT_not_null(scope);
410
411#if DEBUG_LOCATED_IN_DEFINING_SCOPE
412 printf (" --- scope = %p = %s \n",scope,scope->class_name().c_str());
413 printf (" --- scope->isNamedScope() = %s \n",scope->isNamedScope() ? "true" : "false");
414#endif
415 SgGlobal* globalScope = isSgGlobal(scope);
416
417 // Friend functions declared in the class definition are not meaningful for determining name qualification.
418 if (globalScope != nullptr || (scope->isNamedScope() == true && isSgClassDefinition(structural_scope) == nullptr) )
419 {
420 // Check if the function is output in the unparing, else it would not be defined.
421 bool willBeOutput = ((*i)->get_file_info()->isCompilerGenerated() == false ||
422 ((*i)->get_file_info()->isCompilerGenerated() &&
423 (*i)->get_file_info()->isOutputInCodeGeneration()) );
424#if DEBUG_LOCATED_IN_DEFINING_SCOPE
425 printf (" --- before: willBeOutput = %s \n",willBeOutput ? "true" : "false");
426#endif
427 // Being output only count when it is output where it is located structurally.
428 willBeOutput = willBeOutput && scope == structural_scope;
429
430#if DEBUG_LOCATED_IN_DEFINING_SCOPE
431 printf (" --- after: willBeOutput = %s \n",willBeOutput ? "true" : "false");
432#endif
433 // DQ (3/20/2016): this is reported by GNU as set but not used.
434 // associatedDeclaration = *i;
435
436 // isDefinedInNamedScope = true;
437 isDefinedInNamedScope = willBeOutput;
438 }
439
440 i++;
441 }
442
443#if DEBUG_LOCATED_IN_DEFINING_SCOPE
444 if (associatedDeclaration != nullptr)
445 {
446 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p = %s \n",associatedDeclaration,associatedDeclaration->class_name().c_str());
447 }
448 else
449 {
450 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p \n",associatedDeclaration);
451 }
452#endif
453
454 return isDefinedInNamedScope;
455 }
456
458SageInterface::buildDeclarationSets(SgNode* n)
459 {
460 DeclarationSets* declarationSet = new DeclarationSets();
461
462 class DeclarationSetTraversal : public AstSimpleProcessing
463 {
464 private:
465 DeclarationSets* declarationSet;
466
467 public:
468 DeclarationSetTraversal(DeclarationSets* ds) : declarationSet(ds) {}
469 void visit (SgNode* node)
470 {
471 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
472 if (decl != nullptr)
473 {
474 declarationSet->addDeclaration(decl);
475 }
476 }
477 };
478
479 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
480 DeclarationSetTraversal traversal(declarationSet);
481 traversal.traverse(n, preorder);
482
483 return declarationSet;
484 }
485
487// DQ: 09/23/03
488// We require a global function for getting the string associated
489// with the definition of a variant (which is a global enum).
490string getVariantName ( VariantT v )
491 {
492 ROSE_ASSERT( int(v) < int(V_SgNumVariants));
493
494 // This code is far simpler (if the function is static)
495
496 extern const char* roseGlobalVariantNameList[];
497 return string(roseGlobalVariantNameList[v]);
498 }
499
500bool
502 {
503 // DQ (6/7/2012): This refactors the test for template instantiation syntax in names used for classes, member functions, and functions
504 bool usingTemplateSyntax = false;
505 string nameString = name.getString();
506
507 // DQ (6/7/2012): We need to avoid the identification of the "operator<()" as valid template syntax.
508 usingTemplateSyntax = (nameString.find('<') != string::npos) && (nameString.find('>') != string::npos);
509
510 // DQ (5/10/2016): Debugging case of C++11 using the Intel v16 compiler and it's associated mutex header file.
511 // See Cxx11_tests/test2016_32.C for an example that demonstrates this problem.
512 if (nameString == "<unnamed>")
513 {
514 printf ("In SageInterface::hasTemplateSyntax(): Identified case of name == <unnamed> \n");
515
516 usingTemplateSyntax = false;
517 }
518
519 return usingTemplateSyntax;
520 }
521
522
523
524void
526 {
527 // DQ (2/12/2012): Refactoring disagnostic support for detecting where we are when something fails.
528
529 // This highest level node acceptable for us by this function is a SgGlobal (global scope).
530
531 ROSE_ASSERT(node != NULL);
532// printf ("Inside of SageInterface::whereAmI(node = %p = %s) \n",node,node->class_name().c_str());
533
534 // Enforce that some IR nodes should not be acepted inputs.
535 ROSE_ASSERT(isSgFile(node) == NULL);
536 ROSE_ASSERT(isSgFileList(node) == NULL);
537 ROSE_ASSERT(isSgProject(node) == NULL);
538
539 SgNode* parent = node->get_parent();
540
541 // Don't traverse past the SgFile level.
542 while (parent != nullptr && isSgFileList(parent) == nullptr)
543 {
544 // DQ (7/14/2019): These were commented out, but they are intended for debugging, so
545 // if someone does not need this output then the function should not have been called.
546 printf ("--- parent = %p = %s \n",parent,parent->class_name().c_str());
547
548 ROSE_ASSERT(parent->get_file_info() != NULL);
549 parent->get_file_info()->display("In SageInterface::whereAmI() diagnostics support");
550
551 parent = parent->get_parent();
552 }
553 }
554
555void
556SageInterface::initializeIfStmt(SgIfStmt *ifstmt, SgStatement* conditional, SgStatement * true_body, SgStatement * false_body)
557 {
558 // DQ (2/13/2012): Added new function to support proper initialization of a SgIfStmt that has already been built.
559 // This is important when we have to build the scope ahead of the test becasue the text contains a simple
560 // declaration (which must be put into the SgIfStmt scope).
561
562 // SgIfStmt *ifstmt = new SgIfStmt(conditional, true_body, false_body);
563 ROSE_ASSERT(ifstmt);
564
565 if (ifstmt->get_conditional() == nullptr)
566 ifstmt->set_conditional(conditional);
567
568 if (ifstmt->get_true_body() == nullptr)
569 ifstmt->set_true_body(true_body);
570
571 if (ifstmt->get_false_body() == nullptr)
572 ifstmt->set_false_body(false_body);
573
574 // Rasmussen (3/22/2020): Fixed setting case insensitivity
576 ifstmt->setCaseInsensitive(true);
577
579 if (conditional) conditional->set_parent(ifstmt);
580 if (true_body) true_body->set_parent(ifstmt);
581 if (false_body) false_body->set_parent(ifstmt);
582 }
583
584
585void
587 {
588 ROSE_ASSERT(switchStatement != NULL);
589
590 // Rasmussen (3/22/2020): Fixed setting case insensitivity
592 switchStatement->setCaseInsensitive(true);
593
594 if (switchStatement->get_item_selector() == nullptr)
595 switchStatement->set_item_selector(item_selector);
596
597 if (switchStatement->get_body() == nullptr)
598 switchStatement->set_body(body);
599
601 if (item_selector != nullptr)
602 item_selector->set_parent(switchStatement);
603 if (body != nullptr)
604 body->set_parent(switchStatement);
605 }
606
607
608void
610 {
611 ROSE_ASSERT(whileStatement);
612
613 // Rasmussen (3/22/2020): Fixed setting case insensitivity
615 whileStatement->setCaseInsensitive(true);
616
617 if (whileStatement->get_condition() == nullptr)
618 whileStatement->set_condition(condition);
619 if (whileStatement->get_body() == nullptr)
620 whileStatement->set_body(body);
621
622 // Python support.
623 if (whileStatement->get_else_body() == nullptr)
624 whileStatement->set_else_body(else_body);
625
626 setOneSourcePositionNull(whileStatement);
627 if (condition) condition->set_parent(whileStatement);
628 if (body) body->set_parent(whileStatement);
629
630 // DQ (8/10/2011): This is added by Michael to support a Python specific feature.
631 if (else_body != nullptr)
632 {
633 whileStatement->set_else_body(else_body);
634 else_body->set_parent(whileStatement);
635 }
636 }
637
638
639
642 {
643 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
644
645 // This function returns the namespace associated with any declaration.
646 // If the declaration is nested inside of other scopes this function
647 // iterates through these scopes to get the the first namespace.
648 // This is important for details of template handling, namely making sure
649 // that the template specializations (generated by ROSE) are put into the
650 // correct location (namespace) since stricted rules in gnu now enforce
651 // these details. If the declaration is not in a namespace as computed
652 // in the chain of scopes then this function returns nullptr.
653
654 ASSERT_not_null(declaration);
655 SgScopeStatement* tempScope = declaration->get_scope();
656
657 // Loop back to the first namespace or stop at global scope (stop on either a namespace or the global scope)
658 while ( isSgNamespaceDefinitionStatement(tempScope) == nullptr && isSgGlobal(tempScope) == nullptr )
659 {
660 tempScope = tempScope->get_scope();
661 ASSERT_not_null(tempScope);
662 }
663
664 SgNamespaceDefinitionStatement* namespaceScope = isSgNamespaceDefinitionStatement(tempScope);
665 return namespaceScope;
666 }
667
668
671 {
672 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
673 // DQ (11/4/2007): Get the associated declaration that will be in the original source code,
674 // if it is part of a template instantiation then get the original template declaration.
675
676 SgDeclarationStatement* parentDeclaration = nullptr;
677
678 SgScopeStatement* defn = memberFunctionInstantiation->get_class_scope();
679 ASSERT_not_null(defn);
680
681 // SgTemplateDeclaration* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
682 SgDeclarationStatement* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
683 ASSERT_not_null(templateDeclaration);
684
685 // If it is a template instatiation, then we have to find the temple declaration (not the template instantiation declaration), else we want the class declaration.
686 SgClassDefinition* cdefn = isSgClassDefinition(defn);
687 SgDeclarationScope* nrscope = isSgDeclarationScope(defn);
688 SgTemplateInstantiationDefn* templateInstatiationClassDefinition = isSgTemplateInstantiationDefn(defn);
689 if (templateInstatiationClassDefinition != nullptr)
690 {
691 // This is the case of a template member function in a templated class (see test2005_172.C).
692 SgTemplateInstantiationDefn* parentTemplateInstantiationDefinition = isSgTemplateInstantiationDefn(templateDeclaration->get_scope());
693 ASSERT_not_null(parentTemplateInstantiationDefinition);
694 SgTemplateInstantiationDecl* parentTemplateInstantiationDeclaration = isSgTemplateInstantiationDecl(parentTemplateInstantiationDefinition->get_declaration());
695 ASSERT_not_null(parentTemplateInstantiationDeclaration);
696
697 parentDeclaration = parentTemplateInstantiationDeclaration->get_templateDeclaration();
698 ASSERT_not_null(parentDeclaration);
699 }
700 else if (cdefn != nullptr)
701 {
702 // This is the case of a template member function in a class definition (see test2005_168.C).
703 parentDeclaration = cdefn->get_declaration();
704 ASSERT_not_null(parentDeclaration);
705 }
706 else if (nrscope != nullptr)
707 {
708 parentDeclaration = isSgDeclarationStatement(nrscope->get_parent());
709 ASSERT_not_null(parentDeclaration);
710 }
711 else
712 {
713 ROSE_ABORT();
714 }
715
716 return parentDeclaration;
717 }
718
722void
724{
725 ASSERT_not_null(var_decl);
726 ASSERT_not_null(base_decl);
727
728 // There is a bug (see gitlab-issue-349.jov) that arises when base_decl has a comment and it is the
729 // first statement, because base_decl will be removed (causing comments to be moved, where? good question!).
730 // Consider moving comments to var_decl first to circumvent (by artfulness or deception) potential problems.
731 // [Rasmussen 2024.04.10]
732
733 // try to remove it from the scope's declaration list
734 // If the struct decl was previously inserted into its scope
735 if (base_decl->get_parent() != nullptr)
736 {
737 if (base_decl->get_scope() == base_decl->get_parent())
738 {
739 SgStatementPtrList stmt_list = base_decl->get_scope()->generateStatementList();
740 if (find(stmt_list.begin(), stmt_list.end(), base_decl) != stmt_list.end())
742 }
743 }
744 base_decl->set_parent(var_decl);
745 var_decl->set_baseTypeDefiningDeclaration(base_decl);
746
747 //Set an internal mangled name for the anonymous declaration, if necessary
748 // resetNamesInAST(); // this will trigger mangleNameMap.size() ==0 assertion.
749 // We call resetEmptyNames directly instead.
750 ResetEmptyNames t1;
751 t1.traverseMemoryPool();
752}
753
754// DQ (11/4/2007): This looks for a forward temple member function declaration of matching name exists in the specified scope.
755bool
757 {
758 // DQ (11/3/2007): Look for an existing previously inserted (or existing) template member function declaration and only add one if we can't find it.
759
760 bool foundExistingPrototype = false;
761
762 ROSE_ASSERT(scope != NULL);
763 ROSE_ASSERT(functionDeclaration != NULL);
764 ROSE_ASSERT(startingAtDeclaration != NULL);
765
766 // TV (09/17/2018): ROSE-1378
767 if (isSgDeclarationScope(scope)) {
768 printf("TODO: SgDeclarationScope handling in SageInterface::isPrototypeInScope see ROSE-1378\n");
769 return false;
770 }
771
772 // These are the scopes for which get_declarationList() is properly defined.
773 ROSE_ASSERT(scope->containsOnlyDeclarations() == true);
774
775 // Note that this is only defined for certain scopes, but we only want it for THOSE scopes
776 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
777
778 // This is a simple way to restrict the evaluation (still linear, but jumps to initial position to start search).
779 SgDeclarationStatementPtrList::iterator startingLocation = find(declarationList.begin(),declarationList.end(),startingAtDeclaration);
780
781 if (startingLocation != declarationList.end())
782 {
783#if 0
784 printf ("startingLocation = %p = %s = %s \n",*startingLocation,(*startingLocation)->class_name().c_str(),SageInterface::get_name(*startingLocation).c_str());
785#endif
786 // printf ("Found the startingLocation is the global scope, now check if we need to add a new declaration \n");
787 SgDeclarationStatementPtrList::iterator i = startingLocation;
788 SgScopeStatement* targetScope = functionDeclaration->get_scope();
789 SgName targetName = functionDeclaration->get_name();
790
791 while (i != declarationList.end())
792 {
793 // printf ("i = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
794
795 // Look for a prototype like what we want to insert, if we find it then we don't need to add a second one!
796 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(*i);
797 if (templateMemberFunction != nullptr)
798 {
799 // Check the name and the scope
800 if (targetScope == templateMemberFunction->get_scope())
801 {
802 if (targetName == templateMemberFunction->get_name())
803 {
804 // Don't count the defining declaration which may be at the end of the global scope.
805 if (templateMemberFunction->isForward() == true)
806 {
807 foundExistingPrototype = true;
808
809 // Exit the loop (optimization)
810 break;
811 }
812 }
813 }
814 }
815
816 i++;
817 }
818 }
819
820 return foundExistingPrototype;
821 }
822
823bool
825 {
826 ROSE_ASSERT(node1 && node2);
827
828 SgNode* curnode = node2;
829 if (node1==node2)
830 {
831 return false;
832 }
833
834 do {
835 curnode= curnode->get_parent();
836 } while( (curnode!=nullptr) && (curnode!=node1));
837
838 if (curnode==node1)
839 {
840 return true;
841 }
842 else
843 {
844 return false;
845 }
846 }
847
848bool
850 {
851 // DQ (12/7/2020): This is supporting the recognition of functions in header files from two different AST.
852
853#define DEBUG_HAS_SAME_SCOPE 0
854
855#if DEBUG_HAS_SAME_SCOPE
856 printf ("In SageInterface::hasSameGlobalScope(): \n");
857 printf (" --- statement_1 = %p = %s \n",statement_1,statement_1->class_name().c_str());
858 printf (" --- statement_2 = %p = %s \n",statement_2,statement_2->class_name().c_str());
859#endif
860
861 bool includingSelf = true;
862 SgGlobal* global_scope_1 = getEnclosingNode<SgGlobal>(statement_1,includingSelf);
863 SgGlobal* global_scope_2 = getEnclosingNode<SgGlobal>(statement_2,includingSelf);
864
865#if DEBUG_HAS_SAME_SCOPE
866 printf (" --- global_scope_1 = %p = %s \n",global_scope_1,global_scope_1->class_name().c_str());
867 SgSourceFile* sourcefile_1 = isSgSourceFile(global_scope_1->get_parent());
868 printf (" --- --- sourcefile_1 = %p filename = %s \n",sourcefile_1,sourcefile_1->getFileName().c_str());
869
870 printf (" --- global_scope_2 = %p = %s \n",global_scope_2,global_scope_2->class_name().c_str());
871 SgSourceFile* sourcefile_2 = isSgSourceFile(global_scope_2->get_parent());
872 printf (" --- --- sourcefile_2 = %p filename = %s \n",sourcefile_2,sourcefile_2->getFileName().c_str());
873#endif
874
875 bool returnResult = (global_scope_1 == global_scope_2);
876
877#if DEBUG_HAS_SAME_SCOPE
878 printf ("Leaving SageInterface::hasSameGlobalScope(): returning: %s \n",returnResult ? "true" : "false");
879#endif
880
881 return returnResult;
882 }
883
884
885std::vector<SgNode*>
887 {
888 std::vector<SgNode*> intersectionSet;
889
890 // Collect all the IR nodes for the original AST
891 std::vector<SgNode*> AST_original = NodeQuery::querySubTree (original,V_SgNode);
892 std::vector<SgNode*> AST_copy = NodeQuery::querySubTree (copy,V_SgNode);
893
894 int AST_original_size = AST_original.size();
895 int AST_copy_size = AST_copy.size();
896
897 if (SgProject::get_verbose() > 0)
898 {
899 printf ("Original AST size = %d \n",AST_original_size);
900 printf ("Copy of original AST size = %d \n",AST_copy_size);
901 }
902
903 int differenceInSizes = AST_original_size - AST_copy_size;
904 if (differenceInSizes == 0)
905 {
906 if (SgProject::get_verbose() > 0)
907 printf ("Copied AST is the SAME size as the original (size = %d) \n",AST_original_size);
908 }
909 else
910 {
911 printf ("Warning: Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) \n",AST_original_size,AST_copy_size);
912 }
913
914 // Compute the intersection (reference in the copy that point to the origal AST).
915 // std::set<SgNode*> AST_set_original = AST_original;
916 std::set<SgNode*> AST_set_original;
917 for (int i = 0; i < AST_original_size; i++)
918 {
919 AST_set_original.insert(AST_original[i]);
920 }
921
922 std::set<SgNode*> AST_set_copy;
923 for (int i = 0; i < AST_copy_size; i++)
924 {
925 AST_set_copy.insert(AST_copy[i]);
926 }
927
928 int size = AST_original_size;
929 std::vector<SgNode*> intersectionList(size);
930
931 // Is there a better way to do this? Build scratch space and then use the different between begin() and end to build another vector.
932 std::vector<SgNode*>::iterator end = set_intersection(AST_set_original.begin(),AST_set_original.end(),AST_set_copy.begin(),AST_set_copy.end(),intersectionList.begin());
933
934 // Build a new vector from the relevant elements of the intersectionList scratch space.
935 std::vector<SgNode*> meaningIntersectionList = std::vector<SgNode*>(intersectionList.begin(),end);
936 std::vector<SgNode*> deleteList;
937 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
938 {
939 if (meaningIntersectionList[i] != nullptr && isSgType(meaningIntersectionList[i]) != nullptr)
940 {
941 deleteList.push_back(meaningIntersectionList[i]);
942 }
943 }
944
945 // Remove the types since they are allowed to be shared...
946 if (SgProject::get_verbose() > 0)
947 printf ("Remove the types that are allowed to be shared: deleteList.size() = %ld \n",(long)deleteList.size());
948
949 for (std::vector<SgNode*>::iterator i = deleteList.begin(); i != deleteList.end(); i++)
950 {
951 meaningIntersectionList.erase(find(meaningIntersectionList.begin(),meaningIntersectionList.end(),*i));
952 }
953
954 if (SgProject::get_verbose() > 0)
955 printf ("After removing the types there are meaningIntersectionList.size() = %ld \n",(long)meaningIntersectionList.size());
956
957 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
958 {
959 printf (" meaningIntersectionList[%d] = %p = %s = %s \n",i,meaningIntersectionList[i],meaningIntersectionList[i]->class_name().c_str(),get_name(meaningIntersectionList[i]).c_str());
960 }
961
962 int unmatchedIRnodes = 0;
963 if (help != nullptr)
964 {
965 std::vector<SgNode*> tmp_AST_original; // = AST_original;
966 std::vector<SgNode*> tmp_AST_copy; // = AST_copy;
967
968 int AST_original_size = AST_original.size();
969 for (int j = 0; j < AST_original_size; j++)
970 {
971 if (AST_original[j] != NULL && isSgType(AST_original[j]) == NULL)
972 {
973 tmp_AST_original.push_back(AST_original[j]);
974 }
975 }
976
977 int AST_copy_size = AST_copy.size();
978 for (int j = 0; j < AST_copy_size; j++)
979 {
980 if (AST_copy[j] != NULL && isSgType(AST_copy[j]) == NULL)
981 {
982 tmp_AST_copy.push_back(AST_copy[j]);
983 }
984 }
985
986 std::vector<SgNode*> deleteList_original;
987 std::vector<SgNode*> deleteList_copy;
988 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
989 {
990 // printf (" (before removing types) meaningIntersectionList[%d] = %p = %s \n",i,meaningIntersectionList[i],(meaningIntersectionList[i] != NULL) ? meaningIntersectionList[i]->class_name().c_str() : "NULL");
991 SgCopyHelp::copiedNodeMapTypeIterator i = help->get_copiedNodeMap().find(tmp_AST_original[j]);
992 // printf ("SgCopyHelp::copiedNodeMapTypeIterator i != help->get_copiedNodeMap().end() = %s \n",i != help->get_copiedNodeMap().end() ? "true" : "false");
993 if (i != help->get_copiedNodeMap().end())
994 {
995 // Matched up an original IR node with it's copy
996 SgNode* associated_node_copy = i->second;
997 ROSE_ASSERT(associated_node_copy != NULL);
998 deleteList_original.push_back(tmp_AST_original[j]);
999 deleteList_copy.push_back(associated_node_copy);
1000#if 0
1001 // printf ("Original IR node = %p = %s copy = %p \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),associated_node_copy);
1002 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(tmp_AST_original[j]);
1003 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction_copy = isSgTemplateInstantiationMemberFunctionDecl(associated_node_copy);
1004 if (templateMemberFunction != NULL)
1005 {
1006 printf ("In SageInterface::astIntersection(): Found a SgTemplateInstantiationMemberFunctionDecl = %p copy = %p \n",templateMemberFunction,associated_node_copy);
1007 // templateMemberFunction->get_startOfConstruct()->display("original: debug");
1008 // templateMemberFunction_copy->get_startOfConstruct()->display("copy: debug");
1009 }
1010#endif
1011 }
1012 }
1013
1014 int deleteList_original_size = deleteList_original.size();
1015 for (int j = 0; j < deleteList_original_size; j++)
1016 {
1017 // tmp_AST_original.erase(find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]));
1018 std::vector<SgNode*>::iterator k = find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]);
1019 if (k != tmp_AST_original.end())
1020 {
1021 tmp_AST_original.erase(k);
1022 }
1023 }
1024
1025 if (SgProject::get_verbose() > 0)
1026 printf ("IR nodes different between the original AST and the copy of the AST = %" PRIuPTR " \n",tmp_AST_original.size());
1027
1028 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1029 {
1030 printf ("non matched IR node = %p = %s = %s \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),get_name(tmp_AST_original[j]).c_str());
1031 // tmp_AST_original[j]->get_startOfConstruct()->display("debug");
1032 }
1033
1034 unmatchedIRnodes = (int)tmp_AST_original.size();
1035 }
1036
1037 // DQ (11/2/2007): Make this an error now!
1038 if (differenceInSizes != 0)
1039 {
1040 SgProject* originalProject = isSgProject(original);
1041 if (originalProject != NULL)
1042 {
1043 printf ("In %s Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) IR nodes different = %d \n",
1044 (*originalProject)[0]->get_sourceFileNameWithoutPath().c_str(),AST_original_size,AST_copy_size,unmatchedIRnodes);
1045 }
1046
1047 if (unmatchedIRnodes > 0)
1048 {
1049 printf ("Make this an error under stricter testing \n");
1050 ROSE_ABORT();
1051 }
1052 }
1053
1054 return intersectionSet;
1055 }
1056
1057// AJ (10/21/2004): Added support for changing the symbol name associated with an SgInitializedName
1058// by updating the symbol table
1059int
1060SageInterface::set_name ( SgInitializedName *initializedNameNode, SgName new_name )
1061 {
1062 // find the appropriate symbol table, delete the symbol
1063 // with the old name and add a symbol with the new name.
1064 ROSE_ASSERT(initializedNameNode != NULL);
1065
1066#define DEBUG_SET_NAME 0
1067
1068 // SgNode * node = this;
1069#if DEBUG_SET_NAME
1070 printf ("In SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1071#endif
1072
1073#if 0
1074 // DQ (12/9/2004): This should likely call the get_scope function (which is more robust than traversing
1075 // parents, there is a reason why we are forced to include the scope explicitly on some IR nodes,
1076 // see test2004_133.C for details).
1077 while((node!=NULL) && ( isSgScopeStatement(node)==NULL))
1078 node = node->get_parent();
1079
1080 ROSE_ASSERT(node!=NULL);
1081
1082 SgScopeStatement * scope_stmt = isSgScopeStatement(node);
1083#else
1084 SgScopeStatement *scope_stmt = initializedNameNode->get_scope();
1085#endif
1086
1087 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1088 if (isSgEnumDeclaration(initializedNameNode->get_parent()) != NULL)
1089 {
1090 ROSE_ASSERT(scope_stmt != NULL);
1091 printf ("scope_stmt = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1092#if 0
1093 printf ("Detected isSgEnumDeclaration as parent: exiting as a test in SageInterface::set_name() \n");
1094 ROSE_ASSERT(false);
1095#endif
1096 }
1097
1098 ROSE_ASSERT(scope_stmt != NULL);
1099 ROSE_ASSERT(scope_stmt->get_symbol_table() != NULL);
1100 ROSE_ASSERT(scope_stmt->get_symbol_table()->get_table() != NULL);
1101
1102 SgDeclarationStatement * parent_declaration = initializedNameNode->get_declaration();
1103
1104 ROSE_ASSERT(parent_declaration != NULL);
1105
1106 // Find the symbols associated with p_name
1107 std::pair<SgSymbolTable::hash_iterator,SgSymbolTable::hash_iterator> pair_it = scope_stmt->get_symbol_table()->get_table()->equal_range(initializedNameNode->get_name());
1108
1109 SgSymbolTable::hash_iterator found_it = scope_stmt->get_symbol_table()->get_table()->end();
1110
1111 for (SgSymbolTable::hash_iterator it = pair_it.first; it != pair_it.second; ++it)
1112 {
1113#if DEBUG_SET_NAME
1114 printf ("Looking for symbol in scope = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1115 printf (" --- *it = %p = %s \n",(*it).second,(*it).second->class_name().c_str());
1116#endif
1117 switch(parent_declaration->variantT())
1118 {
1119 case V_SgFunctionParameterList:
1120 case V_SgVariableDeclaration:
1121 {
1122 if (isSgVariableSymbol((*it).second) != NULL)
1123 found_it = it;
1124 break;
1125 }
1126
1127 case V_SgClassDeclaration:
1128 {
1129 if (isSgClassSymbol((*it).second) != NULL)
1130 found_it = it;
1131 break;
1132 }
1133
1134 case V_SgFunctionDeclaration:
1135 {
1136 if (isSgFunctionSymbol((*it).second) != NULL)
1137 found_it = it;
1138 break;
1139 }
1140
1141 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1142 case V_SgEnumDeclaration:
1143 {
1144 if (isSgEnumFieldSymbol((*it).second) != NULL)
1145 found_it = it;
1146 break;
1147 }
1148
1149 default:
1150 {
1151 printf ("Default reached in switch in SageInterface::set_name() \n");
1152 }
1153 };
1154 }
1155
1156 // there is no Variable, Class or Function symbol associated with p_name
1157 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1158 {
1159 printf ("Warning: There is no Variable, Class, Function, or EnumValue symbol associated with p_name \n");
1160 return 0;
1161 }
1162
1163 // DQ (11/12/2018): In general, this can't be tested if we permit it to be transformed.
1164 if (statementCanBeTransformed(parent_declaration) == false)
1165 {
1166 printf ("WARNING: SageInterface::set_name(): This statement can not be transformed because it is part of a header file specific more then once with different include file syntax \n");
1167 return 0;
1168 }
1169 else
1170 {
1171#if DEBUG_SET_NAME
1172 printf ("In SageInterface::set_name(): This statement can be transformed! parent_declaration = %p = %s \n",parent_declaration,get_name(parent_declaration).c_str());
1173#endif
1174
1175#if 0
1176 // DQ (11/12/2018): Initial test problem should not permit a transformation!
1177 printf ("Exiting as a test! \n");
1178 ROSE_ABORT();
1179#endif
1180 }
1181
1182 SgSymbol * associated_symbol = (*found_it).second;
1183
1184 // erase the name from there
1185 scope_stmt->get_symbol_table()->get_table()->erase(found_it);
1186
1187 // insert the new_name in the symbol table
1188// CH (4/9/2010): Use boost::unordered instead
1189//#ifdef _MSCx_VER
1190#if 0
1191 // DQ (11/28/2009): Unclear if this code is a problem (testing).
1192
1193// CH (4/7/2010): It seems that the following code can be compiled under MSVC 9.0
1194//#pragma message ("WARNING: this code does not apprear to compile with MSVC.")
1195// printf ("ERROR: this code does not apprear to compile with MSVC. \n");
1196// ROSE_ASSERT(false);
1197 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1198#else
1199 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1200#endif
1201 // if insertion failed
1202 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1203 {
1204 printf ("Warning: insertion of new symbol failed \n");
1205 return 0;
1206 }
1207
1208#if DEBUG_SET_NAME
1209 // Set the p_name to the new_name
1210 printf ("Reset initializedNameNode->get_name() = %s to new_name = %s \n",initializedNameNode->get_name().str(),new_name.str());
1211#endif
1212
1213 // p_name = new_name;
1214 initializedNameNode->set_name(new_name);
1215
1216 // DQ (11/30/2018): Mark the enclosing statement as modified, so that it will be recognized
1217 // in the header file unparsing as being a header file that should be unparsed.
1218 SgStatement* enclosingStatement = getEnclosingStatement(initializedNameNode);
1219 ROSE_ASSERT(enclosingStatement != NULL);
1220 enclosingStatement->set_isModified(true);
1221 enclosingStatement->setTransformation();
1222
1223 // Invalidate the p_iterator, p_no_name and p_name data members in the Symbol table
1224
1225#if 1
1226 // Search the AST for references to this SgInitializedName (SgVarRefExp), check if the symbol matches
1227 // (we can do this since we only reused the exisitng symbol), and mark those expressions as modified.
1228 class RoseVisitor : public ROSE_VisitTraversal
1229 {
1230 public:
1231 int counter;
1232 SgSymbol* symbol;
1233
1235 void visit (SgNode* node)
1236 {
1237 SgVarRefExp* varRefExp = isSgVarRefExp(node);
1238 SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol);
1239
1240 ROSE_ASSERT(varRefExp != NULL);
1241 ROSE_ASSERT(variableSymbol != NULL);
1242
1243 if (varRefExp->get_symbol() == variableSymbol)
1244 {
1245#if DEBUG_SET_NAME
1246 printf ("In SageInterface::set_name(): Found associated SgVarRefExp varRefExp = %p to symbol associated_symbol = %p \n",varRefExp,variableSymbol);
1247#endif
1248#if 0
1249 printf ("Exiting as a test! \n");
1250 ROSE_ABORT();
1251#endif
1252 varRefExp->set_isModified(true);
1253 varRefExp->setTransformation();
1254#if 1
1255 // DQ (5/2/2021): The traversal over the file will identify the nesting of and transformations in outer (enclosing) IR nodes.
1256 // DQ (5/1/2021): I think that we may have to set the physical node id and maybe make it to be output. This is
1257 // special to the case of using the header file unparsing (any maybe the token-based unparsing with the header
1258 // file unparsing, but I think just the header file unparsing).
1259#if 0
1260 printf ("In SageInterface::set_name(): When unparsing header files, we need to set the physical file id to the correct file \n");
1261#endif
1262 // DQ (4/23/2021): I think it is a problem that the statement is not marked as a transformation so that we
1263 // know how to handle it with the token-based unparsing.
1264 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1265 ROSE_ASSERT(associatedStatement != NULL);
1266 associatedStatement->setTransformation();
1267#endif
1268#if 0
1269 // DQ (11/13/2018): Mark the statement associated with this SgVarRefExp (see test9 in UnparseHeaders_tests).
1270 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1271 ROSE_ASSERT(associatedStatement != NULL);
1272 // associatedStatement->set_isModified(true);
1273 // associatedStatement->set_containsTransformation(true);
1274 associatedStatement->setTransformation();
1275#endif
1276 }
1277 }
1278
1279 RoseVisitor(SgSymbol* symbol_parmeter) : counter(0), symbol(symbol_parmeter)
1280 {
1281#if 0
1282 printf ("roseVisitor::visit: counter %4d node = %s \n",counter,symbol_parmeter->class_name().c_str());
1283#endif
1284 counter++;
1285 }
1286 };
1287
1288 // RoseVisitor visitor;
1289 // visitor.traverseMemoryPool();
1290 RoseVisitor t1(associated_symbol);
1292#endif
1293
1294#if DEBUG_SET_NAME
1295 printf ("Leaving SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s (return 1) \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1296#endif
1297
1298 // DQ (4/23/2021): I think that we should be returning zero for no error
1299 // and one for an error, this function appears to have this detail reversed.
1300 return 1;
1301 }
1302
1303
1304void
1306 {
1307 printf ("In SageInterface::listHeaderFiles(): includeFile filename = %s \n",includeFile->get_filename().str());
1308
1309 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
1310 class PrefixTraversal : public AstSimpleProcessing
1311 {
1312 public:
1313 void visit (SgNode* node)
1314 {
1315 printf ("In listHeaderFiles visit(): node = %p = %s \n",node,node->class_name().c_str());
1316 SgIncludeFile* includeFile = isSgIncludeFile(node);
1317 if (includeFile != NULL)
1318 {
1319 printf ("include file: filename = %s \n",includeFile->get_filename().str());
1320 }
1321 }
1322 };
1323
1324 // Now buid the traveral object and call the traversal (preorder) on the function definition.
1325 PrefixTraversal traversal;
1326 traversal.traverse(includeFile, preorder);
1327
1328 }
1329
1330
1331bool
1333 {
1334 // DQ (5/9/2021): Adding support for detection of statements in a scope that must be unparsed.
1335 // This function supports the token-based unparsing when used with unparsing of header files
1336 // to know when the scope can be unparsed via it's token stream, even though a statement from
1337 // a header file may contain a transformation.
1338 // returns true if there is a statement in the scope that has to be unparsed (is from the same file as the scope).
1339 // returns false if the scope is empty or contains only statements associated with one or more header files.
1340 // When the scope has statements from the same file, then if there is a transformation contained in any of
1341 // those statements then we have to unparse the scope one statement at a time when using the token-based
1342 // unparsing. If the scope has no statements from the same file, then the existance of any statement that
1343 // contains a transformation does not case the statements to be unparsed individually.
1344
1345 ROSE_ASSERT(scope != NULL);
1346 int scope_file_id = scope->get_file_info()->get_physical_file_id();
1347
1348 bool return_value = false;
1349
1350 if (scope->containsOnlyDeclarations() == true)
1351 {
1352 SgDeclarationStatementPtrList & declarationStatementList = scope->getDeclarationList();
1353#if 1
1354 printf ("In scopeHasStatementsFromSameFile(): DeclarationStatementList not implemented \n");
1355#endif
1356#if 1
1357 printf ("declarationStatementList.size() = %zu \n",declarationStatementList.size());
1358#endif
1359 SgDeclarationStatementPtrList::iterator i = declarationStatementList.begin();
1360
1361 while (i != declarationStatementList.end() && return_value == false)
1362 {
1363 SgDeclarationStatement* statement = *i;
1364 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1365
1366 if (statement_file_id == scope_file_id)
1367 {
1368 return_value = true;
1369 }
1370
1371 i++;
1372 }
1373#if 0
1374 printf ("Exiting as a test! \n");
1375 ROSE_ASSERT(false);
1376#endif
1377 }
1378 else
1379 {
1380 SgStatementPtrList & statementList = scope->getStatementList();
1381#if 1
1382 printf ("In scopeHasStatementsFromSameFile(): StatementList not implemented \n");
1383#endif
1384 SgStatementPtrList::iterator i = statementList.begin();
1385
1386 while (i != statementList.end() && return_value == false)
1387 {
1388 SgStatement* statement = *i;
1389 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1390
1391 if (statement_file_id == scope_file_id)
1392 {
1393 return_value = true;
1394 }
1395
1396 i++;
1397 }
1398 }
1399
1400 return return_value;
1401 }
1402
1403
1404namespace
1405{
1406 template <class SageDecl>
1407 std::string genericGetName(SageDecl* dcl)
1408 {
1409 ROSE_ASSERT(dcl);
1410 return dcl->get_name();
1411 }
1412}
1413
1414
1415
1416
1417string
1419 {
1420 string name = "undefined_name";
1421
1422 ROSE_ASSERT(directive != NULL);
1423
1424 name = directive->class_name();
1425
1426#if 1
1427 // I don't think we need this code now!
1428 switch (directive->variantT())
1429 {
1430 // Separate out these cases...
1431 case V_SgIncludeDirectiveStatement:
1432 case V_SgDefineDirectiveStatement:
1433 case V_SgUndefDirectiveStatement:
1434 case V_SgIfdefDirectiveStatement:
1435 case V_SgIfndefDirectiveStatement:
1436 case V_SgDeadIfDirectiveStatement:
1437 case V_SgIfDirectiveStatement:
1438 case V_SgElseDirectiveStatement:
1439 case V_SgElseifDirectiveStatement:
1440 case V_SgLineDirectiveStatement:
1441 case V_SgWarningDirectiveStatement:
1442 case V_SgErrorDirectiveStatement:
1443 case V_SgEmptyDirectiveStatement:
1444 {
1445 name = directive->class_name();
1446 break;
1447 }
1448
1449 // case ClinkageDeclarationStatement:
1450 case V_SgClinkageStartStatement:
1451 case V_SgClinkageEndStatement:
1452 {
1453 name = directive->class_name();
1454 break;
1455 }
1456
1457 case V_SgFortranIncludeLine:
1458 {
1459 name = directive->class_name();
1460 break;
1461 }
1462
1463 default:
1464 // name = "default name (default case reached: not handled)";
1465 printf ("Warning: default case reached in SageInterface::get_name ( const SgC_PreprocessorDirectiveStatement* directive ), directive = %p = %s \n",
1466 directive,directive->class_name().c_str());
1467 ROSE_ABORT();
1468#if 0 // [Robb Matzke 2021-03-24]: unreachable
1469 name = "directive_default_name_case_reached_not_handled";
1470 break;
1471#endif
1472 }
1473#endif
1474
1475 return name;
1476 }
1477
1478string
1480 {
1481 string name = "undefined_name";
1482
1483 ROSE_ASSERT(declaration != NULL);
1484
1485 // DQ (11/23/2008): Handle the case of a Cpp directive...
1486 const SgC_PreprocessorDirectiveStatement* directive = isSgC_PreprocessorDirectiveStatement(declaration);
1487 if (directive != NULL)
1488 {
1489 return SageInterface::get_name (directive);
1490 }
1491
1492 switch (declaration->variantT())
1493 {
1494 case V_SgTemplateMemberFunctionDeclaration:
1495 name = isSgTemplateMemberFunctionDeclaration(declaration)->get_name().str();
1496 break;
1497
1498 case V_SgTemplateFunctionDeclaration:
1499 name = isSgTemplateFunctionDeclaration(declaration)->get_name().str();
1500 break;
1501
1502 case V_SgTemplateClassDeclaration:
1503 name = isSgTemplateClassDeclaration(declaration)->get_name().str();
1504 break;
1505
1506 case V_SgTemplateDeclaration:
1507 name = isSgTemplateDeclaration(declaration)->get_name().str();
1508 break;
1509
1510 case V_SgTemplateInstantiationDecl:
1511 name = isSgTemplateInstantiationDecl(declaration)->get_templateName().str();
1512 break;
1513
1514 case V_SgClassDeclaration:
1515 case V_SgDerivedTypeStatement:
1516 case V_SgJovialTableStatement:
1517 name = isSgClassDeclaration(declaration)->get_name().str();
1518 break;
1519
1520 // Rasmussen (8/2/2019): Added SgJovialDefineDeclaration and SgJovialDirectiveStatement
1521 // I'm not sure class_name() is correct. Probably get_name() should be fixed.
1522 case V_SgJovialDefineDeclaration:
1523 case V_SgJovialDirectiveStatement:
1524 case V_SgJovialCompoolStatement:
1525 name = "__" + declaration->class_name() + "_";
1526 name += StringUtility::numberToString(declaration);
1527 break;
1528
1529 case V_SgJovialLabelDeclaration:
1530 name = isSgJovialLabelDeclaration(declaration)->get_label();
1531 break;
1532
1533 case V_SgEnumDeclaration:
1534 name = isSgEnumDeclaration(declaration)->get_name().str();
1535 break;
1536
1537 // DQ (11/5/2014): Adding support for template typedef declarations (C++11 feature).
1538 case V_SgTemplateInstantiationTypedefDeclaration:
1539 // DQ (11/3/2014): Adding support for template typedef declarations (C++11 feature).
1540 case V_SgTemplateTypedefDeclaration:
1541 case V_SgTypedefDeclaration:
1542 name = isSgTypedefDeclaration(declaration)->get_name().str();
1543 break;
1544
1545 case V_SgFunctionDeclaration:
1546 case V_SgProgramHeaderStatement:
1547 case V_SgProcedureHeaderStatement:
1548 case V_SgMemberFunctionDeclaration:
1549 case V_SgTemplateInstantiationFunctionDecl:
1550 case V_SgTemplateInstantiationMemberFunctionDecl:
1551 case V_SgAdaFunctionRenamingDecl:
1552 case V_SgAdaEntryDecl:
1553 name = isSgFunctionDeclaration(declaration)->get_name().str();
1554 break;
1555
1556 case V_SgNamespaceDeclarationStatement:
1557 name = isSgNamespaceDeclarationStatement(declaration)->get_name().str();
1558 break;
1559
1560 // DQ (2/12/2006): Added support to get name of SgFunctionParameterList
1561 case V_SgFunctionParameterList:
1562 {
1563 // Parents should be set prior to calling these functions (if not we might have to implement that case)
1564 ROSE_ASSERT(declaration->get_parent() != NULL);
1565
1566 if (SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration->get_parent()))
1567 {
1568 name = get_name(functionDeclaration);
1569 }
1570 else if (SgScopeStatement* scopeStmt = isSgScopeStatement(declaration->get_parent()))
1571 {
1572 name = get_name(scopeStmt);
1573 }
1574 else ROSE_ABORT();
1575
1576 name += "_parameter_list_";
1577 break;
1578 }
1579
1580 // DQ (2/10/2012): Added support for template variable declarations (using base class support).
1581 case V_SgTemplateVariableDeclaration:
1582 case V_SgTemplateVariableInstantiation:
1583
1584 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1585 case V_SgVariableDeclaration:
1586 {
1587 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1588 // because we use this mechanism to generate names for unnamed structs and enums).
1589 name = "_variable_declaration_";
1590 const SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declaration);
1591 ROSE_ASSERT(variableDeclaration != NULL);
1592 SgInitializedNamePtrList::const_iterator i = variableDeclaration->get_variables().begin();
1593
1594 // Make sure that we have at least one variable in the list
1595 ROSE_ASSERT(i != variableDeclaration->get_variables().end());
1596 do {
1597 // name += string(" ") + string((*i)->get_name().str());
1598 name += string((*i)->get_name().str());
1599 i++;
1600 }
1601 while (i != variableDeclaration->get_variables().end());
1602 break;
1603 }
1604
1605
1606 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1607 case V_SgVariableDefinition:
1608 {
1609 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1610 // because we use this mechanism to generate names for unnamed structs and enums).
1611 name = "_variable_definition_";
1612 const SgVariableDefinition* variableDefinition = isSgVariableDefinition(declaration);
1613 ROSE_ASSERT(variableDefinition != NULL);
1614
1615 // define this in terms of the associated SgInitializedName
1616 ROSE_ASSERT(variableDefinition->get_vardefn() != NULL);
1617 name += get_name(variableDefinition->get_vardefn());
1618 break;
1619 }
1620
1621 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
1622 case V_SgPragmaDeclaration:
1623 {
1624 name = "_pragma_declaration_";
1625 const SgPragmaDeclaration* pragmaDeclaration = isSgPragmaDeclaration(declaration);
1626 ROSE_ASSERT(pragmaDeclaration != NULL);
1627 ROSE_ASSERT(pragmaDeclaration->get_pragma() != NULL);
1628 name += get_name(pragmaDeclaration->get_pragma());
1629 break;
1630 }
1631
1632 // DQ (4/15/2007): Implemented case for using directive statement (forgot this case)
1633 case V_SgUsingDirectiveStatement:
1634 {
1635 name = "_using_directive_statement_";
1636 const SgUsingDirectiveStatement* usingDeclaration = isSgUsingDirectiveStatement(declaration);
1637 ROSE_ASSERT(usingDeclaration != NULL);
1638 ROSE_ASSERT(usingDeclaration->get_namespaceDeclaration() != NULL);
1639 name += get_name(usingDeclaration->get_namespaceDeclaration());
1640 break;
1641 }
1642
1643 // DQ (6/20/2007): Added new case!
1644 case V_SgNamespaceAliasDeclarationStatement:
1645 {
1646 name = "_namespace_alias_directive_statement_";
1647 const SgNamespaceAliasDeclarationStatement* namespaceAliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
1648 ROSE_ASSERT(namespaceAliasDeclaration != NULL);
1649 ROSE_ASSERT(namespaceAliasDeclaration->get_name().is_null() == false);
1650 name += namespaceAliasDeclaration->get_name();
1651 break;
1652 }
1653
1654 // DQ (6/20/2007): Added new case!
1655 case V_SgUsingDeclarationStatement:
1656 {
1657 name = "_using_declaration_statement_";
1658 const SgUsingDeclarationStatement* usingDeclaration = isSgUsingDeclarationStatement(declaration);
1659 ROSE_ASSERT(usingDeclaration != NULL);
1660 if (usingDeclaration->get_declaration() != NULL)
1661 {
1662 name += get_name(usingDeclaration->get_declaration());
1663 }
1664 else
1665 {
1666 ROSE_ASSERT(usingDeclaration->get_initializedName() != NULL);
1667 name += get_name(usingDeclaration->get_initializedName());
1668 }
1669 break;
1670 }
1671
1672 // DQ (6/20/2007): Added new case!
1673 case V_SgTemplateInstantiationDirectiveStatement:
1674 {
1675 name = "_template_instantiation_directive_statement_";
1676 ROSE_ASSERT(declaration != NULL);
1677 const SgTemplateInstantiationDirectiveStatement* templateInstantiationDirective = isSgTemplateInstantiationDirectiveStatement(declaration);
1678 ROSE_ASSERT(templateInstantiationDirective != NULL);
1679 ROSE_ASSERT(templateInstantiationDirective->get_declaration() != NULL);
1680#if 0
1681 printf ("declaration->get_declaration() = %p = %s \n",templateInstantiationDirective->get_declaration(),templateInstantiationDirective->get_declaration()->class_name().c_str());
1682#endif
1683 name += get_name(templateInstantiationDirective->get_declaration());
1684 break;
1685 }
1686
1687 case V_SgCtorInitializerList:
1688 {
1689 name = "_ctor_list_";
1690 const SgCtorInitializerList* ctorDeclaration = isSgCtorInitializerList(declaration);
1691 ROSE_ASSERT(ctorDeclaration != NULL);
1692 ROSE_ASSERT(ctorDeclaration->get_parent() != NULL);
1693 name += get_name(ctorDeclaration->get_parent());
1694 break;
1695 }
1696
1697 // DQ (8/9/2007): Added case for SgAsmStmt
1698 case V_SgAsmStmt:
1699 {
1700 name = "_asm_stmt_";
1701 const SgAsmStmt* asmStatement = isSgAsmStmt(declaration);
1702 ROSE_ASSERT(asmStatement != NULL);
1703 ROSE_ASSERT(asmStatement->get_parent() != NULL);
1704 name += StringUtility::numberToString(const_cast<SgAsmStmt*>(asmStatement));
1705 break;
1706 }
1707
1708 // DQ (8/22/2007): Added case for SgImplicitStatement
1709 case V_SgImplicitStatement:
1710 {
1711 name = "_fortran_implicit_";
1712 const SgImplicitStatement* implicitStatement = isSgImplicitStatement(declaration);
1713 ROSE_ASSERT(implicitStatement != NULL);
1714 ROSE_ASSERT(implicitStatement->get_parent() != NULL);
1715 name += StringUtility::numberToString(const_cast<SgImplicitStatement*>(implicitStatement));
1716 break;
1717 }
1718
1719 // DQ (8/22/2007): Added case for SgNamelistStatement
1720 case V_SgNamelistStatement:
1721 {
1722 name = "_fortran_namelist_";
1723 const SgNamelistStatement* namelistStatement = isSgNamelistStatement(declaration);
1724 ROSE_ASSERT(namelistStatement != NULL);
1725 ROSE_ASSERT(namelistStatement->get_parent() != NULL);
1726 name += StringUtility::numberToString(const_cast<SgNamelistStatement*>(namelistStatement));
1727 break;
1728 }
1729
1730 // DQ (11/21/2007): Added case for SgEquivalenceStatement
1731 case V_SgEquivalenceStatement:
1732 {
1733 name = "_fortran_equivalence_";
1734 const SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(declaration);
1735 ROSE_ASSERT(equivalenceStatement != NULL);
1736 ROSE_ASSERT(equivalenceStatement->get_parent() != NULL);
1737 name += StringUtility::numberToString(const_cast<SgEquivalenceStatement*>(equivalenceStatement));
1738 break;
1739 }
1740
1741
1742 // DQ (11/21/2007): Added case for SgCommonBlock
1743 case V_SgCommonBlock:
1744 {
1745 name = "_fortran_common_block_";
1746 const SgCommonBlock* commonBlockStatement = isSgCommonBlock(declaration);
1747 ROSE_ASSERT(commonBlockStatement != NULL);
1748 ROSE_ASSERT(commonBlockStatement->get_parent() != NULL);
1749 name += StringUtility::numberToString(const_cast<SgCommonBlock*>(commonBlockStatement));
1750 break;
1751 }
1752
1753 // DQ (11/21/2007): Added case for SgImportStatement
1754 case V_SgImportStatement:
1755 {
1756 name = "_fortran_import_stmt_";
1757 const SgImportStatement* importStatement = isSgImportStatement(declaration);
1758 ROSE_ASSERT(importStatement != NULL);
1759 ROSE_ASSERT(importStatement->get_parent() != NULL);
1760 name += StringUtility::numberToString(const_cast<SgImportStatement*>(importStatement));
1761 break;
1762 }
1763
1764 // DQ (11/21/2007): Added case for SgFormatStatement
1765 case V_SgFormatStatement:
1766 {
1767 name = "_fortran_format_stmt_";
1768 const SgFormatStatement* formatStatement = isSgFormatStatement(declaration);
1769 ROSE_ASSERT(formatStatement != NULL);
1770 ROSE_ASSERT(formatStatement->get_parent() != NULL);
1771 name += StringUtility::numberToString(const_cast<SgFormatStatement*>(formatStatement));
1772 break;
1773 }
1774
1775 // DQ (12/27/2007): Added case for SgModuleStatement
1776 case V_SgModuleStatement:
1777 {
1778 name = "_fortran_module_stmt_";
1779 const SgModuleStatement* moduleStatement = isSgModuleStatement(declaration);
1780 ROSE_ASSERT(moduleStatement != NULL);
1781 ROSE_ASSERT(moduleStatement->get_parent() != NULL);
1782 name += StringUtility::numberToString(const_cast<SgModuleStatement*>(moduleStatement));
1783 break;
1784 }
1785
1786 // DQ (12/27/2007): Added case for SgUseStatement
1787 case V_SgUseStatement:
1788 {
1789 name = "_fortran_use_stmt_";
1790 const SgUseStatement* useStatement = isSgUseStatement(declaration);
1791 ROSE_ASSERT(useStatement != NULL);
1792 ROSE_ASSERT(useStatement->get_parent() != NULL);
1793 name += StringUtility::numberToString(const_cast<SgUseStatement*>(useStatement));
1794 break;
1795 }
1796
1797 // DQ (12/28/2007): Added case for SgContainsStatement
1798 case V_SgContainsStatement:
1799 {
1800 name = "_fortran_contains_stmt_";
1801 const SgContainsStatement* containsStatement = isSgContainsStatement(declaration);
1802 ROSE_ASSERT(containsStatement != NULL);
1803 ROSE_ASSERT(containsStatement->get_parent() != NULL);
1804 name += StringUtility::numberToString(const_cast<SgContainsStatement*>(containsStatement));
1805 break;
1806 }
1807
1808 // DQ (1/20/2008): Added case for SgEntryStatement
1809 case V_SgEntryStatement:
1810 {
1811 name = "_fortran_entry_stmt_";
1812 const SgEntryStatement* entryStatement = isSgEntryStatement(declaration);
1813 ROSE_ASSERT(entryStatement != NULL);
1814 ROSE_ASSERT(entryStatement->get_parent() != NULL);
1815 name += StringUtility::numberToString(const_cast<SgEntryStatement*>(entryStatement));
1816 break;
1817 }
1818
1819 // DQ (1/23/2008): Added case for SgAttributeSpecificationStatement
1820 case V_SgAttributeSpecificationStatement:
1821 {
1822 name = "_fortran_attribute_specification_stmt_";
1823 const SgAttributeSpecificationStatement* statement = isSgAttributeSpecificationStatement(declaration);
1824 ROSE_ASSERT(statement != NULL);
1825 ROSE_ASSERT(statement->get_parent() != NULL);
1827 break;
1828 }
1829
1830 case V_SgInterfaceStatement:
1831 {
1832 name = "_fortran_interface_stmt_";
1833 const SgInterfaceStatement* statement = isSgInterfaceStatement(declaration);
1834 ROSE_ASSERT(statement != NULL);
1835 ROSE_ASSERT(statement->get_parent() != NULL);
1836 name += StringUtility::numberToString(const_cast<SgInterfaceStatement*>(statement));
1837 break;
1838 }
1839
1840 case V_SgFortranIncludeLine:
1841 {
1842 name = "_fortran_include_line_stmt_";
1843 const SgFortranIncludeLine* statement = isSgFortranIncludeLine(declaration);
1844 ROSE_ASSERT(statement != NULL);
1845 ROSE_ASSERT(statement->get_parent() != NULL);
1846 name += StringUtility::numberToString(const_cast<SgFortranIncludeLine*>(statement));
1847 break;
1848 }
1849
1850 // DQ (4/16/2011): Added Java import statment support.
1851 case V_SgJavaImportStatement:
1852 {
1853 name = "_java_import_stmt_";
1854 const SgJavaImportStatement* statement = isSgJavaImportStatement(declaration);
1855 ROSE_ASSERT(statement != NULL);
1856 ROSE_ASSERT(statement->get_parent() != NULL);
1857 name += StringUtility::numberToString(const_cast<SgJavaImportStatement*>(statement));
1858 break;
1859 }
1860
1861 case V_SgJavaPackageDeclaration:
1862 {
1863 name = "_java_package_declaration_";
1864 const SgJavaPackageDeclaration* package_declaration = isSgJavaPackageDeclaration(declaration);
1865 ROSE_ASSERT(package_declaration != NULL);
1866 ROSE_ASSERT(package_declaration->get_parent() != NULL);
1867 name += StringUtility::numberToString(const_cast<SgJavaPackageDeclaration*>(package_declaration));
1868 break;
1869 }
1870
1871 case V_SgJavaPackageStatement:
1872 {
1873 name = "_java_package_stmt_";
1874 const SgJavaPackageStatement* statement = isSgJavaPackageStatement(declaration);
1875 ROSE_ASSERT(statement != NULL);
1876 ROSE_ASSERT(statement->get_parent() != NULL);
1877 name += StringUtility::numberToString(const_cast<SgJavaPackageStatement*>(statement));
1878 break;
1879 }
1880
1881 // DQ (1/21/2018): Added case for C++11 SgStaticAssertionDeclaration
1882 case V_SgStaticAssertionDeclaration:
1883 {
1884 name = "_static_assertion_declaration_stmt_";
1885 const SgStaticAssertionDeclaration* statement = isSgStaticAssertionDeclaration(declaration);
1886 ROSE_ASSERT(statement != NULL);
1887 ROSE_ASSERT(statement->get_parent() != NULL);
1888 name += StringUtility::numberToString(const_cast<SgStaticAssertionDeclaration*>(statement));
1889 break;
1890 }
1891
1892 case V_SgNonrealDecl:
1893 {
1894 const SgNonrealDecl * nrdecl = isSgNonrealDecl(declaration);
1895 ROSE_ASSERT(nrdecl != NULL);
1896 name = nrdecl->get_name();
1897 break;
1898 }
1899
1900 // DQ (3/26/2019): Adding support for new declaration.
1901 case V_SgEmptyDeclaration:
1902 {
1903 const SgEmptyDeclaration * emptyDeclaration = isSgEmptyDeclaration(declaration);
1904 ROSE_ASSERT(emptyDeclaration != NULL);
1905 name = string("emptyDeclaration") + StringUtility::numberToString(const_cast<SgDeclarationStatement*>(declaration));
1906 break;
1907 }
1908
1909 case V_SgAdaPackageSpecDecl:
1910 {
1911 name = genericGetName(isSgAdaPackageSpecDecl(declaration));
1912 break;
1913 }
1914
1915 case V_SgAdaPackageBodyDecl:
1916 {
1917 name = genericGetName(isSgAdaPackageBodyDecl(declaration));
1918 break;
1919 }
1920
1921 case V_SgAdaFormalTypeDecl:
1922 {
1923 name = genericGetName(isSgAdaFormalTypeDecl(declaration));
1924 break;
1925 }
1926
1927 case V_SgAdaGenericDecl:
1928 {
1929 // need to look inside the declaration wrapped by the generic.
1930 const SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(declaration);
1931 name = get_name(gendcl->get_declaration());
1932 break;
1933#if OBSOLETE_CODE
1934 if (isSgFunctionDeclaration(dcl->get_declaration())) {
1935 name = "_ada_generic_decl_" + genericGetName(isSgFunctionDeclaration(dcl->get_declaration()));
1936 break;
1937 }
1938 if (isSgAdaPackageSpecDecl(dcl->get_declaration())) {
1939 name = "_ada_generic_decl_" + genericGetName(isSgAdaPackageSpecDecl(dcl->get_declaration()));
1940 break;
1941 }
1942
1943 // something malformed in the tree if we get here
1944 ROSE_ABORT();
1945 break;
1946#endif /* OBSOLETE_CODE */
1947 }
1948
1949 case V_SgAdaDiscriminatedTypeDecl:
1950 {
1951 const SgAdaDiscriminatedTypeDecl* dcl = isSgAdaDiscriminatedTypeDecl(declaration);
1952 ROSE_ASSERT(dcl);
1953
1954 if (const SgDeclarationStatement* discrDcl = dcl->get_discriminatedDecl())
1955 {
1956 name = get_name(discrDcl);
1957 }
1958 else
1959 {
1960 name = "_incomplete_Ada_discriminated_type_";
1961 }
1962
1963 break;
1964 }
1965
1966 case V_SgAdaVariantDecl:
1967 {
1968 name = "_ada_variant_decl_";
1969 break;
1970 }
1971
1972 case V_SgAdaAttributeClause:
1973 {
1974 name = "_ada_attribute_clause_";
1975 break;
1976 }
1977
1978 case V_SgAdaRepresentationClause:
1979 {
1980 name = "_ada_representation_clause_";
1981 break;
1982 }
1983
1984 case V_SgAdaEnumRepresentationClause:
1985 {
1986 name = "_ada_enum_representation_clause_";
1987 break;
1988 }
1989
1990 case V_SgAdaComponentClause:
1991 {
1992 name = "_ada_component_clause_";
1993 break;
1994 }
1995
1996 case V_SgAdaTaskTypeDecl:
1997 {
1998 name = genericGetName(isSgAdaTaskTypeDecl(declaration));
1999 break;
2000 }
2001
2002 case V_SgAdaProtectedTypeDecl:
2003 {
2004 name = genericGetName(isSgAdaProtectedTypeDecl(declaration));
2005 break;
2006 }
2007
2008 case V_SgAdaTaskBodyDecl:
2009 {
2010 name = genericGetName(isSgAdaTaskBodyDecl(declaration));
2011 break;
2012 }
2013
2014 case V_SgAdaProtectedBodyDecl:
2015 {
2016 name = genericGetName(isSgAdaProtectedBodyDecl(declaration));
2017 break;
2018 }
2019
2020 case V_SgAdaRenamingDecl:
2021 {
2022 name = genericGetName(isSgAdaRenamingDecl(declaration));
2023 break;
2024 }
2025
2026 case V_SgAdaTaskSpecDecl:
2027 {
2028 name = genericGetName(isSgAdaTaskSpecDecl(declaration));
2029 break;
2030 }
2031
2032 case V_SgAdaProtectedSpecDecl:
2033 {
2034 name = genericGetName(isSgAdaProtectedSpecDecl(declaration));
2035 break;
2036 }
2037
2038 case V_SgAdaGenericInstanceDecl:
2039 {
2040 name = genericGetName(isSgAdaGenericInstanceDecl(declaration));
2041 break;
2042 }
2043
2044 case V_SgAdaFormalPackageDecl:
2045 {
2046 name = genericGetName(isSgAdaFormalPackageDecl(declaration));
2047 break;
2048 }
2049
2050 case V_SgAdaParameterList:
2051 {
2052 const SgAdaParameterList* plst = isSgAdaParameterList(declaration);
2053 ROSE_ASSERT(plst);
2054
2055 name = std::accumulate( plst->get_parameters().begin(), plst->get_parameters().end(),
2056 std::string{"_ada_parameter_list_"},
2057 [](std::string n, SgDeclarationStatement* rhs) -> std::string
2058 {
2059 n += SageInterface::get_name(rhs);
2060 return n;
2061 }
2062 );
2063 break;
2064 }
2065
2066 // Note that the case for SgVariableDeclaration is not implemented
2067 default:
2068 printf ("Warning: default case reached in SageInterface::get_name ( const SgDeclarationStatement* declaration ), declaration = %p = %s \n",
2069 declaration,declaration->class_name().c_str());
2070 ROSE_ABORT();
2071 }
2072
2073 return name;
2074 }
2075
2076string
2078 {
2079 string name = "undefined_name";
2080
2081 ROSE_ASSERT(scope != NULL);
2082
2083 switch (scope->variantT())
2084 {
2085 // DQ (6/11/2011): Added support for new template IR nodes.
2086 case V_SgTemplateClassDefinition:
2087 name = get_name(isSgTemplateClassDefinition(scope)->get_declaration());
2088 break;
2089
2090 case V_SgClassDefinition:
2091 case V_SgTemplateInstantiationDefn:
2092 name = get_name(isSgClassDefinition(scope)->get_declaration());
2093 break;
2094
2095 // DQ (9/8/2012): Added missing case for SgTemplateFunctionDefinition.
2096 case V_SgTemplateFunctionDefinition:
2097 case V_SgFunctionDefinition:
2098 name = get_name(isSgFunctionDefinition(scope)->get_declaration());
2099 break;
2100
2101 case V_SgNamespaceDefinitionStatement:
2102 name = get_name(isSgNamespaceDefinitionStatement(scope)->get_namespaceDeclaration());
2103 break;
2104 case V_SgJavaLabelStatement:
2105 name = (isSgJavaLabelStatement(scope)->get_label()).getString();
2106 break;
2107
2108 // DQ (7/18/2017): Added support for the new declaration scope.
2109 case V_SgDeclarationScope:
2110
2111 // DQ (11/30/2007): Added more fortran support.
2112 case V_SgAssociateStatement:
2113 case V_SgJavaForEachStatement:
2114
2115 case V_SgFunctionParameterScope:
2116 case V_SgAdaPackageSpec:
2117 case V_SgAdaPackageBody:
2118 case V_SgAdaTaskSpec:
2119 case V_SgAdaTaskBody:
2120 case V_SgAdaProtectedSpec:
2121 case V_SgAdaProtectedBody:
2122 case V_SgAdaGenericDefn:
2123 case V_SgAdaAcceptStmt:
2124 case V_SgJovialForThenStatement: //Rasmussen: Jovial for statement
2125 case V_SgMatlabForStatement: //SK: Matlab for statement
2126 case V_SgBasicBlock:
2127 case V_SgCatchOptionStmt:
2128 case V_SgDoWhileStmt:
2129 case V_SgForStatement:
2130 case V_SgGlobal:
2131 case V_SgIfStmt:
2132 case V_SgSwitchStatement:
2133 case V_SgWhileStmt:
2134 case V_SgFortranDo:
2135 case V_SgForAllStatement:
2136 case V_SgRangeBasedForStatement:
2137 name = StringUtility::numberToString(const_cast<SgScopeStatement*>(scope));
2138 break;
2139
2140 default:
2141 printf ("Error: undefined case (SgScopeStatement) in SageInterface::get_name(): node = %s \n",scope->class_name().c_str());
2142 ROSE_ABORT();
2143 }
2144
2145 return name;
2146 }
2147
2148string
2150 {
2151 string name = "undefined_name";
2152
2153 ROSE_ASSERT(stmt != NULL);
2154
2155 const SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
2156 if (declaration != NULL)
2157 {
2158 name = get_name(declaration);
2159 }
2160 else
2161 {
2162 const SgScopeStatement* scope = isSgScopeStatement(stmt);
2163 if (scope != NULL)
2164 {
2165 name = get_name(scope);
2166 }
2167 else
2168 {
2169 // DQ (10/25/2007): This is better since it names the SgLabelStatement case
2170 switch (stmt->variantT())
2171 {
2172#if 0
2173 case V_SgBreakStmt:
2174 case V_SgCaseOptionStmt:
2175 case V_SgCatchStatementSeq:
2176 case V_SgClinkageStartStatement:
2177 case V_SgContinueStmt:
2178 case V_SgDefaultOptionStmt:
2179 case V_SgExprStmt:
2180 case V_SgForInitStmt:
2181 case V_SgFunctionTypeTable:
2182 case V_SgGotoStatement:
2183 case V_SgReturnStmt:
2184 case V_SgSpawnStmt:
2185 case V_SgTryStmt:
2186 name = stmt->class_name();
2187 break;
2188#endif
2189 case V_SgLabelStatement:
2190 {
2191 const SgLabelStatement* labelStatement = isSgLabelStatement(stmt);
2192 name = labelStatement->get_label().str();
2193 break;
2194 }
2195
2196 default:
2197 {
2198 // printf ("Default reached in switch \n");
2199 // name = "default name";
2200 name = stmt->class_name();
2201 break;
2202 }
2203 }
2204 }
2205 }
2206
2207 return name;
2208 }
2209
2210string
2212 {
2213 // This function is useful for debugging
2214 // This is the most general case of a function to return a name for an IR node.
2215 ROSE_ASSERT(node != NULL);
2216
2217 string name = "undefined_name";
2218
2219 ROSE_ASSERT(node != NULL);
2220
2221 switch (node->variantT())
2222 {
2223 case V_SgInitializedName:
2224 {
2225 const SgInitializedName* initializedName = isSgInitializedName(node);
2226 if (initializedName != NULL)
2227 {
2228 name = initializedName->get_name().str();
2229 }
2230 break;
2231 }
2232#if 1
2233 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
2234 case V_SgPragma:
2235 {
2236 name = "_pragma_string_";
2237 const SgPragma* pragma = isSgPragma(node);
2238 ROSE_ASSERT(pragma != NULL);
2239 name += pragma->get_pragma();
2240 break;
2241 }
2242#endif
2243
2244 // DQ (5/31/2007): Implemented case for SgProject
2245 case V_SgProject:
2246 {
2247 name = "_project_";
2248 break;
2249 }
2250
2251 // DQ (5/31/2007): Implemented case for SgFile
2252 // case V_SgFile:
2253 case V_SgSourceFile:
2254#ifdef ROSE_ENABLE_BINARY_ANALYSIS
2255 case V_SgBinaryComposite:
2256#endif
2257 {
2258 name = "_file_";
2259
2260 // DQ (3/1/2009): Added support to include the file name.
2261 const SgFile* file = isSgFile(node);
2262 ROSE_ASSERT(file != NULL);
2263
2264 name += file->getFileName();
2265 break;
2266 }
2267
2268 // DQ (5/31/2007): Implemented case for SgSymbolTable
2269 case V_SgSymbolTable:
2270 {
2271 name = "_symbol_table_";
2272 break;
2273 }
2274
2275 // DQ (5/31/2007): Implemented case for SgStorageModifier
2276 case V_SgStorageModifier:
2277 {
2278 name = "_storage_modifier_";
2279 break;
2280 }
2281
2282
2283 // DQ (5/31/2007): Implemented case for Sg_File_Info
2284 case V_Sg_File_Info:
2285 {
2286 name = "_file_info_";
2287 break;
2288 }
2289
2290 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2291 case V_SgTemplateArgument:
2292 {
2293 name = "_template_argument_";
2294 const SgTemplateArgument* templateArgument = isSgTemplateArgument(node);
2295 ROSE_ASSERT(templateArgument != NULL);
2296 switch(templateArgument->get_argumentType())
2297 {
2299 {
2300 SgType* t = templateArgument->get_type();
2301 ROSE_ASSERT(t != NULL);
2302 name += get_name(t);
2303 break;
2304 }
2305
2307 {
2308 SgExpression* t = templateArgument->get_expression();
2309
2310 // DQ (8/11/2013): Adding support for including an initializedName instead of an expression (for template parameters used as expressions).
2311 // ROSE_ASSERT(t != NULL);
2312 // name += get_name(t);
2313 if (t != NULL)
2314 {
2315 ROSE_ASSERT(templateArgument->get_initializedName() == NULL);
2316 name += get_name(t);
2317 }
2318 else
2319 {
2320 ROSE_ASSERT(t == NULL);
2321 SgInitializedName* initializedName = templateArgument->get_initializedName();
2322 ROSE_ASSERT(initializedName != NULL);
2323
2324 name += get_name(initializedName);
2325 }
2326 break;
2327 }
2328
2330 {
2331 // SgTemplateDeclaration* t = templateArgument->get_templateDeclaration();
2332 SgDeclarationStatement* t = templateArgument->get_templateDeclaration();
2333 ROSE_ASSERT(t != NULL);
2334 name += get_name(t);
2335 break;
2336 }
2337
2338 default:
2339 {
2340 printf ("Error: default case reached in switch on templateArgument->get_argumentType() \n");
2341 ROSE_ABORT();
2342 }
2343 }
2344 break;
2345 }
2346
2347
2348 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2349 case V_SgTypeModifier:
2350 {
2351 const SgTypeModifier* typeModifier = isSgTypeModifier(node);
2352 ROSE_ASSERT(typeModifier != NULL);
2353 name = "_type_modifier_" + typeModifier->displayString();
2354 break;
2355 }
2356
2357 // DQ (11/19/2007): Implemented case for SgNameGroup
2358 case V_SgNameGroup:
2359 {
2360 const SgNameGroup* nameGroup = isSgNameGroup(node);
2361 ROSE_ASSERT(nameGroup != NULL);
2362 name = "_name_group_" + nameGroup->get_group_name();
2363 break;
2364 }
2365
2366 // DQ (11/20/2007): Implemented case for Fortran data statement support
2367 case V_SgDataStatementGroup:
2368 {
2369 const SgDataStatementGroup* dataGroup = isSgDataStatementGroup(node);
2370 ROSE_ASSERT(dataGroup != NULL);
2371 name = "_data_statement_group_";
2372 break;
2373 }
2374
2375 // DQ (11/20/2007): Implemented case for Fortran data statement support
2376 case V_SgDataStatementObject:
2377 {
2378 const SgDataStatementObject* dataObject = isSgDataStatementObject(node);
2379 ROSE_ASSERT(dataObject != NULL);
2380 name = "_data_statement_object_";
2381 break;
2382 }
2383
2384 // DQ (11/20/2007): Implemented case for Fortran data statement support
2385 case V_SgDataStatementValue:
2386 {
2387 const SgDataStatementValue* dataValue = isSgDataStatementValue(node);
2388 ROSE_ASSERT(dataValue != NULL);
2389 name = "_data_statement_value_";
2390 break;
2391 }
2392
2393 // DQ (11/19/2007): Implemented case for SgCommonBlock
2394 case V_SgCommonBlockObject:
2395 {
2396 const SgCommonBlockObject* commonBlockObject = isSgCommonBlockObject(node);
2397 ROSE_ASSERT(commonBlockObject != NULL);
2398 name = "_common_block_object_" + commonBlockObject->get_block_name();
2399 break;
2400 }
2401
2402 // DQ (12/23/2007): Added support for repeat_specification
2403 case V_SgFormatItem:
2404 {
2405 const SgFormatItem* formatItem = isSgFormatItem(node);
2406 ROSE_ASSERT(formatItem != NULL);
2407 name = "_format_item_";
2408 break;
2409 }
2410
2411 // DQ (12/23/2007): Added support for repeat_specification
2412 case V_SgFormatItemList:
2413 {
2414 const SgFormatItemList* formatItemList = isSgFormatItemList(node);
2415 ROSE_ASSERT(formatItemList != NULL);
2416 name = "_format_item_list_";
2417 break;
2418 }
2419
2420 // DQ (12/23/2007): Added support for repeat_specification
2421 case V_SgRenamePair:
2422 {
2423 const SgRenamePair* renamePair = isSgRenamePair(node);
2424 ROSE_ASSERT(renamePair != NULL);
2425 name = renamePair->get_local_name() + "__" + renamePair->get_use_name() + "_rename_pair_";
2426 break;
2427 }
2428
2429 // DQ (12/2/2010): Implemented case for SgName
2430 case V_SgName:
2431 {
2432 const SgName* name_node = isSgName(node);
2433 ROSE_ASSERT(name_node != NULL);
2434 name = "_name_" + name_node->getString();
2435 break;
2436 }
2437
2438 // DQ (8/8/2013): Implemented case for SgTemplateParameter
2439 case V_SgTemplateParameter:
2440 {
2441 const SgTemplateParameter* template_parameter_node = isSgTemplateParameter(node);
2442 ROSE_ASSERT(template_parameter_node != NULL);
2443 name = "_template_parameter_";
2444
2445 switch(template_parameter_node->get_parameterType())
2446 {
2448 {
2449 name += "type_parameter_";
2450 break;
2451 }
2452
2454 {
2455 name += "nontype_parameter_";
2456#if 1
2457 name += template_parameter_node->unparseToString();
2458#else
2459 if (template_parameter_node->get_expression() != NULL)
2460 {
2461 name += template_parameter_node->get_expression()->unparseToString();
2462 }
2463 else
2464 {
2465 ROSE_ASSERT(template_parameter_node->get_initializedName() != NULL);
2466
2467 // DQ (8/8/2013): This does not handle the case of "template <void (foo::*M)()> void test() {}"
2468 // since what is unparsed is: "_template_parameter_nontype_parameter_M"
2469 // instead of a string to represent what is in "void (foo::*M)()"
2470 // and differentiate it from: "int foo::*M" in: "template <void (foo::*M)()> void test() {}"
2471 name += template_parameter_node->get_initializedName()->unparseToString();
2472 }
2473#endif
2474 break;
2475 }
2476
2478 {
2479 name += "template_parameter_";
2480 break;
2481 }
2482
2483 default:
2484 {
2485 printf ("Error: default reached \n");
2486 ROSE_ABORT();
2487 }
2488 }
2489 break;
2490 }
2491
2492 // DQ (1/21/2019): Implemented case for SgBaseClass
2493 case V_SgBaseClass:
2494 {
2495 const SgBaseClass* base_class_node = isSgBaseClass(node);
2496 ROSE_ASSERT(base_class_node != NULL);
2497 ROSE_ASSERT(base_class_node->get_base_class() != NULL);
2498
2499 // Add the access modifier to the output.
2500 string access = "";
2501 const SgBaseClassModifier* baseClassModifier = base_class_node->get_baseClassModifier();
2502 ROSE_ASSERT(baseClassModifier != NULL);
2503 access = baseClassModifier->displayString();
2504
2505 name = "_base_class_" + access + "_" + get_name(base_class_node->get_base_class());
2506 break;
2507 }
2508
2509 default:
2510 {
2511 printf ("Default reached in switch for SgSupport IR node = %s \n",node->class_name().c_str());
2512 name = "default name";
2513 // ROSE_ASSERT(false);
2514 break;
2515 }
2516 }
2517
2518 return name;
2519 }
2520
2521
2522string
2524 {
2525 // This function is useful for debugging
2526 // This is the most general case of a function to return a name for an IR node.
2527 ROSE_ASSERT(symbol != NULL);
2528
2529 string aliasSymbolPrefix = "";
2530 if (isSgAliasSymbol(symbol) != NULL)
2531 {
2532 aliasSymbolPrefix = "_ALIAS";
2533 }
2534
2535 // printf ("In SageInterface::get_name(): symbol->get_symbol_basis() = %p = %s \n",symbol->get_symbol_basis(),symbol->get_symbol_basis()->class_name().c_str());
2536 // printf ("In SageInterface::get_name(): symbol->get_declaration() = %p = %s \n",symbol->get_declaration(),symbol->get_declaration()->class_name().c_str());
2537
2538 // This is a call to the "get_name()" virtual function
2539 return symbol->get_name() + aliasSymbolPrefix + "_symbol_";
2540 }
2541
2542string
2544 {
2545 // This function is useful for debugging
2546 // This is the most general case of a function to return a name for an IR node.
2547 ROSE_ASSERT(type != NULL);
2548
2549 string returnName;
2550
2551 const SgNamedType* namedType = isSgNamedType(type);
2552 if (namedType != NULL)
2553 {
2554 returnName = "named_type_";
2555 returnName = namedType->get_name().getString();
2556 }
2557 else
2558 {
2559 switch(type->variantT())
2560 {
2561 case V_SgPointerType:
2562 {
2563 const SgPointerType* pointerType = isSgPointerType(type);
2564 returnName = "pointer_to_";
2565 returnName += get_name(pointerType->get_base_type());
2566 break;
2567 }
2568
2569 case V_SgReferenceType:
2570 {
2571 const SgReferenceType* referenceType = isSgReferenceType(type);
2572 returnName = "reference_to_";
2573 returnName += get_name(referenceType->get_base_type());
2574 break;
2575 }
2576
2577 case V_SgArrayType:
2578 {
2579 const SgArrayType* arrayType = isSgArrayType(type);
2580 returnName = "array_of_";
2581 returnName += get_name(arrayType->get_base_type());
2582 break;
2583 }
2584
2585 case V_SgModifierType:
2586 {
2587 const SgModifierType* modifierType = isSgModifierType(type);
2588 returnName = get_name(&(modifierType->get_typeModifier()));
2589 returnName += get_name(modifierType->get_base_type());
2590 break;
2591 }
2592
2593 // DQ (8/26/2012): Added case to support template declaration work.
2594 case V_SgTemplateType:
2595 {
2596 const SgTemplateType* templateType = isSgTemplateType(type);
2597 returnName = "templateType_";
2598 returnName += templateType->get_name();
2599 break;
2600 }
2601
2602 default:
2603 {
2604 returnName = type->class_name();
2605 }
2606 }
2607 }
2608
2609 return returnName;
2610 }
2611
2612string
2614 {
2615 string name = "undefined_name";
2616
2617 // ROSE_ASSERT(expr != NULL);
2618 switch(expr->variantT())
2619 {
2620 case V_SgVarRefExp:
2621 {
2622 const SgVarRefExp* varRef = isSgVarRefExp(expr);
2623 name = "var_ref_of_";
2624 ROSE_ASSERT(varRef != NULL);
2625 ROSE_ASSERT(varRef->get_symbol() != NULL);
2626 name += varRef->get_symbol()->get_name();
2627 break;
2628 }
2629
2630 // DQ (2/2/2011): Added case to support fortran use of label references in alternate return parameters.
2631 case V_SgLabelRefExp:
2632 {
2633 const SgLabelRefExp* labelRef = isSgLabelRefExp(expr);
2634 name = "label_ref_of_";
2635 ROSE_ASSERT(labelRef != NULL);
2636 ROSE_ASSERT(labelRef->get_symbol() != NULL);
2637 name += labelRef->get_symbol()->get_name();
2638 break;
2639 }
2640
2641 case V_SgPntrArrRefExp:
2642 {
2643 const SgPntrArrRefExp* arrayRef = isSgPntrArrRefExp(expr);
2644 name = "array_ref_of_";
2645 name += get_name(arrayRef->get_lhs_operand());
2646 name += "_at_";
2647 name += get_name(arrayRef->get_rhs_operand());
2648 break;
2649 }
2650
2651 case V_SgFunctionCallExp:
2652 {
2653 const SgFunctionCallExp* functionCall = isSgFunctionCallExp(expr);
2654 name = "function_call_";
2655 name += get_name(functionCall->get_function());
2656 break;
2657 }
2658
2659 case V_SgFunctionRefExp:
2660 {
2661 const SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(expr);
2662 name = "function_ref_";
2663 name += functionRefExp->get_symbol()->get_name();
2664 break;
2665 }
2666
2667 // DQ (4/19/2013): Added support for SgMemberFunctionRefExp.
2668 case V_SgMemberFunctionRefExp:
2669 {
2670 const SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(expr);
2671 name = "member_function_ref_";
2672 name += memberFunctionRefExp->get_symbol()->get_name();
2673 break;
2674 }
2675
2676 case V_SgIntVal:
2677 {
2678 const SgIntVal* valueExp = isSgIntVal(expr);
2679 name = "integer_value_exp_";
2680 name += StringUtility::numberToString(valueExp->get_value());
2681 break;
2682 }
2683
2684 case V_SgStringVal:
2685 {
2686 const SgStringVal* valueExp = isSgStringVal(expr);
2687 name = "string_value_exp_";
2688 name += valueExp->get_value();
2689 break;
2690 }
2691
2692 case V_SgSubscriptExpression:
2693 {
2694 const SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(expr);
2695 name = "subscript_exp_";
2696 // name += StringUtility::numberToString(subscriptExpression->get_lowerBound());
2697 name += get_name(subscriptExpression->get_lowerBound());
2698 name += "_";
2699 // name += StringUtility::numberToString(subscriptExpression->get_upperBound());
2700 name += get_name(subscriptExpression->get_upperBound());
2701 name += "_";
2702 // name += StringUtility::numberToString(subscriptExpression->get_stride());
2703 name += get_name(subscriptExpression->get_stride());
2704 break;
2705 }
2706
2707 case V_SgNullExpression:
2708 {
2709 name = "null_expression";
2710 break;
2711 }
2712
2713 // DQ (1/17/2011): Added support for SgExprListExp (to support debugging).
2714 case V_SgExprListExp:
2715 {
2716 const SgExprListExp* exprListExp = isSgExprListExp(expr);
2717 name = "expr_list_exp_";
2718 for (size_t i = 0; i < exprListExp->get_expressions().size(); i++)
2719 {
2720 name += get_name(exprListExp->get_expressions()[i]);
2721 }
2722 break;
2723 }
2724
2725 // DQ (1/31/2011): Added to support Fortran debugging.
2726 case V_SgActualArgumentExpression:
2727 {
2728 const SgActualArgumentExpression* actualArgExp = isSgActualArgumentExpression(expr);
2729 name = "actual_arg_exp_name_";
2730 name += actualArgExp->get_argument_name();
2731 name = "_exp_";
2732 name += get_name(actualArgExp->get_expression());
2733 break;
2734 }
2735
2736 // DQ (7/25/2012): Added support for new template IR nodes.
2737 case V_SgTemplateParameterVal:
2738 {
2739 const SgTemplateParameterVal* valueExp = isSgTemplateParameterVal(expr);
2740 name = "template_parameter_value_expression_number_";
2741 // name += valueExp->get_value();
2742 // name += get_name(valueExp);
2743 name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2744 break;
2745 }
2746
2747 // DQ (4/19/2013): Added support for SgDotExp.
2748 case V_SgDotExp:
2749 {
2750 const SgDotExp* dotExp = isSgDotExp(expr);
2751 ROSE_ASSERT(dotExp != NULL);
2752
2753 name = "_dot_exp_lhs_";
2754 name += get_name(dotExp->get_lhs_operand());
2755 name += "_dot_exp_rhs_";
2756 name += get_name(dotExp->get_rhs_operand());
2757 // name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2758 break;
2759 }
2760
2761 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2762 case V_SgLambdaExp:
2763 {
2764 const SgLambdaExp* lambdaExp = isSgLambdaExp(expr);
2765 ROSE_ASSERT (lambdaExp != NULL);
2766 name = "lambda_expression_";
2767 break;
2768 }
2769
2770 // DQ (1/3/2020): Added support for SgThisExp.
2771 case V_SgThisExp:
2772 {
2773 const SgThisExp* thisExp = isSgThisExp(expr);
2774 ROSE_ASSERT(thisExp != NULL);
2775
2776 name = "_this_exp_for_";
2777
2778 SgClassSymbol* classSymbol = thisExp->get_class_symbol();
2779 ROSE_ASSERT(classSymbol != NULL);
2780 // name += get_name(classSymbol->get_name());
2781 // string class_name = classSymbol->get_name();
2782 // name += class_name;
2783 name += classSymbol->get_name();
2784 break;
2785 }
2786
2787 default:
2788 {
2789 // Nothing to do for other IR nodes
2790#if 0
2791 // DQ (7/25/2012): Make this an error.
2792 printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2793 ROSE_ABORT();
2794#endif
2795 // DQ (4/8/2010): define something specific to this function to make debugging more clear.
2796 // printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2797 // name = "undefined_expression_name";
2798 name = expr->class_name() + "_undef_name";
2799 break;
2800 }
2801 }
2802
2803 return name;
2804 }
2805
2806string
2808 {
2809 // This function is useful for debugging
2810 // This is the most general case of a function to return a name for an IR node.
2811 ROSE_ASSERT(node != NULL);
2812
2813 string returnName;
2814
2815 switch(node->variantT())
2816 {
2817 case V_SgRenamePair:
2818 {
2819 const SgRenamePair* n = isSgRenamePair(node);
2820 returnName = "rename_pair_";
2821 returnName += n->get_local_name().str();
2822 returnName += "_from_";
2823 returnName += n->get_use_name().str();
2824 break;
2825 }
2826
2827 case V_SgInitializedName:
2828 {
2829 const SgInitializedName* n = isSgInitializedName(node);
2830 ROSE_ASSERT (n != NULL);
2831 returnName = "initialized_name_";
2832 returnName += n->get_name().str();
2833 break;
2834 }
2835
2836 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2837 case V_SgLambdaCapture:
2838 {
2839 const SgLambdaCapture* n = isSgLambdaCapture(node);
2840 ROSE_ASSERT (n != NULL);
2841 returnName = "lambda_capture_";
2842 // returnName += n->get_name().str();
2843 break;
2844 }
2845
2846#if 0
2847 case V_SgInterfaceBody:
2848 {
2849 const SgInterfaceBody* n = isSgInterfaceBody(node);
2850 returnName = "interface_body";
2851 break;
2852 }
2853#endif
2854 default:
2855 {
2856 returnName = node->class_name();
2857 }
2858 }
2859
2860 return returnName;
2861 }
2862
2863string
2865 {
2866 // This function is useful for debugging
2867 // This is the most general case of a function to return a name for an IR node.
2868 // Later this function will handle expressions, etc.
2869
2870 string name = "undefined_name";
2871
2872 ROSE_ASSERT(node != NULL);
2873
2874 const SgLocatedNode* locatedNode = isSgLocatedNode(node);
2875 if (locatedNode != NULL)
2876 {
2877 const SgStatement* statement = isSgStatement(node);
2878 if (statement != NULL)
2879 {
2880 name = get_name(statement);
2881 }
2882 else
2883 {
2884 const SgExpression* expression = isSgExpression(node);
2885 if (expression != NULL)
2886 {
2887 name = get_name(expression);
2888 }
2889 else
2890 {
2891 const SgLocatedNodeSupport* locatedNodeSupport = isSgLocatedNodeSupport(node);
2892 if (locatedNodeSupport != NULL)
2893 {
2894 name = get_name(locatedNodeSupport);
2895 }
2896 else
2897 {
2898 const SgToken* token = isSgToken(node);
2899 if (token != NULL)
2900 {
2901 name = get_name(token);
2902 }
2903 else
2904 {
2905 printf ("Unknown SgLocatedNode = %p = %s \n",node,node->class_name().c_str());
2906 ROSE_ABORT();
2907 }
2908 }
2909 }
2910 }
2911 }
2912 else
2913 {
2914 const SgSupport* supportNode = isSgSupport(node);
2915 if (supportNode != NULL)
2916 {
2917 name = get_name(supportNode);
2918 }
2919 else
2920 {
2921 // DQ (9/21/2005): I think this is good enough for the more general case (for now)
2922 const SgSymbol* symbol = isSgSymbol(node);
2923 if (symbol != NULL)
2924 {
2925 name = get_name(symbol);
2926 }
2927 else
2928 {
2929 // DQ (8/7/2007): Added support to get names of types (usefult for SgNamedType objects).
2930 const SgType* type = isSgType(node);
2931 if (type != NULL)
2932 {
2933 name = get_name(type);
2934 }
2935 else
2936 {
2937 name = node->class_name();
2938 }
2939 }
2940 }
2941 }
2942
2943 return name;
2944 }
2945
2946
2947string
2949 {
2950 // This function is useful for debugging
2951 string name = "undefined_name";
2952
2953 ROSE_ASSERT(token != NULL);
2954 name = token->get_lexeme_string();
2955
2956 // Handle special cases
2957 if (name == " ")
2958 name = "<space>";
2959 else if (name == "\n")
2960 name = "<eol>";
2961 else if (name == "\t")
2962 name = "<tab>";
2963
2964 return name;
2965 }
2966
2967
2968void
2975
2976
2977string
2979 {
2980 // DQ (3/20/2016): Adding support for generating a unique name from a declaration that
2981 // can be used as an identifier. This functionality is used in the DSL infrastructure
2982 // support (refactored to this location in ROSE). The point of this mechanism is that
2983 // unlike mangled names that are compressed in a way that allows them to only be used
2984 // within a single translation unit, names generated by this function can be used across
2985 // multiple translation units. These names are also easier to interprete in debugging
2986 // (since they explicitly contain the scope, function name, and coding to interprete
2987 // function overloading.
2988
2989 // At present it only supports class declarations, and function declarations (all others
2990 // are trapped as errors).
2991
2992 // Name collision testing, it might be that this should be external to this function.
2993 // static std::map<std::string,int> dsl_attribute_name_collision_map;
2994 // static std::map<std::string,int> local_name_collision_map;
2995
2996 string s;
2997
2998 // string scope = SageInterface::get_name(classDeclaration->get_scope());
2999 string scope = isSgGlobal(declaration->get_scope()) == NULL ? SageInterface::get_name(declaration->get_scope()) : "global";
3000
3001 switch (declaration->variantT())
3002 {
3003 case V_SgClassDeclaration:
3004 case V_SgTemplateClassDeclaration:
3005 // case V_SgTemplateInstantiationDecl:
3006 {
3007 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declaration);
3008 ROSE_ASSERT(classDeclaration != NULL);
3009
3010 string type_name = classDeclaration->get_name();
3011#if 0
3012 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case class or template type: type_name = %s \n",type_name.c_str());
3013#endif
3014 string className = string("scope_") + scope + "_type_name_" + type_name;
3015#if 0
3016 printf ("classDeclaration->get_scope() = %p = %s scope = %s \n",classDeclaration->get_scope(),classDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3017#endif
3018 s = className;
3019 break;
3020 }
3021
3022 // DQ (3/29/2016): Seperate out the case of the SgTemplateInstantiationDecl.
3023 case V_SgTemplateInstantiationDecl:
3024 {
3025 SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(declaration);
3026 ROSE_ASSERT(templateInstantiationDeclaration != NULL);
3027
3028 // Note that we can't use the mangled name because they might not be unique across multiple translation units if seperately compiled).
3029 // string type_name = templateInstantiationDeclaration->get_name();
3030 // string type_name = templateInstantiationDeclaration->get_mangled_name();
3031 // string type_name = templateInstantiationDeclaration->get_templateName();
3032 string type_name = templateInstantiationDeclaration->get_name();
3033#if 0
3034 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgTemplateInstantiationDecl: type_name = %s \n",type_name.c_str());
3035#endif
3036 string className = string("scope_") + scope + "_type_name_" + type_name;
3037
3038 // Note that trimSpaces is defined in the name mangling support.
3039 // string compressedClassName = trimSpaces(className);
3040 // string compressedClassName = SageInterface::get_name(templateInstantiationDeclaration);
3041 // ROSE_UTIL_API std::string copyEdit(const std::string& inputString, const std::string & oldToken, const std::string & newToken);
3042
3043 // We need to turn this template instatiation name into a name that can be used as a C++ identifier.
3044 string compressedClassName = StringUtility::copyEdit(className," ","");
3045 compressedClassName = StringUtility::copyEdit(compressedClassName,"<","_abs_");
3046 compressedClassName = StringUtility::copyEdit(compressedClassName,">","_abe_");
3047 compressedClassName = StringUtility::copyEdit(compressedClassName,",","_comma_");
3048 compressedClassName = StringUtility::copyEdit(compressedClassName,"*","_star_");
3049 compressedClassName = StringUtility::copyEdit(compressedClassName,"&","_ref_");
3050#if 0
3051 printf ("className = %s compressedClassName = %s \n",className.c_str(),compressedClassName.c_str());
3052#endif
3053#if 0
3054 printf ("templateInstantiationDeclaration->get_scope() = %p = %s scope = %s \n",
3055 templateInstantiationDeclaration->get_scope(),templateInstantiationDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3056#endif
3057 // s = className;
3058 s = compressedClassName;
3059#if 0
3060 printf ("Exiting as a test! \n");
3061 ROSE_ABORT();
3062#endif
3063 break;
3064 }
3065
3066 case V_SgFunctionDeclaration:
3067 case V_SgTemplateFunctionDeclaration:
3068 case V_SgTemplateInstantiationFunctionDecl:
3069 {
3070 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration);
3071 ROSE_ASSERT(functionDeclaration != NULL);
3072#if 0
3073 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgFunctionDeclaration: not implemented \n");
3074#endif
3075 // We might at some point want the qualified name.
3076 string original_name = functionDeclaration->get_name();
3077
3078 string function_name_part = mangleFunctionName(original_name,"return_type");
3079 string function_name = string("scope_") + scope + "_function_name_" + function_name_part;
3080
3081 // DQ (3/16/2016): Detect name collisions so that we can
3082 // std::map<std::string,int> dsl_attribute_name_collision_map;
3083 if (local_name_collision_map.find(function_name) == local_name_collision_map.end())
3084 {
3085 local_name_collision_map.insert(pair<string,int>(function_name,0));
3086 }
3087 else
3088 {
3089 local_name_collision_map[function_name]++;
3090
3091 int count = local_name_collision_map[function_name];
3092#if 0
3093 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3094#endif
3095 function_name += StringUtility::numberToString(count);
3096 }
3097
3098 s = function_name;
3099#if 0
3100 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgFunctionDeclaration: Exiting as a test! \n");
3101 ROSE_ABORT();
3102#endif
3103 break;
3104 }
3105
3106 case V_SgMemberFunctionDeclaration:
3107 case V_SgTemplateMemberFunctionDeclaration:
3108 case V_SgTemplateInstantiationMemberFunctionDecl:
3109 {
3110 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(declaration);
3111 ROSE_ASSERT(memberFunctionDeclaration != NULL);
3112#if 0
3113 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgMemberFunctionDeclaration: not implemented \n");
3114#endif
3115 // We might at some point want the qualified name.
3116 string original_name = memberFunctionDeclaration->get_name();
3117
3118 // string member_function_name = memberFunctionDeclaration->get_mangled_name();
3119 // string member_function_name = memberFunctionDeclaration->get_qualified_name();
3120 // string member_function_name = SageInterface::get_name(memberFunctionDeclaration);
3121 // string member_function_scope = SageInterface::get_name(memberFunctionDeclaration->get_scope());
3122 string member_function_name_part = mangleFunctionName(original_name,"return_type");
3123 // string member_function_name = string("scope_") + member_function_scope + "_function_name_" + member_function_name_part;
3124 string member_function_name = string("scope_") + scope + "_member_function_name_" + member_function_name_part;
3125
3126 // DQ (3/16/2016): Detect name collisions so that we can
3127 // std::map<std::string,int> dsl_attribute_name_collision_map;
3128 if (local_name_collision_map.find(member_function_name) == local_name_collision_map.end())
3129 {
3130 local_name_collision_map.insert(pair<string,int>(member_function_name,0));
3131 }
3132 else
3133 {
3134 local_name_collision_map[member_function_name]++;
3135
3136 int count = local_name_collision_map[member_function_name];
3137#if 0
3138 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3139#endif
3140 member_function_name += StringUtility::numberToString(count);
3141 }
3142
3143 s = member_function_name;
3144#if 0
3145 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgMemberFunctionDeclaration: Exiting as a test! \n");
3146 ROSE_ABORT();
3147#endif
3148 break;
3149 }
3150
3151 default:
3152 {
3153 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Unsupported declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3154// ROSE_ASSERT(false);
3155 }
3156 }
3157
3158#if 0
3159 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3160#endif
3161#if 0
3162 if (s != "")
3163 {
3164 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3165 }
3166#endif
3167
3168#if 0
3169 printf ("Exiting as a test! \n");
3170 ROSE_ABORT();
3171#endif
3172
3173 return s;
3174 }
3175
3176// Generate unique name for use as a class name for the generated attribute classes.
3177// std::string AttributeGeneratorTraversal::generateUniqueNameForUseAsIdentifier ( SgDeclarationStatement* declaration )
3178// std::string AttributeGeneratorTraversal::generateUniqueName ( SgDeclarationStatement* declaration )
3179std::string
3181 {
3182 // DQ (3/21/2016): The support for unique name generation for use across translation
3183 // units is not refactored into the SageInterface.
3184 // string s = SageInterface::generateUniqueNameForUseAsIdentifier(declaration);
3185 string s;
3186
3187#if 0
3188 printf ("In generateUniqueNameForUseAsIdentifier(): evaluating declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3189#endif
3190
3191 ROSE_ASSERT(local_node_to_name_map.empty() == false);
3192 ROSE_ASSERT(local_name_to_node_map.empty() == false);
3193
3195 {
3197 }
3198 else
3199 {
3200 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3201 if (definingDeclaration != NULL)
3202 {
3203#if 0
3204 printf ("In generateUniqueName(): Using the defining declaration = %p since %p was not in the map \n",definingDeclaration,declaration);
3205#endif
3206 // s = generateUniqueName(definingDeclaration);
3207 s = generateUniqueNameForUseAsIdentifier_support(definingDeclaration);
3208 }
3209 else
3210 {
3211 // Note that builtin functions will not have a defining declaration.
3212 printf ("Warning: defining declaration not in SageInterface::local_node_to_name_map: declaration = %p = %s using name = %s \n",
3213 declaration,declaration->class_name().c_str(),SageInterface::get_name(declaration).c_str());
3214 // ROSE_ASSERT(false);
3215
3216 // If there is no defining declaration then go ahead and use the non-defining one.
3217 // s = SageInterface::get_name(declaration);
3218 SgDeclarationStatement* nondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3219 ROSE_ASSERT(nondefiningDeclaration != NULL);
3220 s = generateUniqueNameForUseAsIdentifier_support(nondefiningDeclaration);
3221 }
3222 }
3223
3224#if 0
3225 printf ("Exiting as a test! \n");
3226 ROSE_ABORT();
3227#endif
3228
3229 return s;
3230 }
3231
3232
3233void
3235 {
3236 ROSE_ASSERT(astNode != NULL);
3237
3238 ROSE_ASSERT(local_name_collision_map.empty() == true);
3239 ROSE_ASSERT(local_name_to_node_map.empty() == true);
3240 ROSE_ASSERT(local_node_to_name_map.empty() == true);
3241
3242 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
3243 class UniqueNameTraversal : public AstSimpleProcessing
3244 {
3245 public:
3246 void visit (SgNode* node)
3247 {
3248 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
3249 if (decl != NULL)
3250 {
3251 SgClassDeclaration* classDeclaration = isSgClassDeclaration(decl);
3252 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(decl);
3253 if (classDeclaration != NULL || functionDeclaration != NULL)
3254 {
3256 local_name_to_node_map.insert(pair<string,SgNode*>(s,decl));
3257 local_node_to_name_map.insert(pair<SgNode*,string>(decl,s));
3258 }
3259 }
3260 }
3261 };
3262
3263 // Now buid the traveral object and call the traversal (preorder) on the function definition.
3264 UniqueNameTraversal traversal;
3265 traversal.traverse(astNode, preorder);
3266 }
3267
3268
3269
3272 {
3273 SgMemberFunctionDeclaration* defaultConstructor = NULL;
3274
3275 ROSE_ASSERT(classDeclaration != NULL);
3276 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3277 ROSE_ASSERT(definingDeclaration != NULL);
3278 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3279
3280 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3281 // would be associated with a class declaration but no definition would exist).
3282 if (definingClassDeclaration != NULL)
3283 {
3284 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3285 ROSE_ASSERT(classDefinition != NULL);
3286
3287 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3288 while ( i != classDefinition->get_members().end() )
3289 {
3290 // Check the parent pointer to make sure it is properly set
3291 ROSE_ASSERT( (*i)->get_parent() != NULL);
3292 ROSE_ASSERT( (*i)->get_parent() == classDefinition);
3293
3294 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3295 if (memberFunction != NULL)
3296 {
3297 // printf ("memberFunction = %p = %s \n",memberFunction,memberFunction->get_name().str());
3298 if ( memberFunction->get_specialFunctionModifier().isConstructor() == true )
3299 defaultConstructor = memberFunction;
3300 }
3301
3302 // iterate through the class members
3303 i++;
3304 }
3305 }
3306
3307 // This should be true for the specific case that we are currently debugging!
3308 // ROSE_ASSERT(defaultConstructor != NULL);
3309
3310 return defaultConstructor;
3311 }
3312
3315 {
3316 SgMemberFunctionDeclaration* defaultDestructor = NULL;
3317
3318 ROSE_ASSERT(classDeclaration != NULL);
3319 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3320 if (definingDeclaration != NULL)
3321 {
3322 ROSE_ASSERT(definingDeclaration != NULL);
3323 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3324
3325 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3326 // would be associated with a class declaration but no definition would exist).
3327 if (definingClassDeclaration != NULL)
3328 {
3329 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3330 ROSE_ASSERT(classDefinition != NULL);
3331
3332 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3333 while ( i != classDefinition->get_members().end() )
3334 {
3335 // Check the parent pointer to make sure it is properly set
3336 SgNode* i_parent = (*i)->get_parent();
3337 ROSE_ASSERT(i_parent != NULL);
3338
3339 // DQ (11/1/2005): Note that a template instantiation can have a parent which is the
3340 // variable which forced it's instantiation. Since it does not really exist in the
3341 // source code explicitly (it is compiler generated) this is as reasonable as anything else.
3342 if ( i_parent != classDefinition )
3343 {
3344 printf ("Error: (*i)->get_parent() = %p = %s \n",i_parent,i_parent->class_name().c_str());
3345 printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),(*i)->unparseToString().c_str());
3346 (*i)->get_file_info()->display("Called from SageInterface::getDefaultDestructor: debug");
3347 }
3348 ROSE_ASSERT( i_parent == classDefinition);
3349
3350 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3351 if (memberFunction != NULL)
3352 {
3353 if ( memberFunction->get_specialFunctionModifier().isDestructor() == true )
3354 defaultDestructor = memberFunction;
3355 }
3356
3357 // iterate through the class members
3358 i++;
3359 }
3360 }
3361 }
3362
3363 return defaultDestructor;
3364 }
3365
3366
3367
3368bool
3369SageInterface::addDefaultConstructorIfRequired ( SgClassType* classType, int physical_file_id /* = Sg_File_Info::TRANSFORMATION_FILE_ID */ )
3370 {
3371 // DQ (11/9/2020): Added function to support adding a default constructor definition to a class
3372 // if it does not have a default constructor, but has any other constructor that would prevent
3373 // a compiler generated default constructor from being generated by the compiler.
3374
3375#define DEBUG_ADD_DEFAULT_CONSTRUCTOR 0
3376
3377 // Note the physical_file_id is so that it can be marked to be unparsed when header file unparsing is active.
3378
3379 ASSERT_not_null(classType);
3380
3381 bool returnValue = false;
3382
3383 // To setup this transformation we need to see if there is a default constructor in the associated class.
3384 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
3385 ROSE_ASSERT(classDeclaration != NULL);
3386 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(classDeclaration->get_definingDeclaration());
3387 ROSE_ASSERT(definingClassDeclaration != NULL);
3388 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3389 ROSE_ASSERT(classDefinition != NULL);
3390
3391 SgDeclarationStatementPtrList & declarationList = classDefinition->get_members();
3392
3393 bool foundConstructor = false;
3394 bool foundDefaultConstructor = false;
3395
3396#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3397 printf ("In addDefaultConstructorIfRequired(): class name = %s \n",classDeclaration->get_name().str());
3398#endif
3399
3400 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
3401 while (i != declarationList.end())
3402 {
3403 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(*i);
3404 if (memberFunctionDeclaration != NULL)
3405 {
3406 bool isConstructor = memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
3407 if (isConstructor == true)
3408 {
3409 foundConstructor = true;
3410
3411#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3412 printf ("Found a constructor! \n");
3413#endif
3414 SgFunctionParameterList* functionParameterList = memberFunctionDeclaration->get_parameterList();
3415 ROSE_ASSERT(functionParameterList != NULL);
3416
3417 // DQ (7/19/2021): Fixed to allow for previously found default constructor to be registered as found.
3418 // foundDefaultConstructor = (functionParameterList->get_args().size() == 0);
3419 foundDefaultConstructor = ((foundDefaultConstructor == true) || (functionParameterList->get_args().size() == 0));
3420
3421#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3422 if (foundDefaultConstructor == true)
3423 {
3424 printf ("Found a default constructor! \n");
3425 }
3426 else
3427 {
3428 printf ("This is not a default constructor: functionParameterList->get_args().size() = %zu \n",functionParameterList->get_args().size());
3429 }
3430#endif
3431 }
3432 else
3433 {
3434#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3435 printf ("This is not a constructor \n");
3436#endif
3437 }
3438 }
3439
3440 i++;
3441 }
3442
3443#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3444 printf ("foundConstructor = %s \n",foundConstructor ? "true" : "false");
3445 printf ("foundDefaultConstructor = %s \n",foundDefaultConstructor ? "true" : "false");
3446#endif
3447
3448 if (foundConstructor == true)
3449 {
3450 // Since there is at least one constructor, we can't rely on compiler generated constructors.
3451#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3452 printf ("Since there is at least one constructor, we can't rely on compiler generated constructors \n");
3453#endif
3454 if (foundDefaultConstructor == true)
3455 {
3456 // We can use the existing default constructor.
3457#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3458 printf ("We can use the existing default constructor (no need to build one) \n");
3459#endif
3460 }
3461 else
3462 {
3463 // We don't have a default constructor, so we need to build one explicitly, and insert it into the class definition.
3464
3465#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3466 printf ("########################################################### \n");
3467 printf ("Need to build a default constructor in the associated class \n");
3468#endif
3469 SgMemberFunctionDeclaration* constructorDeclaration = SageBuilder::buildDefaultConstructor(classType);
3470 ROSE_ASSERT(constructorDeclaration != NULL);
3471
3472#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3473 printf (" --- constructorDeclaration = %p = %s name = %s \n",constructorDeclaration,constructorDeclaration->class_name().c_str(),constructorDeclaration->get_name().str());
3474#endif
3475 ROSE_ASSERT (constructorDeclaration->get_declarationModifier().get_accessModifier().isPublic() == true);
3476
3477 classDefinition->prepend_statement(constructorDeclaration);
3478
3479 // constructorDeclaration->set_parent(classDefinition);
3480 ROSE_ASSERT(constructorDeclaration->get_parent() != NULL);
3481
3482 // int physical_file_id = variableDeclaration->get_startOfConstruct()->get_physical_file_id();
3483 markSubtreeToBeUnparsed(constructorDeclaration,physical_file_id);
3484
3485 returnValue = true;
3486#if 0
3487 constructorDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3488 constructorDeclaration->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3489
3490 // We also need to set the source position of the function definition, else the
3491 // function declaration will not be output.
3492 ROSE_ASSERT(constructorDeclaration->get_definition() != NULL);
3493 ROSE_ASSERT(constructorDeclaration->get_definition()->get_startOfConstruct() != NULL);
3494 ROSE_ASSERT(constructorDeclaration->get_definition()->get_endOfConstruct() != NULL);
3495 constructorDeclaration->get_definition()->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3496 constructorDeclaration->get_definition()->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3497#endif
3498
3499#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3500 printf ("DONE: Need to build a default constructor in the associated class \n");
3501 printf ("################################################################# \n");
3502#endif
3503#if 0
3504 printf ("Exiting as a test! \n");
3505 ROSE_ABORT();
3506#endif
3507 }
3508 }
3509 else
3510 {
3511 // No constructors found, so we don't need to add an explicit default constructor.
3512
3513#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3514 printf ("No constructors found, so we don't need to add an explicit default constructor \n");
3515#endif
3516 }
3517
3518#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3519 printf ("Leaving addDefaultConstructorIfRequired(): returnValue = %s \n",returnValue ? "true" : "false");
3520#endif
3521
3522 return returnValue;
3523 }
3524
3525
3526
3527
3528void
3530 {
3531 // DQ (6/27/2005): This function outputs the global table of function type symbols
3532 // it is built during the EDG/Sage translation phase, and it built initially with
3533 // the EDG names of all instantiated templates. At a later phase (incomplete at
3534 // the moment) the AST fixup rebuilds the table to use the modified template names
3535 // (that is mangled names built from the modified template names used in Sage III).
3536
3537 // DQ (1/31/2006): Modified to build all types in the memory pools
3538 // extern SgFunctionTypeTable Sgfunc_type_table;
3539 // Sgfunc_type_table.print_functypetable();
3540 ROSE_ASSERT(SgNode::get_globalFunctionTypeTable() != NULL);
3541 SgNode::get_globalFunctionTypeTable()->print_functypetable();
3542 }
3543
3544void
3546 {
3547 // This simplifies how the traversal is called!
3548 OutputLocalSymbolTables astTraversal;
3549
3550 // I think the default should be preorder so that the interfaces would be more uniform
3551 astTraversal.traverse(node,preorder);
3552 }
3553
3554void
3556 {
3557 // DQ (6/27/2005): Output the local symbol table from each scope.
3558 // printf ("node = %s \n",node->sage_class_name());
3559
3560#if 0
3561 printf ("Exiting as a test! \n");
3562 ROSE_ABORT();
3563#endif
3564
3565 SgScopeStatement* scope = isSgScopeStatement(node);
3566 if (scope != NULL)
3567 {
3568 // SgSymbolTable* symbolTable = scope->get_symbol_table();
3569 // ROSE_ASSERT(symbolTable != NULL);
3570
3571 printf ("Symbol Table from %p = %s at: \n",scope,scope->sage_class_name());
3572 scope->get_file_info()->display("Symbol Table Location (Called from SageInterface::OutputLocalSymbolTables::visit())");
3573 // symbolTable->print("Called from SageInterface::OutputLocalSymbolTables::visit()");
3574 scope->print_symboltable("Called from SageInterface::OutputLocalSymbolTables::visit()");
3575 }
3576 }
3577
3578#if 0
3579// DQ (8/28/2005): This is already a member function of the SgFunctionDeclaration
3580// (so that it can handle template functions and member functions)
3581
3582// DQ (8/27/2005):
3583bool
3584SageInterface::isTemplateMemberFunction( SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration )
3585 {
3586 // This function determines if the member function is associated with a template
3587 // or just a template class (where it is a normal non-template member function).
3588
3589 bool result = false;
3590
3591 result = memberFunctionDeclaration->isTemplateFunction();
3592
3593 return result;
3594 }
3595#endif
3596
3597// DQ (8/27/2005):
3598bool
3600 {
3601 // This function determines if the template declaration associated withthis member function instantiation is
3602 // defined in the class or outside of the class.
3603
3604 bool result = false;
3605
3606#if 0
3607 // Check if this is a template or non-template member function
3608 if (isTemplateMemberFunction(memberFunctionDeclaration) == true)
3609 {
3610 SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3611 printf ("templateDeclaration = %p parent of templateDeclaration = %p \n",templateDeclaration,templateDeclaration->get_parent());
3612
3613 // SgTemplateInstantiationDecl* classTemplateInstantiation = memberFunctionDeclaration->get_class_scope()->get_declaration();
3614 SgClassDeclaration* classDeclaration = memberFunctionDeclaration->get_class_scope()->get_declaration();
3615 ROSE_ASSERT(classDeclaration != NULL);
3616 SgTemplateInstantiationDecl* classTemplateInstantiation = isSgTemplateInstantiationDecl(classDeclaration);
3617
3618 if (classTemplateInstantiation != NULL)
3619 {
3620 SgTemplateDeclaration* classTemplateDeclaration = classTemplateInstantiation->get_templateDeclaration();
3621 if (classTemplateDeclaration != NULL && classTemplateDeclaration != templateDeclaration)
3622 {
3623 result = true;
3624 }
3625 }
3626 }
3627#endif
3628
3629 // Alternative approach
3630 // SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3631 SgDeclarationStatement* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3632// printf ("In templateDefinitionIsInClass(): templateDeclaration = %p parent of templateDeclaration = %p = %s \n",templateDeclaration,
3633// templateDeclaration->get_parent(),templateDeclaration->get_parent()->class_name().c_str());
3634
3635 if (templateDeclaration != NULL && templateDeclaration->get_parent() != NULL)
3636 {
3637 SgScopeStatement* parentScope = isSgScopeStatement(templateDeclaration->get_parent());
3638 if (isSgClassDefinition(parentScope) != NULL)
3639 {
3640 result = true;
3641 }
3642 }
3643
3644 return result;
3645 }
3646#if 0
3648generateUniqueDeclaration ( SgDeclarationStatement* declaration )
3649 {
3650 // DQ (10/11/2007): This is no longer used.
3651 printf ("Error: This is no longer used. \n");
3652 ROSE_ABORT();
3653
3654 // Get the defining or first non-defining declaration so that we can use it as a key to know
3655 // when we have found the same function. So we don't count a redundant forward declaration
3656 // found outside of the class as matching the first non-defining declaration or the defining
3657 // declaration in the class by mistake. All declarations share the same firstNondefining
3658 // declaration and defining declaration so either could be a key declaration, but there are
3659 // times when either one of then (but not both) can be NULL (function defined withouth forward
3660 // declaration or not defined at all).
3661 SgDeclarationStatement* firstNondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3662 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3663 SgDeclarationStatement* keyDeclaration = NULL;
3664 if (firstNondefiningDeclaration != NULL)
3665 keyDeclaration = firstNondefiningDeclaration;
3666 else
3667 keyDeclaration = definingDeclaration;
3668 ROSE_ASSERT(keyDeclaration != NULL);
3669
3670 return keyDeclaration;
3671 }
3672#endif
3675{
3676 string pragmaString = pragmaDeclaration->get_pragma()->get_pragma();
3677 istringstream istr(pragmaString);
3678 std::string key;
3679 istr >> key;
3680 return key;
3681}
3682
3684// TODO: move all Omp*statement under a parent SgOmpStatement
3686{
3687 ROSE_ASSERT (n != NULL);
3688 bool result = false;
3689 if (isSgOmpBarrierStatement(n)||
3690 isSgOmpBodyStatement(n)||
3691 isSgOmpDeclareSimdStatement(n) ||
3692 isSgOmpFlushStatement(n)||
3693 isSgOmpThreadprivateStatement(n)||
3694 isSgOmpTaskwaitStatement(n) )
3695 result = true;
3696
3697 return result;
3698
3699}
3700// DQ (8/28/2005):
3701bool
3703 {
3704 // This function looks for any other function that might overload the input function.
3705 // for member functions we only look in the scope where the member function is defined.
3706 // for non-member functions we look only in the scope where the function is declared.
3707
3708 // Note that there are scenarios where this approach of searching only these locations
3709 // might not catch an overloaded function.
3710 // * member functions:
3711 // - overloaded functions might be declared in base classes
3712 // * non-member functions:
3713 // - function declarations might be friend functions in classes
3714 // - functions might be declared in differen namespace definitions
3715 // (SgNamespaceDefinitionStatement), since a namespace in re-entrant
3716 // and can have many namespace declarations and definitions.
3717
3718 // bool result = false;
3719 int counter = 0;
3720
3721 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
3722 if (memberFunctionDeclaration != NULL)
3723 {
3724 // This is a member function declaration
3725
3726 // DQ (10/11/2007): Fix this to NOT use the generateUniqueDeclaration() function.
3727 // Generate a key to use for comparision (avoids false positives)
3728 // SgMemberFunctionDeclaration* keyDeclaration = isSgMemberFunctionDeclaration(generateUniqueDeclaration(functionDeclaration));
3729 // ROSE_ASSERT(keyDeclaration != NULL);
3730
3731 SgScopeStatement * scope = memberFunctionDeclaration->get_scope();
3732 ROSE_ASSERT(scope != NULL);
3733
3734 // TV (09/17/2018): ROSE-1378
3735 if (isSgDeclarationScope(scope)) {
3736 printf("TODO SageInterface::isOverloaded case when scope is SgDeclarationScope. See ROSE-1378.\n");
3737 return false;
3738 }
3739
3740 // Get the class definition
3741 SgClassDefinition* classDefinition =
3742 isSgClassDefinition(memberFunctionDeclaration->get_scope());
3743 ROSE_ASSERT(classDefinition != NULL);
3744
3745 // Get the class declaration associated with the class definition
3746 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classDefinition->get_declaration());
3747 ROSE_ASSERT(classDeclaration != NULL);
3748
3749 // Get the list of member declarations in the class
3750 SgDeclarationStatementPtrList & memberList = classDefinition->get_members();
3751#if 0
3752 // DQ (10/11/2007): Fix this function better by checking for more than one member function declaration in the class definition.
3753 printf (" memberList.size() = %" PRIuPTR " \n",memberList.size());
3754#endif
3755 for (SgDeclarationStatementPtrList::iterator i = memberList.begin(); i != memberList.end(); i++)
3756 {
3757#if 0
3758 printf (" counter = %d declaration = %p = %s \n",counter,*i,(*i)->class_name().c_str());
3759#endif
3760 SgMemberFunctionDeclaration* tempMemberFunction = isSgMemberFunctionDeclaration(*i);
3761 SgTemplateDeclaration* tempTemplateDeclaration = isSgTemplateDeclaration(*i);
3762
3763 // Member functions could be overloaded
3764 if (tempMemberFunction != NULL)
3765 {
3766#if 0
3767 // DQ (10/11/2007): This is a problem for where s member function prototype from outside the class is checked to be an ovverloaded function.
3768 // Check using the key declaration
3769 if ( keyDeclaration == generateUniqueDeclaration(tempMemberFunction) )
3770 {
3771#if 0
3772 printf ("Skipping the case of keyDeclaration == generateUniqueDeclaration(tempMemberFunction) = %p \n",keyDeclaration);
3773#endif
3774 continue;
3775 }
3776#endif
3777 ROSE_ASSERT(tempMemberFunction->get_name() != "");
3778#if 0
3779 printf (" tempMemberFunction = (name) %s = (qualified) %s \n",
3780 tempMemberFunction->get_name().str(),
3781 tempMemberFunction->get_qualified_name().str());
3782#endif
3783 if (tempMemberFunction->get_name() == memberFunctionDeclaration->get_name())
3784 {
3785#if 0
3786 printf (" Found a matching overloaded member function! \n");
3787#endif
3788 // result = true;
3789 counter++;
3790 }
3791 }
3792 else
3793 {
3794 // Or templates could be overloaded, but nothing else.
3795 if (tempTemplateDeclaration != NULL)
3796 {
3797 // If this is a template declaration, it could be a template
3798 // declaration for an overloaded member function of the same name.
3799#if 0
3800 // printf ("keyDeclaration->get_name() = %s \n",keyDeclaration->get_name().str());
3801 printf ("tempTemplateDeclaration->get_name() = %s \n",tempTemplateDeclaration->get_name().str());
3802#endif
3803 if (memberFunctionDeclaration->get_name() == tempTemplateDeclaration->get_name())
3804 {
3805#if 0
3806 printf (" Found a matching overloaded member function! \n");
3807#endif
3808 // result = true;
3809 counter++;
3810 }
3811 }
3812 else
3813 {
3814 // DQ (10/12/2007): Could friend functions defined in a class be overloaded? Need to check this!
3815 if (functionDeclaration->variantT() == V_SgFunctionDeclaration)
3816 {
3817 printf ("In SageInterface::isOverloaded(): could friend functions be overloaded in a class? \n");
3818 }
3819 }
3820 }
3821
3822 // If we have detected two, so we have an overloaded function.
3823 if (counter > 1)
3824 break;
3825 }
3826 }
3827 else
3828 {
3829 // This is a non-member function declaration
3830 printf ("In SageInterface::isOverloaded(): case of non-member function not yet implemented! \n");
3831 ROSE_ABORT();
3832 }
3833
3834 // DQ (10/11/2007): Fixup to use the counter and consider more than 1 function with the same name an overloaded member function.
3835 // This might be a problem for friend functions, so test this separately.
3836 // return result;
3837 return (counter > 1);
3838 }
3839
3840
3841
3842
3845 {
3846 // DQ (9/6/2005): This function builds a copy of the input function for the
3847 // construction of a forward declaration of the function. Required in the
3848 // instantiated functions definition is to be output as a specialization by ROSE.
3849 // Since the shallow copy mechanism will cause IR nodes to be shared, we have
3850 // to fix it up with deep copies of the parameter list and the CtorInitializerList.
3851
3852 ROSE_ASSERT(memberFunctionInstantiation != NULL);
3853
3854#if 0
3855 printf ("buildForwardFunctionDeclaration: Member function = %p = %s = definition = %p \n",
3856 memberFunctionInstantiation,
3857 memberFunctionInstantiation->get_name().str(),
3858 memberFunctionInstantiation->get_definition());
3859 memberFunctionInstantiation->get_file_info()->display("memberFunctionInstantiation: debug");
3860#endif
3861
3862 // This is a better implementation using a derived class from SgCopyHelp to control the
3863 // copying process (skipping the copy of any function definition). This is a variable
3864 // declaration with an explicitly declared class type.
3865 class NondefiningFunctionDeclarationCopyType : public SgCopyHelp
3866 {
3867 // DQ (9/26/2005): This class demonstrates the use of the copy mechanism
3868 // within Sage III (originally designed and implemented by Qing Yi).
3869 // One problem with it is that there is no context information permitted.
3870
3871 public:
3872 virtual SgNode *copyAst(const SgNode *n)
3873 {
3874 // If still NULL after switch then make the copy
3875 SgNode* returnValue = NULL;
3876
3877 switch(n->variantT())
3878 {
3879 // DQ (10/21/2007): Now that s bug is fixed in the SgDeclarationStatement::fixupCopy()
3880 // member function, I think we might not need this case.
3881
3882 // Don't copy the associated non-defining declaration when building a function prototype!
3883 case V_SgFunctionDeclaration:
3884 case V_SgMemberFunctionDeclaration:
3885 case V_SgTemplateInstantiationFunctionDecl:
3886 case V_SgTemplateInstantiationMemberFunctionDecl:
3887 {
3888 // printf ("Skip copying an associated non-defining declaration if it is present \n");
3889 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n);
3890 ROSE_ASSERT(functionDeclaration != NULL);
3891 if (functionDeclaration == functionDeclaration->get_definingDeclaration())
3892 {
3893 // This is the defining declaration (make a shallow copy)
3894 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the DEFINING declaration! \n");
3895 // return const_cast<SgNode *>(n);
3896 returnValue = const_cast<SgNode *>(n);
3897 }
3898 else
3899 {
3900 // This is the non-defining declaration where we want to make a deep copy.
3901 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the NONDEFINING declaration! \n");
3902 }
3903
3904 break;
3905 }
3906
3907 // Don't copy the function definitions (roughly the body of the function)
3908 case V_SgFunctionDefinition:
3909 {
3910 printf ("Skip copying the function definition if it is present \n");
3911 // return const_cast<SgNode *>(n);
3912 returnValue = const_cast<SgNode *>(n);
3913 break;
3914 }
3915
3916 default:
3917 {
3918 // Nothing to do here
3919 break;
3920 }
3921 }
3922
3923 // return n->copy(*this);
3924
3925 // If not set at this point then make the copy!
3926 if (returnValue == NULL)
3927 returnValue = n->copy(*this);
3928
3929 ROSE_ASSERT(returnValue != NULL);
3930 return returnValue;
3931 }
3932 } nondefiningFunctionDeclarationCopy;
3933
3934 // DQ (10/20/2007): The more accurate copy mechanism now builds us a defining declaration to go with the non-defining declaration!
3935 // This is because we have to remove the pointers from non-defining declaration to the definition (which should be pointed to ONLY by the defining declaration!
3936 // delete copyOfMemberFunction->get_definingDeclaration();
3937 if (memberFunctionInstantiation->get_definition() != NULL)
3938 {
3939 printf ("\n\nNEED TO REMOVE POINTERS IN THE NON-DEFINING DECLARATION TO THE SgClassDefinition objects. \n");
3940 ROSE_ABORT();
3941
3942 // If we see the assertion above fail then we might want to use this code:
3943 ROSE_ASSERT( memberFunctionInstantiation != memberFunctionInstantiation->get_definingDeclaration() );
3944 memberFunctionInstantiation->set_definition(NULL);
3945 }
3946 SgNode* copyOfMemberFunctionNode = memberFunctionInstantiation->copy(nondefiningFunctionDeclarationCopy);
3947 SgTemplateInstantiationMemberFunctionDecl* copyOfMemberFunction = static_cast<SgTemplateInstantiationMemberFunctionDecl*>(copyOfMemberFunctionNode);
3948
3949 // printf ("\n\nHOW DO WE KNOW WHEN TO NOT COPY THE DEFINING DECLARATION SO THAT WE CAN JUST BUILD A FUNCTION PROTOTYPE! \n");
3950 // ROSE_ASSERT(false);
3951
3952#if 0
3953 printf ("copyOfMemberFunction->get_firstNondefiningDeclaration() = %p \n",copyOfMemberFunction->get_firstNondefiningDeclaration());
3954#endif
3955 // DQ (10/11/2007): The copy function sets the firstNondefiningDeclaration to itself if in the original declaration it had the
3956 // firstNondefiningDeclaration set to itself, this is incorrect in the case where we only make a copy of function declaration,
3957 // and causes the symbol table tests for get_declaration_associated_with_symbol() to fail because it uses the
3958 // firstNondefiningDeclaration which is not the one associated with the symbol in the parent scope. So reset the
3959 // firstNondefiningDeclaration in the copy of the member function.
3960 copyOfMemberFunction->set_firstNondefiningDeclaration(memberFunctionInstantiation->get_firstNondefiningDeclaration());
3961
3962#if 0
3963 printf ("memberFunctionInstantiation->get_firstNondefiningDeclaration() = %p \n",memberFunctionInstantiation->get_firstNondefiningDeclaration());
3964
3965 printf ("copyOfMemberFunction->isForward() = %s \n",copyOfMemberFunction->isForward() ? "true" : "false");
3966 printf ("memberFunctionInstantiation->isForward() = %s \n",memberFunctionInstantiation->isForward() ? "true" : "false");
3967#endif
3968#if 0
3969 printf ("memberFunctionInstantiation->isSpecialization() = %s \n",memberFunctionInstantiation->isSpecialization() ? "true" : "false");
3970 printf ("copyOfMemberFunctionNode = %p = %s = %s memberFunctionInstantiation->isSpecialization() = %s \n",
3971 copyOfMemberFunction,copyOfMemberFunction->class_name().c_str(),SageInterface::get_name(copyOfMemberFunction).c_str(),copyOfMemberFunction->isSpecialization() ? "true" : "false");
3972 copyOfMemberFunction->get_file_info()->display("copyOfMemberFunction: debug");
3973#endif
3974
3975 // Make sure that we have the same number of arguments on the copy that we build
3976 ROSE_ASSERT(memberFunctionInstantiation->get_args().size() == copyOfMemberFunction->get_args().size());
3977
3978 // DQ (11/5/2007): Additional tests
3979 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isOutputInCodeGeneration() == copyOfMemberFunction->get_startOfConstruct()->isOutputInCodeGeneration());
3980 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isCompilerGenerated() == copyOfMemberFunction->get_startOfConstruct()->isCompilerGenerated());
3981
3982 ROSE_ASSERT(copyOfMemberFunction != NULL);
3983 return copyOfMemberFunction;
3984 }
3985
3986
3987void
3988supportForBaseTypeDefiningDeclaration ( SgSymbolTable* symbolTable, SgDeclarationStatement* declarationForType )
3989 {
3990 // DQ (10/14/2007): Supporting function for
3991
3992 ROSE_ASSERT(declarationForType != NULL);
3993
3994 // DQ (11/7/2007): Added more cases...
3995 switch(declarationForType->variantT())
3996 {
3997 // DQ (12/26/2012): Added support for templates.
3998 case V_SgTemplateInstantiationDecl:
3999 case V_SgTemplateClassDeclaration:
4000
4001 case V_SgClassDeclaration:
4002 {
4003 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationForType);
4004 // SgSymbol* symbol = new SgClassSymbol(classDeclaration);
4005 SgSymbol* symbol = NULL;
4006 if (isSgTemplateClassDeclaration(declarationForType) != NULL)
4007 {
4008 symbol = new SgTemplateClassSymbol(classDeclaration);
4009 }
4010 else
4011 {
4012 symbol = new SgClassSymbol(classDeclaration);
4013 }
4014
4015 ROSE_ASSERT(symbol != NULL);
4016 SgName name = classDeclaration->get_name();
4017 symbolTable->insert(name,symbol);
4018 break;
4019 }
4020
4021 case V_SgEnumDeclaration:
4022 {
4023 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(declarationForType);
4024 SgSymbol* symbol = new SgEnumSymbol(enumDeclaration);
4025 ROSE_ASSERT(symbol != NULL);
4026 SgName name = enumDeclaration->get_name();
4027 symbolTable->insert(name,symbol);
4028 break;
4029 }
4030
4031 case V_SgFunctionDeclaration:
4032 {
4033 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declarationForType);
4034 SgSymbol* symbol = new SgFunctionSymbol(functionDeclaration);
4035 ROSE_ASSERT(symbol != NULL);
4036 SgName name = functionDeclaration->get_name();
4037 symbolTable->insert(name,symbol);
4038 break;
4039 }
4040
4041 case V_SgMemberFunctionDeclaration:
4042 {
4043 SgMemberFunctionDeclaration* functionDeclaration = isSgMemberFunctionDeclaration(declarationForType);
4044 SgSymbol* symbol = new SgMemberFunctionSymbol(functionDeclaration);
4045 ROSE_ASSERT(symbol != NULL);
4046
4047 // printf ("In supportForBaseTypeDefiningDeclaration(): symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4048
4049 SgName name = functionDeclaration->get_name();
4050 symbolTable->insert(name,symbol);
4051 break;
4052 }
4053
4054 default:
4055 {
4056 printf ("Default reached in evaluation of typedef inner definition = %p = %s and building a symbol for it for the symbol table \n",declarationForType,declarationForType->class_name().c_str());
4057 ROSE_ABORT();
4058 }
4059 }
4060 }
4061
4062
4063void
4064supportForVariableLists ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgInitializedNamePtrList & variableList )
4065 {
4066 // DQ (11/1/2007): Added supporting function to refactor code.
4067 SgInitializedNamePtrList::iterator i = variableList.begin();
4068 while (i != variableList.end())
4069 {
4071 ROSE_ASSERT(variable != NULL);
4072 if (variable->get_scope() == scope)
4073 {
4074 // printf ("Scopes match, OK! \n");
4075 }
4076 else
4077 {
4078 if (SgProject::get_verbose() > 0)
4079 {
4080 printf ("WARNING: Scopes do NOT match! variable = %p = %s (could this be a static variable, or has the symbol table been setup before the scopes have been set?) \n",variable,variable->get_name().str());
4081 }
4082 }
4083
4084 SgSymbol* symbol = new SgVariableSymbol(variable);
4085 ROSE_ASSERT(symbol != NULL);
4086 SgName name = variable->get_name();
4087 symbolTable->insert(name,symbol);
4088
4089 i++;
4090 }
4091 }
4092#if 0
4093// DQ (3/2/2014): Added a new interface function (used in the snippet insertion support).
4094void
4095SageInterface::supportForInitializedNameLists ( SgScopeStatement* scope, SgInitializedNamePtrList & variableList )
4096 {
4097 SgSymbolTable* symbolTable = scope->get_symbol_table();
4098 ROSE_ASSERT(symbolTable != NULL);
4099
4100 supportForVariableLists(scope,symbolTable,variableList);
4101 }
4102#endif
4103
4104void
4105supportForVariableDeclarations ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgVariableDeclaration* variableDeclaration )
4106 {
4107 // DQ (10/24/2007): Added supporting function to refactor code.
4108 SgInitializedNamePtrList & variableList = variableDeclaration->get_variables();
4109 supportForVariableLists(scope,symbolTable,variableList);
4110
4111 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4112 // that also force symbols to be built in the current scope!
4113 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4114 if (variableDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4115 {
4116 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4117 ROSE_ASSERT(symbolTable != NULL);
4118 ROSE_ASSERT(variableDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4119 supportForBaseTypeDefiningDeclaration ( symbolTable, variableDeclaration->get_baseTypeDefiningDeclaration() );
4120 }
4121 }
4122
4123void
4124supportForLabelStatements ( SgScopeStatement* scope, SgSymbolTable* symbolTable )
4125 {
4126 // Update the symbol table in SgFunctionDefinition with all the labels in the function.
4127
4128 std::vector<SgNode*> labelList = NodeQuery::querySubTree (scope,V_SgLabelStatement);
4129
4130 int numberOfLabels = labelList.size();
4131 for (int i=0; i < numberOfLabels; i++)
4132 {
4133 SgLabelStatement* labelStatement = isSgLabelStatement(labelList[i]);
4134
4135 ROSE_ASSERT(labelStatement != NULL);
4136 ROSE_ASSERT(labelStatement->get_scope() == scope);
4137
4138 SgSymbol* symbol = new SgLabelSymbol(labelStatement);
4139 ROSE_ASSERT(symbol != NULL);
4140
4141 // printf ("In SageInterface::rebuildSymbolTable() labelStatement = %p building a new SgLabelSymbol = %p \n",labelStatement,symbol);
4142
4143 SgName name = labelStatement->get_name();
4144 symbolTable->insert(name,symbol);
4145 }
4146 }
4147
4148
4149void
4151 {
4152 // This function is called from the implementation of the copy member functions.
4153
4154 ROSE_ASSERT(scope != NULL);
4155#if 0
4156 printf ("In SageInterface::rebuildSymbolTable(): Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4157#endif
4158#if 0
4159 printf ("Exiting as a test \n");
4160 ROSE_ABORT();
4161#endif
4162
4163 SgSymbolTable* symbolTable = scope->get_symbol_table();
4164
4165 if (symbolTable != NULL)
4166 {
4167 // This must be an empty symbol table!
4168 if (symbolTable->size() != 0)
4169 {
4170 printf ("symbolTable->size() = %d \n",symbolTable->size());
4171 }
4172 ROSE_ASSERT(symbolTable->size() == 0);
4173#if 0
4174 printf ("Symbol Table from %p = %s of size = %" PRIuPTR " \n",scope,scope->class_name().c_str(),symbolTable->size());
4175 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
4176#endif
4177 }
4178 else
4179 {
4180#if 0
4181 printf ("In SageInterface::rebuildSymbolTable(): No symbol table found \n");
4182#endif
4183 ROSE_ASSERT(symbolTable == NULL);
4184
4185 // DQ (10/8/2007): Build a new symbol table if there was not already one built.
4186 symbolTable = new SgSymbolTable();
4187
4188 ROSE_ASSERT(symbolTable != NULL);
4189 ROSE_ASSERT(symbolTable->get_table() != NULL);
4190
4191 // DQ (2/16/2006): Set this parent directly (now tested)
4192 symbolTable->set_parent(scope);
4193 ROSE_ASSERT(symbolTable->get_parent() != NULL);
4194
4195 scope->set_symbol_table(symbolTable);
4196 }
4197
4198 // DQ (10/8/2007): If there is already a symbol table then don't over write it. This fixes copies generated with more than one symbol table.
4199 ROSE_ASSERT(scope->get_symbol_table() != NULL);
4200 ROSE_ASSERT(scope->get_symbol_table()->get_table() != NULL);
4201
4202 // This implements SgScopeStatement specific details (e.g function declarations have parameters and their declaration causes variable
4203 // symbols to be placed into the SgFunctionDefinition scope (but only for defining declarations).
4204 switch(scope->variantT())
4205 {
4206 case V_SgForStatement:
4207 {
4208 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4209 // printf ("Symbol tables could contain symbols outside of the inclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4210
4211 SgForStatement* forStatement = isSgForStatement(scope);
4212
4213 SgStatementPtrList::iterator i = forStatement->get_init_stmt().begin();
4214
4215 // printf ("i != forStatement->get_init_stmt().end() = %s \n",i != forStatement->get_init_stmt().end() ? "true" : "false");
4216
4217 while (i != forStatement->get_init_stmt().end())
4218 {
4219 // printf ("For statement initialization list: *i = %p = %s \n",*i,(*i)->class_name().c_str());
4220 SgVariableDeclaration* variableDeclarationInitializer = isSgVariableDeclaration(*i);
4221 if (variableDeclarationInitializer != NULL)
4222 {
4223 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4224 // printf ("There is a variable declaration in the for statement initializer, it needs to be added to the symbol table scope = %p = %s \n",scope,scope->class_name().c_str());
4225 // ROSE_ASSERT(false);
4226 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationInitializer );
4227 }
4228
4229 i++;
4230 }
4231
4232 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(forStatement->get_test());
4233 if (variableDeclarationCondition != NULL)
4234 {
4235 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4236 // printf ("There is a variable declaration in the for statement test, it needs to be added to the symbol table scope = %p = %s \n",scope,scope->class_name().c_str());
4237 // ROSE_ASSERT(false);
4238 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4239 }
4240
4241 return;
4242 break;
4243 }
4244
4245 case V_SgJovialForThenStatement:
4246 case V_SgMatlabForStatement:
4247 {
4248 return;
4249 break;
4250 }
4251
4252
4253 // DQ (12/23/2012): Added support for templates.
4254 case V_SgTemplateFunctionDefinition:
4255
4256 case V_SgFunctionDefinition:
4257 {
4258 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4259 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4260
4261 // DQ (10/8/2007): If this is a SgFunctionDefinition, then include the parameters in the SgFunctionDeclaration.
4262 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
4263 if (functionDefinition != NULL)
4264 {
4265 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
4266 // printf ("In SageInterface::rebuildSymbolTable(): functionDefinition = %p functionDeclaration = %p \n",functionDefinition,functionDeclaration);
4267
4268 // DQ (10/8/2007): It turns out that this is always NULL, because the parent of the functionDeclaration has not yet been set in the copy mechanism!
4269 if (functionDeclaration != NULL)
4270 {
4271 // DQ (3/28/2014): After a call with Philippe, this Java specific issues is fixed and we don't seem to see this problem any more.
4272 if (functionDeclaration->isForward() == true)
4273 {
4274 printf ("ERROR: functionDeclaration = %p = %s = %s \n",functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
4275 printf (" --- functionDeclaration (get_name()) = %s \n",get_name(functionDeclaration).c_str());
4276 printf (" --- functionDeclaration (mangled name) = %s \n",functionDeclaration->get_mangled_name().str());
4277 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
4278 if (memberFunctionDeclaration != NULL)
4279 {
4280 printf ("memberFunctionDeclaration != NULL \n");
4281 }
4282 }
4283 ROSE_ASSERT(functionDeclaration->isForward() == false);
4284 SgInitializedNamePtrList & argumentList = functionDeclaration->get_args();
4285 supportForVariableLists(scope,symbolTable,argumentList);
4286 }
4287 else
4288 {
4289 // This happens in the copy function because the function definition is copied from the SgFunctionDeclaration
4290 // and only after the copy is made is the parent of the definition set to be the function declaration. Thus
4291 // the get_declaration() member function returns NULL.
4292 // printf ("There is no function declaration associated with this function definition! \n");
4293 // ROSE_ASSERT(functionDeclaration->isForward() == true);
4294 }
4295 }
4296
4297 // DQ (10/25/2007): Label symbols are now places into the SgFunctionDefinition (they have to be collected from the function).
4298 supportForLabelStatements(scope,symbolTable);
4299
4300 return;
4301 break;
4302 }
4303
4304 case V_SgIfStmt:
4305 {
4306 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4307 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4308
4309 SgIfStmt* ifStatement = isSgIfStmt(scope);
4310 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(ifStatement->get_conditional());
4311 if (variableDeclarationCondition != NULL)
4312 {
4313 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4314 // printf ("There is a variable declaration in the conditional, it needs to be added to the symbol table \n");
4315 // ROSE_ASSERT(false);
4316 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4317 }
4318 return;
4319 break;
4320 }
4321
4322 case V_SgSwitchStatement:
4323 {
4324 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4325 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4326
4327 SgSwitchStatement* switchStatement = isSgSwitchStatement(scope);
4328 SgVariableDeclaration* variableDeclarationSelector = isSgVariableDeclaration(switchStatement->get_item_selector());
4329 if (variableDeclarationSelector != NULL)
4330 {
4331 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4332 // printf ("There is a variable declaration in the item selector of the switch statement, it needs to be added to the symbol table \n");
4333
4334 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationSelector );
4335 }
4336 return;
4337 break;
4338 }
4339
4340 case V_SgWhileStmt:
4341 {
4342 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4343 // commented out like for others, otherwise show up each time a While is being copied. Liao, 1/31/2008
4344 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4345
4346 SgWhileStmt* whileStatement = isSgWhileStmt(scope);
4347 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(whileStatement->get_condition());
4348 if (variableDeclarationCondition != NULL)
4349 {
4350 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4351 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4352 // ROSE_ASSERT(false);
4353
4354 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4355 }
4356 return;
4357 break;
4358 }
4359
4360 case V_SgCatchOptionStmt:
4361 case V_SgDoWhileStmt:
4362 {
4363 // These scopes contain a SgBasicBlock as a data member and the scope is held there.
4364 // printf ("Symbol tables can must be computed by the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4365 return;
4366 break;
4367 }
4368
4369 // DQ (12/24/2012): Added support for templates.
4370 case V_SgTemplateClassDefinition:
4371
4372 case V_SgBasicBlock:
4373 case V_SgClassDefinition:
4374 case V_SgTemplateInstantiationDefn:
4375 case V_SgGlobal:
4376 case V_SgNamespaceDefinitionStatement:
4377 case V_SgFortranDo: // Liao 12/19/2008, My understanding is that Fortran do loop header does not introduce new symbols like a C/C++ for loop does
4378 {
4379 // printf ("Used the list of statements/declarations that are held deirectly by this scope \n");
4380 break;
4381 }
4382
4383 // DQ (3/29/2014): Added support for SgJavaForEachStatement.
4384 case V_SgJavaForEachStatement:
4385 {
4386 SgJavaForEachStatement* javaForEachStatement = isSgJavaForEachStatement(scope);
4387 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(javaForEachStatement->get_element());
4388 if (variableDeclarationCondition != NULL)
4389 {
4390 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4391 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4392 // ROSE_ASSERT(false);
4393
4394 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4395 }
4396 return;
4397 break;
4398 }
4399
4400 default:
4401 {
4402 printf ("Default reached in SageInterface::rebuildSymbolTable() scope = %p = %s \n",scope,scope->class_name().c_str());
4403 ROSE_ABORT();
4404 }
4405 }
4406
4407#if 0
4408 printf ("In SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4409#endif
4410
4411 // Generate a copy of the statement list (this is simpler than handling the cases of a
4412 // declaration list and a statement list separately for the scopes that contain one or the other.
4413 SgStatementPtrList statementList = scope->generateStatementList();
4414
4415 // Loop through the statements and for each declaration build a symbol and add it to the symbol table
4416 for (SgStatementPtrList::iterator i = statementList.begin(); i != statementList.end(); i++)
4417 {
4418 // At some point we should move this mechanism in to a factory patterns for SgSymbol
4419
4420 // printf ("Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4421
4422 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
4423 if (declaration != NULL)
4424 {
4425 // DQ (11/7/2007): Where there can be multiple declaration (e.g. function declarations with prototypes) only use one of them.
4426 bool useThisDeclaration = (declaration->get_firstNondefiningDeclaration() == declaration) ||
4427 ( (declaration->get_firstNondefiningDeclaration() == NULL) && (declaration->get_definingDeclaration() == declaration) );
4428
4429 list<SgSymbol*> symbolList;
4430 switch(declaration->variantT())
4431 {
4432 case V_SgTemplateInstantiationMemberFunctionDecl:
4433 {
4434 SgTemplateInstantiationMemberFunctionDecl* derivedDeclaration = isSgTemplateInstantiationMemberFunctionDecl(declaration);
4435 // DQ (11/6/2007): Don't build a symbol for the defining declaration defined in another scope and put the resulting symbol into the wrong scope
4436 if (scope == derivedDeclaration->get_scope())
4437 {
4438 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4439 ROSE_ASSERT(symbol != NULL);
4440
4441 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4442
4443 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s inserting a symbol = %p \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str(),symbol);
4444
4445 SgName name = derivedDeclaration->get_name();
4446 symbolTable->insert(name,symbol);
4447 }
4448 else
4449 {
4450 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4451
4452 // These IR nodes might only exist as a template declaration and thus not be structureally present in their scope.
4453 // So we would never traverse them in the correct scope and so never build sysmbols for them and add the symbols
4454 // to the correct symbol table. This is a fundamental problem. So we have to try to add these sorts of symbols
4455 // to the scope were they belong.
4456 SgScopeStatement* derivedDeclarationScope = derivedDeclaration->get_scope();
4457 ROSE_ASSERT(derivedDeclarationScope != NULL);
4458
4459 // If this is a copy then it would be nice to make sure that the scope has been properly set.
4460 // Check this by looking for the associated template declaration in the scope.
4461 // SgTemplateDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4462 // SgDeclarationStatement* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4463 SgTemplateMemberFunctionDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4464 ROSE_ASSERT(templateDeclaration != NULL);
4465 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_name());
4466
4467 // DQ (8/13/2013): Fixed the interface to avoid use of lookup_template_symbol() (removed).
4468 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
4469 // In this case these are unavailable from this point.
4470 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name());
4471 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4472 SgType* functionType = templateDeclaration->get_type();
4473 SgTemplateParameterPtrList & templateParameterList = templateDeclaration->get_templateParameters();
4474 // SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4475 SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_member_function_symbol(templateDeclaration->get_template_name(),functionType,&templateParameterList);
4476 if (templateSymbol != NULL)
4477 {
4478 // The symbol is not present, so we have to build one and add it.
4479#if 0
4480 printf ("Building a symbol for derivedDeclaration = %p = %s to an alternative symbol table in derivedDeclarationScope = %p \n",
4481 derivedDeclaration,get_name(derivedDeclaration).c_str(),derivedDeclarationScope);
4482#endif
4483 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4484 ROSE_ASSERT(symbol != NULL);
4485 SgName name = derivedDeclaration->get_name();
4486 derivedDeclarationScope->insert_symbol(name,symbol);
4487 }
4488 else
4489 {
4490 // printf ("The symbol was already present in the derivedDeclarationScope = %p \n",derivedDeclarationScope);
4491 }
4492 }
4493 break;
4494 }
4495
4496 // DQ (12/26/2012): Added support for templates.
4497 case V_SgTemplateMemberFunctionDeclaration:
4498
4499 case V_SgMemberFunctionDeclaration:
4500 {
4501 SgMemberFunctionDeclaration* derivedDeclaration = isSgMemberFunctionDeclaration(declaration);
4502
4503 // DQ (11/6/2007): Don't build a symbol for the defining declaration defined in another scope and put the resulting symbol into the wrong scope
4504 if (scope == derivedDeclaration->get_scope())
4505 {
4506 // SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4507 SgSymbol* symbol = NULL;
4508 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4509 symbol = new SgTemplateMemberFunctionSymbol(derivedDeclaration);
4510 else
4511 symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4512
4513 ROSE_ASSERT(symbol != NULL);
4514
4515 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4516
4517 SgName name = derivedDeclaration->get_name();
4518 symbolTable->insert(name,symbol);
4519 }
4520 else
4521 {
4522 // This happens when a defining declaration is located outside of the class where it is associated.
4523 // printf ("SgMemberFunctionDeclaration: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4524 }
4525 break;
4526 }
4527
4528 // DQ (2/26/2009): These have to be reformatted from where someone removed the formatting previously.
4529 case V_SgTemplateInstantiationFunctionDecl:
4530 {
4531 SgTemplateInstantiationFunctionDecl* derivedDeclaration = isSgTemplateInstantiationFunctionDecl(declaration);
4532 // DQ (10/21/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4533 if (scope == derivedDeclaration->get_scope())
4534 {
4535 SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4536 ROSE_ASSERT(symbol != NULL);
4537 SgName name = derivedDeclaration->get_name();
4538 symbolTable->insert(name,symbol);
4539 }
4540 else
4541 {
4542 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4543 {
4544#if PRINT_DEVELOPER_WARNINGS
4545 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4546#endif
4547 }
4548 }
4549
4550 break;
4551 }
4552
4553 // DQ (12/24/2012): Added support for templates.
4554 case V_SgTemplateFunctionDeclaration:
4555
4556 case V_SgFunctionDeclaration:
4557 {
4558 SgFunctionDeclaration* derivedDeclaration = isSgFunctionDeclaration(declaration);
4559
4560 // DQ (10/20/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4561
4562 if (useThisDeclaration == true)
4563 {
4564 if (scope == derivedDeclaration->get_scope())
4565 {
4566 // DQ (12/24/2012): Added support for templates.
4567 // SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4568 SgSymbol* symbol = NULL;
4569 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4570 symbol = new SgTemplateFunctionSymbol(derivedDeclaration);
4571 else
4572 symbol = new SgFunctionSymbol(derivedDeclaration);
4573
4574 ROSE_ASSERT(symbol != NULL);
4575 SgName name = derivedDeclaration->get_name();
4576 symbolTable->insert(name,symbol);
4577 }
4578 else
4579 {
4580 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4581 {
4582#if PRINT_DEVELOPER_WARNINGS
4583 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4584#endif
4585 }
4586 }
4587 }
4588 break;
4589 }
4590
4591 // DQ (12/28/2012): Adding support for templates.
4592 case V_SgTemplateVariableDeclaration:
4593
4594 case V_SgVariableDeclaration:
4595 {
4596 SgVariableDeclaration* derivedDeclaration = isSgVariableDeclaration(declaration);
4597 SgInitializedNamePtrList & variableList = derivedDeclaration->get_variables();
4598 SgInitializedNamePtrList::iterator i = variableList.begin();
4599 while ( i != variableList.end() )
4600 {
4602 ROSE_ASSERT(variable != NULL);
4603
4604 // DQ (10/20/2007): static data members declared outside the class scope don't generate symbols.
4605 if (variable->get_scope() == scope)
4606 {
4607 SgSymbol* symbol = new SgVariableSymbol(variable);
4608 ROSE_ASSERT(symbol != NULL);
4609
4610 // printf ("In SageInterface::rebuildSymbolTable() variable = %p building a new SgVariableSymbol = %p \n",variable,symbol);
4611
4612 SgName name = variable->get_name();
4613 symbolTable->insert(name,symbol);
4614 }
4615 else
4616 {
4617 // I think there is nothing to do in this case
4618 // printf ("In SageInterface::rebuildSymbolTable() This variable has a scope inconsistant with the symbol table: variable->get_scope() = %p scope = %p \n",variable->get_scope(),scope);
4619 }
4620
4621 i++;
4622 }
4623
4624 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4625 // that also force symbols to be built in the current scope!
4626 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4627 if (derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4628 {
4629 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4630 ROSE_ASSERT(symbolTable != NULL);
4631 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4632 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4633 }
4634
4635 // ROSE_ASSERT(symbolList.empty() == false);
4636 break;
4637 }
4638
4639 case V_SgTemplateInstantiationDecl:
4640 {
4641 SgTemplateInstantiationDecl* derivedDeclaration = isSgTemplateInstantiationDecl(declaration);
4642#if 1
4643 // printf ("case SgTemplateInstantiationDecl: derivedDeclaration name = %s derivedDeclaration->get_declarationModifier().isFriend() = %s \n",
4644 // derivedDeclaration->get_name().str(),derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4645
4646 if (scope == derivedDeclaration->get_scope())
4647 {
4648 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4649 // printf ("Inserting SgClassSymbol = %p into scope = %p = %s \n",symbol,scope,scope->class_name().c_str());
4650 ROSE_ASSERT(symbol != NULL);
4651 SgName name = derivedDeclaration->get_name();
4652#if 0
4653 // DQ (10/21/2007): The scopes should match
4654 if (scope != derivedDeclaration->get_scope())
4655 {
4656 printf ("Error: scopes don't match for derivedDeclaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4657 }
4658 ROSE_ASSERT(scope == derivedDeclaration->get_scope());
4659#endif
4660 symbolTable->insert(name,symbol);
4661 }
4662 else
4663 {
4664 // printf ("SgTemplateInstantiationDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4665
4666 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4667 {
4668#if PRINT_DEVELOPER_WARNINGS
4669 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4670#endif
4671 }
4672 }
4673#else
4674 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4675 ROSE_ASSERT(symbol != NULL);
4676 SgName name = derivedDeclaration->get_name();
4677 symbolTable->insert(name,symbol);
4678#endif
4679 break;
4680 }
4681
4682
4683 // DQ (12/24/2012): Added support for templates.
4684 case V_SgTemplateClassDeclaration:
4685
4686 case V_SgClassDeclaration:
4687 {
4688 SgClassDeclaration* derivedDeclaration = isSgClassDeclaration(declaration);
4689#if 1
4690 if (scope == derivedDeclaration->get_scope())
4691 {
4692 SgSymbol* symbol = NULL;
4693 if (isSgTemplateClassDeclaration(declaration) != NULL)
4694 symbol = new SgTemplateClassSymbol(derivedDeclaration);
4695 else
4696 symbol = new SgClassSymbol(derivedDeclaration);
4697
4698 ROSE_ASSERT(symbol != NULL);
4699 SgName name = derivedDeclaration->get_name();
4700 symbolTable->insert(name,symbol);
4701 }
4702 else
4703 {
4704 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4705 {
4706#if PRINT_DEVELOPER_WARNINGS
4707 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4708#endif
4709 }
4710 }
4711#else
4712 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4713 ROSE_ASSERT(symbol != NULL);
4714 SgName name = derivedDeclaration->get_name();
4715 symbolTable->insert(name,symbol);
4716#endif
4717 break;
4718 }
4719
4720 case V_SgEnumDeclaration:
4721 {
4722 SgEnumDeclaration* derivedDeclaration = isSgEnumDeclaration(declaration);
4723 ROSE_ASSERT(derivedDeclaration != NULL);
4724 SgSymbol* symbol = new SgEnumSymbol(derivedDeclaration);
4725 ROSE_ASSERT(symbol != NULL);
4726 SgName name = derivedDeclaration->get_name();
4727 symbolTable->insert(name,symbol);
4728
4729 // DQ (10/18/2007): Fixed construction of symbol tabel to include enum fields.
4730 SgInitializedNamePtrList & enumFieldList = derivedDeclaration->get_enumerators();
4731 SgInitializedNamePtrList::iterator i = enumFieldList.begin();
4732
4733 // Iterate over enum fields and add each one to the symbol table.
4734 while (i != enumFieldList.end())
4735 {
4736 SgSymbol* enum_field_symbol = new SgEnumFieldSymbol(*i);
4737 ROSE_ASSERT(enum_field_symbol != NULL);
4738 SgName enum_field_name = (*i)->get_name();
4739 symbolTable->insert(enum_field_name,enum_field_symbol);
4740
4741 i++;
4742 }
4743
4744 break;
4745 }
4746
4747
4748 // DQ (2/18/2017): Added support for C++11 SgTemplateTypedefDeclaration.
4749 case V_SgTemplateTypedefDeclaration:
4750
4751 case V_SgTypedefDeclaration:
4752 {
4753 SgTypedefDeclaration* derivedDeclaration = isSgTypedefDeclaration(declaration);
4754 SgSymbol* symbol = new SgTypedefSymbol(derivedDeclaration);
4755 ROSE_ASSERT(symbol != NULL);
4756 SgName name = derivedDeclaration->get_name();
4757 symbolTable->insert(name,symbol);
4758#if 0
4759 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration \n");
4760#endif
4761 // DQ (10/13/2007): Need to look into typedefs to see if there are defining declaration
4762 // that also force symbols to be built in the current scope!
4763 // ROSE_ASSERT(derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == false);
4764 if (derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == true)
4765 {
4766 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4767 ROSE_ASSERT(symbolTable != NULL);
4768 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4769#if 0
4770 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == true calling supportForBaseTypeDefiningDeclaration() \n");
4771#endif
4772 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4773 }
4774 else
4775 {
4776 // DQ (11/7/2007): If the typedef has a definition (e.g. function pointer) then build a symbol.
4777 SgDeclarationStatement* declaration = derivedDeclaration->get_declaration();
4778 if (declaration != NULL)
4779 {
4780#if 0
4781 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false calling supportForBaseTypeDefiningDeclaration() \n");
4782#endif
4783 // DQ (12/27/2012): Debugging the support for copytest_2007_40_cpp.C (we don't want to build this symbol since it is associated with an outer scope).
4784 // supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_declaration() );
4785
4786 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false: skipping call to supportForBaseTypeDefiningDeclaration() \n");
4787 }
4788 }
4789#if 0
4790 printf ("In SageInterface::rebuildSymbolTable(): Leaving case of SgTypedefDeclaration \n");
4791#endif
4792 break;
4793 }
4794
4795 case V_SgTemplateDeclaration:
4796 {
4797 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4798#if 1
4799 // DQ (10/21/2007): If this is a friend function in a class then we have to skip insertion of the symbol into this scope (this symbol table)
4800#if 0
4801 printf ("case V_SgTemplateDeclaration: derivedDeclaration = %p \n",derivedDeclaration);
4802 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_declarationModifier().isFriend() = %s \n",derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4803 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_name() = %s \n",derivedDeclaration->get_name().str());
4804 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_string() = %s \n",derivedDeclaration->get_string().str());
4805#endif
4806 if (scope == derivedDeclaration->get_scope())
4807 {
4808 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4809 ROSE_ASSERT(symbol != NULL);
4810 SgName name = derivedDeclaration->get_name();
4811 symbolTable->insert(name,symbol);
4812 }
4813 else
4814 {
4815 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4816 {
4817#if PRINT_DEVELOPER_WARNINGS
4818 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4819#endif
4820 }
4821 }
4822#else
4823 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4824 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4825 ROSE_ASSERT(symbol != NULL);
4826 SgName name = derivedDeclaration->get_name();
4827 symbolTable->insert(name,symbol);
4828#endif
4829 break;
4830 }
4831
4832 // Does this cause a symbol to be built? Seems that it should,
4833 // unless we always reference the non-aliased symbol (reuse it)!
4834 case V_SgNamespaceAliasDeclarationStatement:
4835 {
4836 SgNamespaceAliasDeclarationStatement* aliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
4837 ROSE_ASSERT(aliasDeclaration != NULL);
4838 ROSE_ASSERT(aliasDeclaration->get_namespaceDeclaration() != NULL);
4839
4840 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(aliasDeclaration->get_namespaceDeclaration());
4841 ROSE_ASSERT(derivedDeclaration != NULL);
4842
4843 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4844 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4845 ROSE_ASSERT(symbol != NULL);
4846 SgName name = derivedDeclaration->get_name();
4847 symbolTable->insert(name,symbol);
4848 // symbolList.push_back(symbol);
4849 // ROSE_ASSERT(symbolList.empty() == false);
4850 break;
4851 }
4852
4853 // Does this cause a symbol to be built? Seems that it should,
4854 // unless we always reference the non-aliased symbol (reuse it)!
4855 case V_SgNamespaceDeclarationStatement:
4856 {
4857 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(declaration);
4858 ROSE_ASSERT(derivedDeclaration != NULL);
4859
4860 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4861 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4862 ROSE_ASSERT(symbol != NULL);
4863 SgName name = derivedDeclaration->get_name();
4864 symbolTable->insert(name,symbol);
4865 // symbolList.push_back(symbol);
4866 // ROSE_ASSERT(symbolList.empty() == false);
4867 break;
4868 }
4869
4870 case V_SgUsingDirectiveStatement:
4871 case V_SgPragmaDeclaration:
4872 case V_SgTemplateInstantiationDirectiveStatement:
4873 case V_SgUsingDeclarationStatement:
4874 {
4875 // DQ (10/22/2005): Not sure if we have to worry about this declaration's appearance in the symbol table!
4876#if 0
4877 printf ("This declaration is ignored in rebuilding symbol table %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4878#endif
4879 break;
4880 }
4881
4882 case V_SgAsmStmt:
4883 {
4884 // DQ (8/13/2006): This is not really a declaration (I think). This will be fixed later.
4885#if 0
4886 printf ("An ASM statement (SgAsmStmt) declaration is not really a declaration %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4887#endif
4888 break;
4889 }
4890
4891 // Cases where declations are not used or referenced and so symbols are not required!
4892 case V_SgVariableDefinition:
4893 case V_SgFunctionParameterList:
4894 case V_SgCtorInitializerList:
4895 // These are not referenced so they don't need a symbol!
4896 {
4897 printf ("Special cases not handled %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4898 ROSE_ABORT();
4899 }
4900
4901 case V_SgStaticAssertionDeclaration:
4902 {
4903 // DQ (2/18/2017): This is not really a declaration (I think). This will be fixed later.
4904#if 0
4905 printf ("A static assertion statement (SgStaticAssertionDeclaration) declaration is not really a declaration %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4906#endif
4907 break;
4908 }
4909
4910 default:
4911 {
4912 printf ("Error: Default reached in rebuildSymbolTable declaration = %p = %s \n",declaration,declaration->class_name().c_str());
4913 ROSE_ABORT();
4914 }
4915 }
4916
4917 ROSE_ASSERT(symbolTable != NULL);
4918 ROSE_ASSERT(symbolTable->get_table() != NULL);
4919 }
4920 // printf ("DONE: Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4921
4922 }
4923
4924 ROSE_ASSERT(symbolTable != NULL);
4925 ROSE_ASSERT(symbolTable->get_table() != NULL);
4926
4927#if 0
4928 printf ("Leaving SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4929#endif
4930
4931#if 0
4932 printf ("Symbol Table from %p = %s at: \n",scope,scope->class_name().c_str());
4933 scope->get_file_info()->display("Symbol Table Location");
4934 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
4935#endif
4936 }
4937
4938
4939// #ifndef USE_ROSE
4940
4941void
4943 {
4944 // This function is called by the SageInterface::rebuildSymbolTable().
4945 // It resets references to old symbols to the new symbols (just built).
4946 // All pairs of old/new symbols are also saved in the object:
4947 // SgCopyHelp::copiedNodeMapType copiedNodeMap
4948
4949#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
4950 ROSE_ASSERT(this_scope != NULL);
4951 ROSE_ASSERT(copy_scope != NULL);
4952
4953#if 0
4954 printf ("In fixupReferencesToSymbols(this_scope = %p = %s = %s, copy_scope = %p = %s = %s) \n",
4955 this_scope,this_scope->class_name().c_str(),get_name(this_scope).c_str(),
4956 copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
4957#endif
4958
4959 SgSymbolTable* this_symbolTable = this_scope->get_symbol_table();
4960 SgSymbolTable* copy_symbolTable = copy_scope->get_symbol_table();
4961#if 0
4962 printf ("Before fixup: this scope = %p = %s this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_scope,this_scope->class_name().c_str(),this_symbolTable->get_table()->size());
4963 printf ("Before fixup: copy scope = %p = %s copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_scope,copy_scope->class_name().c_str(),copy_symbolTable->get_table()->size());
4964#endif
4965
4966 // DQ (3/4/2009): For now just output a warning, but this might be a more serious problem.
4967 // Since the symbol table size of the copy is larger than that of the original it might
4968 // be that a symbol is enterted twice by the copy mechanism. If so I want to fix this.
4969 if (this_symbolTable->get_table()->size() != copy_symbolTable->get_table()->size())
4970 {
4971 if (SgProject::get_verbose() > 0)
4972 {
4973 printf ("Before fixup: this scope = %p = %s this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_scope,this_scope->class_name().c_str(),this_symbolTable->get_table()->size());
4974 printf ("Before fixup: copy scope = %p = %s copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_scope,copy_scope->class_name().c_str(),copy_symbolTable->get_table()->size());
4975 printf ("Warning the symbols tables in these different scopes are different sizes \n");
4976 }
4977 }
4978 // ROSE_ASSERT(this_symbolTable->get_table()->size() <= copy_symbolTable->get_table()->size());
4979
4980 SgSymbolTable::hash_iterator i = this_symbolTable->get_table()->begin();
4981
4982 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
4983 std::map<SgNode*, SgNode*> replacementMap;
4984 int counter = 0;
4985 while (i != this_symbolTable->get_table()->end())
4986 {
4987 ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL );
4988
4989 SgName name = (*i).first;
4990 // SgSymbol* symbol = isSgSymbol((*i).second);
4991 SgSymbol* symbol = (*i).second;
4992 ROSE_ASSERT ( symbol != NULL );
4993
4994 SgSymbol* associated_symbol = NULL;
4995#if 0
4996 printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) = %p sage_class_name() = %s \n",counter,i->first.str(),i->second,i->second->class_name().c_str());
4997#endif
4998 // Look for the associated symbol in the copy_scope's symbol table.
4999 SgSymbolTable::hash_iterator associated_symbol_iterator = copy_symbolTable->get_table()->find(name);
5000
5001 // Note that this is a multi-map and for C++ a number of symbols can have the same name
5002 // (though not the same type of symbol) so we have to iterator over the symbols of the
5003 // same name so that we can identify the associated symbol.
5004 while (associated_symbol_iterator != copy_symbolTable->get_table()->end() && associated_symbol_iterator->first == name)
5005 {
5006 if ( associated_symbol_iterator->second->variantT() == symbol->variantT() )
5007 {
5008 associated_symbol = associated_symbol_iterator->second;
5009 }
5010
5011 associated_symbol_iterator++;
5012 }
5013
5014 if (associated_symbol != NULL)
5015 {
5016 ROSE_ASSERT ( associated_symbol != NULL );
5017
5018 // Check to make sure that this is correct
5019 ROSE_ASSERT(copy_scope->symbol_exists(associated_symbol) == true);
5020
5021 // Add the SgGlobal referenece to the replacementMap
5022 // replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
5023 // DQ (23/1/2009): Find the reference to symbol and replace it with associated_symbol.
5024 replacementMap.insert(pair<SgNode*,SgNode*>(symbol,associated_symbol));
5025
5026 // DQ (3/1/2009): This is backwards
5027 // replacementMap.insert(pair<SgNode*,SgNode*>(associated_symbol,symbol));
5028
5029 // DQ (3/2/2009): accumulate the symbol pair into the SgCopyHelp object (to support the outliner).
5030 // Actually this should also improve the robustness of the outliner.
5031 help.get_copiedNodeMap().insert(pair<const SgNode*,SgNode*>(symbol,associated_symbol));
5032 }
5033 else
5034 {
5035 // DQ (3/4/2009): This case was broken out because copytest2007_14.C fails here.
5036 if (SgProject::get_verbose() > 0)
5037 {
5038 printf ("Warning: Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) = %p sage_class_name() = %s \n",counter,i->first.str(),i->second,i->second->class_name().c_str());
5039 printf ("Warning: associated_symbol == NULL, need to investigate this (ignoring for now) \n");
5040 }
5041 }
5042
5043 counter++;
5044
5045 i++;
5046 }
5047
5048#if 0
5049 printf ("\n\n************************************************************\n");
5050 printf ("fixupReferencesToSymbols(this_scope = %p copy_scope = %p = %s = %s): calling Utils::edgePointerReplacement() \n",this_scope,copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5051#endif
5052
5053 Rose::AST::Utility::edgePointerReplacement(copy_scope,replacementMap);
5054
5055#if 0
5056 printf ("fixupReferencesToSymbols(): calling Utils::edgePointerReplacement(): DONE \n");
5057 printf ("************************************************************\n\n");
5058
5059 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
5060 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
5061
5062 printf ("After fixup: this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_symbolTable->get_table()->size());
5063 printf ("After fixup: copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_symbolTable->get_table()->size());
5064#endif
5065
5066 // DQ (3/1/2009): find a case where this code is tested.
5067 // ROSE_ASSERT(this_symbolTable->get_table()->size() == 0);
5068 // ROSE_ASSERT(isSgClassDefinition(copy_scope) == NULL);
5069#endif
5070
5071#if 0
5072 printf ("Exiting as a test in fixupReferencesToSymbols() \n");
5073 ROSE_ABORT();
5074#endif
5075 }
5076
5077// #endif
5078
5079#ifndef USE_ROSE
5080
5081std::vector<SgFile*>
5083 {
5084 // This function uses a memory pool traversal specific to the SgFile IR nodes
5085 class FileTraversal : public ROSE_VisitTraversal
5086 {
5087 public:
5088 vector<SgFile*> fileList;
5089 void visit ( SgNode* node)
5090 {
5091 SgFile* file = isSgFile(node);
5092 ROSE_ASSERT(file != NULL);
5093 if (file != NULL)
5094 {
5095 fileList.push_back(file);
5096 }
5097 };
5098
5099 virtual ~FileTraversal() {}
5100 };
5101
5102 FileTraversal fileTraversal;
5103
5104 // traverse just the SgFile nodes (both the SgSourceFile and SgBinaryComposite IR nodes)!
5105 // SgFile::visitRepresentativeNode(fileTraversal);
5107#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5109#endif
5110
5111 // This would alternatively traverse all IR nodes in thememory pool!
5112 // fileTraversal.traverseMemoryPool();
5113
5114 // TV (06/24/2013): This fail when calling SageBuilder::buildVariableDeclaration(...) without any file created.
5115 // DQ (10/11/2014): This is allowed to be empty (required for new aterm support).
5116 // ROSE_ASSERT(fileTraversal.fileList.empty() == false);
5117
5118 return fileTraversal.fileList;
5119 }
5120
5121#endif
5122
5123// #ifndef USE_ROSE
5124
5125// DQ (4/17/2015): I think this function should be removed since it interferes
5126// with the concept of having more than one SgProject node.
5127// This function uses a memory pool traversal specific to the SgProject IR nodes
5128SgProject*
5130{
5131#if 0
5132 class ProjectTraversal : public ROSE_VisitTraversal
5133 {
5134 public:
5135 SgProject * project;
5136 void visit ( SgNode* node)
5137 {
5138 project = isSgProject(node);
5139 ROSE_ASSERT(project!= NULL);
5140 };
5141 virtual ~ProjectTraversal() {}
5142 };
5143
5144 ProjectTraversal projectTraversal;
5145 SgProject::visitRepresentativeNode(projectTraversal);
5146 return projectTraversal.project;
5147#endif
5148 std::vector<SgProject* > resultlist = getSgNodeListFromMemoryPool<SgProject>();
5149 if (resultlist.empty())
5150 return NULL;
5151 ROSE_ASSERT(resultlist.size()==1);
5152 return resultlist[0];
5153}
5154
5155SgProject*
5157 return getEnclosingNode<SgProject>(node, true /*includingSelf*/);
5158}
5159
5161 SgFunctionDeclaration * ret = NULL;
5162 if (isSgFunctionRefExp(func))
5163 {
5164 return isSgFunctionRefExp(func)->get_symbol()->get_declaration();
5165 }
5166 else if (isSgDotExp(func) || isSgArrowExp(func))
5167 {
5168 SgExpression* func2 = isSgBinaryOp(func)->get_rhs_operand();
5169 if (isSgMemberFunctionRefExp(func2))
5170 return isSgMemberFunctionRefExp(func2)->get_symbol()->get_declaration();
5171 else
5172 {
5173 cerr<<"Warning in SageInterface::getDeclarationOfNamedFunction(): rhs operand of dot or arrow operations is not a member function, but a "<<func2->class_name()<<endl;
5174 }
5175 }
5176
5177 return ret;
5178}
5179
5181 SgExprListExp* el = stmt->get_forall_header();
5182 const SgExpressionPtrList& ls = el->get_expressions();
5183 if (ls.empty()) return 0;
5184 if (isSgAssignOp(ls.back())) return 0;
5185 return ls.back();
5186}
5187
5188//Find all SgPntrArrRefExp under astNode, add the referenced dim_info SgVarRefExp (if any) into NodeList_t
5189void SageInterface::addVarRefExpFromArrayDimInfo(SgNode * astNode, Rose_STL_Container<SgNode *>& NodeList_t)
5190{
5191 ASSERT_not_null(astNode);
5192 Rose_STL_Container<SgNode*> arr_exp_list = NodeQuery::querySubTree(astNode,V_SgPntrArrRefExp);
5193 for (SgNode* expr : arr_exp_list)
5194 {
5195 SgPntrArrRefExp* arr_exp = isSgPntrArrRefExp(expr);
5196 ASSERT_not_null(arr_exp);
5197 Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp);
5198 for (SgNode* ref : refList)
5199 {
5200 SgVarRefExp* cur_ref = isSgVarRefExp(ref);
5201 ASSERT_not_null(cur_ref);
5202 SgVariableSymbol * sym = cur_ref->get_symbol();
5203 ASSERT_not_null(sym);
5204 SgInitializedName * iname = sym->get_declaration();
5205 ASSERT_not_null(iname);
5206 SgArrayType * a_type = isSgArrayType(iname->get_typeptr());
5207 if (a_type && a_type->get_dim_info())
5208 {
5209 Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp);
5210 for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++)
5211 {
5212 SgVarRefExp* dim_ref = isSgVarRefExp(*iter2);
5213 NodeList_t.push_back(dim_ref);
5214 }
5215 }
5216 }
5217 } // end for
5218}
5219
5220
5221// DQ (11/25/2020): This disables these non-inlined functions in favor of
5222// inlined versions of the functions in the sageInterface.h (header file).
5223#if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5224bool
5226 {
5227#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5228 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5229 return Rose::is_Ada_language;
5230#else
5231 bool returnValue = false;
5232
5233 vector<SgFile*> fileList = generateFileList();
5234
5235 int size = (int)fileList.size();
5236 for (int i = 0; i < size; i++)
5237 {
5238 if (fileList[i]->get_Ada_only() == true)
5239 returnValue = true;
5240 }
5241
5242 return returnValue;
5243#endif
5244 }
5245
5246bool
5248 {
5249#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5250 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5251 return Rose::is_C_language;
5252#else
5253 bool returnValue = false;
5254
5255 vector<SgFile*> fileList = generateFileList();
5256
5257 int size = (int)fileList.size();
5258 for (int i = 0; i < size; i++)
5259 {
5260 if (fileList[i]->get_C_only() == true)
5261 returnValue = true;
5262 }
5263
5264 return returnValue;
5265#endif
5266 }
5267
5268bool
5270 {
5271#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5272 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5273 return Rose::is_OpenMP_language;
5274#else
5275 bool returnValue = false;
5276
5277 vector<SgFile*> fileList = generateFileList();
5278
5279 int size = (int)fileList.size();
5280 for (int i = 0; i < size; i++)
5281 {
5282 if (fileList[i]->get_openmp() == true)
5283 returnValue = true;
5284 }
5285
5286 return returnValue;
5287#endif
5288 }
5289
5290bool
5292 {
5293#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5294 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5295 return Rose::is_UPC_language;
5296#else
5297 bool returnValue = false;
5298
5299 vector<SgFile*> fileList = generateFileList();
5300
5301 int size = (int)fileList.size();
5302 for (int i = 0; i < size; i++)
5303 {
5304 if (fileList[i]->get_UPC_only() == true)
5305 returnValue = true;
5306 }
5307
5308 return returnValue;
5309#endif
5310 }
5311
5312//FMZ
5313bool
5315 {
5316#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5317 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5318 return Rose::is_CAF_language;
5319#else
5320 bool returnValue = false;
5321
5322 vector<SgFile*> fileList = generateFileList();
5323
5324 int size = (int)fileList.size();
5325 for (int i = 0; i < size; i++)
5326 {
5327 if (fileList[i]->get_CoArrayFortran_only()==true)
5328 returnValue = true;
5329 }
5330
5331 return returnValue;
5332#endif
5333 }
5334
5335
5336// true if any of upc_threads is set to >0 via command line: -rose:upc_threads n
5337bool
5339 {
5340#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5341 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5342 return Rose::is_UPC_dynamic_threads;
5343#else
5344 bool returnValue = false;
5345
5346 vector<SgFile*> fileList = generateFileList();
5347
5348 int size = (int)fileList.size();
5349 for (int i = 0; i < size; i++)
5350 {
5351 if (fileList[i]->get_upc_threads() > 0)
5352 returnValue = true;
5353 }
5354
5355 return returnValue;
5356#endif
5357 }
5358
5359
5360
5361bool
5363 {
5364#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5365 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5366 return Rose::is_C99_language;
5367#else
5368 bool returnValue = false;
5369
5370 vector<SgFile*> fileList = generateFileList();
5371
5372 int size = (int)fileList.size();
5373 for (int i = 0; i < size; i++)
5374 {
5375 if (fileList[i]->get_C99_only() == true)
5376 returnValue = true;
5377 }
5378
5379 return returnValue;
5380#endif
5381 }
5382
5383bool
5385 {
5386#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5387 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5388 return Rose::is_Cxx_language;
5389#else
5390 bool returnValue = false;
5391
5392 vector<SgFile*> fileList = generateFileList();
5393
5394 int size = (int)fileList.size();
5395 for (int i = 0; i < size; i++)
5396 {
5397 // DQ (8/19/2007): Make sure this is not a Fortran code!
5398 if (fileList[i]->get_Cxx_only() == true)
5399 {
5400 ROSE_ASSERT(fileList[i]->get_Fortran_only() == false && fileList[i]->get_C99_only() == false && fileList[i]->get_C_only() == false && fileList[i]->get_binary_only() == false);
5401
5402 returnValue = true;
5403 }
5404 }
5405
5406 return returnValue;
5407#endif
5408 }
5409
5410bool
5412 {
5413#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5414 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5415 return Rose::is_Java_language;
5416#else
5417 bool returnValue = false;
5418
5419 vector<SgFile*> fileList = generateFileList();
5420
5421 int size = (int)fileList.size();
5422 for (int i = 0; i < size; i++)
5423 {
5424 if (fileList[i]->get_Java_only() == true)
5425 returnValue = true;
5426 }
5427
5428 return returnValue;
5429#endif
5430 }
5431
5432bool
5434 {
5435#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5436 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5437 return Rose::is_Jvm_language;
5438#else
5439 bool returnValue = false;
5440
5441 vector<SgFile*> fileList = generateFileList();
5442
5443 int size = (int)fileList.size();
5444 for (int i = 0; i < size; i++)
5445 {
5446 if (fileList[i]->get_Jvm_only() == true)
5447 returnValue = true;
5448 }
5449
5450 return returnValue;
5451#endif
5452 }
5453
5454// Rasmussen (4/4/2018): Added Jovial
5455bool
5457 {
5458#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5459 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5460 return Rose::is_Jovial_language;
5461#else
5462 bool returnValue = false;
5463
5464 vector<SgFile*> fileList = generateFileList();
5465
5466 int size = (int)fileList.size();
5467 for (int i = 0; i < size; i++)
5468 {
5469 if (fileList[i]->get_Jovial_only() == true)
5470 returnValue = true;
5471 }
5472
5473 return returnValue;
5474#endif
5475 }
5476
5477
5478bool
5480 {
5481#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5482 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5483 return Rose::is_Fortran_language;
5484#else
5485 bool returnValue = false;
5486
5487 vector<SgFile*> fileList = generateFileList();
5488
5489 int size = (int)fileList.size();
5490 for (int i = 0; i < size; i++)
5491 {
5492 if (fileList[i]->get_Fortran_only() == true)
5493 returnValue = true;
5494 }
5495
5496 return returnValue;
5497#endif
5498 }
5499
5500
5501bool
5503 {
5504#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5505 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5506 return Rose::is_binary_executable;
5507#else
5508 bool returnValue = false;
5509
5510 vector<SgFile*> fileList = generateFileList();
5511
5512 int size = (int)fileList.size();
5513 for (int i = 0; i < size; i++)
5514 {
5515 if (fileList[i]->get_binary_only() == true)
5516 returnValue = true;
5517 }
5518
5519 return returnValue;
5520#endif
5521 }
5522
5523bool
5525 {
5526#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5527 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5528 return Rose::is_PHP_language;
5529#else
5530 bool returnValue = false;
5531
5532 vector<SgFile*> fileList = generateFileList();
5533
5534 int size = (int)fileList.size();
5535 for (int i = 0; i < size; i++)
5536 {
5537 if (fileList[i]->get_PHP_only() == true)
5538 returnValue = true;
5539 }
5540
5541 return returnValue;
5542#endif
5543 }
5544
5545bool
5547 {
5548#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5549 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5550 return Rose::is_Python_language;
5551#else
5552 bool returnValue = false;
5553
5554 vector<SgFile*> fileList = generateFileList();
5555
5556 int size = (int)fileList.size();
5557 for (int i = 0; i < size; i++)
5558 {
5559 if (fileList[i]->get_Python_only() == true)
5560 returnValue = true;
5561 }
5562
5563 return returnValue;
5564#endif
5565 }
5566
5567bool
5569 {
5570#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5571 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5572 return Rose::is_Cuda_language;
5573#else
5574 bool returnValue = false;
5575
5576 vector<SgFile*> fileList = generateFileList();
5577
5578 int size = (int)fileList.size();
5579 for (int i = 0; i < size; i++)
5580 {
5581 if (fileList[i]->get_Cuda_only() == true)
5582 returnValue = true;
5583 }
5584
5585 return returnValue;
5586#endif
5587 }
5588
5589bool
5591 {
5592#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5593 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5594 return Rose::is_OpenCL_language;
5595#else
5596 bool returnValue = false;
5597
5598 vector<SgFile*> fileList = generateFileList();
5599
5600 int size = (int)fileList.size();
5601 for (int i = 0; i < size; i++)
5602 {
5603 if (fileList[i]->get_OpenCL_only() == true)
5604 returnValue = true;
5605 }
5606
5607 return returnValue;
5608#endif
5609 }
5610
5611// for if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5612#endif
5613
5618
5623
5628
5633
5638
5639// Languages that may have scopes that contain statements that are not only declarations.
5640// For Fortran and Jovial (at least), function definitions may be declared at the end of procedures.
5645
5646// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5647// labels for scopes in a function (as required for name mangling).
5648void
5650 {
5651 ASSERT_not_null(functionDefinition);
5652 std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5653
5654 // Clear the cache of stored (scope,integer) pairs
5655 scopeMap.erase(scopeMap.begin(),scopeMap.end());
5656
5657 ASSERT_require(scopeMap.empty() == true);
5658 ASSERT_require(functionDefinition->get_scope_number_list().empty() == true);
5659 }
5660
5661#ifndef USE_ROSE
5662
5663// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5664// labels for scopes in a function (as required for name mangling).
5665void
5667 {
5668 ROSE_ASSERT(functionDefinition != NULL);
5669 // std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5670 // ROSE_ASSERT(scopeMap.empty() == true);
5671 ROSE_ASSERT(functionDefinition->get_scope_number_list().empty() == true);
5672
5673 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5674 class ScopeNumberingTraversal : public AstSimpleProcessing
5675 {
5676 public:
5677 ScopeNumberingTraversal() : count (0), storedFunctionDefinition(NULL) {}
5678 void visit (SgNode* node)
5679 {
5680 SgScopeStatement* scope = isSgScopeStatement (node);
5681 if (scope != NULL)
5682 {
5683 // Set the function definition
5684 SgFunctionDefinition* testFunctionDefinition = isSgFunctionDefinition(scope);
5685 if (testFunctionDefinition != NULL && storedFunctionDefinition == NULL)
5686 {
5687 ROSE_ASSERT(storedFunctionDefinition == NULL);
5688 storedFunctionDefinition = testFunctionDefinition;
5689 }
5690
5691 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5692 ROSE_ASSERT(storedFunctionDefinition != NULL);
5693
5694 count++;
5695
5696 std::map<SgNode*,int> & scopeMap = storedFunctionDefinition->get_scope_number_list();
5697 scopeMap.insert(pair<SgNode*,int>(scope,count));
5698#if 0
5699 string functionName = storedFunctionDefinition->get_declaration()->get_name().str();
5700 printf ("In function = %s insert scope = %p = %s with count = %d into local map (size = %d) \n",
5701 functionName.c_str(),scope,scope->class_name().c_str(),count,scopeMap.size());
5702#endif
5703 }
5704 }
5705
5706 private:
5707 int count; // running total of scopes found in the input function
5708 SgFunctionDefinition* storedFunctionDefinition;
5709 };
5710
5711 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5712 ScopeNumberingTraversal traversal;
5713 traversal.traverse(functionDefinition, preorder);
5714 }
5715
5716#endif
5717
5718#ifndef USE_ROSE
5719
5720#if 0
5721// DQ (6/26/2007): These are removed and the support is added to SgNode to support a single mangled name cache.
5722// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5723// labels for scopes in a function (as required for name mangling).
5724void
5726 {
5727 ROSE_ASSERT(globalScope != NULL);
5728 std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5729
5730 // Clear the cache of stored (scope,integer) pairs
5731 mangledNameCache.erase(mangledNameCache.begin(),mangledNameCache.end());
5732
5733 ROSE_ASSERT(mangledNameCache.empty() == true);
5734 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5735 }
5736
5737// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5738// labels for scopes in a function (as required for name mangling).
5739void
5741 {
5742 ROSE_ASSERT(globalScope != NULL);
5743 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5744
5745 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5746 class MangledNameTraversal : public AstSimpleProcessing
5747 {
5748 public:
5749 MangledNameTraversal() : storedGlobalScope(NULL) {}
5750 void visit (SgNode* node)
5751 {
5752 SgFunctionDeclaration* mangleableNode = isSgFunctionDeclaration(node);
5753 if ( (mangleableNode != NULL) || (isSgGlobal(node) != NULL) )
5754 {
5755 // Set the global scope
5756 SgGlobal* testGlobalScope = isSgGlobal(mangleableNode);
5757 if (testGlobalScope != NULL && storedGlobalScope == NULL)
5758 {
5759 ROSE_ASSERT(storedGlobalScope == NULL);
5760 storedGlobalScope = testGlobalScope;
5761 }
5762
5763 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5764 ROSE_ASSERT(storedGlobalScope != NULL);
5765
5766 string mangledName = mangleableNode->get_mangled_name();
5767 // printf ("mangledName = %s \n",mangledName.c_str());
5768
5769 std::map<SgNode*,std::string> & mangledNameCache = storedGlobalScope->get_mangledNameCache();
5770 mangledNameCache.insert(pair<SgNode*,std::string>(mangleableNode,mangledName));
5771#if 0
5772 string nodeName = get_name(mangleableNode);
5773 printf ("At node = %p = %s = %s in local map (size = %d) \n",
5774 mangleableNode,mangleableNode->class_name().c_str(),nodeName.c_str(),mangledNameCache.size());
5775#endif
5776 }
5777 }
5778
5779 private:
5780 SgGlobal* storedGlobalScope;
5781 };
5782
5783 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5784 MangledNameTraversal traversal;
5785 traversal.traverse(globalScope, preorder);
5786 }
5787#endif
5788
5789
5790string
5792 {
5793 // The TransformationSupport is not defined yet (I forget the
5794 // details but I recall that there is a reason why this is this way).
5795 // SgGlobal* globalScope = TransformationSupport::getGlobalScope(astNode);
5796#if 0
5797 SgGlobal* globalScope = isSgGlobal(astNode);
5798
5799 if (globalScope == NULL && isSgFile(astNode) != NULL)
5800 {
5801 globalScope = isSgFile(astNode)->get_globalScope();
5802 ROSE_ASSERT(globalScope != NULL);
5803 }
5804
5805 if (globalScope == NULL && isSgProject(astNode) != NULL)
5806 {
5807 // Check to make sure that the SgFile can be uniquely determined
5808 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5809 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5810 ROSE_ASSERT(globalScope != NULL);
5811 }
5812
5813 SgNode* temp = astNode;
5814 while (temp->get_parent() != NULL && globalScope == NULL)
5815 {
5816 temp = temp->get_parent();
5817 globalScope = isSgGlobal(temp);
5818 }
5819 ROSE_ASSERT(globalScope != NULL);
5820#endif
5821
5822 // std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5823 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
5824
5825 // Build an iterator
5826 std::map<SgNode*,std::string>::iterator i = mangledNameCache.find(astNode);
5827
5828 string mangledName;
5829 if (i != mangledNameCache.end())
5830 {
5831 // get the precomputed mangled name!
5832 //~ printf ("Mangled name IS found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5833 mangledName = i->second;
5834 }
5835 else
5836 {
5837 // mangled name not found in cache!
5838 //~ printf ("Mangled name NOT found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5839 }
5840
5841 return mangledName;
5842 }
5843
5844#define DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE 0
5845#define DEBUG_MANGLED_SHORTNAME 1
5846
5847//#ifdef DEBUG_MANGLED_SHORTNAME
5848//std::unordered_map<uint64_t, std::string> SageInterface::mangledNameHashCollisionCheckMap;
5849//#endif
5850
5851std::string
5852SageInterface::addMangledNameToCache( SgNode* astNode, const std::string & oldMangledName)
5853 {
5854#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
5855 printf ("In SageInterface::addMangledNameToCache(): TOP: astNode = %p = %s oldMangledName = %s \n",astNode,astNode->class_name().c_str(),oldMangledName.c_str());
5856#endif
5857
5858//#define DEBUG_MANGLED_SHORTNAME 1
5859#ifdef DEBUG_MANGLED_SHORTNAME
5860 static std::unordered_map<uint64_t, std::string> mangledNameHashCollisionCheckMap;
5861#endif
5862
5863
5864#if 0
5865 SgGlobal* globalScope = isSgGlobal(astNode);
5866
5867 if (globalScope == NULL && isSgFile(astNode) != NULL)
5868 {
5869 globalScope = isSgFile(astNode)->get_globalScope();
5870 ROSE_ASSERT(globalScope != NULL);
5871 }
5872
5873 if (globalScope == NULL && isSgProject(astNode) != NULL)
5874 {
5875 // Check to make sure that the SgFile can be uniquely determined
5876 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5877 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5878 ROSE_ASSERT(globalScope != NULL);
5879 }
5880
5881 SgNode* temp = astNode;
5882 while (temp->get_parent() != NULL && globalScope == NULL)
5883 {
5884 temp = temp->get_parent();
5885 globalScope = isSgGlobal(temp);
5886 }
5887 ROSE_ASSERT(globalScope != NULL);
5888#endif
5889
5890 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
5891
5892 std::string mangledName;
5893
5894 if (SgProject::get_mangled_noshortname() == false) {
5895 std::map<std::string, uint64_t> & shortMangledNameCache = SgNode::get_shortMangledNameCache();
5896
5897 if (oldMangledName.size() > 40) {
5898 std::map<std::string, uint64_t>::const_iterator shortMNIter = shortMangledNameCache.find(oldMangledName);
5899 uint64_t idNumber = 0;
5900 if (shortMNIter != shortMangledNameCache.end())
5901 {
5902 idNumber = shortMNIter->second;
5903
5904#ifdef DEBUG_MANGLED_SHORTNAME
5905 //Check for hash colisions, if we found an idNumber, but the long mangled name is different, we have a problem
5906 auto collisionIt = mangledNameHashCollisionCheckMap.find(idNumber);
5907 if(collisionIt != mangledNameHashCollisionCheckMap.end() &&
5908 oldMangledName != shortMNIter->first)
5909 {
5910 mlog[Sawyer::Message::Common::ERROR] <<" Got a short mangled name collision. \n "<<
5911 oldMangledName << " and \n " << shortMNIter->first << " \n" <<
5912 "have the same idNumber of: " << Combinatorics::toBase62String(idNumber) << " " << shortMNIter->second << endl;
5913 exit(12);
5914 } else {
5915 mangledNameHashCollisionCheckMap[idNumber] = oldMangledName;
5916 }
5917#endif //DEBUG_MANGLED_SHORTNAME
5918
5919 }
5920 else
5921 {
5923 hasher.insert(oldMangledName);
5924 hasher.digest();
5925 idNumber = hasher.toU64();
5926 shortMangledNameCache.insert(std::pair<std::string, uint64_t>(oldMangledName, idNumber));
5927 }
5928
5929 std::ostringstream mn;
5930 mn << 'L' << Combinatorics::toBase62String(idNumber) << 'R';
5931 mangledName = mn.str();
5932 } else {
5933 mangledName = oldMangledName;
5934 }
5935 } else {
5936
5937 // DQ (7/24/2012): Note that using this option can cause some test codes using operators that have
5938 // difficult names (conversion operators to user-defined types) to fail. See test2004_141.C for example.
5939 // The conversion operator "operator T&() const;" will fail because the character "&" will remain in
5940 // mangled name. The substring coding changes the strings for the mangled names and this effectively
5941 // removes the special characters, but there could be cases where they might remain.
5942
5943 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
5944 static unsigned long counter = 0;
5945
5946 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
5947 // This supports debugging the new EDG 4.x interface...
5948 if (counter++ % 500 == 0)
5949 {
5950 printf ("WARNING: In SageInterface::addMangledNameToCache(): Using longer forms of mangled names (can cause some function names with embedded special characters to fail; test2004_141.C) \n");
5951 }
5952 mangledName = oldMangledName;
5953}
5954
5955 // DQ (6/26/2007): Output information useful for understanding Jeremiah's shortended name merge caching.
5956 // std::cerr << "Changed MN " << oldMangledName << " to " << mangledName << std::endl;
5957
5958#if 0
5959 printf ("Updating mangled name cache for node = %p = %s with mangledName = %s \n",astNode,astNode->class_name().c_str(),mangledName.c_str());
5960#endif
5961
5962#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
5963 SgStatement* statement = isSgStatement(astNode);
5964 if (statement != NULL && statement->hasExplicitScope() == true)
5965 {
5966 if (statement->get_scope() == NULL)
5967 {
5968 printf ("Warning: SageInterface::addMangledNameToCache(): In it might be premature to add this IR node and name to the mangledNameCache: statement = %p = %s oldMangledName = %s \n",
5969 statement,statement->class_name().c_str(),oldMangledName.c_str());
5970 }
5971 }
5972#endif
5973
5974 mangledNameCache.insert(pair<SgNode*,string>(astNode,mangledName));
5975
5976#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
5977 printf ("In SageInterface::addMangledNameToCache(): returning mangledName = %s \n",mangledName.c_str());
5978#endif
5979
5980 return mangledName;
5981 }
5982
5983
5984// #endif
5985
5986#ifndef USE_ROSE
5987
5988bool
5990 {
5991 // This function is used in the unparser, but might be more generally useful. Since it is
5992 // related to general AST tests, I have put it here. It might be alternatively put in the
5993 // src/backend/unparser or related utility directory.
5994
5995 // Preorder traversal to test the order of declaration of non-defining vs. defining class
5996 // declarations in the preorder traversal of the AST.
5997 class DeclarationOrderTraversal : public AstSimpleProcessing
5998 {
5999 public:
6000 DeclarationOrderTraversal( SgDeclarationStatement* nonDefiningDeclaration, SgDeclarationStatement* definingDeclaration )
6001 : storedNondefiningDeclaration(nonDefiningDeclaration),
6002 storedDefiningDeclaration(definingDeclaration)
6003 {
6004 storedDeclarationFound = false;
6005 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6006 }
6007
6008 void visit (SgNode* node)
6009 {
6010 ROSE_ASSERT(storedNondefiningDeclaration != NULL);
6011 ROSE_ASSERT(storedDefiningDeclaration != NULL);
6012 ROSE_ASSERT(storedNondefiningDeclaration != storedDefiningDeclaration);
6013 // ROSE_ASSERT(storedNondefiningDeclaration->get_definingDeclaration() == storedDefiningDeclaration);
6014
6015 // Even though we only care about the SgClassDeclaration IR nodes we have to traverse them
6016 // in the AST in the order defined by the traversal (order of apprearance in the AST). We
6017 // also can't just search the declarations of a single scope (since the nondefining declaration
6018 // can appear in a different scope than the defining declaration).
6019 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6020 if ( declaration != NULL )
6021 {
6022 if (storedDeclarationFound == false)
6023 {
6024 if (declaration == storedDefiningDeclaration)
6025 {
6026 storedDeclarationFound = true;
6027 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6028 }
6029 if (declaration == storedNondefiningDeclaration)
6030 {
6031 storedDeclarationFound = true;
6032 nonDefiningDeclarationPreceedsDefiningDeclaration = true;
6033 }
6034 }
6035 }
6036 }
6037
6038 public:
6039 bool storedDeclarationFound;
6040 bool nonDefiningDeclarationPreceedsDefiningDeclaration;
6041
6042 private:
6043 SgDeclarationStatement* storedNondefiningDeclaration;
6044 SgDeclarationStatement* storedDefiningDeclaration;
6045 };
6046
6047 ROSE_ASSERT(nonDefiningDeclaration != NULL);
6048#if 0
6049 printf ("In SageInterface::declarationPreceedsDefinition(): \n");
6050 printf (" nondefiningDeclaration = %p = %s \n",nonDefiningDeclaration,nonDefiningDeclaration->class_name().c_str());
6051 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6052 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6053 printf (" definingDeclaration = %p = %s \n",definingDeclaration,definingDeclaration->class_name().c_str());
6054 definingDeclaration->get_file_info()->display("definingDeclaration");
6055 printf ("************************************************************* \n");
6056#endif
6057
6058#if 0
6059 // The nonDefiningDeclaration can be a different type of declaration than the definingDeclaration
6060 if (nonDefiningDeclaration->get_definingDeclaration() != definingDeclaration)
6061 {
6062 printf ("In SageInterface::declarationPreceedsDefinition() (warning): \n");
6063 printf (" nondefiningDeclaration = %p \n",nonDefiningDeclaration);
6064 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6065 printf (" definingDeclaration = %p \n",definingDeclaration);
6066 }
6067#endif
6068
6069 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6070 bool returnResult = false;
6071 if (nonDefiningDeclaration != definingDeclaration)
6072 {
6073 // Get the global scope from a traversal back (up) through the AST.
6074 SgGlobal* globalScope = TransformationSupport::getGlobalScope(definingDeclaration);
6075 ROSE_ASSERT(globalScope != NULL);
6076
6077 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6078 DeclarationOrderTraversal traversal (nonDefiningDeclaration,definingDeclaration);
6079
6080#if 0
6081 traversal.traverse(globalScope, preorder);
6082#else
6083 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6084 printf ("Skipping traversal within SageInterface::declarationPreceedsDefinition() \n");
6085 traversal.storedDeclarationFound = true;
6086 traversal.nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6087#endif
6088
6089 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6090 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6091 // nondefining declarations that are not in the traversal).
6092
6093 if (traversal.storedDeclarationFound == false)
6094 {
6095#if 0
6096 printf ("In SageInterface::declarationPreceedsDefinition(): warning, nonDefiningDeclaration not found in the AST \n");
6097 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6098 definingDeclaration->get_file_info()->display("definingDeclaration");
6099 printf ("---------------------------------------------------- \n\n");
6100#endif
6101 // Set this error case to return true so that we will not assume incorrectly
6102 // that the classNonDefiningDeclaration apears after the classDefiningDeclaration.
6103 returnResult = true;
6104 }
6105 else
6106 {
6107 returnResult = traversal.nonDefiningDeclarationPreceedsDefiningDeclaration;
6108 }
6109
6110 // ROSE_ASSERT(traversal.storedDeclarationFound == true);
6111 }
6112#if 0
6113 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6114 printf ("************************************************************* \n\n");
6115#endif
6116 return returnResult;
6117 }
6118
6119
6120bool
6122 {
6123 // This function is used in the unparser, but might be more generally useful. Since it is
6124 // related to general AST tests, I have put it here. It might be alternatively put in the
6125 // src/backend/unparser or related utility directory.
6126
6127 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6128 // declarations in the preorder traversal of the AST.
6129 class DeclarationOrderTraversal : public AstSimpleProcessing
6130 {
6131 public:
6132 DeclarationOrderTraversal( SgFunctionCallExp* functionCall )
6133 : storedFunctionCall(functionCall)
6134 {
6135 ROSE_ASSERT(functionCall != NULL);
6136 ROSE_ASSERT(functionCall->get_function() != NULL);
6137 SgExpression* functionExpression = functionCall->get_function();
6138
6139 switch (functionExpression->variantT())
6140 {
6141 // these are the acceptable cases
6142 case V_SgDotExp:
6143 case V_SgDotStarOp:
6144 case V_SgArrowExp:
6145 case V_SgArrowStarOp:
6146 case V_SgPointerDerefExp:
6147 {
6148 // These are the acceptable cases, but not handled yet.
6149 printf ("These are the acceptable cases, but not handled yet... \n");
6150 ROSE_ABORT();
6151 }
6152
6153 case V_SgFunctionRefExp:
6154 {
6155 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression);
6156 ROSE_ASSERT(functionRefExp != NULL);
6157 SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol();
6158 ROSE_ASSERT(functionSymbol != NULL);
6159
6160 // Make sure that the function has a valid declaration
6161 ROSE_ASSERT(functionSymbol->get_declaration() != NULL);
6162 storedFunctionDeclaration = functionSymbol->get_declaration();
6163 break;
6164 }
6165
6166 case V_SgMemberFunctionRefExp:
6167 {
6168 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression);
6169 ROSE_ASSERT(memberFunctionRefExp != NULL);
6170 SgMemberFunctionSymbol* memberFunctionSymbol = memberFunctionRefExp->get_symbol();
6171 ROSE_ASSERT(memberFunctionSymbol != NULL);
6172
6173 storedFunctionDeclaration = memberFunctionSymbol->get_declaration();
6174
6175 printf ("V_SgMemberFunctionRefExp case not handled yet... \n");
6176 ROSE_ABORT();
6177 }
6178
6179 default:
6180 {
6181 printf ("default reached in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() functionExpression = %s \n",
6182 functionExpression->class_name().c_str());
6183 ROSE_ABORT();
6184 }
6185 }
6186 // ROSE_ASSERT(functionCall->get_declaration() != NULL);
6187 // ROSE_ASSERT(functionCall->get_function()->get_firstNondefiningDeclaration() != NULL);
6188 // storedFunctionDeclaration = functionCall->get_declaration()->get_firstNondefiningDeclaration();
6189 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6190
6191 storedFunctionCallFound = false;
6193 }
6194
6195 void visit (SgNode* node)
6196 {
6197 ROSE_ASSERT(storedFunctionCall != NULL);
6198 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6199 // ROSE_ASSERT(storedFunctionCall != storedFunctionDeclaration);
6200
6201 if (storedFunctionCallFound == false)
6202 {
6203 SgFunctionCallExp* functionCall = isSgFunctionCallExp(node);
6204 if ( functionCall != NULL )
6205 {
6206 if (functionCall == storedFunctionCall)
6207 {
6208 storedFunctionCallFound = true;
6209
6210 // A declaration for the function in a scope where the function could be defined
6211 // (and a scope associated with it) has not been found so the function call
6212 // preceeds such a declaration (if it even exists).
6214 }
6215 }
6216
6217 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6218 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6219
6220 // Note that all firstNondefiningDeclaration are set to the same declaration (for all associated declarations).
6221 // Need to check the result of get_firstNondefiningDeclaration() since this will be the same for all declarations
6222 // of the same function and thus can be used to match that we have an associated declaration for the same function.
6223 if ( declaration != NULL && declaration->get_firstNondefiningDeclaration() == storedFunctionDeclaration->get_firstNondefiningDeclaration())
6224 {
6225 // Test if this is a declaration is a scope where the existance of the forward
6226 // declaration will define the scope fo the function declaration.
6227 SgScopeStatement* parentScopeOfDeclaration = isSgScopeStatement(declaration->get_parent());
6228 if (parentScopeOfDeclaration != NULL && parentScopeOfDeclaration->supportsDefiningFunctionDeclaration() == true)
6229 {
6230 // We are done so we can skip further testing
6231 storedFunctionCallFound = true;
6232
6233 // We have found a declaration which will associated the scope of a function declaration
6234 // (so all function calls after this point can be qualified (and might have to be).
6236#if 0
6237 printf ("Found a declaration which preceeds the function \n");
6238 declaration->get_file_info()->display("Found a declaration which preceeds the function: declaration");
6239 storedFunctionCall->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionCall");
6240 storedFunctionDeclaration->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionDeclaration");
6241#endif
6242 }
6243 else
6244 {
6245 // Error checking!
6246 if (parentScopeOfDeclaration == NULL)
6247 {
6248 // This might be a function declaration (non-defining) used in a type or buried deeply in some sort of declaration!
6249 printf ("Strange case of parentScopeOfDeclaration == NULL in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6250 SgNode* parent = declaration->get_parent();
6251 if (parent != NULL) {
6252 printf ("declaration->get_parent() = %s \n",parent->class_name().c_str());
6253 }
6254 else {
6255 printf ("declaration->get_parent() = NULL \n");
6256 }
6257 declaration->get_file_info()->display("case of parentScopeOfDeclaration == NULL");
6258 ROSE_ABORT();
6259 }
6260 }
6261 }
6262 }
6263 }
6264
6265 public:
6266 bool storedFunctionCallFound;
6268
6269 private:
6270 SgFunctionCallExp* storedFunctionCall;
6271 SgDeclarationStatement* storedFunctionDeclaration;
6272 };
6273
6274 ROSE_ASSERT(functionCall != NULL);
6275#if 0
6276 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): \n");
6277 printf (" storedFunctionCall = %p = %s \n",functionCall,functionCall->class_name().c_str());
6278 functionCall->get_file_info()->display("storedFunctionCall");
6279 printf (" storedFunctionCall->get_function() = %p = %s \n",functionCall->get_function(),functionCall->get_function()->class_name().c_str());
6280 printf ("************************************************************* \n");
6281#endif
6282
6283 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6284 bool returnResult = false;
6285
6286 // Get the global scope from a traversal back (up) through the AST.
6287 SgGlobal* globalScope = TransformationSupport::getGlobalScope(functionCall);
6288 ROSE_ASSERT(globalScope != NULL);
6289
6290 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6291 DeclarationOrderTraversal traversal (functionCall);
6292
6293#if 0
6294 traversal.traverse(globalScope, preorder);
6295#else
6296 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6297 printf ("Skipping traversal within SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6298 traversal.storedFunctionCallFound = true;
6299 traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope = false;
6300#endif
6301
6302 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6303 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6304 // nondefining declarations that are not in the traversal).
6305
6306 if (traversal.storedFunctionCallFound == false)
6307 {
6308#if 0
6309 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): warning, storedFunctionCall not found in the AST \n");
6310 functionCall->get_file_info()->display("functionCall");
6311 printf ("---------------------------------------------------- \n\n");
6312#endif
6313 // Set this error case to return true so that we will not assume incorrectly
6314 // that the function call is used after a declaration that associated the scope
6315 // with the function. This still causes the global name qualifier to be omitted.
6316 returnResult = true;
6317 }
6318 else
6319 {
6320 returnResult = traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope;
6321 }
6322
6323 // I hope that this is nearly always be true!
6324 ROSE_ASSERT(traversal.storedFunctionCallFound == true);
6325#if 0
6326 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6327 printf ("************************************************************* \n\n");
6328#endif
6329 return returnResult;
6330 }
6331
6332#endif
6333
6334// #ifndef USE_ROSE
6335
6336string
6337SageInterface::generateProjectName( const SgProject* project, bool supressSuffix )
6338 {
6339 // This function generates a string to use as a unique project name for
6340 // a collection of files. The last file will include it's suffix so that
6341 // we generate proper names that communicate the source language.
6342 // Also also allows the single file case to be consistant with the previous
6343 // version of names generated for "DOT" files in the tutorial.
6344
6345 // DQ (9/6/2008): Introduced optional parameter to supresse the suffix in the
6346 // generation of the project name so that we can support more complex name
6347 // construction as required for the generation of names for the whole AST
6348 // graphs which append an additional suffix to avoid filename collision.
6349
6350 ROSE_ASSERT(project != NULL);
6351 string projectName;
6352
6353 // DQ (9/2/2008): Removed the redundant function getFileNames().
6354 // Rose_STL_Container<string> fileList = project->get_sourceFileNameList();
6355 Rose_STL_Container<string> fileList = project->getAbsolutePathFileNames();
6356
6357 Rose_STL_Container<string>::iterator i = fileList.begin();
6358
6359 // Handle the case of an empty list (e.g. for link lines).
6360 if ( fileList.empty() == true )
6361 {
6362 return "empty_file_list";
6363 }
6364
6365 do {
6366 string filename = *i;
6367
6368 // printf ("In SageInterface::generateProjectName(): absolute filename = %s \n",filename.c_str());
6369
6370 // string filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6371
6372 if (i != fileList.begin())
6373 projectName += "--";
6374
6375 i++;
6376
6377 string filenameWithoutSuffix;
6378 if ( i != fileList.end() || supressSuffix == true )
6379 filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6380 else
6381 filenameWithoutSuffix = filename;
6382
6383 string filenameWithoutPathOrSuffix = StringUtility::stripPathFromFileName(filenameWithoutSuffix);
6384
6385 // printf ("filenameWithoutSuffix = %s \n",filenameWithoutSuffix.c_str());
6386 // printf ("filenameWithoutPathOrSuffix = %s \n",filenameWithoutPathOrSuffix.c_str());
6387
6388 filename = filenameWithoutPathOrSuffix;
6389
6390 unsigned long int n = 0;
6391 while (n < filename.size())
6392 {
6393 if (filename[n] == '/')
6394 filename[n] = '_';
6395 n++;
6396 }
6397
6398 // printf ("In SageInterface:generateProjectName(): modified absolute filename = %s \n",filename.c_str());
6399
6400 projectName += filename;
6401
6402 // printf ("In SageInterface:generateProjectName(): evolving projectName = %s \n",projectName.c_str());
6403 }
6404 while (i != fileList.end());
6405
6406 // printf ("In SageInterface:generateProjectName(): projectName = %s \n",projectName.c_str());
6407
6408 return projectName;
6409 }
6410
6411// #endif
6412
6413// #ifndef USE_ROSE
6414
6417 {
6418 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6419 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6420
6421 // enable default search from top of StackScope, Liao, 1/24/2008
6422 SgFunctionSymbol* functionSymbol = NULL;
6423 if (currentScope == NULL)
6424 currentScope = SageBuilder::topScopeStack();
6425 ROSE_ASSERT(currentScope != NULL);
6426
6427 SgScopeStatement* tempScope = currentScope;
6428 while ((functionSymbol == NULL) && (tempScope != NULL))
6429 {
6430 functionSymbol = tempScope->lookup_function_symbol(functionName);
6431#if 0
6432 printf ("In lookupFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6433#endif
6434 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6435 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6436 else
6437 tempScope = NULL;
6438 }
6439 return functionSymbol;
6440 }
6441
6443SageInterface::lookupTemplateFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6444 {
6445 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6446 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6447
6448 // enable default search from top of StackScope, Liao, 1/24/2008
6449 SgFunctionSymbol* functionSymbol = NULL;
6450 if (currentScope == NULL)
6451 currentScope = SageBuilder::topScopeStack();
6452 ROSE_ASSERT(currentScope != NULL);
6453
6454 SgScopeStatement* tempScope = currentScope;
6455 while ((functionSymbol == NULL) && (tempScope != NULL))
6456 {
6457 functionSymbol = tempScope->lookup_template_function_symbol(functionName, ftype, tplparams);
6458#if 0
6459 printf ("In lookupTemplateFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6460#endif
6461 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6462 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6463 else
6464 tempScope = NULL;
6465 }
6466 return functionSymbol;
6467 }
6468
6470SageInterface::lookupTemplateMemberFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6471 {
6472 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6473 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6474
6475 // enable default search from top of StackScope, Liao, 1/24/2008
6476 SgFunctionSymbol* functionSymbol = NULL;
6477 if (currentScope == NULL)
6478 currentScope = SageBuilder::topScopeStack();
6479 ROSE_ASSERT(currentScope != NULL);
6480
6481 SgScopeStatement* tempScope = currentScope;
6482 while ((functionSymbol == NULL) && (tempScope != NULL))
6483 {
6484 functionSymbol = tempScope->lookup_template_member_function_symbol(functionName, ftype, tplparams);
6485#if 0
6486 printf ("In lookupTemplateMemberFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6487#endif
6488 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6489 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6490 else
6491 tempScope = NULL;
6492 }
6493 return functionSymbol;
6494 }
6495
6496void
6497SageInterface::addTextForUnparser ( SgNode* astNode, string s, AstUnparseAttribute::RelativePositionType inputlocation )
6498 {
6499 // printf ("addText(): using new attribute interface (s = %s) \n",s.c_str());
6500
6501 if (isSgType(astNode) != NULL)
6502 {
6503 printf ("Error: the mechanism to add text to be unparsed at IR nodes is not intended to operate on SgType IR nodes (since they are shared) \n");
6504 ROSE_ABORT();
6505 }
6506
6507 if (astNode->attributeExists(AstUnparseAttribute::markerName) == true)
6508 {
6509 AstUnparseAttribute* code = dynamic_cast<AstUnparseAttribute*>(astNode->getAttribute(AstUnparseAttribute::markerName));
6510 ROSE_ASSERT(code != NULL);
6511
6512 // DQ (2/23/2009): commented added.
6513 // Since there is at least one other string (there is an existing attribute) the relative order of the strings is significant.
6514 code->addString(s,inputlocation);
6515 }
6516 else
6517 {
6518 // DQ (2/25/2016): I think it is significant, because inputlocation refers to the order relative to
6519 // the statement, not relative to other AstUnparseAttribute objects. Fixed to use the inputlocation.
6520 // DQ (2/23/2009): commented added.
6521 // Note that this will be the only string in the attribute, so inputlocation is not significant (and e_before is the default used).
6522 // AstUnparseAttribute* code = new AstUnparseAttribute(s,AstUnparseAttribute::e_before);
6523 AstUnparseAttribute* code = new AstUnparseAttribute(s,inputlocation);
6524 ROSE_ASSERT(code != NULL);
6525
6526 astNode->addNewAttribute(AstUnparseAttribute::markerName,code);
6527 }
6528 }
6529
6530
6531#if 0
6532// DQ (7/20/2011): Resolving conflict, this was added in previous work in dq-cxx-rc branch.
6533// DQ (7/17/2011): Added function from cxx branch that I need here for the Java support.
6536 {
6537 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6538 SgClassSymbol* symbol = NULL;
6539 if (cscope == NULL)
6540 cscope = SageBuilder::topScopeStack();
6541 ROSE_ASSERT(cscope != NULL);
6542
6543 while ((cscope != NULL) && (symbol == NULL))
6544 {
6545 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6546 symbol = cscope->lookup_class_symbol(name,NULL);
6547
6548 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6549 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6550 else
6551 cscope = NULL;
6552 }
6553
6554 return symbol;
6555 }
6556#endif
6557
6558
6559
6560SgType* SageInterface::lookupNamedTypeInParentScopes(const std::string& type_name, SgScopeStatement* scope/*=NULL*/)
6561 {
6562 if (scope == NULL)
6564
6565 // DQ (8/16/2013): Added NULL pointers to at least handle the API change.
6566 SgSymbol* symbol = lookupSymbolInParentScopes (type_name,scope,NULL,NULL);
6567
6568 if (symbol == NULL)
6569 return NULL;
6570 else
6571 return symbol->get_type();
6572 }
6573
6575 const SgType* t,
6576 SgScopeStatement *currentScope)
6577 //SgScopeStatement *currentScope=NULL)
6578{
6579 SgFunctionSymbol* functionSymbol = NULL;
6580 if (currentScope == NULL)
6581 currentScope = SageBuilder::topScopeStack();
6582 ROSE_ASSERT(currentScope != NULL);
6583 SgScopeStatement* tempScope = currentScope;
6584 while (functionSymbol == NULL && tempScope != NULL)
6585 {
6586 functionSymbol = tempScope->lookup_function_symbol(functionName,t);
6587 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6588 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6589 else tempScope = NULL;
6590 }
6591 return functionSymbol;
6592}
6593
6594SgSymbol*
6595SageInterface::lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6596 {
6597 SgSymbol* symbol = nullptr;
6598 if (cscope == nullptr) {
6599 cscope = SageBuilder::topScopeStack();
6600 }
6601 ASSERT_not_null(cscope);
6602
6603 while ((cscope != nullptr) && (symbol == nullptr))
6604 {
6605 symbol = cscope->lookup_symbol(name,templateParameterList,templateArgumentList);
6606 if (cscope->get_parent() != nullptr) // avoid calling get_scope when parent is not set
6607 cscope = isSgGlobal(cscope) ? nullptr : cscope->get_scope();
6608 else
6609 cscope = nullptr;
6610 }
6611
6612 return symbol;
6613 }
6614
6615
6616
6617SgSymbol*
6618SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols (const SgName & name, SgScopeStatement *currentScope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6619 {
6620 // DQ (8/5/2020): the "using namespace" directive will not hide existing visability of symbols in resolving visability.
6621 // So we need to test if a symbol is visible exclusing matching alises due to using direectives before we can decide to
6622 // persue name space qualification. This is best demonstrated by Cxx_tests/test2020_18.C, test2020_19.C, test2020_20.C,
6623 // and test2020_21.C.
6624
6625// DQ (7/14/2025): Adding timers to support Matt's tool.
6626#define USING_PERFORMANCE_TRACING 0
6627
6628 SgSymbol* symbol = NULL;
6629
6630#if USING_PERFORMANCE_TRACING
6631 // DQ (7/14/2025): Adding timers to support Matt's tool.
6632 TimingPerformance timer1 ("SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols: whole function:");
6633#endif
6634
6635 if (currentScope == NULL)
6636 {
6637 currentScope = SageBuilder::topScopeStack();
6638 }
6639
6640 ROSE_ASSERT(currentScope != NULL);
6641
6642#define DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS 0
6643
6644#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6645 printf ("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): currentScope = %p = %s (templateParameterList = %p templateArgumentList = %p) \n",
6646 currentScope,currentScope->class_name().c_str(),templateParameterList,templateArgumentList);
6647#endif
6648
6649 while ((currentScope != NULL) && (symbol == NULL))
6650 {
6651#if USING_PERFORMANCE_TRACING
6652 // DQ (7/14/2025): Adding timers to support Matt's tool.
6653 TimingPerformance timer1 ("SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols: in loop:");
6654#endif
6655
6656#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6657 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): name = %s currentScope = %p = %s \n",
6658 name.str(),currentScope,currentScope->class_name().c_str());
6659#endif
6660
6661 // DQ (8/16/2013): Changed API to support template parameters and template arguments.
6662 // symbol = cscope->lookup_symbol(name);
6663 symbol = currentScope->lookup_symbol(name,templateParameterList,templateArgumentList);
6664
6665 if (isSgAliasSymbol(symbol) != NULL)
6666 {
6667#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6668 printf ("Found a SgAliasSymbol: reset to NULL: symbol = %p = %s \n",symbol,symbol->class_name().c_str());
6669#endif
6670 symbol = NULL;
6671 }
6672
6673#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS && 1
6674 // debug
6675 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): symbol = %p \n",symbol);
6676 currentScope->print_symboltable("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): debug");
6677#endif
6678 if (currentScope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6679 currentScope = isSgGlobal(currentScope) ? NULL : currentScope->get_scope();
6680 else
6681 currentScope = NULL;
6682
6683#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6684 printf (" --- In SageInterface:: (base of loop) lookupSymbolInParentScopesIgnoringAliasSymbols(): cscope = %p symbol = %p \n\n",currentScope,symbol);
6685#endif
6686 }
6687
6688 if (symbol == NULL)
6689 {
6690#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6691 printf ("Warning: In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): could not locate the specified name %s in any outer symbol table (templateParameterList = %p templateArgumentList = %p) \n",
6692 name.str(),templateParameterList,templateArgumentList);
6693#endif
6694 // ROSE_ASSERT(false);
6695 }
6696
6697#if 0
6698 printf ("Support for lookupSymbolInParentScopesIgnoringAliasSymbols() is not yet implemented \n");
6699 ROSE_ABORT();
6700#endif
6701
6702 return symbol;
6703 }
6704
6705
6706
6707
6708
6709
6710
6711
6712#if 0
6713// DQ (7/13/2011): This was part of a merge conflict with the above modified function.
6714// It appeas they are the same so this one is commented out.
6716{
6717 SgSymbol* symbol = NULL;
6718 if (cscope == NULL)
6719 cscope = SageBuilder::topScopeStack();
6720 ROSE_ASSERT(cscope);
6721
6722 while ((cscope!=NULL)&&(symbol==NULL))
6723 {
6724 symbol = cscope->lookup_symbol(name);
6725 //debug
6726 // cscope->print_symboltable("debug sageInterface.C L3749...");
6727 if (cscope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6728 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6729 else
6730 cscope = NULL;
6731 }
6732
6733 if (symbol==NULL)
6734 {
6735 // printf ("Warning: could not locate the specified name %s in any outer symbol table \n"e,
6736 // name.str());
6737 // ROSE_ASSERT(false);
6738 }
6739 return symbol;
6740}
6741#endif
6742
6745 {
6746 // DQ (1/24/2011): This function is inconsistant with an implementation that would correctly handle SgAliasSymbols.
6747 // Also this function might get a SgClassSymbol instead of a SgVariableSymbol when both names are used.
6748 // This function needs to be fixed to handle the multi-map semantics of the symbol tables.
6749
6750#if 0
6751 // DQ (5/7/2011): I think this implementation is not correct (does not resolve past hidden types) and so should
6752 // be fixed to be consistant with the implementation of SageInterface::lookupClassSymbolInParentScopes().
6753 // Since I don't know where this function is used, I don't want to change it just yet.
6754 printf ("WARNING: SageInterface::lookupVariableSymbolInParentScopes() should be implemented similar to SageInterface::lookupClassSymbolInParentScopes() \n");
6755
6756 SgVariableSymbol* result = NULL;
6757 SgSymbol* symbol=lookupSymbolInParentScopes(name,cscope);
6758 if (symbol != NULL)
6759 {
6760 if (isSgAliasSymbol(symbol) != NULL)
6761 {
6762 printf ("Error: This SageInterface::lookupVariableSymbolInParentScopes() function does not handle SgAliasSymbols \n");
6763 ROSE_ABORT();
6764 }
6765 result = isSgVariableSymbol(symbol);
6766 }
6767 return result;
6768#else
6769 // I think this is the better implementation.
6770 SgVariableSymbol* symbol = NULL;
6771 if (cscope == NULL)
6772 cscope = SageBuilder::topScopeStack();
6773 ROSE_ASSERT(cscope != NULL);
6774
6775 while ((cscope != NULL) && (symbol == NULL))
6776 {
6777 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6778 symbol = cscope->lookup_variable_symbol(name);
6779
6780 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6781 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6782 else
6783 cscope = NULL;
6784 }
6785
6786 return symbol;
6787#endif
6788 }
6789
6790#define DEBUG_LOOKUP_TEMPLATE_VARIABLE 0
6791
6793SageInterface::lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *cscope)
6794 {
6795#if DEBUG_LOOKUP_TEMPLATE_VARIABLE
6796 printf ("In SageInterface::lookupTemplateVariableSymbolInParentScopes():\n");
6797 printf (" -- name = %s\n", name.str());
6798 printf (" -- tplparams = %p [%zd]\n", tplparams, tplparams ? tplparams->size() : 0);
6799 printf (" -- tplargs = %p [%zd]\n", tplargs, tplargs ? tplargs->size() : 0);
6800 printf (" -- cscope = %p (%s)\n", cscope, cscope ? cscope->class_name().c_str() : "");
6801#endif
6802
6803 SgTemplateVariableSymbol* symbol = NULL;
6804 if (cscope == NULL)
6805 cscope = SageBuilder::topScopeStack();
6806 ROSE_ASSERT(cscope != NULL);
6807
6808 while ((cscope != NULL) && (symbol == NULL))
6809 {
6810 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6811 symbol = cscope->lookup_template_variable_symbol(name, tplparams, tplargs);
6812
6813 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6814 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6815 else
6816 cscope = NULL;
6817 }
6818
6819 return symbol;
6820 }
6821
6822// SgClassSymbol* SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6824SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateArgumentPtrList* templateArgumentList)
6825 {
6826 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6827 SgClassSymbol* symbol = NULL;
6828 if (cscope == NULL)
6829 cscope = SageBuilder::topScopeStack();
6830 ROSE_ASSERT(cscope != NULL);
6831
6832 while ((cscope != NULL) && (symbol == NULL))
6833 {
6834 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6835 // symbol = cscope->lookup_class_symbol(name,NULL);
6836 symbol = cscope->lookup_class_symbol(name,templateArgumentList);
6837
6838 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6839 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6840 else
6841 cscope = NULL;
6842 }
6843
6844 return symbol;
6845 }
6846
6848SageInterface::lookupNonrealSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6849 {
6850 SgNonrealSymbol* symbol = NULL;
6851 if (cscope == NULL)
6852 cscope = SageBuilder::topScopeStack();
6853 ROSE_ASSERT(cscope != NULL);
6854
6855 while ((cscope != NULL) && (symbol == NULL))
6856 {
6857 symbol = cscope->lookup_nonreal_symbol(name,templateParameterList,templateArgumentList);
6858
6859 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6860 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6861 else
6862 cscope = NULL;
6863 }
6864
6865 return symbol;
6866 }
6867
6870 {
6871 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6872 SgTypedefSymbol* symbol = NULL;
6873 if (cscope == NULL)
6874 cscope = SageBuilder::topScopeStack();
6875 ROSE_ASSERT(cscope != NULL);
6876
6877#if 0
6878 printf ("In lookupTypedefSymbolInParentScopes(): name = %s starting with cscope = %p = %s \n",name.str(),cscope,cscope->class_name().c_str());
6879 printf ("--- parent scope = %p = %s \n",cscope->get_scope(),(cscope->get_scope() != NULL) ? cscope->get_scope()->class_name().c_str() : "null");
6880#endif
6881
6882 while ((cscope != NULL) && (symbol == NULL))
6883 {
6884 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6885 symbol = cscope->lookup_typedef_symbol(name);
6886
6887 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6888 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6889 else
6890 cscope = NULL;
6891
6892#if 0
6893 printf ("In lookupTypedefSymbolInParentScopes(): symbol = %p next cscope = %p = %s \n",symbol,cscope,(cscope != NULL) ? cscope->class_name().c_str() : "null");
6894#endif
6895 }
6896
6897#if 0
6898 printf ("Leaving lookupTypedefSymbolInParentScopes(): symbol = %p \n",symbol);
6899#endif
6900
6901 return symbol;
6902 }
6903
6904#if 0
6905// DQ (8/13/2013): This function does not make since any more, now that we have make the symbol
6906// table handling more precise and we have to provide template parameters for any template lookup.
6907// We also have to know if we want to lookup template classes, template functions, or template
6908// member functions (since each have specific requirements).
6910SageInterface::lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6911 {
6912 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6913 SgTemplateSymbol* symbol = NULL;
6914 if (cscope == NULL)
6915 cscope = SageBuilder::topScopeStack();
6916 ROSE_ASSERT(cscope != NULL);
6917
6918 while ((cscope != NULL) && (symbol == NULL))
6919 {
6920 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
6921 // In this case these are unavailable from this point.
6922 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6923 // symbol = cscope->lookup_template_symbol(name);
6924 symbol = cscope->lookup_template_symbol(name,NULL,NULL);
6925#if 0
6926 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
6927#endif
6928 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6929 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6930 else
6931 cscope = NULL;
6932 }
6933
6934 return symbol;
6935 }
6936#endif
6937
6938
6940SageInterface::lookupTemplateClassSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope)
6941 {
6942 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6943 SgTemplateClassSymbol* symbol = NULL;
6944 if (cscope == NULL)
6945 cscope = SageBuilder::topScopeStack();
6946 ROSE_ASSERT(cscope != NULL);
6947
6948 while ((cscope != NULL) && (symbol == NULL))
6949 {
6950 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
6951 // In this case these are unavailable from this point.
6952 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6953 // symbol = cscope->lookup_template_symbol(name);
6954 symbol = cscope->lookup_template_class_symbol(name,templateParameterList,templateArgumentList);
6955#if 0
6956 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
6957#endif
6958 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6959 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6960 else
6961 cscope = NULL;
6962 }
6963
6964 return symbol;
6965 }
6966
6967
6970 {
6971 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6972 // A templated solution might make for a better implementation.
6973 SgEnumSymbol* symbol = NULL;
6974 if (cscope == NULL)
6975 cscope = SageBuilder::topScopeStack();
6976 ROSE_ASSERT(cscope != NULL);
6977
6978 while ((cscope != NULL) && (symbol == NULL))
6979 {
6980 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6981 symbol = cscope->lookup_enum_symbol(name);
6982
6983 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6984 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6985 else
6986 cscope = NULL;
6987 }
6988
6989 return symbol;
6990 }
6991
6994 {
6995 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6996 SgNamespaceSymbol* symbol = NULL;
6997 if (cscope == NULL)
6998 cscope = SageBuilder::topScopeStack();
6999 ROSE_ASSERT(cscope != NULL);
7000
7001 while ((cscope != NULL) && (symbol == NULL))
7002 {
7003 // I think this will resolve SgAliasSymbols to be a SgNamespaceSymbol where the alias is of a SgNamespaceSymbol.
7004 symbol = cscope->lookup_namespace_symbol(name);
7005
7006 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7007 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7008 else
7009 cscope = NULL;
7010 }
7011
7012 return symbol;
7013 }
7014
7015template<class T>
7016void
7017SageInterface::setSourcePositionToDefault( T* node )
7018 {
7019 // This is a templated function because SgPragma is not yet derived from SgLocatedNode.
7020
7021 // DQ (2/17/2013): This function is called a lot, so it might be a performance issue.
7022 // All IR nodes built by the Build Interface are assighed source position information
7023 // using this function and then reset afterward as we use information within EDG to
7024 // reset the source position information. Ideally, the EDG/ROSE connection would
7025 // use NULL pointers as the behavior for the front-end mode. We can move to that
7026 // later to maek the source position handling more efficient.
7027
7028 // DQ (1/24/2009): It might be that this function is only called from the Fortran support.
7029
7030 // This function sets the source position to be marked as not
7031 // available (since we often don't have token information)
7032 // These nodes WILL be unparsed in the conde generation phase.
7033
7034 // The SgLocatedNode has both a startOfConstruct and endOfConstruct source position.
7035 ROSE_ASSERT(node != NULL);
7036
7037 // We have to support this being called where the Sg_File_Info have previously been set.
7038 if (node->get_endOfConstruct() == NULL && node->get_startOfConstruct() == NULL)
7039 {
7040#if 0
7041 printf ("Both startOfConstruct and endOfConstruct are NOT yet initialized with pointers to Sg_File_Info objects (node = %p = %s) \n",node,node->class_name().c_str());
7042#endif
7043 // Check the endOfConstruct first since it is most likely NULL (helpful in debugging)
7044 ROSE_ASSERT(node->get_endOfConstruct() == NULL);
7045 ROSE_ASSERT(node->get_startOfConstruct() == NULL);
7046
7049
7050 // DQ (5/2/2012): I think we don't want to do this.
7051#if 0
7052 printf ("In SageInterface::setSourcePositionToDefault(): Calling setSourcePositionUnavailableInFrontend() \n");
7053#endif
7054 start_fileInfo->setSourcePositionUnavailableInFrontend();
7055 end_fileInfo->setSourcePositionUnavailableInFrontend();
7056
7057 // DQ (5/2/2012): I think we don't want to do this.
7058#if 0
7059 printf ("In SageInterface::setSourcePositionToDefault(): Calling setOutputInCodeGeneration() \n");
7060#endif
7061 // This is required for the unparser to output the code from the AST.
7062 start_fileInfo->setOutputInCodeGeneration();
7063 end_fileInfo->setOutputInCodeGeneration();
7064
7065 node->set_startOfConstruct(start_fileInfo);
7066 node->set_endOfConstruct (end_fileInfo);
7067
7068 node->get_startOfConstruct()->set_parent(node);
7069 node->get_endOfConstruct ()->set_parent(node);
7070 }
7071 else
7072 {
7073 // If both the starting and ending Sg_File_Info pointers are not NULL then both must be valid.
7074 // We don't want to support partially completed source code position information.
7075#if 0
7076 printf ("Both startOfConstruct and endOfConstruct are ALREADY initialized with pointers to Sg_File_Info objects (node = %p = %s) \n",node,node->class_name().c_str());
7077#endif
7078 if (node->get_startOfConstruct() == NULL)
7079 {
7080 printf ("ERROR: startOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7081 }
7082 if (node->get_endOfConstruct() == NULL)
7083 {
7084 printf ("ERROR: endOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7085 }
7086
7087 ROSE_ASSERT(node->get_startOfConstruct() != NULL);
7088 ROSE_ASSERT(node->get_endOfConstruct() != NULL);
7089 ROSE_ASSERT(node->get_endOfConstruct() != NULL && node->get_startOfConstruct() != NULL);
7090 }
7091
7092 // DQ (11/2/2012): This is an important fix to support the new EDG 4.x branch.
7093 // Note that because the unparser will use the function isFromAnotherFile() in the unparsing
7094 // of expressions, specifically: SgAggregateInitializer, SgCompoundInitializer, and anything
7095 // in their expression lists (which could be any expression). The isFromAnotherFile() will
7096 // use the get_file_info() function on the SgExpression IR nodes and the data from that
7097 // Sg_File_Info object to determine if that expression subtree should be unparsed. This
7098 // expression level granularity of unparsing capability is extremely useful in handling
7099 // now #includes and other CPP directives are woven back into the AST. But since the
7100 // get_file_info() function is used, and it returns the value of get_operatorPosition(),
7101 // it is critically important to have correct data in the SgExpression::p_operatorPosition
7102 // Sg_File_Info object (it counts more that the startOfConstruct and endOfConstruct
7103 // Sg_File_Info objects in controlling what expressions are unparsed. So we have to set these
7104 // up for all expressions (since any SgExpression could appear in the list contained in
7105 // a SgAggregateInitializer or SgCompoundInitializer.
7106
7107 // DQ (11/2/2012): Set the operator source position information to default values.
7108 // This will trigger it to be reset to valid source position information in the front-end.
7109 SgExpression* expression = isSgExpression(node);
7110 if (expression != NULL)
7111 {
7112#if 0
7113 SgBinaryOp* binaryOp = isSgBinaryOp(expression);
7114 if (binaryOp != NULL)
7115 {
7116 if (binaryOp->get_operatorPosition() == NULL)
7117 {
7119 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7120 operator_fileInfo->setOutputInCodeGeneration();
7121 binaryOp->set_operatorPosition(operator_fileInfo);
7122
7123 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7124 binaryOp->get_operatorPosition()->set_parent(binaryOp);
7125 }
7126 }
7127#else
7128 // Setup all of the SgExpression operatorPosition pointers to default objects.
7129 if (expression->get_operatorPosition() == NULL)
7130 {
7132 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7133 operator_fileInfo->setOutputInCodeGeneration();
7134 expression->set_operatorPosition(operator_fileInfo);
7135
7136 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7137 // expression->get_operatorPosition()->set_parent(expression);
7138 operator_fileInfo->set_parent(expression);
7139 ROSE_ASSERT(expression->get_operatorPosition()->get_parent() == expression);
7140 }
7141#endif
7142 }
7143 }
7144
7145
7146void
7148 {
7149 // DQ (5/1/2012): Older depricated function.
7150#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
7151 printf ("+++++ Depricated function (use setSourcePositionAsTransformation() instead) (no using internal source position mode) \n");
7152#endif
7153
7154 // setSourcePositionAsTransformation(node);
7155 setSourcePosition(node);
7156 }
7157
7158
7159void
7161 {
7162 // DQ (5/1/2012): Newer function to support specification of IR nodes being a part of a transformation.
7163
7164 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionAsTransformation(SgNode *node)"
7165 // The logic should be make more independent of if (locatedNode->get_startOfConstruct() == NULL)
7166 // Since that make understanding where the function is applied too complex.
7167 // If (locatedNode->get_startOfConstruct() != NULL), then we should just make that Sg_File_Info as
7168 // a transforamtion directly, this function misses that step.
7169
7170 ROSE_ASSERT(node != NULL);
7171
7172 // DQ (10/12/2012): Commented out since we are past AST regression tests passing and now trying to get this work checked in.
7173// printf ("In SageInterface::setSourcePositionAsTransformation() for node = %p = %s (make this an error while debugging AST construction) \n",node,node->class_name().c_str());
7174 // ROSE_ASSERT(false);
7175
7176 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7177 SgExpression* expression = isSgExpression(node);
7178 // SgInitializedName* initName = isSgInitializedName(node);
7179 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7180 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7181
7182#if 0
7183 SgVariableDefinition * v_d = isSgVariableDefinition(node);
7184 if (v_d )
7185 printf ("Debug, Found a variable definition: %p\n", v_d);
7186#endif
7187
7188 if (locatedNode != NULL)
7189 {
7191 locatedNode->get_startOfConstruct()->set_parent(locatedNode);
7192
7193 if (global==NULL)
7194 {
7196 locatedNode->get_endOfConstruct ()->set_parent(locatedNode);
7197 }
7198
7199 // Only SgExpression IR nodes have a 3rd source position data structure.
7200 if (expression!=NULL)
7201 {
7202 expression->set_operatorPosition(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7203 expression->get_operatorPosition()->set_parent(expression);
7204 }
7205 }
7206 else // special non-located node with file info
7207 {
7208 if ( (pragma != NULL) && (pragma->get_startOfConstruct() == NULL) )
7209 {
7210 pragma->set_startOfConstruct(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7211 pragma->get_startOfConstruct()->set_parent(pragma);
7212 }
7213 }
7214 }
7215
7216
7217void
7219 {
7220 // DQ (5/1/2012): Older depricated function (use setSourcePositionPointersToNull() instead).
7221#if 0
7222 printf ("+++++ Depricated name setOneSourcePositionNull() (use setSourcePositionPointersToNull() instead) (no using internal source position mode) \n");
7223#endif
7224
7225 setSourcePosition(node);
7226 }
7227
7228// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
7229void
7231 {
7232 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionToNULL(SgNode *node)"
7233 // However, if this is doen then the logic should be that it asserts that: (locatedNode->get_startOfConstruct() == NULL)
7234 // so that we know when we are leaking memory. Similarly, we should assert that:
7235 // (locatedNode->get_endOfConstruct() == NULL).
7236 // But then this function just asserts that everything is already NULL and is less about setting them to NULL.
7237 // If (locatedNode->get_startOfConstruct() != NULL), should we delete the existing Sg_File_Info object?
7238 // This function misses that step.
7239
7240 ROSE_ASSERT(node != NULL);
7241
7242 SgLocatedNode * locatedNode = isSgLocatedNode(node);
7243 SgExpression* expression = isSgExpression(node);
7244 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7245 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7246
7247 // DQ (1/24/2009): If the point is to set the source position to NULL pointers,
7248 // why do we only handle the case when (get_startOfConstruct() == NULL)
7249 // (i.e. when the start source postion is already NULL).
7250
7251 if (locatedNode != NULL)
7252 {
7253 if (locatedNode->get_startOfConstruct() != NULL)
7254 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of startOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7255
7256 locatedNode->set_startOfConstruct(NULL);
7257
7258 // Note that SgGlobal should have NULL endOfConstruct()
7259 if (global == NULL)
7260 {
7261 if (locatedNode->get_endOfConstruct() != NULL)
7262 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of endOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7263
7264 locatedNode->set_endOfConstruct(NULL);
7265 }
7266
7267 // Only SgExpression IR nodes have a 3rd source position data structure.
7268 if (expression != NULL)
7269 {
7270 if (expression->get_operatorPosition() != NULL)
7271 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of operatorPosition Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7272
7273 expression->set_operatorPosition(NULL);
7274 }
7275 }
7276 else
7277 {
7278 if ( (pragma != NULL) && (pragma->get_startOfConstruct() != NULL) )
7279 {
7280 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7281
7282 pragma->set_startOfConstruct(NULL);
7283 }
7284 }
7285 }
7286
7287// DQ (1/24/2009): Could we change the name to be "setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)"
7288void
7290 {
7291#if 1
7292#if 0
7293 printf ("+++++ Depricated name setSourcePositionForTransformation() (use setSourcePositionAtRootAndAllChildrenAsTransformation() instead) \n");
7294#endif
7295
7296 // This is the semantically correct function to call.
7297 // setSourcePositionAtRootAndAllChildrenAsTransformation(root);
7298
7299 // DQ (5/2/2012): This is a test to replace the support we have to mark every thing as a transformation with the new mechanism using source position modes.
7300 // setSourcePosition(root);
7301 // Liao 11/21/2012. This function should only be called when the mode is transformation
7302 // Liao 8/2/2013. It can actually be called inside frontend by OmpSupport::lower_omp().
7303 //ROSE_ASSERT(SageBuilder::SourcePositionClassificationMode == SageBuilder::e_sourcePositionTransformation);
7305#else
7306 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7307 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7308 {
7310 }
7311#endif
7312 }
7313
7314
7315#if 0
7316// DQ (5/1/2012): New function with improved name (still preserving the previous interface).
7317void
7318SageInterface::setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)
7319 {
7320 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7321 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7322 {
7324 }
7325 }
7326#endif
7327
7328#if 0
7329void
7330SageInterface::setSourcePositionAtRootAndAllChildrenAsDefault(SgNode *root)
7331 {
7332 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7333 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7334 {
7335 setSourcePositionAsDefault(*i);
7336 }
7337 }
7338#endif
7339
7340void
7342 {
7343 // DQ (2/17/2013): This is a relatively expensive operation so we might look into this.
7344
7345 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7346
7347#if 0
7348 printf ("In setSourcePositionAtRootAndAllChildren(): nodeList.size() = %" PRIuPTR " \n",nodeList.size());
7349#endif
7350
7351 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
7352 {
7353#if 0
7354 printf ("In setSourcePositionAtRootAndAllChildren(): *i = %p = %s \n",*i,(*i)->class_name().c_str());
7355#endif
7357 }
7358 }
7359
7360// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
7361// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects). This
7362// function is the only function that should be called directly (though in a namespace we can't define permissions).
7363void
7365 {
7366 // Check the mode and build the correct type of source code position.
7368
7369 // DQ (2/17/2013): Note that the SourcePositionClassification will be e_sourcePositionFrontendConstruction
7370 // during construction of the AST from the EDG frontend.
7371
7372#if 0
7373 printf ("In SageInterface::setSourcePosition(): SourcePositionClassification scp = %s \n",display(scp).c_str());
7374#endif
7375
7376 switch(scp)
7377 {
7378 case e_sourcePositionError: // Error value for enum.
7379 {
7380 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7381 ROSE_ABORT();
7382 }
7383
7384 case e_sourcePositionDefault: // Default source position.
7385 {
7386#if 0
7387 printf ("e_sourcePositionDefault in SageInterface::setSourcePosition() \n");
7388#endif
7389 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7390 if (locatedNode != NULL)
7391 {
7392 setSourcePositionToDefault(locatedNode);
7393 }
7394 else
7395 {
7396 // This is not supported (not clear if it need be).
7397 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionDefault with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7398 ROSE_ABORT();
7399 }
7400 break;
7401 }
7402
7403 case e_sourcePositionTransformation: // Classify as a transformation.
7404 {
7405#if 0
7406 printf ("e_sourcePositionTransformation in SageInterface::setSourcePosition() \n");
7407#endif
7408 // setSourcePositionAtRootAndAllChildrenAsTransformation(node);
7410 break;
7411 }
7412
7413 case e_sourcePositionCompilerGenerated: // Classify as compiler generated code (e.g. template instantiation).
7414 {
7415 printf ("e_sourcePositionCompilerGenerated in SageInterface::setSourcePosition() \n");
7416
7417 printf ("Sorry, not implemented \n");
7418 ROSE_ABORT();
7419 }
7420
7421 case e_sourcePositionNullPointers: // Set pointers to Sg_File_Info objects to NULL.
7422 {
7423 // DQ (2/17/2013): We want to move to this mode as the one used for EDG/ROSE connection so that we can
7424 // avoid building and rebuilding source position information.
7425#if 0
7426 printf ("e_sourcePositionNullPointers in SageInterface::setSourcePosition() \n");
7427#endif
7429 break;
7430 }
7431
7432 case e_sourcePositionFrontendConstruction: // Specify as source position to be filled in as part of AST construction in the front-end.
7433 {
7434 // DQ (2/17/2013): The setSourcePositionToDefault() function is called a lot, so it might be a performance issue.
7435 // All IR nodes built by the Build Interface are assighed source position information
7436 // using this function and then reset afterward as we use information within EDG to
7437 // reset the source position information. Ideally, the EDG/ROSE connection would
7438 // use NULL pointers as the behavior for the front-end mode. We can move to that
7439 // later to make the source position handling more efficient.
7440
7441 // This function builds an empty Sg_File_Info entry (valid object but filled with default values; must be reset in front-end processing).
7442#if 0
7443 printf ("e_sourcePositionFrontendConstruction in SageInterface::setSourcePosition() \n");
7444#endif
7445 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7446 if (locatedNode != NULL)
7447 {
7448 // setSourcePositionAtRootAndAllChildrenAsDefault(locatedNode);
7449 setSourcePositionToDefault(locatedNode);
7450 }
7451 else
7452 {
7453 // This is not supported (not clear if it need be).
7454 SgPragma* pragma = isSgPragma(node);
7455 if (pragma != NULL)
7456 {
7457 setSourcePositionToDefault(pragma);
7458 }
7459 else
7460 {
7461 // printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7462 // ROSE_ASSERT(false);
7463 SgType* type = isSgType(node);
7464 if (type != NULL)
7465 {
7466 // Ignore this case, OK.
7467 }
7468 else
7469 {
7470 SgFunctionParameterTypeList* functionParameterTypeList = isSgFunctionParameterTypeList(node);
7471 if (functionParameterTypeList != NULL)
7472 {
7473 // Ignore this case, OK.
7474 }
7475 else
7476 {
7477 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7478 ROSE_ABORT();
7479 }
7480 }
7481 }
7482 }
7483
7484 break;
7485 }
7486
7487
7489 {
7490 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7491 ROSE_ABORT();
7492 }
7493
7494 default:
7495 {
7496 printf ("Error: default reached in SageInterface::setSourcePosition() \n");
7497 break;
7498 }
7499 }
7500
7501#if 0
7502 if (node->get_file_info() != NULL)
7503 {
7504 node->get_file_info()->display("Leaving SageInterface::setSourcePosition()");
7505 }
7506#endif
7507 }
7508
7509#if 0
7510void
7511SageInterface::setSourcePositionForTransformation_memoryPool()
7512 {
7513 // DQ (1/24/2009): This seems like a very dangerous function to have, is it required!
7514
7515 // DQ (5/1/2012): Make it an error to call this function.
7516 printf ("ERROR: In setSourcePositionForTransformation_memoryPool(): This seems like a very dangerous function to have, is it required? \n");
7517 ROSE_ABORT();
7518
7519 VariantVector vv(V_SgNode);
7520 Rose_STL_Container<SgNode*> nodeList = NodeQuery::queryMemoryPool(vv);
7521 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++ )
7522 {
7524 }
7525 }
7526#endif
7527
7529 {
7530 // Liao, 1/9/2008, get the first global scope from current project
7531 // mostly used to prepare for AST construction under the global scope
7532 ROSE_ASSERT(project != NULL);
7533
7534 // DQ (1/24/2009): Added a check to make sure STL list is non-empty.
7535 ROSE_ASSERT(project->get_fileList().empty() == false);
7536
7537 // SgGlobal* global = project->get_file(0).get_root();
7538 SgSourceFile* file = isSgSourceFile(project->get_fileList()[0]);
7539 SgGlobal* global = file->get_globalScope();
7540
7541#if 0
7542 SgFilePtrListPtr fileList = project->get_fileList();
7543 SgFilePtrList::const_iterator i= fileList->begin();
7544
7545 SgGlobal* global = (*i)->get_globalScope();
7546#endif
7547 ROSE_ASSERT(global != NULL);
7548
7549 return global;
7550 }
7551
7552// Liao, 1/10/2008, get the last stmt from the scope
7553// two cases
7554// SgScopeStatement::getDeclarationList
7555// SgScopeStatement::getStatementList()
7557 {
7558 ROSE_ASSERT(scope);
7559 SgStatement* stmt = NULL;
7560
7561 if (scope->containsOnlyDeclarations())
7562 {
7563 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7564 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7565 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7566
7567 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7568 if (declList.empty() == false)
7569 {
7570 stmt = isSgStatement(declList.back());
7571 }
7572 }
7573 else
7574 {
7575 // DQ (2/17/2013): Fixed stmtList to be a reference instead of a copy.
7576 SgStatementPtrList & stmtList = scope->getStatementList();
7577
7578 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7579 if (stmtList.empty() == false)
7580 {
7581 stmt = stmtList.back();
7582 }
7583 }
7584
7585 return stmt;
7586 }
7587
7588
7589SgStatement* SageInterface::getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated/*=false*/)
7590 {
7591 // DQ (2/17/2013): This function appears to be a performance problem (so a pass was made to
7592 // use lower complexity operations that are equivalent in funcionality for this context).
7593
7594 ROSE_ASSERT(scope);
7595 SgStatement* stmt = NULL;
7596
7597 if (scope->containsOnlyDeclarations())
7598 {
7599 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7600 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7601 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7602 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7603 if (includingCompilerGenerated)
7604 {
7605 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7606 // DQ Note: (declList.empty() == false) is a much faster test O(1) than (declList.size() > 0), which is O(n).
7607 if (declList.empty() == false)
7608 {
7609 stmt = isSgStatement(declList.front());
7610 }
7611 }
7612 else
7613 {
7614 // skip compiler-generated declarations
7615 SgDeclarationStatementPtrList::iterator i=declList.begin();
7616 while (i != declList.end())
7617 {
7618 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7619 // some content from headers included are not marked as compiler-generated
7620 //
7621 // cout<<(*i)->unparseToString()<<endl;
7622 // ((*i)->get_file_info())->display("debug.......");
7623 Sg_File_Info * fileInfo = (*i)->get_file_info();
7624 // include transformation-generated statements, but not the hidden ones
7625 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7626 if ((fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation() && fileInfo->isOutputInCodeGeneration()))
7627 {
7628 stmt = *i;
7629 break;
7630 }
7631 else
7632 {
7633 i++;
7634 continue;
7635 }
7636 }
7637 }
7638 }
7639 else
7640 {
7641 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7642 SgStatementPtrList & stmtList = scope->getStatementList();
7643 if (includingCompilerGenerated)
7644 {
7645 // DQ (2/17/2013): Fixed evaluation of empty list use SgStatementPtrList::empty() member function for faster performance.
7646 // DQ Note: (stmtList.empty() == false) is a much faster test O(1) than (stmtList.size() > 0), which is O(n).
7647 if (stmtList.empty() == false)
7648 {
7649 stmt = stmtList.front();
7650 }
7651 }
7652 else
7653 {
7654 // skip compiler-generated declarations
7655 SgStatementPtrList::iterator i = stmtList.begin();
7656 while (i!=stmtList.end())
7657 {
7658 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7659 // some content from headers included are not marked as compiler-generated
7660 //
7661 // cout<<(*i)->unparseToString()<<endl;
7662 // ((*i)->get_file_info())->display("debug.......");
7663 Sg_File_Info * fileInfo = (*i)->get_file_info();
7664 // include transformation-generated statements, but not the hidden ones
7665 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7666 if ( (fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration()))
7667 {
7668 stmt=*i;
7669 break;
7670 }
7671 else
7672 {
7673 i++;
7674 continue;
7675 }
7676 }
7677 }
7678 }
7679
7680 return stmt;
7681 }
7682
7683
7685 {
7686 ROSE_ASSERT(scope);
7687 SgFunctionDeclaration* result = NULL;
7688 if (scope->containsOnlyDeclarations())
7689 {
7690 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7691 SgDeclarationStatementPtrList::iterator i=declList.begin();
7692 while (i!=declList.end())
7693 {
7694 Sg_File_Info * fileInfo = (*i)->get_file_info();
7695
7696 if ((fileInfo->isSameFile(scope->get_file_info()))||
7697 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7698 )
7699 {
7700 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7701 if (func)
7702 {
7703 if (func->get_definingDeclaration ()==func)
7704 {
7705 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7706 result=func;
7707 break;
7708 }
7709 }
7710 }
7711 i++;
7712 }//end while
7713 } else
7714 {
7715 SgStatementPtrList stmtList = scope->getStatementList();
7716 SgStatementPtrList::iterator i=stmtList.begin();
7717 while (i!=stmtList.end())
7718 {
7719 Sg_File_Info * fileInfo = (*i)->get_file_info();
7720 if ( (fileInfo->isSameFile(scope->get_file_info()))||
7721 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7722 )
7723 {
7724 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7725 if (func)
7726 {
7727 if (func->get_definingDeclaration ()==func)
7728 {
7729 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7730 result=func;
7731 break;
7732 }// if defining
7733 } // if func
7734 }// if fileInof
7735 i++;
7736 }//while
7737 } // end if
7738 return result;
7739 }
7740
7741
7743{
7744 bool result = false;
7745 // Liao 1/5/2010, handle Fortran main entry: SgProgramHeaderStatement
7747 if (isSgProgramHeaderStatement(n)) {
7748 result = true;
7749 }
7750 }
7751 else {
7752 if (isSgFunctionDeclaration(n) != nullptr) {
7753 bool either = false;
7755 either = true;
7756 }
7757 else {
7758 const SgStatement* stmnt = isSgStatement(n);
7759 ROSE_ASSERT(stmnt != nullptr);
7760 if (isSgGlobal(stmnt->get_scope())) {
7761 either = true;
7762 }
7763 }
7764 if (either) {
7765 const SgFunctionDeclaration* funcDefn = isSgFunctionDeclaration(n);
7766 ROSE_ASSERT(funcDefn != nullptr);
7767 if (funcDefn->get_name() == "main") {
7768 result = true;
7769 }
7770 }
7771 }
7772 }
7773 return result;
7774}
7775
7776// Originally from ompTranslator.C
7777// DQ (1/6/2007): The correct qualified name for "main" is "::main", at least in C++.
7778// however for C is should be "main". Our name qualification is not language specific,
7779// however, for C is makes no sense to as for the qualified name, so the name we
7780// want to search for could be language specific. The test code test2007_07.C
7781// demonstrates that the function "main" can exist in both classes (as member functions)
7782// and in namespaces (as more meaningfully qualified names). Because of this C++
7783// would have to qualify the global main function as "::main", I think.
7784
7785// Revised by Jeremiah,
7786// Added check to see if the scope is global: Liao
7788 if (!n) return 0;
7789 if (isMain(n))
7790 {
7791 return isSgFunctionDeclaration(n);
7792 }
7793 vector<SgNode*> children = n->get_traversalSuccessorContainer();
7794 for (vector<SgNode*>::const_iterator i = children.begin();
7795 i != children.end(); ++i) {
7796
7797 SgFunctionDeclaration* mainDecl = findMain(*i);
7798 if (mainDecl)
7799 if (mainDecl->get_definingDeclaration() == mainDecl) // skip non-defining main() declaration, Liao 8/27/2010
7800 return mainDecl;
7801 }
7802 return 0;
7803}
7804
7806// another declaration statement can be inserted.
7807// This is useful to find a safe place to insert a declaration statement with special requirements about where it can be inserted.
7808// e.g. a variable declaration statement should not be inserted before IMPLICIT none in Fortran
7809// If it returns NULL, a declaration statement should be able to be prepended to the scope
7811{
7812 SgStatement* rt = NULL;
7813 ROSE_ASSERT (scope != NULL);
7814
7815 SgStatementPtrList stmt_list = scope->generateStatementList ();
7816
7817 for (size_t i = 0; i<stmt_list.size(); i++)
7818 {
7819 SgStatement* cur_stmt = stmt_list[i];
7820 // We should exclude pragma decl. We don't want to insert things after pragmas.
7821 if (isSgDeclarationStatement(cur_stmt))
7822 {
7823 if (isSgPragmaDeclaration (cur_stmt))
7824 {
7825 if (includePragma)
7826 rt = cur_stmt;
7827 }
7828 else
7829 rt = cur_stmt;
7830 }
7831 //if (isSgImplicitStatement(cur_stmt)) || isSgFortranIncludeLine(cur_stmt) || isSgDeclarationStatement
7832 }
7833
7834 return rt;
7835}
7836
7838{
7839 SgNode* rt = NULL;
7840 SgTreeCopy g_treeCopy; // should use a copy object each time of usage!
7841 if (n!= NULL)
7842 {
7843 rt = n->copy (g_treeCopy);
7845 }
7846 // return n ? n->copy (g_treeCopy) : 0;
7847 return rt;
7848}
7849
7850// by Jeremiah
7851// Return bool for C++ code, and int for C code
7853 bool isC = TransformationSupport::getSourceFile(n)->get_outputLanguage() == SgFile::e_C_language;
7854 if (isC) {
7855 return SgTypeInt::createType();
7856 } else {
7857 return SgTypeBool::createType();
7858 }
7859}
7860
7861#if 1
7862// Change continue statements in a given block of code to gotos to a label
7864 {
7865#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
7866 std::vector<SgContinueStmt*> continues = SageInterface::findContinueStmts(stmt);
7867 for (std::vector<SgContinueStmt*>::iterator i = continues.begin(); i != continues.end(); ++i)
7868 {
7869 SgGotoStatement* gotoStatement = SageBuilder::buildGotoStatement(label);
7870 // printf ("Building gotoStatement #1 = %p \n",gotoStatement);
7871#ifndef _MSC_VER
7872 LowLevelRewrite::replace(*i, make_unit_list( gotoStatement ) );
7873#else
7874 ROSE_ABORT();
7875#endif
7876 }
7877#else
7878 printf ("Not supported in mode: ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT (LowLevelRewrite::replace() is unavailable)");
7879 ROSE_ABORT();
7880#endif
7881 }
7882
7883#define DEBUG_TEMPLATE_ARG_EQUIVALENCE 0
7884
7886 {
7887 if (arg1 == arg2)
7888 {
7889#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7890 printf ("In templateArgumentEquivalence(): same pointer to template argument: returning true \n");
7891#endif
7892 return true;
7893 }
7894
7895 if (arg1->get_argumentType() != arg2->get_argumentType())
7896 {
7897#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7898 printf ("In templateArgumentEquivalence(): different argumentType(): returning false \n");
7899#endif
7900 return false;
7901 }
7902
7903 switch (arg1->get_argumentType())
7904 {
7906 {
7907 ROSE_ASSERT(arg1->get_type() != NULL);
7908 ROSE_ASSERT(arg2->get_type() != NULL);
7909
7910#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7911 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: arg1->get_type() = %p = %s arg2->get_type() = %p = %s \n",
7912 arg1->get_type(),arg1->get_type()->class_name().c_str(),
7913 arg2->get_type(),arg2->get_type()->class_name().c_str());
7914#endif
7915 // DQ (5/19/2016): Rewrote to support debugging.
7916 // return arg1->get_type() == arg2->get_type();
7917 if (arg1->get_type() == arg2->get_type())
7918 {
7919#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7920 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: returning true \n");
7921#endif
7922 return true;
7923 }
7924 else
7925 {
7926 // ROSE_ASSERT(!"NIY: non-type template argument comparaison."); /// \todo
7927
7928 // DQ (5/19/2016): Use type equivalence mechanism to handle the case where
7929 // these are different pointers to what might still be the same type.
7930 // return false;
7931 bool typesAreEqual = isEquivalentType(arg1->get_type(),arg2->get_type());
7932
7933#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7934 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: pointers are different: returning typesAreEqual = %s \n",typesAreEqual ? "true" : "false");
7935#endif
7936 return typesAreEqual;
7937 }
7938 }
7939
7941 {
7942 SgExpression * expr1 = arg1->get_expression();
7943 SgExpression * expr2 = arg2->get_expression();
7944 if (expr1 == expr2) {
7945#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7946 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: checking for the same expression: returning true \n");
7947#endif
7948 return true;
7949 } else if (expr1->variantT() == expr2->variantT() ) {
7950#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7951 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: same variant of expression: %s\n", expr1->class_name().c_str());
7952#endif
7953 switch (expr1->variantT()) {
7954 case V_SgLongIntVal: {
7955 return ((SgLongIntVal *)expr1)->get_value() == ((SgLongIntVal *)expr2)->get_value();
7956 }
7957 // DQ (7/21/2024): Adding support for another type (from processing nlohmann/json.hpp with ROSE)
7958 case V_SgUnsignedLongVal:
7959 {
7960 return ((SgUnsignedLongVal*) expr1)->get_value() == ((SgUnsignedLongVal*) expr2)->get_value();
7961 }
7962 // PP (4/10/2025): Adding support for another type (from processing ROSE with ROSE)
7963 case V_SgBoolValExp:
7964 {
7965 return static_cast<SgBoolValExp*>(expr1)->get_value() == static_cast<SgBoolValExp*>(expr2)->get_value();
7966 }
7967 default: {
7968 mlog[Sawyer::Message::Common::FATAL]
7969 << "FATAL: In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: expression have the same variant "
7970 << expr1->class_name()
7971 << " but comparison is not NIY!"
7972 << std::endl;
7973 ROSE_ABORT();
7974 }
7975 }
7976 } else {
7977#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7978 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: different variant of expression: returning false \n");
7979#endif
7980 return false;
7981 }
7982 }
7983
7985 {
7986 if (arg1->get_templateDeclaration() == arg2->get_templateDeclaration())
7987 {
7988#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7989 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::template_template_argument: checking for the same templateDeclaration: returning true \n");
7990#endif
7991 return true;
7992 }
7993 else
7994 {
7995 ROSE_ASSERT(!"NIY: template template argument comparaison.");
7996 }
7997 }
7998
8000 {
8001 ROSE_ASSERT(!"Try to compare template arguments of unknown type...");
8002 }
8003
8004 // DQ (7/19/2015): Added missing case:
8006 {
8007 // Liao 6/24/2016. Handle the simplest case: both arguments are parameter pack.
8009 return true;
8010 ROSE_ASSERT(!"Try to compare template arguments of unknown type start_of_pack_expansion_argument");
8011 }
8012
8013 // DQ (7/19/2015): Added missing default case: we always want to ahve a default case to catch errors and missing cases.
8014 default:
8015 {
8016 printf ("Error: default case not handled! \n");
8017 ROSE_ABORT();
8018 }
8019 }
8020
8021 ROSE_ABORT(); // unreachable code
8022 }
8023
8024#define DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE 0
8025
8026bool SageInterface::templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2)
8027 {
8028 if (list1.size() != list2.size())
8029 {
8030#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8031 printf ("In templateArgumentListEquivalence(): different list sizes: returning false \n");
8032 printf (" --- list1.size() = %zu \n",list1.size());
8033 printf (" --- list2.size() = %zu \n",list2.size());
8034#endif
8035 return false;
8036 }
8037
8038 if (list1 == list2)
8039 {
8040#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8041 printf ("In templateArgumentListEquivalence(): same list using STL equality operator: returning true \n");
8042#endif
8043 return true;
8044 }
8045
8046 // for (unsigned i = 0; i < list1.size(); i++)
8047 for (size_t i = 0; i < list1.size(); i++)
8048 {
8049#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8050 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu \n",i);
8051#endif
8052 // if (!templateArgumentEquivalence(list1[i], list2[i]))
8053 if (templateArgumentEquivalence(list1[i], list2[i]) == false)
8054 {
8055#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8056 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu --- returned false: returning false \n",i);
8057#endif
8058 return false;
8059 }
8060 }
8061
8062#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8063 printf ("In templateArgumentListEquivalence(): reached base of function: returning true \n");
8064#endif
8065
8066 return true;
8067 }
8068
8069// Add a step statement to the end of a loop body
8070// Add a new label to the end of the loop, with the step statement after
8071// it; then change all continue statements in the old loop body into
8072// jumps to the label
8073//
8074// For example:
8075// while (a < 5) {if (a < -3) continue;} (adding "a++" to end) becomes
8076// while (a < 5) {if (a < -3) goto label; label: a++;}
8078 using namespace SageBuilder;
8080 SgStatement* old_body = SageInterface::getLoopBody(loopStmt);
8081 SgBasicBlock* new_body = buildBasicBlock();
8082// printf ("Building IR node #13: new SgBasicBlock = %p \n",new_body);
8083 SgName labelname = "rose_label__";
8084 labelname << ++gensym_counter;
8085 SgLabelStatement* labelstmt = buildLabelStatement(labelname,
8086buildBasicBlock(), proc);
8087 changeContinuesToGotos(old_body, labelstmt);
8088 appendStatement(old_body, new_body);
8089 appendStatement(labelstmt, new_body);
8090 appendStatement(step, new_body);
8091 SageInterface::setLoopBody(loopStmt, new_body);
8092}
8093
8094
8096 if (isSgNullExpression(f->get_increment())) return;
8097 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(f->get_increment());
8098 f->get_increment()->set_parent(incrStmt);
8101 f->set_increment(ne);
8102 ne->set_parent(f);
8103}
8104
8105static
8106bool hasEmptyCondition(SgForStatement* f)
8107{
8108 ROSE_ASSERT(f);
8109
8110 SgStatement* condstmt = f->get_test();
8111 ROSE_ASSERT(condstmt);
8112
8113 if (isSgNullStatement(condstmt)) return true;
8114
8115 SgExprStatement* exprStmt = isSgExprStatement(condstmt);
8116
8117 return isSgNullExpression(exprStmt->get_expression());
8118}
8119
8124 SgStatementPtrList& bbStmts = bb->get_statements();
8125 SgStatementPtrList& initStmts = inits->get_init_stmt();
8126 bbStmts = initStmts;
8127 for (size_t i = 0; i < bbStmts.size(); ++i) {
8128 bbStmts[i]->set_parent(bb);
8129 }
8130
8131 const bool testIsNull = hasEmptyCondition(f);
8133 : f->get_test();
8135
8136 appendStatement(ws, bb);
8137 isSgStatement(f->get_parent())->replace_statement(f, bb);
8138}
8139
8141 Rose_STL_Container<SgNode*> fors = NodeQuery::querySubTree(top,
8142V_SgForStatement);
8143 for (size_t i = 0; i < fors.size(); ++i) {
8144 convertForToWhile(isSgForStatement(fors[i]));
8145 }
8146}
8147
8148 vector<SgGotoStatement*> SageInterface::findGotoStmts(SgStatement* scope, SgLabelStatement* l) {
8149 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8150 // But we still need the copy since the return type is IR node specific.
8151 Rose_STL_Container<SgNode*> allGotos = NodeQuery::querySubTree(scope, V_SgGotoStatement);
8152
8153 vector<SgGotoStatement*> result;
8154 for (Rose_STL_Container<SgNode*>::const_iterator i = allGotos.begin(); i != allGotos.end(); ++i) {
8155 if (isSgGotoStatement(*i)->get_label() == l) {
8156 result.push_back(isSgGotoStatement(*i));
8157 }
8158 }
8159 return result;
8160 }
8161
8162#if 0 // Liao 5/21/2010. This is a bad function in terms of performance
8163 // vectors are created/destroyed multiple times
8164 vector<SgReturnStmt*> SageInterface::findReturnStmts(SgStatement* scope) {
8165 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8166 // But we still need the copy since the return type is IR node specific.
8167 Rose_STL_Container<SgNode*> returns = NodeQuery::querySubTree(scope, V_SgReturnStmt);
8168
8169 vector<SgReturnStmt*> result;
8170 for (Rose_STL_Container<SgNode*>::const_iterator i = returns.begin(); i != returns.end(); ++i) {
8171 result.push_back(isSgReturnStmt(*i));
8172 }
8173 return result;
8174 }
8175
8176#endif
8177static void getSwitchCasesHelper(SgStatement* top, vector<SgStatement*>& result) {
8178 ROSE_ASSERT (top);
8179 if (isSgSwitchStatement(top)) return; // Don't descend into nested switches
8180 if (isSgCaseOptionStmt(top) || isSgDefaultOptionStmt(top)) {
8181 result.push_back(top);
8182 }
8183 vector<SgNode*> children = top->get_traversalSuccessorContainer();
8184 for (unsigned int i = 0; i < children.size(); ++i) {
8185 if (isSgStatement(children[i])) {
8186 getSwitchCasesHelper(isSgStatement(children[i]), result);
8187 }
8188 }
8189 }
8190
8192 vector<SgStatement*> result;
8193 getSwitchCasesHelper(sw->get_body(), result);
8194 return result;
8195 }
8196
8197
8198#endif
8199
8206SgScopeStatement* SageInterface::getEnclosingScope(SgNode* n, const bool includingSelf/* =false*/)
8207{
8208 SgScopeStatement* result = getScope (n);
8209 if (result == n)
8210 {
8211 if (!includingSelf)
8212 result = getScope(n->get_parent());
8213 }
8214 return result;
8215}
8216
8217// from transformationSupport.C
8220 {
8221
8222 // Case 1: directly call get_scope() for some types of nodes
8223 if (const SgSymbol* symbol = isSgSymbol(astNode))
8224 return symbol->get_scope();
8225 else if (const SgInitializedName* initName = isSgInitializedName(astNode))
8226 return initName->get_scope();
8227 else if (const SgTemplateArgument* tempArg = isSgTemplateArgument(astNode))
8228 return tempArg->get_scope();
8229 else if (const SgQualifiedName* qualifiedName = isSgQualifiedName(astNode))
8230 return qualifiedName->get_scope();
8231
8232 // DQ (6/9/2007): This function traverses through the parents to the first scope (used for name qualification support of template arguments)
8233 const SgNode* parentNode = astNode;
8234 while (!isSgScopeStatement(parentNode))
8235 {
8236 //George Vulov (11/29/2010)
8237 //Function parameter lists are siblings of SgFunctionDefinition, so just going up to parents
8238 //produces SgGlobal.
8239 if (isSgFunctionParameterList(parentNode) || isSgCtorInitializerList(parentNode))
8240 {
8241 const SgFunctionDeclaration* funcDeclaration = isSgFunctionDeclaration(parentNode->get_parent());
8242 ROSE_ASSERT(funcDeclaration != NULL);
8243 funcDeclaration = isSgFunctionDeclaration(funcDeclaration->get_definingDeclaration());
8244 if (funcDeclaration != NULL)
8245 {
8246 return funcDeclaration->get_definition();
8247 }
8248 }
8249
8250 parentNode = parentNode->get_parent();
8251 if (parentNode == NULL)
8252 {
8253 break;
8254 }
8255 }
8256
8257 // Check to see if we made it back to the root (current root is SgProject).
8258 // It is also OK to stop at a node for which get_parent() returns NULL (SgType and SgSymbol nodes).
8259 if ( isSgScopeStatement(parentNode) == NULL &&
8260 dynamic_cast<const SgType*>(parentNode) == NULL &&
8261 dynamic_cast<const SgSymbol*>(parentNode) == NULL )
8262 {
8263 printf ("Error: In SageInterface::getScope(): could not trace back to SgScopeStatement node \n");
8264 ROSE_ABORT();
8265 }
8266 else
8267 {
8268 if ( dynamic_cast<const SgType*>(parentNode) != NULL || dynamic_cast<const SgSymbol*>(parentNode) != NULL )
8269 {
8270 printf ("Error: can't locate an associated SgStatement from astNode = %p = %s parentNode = %p = %s \n",astNode,astNode->class_name().c_str(),parentNode,parentNode->class_name().c_str());
8271 return NULL;
8272 }
8273 }
8274
8275 // Make sure we have a SgStatement node
8276 const SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8277 //SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8278 ROSE_ASSERT (scopeStatement != NULL);
8279
8280 // ensure the search is inclusive
8281 if (isSgScopeStatement(astNode))
8282 if (isSgScopeStatement(parentNode))
8283 {
8284 ROSE_ASSERT (astNode == parentNode);
8285 }
8286
8287 // return scopeStatement;
8288 return const_cast<SgScopeStatement*>(scopeStatement);
8289 }
8290
8291
8292// from outliner, ASTtools
8293// ------------------------------------------------
8294
8302static
8303const SgVariableSymbol *
8304getVarSymFromName_const (const SgInitializedName* name)
8305 {
8306 SgVariableSymbol* v_sym = NULL;
8307
8308 if (name != NULL)
8309 {
8310#if 0
8311 printf ("In getVarSymFromName(): name->get_name() = %s \n",name->get_name().str());
8312#endif
8313 SgScopeStatement* scope = name->get_scope();
8314 ROSE_ASSERT (scope != NULL);
8315#if 0
8316 printf ("In getVarSymFromName(): name->get_name() = %s scope = %p = %s \n",name->get_name().str(),scope,scope->class_name().c_str());
8317#endif
8318 v_sym = scope->lookup_var_symbol (name->get_name());
8319
8320 if (!v_sym) // E.g., might be part of an 'extern' declaration.
8321 {
8322 // Try the declaration's scope.
8323 SgDeclarationStatement* decl = name->get_declaration ();
8324 ROSE_ASSERT (decl);
8325
8326 SgScopeStatement* decl_scope = decl->get_scope ();
8327 if (decl_scope != NULL)
8328 v_sym = decl_scope->lookup_var_symbol (name->get_name());
8329
8330 if (!v_sym)
8331 cerr << "\t\t*** WARNING: Can't seem to find a symbol for '"
8332 << name->get_name ().str ()
8333 << "' ***" << endl;
8334 }
8335 }
8336
8337 return v_sym;
8338 }
8339
8340#if 0
8348static
8350getVarSymFromName (SgInitializedName* name)
8351{
8352 const SgVariableSymbol* v_sym = getVarSymFromName_const (name);
8353 return const_cast<SgVariableSymbol *> (v_sym);
8354}
8355#endif
8360static
8361const SgVariableSymbol *
8362getVarSym_const (const SgNode* n)
8363{
8364 const SgVariableSymbol* v_sym = 0;
8365 switch (n->variantT ())
8366 {
8367 case V_SgVarRefExp:
8368 v_sym = isSgVarRefExp (n)->get_symbol ();
8369 break;
8370 case V_SgInitializedName:
8371 v_sym = getVarSymFromName_const (isSgInitializedName (n));
8372 break;
8373 default:
8374 break;
8375 }
8376 return v_sym;
8377}
8378
8379#if 0
8384static
8386getVarSym (SgNode* n)
8387{
8388 const SgVariableSymbol* v_sym = getVarSym_const (n);
8389 return const_cast<SgVariableSymbol *> (v_sym);
8390}
8391#endif
8392
8393static
8394const SgVariableSymbol *
8395getFirstVarSym_const (const SgVariableDeclaration* decl)
8396{
8397 if (!decl) return 0;
8398 const SgInitializedNamePtrList& names = decl->get_variables ();
8399 if (names.begin () != names.end ())
8400 {
8401 const SgInitializedName* name = *(names.begin ());
8402 return getVarSym_const (name);
8403 }
8404 else
8405 return 0;
8406}
8407
8410{
8411 const SgVariableSymbol* sym = getFirstVarSym_const (decl);
8412 return const_cast<SgVariableSymbol *> (sym);
8413}
8414
8415
8418{
8419 ROSE_ASSERT(decl);
8420 SgInitializedNamePtrList& names = decl->get_variables ();
8421 if (names.begin () != names.end ())
8422 return *(names.begin ());
8423 else
8424 return NULL;
8425}
8426
8427
8428static void findBreakStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgBreakStmt*>& breakStmts) {
8429 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code) || isSgSwitchStatement(code)) {
8430 if (fortranLabel == "") {
8431 // Outermost loop only
8432 return;
8433 } else {
8434 // Set this for query on children
8435 inOutermostBody = false;
8436 }
8437 }
8438 if (isSgBreakStmt(code)) {
8439 SgBreakStmt* bs = isSgBreakStmt(code);
8440 bool breakMatchesThisConstruct = false;
8441 if (bs->get_do_string_label() == "") {
8442 // Break matches closest construct
8443 breakMatchesThisConstruct = inOutermostBody;
8444 } else {
8445 breakMatchesThisConstruct = (fortranLabel == bs->get_do_string_label());
8446 }
8447 if (breakMatchesThisConstruct) {
8448 breakStmts.push_back(bs);
8449 }
8450 return;
8451 }
8452 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8453 for (unsigned int i = 0; i < children.size(); ++i) {
8454 if (isSgStatement(children[i])) {
8455 findBreakStmtsHelper(isSgStatement(children[i]), fortranLabel, inOutermostBody, breakStmts);
8456 }
8457 }
8458}
8459
8460vector<SgBreakStmt*> SageInterface::findBreakStmts(SgStatement* code, const std::string& fortranLabel) {
8461 // Run this on the body of a loop or switch, because it stops at any
8462 // construct which defines a new scope for break statements
8463 vector<SgBreakStmt*> result;
8464 findBreakStmtsHelper(code, fortranLabel, true, result);
8465 return result;
8466}
8467
8468
8469static void findContinueStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgContinueStmt*>& continueStmts) {
8470 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code)) {
8471 if (fortranLabel == "") {
8472 // Outermost loop only
8473 return;
8474 } else {
8475 // Set this for query on children
8476 inOutermostBody = false;
8477 }
8478 }
8479 if (isSgContinueStmt(code)) {
8480 SgContinueStmt* cs = isSgContinueStmt(code);
8481 bool continueMatchesThisConstruct = false;
8482 if (cs->get_do_string_label() == "") {
8483 // Continue matches closest construct
8484 continueMatchesThisConstruct = inOutermostBody;
8485 } else {
8486 continueMatchesThisConstruct = (fortranLabel == cs->get_do_string_label());
8487 }
8488 if (continueMatchesThisConstruct) {
8489 continueStmts.push_back(cs);
8490 }
8491 return;
8492 }
8493 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8494 for (unsigned int i = 0; i < children.size(); ++i) {
8495 SgStatement* stmnt = isSgStatement(children[i]);
8496 if (stmnt != NULL) {
8497 findContinueStmtsHelper(stmnt, fortranLabel, inOutermostBody, continueStmts);
8498 }
8499 }
8500}
8501
8502vector<SgContinueStmt*> SageInterface::findContinueStmts(SgStatement* code, const std::string& fortranLabel) {
8503 // Run this on the body of a loop, because it stops at any construct which
8504 // defines a new scope for continue statements
8505 vector<SgContinueStmt*> result;
8506 findContinueStmtsHelper(code, fortranLabel, true, result);
8507 return result;
8508}
8509
8510
8511// Get the initializer containing an expression if it is within an
8512// initializer.
8513// from replaceExpressionWithStatement.C
8515 assert(n);
8516#if 0
8517 std::cout << "Starting getInitializerOfExpression on 0x" << std::hex << (int)n << ", which has type " << n->sage_class_name() << std::endl;
8518#endif
8519 while (!isSgInitializer(n)) {
8520 n = isSgExpression(n->get_parent());
8521#if 0
8522 std::cout << "Continuing getInitializerOfExpression on 0x" << std::hex << (int)n;
8523 if (n) std::cout << ", which has type " << n->sage_class_name();
8524 std::cout << std::endl;
8525#endif
8526 assert(n);
8527 }
8528 return isSgInitializer(n);
8529}
8530
8531#ifndef USE_ROSE
8532// Get all symbols used in a given expression
8534 class GetSymbolsUsedInExpressionVisitor: public AstSimpleProcessing {
8535 public:
8536 std::vector<SgVariableSymbol*> symbols;
8537
8538 virtual void visit(SgNode* n) {
8539 if (isSgVarRefExp(n))
8540 symbols.push_back(isSgVarRefExp(n)->get_symbol());
8541 }
8542 };
8543
8544 GetSymbolsUsedInExpressionVisitor vis;
8545 vis.traverse(expr, preorder);
8546 return vis.symbols;
8547}
8548#endif
8549
8552 return getEnclosingNode<SgSourceFile>(n, includingSelf);
8553}
8554
8555
8557{
8558 return findDeclarationStatement<SgFunctionDeclaration> (root, name, scope, isDefining);
8559}
8560
8561
8563{
8564 return getEnclosingFunctionDefinition(n,includingSelf);
8565}
8566
8569 return getEnclosingNode<SgFunctionDefinition>(n, includingSelf);
8570}
8571
8572
8575 return getEnclosingNode<SgFunctionDeclaration>(astNode, includingSelf);
8576}
8577
8578// #endif
8579
8580// #ifndef USE_ROSE
8581
8582SgGlobal*
8584 // should including itself in this case
8585 return getEnclosingNode<SgGlobal>(astNode, true /*includingSelf*/);
8586}
8587
8589SageInterface::getEnclosingClassDefinition(SgNode* astNode, const bool includingSelf/* =false*/) {
8590 return getEnclosingNode<SgClassDefinition>(astNode, includingSelf);
8591}
8592
8593
8596 // DQ (1/24/2019): This might have to get the SgClassDefinition and then the SgClassDeclaration from that.
8597 // I'm having trouble making this work for a member function declared outside of the class definition.
8598 return getEnclosingNode<SgClassDeclaration>(astNode, true);
8599}
8600
8602SageInterface::getEnclosingExprListExp(SgNode* astNode, const bool includingSelf/* =false*/) {
8603 return getEnclosingNode<SgExprListExp>(astNode, includingSelf);
8604}
8605
8606bool
8608 {
8609 bool returnValue = false;
8610
8611 struct Visitor: public AstSimpleProcessing
8612 {
8613 SgExpression* expression_target;
8614 bool in_subtree;
8615 virtual void visit(SgNode* n)
8616 {
8617 if (n == expression_target)
8618 {
8619 in_subtree = true;
8620 }
8621 }
8622
8623 Visitor(SgExpression* expr) : expression_target(expr), in_subtree(false) {}
8624 };
8625
8626 Visitor traversal(exp);
8627
8628 traversal.traverse(subtree, preorder);
8629
8630 returnValue = traversal.in_subtree;
8631
8632 return returnValue;
8633 }
8634
8635
8638 {
8639 // DQ (2/7/2019): Added more general function to support extraction of the associated function declaration.
8640 // The lower level functions are more robust on the SgFunctionRefExp and SgMemberFunctionRefExp than
8641 // when called on the SgFunctionCallExp for example.
8642
8643 // SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
8644 ROSE_ASSERT (functionCallExp != NULL);
8645
8646 SgExpression* expression = functionCallExp->get_function();
8647 ROSE_ASSERT (expression != NULL);
8648
8649 SgFunctionDeclaration* returnDeclaration = NULL;
8650
8651 SgDotExp* dotExp = isSgDotExp(expression);
8652 if (dotExp != NULL)
8653 {
8654 ROSE_ASSERT (dotExp != NULL);
8655
8656 SgExpression* rhsOperand = dotExp->get_rhs_operand();
8657 ROSE_ASSERT (rhsOperand != NULL);
8658
8659 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8660
8661 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8662 if (memberFunctionRefExp != NULL)
8663 {
8664 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8665 }
8666 }
8667
8668 SgFunctionRefExp* functionReferenceExp = isSgFunctionRefExp(expression);
8669 if (functionReferenceExp != NULL)
8670 {
8671 returnDeclaration = functionReferenceExp->getAssociatedFunctionDeclaration();
8672 }
8673
8674 SgArrowExp* arrowExp = isSgArrowExp(expression);
8675 if ( arrowExp != NULL)
8676 {
8677 ROSE_ASSERT (arrowExp != NULL);
8678
8679 SgExpression* rhsOperand = arrowExp->get_rhs_operand();
8680 ROSE_ASSERT (rhsOperand != NULL);
8681
8682 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8683
8684 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8685 if (memberFunctionRefExp != NULL)
8686 {
8687 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8688 }
8689 }
8690
8691 return returnDeclaration;
8692 }
8693
8694
8695
8696std::list<SgClassType*>
8698 {
8699 // DQ (2/16/2019): This version support for data member name qualification return type chains.
8700
8701#define DEBUG_DATA_MEMBER_TYPE_CHAIN 0
8702
8703 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
8704 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
8705 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
8706
8707 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
8708
8709 std::list<SgClassType*> returnTypeChain;
8710
8711 // Internal list used to filter the class chain generated from chained SgCastExp objects to identify the subset containing an ambiguity.
8712 std::list<SgClassType*> classChain;
8713
8714 // Make sure this is at least a reference to a data or member function member.
8715 // The requirements for these functions are different, however, if they were
8716 // virtual functions it might be a more attractive design.
8717 if (varRefExp != NULL)
8718 {
8719 ROSE_ASSERT(isDataMemberReference(varRefExp) == true);
8720 }
8721 else
8722 {
8723 ROSE_ASSERT(memberFunctionRefExp != NULL);
8724 ROSE_ASSERT(isMemberFunctionMemberReference(memberFunctionRefExp) == true);
8725 }
8726
8727 SgNode* parent = refExp->get_parent();
8728 ROSE_ASSERT(parent != NULL);
8729
8730#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8731 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): parent = %p = %s \n",parent,parent->class_name().c_str());
8732#endif
8733
8734 SgArrowExp* arrowExp = isSgArrowExp(parent);
8735 SgDotExp* dotExp = isSgDotExp(parent);
8736
8737 SgBinaryOp* binaryOperator = NULL;
8738
8739 if (arrowExp != NULL)
8740 {
8741#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8742 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an arrow expression \n");
8743#endif
8744 binaryOperator = arrowExp;
8745 }
8746
8747 if (dotExp != NULL)
8748 {
8749#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8750 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an dot expression \n");
8751#endif
8752 binaryOperator = dotExp;
8753 }
8754
8755 // ROSE_ASSERT(binaryOperator != NULL);
8756 if (binaryOperator != NULL)
8757 {
8758 SgExpression* lhs = binaryOperator->get_lhs_operand();
8759 ROSE_ASSERT(lhs != NULL);
8760
8761#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8762 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs = %p = %s \n",lhs,lhs->class_name().c_str());
8763#endif
8764
8765 // Looking for a chain of SgCastExp expressions.
8766 SgExpression* temp_lhs = lhs;
8767 SgCastExp* cast = NULL;
8768 while (isSgCastExp(temp_lhs) != NULL)
8769 {
8770 cast = isSgCastExp(temp_lhs);
8771 ROSE_ASSERT(cast != NULL);
8772 temp_lhs = cast->get_operand();
8773
8774#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8775 printf ("Top of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8776#endif
8777 ROSE_ASSERT(cast->get_type() != NULL);
8778 SgClassType* classType = isSgClassType(cast->get_type());
8779 if (classType == NULL)
8780 {
8781#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8782 printf (" --- looking for base type: In SageInterface::getClassTypeChainForDataMemberReference(): classType == NULL: cast->get_type() = %p = %s \n",
8783 cast->get_type(),cast->get_type()->class_name().c_str());
8784#endif
8785 SgType* baseType = cast->get_type()->stripType(SgType::STRIP_POINTER_TYPE | SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
8786 ROSE_ASSERT(baseType != NULL);
8787
8788#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8789 printf (" --- baseType = %p = %s name = %s \n",baseType,baseType->class_name().c_str(),get_name(baseType).c_str());
8790#endif
8791 classType = isSgClassType(baseType);
8792 }
8793 // ROSE_ASSERT(classType != NULL);
8794
8795 ROSE_ASSERT(temp_lhs != NULL);
8796
8797#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8798 printf (" --- temp_lhs = %p = %s name = %s \n",temp_lhs,temp_lhs->class_name().c_str(),get_name(temp_lhs).c_str());
8799#endif
8800
8801#if 1
8802 // DQ (1/20/2020): This (original) code works fine.
8803 // returnTypeChain.push_front(classType);
8804 if (classType != NULL)
8805 {
8806 classChain.push_front(classType);
8807 }
8808#else
8809 // DQ (1/20/2020): This (new) code works for Cxx11_tests/test2020_61.C.
8810 if (classType != NULL)
8811 {
8812 // DQ (1/20/2020): We might want to fully resolve the class types associated with this cast here directly
8813 // (see Cxx11_tests/test2020_61.C). The point is that we need a qualified name that will reflect all of
8814 // the class declarations from the temp_lhs to the declarations associated with the classType.
8815 // The steps are:
8816 // 1) Get the target class definition for the type represented by the temp_lhs.
8817 // 2) Get the source class definition for the classType.
8818 // 3) Iterate from the source class definition to the target class definition, and save the associated
8819 // types associated with the class declarations associated with the scopes visited.
8820 SgType* target_type = temp_lhs->get_type();
8821 ROSE_ASSERT(target_type != NULL);
8822 SgClassType* target_classType = isSgClassType(target_type);
8823 // ROSE_ASSERT(target_classType != NULL);
8824 if (target_classType != NULL)
8825 {
8826 SgDeclarationStatement* target_declaration = target_classType->get_declaration();
8827 ROSE_ASSERT(target_declaration != NULL);
8828 SgClassDeclaration* target_classDeclaration = isSgClassDeclaration(target_declaration);
8829 ROSE_ASSERT(target_classDeclaration != NULL);
8830 SgClassDeclaration* target_definingClassDeclaration = isSgClassDeclaration(target_classDeclaration->get_definingDeclaration());
8831 ROSE_ASSERT(target_definingClassDeclaration != NULL);
8832 SgScopeStatement* target_scope = target_definingClassDeclaration->get_definition();
8833 ROSE_ASSERT(target_scope != NULL);
8834
8835#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8836 printf ("target_classDeclaration = %p = %s name = %s target_scope = %p = %s \n",
8837 target_classDeclaration,target_classDeclaration->class_name().c_str(),target_classDeclaration->get_name().str(),target_scope,target_scope->class_name().c_str());
8838#endif
8839 SgClassType* source_classType = classType;
8840 ROSE_ASSERT(source_classType != NULL);
8841 SgDeclarationStatement* source_declaration = source_classType->get_declaration();
8842 ROSE_ASSERT(source_declaration != NULL);
8843 SgClassDeclaration* source_classDeclaration = isSgClassDeclaration(source_declaration);
8844 ROSE_ASSERT(source_classDeclaration != NULL);
8845 SgClassDeclaration* source_definingClassDeclaration = isSgClassDeclaration(source_classDeclaration->get_definingDeclaration());
8846 ROSE_ASSERT(source_definingClassDeclaration != NULL);
8847 SgScopeStatement* source_scope = source_definingClassDeclaration->get_definition();
8848 ROSE_ASSERT(source_scope != NULL);
8849
8850#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8851 printf ("source_classDeclaration = %p = %s name = %s source_scope = %p = %s \n",
8852 source_classDeclaration,source_classDeclaration->class_name().c_str(),source_classDeclaration->get_name().str(),source_scope,source_scope->class_name().c_str());
8853#endif
8854 SgScopeStatement* tmp_scope = source_scope;
8855 while (tmp_scope != NULL && tmp_scope != target_scope)
8856 {
8857#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8858 printf ("tmp_scope = %p = %s \n",tmp_scope,tmp_scope->class_name().c_str());
8859#endif
8860 SgClassDefinition* tmp_classDefinition = isSgClassDefinition(tmp_scope);
8861 ROSE_ASSERT(tmp_classDefinition != NULL);
8862 SgClassDeclaration* tmp_classDeclaration = tmp_classDefinition->get_declaration();
8863 ROSE_ASSERT(tmp_classDeclaration != NULL);
8864
8865#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8866 SgName scope_name = tmp_classDeclaration->get_name();
8867 printf ("scope_name = %s \n",scope_name.str());
8868#endif
8869 SgClassType* tmp_classType = tmp_classDeclaration->get_type();
8870 ROSE_ASSERT(tmp_classType != NULL);
8871
8872 // classChain.push_front(tmp_classDefinition);
8873 classChain.push_front(tmp_classType);
8874
8875 tmp_scope = tmp_scope->get_scope();
8876
8877 if (isSgGlobal(tmp_scope) != NULL)
8878 {
8879 tmp_scope = NULL;
8880 }
8881 }
8882 }
8883 else
8884 {
8885#if 1
8886 printf ("In loop processing cast: target_type = %p = %s \n",target_type,target_type->class_name().c_str());
8887#endif
8888 }
8889 }
8890#endif
8891
8892#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8893 printf ("Bottom of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8894#endif
8895 }
8896
8897 // We also need to include the first class where we are referencing the variable or function because that is where the first ambiguity may happen.
8898
8899 ROSE_ASSERT(temp_lhs != NULL);
8900
8901#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8902 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
8903#endif
8904
8905 SgVarRefExp* derivedClassVarRefExp = isSgVarRefExp(temp_lhs);
8906 if (derivedClassVarRefExp != NULL)
8907 {
8908 SgVariableSymbol* derivedClassVariableSymbol = derivedClassVarRefExp->get_symbol();
8909 ROSE_ASSERT(derivedClassVariableSymbol != NULL);
8910
8911 SgName derivedClassVariableName = derivedClassVariableSymbol->get_name();
8912
8913#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8914 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): derivedClassVariableName = %s \n",derivedClassVariableName.str());
8915#endif
8916 // SgType* type = cast->get_type();
8917 SgType* type = temp_lhs->get_type();
8918 ROSE_ASSERT(type != NULL);
8919
8920#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8921 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s \n",type,type->class_name().c_str());
8922#endif
8923
8924 // SgType* stripped_type = type->stripType(SgType::STRIP_POINTER_TYPE|SgType::STRIP_ARRAY_TYPE|SgType::STRIP_REFERENCE_TYPE|SgType::STRIP_RVALUE_REFERENCE_TYPE|SgType::STRIP_MODIFIER_TYPE);
8925 SgType* stripped_type = type->stripType(SgType::STRIP_POINTER_TYPE|SgType::STRIP_ARRAY_TYPE|SgType::STRIP_REFERENCE_TYPE|SgType::STRIP_RVALUE_REFERENCE_TYPE|SgType::STRIP_MODIFIER_TYPE);
8926
8927#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8928 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type = %p = %s \n",stripped_type,stripped_type->class_name().c_str());
8929#endif
8930
8931 // SgClassType* classType = isSgClassType(type);
8932 SgClassType* classType = isSgClassType(stripped_type);
8933
8934 // ROSE_ASSERT(classType != NULL);
8935 if (classType != NULL)
8936 {
8937#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8938 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classType = %p = %s \n",classType,classType->class_name().c_str());
8939 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
8940 ROSE_ASSERT(classDeclaration != NULL);
8941 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classDeclaration = %p = %s name = %s \n",
8942 classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
8943#endif
8944 // This is where we want the SgVarRefExp data member qualification to start.
8945 // returnType = classType;
8946 // returnTypeChain.push_front(classType);
8947 classChain.push_front(classType);
8948 }
8949 else
8950 {
8951#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8952 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type is not a SgClassType \n");
8953#endif
8954 }
8955 }
8956 else
8957 {
8958#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8959 printf ("Need to support alternative to SgVarRefExp: temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
8960#endif
8961 SgType* type = temp_lhs->get_type();
8962 ROSE_ASSERT(type != NULL);
8963
8964#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8965 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s name = %s \n",type,type->class_name().c_str(),get_name(type).c_str());
8966#endif
8967
8968 // DQ (1/3/2019): Need to strip the type to get to a possible SgClassType.
8969 SgType* stripped_type = type->stripType(SgType::STRIP_POINTER_TYPE|SgType::STRIP_ARRAY_TYPE|SgType::STRIP_REFERENCE_TYPE|SgType::STRIP_RVALUE_REFERENCE_TYPE|SgType::STRIP_MODIFIER_TYPE);
8970
8971#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8972 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): stripped_type = %p = %s name = %s \n",stripped_type,stripped_type->class_name().c_str(),get_name(stripped_type).c_str());
8973#endif
8974 // SgClassType* classType = isSgClassType(type);
8975 SgClassType* classType = isSgClassType(stripped_type);
8976 // returnTypeChain.push_front(classType);
8977 if (classType != NULL)
8978 {
8979 classChain.push_front(classType);
8980 }
8981 }
8982
8983#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8984 printf ("classChain.size() = %zu \n",classChain.size());
8985 std::list<SgClassType*>::iterator iter = classChain.begin();
8986 while(iter != classChain.end())
8987 {
8988 printf (" --- *iter = %p = %s name = %s \n",*iter,(*iter)->class_name().c_str(),(*iter)->get_name().str());
8989
8990 iter++;
8991 }
8992#endif
8993
8994 // Test the first element in the list to see if there is an ambiguity in the associated classDefinition
8995 // for the input variable referenced SgVarRefExp).
8996
8997 // SgVariableSymbol* variableSymbol = varRefExp->get_symbol();
8998 // ROSE_ASSERT(variableSymbol != NULL);
8999 // SgName variableName = variableSymbol->get_name();
9000 SgSymbol* referenceSymbol = NULL;
9001 if (varRefExp != NULL)
9002 {
9003 ROSE_ASSERT(varRefExp != NULL);
9004 ROSE_ASSERT(memberFunctionRefExp == NULL);
9005
9006 referenceSymbol = varRefExp->get_symbol();
9007 }
9008 else
9009 {
9010 ROSE_ASSERT(varRefExp == NULL);
9011 ROSE_ASSERT(memberFunctionRefExp != NULL);
9012
9013 referenceSymbol = memberFunctionRefExp->get_symbol();
9014 }
9015 ROSE_ASSERT(referenceSymbol != NULL);
9016 SgName symbolName = referenceSymbol->get_name();
9017
9018#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9019 printf ("referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9020 printf ("symbolName = %s \n",symbolName.str());
9021#endif
9022
9023 // Generate the name without the template arguments.
9024 SgFunctionSymbol* functionSymbol = isSgFunctionSymbol(referenceSymbol);
9025 if (functionSymbol != NULL)
9026 {
9027 // DQ (2/24/2019): NOTE: the SgSymbol get_declaration() function is not a virtual function (and maybe it should be). So we need to case it explicitly.
9028 // SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(referenceSymbol->get_declaration());
9029 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(functionSymbol->get_declaration());
9030 if (templateInstantiationMemberFunctionDeclaration != NULL)
9031 {
9032#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9033 printf ("This is a template name, we want the name without template arguments \n");
9034 printf ("templateInstantiationMemberFunctionDeclaration = %p \n",templateInstantiationMemberFunctionDeclaration);
9035 printf ("templateInstantiationMemberFunctionDeclaration->get_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_name().str());
9036#endif
9037
9038 // DQ (2/24/2019): This is an error (calls base class function).
9039 // printf ("templateInstantiationMemberFunctionDeclaration->get_template_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_template_name().str());
9040
9041 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration =
9042 isSgTemplateMemberFunctionDeclaration(templateInstantiationMemberFunctionDeclaration->get_templateDeclaration());
9043 if (templateMemberFunctionDeclaration != NULL)
9044 {
9045#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9046 printf ("templateMemberFunctionDeclaration = %p \n",templateMemberFunctionDeclaration);
9047 printf ("templateMemberFunctionDeclaration->get_name() = %s \n",templateMemberFunctionDeclaration->get_name().str());
9048#endif
9049 // We need the template name without template arguments.
9050 symbolName = templateMemberFunctionDeclaration->get_name();
9051 }
9052 else
9053 {
9054#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9055 printf ("templateMemberFunctionDeclaration == NULL: template declaration not available from template instantiation (rare, I think) \n");
9056#endif
9057 }
9058#if 0
9059 printf ("Exiting as a test! \n");
9060 ROSE_ABORT();
9061#endif
9062 }
9063 else
9064 {
9065 // DQ (2/24/2019): This might indicate another case to handle: finding SgMemberFunctionDeclaration (but this is not a template).
9066 SgDeclarationStatement* declarationStatement = functionSymbol->get_declaration();
9067 ROSE_ASSERT(declarationStatement != NULL);
9068#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9069 printf ("functionSymbol != NULL: but declaration is not a member function: declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
9070#endif
9071 }
9072 }
9073 else
9074 {
9075 SgVariableSymbol* variableSymbol = isSgVariableSymbol(referenceSymbol);
9076 if (variableSymbol != NULL)
9077 {
9078 // Nothing to do in this case of a SgVariableSymbol.
9079 }
9080 else
9081 {
9082#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9083 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): NOTE: referenceSymbol is not a SgFunctionSymbol or SgVariableSymbol \n");
9084#endif
9085#if 1
9086 printf ("Exiting as a test! \n");
9087 ROSE_ABORT();
9088#endif
9089 }
9090
9091 }
9092
9093#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9094 printf ("symbolName = %s \n",symbolName.str());
9095#endif
9096
9097 // SgClassType* firstDetectedAmbiguity = NULL;
9098 // SgClassType* lastDetectedAmbiguity = NULL;
9099
9100 // bool nameQualificationRequired = false;
9101
9102 // std::list<SgClassType*> deleteList;
9103 std::list<SgClassType*> saveList;
9104
9105#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9106 printf ("classChain.size() = %zu \n",classChain.size());
9107#endif
9108
9109 std::list<SgClassType*>::iterator i = classChain.begin();
9110 std::list<SgClassType*>::iterator save_iter = i;
9111
9112 // If we have an abiguity at i then we want to save i++, so define save_iter to be the next in the class type list.
9113 save_iter++;
9114
9115 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9116 bool ambiguityDetectedSoSaveWholeChain = false;
9117
9118 while(i != classChain.end())
9119 {
9120#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9121 printf ("******** TOP OF WHILE LOOP ******** \n");
9122 printf (" --- *i = %p = %s name = %s \n",*i,(*i)->class_name().c_str(),(*i)->get_name().str());
9123 printf (" --- --- referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9124#endif
9125 bool ambiguityDetected = false;
9126
9127 SgDeclarationStatement* declarationStatement = (*i)->get_declaration();
9128 ROSE_ASSERT(declarationStatement != NULL);
9129 SgDeclarationStatement* definingDeclarationStatement = declarationStatement->get_definingDeclaration();
9130 if (definingDeclarationStatement != NULL)
9131 {
9132 SgClassDeclaration* classDeclaration = isSgClassDeclaration(definingDeclarationStatement);
9133 ROSE_ASSERT(classDeclaration != NULL);
9134 SgClassDefinition* classDefinition = classDeclaration->get_definition();
9135
9136#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9137 printf (" --- classDeclaration = %p = %s name = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9138 printf (" --- classDefinition = %p = %s \n",classDefinition,classDefinition->class_name().c_str());
9139#endif
9140 // This works for any SgName and SgSymbol, so it need not be specific to variables.
9141 ambiguityDetected = classDefinition->hasAmbiguity(symbolName,referenceSymbol);
9142
9143#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9144 printf (" --- ambiguityDetected = %s \n",ambiguityDetected ? "true" : "false");
9145#endif
9146 }
9147
9148 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9149 if (ambiguityDetected == true || ambiguityDetectedSoSaveWholeChain == true)
9150 {
9151 ambiguityDetectedSoSaveWholeChain = true;
9152
9153 if (save_iter != classChain.end())
9154 {
9155#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9156 printf (" --- add to saveList: *save_iter = %p \n",*save_iter);
9157#endif
9158 saveList.push_back(*save_iter);
9159 }
9160 else
9161 {
9162#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9163 printf (" --- save_iter == classChain.end() \n");
9164#endif
9165 }
9166 }
9167
9168#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9169 printf ("******** BOTTOM OF WHILE LOOP ******** \n");
9170#endif
9171 i++;
9172
9173 // Also increment the save_iter.
9174 save_iter++;
9175 }
9176
9177 // Now build a list of class types to use in the name qualification from firstDetectedAmbiguity to lastDetectedAmbiguity (inclusive).
9178
9179#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9180 printf ("saveList.size() = %zu \n",saveList.size());
9181 std::list<SgClassType*>::iterator saveList_iterator = saveList.begin();
9182 while (saveList_iterator != saveList.end())
9183 {
9184 printf (" --- *saveList_iterator = %p = %s name = %s \n",*saveList_iterator,(*saveList_iterator)->class_name().c_str(),(*saveList_iterator)->get_name().str());
9185
9186 saveList_iterator++;
9187 }
9188#endif
9189
9190 returnTypeChain = saveList;
9191
9192 // End of branch for binaryOperator != NULL.
9193 }
9194
9195 return returnTypeChain;
9196 }
9197
9198
9199
9200bool
9202 {
9203 // DQ (2/17/2019): This may share a design in common with isDataMemberReference() below.
9204
9205#define DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE 0
9206
9207 ROSE_ASSERT(memberFunctionRefExp != NULL);
9208
9209 bool returnValue = false;
9210
9211 // Check that this is a data member access (e.g. "X x; x.member;") and not just a reference to a data member (e.g. "X::member;")
9212 SgNode* parent = memberFunctionRefExp->get_parent();
9213
9214 SgArrowExp* arrowExp = isSgArrowExp(parent);
9215 SgDotExp* dotExp = isSgDotExp(parent);
9216
9217 // I don't know that the SgAddressOfOp is as relevant for the case of SgMemberFunctionRefExp, but I think
9218 // it is because we would have to support membr pointeds to functions the same a member pointers to data.
9219 // I need some examples test codes to verify that name qualification is important in this case.
9220 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9221
9222 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9223 {
9224 // Use a SgFunctionSymbol instead of a SgMemberFunctionSymbol for generality (I hope this works).
9225 SgFunctionSymbol* symbol = memberFunctionRefExp->get_symbol();
9226 ROSE_ASSERT(symbol != NULL);
9227
9228 SgFunctionDeclaration* functionDeclaration = symbol->get_declaration();
9229 ROSE_ASSERT(functionDeclaration != NULL);
9230
9231 // Check if this is a statically declared variable.
9232 if (functionDeclaration != NULL)
9233 {
9234 bool isStatic = functionDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9235#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9236 printf ("isStatic = %s \n",isStatic ? "true" : "false");
9237#endif
9238 if (isStatic == false)
9239 {
9240 SgScopeStatement* scope = functionDeclaration->get_scope();
9241 ROSE_ASSERT(scope != NULL);
9242
9243 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9244 if (classDefinition != NULL)
9245 {
9246 returnValue = true;
9247 }
9248 }
9249 }
9250 else
9251 {
9252#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9253 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9254#endif
9255 }
9256 }
9257 else
9258 {
9259#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9260 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9261#endif
9262 }
9263
9264#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9265 printf ("Leaving SageInterface::isMemberFunctionMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9266#endif
9267
9268 return returnValue;
9269 }
9270
9271
9272
9273bool
9275 {
9276 // This function is used to support the name qualification of data member references seperate from name qualification
9277 // of variables that might be members (e.g. "X x; x.A::y;" instead of "A::y" (which is just simple name qualification)).
9278
9279 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9280
9281 // DQ (2/17/2019): I think we need to make sure this is not a static data member reference (since those are qualified
9282 // differently (not member data name qualification). Consider changing the name of this function to indicate non-static.
9283
9284#define DEBUG_IS_DATA_MEMBER_REFERENCE 0
9285
9286 ROSE_ASSERT(varRefExp != NULL);
9287
9288 bool returnValue = false;
9289
9290 // Check that this is a data member access (e.g. "X x; x.member;") and not just a reference to a data member (e.g. "X::member;")
9291 SgNode* parent = varRefExp->get_parent();
9292
9293 SgArrowExp* arrowExp = isSgArrowExp(parent);
9294 SgDotExp* dotExp = isSgDotExp(parent);
9295
9296 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9297
9298 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9299 {
9300 if (arrowExp != NULL)
9301 {
9302 // DQ (2/17/2019): Check if this is part of a sizeof operand for which is is_objectless_nonstatic_data_member_reference == true.
9303 SgNode* parentOfArrowExp = arrowExp->get_parent();
9304 ROSE_ASSERT(parentOfArrowExp != NULL);
9305 SgSizeOfOp* sizeOfOp = isSgSizeOfOp(parentOfArrowExp);
9306 if (sizeOfOp != NULL && sizeOfOp->get_is_objectless_nonstatic_data_member_reference() == true)
9307 {
9308 // This is not to be qualified using data member name qualification (it should use standard name qualification).
9309#if DEBUG_IS_DATA_MEMBER_REFERENCE
9310 printf ("In SageInterface::isDataMemberReference(): Found case of expression used in sizeof with objectless_nonstatic_data_member_reference \n");
9311#endif
9312 return false;
9313 }
9314 }
9315
9316 SgVariableSymbol* symbol = varRefExp->get_symbol();
9317 ROSE_ASSERT(symbol != NULL);
9318
9319 SgInitializedName* initializedName = symbol->get_declaration();
9320 ROSE_ASSERT(initializedName != NULL);
9321
9322 // Check if this is a statically declared variable.
9323 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(initializedName->get_parent());
9324 if (variableDeclaration != NULL)
9325 {
9326 bool isStatic = variableDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9327 if (isStatic == false)
9328 {
9329 SgScopeStatement* scope = initializedName->get_scope();
9330 ROSE_ASSERT(scope != NULL);
9331
9332 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9333 if (classDefinition != NULL)
9334 {
9335 returnValue = true;
9336 }
9337 }
9338 }
9339 else
9340 {
9341#if DEBUG_IS_DATA_MEMBER_REFERENCE
9342 printf ("In SageInterface::isDataMemberReference(): varRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9343#endif
9344 }
9345 }
9346 else
9347 {
9348#if DEBUG_IS_DATA_MEMBER_REFERENCE
9349 printf ("In SageInterface::isDataMemberReference(): varRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9350#endif
9351 }
9352
9353#if DEBUG_IS_DATA_MEMBER_REFERENCE
9354 printf ("Leaving SageInterface::isDataMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9355#endif
9356
9357 return returnValue;
9358 }
9359
9360
9361#if 0
9362bool
9364 {
9365 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9366 ROSE_ASSERT(varRefExp != NULL);
9367
9368 bool returnValue = false;
9369
9370 SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9371
9372 if (addressOfOp != NULL)
9373 {
9374 returnValue = true;
9375 }
9376
9377 return returnValue;
9378 }
9379#endif
9380
9381bool
9383 {
9384 // DQ (2/17/2019): Need to generalize this function to apply to member functions references as well.
9385
9386 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
9387 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
9388 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
9389
9390 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
9391
9392 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9393 // ROSE_ASSERT(varRefExp != NULL);
9394 ROSE_ASSERT(refExp != NULL);
9395
9396 bool returnValue = false;
9397
9398 // SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9399 SgAddressOfOp* addressOfOp = isSgAddressOfOp(refExp->get_parent());
9400
9401 if (addressOfOp != NULL)
9402 {
9403 returnValue = true;
9404 }
9405
9406 return returnValue;
9407 }
9408
9410 {
9411 // DQ (3/4/2014): This new version of this function supports both C/C++ and also Java.
9412 // If the SgJavaPackageDeclaration is noticed then the previous parent is a
9413 // SgClassDefinition and the previous previous parent is a SgClassDeclaration whose
9414 // name can be used to match the filename in the SgProject's list of files.
9415 // A better implementation usign an attribute (not in place until tomorrow) and
9416 // from the attribute the pointer to the associated file is directly available.
9417 // The later implementation is as fast as possible.
9418
9419 ROSE_ASSERT (astNode != NULL);
9420
9421 // Make sure this is not a project node (since the SgFile exists below
9422 // the project and could not be found by a traversal of the parent list)
9423 ROSE_ASSERT (isSgProject(astNode) == NULL);
9424
9425 SgNode* previous_parent = NULL;
9426 SgNode* previous_previous_parent = NULL;
9427
9428 SgNode* parent = astNode;
9429 // while ( (parent != NULL) && (isSgFile(parent) == NULL) )
9430 while ( (parent != NULL) && (isSgFile(parent) == NULL) && isSgJavaPackageDeclaration(parent) == NULL)
9431 {
9432#if 0
9433 printf ("In getEnclosingFileNode(): parent = %p = %s \n",parent,parent->class_name().c_str());
9434#endif
9435 previous_previous_parent = previous_parent;
9436 previous_parent = parent;
9437
9438 parent = parent->get_parent();
9439 }
9440
9441 if (previous_previous_parent != NULL && previous_parent != NULL && isSgJavaPackageDeclaration(parent) != NULL)
9442 {
9443 // This is for a Java program and is contained within a SgJavaPackageDeclaration
9444#if 0
9445 printf ("parent = %p = %s \n",parent,parent->class_name().c_str());
9446 printf ("previous_parent = %p = %s \n",previous_parent,previous_parent->class_name().c_str());
9447 printf ("previous_previous_parent = %p = %s \n",previous_previous_parent,previous_previous_parent->class_name().c_str());
9448#endif
9449 SgClassDeclaration* classDeclaration = isSgClassDeclaration(previous_previous_parent);
9450 if (classDeclaration != NULL)
9451 {
9452#if 0
9453 printf ("Class name = %p = %s = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9454#endif
9455 // Find the associated Java class file.
9456#if 0
9457 // DQ (3/4/2014): This is the code we want to use until we get Philippe's branch in place with the attribute.
9458 SgProject* project = TransformationSupport::getProject(parent);
9459 ROSE_ASSERT(project != NULL);
9460 SgFileList* fileList = project->get_fileList_ptr();
9461 ROSE_ASSERT(fileList != NULL);
9462 SgFilePtrList & vectorFile = fileList->get_listOfFiles();
9463#if 0
9464 printf ("Output list of files: \n");
9465#endif
9466 SgFilePtrList::iterator i = vectorFile.begin();
9467 while (i != vectorFile.end())
9468 {
9469 SgFile* file = *i;
9470 ROSE_ASSERT(file != NULL);
9471#if 0
9472 printf (" --- filename = %s \n",file->getFileName().c_str());
9473#endif
9474 string filename = file->getFileName();
9475 string filenameWithoutPath = file->get_sourceFileNameWithoutPath();
9476 string classname = classDeclaration->get_name();
9477 string matchingfilename = classname + ".java";
9478#if 0
9479 printf (" --- --- filename = %s \n",filename.c_str());
9480 printf (" --- --- filenameWithoutPath = %s \n",filenameWithoutPath.c_str());
9481 printf (" --- --- classname = %s \n",classname.c_str());
9482 printf (" --- --- matchingfilename = %s \n",matchingfilename.c_str());
9483#endif
9484 if (filenameWithoutPath == matchingfilename)
9485 {
9486#if 0
9487 printf (" return file = %p \n",file);
9488#endif
9489 return file;
9490 }
9491
9492 i++;
9493 }
9494#else
9495 // DQ (3/4/2014): This is the code we want to use when the attribute is in place (philippe's branch).
9496 AstSgNodeAttribute *attribute = (AstSgNodeAttribute *) classDeclaration->getAttribute("sourcefile");
9497
9498 // "This simpler and more efficent code requires the latest work in Java support (3/6/2014)"
9499
9500 if (attribute)
9501 {
9502 // true for all user-specified classes and false for all classes fom libraries
9503 SgSourceFile *sourcefile = isSgSourceFile(attribute->getNode());
9504 ROSE_ASSERT(sourcefile != NULL);
9505 return sourcefile;
9506 }
9507#endif
9508 }
9509 }
9510 else
9511 {
9512 // previous_parent was uninitialized to a non-null value or astNode is a SgJavaPackageDeclaration or SgFile.
9513 if (previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9514 {
9515 // The input was a SgJavaPackageDeclaration (so there is no associated SgFile).
9516 ROSE_ASSERT(isSgJavaPackageDeclaration(astNode) != NULL);
9517 return NULL;
9518 }
9519 else
9520 {
9521 if (previous_previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9522 {
9523 // The input was a SgClassDefinition (so there is no associated SgFile).
9524 ROSE_ASSERT(isSgClassDefinition(astNode) != NULL);
9525 return NULL;
9526 }
9527 else
9528 {
9529 // This could be a C/C++ file (handled below).
9530 }
9531 }
9532 }
9533
9534 // This is where we handle the C/C++ files.
9535 if (parent == nullptr)
9536 {
9537 return nullptr;
9538 }
9539 else
9540 {
9541 return isSgFile(parent);
9542 }
9543 }
9544
9546 struct FrontendSpecificTraversal : public ROSE_VisitTraversal {
9547 std::set<SgNode*> specific;
9548 std::set<SgNode*> non_specific;
9549
9550 static void recursive_collect( SgNode* node , std::set<SgNode *> & collection ) {
9551 // Stop on sinks and loops
9552 if (node == NULL || !collection.insert(node).second) return;
9553
9554 std::vector<std::pair<SgNode*, std::string> > data_members = node->returnDataMemberPointers();
9555 for (std::vector<std::pair<SgNode*, std::string> >::iterator i = data_members.begin(); i != data_members.end(); ++i) {
9556 recursive_collect(i->first, collection);
9557 }
9558 }
9559
9560 void visit (SgNode* n) {
9561 Sg_File_Info * fileInfo = n->get_file_info();
9562
9563 if (fileInfo != NULL) {
9564 if (fileInfo->isFrontendSpecific()) {
9565 specific.insert(n);
9566 recursive_collect(n, specific);
9567 } else {
9568 non_specific.insert(n);
9569 recursive_collect(n, non_specific);
9570 }
9571 } else {
9572 fileInfo = isSg_File_Info(n);
9573 if (fileInfo != NULL) {
9574 if (fileInfo->isFrontendSpecific()) {
9575 specific.insert(n);
9576 } else {
9577 non_specific.insert(n);
9578 }
9579 }
9580 }
9581 }
9582
9583 std::set<SgNode*> apply() {
9584 traverseMemoryPool();
9585
9586 std::set<SgNode*> result;
9587
9588 std::set_difference(
9589 specific.begin(), specific.end(),
9590 non_specific.begin(), non_specific.end(),
9591 std::insert_iterator<set<SgNode*> >(result, result.begin())
9592 );
9593
9594 return result;
9595 }
9596 };
9597
9598 FrontendSpecificTraversal fst;
9599 return fst.apply();
9600}
9601
9602void
9604 {
9605 // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
9606
9607 class OutputSharedNodesTraversal : public SgSimpleProcessing
9608 {
9609 // This traversal collects the includes at the top of a file.
9610 public:
9611 void visit(SgNode *astNode)
9612 {
9613 ROSE_ASSERT(astNode != NULL);
9614 Sg_File_Info* file_info = astNode->get_file_info();
9615 if (file_info != NULL)
9616 {
9617 if (file_info->isShared() == true)
9618 {
9619 printf ("Found shared node: astNode = %p = %s \n",astNode,astNode->class_name().c_str());
9620 }
9621 }
9622 }
9623 };
9624
9625 OutputSharedNodesTraversal tt;
9626 tt.traverse(node,preorder);
9627 }
9628
9629
9630
9631
9632
9634 while (n && !isSgStatement(n)) n = n->get_parent();
9635 return isSgStatement(n);
9636}
9637
9638
9639
9640#if 1
9641// DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
9642// So I need to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.
9643
9644SageInterface::DeferredTransformation::DeferredTransformation()
9645 : deferredTransformationKind(e_default),
9646 statementToRemove(NULL),
9647 statementToAdd(NULL),
9648 class_definition(NULL),
9649 target_class_member(NULL),
9650 new_function_prototype(NULL),
9651 // DQ (2/28/2021): Added new data member to support deferred transformations.
9652 locationToOverwriteWithTransformation(NULL),
9653 transformationToOverwriteFirstStatementInInterval(NULL),
9654 blockOfStatementsToOutline(NULL)
9655 {
9656 // Default constructor (not particularly useful).
9657#if 0
9658 printf ("In SageInterface::DeferredTransformation default constructor called \n");
9659#endif
9660 }
9661
9662// DQ (2/28/2021): Added new data member to support deferred transformations.
9663// IntervalType statementInterval;
9664// SgStatement* locationToOverwriteWithTransformation;
9665
9666SageInterface::DeferredTransformation::DeferredTransformation(
9667 SgClassDefinition* input_class_definition,
9668 SgDeclarationStatement* input_target_class_member,
9669 SgDeclarationStatement* input_new_function_prototype)
9670 : deferredTransformationKind(e_outliner),
9671 statementToRemove(NULL),
9672 statementToAdd(NULL),
9673 class_definition(input_class_definition),
9674 target_class_member(input_target_class_member),
9675 new_function_prototype(input_new_function_prototype),
9676 // DQ (2/28/2021): Added new data member to support deferred transformations.
9677 locationToOverwriteWithTransformation(NULL),
9678 transformationToOverwriteFirstStatementInInterval(NULL),
9679 blockOfStatementsToOutline(NULL)
9680 {
9681 // This constructor is used by the outliner.
9682#if 0
9683 printf ("In SageInterface::DeferredTransformation constructor for outliner called \n");
9684#endif
9685 }
9686
9689 {
9690#if 0
9691 printf ("In SageInterface::DeferredTransformation constructor for replaceDefiningFunctionDeclarationWithFunctionPrototype called \n");
9692#endif
9693 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9694 // This constructor is used by tool_G and supports the use of the transformation represented
9695 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9697 X.deferredTransformationKind = e_replaceDefiningFunctionDeclarationWithFunctionPrototype;
9698 X.statementToRemove = functionDeclaration;
9699 X.statementToAdd = NULL;
9700 X.class_definition = NULL;
9701 X.target_class_member = NULL;
9702 X.new_function_prototype = NULL;
9703
9704 // DQ (2/28/2021): Added new data member to support deferred transformations.
9705 X.locationToOverwriteWithTransformation = NULL;
9706 X.transformationToOverwriteFirstStatementInInterval = NULL;
9707 X.blockOfStatementsToOutline = NULL;
9708
9709 return X;
9710 }
9711
9713SageInterface::DeferredTransformation::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool /*movePreprocessingInfo = false*/)
9714 {
9715#if 0
9716 printf ("In SageInterface::DeferredTransformation constructor for replaceStatement called \n");
9717#endif
9718 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9719 // This constructor is used by tool_G and supports the use of the transformation represented
9720 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9722 X.deferredTransformationKind = e_replaceStatement;
9723 X.statementToRemove = oldStmt;
9724 X.statementToAdd = newStmt;
9725 X.class_definition = NULL;
9726 X.target_class_member = NULL;
9727 X.new_function_prototype = NULL;
9728
9729 // DQ (2/28/2021): Added new data member to support deferred transformations.
9730 X.locationToOverwriteWithTransformation = NULL;
9731 X.transformationToOverwriteFirstStatementInInterval = NULL;
9732 X.blockOfStatementsToOutline = NULL;
9733
9734 return X;
9735 }
9736
9737SageInterface::DeferredTransformation::DeferredTransformation (const DeferredTransformation& X)
9738#if 0
9739 : deferredTransformationKind(X.deferredTransformationKind),
9740 statementToRemove(X.statementToRemove),
9741 statementToAdd(X.StatementToAdd),
9742 class_definition(X.class_definition),
9743 target_class_member(X.target_class_member),
9744 new_function_prototype(X.new_function_prototype),
9745 targetClasses(X.targetClasses),
9746 targetFriends(X.targetFriends)
9747 {
9748 }
9749#else
9750 {
9751#if 0
9752 printf ("In SageInterface::DeferredTransformation copy constructor called \n");
9753#endif
9754 // DQ (11/19/2020): Leverage the operator=() implementation to reduce complexity (one place to update).
9755 *this = X;
9756 }
9757#endif
9758
9760 {
9761#if 0
9762 printf ("Inside of SageInterface::DeferredTransformation::operator= (const DeferredTransformation& X) \n");
9763#endif
9764
9765#if 0
9766 // Original code.
9767 targetFriends = X.targetFriends;
9768 targetClasses = X.targetClasses;
9769#else
9770
9771 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9772 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9773 // definitions in the dynamic library file with function prototypes.
9774 transformationLabel = X.transformationLabel;
9775
9776 // New code added to support more general usage.
9777 deferredTransformationKind = X.deferredTransformationKind;
9778 statementToRemove = X.statementToRemove;
9779 statementToAdd = X.statementToAdd;
9780
9781 class_definition = X.class_definition;
9782 target_class_member = X.target_class_member;
9783 new_function_prototype = X.new_function_prototype;
9784 targetClasses = X.targetClasses;
9785 targetFriends = X.targetFriends;
9786
9787 // DQ (2/28/2021): Added new data member to support deferred transformations.
9788 statementInterval = X.statementInterval;
9789 locationToOverwriteWithTransformation = X.locationToOverwriteWithTransformation;
9790 transformationToOverwriteFirstStatementInInterval = X.transformationToOverwriteFirstStatementInInterval;
9791
9792 // DQ (3/1/2021): Added new data member to support deferred transformations.
9793 blockOfStatementsToOutline = X.blockOfStatementsToOutline;
9794#endif
9795
9796 return *this;
9797 }
9798
9803
9804std::string SageInterface::DeferredTransformation::outputDeferredTransformationKind(const TransformationKind & kind)
9805 {
9806 string returnValue = "uninitialized";
9807 switch (kind)
9808 {
9809 case e_error: returnValue = "e_error"; break;
9810 case e_default: returnValue = "e_default"; break;
9811 case e_outliner: returnValue = "e_outliner"; break;
9812 case e_replaceStatement: returnValue = "e_replaceStatement"; break;
9813 case e_removeStatement: returnValue = "e_removeStatement"; break;
9814 case e_replaceDefiningFunctionDeclarationWithFunctionPrototype: returnValue = "e_replaceDefiningFunctionDeclarationWithFunctionPrototype"; break;
9815 case e_last: returnValue = "e_last"; break;
9816 default:
9817 {
9818 printf ("Error: SageInterface::DeferredTransformation::get_deferredTransformationKind_string(): default reached \n");
9819 ROSE_ABORT();
9820 }
9821 }
9822
9823 return returnValue;
9824 }
9825
9826void SageInterface::DeferredTransformation::display ( std::string label ) const
9827 {
9828 printf ("SageInterface::DeferredTransformation::display(): label = %s \n",label.c_str());
9829
9830 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9831 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9832 // definitions in the dynamic library file with function prototypes.
9833 printf (" --- transformationLabel = %s \n",transformationLabel.c_str());
9834
9835 printf (" --- deferredTransformationKind = %s \n",outputDeferredTransformationKind(deferredTransformationKind).c_str());
9836 if (statementToRemove != NULL)
9837 {
9838 printf (" --- statementToRemove = %p = %s name = %s \n",statementToRemove,statementToRemove->class_name().c_str(),get_name(statementToRemove).c_str());
9839 }
9840 else
9841 {
9842 printf (" --- statementToRemove == NULL \n");
9843 }
9844
9845 if (statementToAdd != NULL)
9846 {
9847 printf (" --- statementToAdd = %p = %s name = %s \n",statementToAdd,statementToAdd->class_name().c_str(),get_name(statementToAdd).c_str());
9848 }
9849 else
9850 {
9851 printf (" --- statementToAdd == NULL \n");
9852 }
9853
9854 if (class_definition != NULL)
9855 {
9856 // printf (" --- class_definition = %p = %s name = %s \n",class_definition,class_definition->class_name().c_str(),get_name(class_definition).c_str());
9857 printf (" --- class_definition = %p \n",class_definition);
9858 }
9859
9860 if (target_class_member != NULL)
9861 {
9862 printf (" --- target_class_member = %p = %s name = %s \n",target_class_member,target_class_member->class_name().c_str(),get_name(target_class_member).c_str());
9863 }
9864
9865 if (new_function_prototype != NULL)
9866 {
9867 printf (" --- new_function_prototype = %p = %s name = %s \n",new_function_prototype,new_function_prototype->class_name().c_str(),get_name(new_function_prototype).c_str());
9868 }
9869
9870 // DQ (2/28/2021): Added new data member to support deferred transformations.
9871 if (locationToOverwriteWithTransformation != NULL)
9872 {
9873 // printf (" --- locationToOverwriteWithTransformation = %p = %s name = %s \n",locationToOverwriteWithTransformation,
9874 // locationToOverwriteWithTransformation->class_name().c_str(),get_name(locationToOverwriteWithTransformation).c_str());
9875 printf (" --- locationToOverwriteWithTransformation = %p \n",locationToOverwriteWithTransformation);
9876 }
9877
9878 // DQ (2/28/2021): Added new data member to support deferred transformations.
9879 if (transformationToOverwriteFirstStatementInInterval != NULL)
9880 {
9881 // printf (" --- transformationToOverwriteFirstStatementInInterval = %p = %s name = %s \n",transformationToOverwriteFirstStatementInInterval,
9882 // transformationToOverwriteFirstStatementInInterval->class_name().c_str(),get_name(transformationToOverwriteFirstStatementInInterval).c_str());
9883 printf (" --- transformationToOverwriteFirstStatementInInterval = %p \n",transformationToOverwriteFirstStatementInInterval);
9884 }
9885
9886 // DQ (3/1/2021): Added new data member to support deferred transformations.
9887 if (blockOfStatementsToOutline != NULL)
9888 {
9889 printf (" --- blockOfStatementsToOutline = %p \n",blockOfStatementsToOutline);
9890 }
9891
9892 printf ("targetClasses.size() = %zu \n",targetClasses.size());
9893 printf ("targetFriends.size() = %zu \n",targetFriends.size());
9894
9895 // DQ (2/28/2021): Added new data member to support deferred transformations.
9896 printf ("statementInterval.size() = %zu \n",statementInterval.size());
9897
9898 }
9899#endif
9900
9901
9902
9903
9904
9905// DQ (/20/2010): Control debugging output for SageInterface::removeStatement() function.
9906#define REMOVE_STATEMENT_DEBUG 0
9907
9909void SageInterface::removeStatement(SgStatement* targetStmt, bool autoRelocatePreprocessingInfo /*= true*/)
9910 {
9911#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
9912 // This function removes the input statement.
9913 // If there are comments and/or CPP directives then those comments and/or CPP directives will
9914 // be moved to a new SgStatement. The new SgStatement is selected using the findSurroundingStatementFromSameFile()
9915 // function and if there is not statement found then the SgGlobal IR node will be selected.
9916 // this work is tested by the tests/nonsmoke/functional/roseTests/astInterfaceTests/removeStatementCommentRelocation.C
9917 // translator and a number of input codes that represent a range of contexts which exercise different
9918 // cases in the code below.
9919
9920#ifndef _MSC_VER
9921 // This function only supports the removal of a whole statement (not an expression within a statement)
9922 ASSERT_not_null(targetStmt);
9923
9924 SgStatement * parentStatement = isSgStatement(targetStmt->get_parent());
9925
9926 // Can't assert this since SgFile is the parent of SgGlobal, and SgFile is not a statement.
9927 // Even so SgGlobal can't be removed from SgFile, but isRemovableStatement() takes a SgStatement.
9928 // ROSE_ASSERT (parentStatement != NULL);
9929
9930 bool isRemovable = (parentStatement != NULL) ? LowLevelRewrite::isRemovableStatement(targetStmt) : false;
9931
9932#if REMOVE_STATEMENT_DEBUG || 0
9933 printf ("In SageInterface::removeStatement(): parentStatement = %p = %s remove targetStatement = %p = %s (isRemovable = %s) \n",
9934 parentStatement,parentStatement->class_name().c_str(),targetStmt,targetStmt->class_name().c_str(),isRemovable ? "true" : "false");
9935#endif
9936
9937 if (isRemovable == true)
9938 {
9939 // DQ (9/19/2010): Disable this new (not completely working feature) so that I can checkin the latest UPC/UPC++ work.
9940#if 1
9941 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
9942 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
9943 // Liao 10/28/2010. Sometimes we want remove the statement with all its preprocessing information
9944 if (autoRelocatePreprocessingInfo == true)
9945 {
9946 // WE need to move up inner danglinge #endif or #if directives first.
9948 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
9949 // appear before the statment to be attached to the inserted statement (and marked
9950 // to appear before that statement).
9951 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
9952
9953
9954 if (comments != nullptr && isSgBasicBlock(targetStmt) == nullptr )
9955 {
9956 vector<int> captureList;
9957#if REMOVE_STATEMENT_DEBUG
9958 printf ("Found attached comments (removing %p = %s): comments->size() = %" PRIuPTR " \n",targetStmt,targetStmt->class_name().c_str(),comments->size());
9959#endif
9960
9961 // Liao 10/28/2010. relinking AST statements may be achieved by remove it and attach it to somewhere else.
9962 // In this case, preprocessing information sometimes should go with the statements and not be relocated to the original places.
9963 // Dan: Since this statement will be removed we have to relocate all the associated comments and CPP directives.
9964 int commentIndex = 0;
9965 AttachedPreprocessingInfoType::iterator i;
9966 for (i = comments->begin(); i != comments->end(); i++)
9967 {
9968 ROSE_ASSERT ( (*i) != NULL );
9969#if REMOVE_STATEMENT_DEBUG
9970 printf (" Attached Comment (relativePosition=%s): %s\n",
9971 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
9972 (*i)->getString().c_str());
9973 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
9974 (*i)->get_file_info()->display("comment/directive location debug");
9975#endif
9976 captureList.push_back(commentIndex);
9977 commentIndex++;
9978 }
9979
9980#if REMOVE_STATEMENT_DEBUG
9981 printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
9982#endif
9983
9984 if (captureList.empty() == false)
9985 {
9986 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
9987 // Find the surrounding statement by first looking up in the sequence of statements in this block, then down, we need another
9988 // statement from the same file. SgGlobal may be returned if nothing else is found.
9989 bool surroundingStatementPreceedsTargetStatement = false;
9990 SgStatement* surroundingStatement = findSurroundingStatementFromSameFile(targetStmt,surroundingStatementPreceedsTargetStatement);
9991
9992 if (surroundingStatement != nullptr)
9993 {
9994 // If we have identified a valid surrounding statemen, then move the comments and CPP directives to that statement.
9995#if REMOVE_STATEMENT_DEBUG
9996 printf ("In removeStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
9997 printf (" --- moving comments from targetStmt = %p = %s name = %s \n",targetStmt,targetStmt->class_name().c_str(),get_name(targetStmt).c_str());
9998 printf (" --- moving comments to surroundingStatement = %p = %s name = %s \n",surroundingStatement,surroundingStatement->class_name().c_str(),get_name(surroundingStatement).c_str());
9999#endif
10000 moveCommentsToNewStatement(targetStmt,captureList,surroundingStatement,surroundingStatementPreceedsTargetStatement);
10001 }
10002 }
10003 } // end if (comments)
10004 }// end if (autoRelocatePreprocessingInfo)
10005#endif // end #if 1
10006
10007 // DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
10009
10010 parentStatement->remove_statement(targetStmt);
10011 }
10012#else
10013 printf ("Error: This is not supported within Microsoft Windows (I forget why). \n");
10014 ROSE_ABORT();
10015#endif
10016
10017#endif
10018 }
10019
10020
10021
10023void
10025 {
10026 // This function allows the modification of the input statement to trigger operations on internal
10027 // data structures that hold references to such statements. An example is the macroExpansion
10028 // data structures that have a reference to the statements that are associated with and macro expansion.
10029 // if a statement assocated with a macro expansion is removed, then the macroExpansion needs to be
10030 // updated to force all of the statements to be marked as transformed (so that the AST will be unparsed
10031 // instead of the tokens representing the macro or some partial representation of the transformed
10032 // statements and the macro call (worse).
10033
10034#if 0
10035 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10036#endif
10037
10038 SgSourceFile* sourceFile = getEnclosingSourceFile(sourceStatement);
10039
10040 // NOTE: if the statment has not yet been added to the AST then it will not return a valid pointer.
10041 // ROSE_ASSERT(sourceFile != NULL);
10042
10043#if 0
10044 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceFile = %p \n",sourceFile);
10045#endif
10046
10047 if (sourceFile != NULL)
10048 {
10049 std::map<SgStatement*,MacroExpansion*> & macroExpansionMap = sourceFile->get_macroExpansionMap();
10050
10051 if (macroExpansionMap.find(sourceStatement) != macroExpansionMap.end())
10052 {
10053 MacroExpansion* macroExpansion = macroExpansionMap[sourceStatement];
10054 ROSE_ASSERT(macroExpansion != NULL);
10055#if 0
10056 printf ("In resetInternalMapsForTargetStatement(): macroExpansion = %p = %s \n",macroExpansion,macroExpansion->macro_name.c_str());
10057#endif
10058 if (macroExpansion->isTransformed == false)
10059 {
10060 // Mark all of the statements in the macro expansion to be transformed.
10061 std::vector<SgStatement*> & associatedStatementVector = macroExpansion->associatedStatementVector;
10062
10063 for (size_t i = 0; i < associatedStatementVector.size(); i++)
10064 {
10065 // I am concerned that some of these statements might have been deleted.
10066 SgStatement* statement = associatedStatementVector[i];
10067#if 0
10068 printf ("Mark as transformation to be output: statement = %p = %s \n",statement,statement->class_name().c_str());
10069#endif
10070 // Note that any new statement might not yet have valid Sg_File_Info objects setup at this point.
10071 // Then again, now did it make it into the associatedStatementVector unless it was via memory
10072 // recycling through the mmory pool.
10073 if (statement->get_file_info() != NULL)
10074 {
10075 // Mark each of the statements as a transformation.
10076 statement->setTransformation();
10077
10078 // This is required, else the statement will not be output in the generated code.
10079 // To understand this, consider that statements in header files could be transformed,
10080 // but we would not want that to cause them to be unparse in the source file.
10081 statement->setOutputInCodeGeneration();
10082
10083 // Not clear if we should also remove the statement from the associatedStatementVector.
10084 // This would be important to do to avoid having the same location in the memory pool
10085 // be reused for another statement. Since we makr the macro expansion as transformed
10086 // we likely don't have to worry about this.
10087 }
10088 }
10089 }
10090
10091 // Mark this macro expansion as having been processed.
10092 macroExpansion->isTransformed = true;
10093 }
10094
10095 // Other data strucutes that may have to be updated include:
10096 // representativeWhitespaceStatementMap (should be required, but only effects whitespace details)
10097 // redundantlyMappedTokensToStatementMultimap (might not be required)
10098
10099 }
10100 }
10101
10102
10104void
10105SageInterface::moveCommentsToNewStatement(SgStatement* sourceStatement, const vector<int> & indexList, SgStatement* destinationStatement , bool destinationStatementProceedsSourceStatement)
10106 {
10107 AttachedPreprocessingInfoType* comments = sourceStatement->getAttachedPreprocessingInfo();
10108
10109#if REMOVE_STATEMENT_DEBUG || 0
10110 printf ("In moveCommentsToNewStatement(): destinationStatementProceedsSourceStatement = %s \n",destinationStatementProceedsSourceStatement ? "true" : "false");
10111 printf (" --- sourceStatement = %p = %s name = %s \n",sourceStatement,sourceStatement->class_name().c_str(),get_name(sourceStatement).c_str());
10112 printf (" --- destinationStatement = %p = %s name = %s \n",destinationStatement,destinationStatement->class_name().c_str(),get_name(destinationStatement).c_str());
10113#endif
10114 // Liao 2024/1/24
10115 // There is a corner case: #if #endif may span very wide in the code. The lead #if may be moved without the matching #endif being found.
10116 // A solution : pcounter++ whenever a leading #if #ifdef #ifndef is encountered.
10117 // pcounter -- if #endif is countered
10118 // Normally the final pcounter ==0, if pcounter>=1, a #endif is missing somewhere. We should patch it up.
10119
10120#if REMOVE_STATEMENT_DEBUG
10121 printf ("Output the comments attached to sourceStatement: \n");
10122 printOutComments(sourceStatement);
10123 printf ("Output the comments attached to destinationStatement: \n");
10124 printOutComments(destinationStatement);
10125#endif
10126
10127 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
10128 vector<int>::const_iterator j = indexList.begin();
10129 PreprocessingInfo* prevTargetAnchorComment = NULL;
10130 while (j != indexList.end())
10131 {
10132 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
10133 ROSE_ASSERT(destinationStatement->get_file_info() != NULL);
10134#if REMOVE_STATEMENT_DEBUG || 0
10135 printf ("Attaching comments to destinationStatement = %p = %s on file = %s line %d \n",
10136 destinationStatement,destinationStatement->class_name().c_str(),
10137 destinationStatement->get_file_info()->get_filenameString().c_str(),
10138 destinationStatement->get_file_info()->get_line());
10139
10140 printf ("(*comments)[*j]->getRelativePosition() = %s \n",PreprocessingInfo::relativePositionName((*comments)[*j]->getRelativePosition()).c_str());
10141#endif
10142
10143 // Liao 2024/3/27: special handling when surrounding statement is SgGlobal
10144 // It should not be treated as either before or after the source statement we want to move comments from
10145 // SgGlobal should be treated as the enclosing scope of the source statement
10146 // The comments of the source statements should be attached to inside position of SgGlobal.
10147 // This is a variant of the before position (SgGlobal vs. source statement).
10148 // We do not treate SgGlobal as the same as if sgGlobal is preceeding source
10149 // because the comments of source statement would be attached to ::after of SgGlobal and
10150 // all comments will show up in the end of the file.
10151 // The ::inside location relies on the unparser to properly handle them later.
10152 if (destinationStatementProceedsSourceStatement == true || isSgGlobal(destinationStatement) != NULL )
10153 {
10154 // dest
10155 // src // comments to be moved up: all before positions become after position
10156 // // then append to dest's commments
10157 // adjust relative position one by one
10158 auto commentPosition = (*comments)[*j]->getRelativePosition();
10159 if (commentPosition == PreprocessingInfo::before)
10160 {
10161 // Mark comments that were before the preceeding statement to be after the preceeding statement
10162 (*comments)[*j]->setRelativePosition(PreprocessingInfo::after);
10163 }
10164 else if (commentPosition == PreprocessingInfo::after ||
10165 commentPosition == PreprocessingInfo::end_of)
10166 {
10167 // Leave position alone [Rasmussen 2023.01.09]
10168 }
10169 else
10170 {
10171 ROSE_ASSERT(false && "Comment relative position neither, before, after, nor end_of");
10172 }
10173
10174 // special handling of inside position
10175 // The surrounding statement will accept the comments. It also preceeds the source statement providing the comments.
10176 // If it is an enclosing scope statement, the comments should be attached to inside position, not before nor after.
10177 // if ( isSgGlobal(destinationStatement) || isSgBasicBlock(destinationStatement) )
10178 // Handle all SgScopeStatement variants.
10179 // We do this only for C/C++ language. Otherwise the code may break Jovial and other languages.
10181 {
10182 if (SageInterface::isAncestor(destinationStatement, sourceStatement))
10183 (*comments)[*j]->setRelativePosition(PreprocessingInfo::inside);
10184 }
10185 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10186
10187 }
10188 else // the target statement is after the source statment: we want to move comments from src to target
10189 {
10190 // src : comments : before or after (when moved to dest, it should become before)
10191 // all should be prepend to dest's first comment
10192 // dest: comments
10193 // adjust relative position one by one
10194 if ((*comments)[*j]->getRelativePosition() == PreprocessingInfo::before)
10195 {
10196 // Leave the comments marked as being before the removed statement
10197 // as before the following statement
10198 }
10199 else
10200 {
10201 // If is is not before, I hope it can only be after. Sometimes it is end_of, e.g. gitlab-issue-186.jov
10202 ASSERT_require((*comments)[*j]->getRelativePosition() == PreprocessingInfo::after||
10203 (*comments)[*j]->getRelativePosition() == PreprocessingInfo::end_of);
10204 (*comments)[*j]->setRelativePosition(PreprocessingInfo::before);
10205 }
10206 AttachedPreprocessingInfoType* targetInfoList = destinationStatement->getAttachedPreprocessingInfo();
10207 // source stmt has a list of comments c1, c2, c3
10208 // we want to keep their order and prepend to target stmt's existing comments
10209 // The solution is to define an anchor comment in target stmt
10210 // first time anchor is NULL, we prepend c1 to before the target stmt's first comment
10211 // after that, we insert after the anchor comment (previous anchor)
10212 // all anchor comments must come from source statement
10213 if (targetInfoList==NULL)
10214 {
10215 // we can just use append to the end. the same effect.
10216 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10217 }
10218 else
10219 {
10220 // target stmt has comments
10221 // first time to grab thing
10222 if( prevTargetAnchorComment==NULL)
10223 {
10224 PreprocessingInfo * origFirstTargetComment = *(targetInfoList->begin());
10225 // insert before this original first one
10226 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],origFirstTargetComment,false);
10227 }
10228 else
10229 {
10230 // now we have non null prev comment from target statement. insert after it!
10231 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],prevTargetAnchorComment ,true);
10232 }
10233 }
10234
10235 prevTargetAnchorComment = (*comments)[*j];
10236 }
10237
10238
10239 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
10240#if REMOVE_STATEMENT_DEBUG
10241 printf ("Marking entry from comments list as NULL on sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10242#endif
10243 (*comments)[*j] = nullptr;// Why do we need to make it NULL??
10244
10245 j++;
10246 }
10247
10248 // Now remove each NULL entries in the comments vector.
10249 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
10250 for (size_t n = 0; n < indexList.size(); n++)
10251 {
10252#if REMOVE_STATEMENT_DEBUG || 0
10253 printf ("Erase entry from comments list on comments->size() %" PRIuPTR " \n",comments->size());
10254#endif
10255 bool modifiedList = false;
10256 AttachedPreprocessingInfoType::iterator k = comments->begin();
10257 while (k != comments->end() && modifiedList == false)
10258 {
10259 // Only modify the list once per iteration over the captureList
10260 if (*k == nullptr)
10261 {
10262 k = comments->erase(k);
10263 modifiedList = true;
10264 continue;
10265 }
10266 else
10267 {
10268 k++;
10269 }
10270 }
10271 }
10272 }
10273
10274
10276// This function is a helper function for SageInterface::removeStatement() to handle preprocessing info.
10277// It should find a suitable destination statement to which we can move the current stmt's preprocessing info to.
10278// targetStmt of this function is the source statement to move preprocessing info first, before removing it.
10280SageInterface::findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement)
10281 {
10282 // Note that if the return value is SgGlobal (global scope), then surroundingStatementPreceedsTargetStatement is false, but meaningless.
10283 // This function can not return a NULL pointer.
10284
10285 ROSE_ASSERT(targetStmt != NULL);
10286
10287 SgStatement* surroundingStatement = targetStmt;
10288 int surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID; // No file id can have this value.
10289
10290#if REMOVE_STATEMENT_DEBUG || 0
10291 printf ("TOP of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10292#endif
10293
10294 std::set<SgStatement*> previousVisitedStatementSet;
10295
10296 // Only handle relocation for statements that exist in the file (at least for now while debugging).
10297 if (targetStmt->get_file_info()->get_file_id() >= 0)
10298 {
10299 surroundingStatementPreceedsTargetStatement = true;
10300
10301#if REMOVE_STATEMENT_DEBUG
10302 printf (" targetStmt->get_file_info()->get_file_id() = %d \n",targetStmt->get_file_info()->get_file_id());
10303#endif
10304#if REMOVE_STATEMENT_DEBUG
10305 printf ("Before loop: surroundingStatement = %p = %s name = %s surroundingStatement_fileId = %d \n",surroundingStatement,
10306 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str(),surroundingStatement_fileId);
10307#endif
10308 bool returningNullSurroundingStatement = false;
10309 // while (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id())
10310 while ((returningNullSurroundingStatement == false) && (surroundingStatement != NULL) && surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id() && surroundingStatement_fileId !=Sg_File_Info::TRANSFORMATION_FILE_ID)
10311 {
10312 // Start by going up in the source sequence.
10313 // This is a declaration from the wrong file so go to the next statement.
10314 // surroundingStatement = (insertBefore == true) ? getNextStatement(surroundingStatement) : getPreviousStatement(surroundingStatement);
10315 // surroundingStatement = (insertBefore == true) ? getPreviousStatement(surroundingStatement) : getNextStatement(surroundingStatement);
10316 // Liao, 12/26/2024. We should not climb out the current scope when finding the previous statement
10317 // Otherwise, preprocessingInfo may be moved from a child stmt to its parent stmt, causing errors in AST.
10318 surroundingStatement = getPreviousStatement(surroundingStatement, false);
10319
10320#if REMOVE_STATEMENT_DEBUG
10321 printf ("In loop: after getPreviousStatement(): surroundingStatement = %p = %s name = %s \n",surroundingStatement,
10322 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str());
10323#endif
10324
10325 if (surroundingStatement == NULL)
10326 {
10327 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10328#if REMOVE_STATEMENT_DEBUG
10329 printf (" surroundingStatement_fileId set to Sg_File_Info::BAD_FILE_ID \n");
10330#endif
10331 }
10332 else
10333 {
10334 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10335#if REMOVE_STATEMENT_DEBUG
10336 printf (" surroundingStatement = %p = %s surroundingStatement->get_file_info()->get_file_id() = %d \n",
10337 surroundingStatement,surroundingStatement->class_name().c_str(),surroundingStatement->get_file_info()->get_file_id());
10338#endif
10339 }
10340
10341#if REMOVE_STATEMENT_DEBUG
10342 if (surroundingStatement != NULL)
10343 {
10344 printf ("Looping toward the top of the file for a statement to attach comments and CPP directives to: surroundingStatement = %p = %s file = %s file id = %d line = %d \n",
10345 surroundingStatement,surroundingStatement->class_name().c_str(),
10346 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10347 surroundingStatement->get_file_info()->get_file_id(),
10348 surroundingStatement->get_file_info()->get_line());
10349 }
10350 else
10351 {
10352 printf ("surroundingStatement == NULL \n");
10353 }
10354#endif
10355
10356 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10357 if (previousVisitedStatementSet.find(surroundingStatement) != previousVisitedStatementSet.end())
10358 {
10359 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10360
10361 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10362
10363 surroundingStatement = NULL;
10364 // break;
10365 // return NULL;
10366 }
10367 else
10368 {
10369 previousVisitedStatementSet.insert(surroundingStatement);
10370 }
10371
10372 // As a last resort restart and go down in the statement sequence.
10373 if (surroundingStatement == NULL || isSgGlobal(surroundingStatement) != NULL)
10374 {
10375 // This is triggered by rose_inputloopUnrolling.C
10376#if REMOVE_STATEMENT_DEBUG
10377 printf ("We just ran off the start (top) of the file... targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
10378#endif
10379#if 0
10380 ROSE_ABORT();
10381#endif
10382 // A statement in the same file could not be identified, so this is false.
10383 surroundingStatementPreceedsTargetStatement = false;
10384
10385 // Restart by going the other direction (down in the source sequence)
10386 surroundingStatement = targetStmt;
10387 SgStatement* previousStatement = surroundingStatement;
10388 // surroundingStatement = getNextStatement(surroundingStatement);
10389 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10390
10391 std::set<SgStatement*> forwardVisitedStatementSet;
10392
10393 // while ( (surroundingStatement != NULL) && (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id()) )
10394 while ( (surroundingStatement != NULL) && (surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id()) )
10395 {
10396 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10397 if (forwardVisitedStatementSet.find(surroundingStatement) != forwardVisitedStatementSet.end())
10398 {
10399 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10400
10401 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10402
10403 surroundingStatement = NULL;
10404 break;
10405 // return NULL;
10406 }
10407 else
10408 {
10409 forwardVisitedStatementSet.insert(surroundingStatement);
10410 }
10411
10412 previousStatement = surroundingStatement;
10413 surroundingStatement = getNextStatement(surroundingStatement);
10414
10415 if (surroundingStatement == NULL)
10416 {
10417 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10418#if REMOVE_STATEMENT_DEBUG
10419 printf ("We just ran off the end (bottom) of the file... \n");
10420#endif
10421#if 0
10422 ROSE_ABORT();
10423#endif
10424 returningNullSurroundingStatement = true;
10425 }
10426 else
10427 {
10428 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10429#if REMOVE_STATEMENT_DEBUG
10430 printf ("Looping toward the bottom of the file for a statement to attach comments and CPP directives to: surroundingStatement = %p = %s file = %s file id = %d line = %d \n",
10431 surroundingStatement,surroundingStatement->class_name().c_str(),
10432 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10433 surroundingStatement->get_file_info()->get_file_id(),
10434 surroundingStatement->get_file_info()->get_line());
10435#endif
10436 }
10437 }
10438
10439 if (surroundingStatement == NULL)
10440 {
10441#if REMOVE_STATEMENT_DEBUG
10442 printf ("Resetting the surroundingStatement to the previousStatement = %p = %s \n",previousStatement,previousStatement->class_name().c_str());
10443#endif
10444 surroundingStatement = previousStatement;
10445
10446 // Check if this is the input statement we are removing (since the we have to attach comments to the global scope IR node.
10447 if (surroundingStatement == targetStmt)
10448 {
10449 // This can happen if there was only a single statement in a file and it was removed.
10450 // All associated comments would have to be relocated to the SgGlobal IR node.
10451#if REMOVE_STATEMENT_DEBUG
10452 printf ("Setting the surroundingStatement to be global scope \n");
10453#endif
10454 surroundingStatement = TransformationSupport::getGlobalScope(targetStmt);
10455 }
10456 }
10457 }
10458 }
10459
10460 ROSE_ASSERT(surroundingStatement != NULL);
10461 }
10462 else
10463 {
10464 printf ("This is a special statement (not associated with the original source code, comment relocation is not supported for these statements) targetStmt file id = %d \n",targetStmt->get_file_info()->get_file_id());
10465 surroundingStatement = NULL;
10466 }
10467
10468#if REMOVE_STATEMENT_DEBUG
10469 printf ("BOTTOM of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s surroundingStatement = %p \n",surroundingStatementPreceedsTargetStatement ? "true" : "false",surroundingStatement);
10470 if (surroundingStatement != NULL)
10471 {
10472 printf ("surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10473 }
10474#endif
10475
10476 // ROSE_ASSERT(surroundingStatement != NULL);
10477
10478 return surroundingStatement;
10479 }
10480
10481
10482#ifndef USE_ROSE
10485{
10486#if 0
10487 struct Visitor: public AstSimpleProcessing {
10488 virtual void visit(SgNode* n) {
10489 delete (n);
10490 }
10491 };
10492 Visitor().traverse(root, postorder);
10493#else
10494 deleteAST(root);
10495#endif
10496}
10497#endif
10498
10500void SageInterface::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessingInfoValue/* = false*/)
10501 {
10502 ROSE_ASSERT(oldStmt);
10503 ROSE_ASSERT(newStmt);
10504
10505 if (oldStmt == newStmt) return;
10506
10507 SgStatement * p = isSgStatement(oldStmt->get_parent());
10508 ROSE_ASSERT(p);
10509
10510#if 0
10511 // TODO handle replace the body of a C/Fortran function definition with a single statement?
10512 // Liao 2/1/2010, in some case, we want to replace the entire body (SgBasicBlock) for some parent nodes.
10513 // the built-in replace_statement() (insert_child() underneath) may not defined for them.
10514 if (SgFortranDo * f_do = isSgFortranDo (p))
10515 {
10516 ROSE_ASSERT (f_do->get_body() == oldStmt);
10517 if (!isSgBasicBlock(newStmt))
10518 newStmt = buildBasicBlock (newStmt);
10519 f_do->set_body(isSgBasicBlock(newStmt));
10520 newStmt->set_parent(f_do);
10521 }
10522 else
10523 {
10524 p->replace_statement(oldStmt,newStmt);
10525 }
10526#endif
10527 p->replace_statement(oldStmt,newStmt);
10528
10529#if 1
10530 // DQ (7/20/2021): Need to make the physical_file_ids match and the parents.
10531 // Acutally this may be too late in the case of a deferred transformation since
10532 // we run the AST consistancy tests as an intermediate step.
10533 int physical_file_id = oldStmt->get_startOfConstruct()->get_physical_file_id();
10534
10535#if 0
10536 printf ("In SageInterface::replaceStatement(): physical_file_id = %d \n",physical_file_id);
10537#endif
10538
10539 newStmt->get_startOfConstruct()->set_physical_file_id(physical_file_id);
10540 newStmt->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
10541
10542 // DQ (7/20/2021): Do we need this when we set the physical_file_id?
10543 newStmt->set_parent(oldStmt->get_parent());
10544#endif
10545
10546 // Some translators have their own handling for this (e.g. the outliner)
10547 if (movePreprocessingInfoValue)
10548 {
10549 // move inner dangling #endif, #if etc to newStmt's after position, otherwise they got lost
10550//A-B test here
10551 // I think we should move up old statement's inner dangling directives
10552 // later , we move directives from old statement to new statement
10554#if 0
10555 printf ("In SageInterface::replaceStatement(): calling moveUpPreprocessingInfo() changed to movePreprocessingInfo() \n");
10556#endif
10557
10558 // DQ (12/28/2020): I think this should be movePreprocessingInfo instead of moveUpPreprocessingInfo
10559 // (which has a collection of defaults that are not appropriate).
10560 // moveUpPreprocessingInfo(newStmt, oldStmt);
10561#if 1
10562 // DQ (12/28/2020): Since this works we will leave it in place (it appears to not be required to call this with: usePrepend == true).
10563 moveUpPreprocessingInfo(newStmt, oldStmt);
10564#else
10565 // void SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
10566 // PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
10567 bool usePrepend = true;
10568 // movePreprocessingInfo ( newStmt, oldStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10569 movePreprocessingInfo ( oldStmt, newStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10570#endif
10571 }
10572 }
10573
10574void
10576 {
10577 // Relocate the declaration to be explicitly represented in its associated namespace (required for some backend compilers to process template instantiations).
10578
10579 // DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
10580 // compiler which does not permit name qualification to be used to support the expression of the namespace
10581 // where a template instantiatoon would be places. Such name qualification would also sometimes require
10582 // global qualification which is also not allowed by the GNU g++ compiler. These issues appear to be
10583 // specific to the GNU compiler versions, at least versions 4.4 through 4.8.
10584
10585 // Find the previous statement in this scope so that we can close off the namepsace and start a new one.
10586 SgStatement* previousDeclarationStatement = getPreviousStatement(declarationStatement);
10587 SgStatement* nextDeclarationStatement = getNextStatement(declarationStatement);
10588
10589#if 0
10590 printf ("In SageInterface::moveDeclarationToAssociatedNamespace(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
10591 printf (" --- previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement != NULL ? previousDeclarationStatement->class_name().c_str() : "null");
10592 printf (" --- nextDeclarationStatement = %p \n",nextDeclarationStatement);
10593 printf (" --- nextDeclarationStatement = %p = %s \n",nextDeclarationStatement, nextDeclarationStatement != NULL ? nextDeclarationStatement->class_name().c_str() : "null");
10594#endif
10595
10596 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10597 if (previousDeclarationStatement != NULL)
10598 {
10599 // printf ("previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement->class_name().c_str());
10600 }
10601 else
10602 {
10603 printf ("There is no previous statement so there is no namespace to close off! \n");
10604
10605 // Handle this corner case after we have the most general case working!
10606 printf ("Exiting as a test! \n");
10607 ROSE_ABORT();
10608 }
10609
10610 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10611 if (nextDeclarationStatement != NULL)
10612 {
10613 // printf ("nextDeclarationStatement = %p = %s \n",nextDeclarationStatement,nextDeclarationStatement->class_name().c_str());
10614 }
10615 else
10616 {
10617#if 0
10618 printf ("There is no next statement so there is no namespace to reopen! \n");
10619#endif
10620#if 0
10621 // Handle this corner case after we have the most general case working!
10622 printf ("Exiting as a test! \n");
10623 ROSE_ABORT();
10624#endif
10625 }
10626
10627 if (previousDeclarationStatement != NULL && nextDeclarationStatement != NULL)
10628 {
10629 // DQ (7/19/2015): This is the most common case!
10630#if 0
10631 printf ("Identified the most common case... \n");
10632#endif
10633 // Identify the associated namespace
10634 //SgScopeStatement* declarationScope = declarationStatement->get_scope();
10635#if 0
10636 printf ("declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10637#endif
10638#if 0
10639 // Handle this corner case after we have the most general case working!
10640 printf ("Exiting as a test! \n");
10641 ROSE_ABORT();
10642#endif
10643 }
10644 else
10645 {
10646 if (previousDeclarationStatement != NULL && nextDeclarationStatement == NULL)
10647 {
10648 // This is the case for the last template instantiaton in global scope (so it too is a common case)!
10649#if 0
10650 printf ("Found 2nd most common case: previousDeclarationStatement != NULL && nextDeclarationStatement == NULL \n");
10651#endif
10652#if 0
10653 // Handle this corner case after we have the most general case working!
10654 printf ("Exiting as a test! \n");
10655 ROSE_ABORT();
10656#endif
10657 }
10658 else
10659 {
10660 if (previousDeclarationStatement == NULL && nextDeclarationStatement == NULL)
10661 {
10662 printf ("This case should require no special handling, unless we are still in the wrong namespace \n");
10663
10664 // Handle this corner case after we have the most general case working!
10665 printf ("Exiting as a test! \n");
10666 ROSE_ABORT();
10667 }
10668 else
10669 {
10670 printf ("This case should have been caught above! \n");
10671
10672 // Handle this corner case after we have the most general case working!
10673 printf ("Exiting as a test! \n");
10674 ROSE_ABORT();
10675 }
10676 }
10677 }
10678
10679 SgScopeStatement* declarationParent = isSgScopeStatement(declarationStatement->get_parent());
10680 if (declarationParent == NULL)
10681 {
10682#if 0
10683 printf ("declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10684#endif
10685 }
10686 // This can be a SgTemplateInstantiationDirectiveStatement (bug we want to skip over this case for now).
10687 // ROSE_ASSERT(declarationParent != NULL);
10688
10689 if (declarationParent != NULL)
10690 {
10691 SgScopeStatement* declarationScope = declarationStatement->get_scope();
10692 ROSE_ASSERT(declarationScope != NULL);
10693
10694 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(declarationScope);
10695 if (namespaceDefinition != NULL)
10696 {
10697 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
10698 ROSE_ASSERT(namespaceDeclaration != NULL);
10699#if 0
10700 printf ("The declaration has been identified to be associuated with a valid namespace = %p = %s \n",namespaceDeclaration,namespaceDeclaration->get_name().str());
10701 printf (" --- declarationParent = %p = %s \n",declarationParent,declarationParent->class_name().c_str());
10702 printf (" --- Move declaration from scope = %p = %s to namespace = %p = %s \n",declarationParent,declarationParent->class_name().c_str(),namespaceDeclaration,namespaceDeclaration->get_name().str());
10703#endif
10704#if 0
10705 printf ("Exiting as a test! \n");
10706 ROSE_ABORT();
10707#endif
10708 }
10709 else
10710 {
10711#if 0
10712 printf ("declaration is not associated with a namespace, so we don't have to wrap it: declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10713#endif
10714 }
10715 }
10716 else
10717 {
10718#if 0
10719 printf ("Warning: declarationParent == NULL: declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10720#endif
10721 // ROSE_ASSERT(declarationParent != NULL);
10722 }
10723
10724 }
10725
10726
10727bool
10729 {
10730 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10731 if (isSgTemplateInstantiationDefn(node) != NULL)
10732 {
10733#if 0
10734 printf ("Note: In SageInterface::isTemplateInstantiationNode(): skipping SgTemplateInstantiationDefn \n");
10735#endif
10736 }
10737
10738 return isSgTemplateInstantiationDecl(node)
10739 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10740// || isSgTemplateInstantiationDefn(node)
10741 || isSgTemplateInstantiationDefn(node)
10742 || isSgTemplateInstantiationFunctionDecl(node)
10743 || isSgTemplateInstantiationMemberFunctionDecl(node)
10744 || isSgTemplateInstantiationTypedefDeclaration(node)
10745 || isSgTemplateInstantiationDirectiveStatement(node)
10746 ;
10747 }
10748
10749#if 0
10750// DQ (5/23/2021): Added (uncommented, and added to the header file) function to support test for template declaration.
10751// Commented back out, since this is not required for what I am debugging currently.
10752// DQ (6/27/2018): This will be the template declaration test version of the template instantiation test function above.
10753bool
10754SageInterface::isTemplateDeclarationNode(SgNode* node)
10755 {
10756 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10757 if (isSgTemplateDefinition(node) != NULL)
10758 {
10759#if 0
10760 printf ("Note: In SageInterface::isTemplateDeclarationNode(): skipping SgTemplateDefinition \n");
10761#endif
10762 }
10763
10764 return isSgTemplateInstantiationDecl(node)
10765 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10766 // || isSgTemplateInstantiationDefn(node)
10767 || isSgTemplateInstantiationDefn(node)
10768 || isSgTemplateInstantiationFunctionDecl(node)
10769 || isSgTemplateInstantiationMemberFunctionDecl(node)
10770 || isSgTemplateInstantiationTypedefDeclaration(node)
10771 || isSgTemplateInstantiationDirectiveStatement(node)
10772 ;
10773 }
10774#endif
10775
10776void
10778 {
10779 // DQ (8/18/2015): This function is called from the tests/nonsmoke/functional/testTemplates translator.
10780
10781 // DQ (7/19/2015): This function can't use an iterator since it will be
10782 // doing transformations on the AST and will cause iterator invalidation errors.
10783
10784 std::vector<SgDeclarationStatement*> templateInstantiationVector;
10785
10786 // DQ (9/24/2015): This feature is not available yet in CMake (Markus is adding the library support for this feature).
10787#ifndef USE_CMAKEx
10788 RoseAst ast(root);
10789
10790 for (RoseAst::iterator i= ast.begin(); i!= ast.end(); ++i)
10791 {
10793 {
10794 // markNodeToBeUnparsed(*i);
10795 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
10796 if (declaration != NULL)
10797 {
10798 templateInstantiationVector.push_back(declaration);
10799 }
10800 else
10801 {
10802 // I think it is OK that not all are a SgDeclarationStatement.
10803 }
10804 }
10805 }
10806#else
10807 std::cerr << "This feature for now is available with autotools only!" << std::endl;
10808 ROSE_ABORT();
10809#endif
10810
10811 std::vector<SgDeclarationStatement*>::iterator j = templateInstantiationVector.begin();
10812 while (j != templateInstantiationVector.end())
10813 {
10815 j++;
10816 }
10817 }
10818
10819
10820
10822// All SgVariantExpression in the pattern will be replaced with copies of the anchor node.
10824{
10825 SgExpression * anchor_exp = isSgExpression(anchor);
10826 SgExpression * pattern_exp = isSgExpression(new_pattern);
10827 ROSE_ASSERT (anchor_exp != NULL);
10828 ROSE_ASSERT (pattern_exp != NULL);
10829
10830 // we replace all SgExpression within the pattern with copies of anchor
10831 Rose_STL_Container<SgNode*> opaque_exp_list = NodeQuery::querySubTree(pattern_exp,V_SgExpression);
10832 for (size_t i = 0; i<opaque_exp_list.size(); i++)
10833 {
10834 SgExpression* opaque_exp = isSgExpression(opaque_exp_list[i]);
10835 ROSE_ASSERT (opaque_exp != NULL);
10836 if (opaque_exp->variantT() == V_SgVariantExpression)
10837 {
10838 SgExpression * anchor_exp_copy = deepCopy(anchor_exp);
10839 replaceExpression(opaque_exp, anchor_exp_copy);
10840 }
10841 }
10842
10843 // finally we replace anchor_exp with the pattern_exp
10844 replaceExpression(anchor_exp, pattern_exp, false);
10845 return new_pattern;
10846}
10850{
10851 //This implementation tends to generate numbers that are unnecessarily high.
10852 static int counter = 0;
10853
10854 string name;
10855 bool collision = false;
10856 do
10857 {
10858 name = "__" + baseName + boost::lexical_cast<string > (counter++) + "__";
10859
10860 // DQ (8/16/2013): Modified to reflect new API.
10861 // Look up the name in the parent scopes
10862 // SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope);
10863 SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope,NULL,NULL);
10864 collision = (nameSymbol != NULL);
10865
10866 //Look up the name in the children scopes
10867 Rose_STL_Container<SgNode*> childScopes = NodeQuery::querySubTree(scope, V_SgScopeStatement);
10868
10869 BOOST_FOREACH(SgNode* childScope, childScopes)
10870 {
10871 SgScopeStatement* childScopeStatement = isSgScopeStatement(childScope);
10872
10873 // DQ (8/16/2013): Modified to reflect new API.
10874 // nameSymbol = childScopeStatement->lookup_symbol(SgName(name));
10875 nameSymbol = childScopeStatement->lookup_symbol(SgName(name),NULL,NULL);
10876
10877 collision = collision || (nameSymbol != NULL);
10878 }
10879 } while (collision);
10880
10881 return name;
10882}
10883
10884
10885std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableForExpression
10886(SgExpression* expression, SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate)
10887{
10888 SgType* expressionType = expression->get_type();
10889 SgType* variableType = expressionType;
10890
10891 //If the expression has a reference type, we need to use a pointer type for the temporary variable.
10892 //Else, re-assigning the variable is not possible
10893 bool isReferenceType = SageInterface::isReferenceType(expressionType);
10894 if (isReferenceType)
10895 {
10896 SgType* expressionBaseType = expressionType->stripType(SgType::STRIP_TYPEDEF_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE);
10897 variableType = SageBuilder::buildPointerType(expressionBaseType);
10898 }
10899
10900 //MS 10/24/2018: If the expression has array type, we need to use a pointer type referring to the base type for the temporary variable.
10901 if (SgArrayType* arrayType=isSgArrayType(expressionType)) {
10902 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
10903 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
10904 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
10905 }
10906 }
10907
10908 // If the expression is a dereferenced pointer, use a reference to hold it.
10909 if (isSgPointerDerefExp(expression))
10910 variableType = SageBuilder::buildReferenceType(variableType);
10911
10912 //Generate a unique variable name
10913 string name = generateUniqueVariableName(scope);
10914
10915 //Initialize the temporary variable to an evaluation of the expression
10916 SgExpression* tempVarInitExpression = SageInterface::copyExpression(expression);
10917 ROSE_ASSERT(tempVarInitExpression != NULL);
10918 if (isReferenceType)
10919 {
10920 //FIXME: the next line is hiding a bug in ROSE. Remove this line and talk to Dan about the resulting assert
10921 tempVarInitExpression->set_lvalue(false);
10922
10923 tempVarInitExpression = SageBuilder::buildAddressOfOp(tempVarInitExpression);
10924 }
10925
10926 //Optionally initialize the variable in its declaration
10927 SgAssignInitializer* initializer = NULL;
10928 if (initializeInDeclaration)
10929 {
10930 SgExpression* initExpressionCopy = SageInterface::copyExpression(tempVarInitExpression);
10931 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
10932 }
10933
10934 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
10935 ROSE_ASSERT(tempVarDeclaration != NULL);
10936
10937 //Now create the assignment op for reevaluating the expression
10938 if (reEvaluate != NULL)
10939 {
10940 SgVarRefExp* tempVarReference = SageBuilder::buildVarRefExp(tempVarDeclaration);
10941 *reEvaluate = SageBuilder::buildAssignOp(tempVarReference, tempVarInitExpression);
10942 }
10943
10944 //Build the variable reference expression that can be used in place of the original expression
10945 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
10946 if (isReferenceType)
10947 {
10948 //The temp variable is a pointer type, so dereference it before using it
10949 varRefExpression = SageBuilder::buildPointerDerefExp(varRefExpression);
10950 }
10951
10952 return std::make_pair(tempVarDeclaration, varRefExpression);
10953}
10954
10955// This function creates a temporary variable for a given expression in the given scope
10956// This is different from SageInterface::createTempVariableForExpression in that it does not
10957// try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
10958// The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
10959// may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
10960
10961std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableAndReferenceForExpression
10962(SgExpression* expression, SgScopeStatement* scope)
10963{
10964 SgType* expressionType = expression->get_type();
10965 SgType* variableType = expressionType;
10966
10967 //MS 10/24/2018: If the expression has array type, we need to use a pointer type for the temporary variable.
10968 if (SgArrayType* arrayType=isSgArrayType(expressionType))
10969 {
10970 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
10971 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
10972 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
10973 }
10974 }
10975
10976 //Generate a unique variable name
10977 string name = generateUniqueVariableName(scope);
10978
10979 //initialize the variable in its declaration
10980 SgAssignInitializer* initializer = NULL;
10981 SgExpression* initExpressionCopy = SageInterface::copyExpression(expression);
10982 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
10983
10984 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
10985 ROSE_ASSERT(tempVarDeclaration != NULL);
10986
10987 //Build the variable reference expression that can be used in place of the original expression
10988 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
10989 return std::make_pair(tempVarDeclaration, varRefExpression);
10990}
10991
10992
10993namespace
10994{
10995 void
10996 replaceExpressionInSgExpressionPtrList(SgExpression* oldExp, SgExpression* newExp, SgExpressionPtrList& lst, bool replAll = false)
10997 {
10998 SgExpressionPtrList::iterator lim = lst.end();
10999 SgExpressionPtrList::iterator pos = lst.begin();
11000 bool chg = false;
11001
11002 do
11003 {
11004 pos = std::find(pos, lim, oldExp);
11005
11006 if (pos != lim) { *pos = newExp; ++pos; chg = true; }
11007 } while (replAll && (pos != lim));
11008
11009 ROSE_ASSERT(chg);
11010 }
11011}
11012
11013// This code is based on OpenMP translator's ASTtools::replaceVarRefExp() and astInling's replaceExpressionWithExpression()
11014// Motivation: It involves the parent node to replace a VarRefExp with a new node
11015// Used to replace shared variables with the dereference expression of their addresses
11016// e.g. to replace shared1 with (*__pp_shared1)
11017
11018void SageInterface::replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp/*=false*/) {
11019 SgExpression* parentExp;
11020
11021 ROSE_ASSERT(oldExp);
11022 ROSE_ASSERT(newExp);
11023 if (oldExp==newExp) return;
11024
11025 if (isSgVarRefExp(newExp))
11026 newExp->set_need_paren(true); // enclosing new expression with () to be safe
11027
11028 SgNode* parent = oldExp->get_parent();
11029 ROSE_ASSERT(parent!=NULL);
11030 newExp->set_parent(parent);
11031
11032 // set lvalue when necessary
11033 if (oldExp->get_lvalue() == true) newExp->set_lvalue(true);
11034
11035 if (isSgExprStatement(parent)) {
11036 isSgExprStatement(parent)->set_expression(newExp);
11037 } else if (isSgForStatement(parent)) {
11038 ROSE_ASSERT (isSgForStatement(parent)->get_increment() == oldExp);
11039 isSgForStatement(parent)->set_increment(newExp);
11040 // TODO: any other cases here??
11041 } else if(SgMatlabForStatement *matlabFor = isSgMatlabForStatement(parent)) {
11042 if(matlabFor->get_index() == oldExp)
11043 matlabFor->set_index(newExp);
11044 else if(matlabFor->get_range() == oldExp)
11045 matlabFor->set_range(newExp);
11046 else
11047 ROSE_ASSERT(!"sub-expression not found");
11048 } else if(SgJovialForThenStatement *jovFor = isSgJovialForThenStatement(parent)) {
11049 if(jovFor->get_initialization() == oldExp)
11050 jovFor->set_initialization(newExp);
11051 else if(jovFor->get_while_expression() == oldExp)
11052 jovFor->set_while_expression(newExp);
11053 else if(jovFor->get_by_or_then_expression() == oldExp)
11054 jovFor->set_by_or_then_expression(newExp);
11055 else
11056 ROSE_ASSERT(!"sub-expression not found");
11057 } else if (SgRangeExp* rngexp = isSgRangeExp(parent)) {
11058 if (rngexp->get_start() == oldExp)
11059 rngexp->set_start(newExp);
11060 else if (rngexp->get_end() == oldExp)
11061 rngexp->set_end(newExp);
11062 else if (rngexp->get_stride() == oldExp)
11063 rngexp->set_stride(newExp);
11064 else
11065 ROSE_ASSERT(!"sub-expression not found");
11066 } else if (isSgReturnStmt(parent)) {
11067 isSgReturnStmt(parent)->set_expression(newExp);
11068 } else if (isSgBinaryOp(parent)!=NULL) {
11069 if (oldExp==isSgBinaryOp(parent)->get_lhs_operand()) {
11070 isSgBinaryOp(parent)->set_lhs_operand(newExp);
11071 } else if (oldExp==isSgBinaryOp(parent)->get_rhs_operand()) {
11072 isSgBinaryOp(parent)->set_rhs_operand(newExp);
11073 } else {
11074 ROSE_ABORT();
11075 }
11076 } else if (isSgUnaryOp(parent)!=NULL){
11077 if (oldExp==isSgUnaryOp(parent)->get_operand_i())
11078 isSgUnaryOp(parent)->set_operand_i(newExp);
11079 else
11080 ROSE_ABORT();
11081 } else if (isSgConditionalExp(parent) != NULL) {
11082 SgConditionalExp* expparent = isSgConditionalExp(parent); //get explicity type parent
11083 if (oldExp==expparent->get_conditional_exp())
11084 expparent->set_conditional_exp(newExp);
11085 else if (oldExp==expparent->get_true_exp())
11086 expparent->set_true_exp(newExp);
11087 else if (oldExp==expparent->get_false_exp())
11088 expparent->set_false_exp(newExp);
11089 else
11090 ROSE_ABORT();
11091 } else if (isSgExprListExp(parent) != NULL) {
11092 SgExpressionPtrList& explist = isSgExprListExp(parent)->get_expressions();
11093 for (Rose_STL_Container<SgExpression*>::iterator i=explist.begin();i!=explist.end();i++) {
11094 if (isSgExpression(*i)==oldExp) {
11095 SgExprListExp* parentExpListExp = isSgExprListExp(parent);
11096 parentExpListExp->replace_expression(oldExp,newExp);
11097 // break; //replace the first occurrence only??
11098 }
11099 }
11100 } else if (isSgValueExp(parent)) {
11101 // For compiler generated code, this could happen.
11102 // We can just ignore this function call since it will not appear in the final AST.
11103 return;
11104 } else if (SgActualArgumentExpression* actexp = isSgActualArgumentExpression(parent)) {
11105 ROSE_ASSERT(oldExp == actexp->get_expression());
11106 actexp->set_expression(newExp);
11107 } else if (SgAdaAttributeExp* attrexp = isSgAdaAttributeExp(parent)) {
11108 if (oldExp == attrexp->get_object()) {
11109 attrexp->set_object(newExp);
11110 } else if (oldExp == attrexp->get_args()) {
11111 SgExprListExp* newLst = isSgExprListExp(newExp);
11112 ASSERT_not_null(newLst);
11113
11114 attrexp->set_args(newLst);
11115 } else {
11116 ROSE_ABORT();
11117 }
11118 /**** ALL expressions must be handled before the next line *****/
11119 } else if ((parentExp=isSgExpression(parent)) != NULL) {
11120 int worked = parentExp->replace_expression(oldExp, newExp);
11121 // ROSE_DEPRECATED_FUNCTION
11122 ROSE_ASSERT (worked);
11123 } else if (isSgInitializedName(parent)) {
11124 SgInitializedName* initializedNameParent = isSgInitializedName(parent);
11125 if (oldExp == initializedNameParent->get_initializer()) {
11126 //We can only replace an initializer expression with another initializer expression
11127 ROSE_ASSERT(isSgInitializer(newExp));
11128 initializedNameParent->set_initializer(isSgInitializer(newExp));
11129 } else {
11130 //What other expressions can be children of an SgInitializedname?
11131 ROSE_ABORT();
11132 }
11133 } else if (isSgCaseOptionStmt(parent)) {
11134 SgCaseOptionStmt * case_stmt = isSgCaseOptionStmt(parent);
11135 if (oldExp == case_stmt->get_key()) {
11136 case_stmt->set_key(newExp);
11137 } else if(oldExp == case_stmt->get_key_range_end()) {
11138 case_stmt->set_key_range_end(newExp);
11139 } else {
11140 ROSE_ABORT();
11141 }
11142 } else if (isSgProcessControlStatement(parent)) {
11144 if (oldExp == ctrl_stmt->get_quiet()) {
11145 ctrl_stmt->set_quiet(newExp);
11146 } else if (oldExp == ctrl_stmt->get_code()) {
11147 ctrl_stmt->set_code(newExp);
11148 } else {
11149 ROSE_ABORT();
11150 }
11151 } else if (isSgFortranDo(parent)) {
11152 SgFortranDo* fortranDo = isSgFortranDo(parent);
11153 if (oldExp == fortranDo->get_initialization()) {
11154 fortranDo->set_initialization(newExp);
11155 } else if(oldExp == fortranDo->get_bound()) {
11156 fortranDo->set_bound(newExp);
11157 } else if (oldExp == fortranDo->get_increment()) {
11158 fortranDo->set_increment(newExp);
11159 } else {
11160 ROSE_ABORT();
11161 }
11162 }
11163 else if (SgAdaExitStmt* stm = isSgAdaExitStmt(parent)) {
11164 ROSE_ASSERT(oldExp == stm->get_condition());
11165 stm->set_condition(newExp);
11166 }
11167 else if (SgAdaModularType* ptype = isSgAdaModularType(parent)) {
11168 ROSE_ASSERT(oldExp == ptype->get_modexpr());
11169 ptype->set_modexpr(newExp);
11170 }
11171 else if (SgAdaDelayStmt* stm = isSgAdaDelayStmt(parent)) {
11172 ROSE_ASSERT(oldExp == stm->get_time());
11173 stm->set_time(newExp);
11174 } else if (SgAdaAttributeClause* clause = isSgAdaAttributeClause(parent)) {
11175 ROSE_ASSERT(oldExp == clause->get_size());
11176 clause->set_size(newExp);
11177 } else if (SgAdaRenamingDecl* dcl = isSgAdaRenamingDecl(parent)) {
11178 ROSE_ASSERT(oldExp == dcl->get_renamed());
11179 dcl->set_renamed(newExp);
11180 } else if (SgAdaEntryDecl* dcl = isSgAdaEntryDecl(parent)) {
11181 ROSE_ASSERT(oldExp == dcl->get_entryBarrier());
11182 dcl->set_entryBarrier(newExp);
11183 } else if (SgAdaSelectAlternativeStmt* stm = isSgAdaSelectAlternativeStmt(parent)) {
11184 ROSE_ASSERT(oldExp == stm->get_guard());
11185 stm->set_guard(newExp);
11186 } else if (SgAdaDeltaConstraint* delc = isSgAdaDeltaConstraint(parent)) {
11187 ROSE_ASSERT(oldExp == delc->get_delta());
11188 delc->set_delta(newExp);
11189 } else if (SgAdaDigitsConstraint* digc = isSgAdaDigitsConstraint(parent)) {
11190 ROSE_ASSERT(oldExp == digc->get_digits());
11191 digc->set_digits(newExp);
11192 } else if (SgAdaDiscriminantConstraint* disc = isSgAdaDiscriminantConstraint(parent)) {
11193 replaceExpressionInSgExpressionPtrList(oldExp, newExp, disc->get_discriminants());
11194 } else if (SgAdaRangeConstraint* rngc = isSgAdaRangeConstraint(parent)) {
11195 ROSE_ASSERT(oldExp == rngc->get_range());
11196 rngc->set_range(newExp);
11197 } else if (SgAdaIndexConstraint* idxc = isSgAdaIndexConstraint(parent)) {
11198 replaceExpressionInSgExpressionPtrList(oldExp, newExp, idxc->get_indexRanges());
11199 } else if (SgAdaVariantDecl* vtdcl = isSgAdaVariantDecl(parent)) {
11200 ROSE_ASSERT(oldExp == vtdcl->get_discriminant());
11201 vtdcl->set_discriminant(newExp);
11202 } else if (SgAdaRepresentationClause* clause = isSgAdaRepresentationClause(parent)) {
11203 ROSE_ASSERT(oldExp == clause->get_alignment());
11204 clause->set_alignment(newExp);
11205 } else if (SgAdaVariantWhenStmt* vtwhen = isSgAdaVariantWhenStmt(parent)) {
11206 SgExprListExp* newLst = isSgExprListExp(newExp);
11207 if (newLst && (oldExp == vtwhen->get_choices()))
11208 vtwhen->set_choices(newLst);
11209 else
11210 ROSE_ABORT();
11211 } else if (SgAdaComponentClause* clause = isSgAdaComponentClause(parent)) {
11212 if (oldExp == clause->get_offset())
11213 clause->set_offset(newExp);
11214 else if (oldExp == clause->get_range() && isSgRangeExp(newExp))
11215 clause->set_range(isSgRangeExp(newExp));
11216 else if (oldExp == clause->get_component() && isSgVarRefExp(newExp))
11217 clause->set_component(isSgVarRefExp(newExp));
11218 else
11219 ROSE_ABORT();
11220 } else if (SgAdaFunctionRenamingDecl* rendcl = isSgAdaFunctionRenamingDecl(oldExp->get_parent())) {
11221 if (oldExp == rendcl->get_renamed_function())
11222 rendcl->set_renamed_function(newExp);
11223 else
11224 ROSE_ABORT();
11225 } else {
11226 cerr<<"SageInterface::replaceExpression(). Unhandled parent expression type of SageIII enum value: " <<parent->class_name()<<endl;
11227 ROSE_ABORT();
11228 }
11229
11230 if (!keepOldExp) {
11231 deepDelete(oldExp); // avoid dangling node in memory pool
11232 } else {
11233 oldExp->set_parent(NULL);
11234 }
11235
11236} //replaceExpression()
11237
11239 {
11240 // reuse the implementation in ROSE namespace from src/roseSupport/utility_functions.C
11241 return Rose::getNextStatement(currentStmt);
11242 }
11243
11244SgStatement* SageInterface::getPreviousStatement(SgStatement * currentStmt, bool climbOutScope /*= true*/)
11245 {
11246 return Rose::getPreviousStatement(currentStmt, climbOutScope);
11247 }
11248
11250 return isSgIntVal(e) && isSgIntVal(e)->get_value() == value;
11251 }
11252
11254 {
11255 ROSE_ASSERT(func1&& func2);
11256 bool result = false;
11257 if (func1 == func2)
11258 result = true;
11259 else
11260 {
11262 {
11263 if (func1->get_name() == func2->get_name())
11264 result = true;
11265 }
11266 else if (is_Cxx_language() || is_Java_language())
11267 {
11268 if (func1->get_qualified_name().getString() +
11269 func1->get_mangled_name().getString() ==
11270 func2->get_qualified_name().getString() +
11271 func2->get_mangled_name().getString()
11272 )
11273 result = true;
11274 }
11275 // DQ (9/9/2025): Adding support for Jovial (similar to Fortran).
11276 // else if (is_Fortran_language())
11277 // else if (is_Jovial_language())
11279 {
11280 if (func1->get_name() == func2->get_name())
11281 result = true;
11282 }
11283 else
11284 {
11285 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11286 ROSE_ABORT();
11287 }
11288
11289 } // not identical
11290 return result;
11291 } // isSameFunction()
11292
11295{
11296 bool result =false;
11297 ROSE_ASSERT(stmt != NULL);
11298 SgScopeStatement* p_scope = stmt->get_scope();
11299 ROSE_ASSERT(p_scope != NULL);
11300#if 0
11301 if (p_scope->containsOnlyDeclarations())
11302 {
11303 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11304 if (stmtlist[stmtlist.size()-1] == stmt)
11305 result = true;
11306 }
11307 else
11308 {
11309 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11310 if (stmtlist[stmtlist.size()-1] == stmt)
11311 result = true;
11312 }
11313#endif
11314 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11315 if (stmtlist[stmtlist.size()-1] == stmt)
11316 result = true;
11317
11318 return result;
11319}
11320
11321#ifndef USE_ROSE
11322//-----------------------------------------------
11323// Remove original expression trees from expressions, so you can change
11324// the value and have it unparsed correctly.
11326 struct Visitor: public AstSimpleProcessing {
11327 virtual void visit(SgNode* n) {
11328 SgValueExp* valueExp = isSgValueExp(n);
11329 if (valueExp != NULL) {
11330 valueExp->set_originalExpressionTree(NULL);
11331 }
11332 else {
11333 SgCastExp* cast_exp = isSgCastExp(n);
11334 if (cast_exp != NULL) {
11335 cast_exp->set_originalExpressionTree(NULL);
11336 }
11337 }
11338 }
11339 };
11340 Visitor().traverse(top, preorder);
11341}
11342#endif
11343
11345 while (s && !isSgSwitchStatement(s)) {
11346 s = isSgStatement(s->get_parent());
11347 }
11348 ROSE_ASSERT (s);
11349 return isSgSwitchStatement(s);
11350}
11351
11354 while (s && !isSgOmpClauseBodyStatement(s)) {
11355 s = isSgStatement(s->get_parent());
11356 }
11357 // ROSE_ASSERT (s); // s is allowed to be NULL.
11358 if (s==NULL)
11359 return NULL;
11360 return isSgOmpClauseBodyStatement(s);
11361}
11362
11363
11364SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11365 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11366 for (; s; s = isSgStatement(s->get_parent())) {
11367 SgScopeStatement* sc = isSgScopeStatement(s);
11368 // Need to check for empty label as for java we must detect the
11369 // innermost labeled statement and skip everything in between
11370 switch (s->variantT()) {
11371 case V_SgDoWhileStmt: {
11372 if (label.empty()) {
11373 return sc;
11374 }
11375 break;
11376 }
11377 case V_SgForStatement: {
11378 if (label.empty()) {
11379 return sc;
11380 }
11381 break;
11382 }
11383 case V_SgFortranDo:
11384 case V_SgFortranNonblockedDo: {
11385 if (label.empty() ||
11386 label == isSgFortranDo(sc)->get_string_label()) {
11387 return sc;
11388 }
11389 break;
11390 }
11391 case V_SgWhileStmt: {
11392 if (label.empty() ||
11393 label == isSgWhileStmt(sc)->get_string_label()) {
11394 return sc;
11395 }
11396 break;
11397 }
11398 case V_SgSwitchStatement: {
11399 if (stopOnSwitches) return sc;
11400 break;
11401 }
11402 case V_SgJavaForEachStatement: {
11403 if (label.empty()) {
11404 return sc;
11405 }
11406 break;
11407 }
11408 case V_SgJavaLabelStatement: {
11409 if (label.empty() ||
11410 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11411 return sc;
11412 }
11413 break;
11414 }
11415 default: continue;
11416 }
11417 }
11418 return NULL;
11419}
11420
11421#ifndef USE_ROSE
11423{
11424 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11425 public:
11426 virtual void visit(SgNode* n) {
11427 if (isSgBasicBlock(n)) {
11428 SgBasicBlock* bb = isSgBasicBlock(n);
11429 bool changes = true;
11430 while (changes) {
11431 changes = false;
11432 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11433 i != bb->get_statements().end(); ++i) {
11434 if (isSgGotoStatement(*i)) {
11435 SgGotoStatement* gs = isSgGotoStatement(*i);
11436 SgStatementPtrList::iterator inext = i;
11437 ++inext;
11438 if (inext == bb->get_statements().end())
11439 continue;
11440 if (!isSgLabelStatement(*inext))
11441 continue;
11442 SgLabelStatement* ls = isSgLabelStatement(*inext);
11443 if (gs->get_label() == ls) {
11444 changes = true;
11445 bb->get_statements().erase(i);
11446 break;
11447 }
11448 }
11449 }
11450 }
11451 }
11452 }
11453 };
11454
11455 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11456
11457}
11458#endif
11459
11460// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11462 // assert (LowLevelRewrite::isRemovableStatement(*i));
11463 SgStatement* parent = isSgStatement(stmt->get_parent());
11464 ROSE_ASSERT (parent);
11465 SgBasicBlock* bb = isSgBasicBlock(parent);
11466 SgForInitStatement* fis = isSgForInitStatement(parent);
11467 if (bb || fis) {
11468 ROSE_ASSERT (bb || fis);
11469 SgStatementPtrList& siblings =
11470 (bb ? bb->get_statements() : fis->get_init_stmt());
11471 SgStatementPtrList::iterator j =
11472 std::find(siblings.begin(), siblings.end(), stmt);
11473 ROSE_ASSERT (j != siblings.end());
11474 siblings.erase(j);
11475 // LowLevelRewrite::remove(*i);
11476 } else {
11477 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11478 }
11479}
11480
11481
11482#ifndef USE_ROSE
11483std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11484{
11485 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11486 SgLabelStatementPtrSet& used;
11487 SgLabelStatementPtrSet& all;
11488
11489 public:
11490 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11491 SgLabelStatementPtrSet& all):
11492 used(used), all(all) {}
11493
11494 virtual void visit(SgNode* n) {
11495 if (isSgGotoStatement(n)) {
11496 used.insert(isSgGotoStatement(n)->get_label());
11497 }
11498 if (isSgLabelStatement(n)) {
11499 all.insert(isSgLabelStatement(n));
11500 }
11501 }
11502 };
11503
11504 SgLabelStatementPtrSet used;
11505 SgLabelStatementPtrSet unused;
11506 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11507
11508 for (SgLabelStatementPtrSet::iterator i = used.begin();
11509 i != used.end(); ++i) {
11510 assert (unused.find(*i) != unused.end());
11511 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11512 unused.erase(*i);
11513 }
11514
11515 return unused;
11516}
11517
11518// Remove all unused labels in a section of code.
11519void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11520
11521 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11522
11523 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11524 i != unused.end(); ++i) {
11525
11526 SgLabelStatement* l_stmt = *i;
11527 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11528 if (keepChild)
11529 {
11530 SgStatement* child= l_stmt->get_statement();
11531// l_stmt->set_parent(NULL);
11532 l_stmt->set_statement(NULL);
11533 replaceStatement (l_stmt, child);
11534 }
11535 else
11537 }
11538}
11539#endif
11540
11542 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11543 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11544 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11545
11546 ROSE_ASSERT (!"Bad loop kind");
11547 return NULL;
11548 }
11549
11551 if (isSgWhileStmt(loopStmt)) {
11552 isSgWhileStmt(loopStmt)->set_body(body);
11553 } else if (isSgForStatement(loopStmt)) {
11554 isSgForStatement(loopStmt)->set_loop_body(body);
11555 } else if (isSgDoWhileStmt(loopStmt)) {
11556 isSgDoWhileStmt(loopStmt)->set_body(body);
11557 } else {
11558 ROSE_ASSERT (!"Bad loop kind");
11559 }
11560 body->set_parent(loopStmt);
11561 }
11562
11564 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11565 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11566 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11567
11568 ROSE_ASSERT (!"Bad loop kind");
11569 return NULL;
11570 }
11571
11573 if (isSgWhileStmt(loopStmt)) {
11574 isSgWhileStmt(loopStmt)->set_condition(cond);
11575 } else if (isSgForStatement(loopStmt)) {
11576 isSgForStatement(loopStmt)->set_test(cond);
11577 } else if (isSgDoWhileStmt(loopStmt)) {
11578 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11579 } else {
11580 ROSE_ASSERT (!"Bad loop kind");
11581 }
11582 cond->set_parent(loopStmt);
11583 }
11584
11586// usually useful when compare two expressions to see if they actually refer to the same variable
11587static SgExpression* SkipCasting (SgExpression* exp)
11588{
11589 SgCastExp* cast_exp = isSgCastExp(exp);
11590 if (cast_exp != NULL)
11591 {
11592 SgExpression* operand = cast_exp->get_operand();
11593 assert(operand != 0);
11594 return SkipCasting(operand);
11595 }
11596 else
11597 return exp;
11598}
11599
11602{
11603 ROSE_ASSERT(loop!=NULL);
11604
11605 SgStatementPtrList &init = loop ->get_init_stmt();
11606 if (init.size() !=1) // We only handle one statement case
11607 return false;
11608
11609 SgStatement* init1 = init.front();
11610 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11611 if (decl == NULL) // we only handle for (int i=0; ...)
11612 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11613
11614 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11615 SgInitializedName* ivarname = decl->get_variables().front();
11616 SgExpression* lbast = NULL; // the lower bound, initial state
11617 ROSE_ASSERT(ivarname != NULL);
11618 SgInitializer * initor = ivarname->get_initializer();
11619 if (isSgAssignInitializer(initor))
11620 {
11621 lbast = isSgAssignInitializer(initor)->get_operand();
11622 }
11623 else
11624 { //SgConstructorInitializer etc.
11625 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11626 // they cause a loop to be non-canonical.
11627 return false;
11628 }
11629
11630 // add a new statement like int i; and insert it to the enclosing function
11631 // There are multiple choices about where to insert this statement:
11632 // global scope: max name pollution,
11633 // right before the loop: mess up perfectly nested loops
11634 // So we prepend the statement to the enclosing function's body
11636 ROSE_ASSERT(funcDef!=NULL);
11637 SgBasicBlock* funcBody = funcDef->get_body();
11638 ROSE_ASSERT(funcBody!=NULL);
11639 //TODO a better name
11640 std::ostringstream os;
11641 os<<ivarname->get_name().getString();
11642
11643 // keep the original variable name if possible
11644 SgSymbol * visibleSym = NULL;
11645 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11646 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11647 {
11648 os<<"_nom_";
11649 os<<++gensym_counter;
11650 }
11651
11652 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11653 prependStatement(ndecl, funcBody);
11654 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11655
11656 // replace variable ref to the new symbol
11657 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11658 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11659 {
11660 SgVarRefExp *vRef = isSgVarRefExp((*i));
11661 if (vRef->get_symbol()==osymbol)
11662 vRef->set_symbol(nsymbol);
11663 }
11664 // replace for (int i=0;) with for (i=0;)
11666 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11667 init.push_back(ninit);
11668 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11669 // ninit->set_parent(loop);
11670 ninit->set_parent(loop->get_for_init_stmt ());
11671
11672 // keep record of this normalization
11673 // We may undo it later on.
11674 trans_records.forLoopInitNormalizationTable[loop] = true;
11675 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11676
11677 return true;
11678}
11679
11680/*
11681 int i_norm_1;
11682 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11683Becomes:
11684 for (int i=0; i< upper; i++) ;
11685 * */
11687{
11688 ROSE_ASSERT (loop != NULL);
11689 //If not previously normalized, nothing to do and return false.
11690 if (!trans_records.forLoopInitNormalizationTable[loop])
11691 return false;
11692 // retrieve original and new declaration of the previous normalization
11693 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11694 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11695 ROSE_ASSERT (decl!= NULL);
11696 ROSE_ASSERT (ndecl!= NULL);
11697
11698
11699 // Sanity check
11700 SgStatementPtrList &init = loop ->get_init_stmt();
11701 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11702
11703 // remove the current init_stmt
11704 SgStatement* init1 = init.front();
11705 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11706 ROSE_ASSERT (exp_stmt != NULL);
11707 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11708 ROSE_ASSERT (assign_op != NULL);
11709
11710 // remove the new declaration and the current i_norm=1;
11711 removeStatement(ndecl);
11712 removeStatement (exp_stmt);
11713
11714 // restore the original declaration
11715 init.push_back(decl);
11716 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11717 // ninit->set_parent(loop);
11718 decl->set_parent(loop->get_for_init_stmt ());
11719
11720 // replace variable references
11721 // current symbol in the AST
11722 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11723 // new symbol we want to have: the original decl
11724 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11725 // replace variable ref to the new symbol
11726 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11727 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11728 {
11729 SgVarRefExp *vRef = isSgVarRefExp((*i));
11730 if (vRef->get_symbol()==osymbol)
11731 vRef->set_symbol(nsymbol);
11732 }
11733
11734 // clear record: now the loop is not normalized any more
11735 trans_records.forLoopInitNormalizationTable[loop] = false;
11736 return true;
11737}
11738
11740{
11741 ROSE_ASSERT(loop != NULL);
11742
11743 // Normalized the test expressions
11744 // -------------------------------------
11745#if 0 // this is undecided
11746 // skip for (;;) case
11747 SgStatement* test_stmt = loop->get_test();
11748 if (test_stmt!=NULL)
11749 {
11750 if (isSgNullStatement(test_stmt))
11751 return false;
11752 }
11753#endif
11754 SgExpression* test = loop->get_test_expr();
11755 SgExpression* testlhs=NULL, * testrhs=NULL;
11756 if (isSgBinaryOp(test))
11757 {
11758 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11759 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11760 ROSE_ASSERT(testlhs && testrhs);
11761 }
11762 else
11763 return false;
11764 // keep the variable since test will be removed later on
11765 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11766 if (testlhs_var == NULL )
11767 return false;
11768 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11769 if (var_symbol==NULL)
11770 return false;
11771
11772 switch (test->variantT()) {
11773 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11775 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11776 // deepDelete(test);// replaceExpression() does this already by default.
11777 break;
11778 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11780 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11781 break;
11782 case V_SgLessOrEqualOp:
11783 case V_SgGreaterOrEqualOp:
11784 case V_SgNotEqualOp: //TODO Do we want to allow this?
11785 break;
11786 default:
11787 return false;
11788 }
11789 return true;
11790}
11792{
11793 ROSE_ASSERT(loop != NULL);
11794
11795 SgExpression* test = loop->get_test_expr();
11796 SgExpression* testlhs=NULL, * testrhs=NULL;
11797 if (isSgBinaryOp(test))
11798 {
11799 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11800 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11801 ROSE_ASSERT(testlhs && testrhs);
11802 }
11803 else
11804 return false;
11805 // keep the variable since test will be removed later on
11806 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11807 if (testlhs_var == NULL )
11808 return false;
11809 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11810 if (var_symbol==NULL)
11811 return false;
11812
11813
11814 // -------------------------------------
11815 SgExpression* incr = loop->get_increment();
11816 ROSE_ASSERT(incr != NULL);
11817 switch (incr->variantT()) {
11818 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11819 {
11820 // check if the variables match
11821 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11822 if (incr_var == NULL) return false;
11823 if ( incr_var->get_symbol() != var_symbol)
11824 return false;
11825 replaceExpression(incr,
11826 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11827 break;
11828 }
11829 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11830 {
11831 // check if the variables match
11832 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11833 if (incr_var == NULL) return false;
11834 if ( incr_var->get_symbol() != var_symbol)
11835 return false;
11836 replaceExpression(incr,
11837 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11838 break;
11839 }
11840 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11841 {
11842 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11843 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11844 ROSE_ASSERT (rhs != NULL);
11845 if (incr_var == NULL) return false;
11846 if ( incr_var->get_symbol() != var_symbol)
11847 return false;
11848 replaceExpression(incr,
11849 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11850 break;
11851 }
11852 case V_SgAssignOp:
11853 case V_SgPlusAssignOp:
11854 break;
11855 default:
11856 return false;
11857 }
11858
11859 return true;
11860}
11861
11862/*
11863The AST of switch-case statement
11864
11865AST using EDG 6.x
11866
11867|___ *[0] ->@0x7f8d973f0010 SgSwitchStatement switch-case.C 4:3
11868 |--- p_item_selector ->@0x7f8d9738e010 SgExprStatement switch-case.C 4:10
11869 | |___ p_expression ->@0x7f8d973bd010 SgVarRefExp switch-case.C 4:10 init name@0x7f8d97757130 symbol name="a"
11870 |___ p_body ->@0x7f8d97522168 SgBasicBlock switch-case.C 5:3
11871 |--- *[0] ->@0x7f8d97343010 SgCaseOptionStmt switch-case.C 6:10
11872 | |___ p_key ->@0x7f8d98d4c090 SgIntVal switch-case.C 6:10 value=1 valueString=
11873 |--- *[1] ->@0x7f8d975222c0 SgBasicBlock switch-case.C 7:7
11874 | |--- *[0] ->@0x7f8d9738e070 SgExprStatement switch-case.C 7:8
11875 | | |___ p_expression ->@0x7f8da76c2010 SgNullExpression compilerGenerated 0:0
11876 | |___ *[1] ->@0x7f8d97308010 SgBreakStmt switch-case.C 8:9
11877 |--- *[2] ->@0x7f8d972c5010 SgDefaultOptionStmt switch-case.C 10:4
11878 |___ *[3] ->@0x7f8d97522418 SgBasicBlock switch-case.C 11:7
11879 |___ *[0] ->@0x7f8d9738e0d0 SgExprStatement switch-case.C 11:8
11880 |___ p_expression ->@0x7f8da76c2060 SgNullExpression compilerGenerated 0:0
11881
11882AST using EDG 5.x
11883└──@0x7fd34c734010 SgSwitchStatement switch-case.cpp 4:3
11884 ├──@0x7fd34c6d2010 SgExprStatement switch-case.cpp 4:10
11885 │ └──@0x7fd34c701010 SgVarRefExp switch-case.cpp 4:10
11886 └──@0x7fd34c866168 SgBasicBlock switch-case.cpp 5:3
11887 ├──@0x7fd34c5b2010 SgCaseOptionStmt switch-case.cpp 6:10
11888 │ ├──@0x7fd34c5fd010 SgCastExp compilerGenerated 0:0
11889 │ │ └──@0x7fd34c63c010 SgBoolValExp switch-case.cpp 6:10
11890 │ ├──@0x7fd34c8662c0 SgBasicBlock switch-case.cpp 7:7
11891 │ │ └──@0x7fd34c6d2070 SgExprStatement switch-case.cpp 7:8
11892 │ │ └──@0x7fd34c6aa010 SgNullExpression compilerGenerated 0:0
11893 │ └── NULL
11894 ├──@0x7fd34c5b20a8 SgCaseOptionStmt switch-case.cpp 9:10
11895 │ ├──@0x7fd34c5fd090 SgCastExp compilerGenerated 0:0
11896 │ │ └──@0x7fd34c63c070 SgBoolValExp switch-case.cpp 9:10
11897 │ ├──@0x7fd34c866418 SgBasicBlock switch-case.cpp 10:7
11898 │ │ └──@0x7fd34c6d20d0 SgExprStatement switch-case.cpp 10:8
11899 │ │ └──@0x7fd34c6aa060 SgNullExpression compilerGenerated 0:0
11900 │ └── NULL
11901 └──@0x7fd34c56f010 SgDefaultOptionStmt switch-case.cpp 12:5
11902 └──@0x7fd34c866570 SgBasicBlock switch-case.cpp 13:7
11903 └──@0x7fd34c6d2130 SgExprStatement switch-case.cpp 13:8
11904 └──@0x7fd34c6aa0b0 SgNullExpression compilerGenerated 0:0
11905
11906*/
11908 bool changed = false;
11909 // Only act on switch statements
11910 if (!switchStmt) return changed;
11911
11912 // The body of the switch should be a basic block
11913 SgBasicBlock* bodyBlock = isSgBasicBlock(switchStmt->get_body());
11914 if (!bodyBlock) return changed;
11915
11916 // Copy the list of statements to allow modification
11917 SgStatementPtrList& stmtList = bodyBlock->get_statements();
11918 std::vector<SgStatement*> stmts(stmtList.begin(), stmtList.end());
11919 int n = static_cast<int>(stmts.size());
11920
11921 // Walk through statements, detecting case/default labels
11922 // Note that this for loop does not have i++!
11923 for (int i = 0; i < n; ) {
11924 SgStatement* curr = stmts[i];
11925 // We expect curr is either SgCaseOptionStmt or SgDefaultOptionStmt at this point
11926 //
11927 // Helper lambda to handle a label statement of either SgCaseOptionStmt or SgDefaultOptionStmt
11928 auto processLabel = [&](SgStatement* labelStmt) {
11929
11930 // set j to next statement after the label statmt
11931 int j = i + 1;
11932 std::vector<SgStatement*> toWrap;
11933 // Collect statements until next case/default or end
11934 while (j < n && !isSgCaseOptionStmt(stmts[j]) && !isSgDefaultOptionStmt(stmts[j])) {
11935 toWrap.push_back(stmts[j]);
11936 ++j;
11937 }
11938
11939 // now the current statement is isSgCaseOptionStmt or isSgDefaultOptionStmt
11940 // Single-block case: if we collected exactly one basic-block and label has no body, just move it
11941 // I think the AST is constructed improperly
11942 if (toWrap.size() == 1
11943 && isSgBasicBlock(toWrap[0])
11944 && ((isSgCaseOptionStmt(labelStmt) && !isSgBasicBlock(isSgCaseOptionStmt(labelStmt)->get_body()))
11945 || (isSgDefaultOptionStmt(labelStmt) && !isSgBasicBlock(isSgDefaultOptionStmt(labelStmt)->get_body()))))
11946 {
11947#if 0
11948 //it seems like the body pointer is no longer used within the connection with EDG 6.x!!
11949 SgBasicBlock* moved = static_cast<SgBasicBlock*>(toWrap[0]);
11950 removeStatement (moved);
11951 if (auto c = isSgCaseOptionStmt(labelStmt)) {
11952 c->set_body(moved);
11953 } else if (auto d = isSgDefaultOptionStmt(labelStmt)) {
11954 d->set_body(moved);
11955 }
11956 moved->set_parent(labelStmt);
11957#endif
11958 // no further wrapping or removal needed
11959 }
11960 else if (!toWrap.empty()) {
11961 // Build a new block around statements
11962 // NOTE: wrong code: buildBasicBlock_nfi() version was calleda
11963 // It does support vector of stmts.
11964 // But we want to avoid the use of _nfi() version no file info (nfi)
11965 // to avoid set file info. manually.
11966 SgBasicBlock* newBlock = buildBasicBlock();
11967 insertStatementAfter(labelStmt, newBlock);
11968 // Insert block after label
11969#if 0
11970 //it seems like the body pointer is no longer used within the connection with EDG 6.x!!
11971 // NOTE: becomes its body
11972 newBlock->set_parent(labelStmt);
11973
11974 // Attach block as body of the label
11975 if (auto caseLabel = isSgCaseOptionStmt(labelStmt)) {
11976 caseLabel->set_body(newBlock);
11977 } else if (auto defaultLabel = isSgDefaultOptionStmt(labelStmt)) {
11978 defaultLabel->set_body(newBlock);
11979 }
11980#endif
11981 // Remove original flat statements
11982 for (auto* w: toWrap) {
11983 {
11984 // we must first remove it from original location, then append it to new location
11985 removeStatement(w);
11986 appendStatement(w, newBlock);
11987 }
11988 }
11989 changed = true;
11990 }
11991 return j; // next index to process
11992 };
11993
11994 // adjust i
11995 if (auto caseLabel = isSgCaseOptionStmt(curr)) {
11996 i = processLabel(caseLabel);
11997 } else if (auto defaultLabel = isSgDefaultOptionStmt(curr)) {
11998 i = processLabel(defaultLabel);
11999 } else {
12000 ++i;
12001 }
12002 }
12003
12004 return changed;
12005}
12006
12008// Her loop translation does not pass AST consistency tests so we rewrite some of them here
12009// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
12010bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
12011{
12012 ROSE_ASSERT(loop != NULL);
12013 // Normalize initialization statement of the for loop
12014 // -------------------------------------
12015 // for (int i=0;... ) becomes int i; for (i=0;..)
12016 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
12018 return false;
12019
12020 // Normalized the test expressions
12021 if (!normalizeForLoopTest(loop))
12022 return false;
12023
12024 // Normalize the increment expression
12025 if (!normalizeForLoopIncrement(loop))
12026 return false;
12027
12028 // Normalize the loop body: ensure there is a basic block
12030 ROSE_ASSERT(body!=NULL);
12031 // Liao, 9/22/2009
12032 // folding entire loop may cause decreased accuracy for floating point operations
12033 // we only want to fold the loop controlling expressions
12034 if (foldConstant)
12035 {
12036 //constantFolding(loop->get_parent());
12037 constantFolding(loop->get_test());
12038 constantFolding(loop->get_increment());
12039 }
12040
12041 return true;
12042}
12043
12046{
12047 // TODO, normalize continue to enddo ?
12048 ROSE_ASSERT (loop != NULL);
12049 SgExpression* e_3 = loop->get_increment();
12050 if (isSgNullExpression(e_3))
12051 {
12052 SgIntVal* iv = buildIntVal(1);
12053 loop->set_increment(iv);
12054 iv->set_parent(loop);
12055 delete (e_3);
12056 }
12057 return true;
12058}
12059
12060#if 0
12061bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
12062{
12063 // normalize the loop first
12064 if (!forLoopNormalization(loop))
12065 return false; // input loop cannot be normalized to a canonical form
12066 // prepare Loop transformation environment
12068 ROSE_ASSERT(func!=NULL);
12069 AstInterfaceImpl faImpl(func->get_definition()->get_body());
12070 AstInterface fa(&faImpl);
12071 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
12072 ArrayInterface array_interface (*annot);
12073 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
12074 array_interface.observe(fa);
12075 LoopTransformInterface :: set_astInterface(fa);
12076 LoopTransformInterface :: set_arrayInterface(&array_interface);
12077
12078 // invoke the unrolling defined in Qing's code
12079 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
12080 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
12081
12082 LoopUnrolling lu(unrolling_factor);
12083 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
12084 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
12085 result = lu(lpTrans, result);
12086 return true;
12087}
12088#else
12089
12090// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12091/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12092 * Handle stride (step) >1
12093 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12094 *
12095 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12096 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12097 * fringe ==0 if no leftover iterations
12098 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12099 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12100 * loop body: copy body n times from 0 to factor -1
12101 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12102 * fringe loop: the same as the original loop, except for no init statement
12103 *
12104 * e.g:
12105 * // unrolling 3 times for the following loop with stride !=1
12106 * for (i=0; i<=9; i+=3)
12107 * {
12108 * a[i]=i;
12109 * }
12110 * // it becomes
12111 * // iteration count = 10%3=1 -> 10/3+1 = 4
12112 * // fringe = 4%3 =1 --> 3*3
12113 * // ub-fringe = 9-3*3
12114 * for (i=0; i<=9-3*3; i+=3*3)
12115 * {
12116 * a[i+3*0]=i;
12117 * a[i+3*1]=i;
12118 * a[i+3*2]=i;
12119 * }
12120 * // i=9 is the leftover iteration
12121 * for (; i<=9; i+=3)
12122 * {
12123 * a[i]=i;
12124 * }
12125 *
12126 */
12127bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12128{
12129#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12130 //Handle 0 and 1, which means no unrolling at all
12131 if (unrolling_factor <= 1)
12132 return true;
12133
12134 // normalize the target loop first
12135
12136 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12137 if (!forLoopNormalization(target_loop))
12138 {
12139 // the return value is not reliable
12140 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12141 // dumpInfo(target_loop);
12142 // return false;
12143 }
12144 // grab the target loop's essential header information
12145 SgInitializedName* ivar = NULL;
12146 SgExpression* lb = NULL;
12147 SgExpression* ub = NULL;
12148 SgExpression* step = NULL;
12149 SgStatement* orig_body = NULL;
12150 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12151 {
12152 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12153 dumpInfo(target_loop);
12154 return false;
12155 }
12156 ROSE_ASSERT(ivar&& lb && ub && step);
12157 ROSE_ASSERT(isSgBasicBlock(orig_body));
12158
12159 // generate the fringe loop
12160 bool needFringe = true;
12161 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12162 insertStatementAfter(target_loop,fringe_loop);
12163 removeStatement(fringe_loop->get_for_init_stmt());
12164 fringe_loop->set_for_init_stmt(NULL);
12165
12166 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12168 copyExpression(lb));
12169 raw_range_exp->set_need_paren(true);
12170 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12171 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12172
12173 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12174 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12175 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12176 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12177
12178 SgScopeStatement* scope = target_loop->get_scope();
12179 ROSE_ASSERT(scope != NULL);
12180 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12181 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12182 insertStatementBefore(target_loop, fringe_decl);
12183 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12184 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12185
12186 // compile-time evaluate to see if index is a constant of value 0
12187 // if so, the iteration count can be divided even by the unrolling factor
12188 // and no fringe loop is needed
12189 // WE have to fold on its parent node to get a possible constant since
12190 // constant folding only folds children nodes, not the current node to a constant
12191 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12192 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12193 ROSE_ASSERT(ivarname != NULL);
12194 // points to a new address if constant folding happens
12195 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12196 if (init1)
12197 if (isSgIntVal(init1->get_operand_i()))
12198 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12199 needFringe = false;
12200
12201 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12202 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12203 ROSE_ASSERT(ub_bin_op);
12204 if (needFringe)
12205 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12206 else
12207 {
12208 ub_bin_op->set_rhs_operand(copyExpression(ub));
12209 removeStatement(fringe_decl);
12210 }
12211
12212 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12213 ROSE_ASSERT(step_bin_op != NULL);
12214 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12215
12216 bool isPlus = false;
12217 if (isSgPlusAssignOp(step_bin_op))
12218 isPlus = true;
12219 else if (isSgMinusAssignOp(step_bin_op))
12220 isPlus = false;
12221 else
12222 {
12223 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12224 dumpInfo(step_bin_op);
12225 ROSE_ABORT();
12226 }
12227
12228 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12229 for (size_t i =1; i<unrolling_factor; i++)
12230 {
12231 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12232 ROSE_ASSERT(body);
12233 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12234 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12235 {
12236 SgVarRefExp* refexp = *iter;
12237 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12238 {
12239 // replace reference to ivar with ivar +/- step*i
12240 SgExpression* new_exp = NULL;
12241 //build replacement expression for every appearance
12242 if (isPlus) //ivar +/- step * i
12243 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12244 else
12246
12247 // replace it with the right one
12248 replaceExpression(refexp, new_exp);
12249 }
12250 }
12251 // copy body to loop body, this should be a better choice
12252 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12253 appendStatement(body,isSgBasicBlock(orig_body));
12254 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12255 }
12256
12257 // remove the fringe loop if not needed finally
12258 // it is used to buffering the original loop body before in either cases
12259 if (!needFringe)
12260 removeStatement(fringe_loop);
12261
12262 // constant folding for the transformed AST
12263 ConstantFolding::constantFoldingOptimization(scope,false);
12264 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12265
12266#endif
12267
12268 return true;
12269}
12270#endif
12271
12272// Liao, 6/15/2009
12275static size_t myfactorial (size_t n)
12276{
12277 size_t result=1;
12278 for (size_t i=2; i<=n; i++)
12279 result*=i;
12280 return result;
12281}
12282
12283#endif
12284
12285#ifndef USE_ROSE
12286
12289std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12290{
12291 size_t k = lexicoOrder;
12292 std::vector<size_t> s(n);
12293 // initialize the permutation vector
12294 for (size_t i=0; i<n; i++)
12295 s[i]=i;
12296
12297 //compute (n- 1)!
12298 size_t factorial = myfactorial(n-1);
12299 //check if the number is not in the range of [0, n! - 1]
12300 if (k/n>=factorial)
12301 {
12302 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12303 ROSE_ABORT();
12304 }
12305 // Algorithm:
12306 //check each element of the array, excluding the right most one.
12307 //the goal is to find the right element for each s[j] from 0 to n-2
12308 // method: each position is associated a factorial number
12309 // s[0] -> (n-1)!
12310 // s[1] -> (n-2)! ...
12311 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12312 // so only big enough k can have non-zero value after division
12313 // 0 value means no change to the position for the current iteration
12314 // The non-zero value is further modular by the number of the right hand elements of the current element.
12315 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12316 // choose one of them to be moved to the current position,
12317 // shift elements between the current and the moved element to the right direction for one position
12318 for (size_t j=0; j<n-1; j++)
12319 {
12320 //calculates the next cell from the cells left
12321 //(the cells in the range [j, s.length - 1])
12322 int tempj = (k/factorial) % (n - j);
12323 //Temporarily saves the value of the cell needed
12324 // to add to the permutation this time
12325 int temps = s[j+tempj];
12326 //shift all elements to "cover" the "missing" cell
12327 //shift them to the right
12328 for (size_t i=j+tempj; i>j; i--)
12329 {
12330 s[i] = s[i-1]; //shift the chain right
12331 }
12332 // put the chosen cell in the correct spot
12333 s[j]= temps;
12334 // updates the factorial
12335 factorial = factorial /(n-(j+1));
12336 }
12337#if 0
12338 for (size_t i = 0; i<n; i++)
12339 cout<<" "<<s[i];
12340 cout<<endl;
12341#endif
12342 return s;
12343}
12344
12346/* Translation
12347 Before:
12348 for (i = 0; i < 100; i++)
12349 for (j = 0; j < 100; j++)
12350 for (k = 0; k < 100; k++)
12351 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12352
12353 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12354
12355// added a new controlling loop at the outer most level
12356 int _lt_var_k;
12357 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12358 for (i = 0; i < 100; i++)
12359 for (j = 0; j < 100; j++)
12360 // rewritten loop header , normalized also
12361 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12362 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12363 }
12364 }
12365// finally run constant folding
12366
12367 */
12368bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12369{
12370 ROSE_ASSERT(loopNest != NULL);
12371 ROSE_ASSERT(targetLevel >0);
12372 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12373 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12374 // 1 (no need to tile)
12375 if (tileSize<=1)
12376 return true;
12377 // Locate the target loop at level n
12378 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12379 ROSE_ASSERT(loops.size()>=targetLevel);
12380 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12381
12382 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12383 // normalize the target loop first
12384 if (!forLoopNormalization(target_loop))
12385 {// the return value is not reliable
12386// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12387// dumpInfo(target_loop);
12388// return false;
12389 }
12390 // grab the target loop's essential header information
12391 SgInitializedName* ivar = NULL;
12392 SgExpression* lb = NULL;
12393 SgExpression* ub = NULL;
12394 SgExpression* step = NULL;
12395 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12396 {
12397 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12398 dumpInfo(target_loop);
12399 return false;
12400 }
12401 ROSE_ASSERT(ivar&& lb && ub && step);
12402
12403 // Add a controlling loop around the top loop nest
12404 // Ensure the parent can hold more than one children
12405 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12406 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12407 parent = makeSingleStatementBodyToBlock (loopNest);
12408 else
12409 parent = isSgLocatedNode(loopNest ->get_parent());
12410
12411 ROSE_ASSERT(parent!= NULL);
12412 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12413 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12414 SgScopeStatement* scope = loopNest->get_scope();
12416 (ivar2_name, buildIntType(),NULL, scope);
12417 insertStatementBefore(loopNest, loop_index_decl);
12418 // init statement of the loop header, copy the lower bound
12419 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12420 //two cases <= or >= for a normalized loop
12421 SgExprStatement* cond_stmt = NULL;
12422 SgExpression* orig_test = target_loop->get_test_expr();
12423 if (isSgBinaryOp(orig_test))
12424 {
12425 if (isSgLessOrEqualOp(orig_test))
12426 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12427 else if (isSgGreaterOrEqualOp(orig_test))
12428 {
12429 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12430 }
12431 else
12432 {
12433 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12434 dumpInfo(orig_test);
12435 ROSE_ABORT();
12436 }
12437 }
12438 else
12439 {
12440 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12441 dumpInfo(orig_test);
12442 ROSE_ABORT();
12443 }
12444 ROSE_ASSERT(cond_stmt != NULL);
12445
12446 // build loop incremental I
12447 // expression var+=up*tilesize or var-=upper * tilesize
12448 SgExpression* incr_exp = NULL;
12449 SgExpression* orig_incr_exp = target_loop->get_increment();
12450 if( isSgPlusAssignOp(orig_incr_exp))
12451 {
12452 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12453 }
12454 else if (isSgMinusAssignOp(orig_incr_exp))
12455 {
12456 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12457 }
12458 else
12459 {
12460 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12461 dumpInfo(orig_incr_exp);
12462 ROSE_ABORT();
12463 }
12464 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12465 insertStatementBefore(loopNest, control_loop);
12466 // move loopNest into the control loop
12467 removeStatement(loopNest);
12468 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12469
12470 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12471 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12472 ROSE_ASSERT(assign_op);
12473 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12474 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12475 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12476 ROSE_ASSERT(bin_op);
12477 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12478 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12479 test_exp->set_need_paren(true);
12480 ub->set_need_paren(true);
12481 ub2->set_need_paren(true);
12482 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12483 bin_op->set_rhs_operand(triple_exp);
12484 // constant folding
12485 // folding entire loop may decrease the accuracy of floating point calculation
12486 // we fold loop control expressions only
12487 //constantFolding(control_loop->get_scope());
12488 constantFolding(control_loop->get_test());
12489 constantFolding(control_loop->get_increment());
12490 return true;
12491}
12492
12494bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12495{
12496 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12497 return true;
12498 // parameter verification
12499 ROSE_ASSERT(loop != NULL);
12500 //must have at least two levels
12501 ROSE_ASSERT (depth >1);
12502 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12503 //TODO need to verify the input loop has n perfectly-nested children loops inside
12504 // save the loop nest's headers: init, test, and increment
12505 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12506 ROSE_ASSERT(loopNest.size()>=depth);
12507 std::vector<std::vector<SgNode*> > loopHeads;
12508 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12509 {
12510 SgForStatement* cur_loop = *i;
12511 std::vector<SgNode*> head;
12512 head.push_back(cur_loop->get_for_init_stmt());
12513 head.push_back(cur_loop->get_test());
12514 head.push_back(cur_loop->get_increment());
12515 loopHeads.push_back(head);
12516 }
12517
12518 // convert the lexicographical number to a permutation order array permutation[depth]
12519 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12520 // rewrite the loop nest to reflect the permutation
12521 // set the header to the new header based on the permutation array
12522 for (size_t i=0; i<depth; i++)
12523 {
12524 // only rewrite if necessary
12525 if (i != changedOrder[i])
12526 {
12527 SgForStatement* cur_loop = loopNest[i];
12528 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12529
12530 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12531 //ROSE_ASSERT(init != NULL) // could be NULL?
12532 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12533 cur_loop->set_for_init_stmt(init);
12534 if (init)
12535 {
12536 init->set_parent(cur_loop);
12538 }
12539
12540 SgStatement* test = isSgStatement(newhead[1]);
12541 cur_loop->set_test(test);
12542 if (test)
12543 {
12544 test->set_parent(cur_loop);
12546 }
12547
12548 SgExpression* incr = isSgExpression(newhead[2]);
12549 cur_loop->set_increment(incr);
12550 if (incr)
12551 {
12552 incr->set_parent(cur_loop);
12554 }
12555 }
12556 }
12557 return true;
12558}
12559
12562{
12563 ROSE_ASSERT(loop != NULL);
12564 SgInitializedName* ivarname=NULL;
12565
12566 // Fortran case ------------------
12567 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12568 {
12569 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12570 ROSE_ASSERT (assign_op != NULL);
12571 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12572 ROSE_ASSERT (var != NULL);
12573 ivarname = var->get_symbol()->get_declaration();
12574 ROSE_ASSERT (ivarname != NULL);
12575 return ivarname;
12576 }
12577 // C/C++ case ------------------------------
12578 SgForStatement* fs = isSgForStatement(loop);
12579 if (fs == NULL)
12580 {
12581 return NULL;
12582 }
12583 // we only handle C/C++ for loops and Fortran Do loops.
12584 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12585 // ROSE_ASSERT (fs != NULL);
12586
12587 //Check initialization statement is something like i=xx;
12588 SgStatementPtrList & init = fs->get_init_stmt();
12589 if (init.size() !=1)
12590 {
12591 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12592 //ROSE_ASSERT(false);
12593 return NULL;
12594 }
12595 SgStatement* init1 = init.front();
12596 SgExpression* ivarast=NULL;
12597
12598 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12599 //bool isCase1=false, isCase2=false;
12600
12601 //consider C99 style: for (int i=0;...)
12602 if (isSgVariableDeclaration(init1))
12603 {
12604 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12605 ivarname = decl->get_variables().front();
12606 ROSE_ASSERT(ivarname != NULL);
12607 //SgInitializer * initor = ivarname->get_initializer();
12608 // if (isSgAssignInitializer(initor))
12609 // isCase1 = true;
12610 }// other regular case: for (i=0;..)
12611 else if (isAssignmentStatement(init1, &ivarast))
12612 {
12613 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12614 if (var)
12615 {
12616 ivarname = var->get_symbol()->get_declaration();
12617 //isCase2 = true;
12618 }
12619 }
12620 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12621 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12622 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12623 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12624 {
12625 SgCommaOpExp* leaf_exp = comma_exp;
12626 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12627 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12628 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12629 {
12630 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12631 if (var)
12632 {
12633 ivarname = var->get_symbol()->get_declaration();
12634 }
12635 }
12636 }
12637 }
12638 else
12639 {
12640
12641 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12642 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12643 init1->get_file_info()->display("Debug");
12644
12645 return NULL;
12646 //ROSE_ASSERT (false);
12647 }
12648 // Cannot be both true
12649 // ROSE_ASSERT(!(isCase1&&isCase2));
12650
12651 //Check loop index's type
12652 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12653 return ivarname;
12654}
12655
12659{
12660 ROSE_ASSERT (ivar != NULL);
12661 ROSE_ASSERT (subtree_root != NULL);
12662 bool result = false;
12663 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12664 while (cur_loop)
12665 {
12666 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12667 if (i_index == ivar)
12668 {
12669 result = true;
12670 break;
12671 }
12672 else
12673 { // findEnclosingLoop() is inclusive.
12674 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12675 }
12676 }
12677 return result;
12678}
12679
12681
12686{
12687 ROSE_ASSERT (loop !=NULL);
12688 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12689 if (stmt_list.size() >1) return true; // two var decl statements
12690 if (stmt_list.size() == 0) return false;
12691
12692// generateDOTforMultipleFile(*getProject());
12693 //single variable declaration statement, like int i;
12694 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12695 if (decl_stmt != NULL)
12696 return false;
12697
12698 // single statement, but with comma expression (i=0, j=0)
12699 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12700 ROSE_ASSERT (exp_stmt != NULL);
12701 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12702 {
12703 return true;
12704 }
12705
12706 return false;
12707}
12709bool SageInterface::isCanonicalDoLoop(SgFortranDo* loop,SgInitializedName** ivar/*=NULL*/, SgExpression** lb/*=NULL*/, SgExpression** ub/*=NULL*/, SgExpression** step/*=NULL*/, SgStatement** body/*=NULL*/, bool *hasIncrementalIterationSpace/*= NULL*/, bool* isInclusiveUpperBound/*=NULL*/)
12710{
12711 ROSE_ASSERT(loop != NULL);
12712 SgFortranDo* fs = isSgFortranDo(loop);
12713 if (fs == NULL)
12714 return false;
12715 // 1. Check initialization statement is something like i=xx;
12716 SgExpression * init = fs->get_initialization();
12717 if (init == NULL)
12718 return false;
12719 SgAssignOp* init_assign = isSgAssignOp (init);
12720 SgExpression *lbast=NULL, *ubast=NULL;
12721 // SgExpression* ivarast=NULL, *stepast=NULL;
12722 SgInitializedName* ivarname=NULL;
12723
12724 bool isCase1=false;
12725 if (init_assign)
12726 {
12727 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12728 if (var)
12729 ivarname = var->get_symbol()->get_declaration();
12730 lbast = init_assign->get_rhs_operand();
12731 if (ivarname && lbast )
12732 isCase1 = true;
12733 }
12734 // if not i=1
12735 if (!isCase1)
12736 return false;
12737
12738 //Check loop index's type
12739 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12740 return false;
12741#if 0
12742 //2. Check test expression i [<=, >=, <, > ,!=] bound
12743 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12744 if (test == NULL)
12745 return false;
12746 switch (test->variantT()) {
12747 case V_SgLessOrEqualOp:
12748 if (isInclusiveUpperBound != NULL)
12749 *isInclusiveUpperBound = true;
12750 if (hasIncrementalIterationSpace != NULL)
12751 *hasIncrementalIterationSpace = true;
12752 break;
12753 case V_SgLessThanOp:
12754 if (isInclusiveUpperBound != NULL)
12755 *isInclusiveUpperBound = false;
12756 if (hasIncrementalIterationSpace != NULL)
12757 *hasIncrementalIterationSpace = true;
12758 break;
12759 case V_SgGreaterOrEqualOp:
12760 if (isInclusiveUpperBound != NULL)
12761 *isInclusiveUpperBound = true;
12762 if (hasIncrementalIterationSpace != NULL)
12763 *hasIncrementalIterationSpace = false;
12764 break;
12765 case V_SgGreaterThanOp:
12766 if (isInclusiveUpperBound != NULL)
12767 *isInclusiveUpperBound = false;
12768 if (hasIncrementalIterationSpace != NULL)
12769 *hasIncrementalIterationSpace = false;
12770 break;
12771// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12772 break;
12773 default:
12774 return false;
12775 }
12776 // check the tested variable is the same as the loop index
12777 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12778 if (testvar == NULL)
12779 return false;
12780 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12781 return false;
12782#endif
12783 //grab the upper bound
12784 ubast = loop->get_bound();
12785 // Fortran Do loops always have inclusive upper bound
12786 if (isInclusiveUpperBound != NULL)
12787 *isInclusiveUpperBound = true;
12788 //3. Check the increment expression
12789 SgExpression* incr = fs->get_increment();
12790 ROSE_ASSERT (incr != NULL);
12791 if (isSgNullExpression(incr))
12792 {
12793 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12794 ROSE_ASSERT (false);
12795 }
12796 if (hasIncrementalIterationSpace != NULL)
12797 {
12798 *hasIncrementalIterationSpace = true;
12799 // We can only tell a few cases
12800 if (SgIntVal* i_v = isSgIntVal(incr))
12801 {
12802 if (i_v->get_value()<0)
12803 *hasIncrementalIterationSpace = false;
12804 }
12805 }
12806#if 0
12807 SgVarRefExp* incr_var = NULL;
12808 switch (incr->variantT()) {
12809 case V_SgPlusAssignOp: //+=
12810 case V_SgMinusAssignOp://-=
12811 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12812 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12813 break;
12814 case V_SgPlusPlusOp: //++
12815 case V_SgMinusMinusOp: //--
12816 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12817 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12818 break;
12819 default:
12820 return false;
12821 }
12822 if (incr_var == NULL)
12823 return false;
12824 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12825 return false;
12826#endif
12827 // return loop information if requested
12828 if (ivar != NULL)
12829 *ivar = ivarname;
12830 if (lb != NULL)
12831 *lb = lbast;
12832 if (ub != NULL)
12833 *ub = ubast;
12834 if (step != NULL)
12835 *step = incr;
12836 if (body != NULL) {
12837 *body = fs->get_body();
12838 }
12839 return true;
12840}
12841//TODO: expose it to the namespace once it matures.
12843// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12844/*
12845From OpenMP 4.5 Specification
12846
128471.2.2 OpenMP Language Terminology
12848
12849For C/C++, an executable statement, possibly compound, with a single entry at the
12850top and a single exit at the bottom, or an OpenMP construct.
12851
12852For Fortran, a block of executable statements with a single entry at the top and a
12853single exit at the bottom, or an OpenMP construct.
12854
12855COMMENTS:
12856
12857For all base languages:
12858* Access to the structured block must not be the result of a branch; and
12859* The point of exit cannot be a branch out of the structured block.
12860
12861 For C/C++:
12862* The point of entry must not be a call to setjmp();
12863* longjmp() and throw() must not violate the entry/exit criteria;
12864* Calls to exit() are allowed in a structured block; and
12865* An expression statement, iteration statement, selection statement, or try block is considered to be a structured block if the corresponding compound statement obtained by enclosing it in { and } would be a structured block.
12866
12867For Fortran:
12868* STOP statements are allowed in a structured block.
12869
12870*/
12871bool isStructuredBlock(SgStatement* s)
12872{
12873 bool rt = true;
12874 ROSE_ASSERT (s != NULL);
12875
12876 // contain break;
12877 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12878 if (bset.size()!=0 )
12879 rt = false;
12880 //TODO: contain goto statement, jumping to outside targets
12881 // longjump(), throw(),
12882 // calls to exit() are allowed.
12883
12884 return rt;
12885
12886}
12887
12889//TODO check the loop index is not being written in the loop body
12890bool SageInterface::isCanonicalForLoop(SgNode* loop,SgInitializedName** ivar/*=NULL*/, SgExpression** lb/*=NULL*/, SgExpression** ub/*=NULL*/, SgExpression** step/*=NULL*/, SgStatement** body/*=NULL*/, bool *hasIncrementalIterationSpace/*= NULL*/, bool* isInclusiveUpperBound/*=NULL*/)
12891{
12892 ROSE_ASSERT(loop != NULL);
12893 SgForStatement* fs = isSgForStatement(loop);
12894 //SgFortranDo* fs2 = isSgFortranDo(loop);
12895 if (fs == NULL)
12896 {
12897 // if (fs2)
12898 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
12899 // else
12900 return false;
12901 }
12902 // 1. Check initialization statement is something like i=xx;
12903 SgStatementPtrList & init = fs->get_init_stmt();
12904 if (init.size() !=1)
12905 return false;
12906 SgStatement* init1 = init.front();
12907 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
12908 SgInitializedName* ivarname=NULL;
12909
12910 bool isCase1=false, isCase2=false;
12911 //consider C99 style: for (int i=0;...)
12912 if (isSgVariableDeclaration(init1))
12913 {
12914 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12915 ivarname = decl->get_variables().front();
12916 ROSE_ASSERT(ivarname != NULL);
12917 SgInitializer * initor = ivarname->get_initializer();
12918 if (isSgAssignInitializer(initor))
12919 {
12920 lbast = isSgAssignInitializer(initor)->get_operand();
12921 isCase1 = true;
12922 }
12923 }// other regular case: for (i=0;..)
12924 else if (isAssignmentStatement(init1, &ivarast, &lbast))
12925 {
12926 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12927 if (var)
12928 {
12929 ivarname = var->get_symbol()->get_declaration();
12930 isCase2 = true;
12931 }
12932 }
12933 // Cannot be both true
12934 ROSE_ASSERT(!(isCase1&&isCase2));
12935 // if not either case is true
12936 if (!(isCase1||isCase2))
12937 return false;
12938
12939 //Check loop index's type
12940 if (!isStrictIntegerType(ivarname->get_type()))
12941 return false;
12942
12943 //2. Check test expression i [<=, >=, <, > ,!=] bound
12944 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12945 if (test == NULL)
12946 return false;
12947 switch (test->variantT()) {
12948 case V_SgLessOrEqualOp:
12949 if (isInclusiveUpperBound != NULL)
12950 *isInclusiveUpperBound = true;
12951 if (hasIncrementalIterationSpace != NULL)
12952 *hasIncrementalIterationSpace = true;
12953 break;
12954 case V_SgLessThanOp:
12955 if (isInclusiveUpperBound != NULL)
12956 *isInclusiveUpperBound = false;
12957 if (hasIncrementalIterationSpace != NULL)
12958 *hasIncrementalIterationSpace = true;
12959 break;
12960 case V_SgGreaterOrEqualOp:
12961 if (isInclusiveUpperBound != NULL)
12962 *isInclusiveUpperBound = true;
12963 if (hasIncrementalIterationSpace != NULL)
12964 *hasIncrementalIterationSpace = false;
12965 break;
12966 case V_SgGreaterThanOp:
12967 if (isInclusiveUpperBound != NULL)
12968 *isInclusiveUpperBound = false;
12969 if (hasIncrementalIterationSpace != NULL)
12970 *hasIncrementalIterationSpace = false;
12971 break;
12972// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12973 break;
12974 default:
12975 return false;
12976 }
12977 // check the tested variable is the same as the loop index
12978 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12979 if (testvar == NULL)
12980 return false;
12981 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12982 return false;
12983 //grab the upper bound
12984 ubast = test->get_rhs_operand();
12985
12986 //3. Check the increment expression
12987 /* Allowed forms
12988 ++var
12989 var++
12990 --var
12991 var--
12992
12993 var += incr
12994 var -= incr
12995
12996 var = var + incr
12997 var = incr + var
12998 var = var - incr
12999 */
13000 SgExpression* incr = fs->get_increment();
13001 SgVarRefExp* incr_var = NULL;
13002 switch (incr->variantT()) {
13003 case V_SgPlusAssignOp: //+=
13004 case V_SgMinusAssignOp://-=
13005 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
13006 stepast = isSgBinaryOp(incr)->get_rhs_operand();
13007 break;
13008 case V_SgPlusPlusOp: //++
13009 case V_SgMinusMinusOp: //--
13010 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
13011 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
13012 break;
13013 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
13014 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
13015 if(incr_var == NULL)
13016 return false;
13017 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
13018 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
13019 SgBinaryOp* arithOp=0;
13020 if(addOp)
13021 arithOp=addOp;
13022 else if(subtractOp)
13023 arithOp=subtractOp;
13024 else
13025 return false;
13026 ROSE_ASSERT(arithOp!=0);
13027 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
13028 // cases : var + incr, var - incr
13029 incr_var=varRefExp;
13030 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
13031 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
13032 if(isSgAddOp(arithOp)) {
13033 // case : incr + var (not allowed: incr-var)
13034 incr_var=varRefExp;
13035 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
13036 }
13037 }
13038 break;
13039 } // end of V_AssignOp
13040 default:
13041 return false;
13042 }
13043
13044 if (incr_var == NULL)
13045 return false;
13046 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
13047 return false;
13048
13049
13050 // single entry and single exit?
13051 // only for C for loop for now
13052 // TODO: Fortran support later
13053 if (fs && !isStructuredBlock(fs->get_loop_body()) )
13054 return false;
13055
13056 // return loop information if requested
13057 if (ivar != NULL)
13058 *ivar = ivarname;
13059 if (lb != NULL)
13060 *lb = lbast;
13061 if (ub != NULL)
13062 *ub = ubast;
13063 if (step != NULL)
13064 *step = stepast;
13065 if (body != NULL) {
13066 *body = fs->get_loop_body();
13067 }
13068 return true;
13069}
13070
13073{
13074 ROSE_ASSERT(loop != NULL);
13075 ROSE_ASSERT(lb != NULL);
13076 SgForStatement* forstmt = isSgForStatement(loop);
13077 SgFortranDo* dostmt = isSgFortranDo(loop);
13078 // ROSE_ASSERT(forstmt!= NULL);
13079
13080 if (forstmt != NULL)
13081 {
13082 // two cases: init_stmt is
13083 // SgExprStatement (assignment) like i=0;
13084 // SgVariableDeclaration int i =0 or
13085 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13086 if (testList.size()>0) // assignment statement
13087 {
13088 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13089 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13090 ROSE_ASSERT(assignop);
13091 if( assignop->get_rhs_operand()->get_lvalue())
13092 lb->set_lvalue(true);
13093 assignop->set_rhs_operand(lb);
13094 lb->set_parent(assignop);
13095 //TODO what happens to the original rhs operand?
13096 }
13097 else // variable declaration case
13098 {
13099 // SgVariableDeclaration
13100 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13101 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13102 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13103 ROSE_ASSERT(init != NULL);
13104 init->set_operand(lb);
13105 lb->set_parent(init);
13106 //TODO what happens to the original rhs operand?
13107 }
13108 }
13109 else if (dostmt != NULL)
13110 {
13111 SgExpression* init = dostmt->get_initialization();
13112 ROSE_ASSERT (init != NULL);
13113 SgAssignOp * a_op = isSgAssignOp (init);
13114 ROSE_ASSERT (a_op!=NULL);
13115 a_op->set_rhs_operand(lb);
13116 lb->set_parent(a_op);
13117 //TODO delete the previous operand?
13118 }
13119 else
13120 {
13121 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13122 ROSE_ASSERT (false);
13123 }
13124}
13125
13128{
13129 ROSE_ASSERT(loop != NULL);
13130 ROSE_ASSERT(ub != NULL);
13131 SgForStatement* forstmt = isSgForStatement(loop);
13132 // ROSE_ASSERT(forstmt!= NULL);
13133 SgFortranDo* dostmt = isSgFortranDo(loop);
13134 if (forstmt != NULL)
13135 {
13136 // set upper bound expression
13137 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13138 ROSE_ASSERT(binop != NULL);
13139 binop->set_rhs_operand(ub);
13140 ub->set_parent(binop);
13141 }
13142 else if (dostmt != NULL)
13143 {
13144 dostmt->set_bound(ub);
13145 ub->set_parent(dostmt);
13146 //TODO delete the original bound expression
13147 }
13148 else
13149 {
13150 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13151 ROSE_ASSERT (false);
13152 }
13153
13154}
13155
13158{
13159 ROSE_ASSERT(loop != NULL);
13160 ROSE_ASSERT(stride != NULL);
13161 SgForStatement* forstmt = isSgForStatement(loop);
13162 SgFortranDo * dostmt = isSgFortranDo (loop);
13163 // ROSE_ASSERT(forstmt!= NULL);
13164 if (dostmt != NULL)
13165 {
13166 dostmt->set_increment(stride);
13167 stride->set_parent(dostmt);
13168 //TODO delete original increment expression
13169 }
13170 else if (forstmt != NULL)
13171 {
13172 // set stride expression
13173 // case 1: i++ change to i+=stride
13174 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13175 if (testList.size()>0)
13176 {
13177 ROSE_ASSERT(testList.size() == 1); // should have only one
13178 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13179 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13180 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13181 forstmt->set_increment(plusassignop);
13182 }
13183
13184 // case 1.5: i-- also changed to i+=stride
13185 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13186 if (testList.size()>0)
13187 {
13188 ROSE_ASSERT(testList.size()==1);// should have only one
13189 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13190 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13191 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13192 forstmt->set_increment(plusassignop);
13193 }
13194
13195 // case 2: i+=X
13196 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13197 if (testList.size()>0)
13198 {
13199 ROSE_ASSERT(testList.size()==1);// should have only one
13200 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13201 ROSE_ASSERT(assignop!=NULL);
13202 assignop->set_rhs_operand(stride);
13203 }
13204
13205 // case 2.5: i-=X changed to i+=stride
13206 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13207 if (testList.size()>0)
13208 {
13209 ROSE_ASSERT(testList.size()==1);// should have only one
13210 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13211 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13212 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13213 ROSE_ASSERT(exprstmt !=NULL);
13214 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13215 exprstmt->set_expression(plusassignop);
13216 }
13217
13218#if 0 // [Robb Matzke 2021-03-17]
13219 // DQ (1/3/2007): I think this is a meaningless statement.
13220 testList.empty();
13221#endif
13222 // case 3: i=i + X or i =X +i i
13223 // TODO; what if users use i*=,etc ??
13224 // send out a warning: not canonical FOR/DO loop
13225 // or do this in the real frontend. MUST conform to canonical form
13226 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13227 if (testList.size()>0)
13228 {
13229 ROSE_ASSERT(testList.size()==1);// should have only one ??
13230 // consider only the top first one
13231 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13232 ROSE_ASSERT(addop!=NULL);
13233 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13234 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13235 {
13236 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13237 addop->set_lhs_operand(stride);
13238 else
13239 addop->set_rhs_operand(stride);
13240 }
13241 else
13242 addop->set_rhs_operand(stride);
13243 }
13244
13245 // case 3.5: i=i - X
13246 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13247 if (testList.size()>0)
13248 {
13249 ROSE_ASSERT(testList.size()==1);// should have only one ??
13250 // consider only the top first one
13251 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13252 ROSE_ASSERT(subtractop!=NULL);
13253 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13254 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13255 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13256 ROSE_ASSERT(assignop !=NULL);
13257 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13258 assignop->set_rhs_operand(plusassignop);
13259 }
13260 }
13261 else
13262 {
13263 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13264 ROSE_ASSERT (false);
13265
13266 }
13267}
13268
13272bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13273{
13274 SgExprStatement *n = isSgExprStatement(s);
13275 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13276 if (exp != 0) {
13277 switch (exp->variantT()) {
13278 case V_SgPlusAssignOp:
13279 case V_SgMinusAssignOp:
13280 case V_SgAndAssignOp:
13281 case V_SgIorAssignOp:
13282 case V_SgMultAssignOp:
13283 case V_SgDivAssignOp:
13284 case V_SgModAssignOp:
13285 case V_SgXorAssignOp:
13286 case V_SgAssignOp:
13287 {
13288 SgBinaryOp* s2 = isSgBinaryOp(exp);
13289 if (lhs != 0)
13290 *lhs = s2->get_lhs_operand();
13291 if (rhs != 0) {
13292 SgExpression* init = s2->get_rhs_operand();
13293 if ( init->variantT() == V_SgAssignInitializer)
13294 init = isSgAssignInitializer(init)->get_operand();
13295 *rhs = init;
13296 }
13297 if (readlhs != 0)
13298 *readlhs = (exp->variantT() != V_SgAssignOp);
13299 return true;
13300 }
13301 default:
13302 return false;
13303 }
13304 }
13305 return false;
13306}
13307
13308
13309void
13311 {
13312 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13313 for (size_t i = 0; i < gotos.size(); ++i)
13314 {
13315 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13316 SgLabelStatement* ls = gs->get_label();
13317 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13318 if (!lsParent) continue;
13319 SgStatementPtrList& bbStatements = lsParent->get_statements();
13320
13321 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13322
13323 ROSE_ASSERT (j != bbStatements.size());
13324
13325 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13326 {
13327 ++j;
13328 }
13329 gs->set_label(isSgLabelStatement(bbStatements[j]));
13330 }
13331 }
13332
13333bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13334{
13335 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13336}
13338
13342bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13343{
13344 bool rt= true;
13345 ROSE_ASSERT(decl != NULL);
13346 ROSE_ASSERT(assign_stmt != NULL);
13347
13348 // Sanity check of assign statement: must be a form of var = xxx;
13349 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13350 if (assign_op == NULL)
13351 return false;
13352 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13353 if (assign_op_var == NULL) return false;
13354
13355 // Sanity check of the variable declaration: it should not have an existing initializer
13357 if (decl_var->get_initptr()!= NULL ) return false;
13358
13359 // check if two variables match
13360 // In translation, it is possible the declaration has not yet been inserted into its scope.
13361 // finding its symbol can return NULL.
13362 // But we still want to do the merge.
13363 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13364 if (decl_var_symbol!=NULL)
13365 {
13366 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13367 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13368 }
13369 else
13370 { // fallback to comparing variable names instead
13371 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13372 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13373 }
13374
13375 // Everything looks fine now. Do the merge.
13377
13378 // Must preserve the proprecessing information of the original assign_stmt
13379 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13380 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13381
13382 // removeStatement() does not support removing a statement which is not inside a container.
13383 // But sometimes we do need to remove such a statement and replace it with a new one.
13384 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13385 // TODO: improve removeStatement() which uses low level rewritting.
13386 if (removeAssignStmt)
13387 SageInterface::removeStatement (assign_stmt);
13388// SageInterface::deepDelete (assign_stmt);
13390 decl_var->set_initptr(initor);
13391 initor->set_parent(decl_var);
13392
13393 return rt;
13394}
13395
13397{
13398 bool rt= true;
13399
13400 // Sanity check of assign statement: must be a form of var = xxx;
13401 ROSE_ASSERT(assign_stmt != NULL);
13402 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13403 if (assign_op == NULL)
13404 return false;
13405 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13406 if (assign_op_var == NULL)
13407 return false;
13408
13409 // Sanity check of the variable declaration: it should not have an existing initializer
13410 ROSE_ASSERT(decl != NULL);
13412 if (decl_var->get_initptr()!= NULL)
13413 return false;
13414
13415 // check if two variables match
13416 // In translation, it is possible the declaration has not yet been inserted into its scope.
13417 // finding its symbol can return NULL.
13418 // But we still want to do the merge.
13419 ROSE_ASSERT(decl_var != NULL);
13420 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13421 if (decl_var_symbol != NULL) {
13422 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13423 if (assign_op_var->get_symbol() != decl_var_symbol)
13424 return false;
13425 }
13426 else
13427 { // fallback to comparing variable names instead
13428 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13429 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13430 return false;
13431 }
13432
13433 // Everything looks fine now. Do the merge.
13434 // It is implemented by
13435 // 1. copy rhs to the decl's rhs,
13436 // 2. then move the decl to the place of the assignment,
13437 // 3. then remove the assignment
13438 //
13439 // Copy rhs to be initializer
13442 decl_var->set_initptr(initor);
13443 initor->set_parent(decl_var);
13444
13445 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13446 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13447 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13448
13449 // removeStatement() does not support removing a statement which is not inside a container.
13450 // But sometimes we do need to remove such a statement and replace it with a new one.
13451 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13452 // TODO: improve removeStatement() which uses low level rewritting.
13453
13454 // Now move the declaration to a new position, right before the assignment statement
13456 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13457
13458 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13459 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13460
13461 // Original assignment statement should be removed
13462 SageInterface::removeStatement (assign_stmt);
13463 // SageInterface::deepDelete (decl);
13464
13465 return rt;
13466}
13467// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13468// Return the generated assignment statement, if any
13470{
13471 SgExprStatement* rt = NULL;
13472 ROSE_ASSERT (decl != NULL);
13473
13475 SgInitializer* initor = decl_var ->get_initptr();
13476 if (initor == NULL)
13477 rt = NULL;
13478 else
13479 {
13480 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13481 SgExpression * rhs=NULL;
13482 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13483 rhs = ainitor->get_operand();
13484 else
13485 rhs = initor;
13486
13487 // we deep copy the rhs operand
13488 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13489 decl_var->set_initptr(NULL);
13490 //TODO clean up initor
13491 insertStatementAfter ( decl, rt );
13492 }
13493 return rt;
13494}
13496ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13497{
13498 int count = 0;
13499 if (!topLevelOnly)
13500 {
13501 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13502 ROSE_ASSERT (false);
13503 }
13504
13505 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13506 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13507 {
13508 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13509 if (topLevelOnly)
13510 {
13511 ROSE_ASSERT(decl != NULL);
13512 if (decl->get_scope() == scope)
13513 {
13515 count ++;
13516 }
13517 }
13518 }
13519 return count;
13520}
13521
13522void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13523{
13524 ROSE_ASSERT (root != NULL);
13525// std::vector<SgVarRefExp* > result;
13526
13527 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13528 // AST query won't find variables used in types
13530
13531 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13532 {
13533 SgVarRefExp *vRef = isSgVarRefExp(*i);
13534 ROSE_ASSERT (vRef != NULL);
13535 result.push_back(vRef);
13536 }
13537}
13538
13539int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13540{
13541 int rt = 0;
13542 ROSE_ASSERT (root != NULL);
13543 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13544 for (size_t i =0; i< constructorList.size(); i++)
13545 {
13546 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13547 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13548 {
13549 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13550 for (size_t j =0 ; j< varList.size(); j++)
13551 {
13552 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13553 currentVarRefList.push_back(var_exp);
13554//TODO: these variable references do have special scopes, how to communicate to users?
13555// specialVarRefScopeExp[var_exp] = c_init ;
13556 rt ++;
13557 }
13558 }
13559 }
13560 return rt;
13561}
13562
13563namespace SageInterface { // A few internal helper classes
13564
13566 {
13567 SgAndOp* op;
13568
13569 public:
13570 AndOpGenerator(SgAndOp* op): op(op) {}
13571
13572 virtual SgStatement* generate(SgExpression* lhs)
13573 {
13574 if (lhs==NULL)
13575 return NULL;
13576 SgTreeCopy treeCopy;
13577 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13578 ROSE_ASSERT (lhsCopy);
13579 SgIfStmt* tree =
13586 return tree;
13587 }
13588 };
13589
13591 {
13592 SgOrOp* op;
13593
13594 public:
13595 OrOpGenerator(SgOrOp* op): op(op) {}
13596
13597 virtual SgStatement* generate(SgExpression* lhs)
13598 {
13599 if (lhs==NULL)
13600 return NULL;
13601 SgTreeCopy treeCopy;
13602 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13603 ROSE_ASSERT (lhsCopy);
13604 SgIfStmt* tree =
13611 return tree;
13612 }
13613 };
13614
13616 {
13617 SgConditionalExp* op;
13618
13619 public:
13621
13622 virtual SgStatement* generate(SgExpression* lhs)
13623 {
13624 if (lhs==NULL)
13625 return NULL;
13626 SgTreeCopy treeCopy;
13627 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13628 ROSE_ASSERT (lhsCopy);
13629 SgIfStmt* tree =
13636 return tree;
13637 }
13638 };
13639
13640} // end of namespace for the helper classes
13641
13644{
13645 ROSE_ASSERT(from != NULL);
13646
13647#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13648#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13650 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13651 ROSE_ASSERT (false);
13652 }
13653
13654 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13655#endif
13656 SgStatement* stmt = getStatementOfExpression(from);
13657 assert (stmt);
13658 if (!isSgForInitStatement(stmt->get_parent())) {
13659 //SageInterface::ensureBasicBlockAsParent(stmt);
13660 // no return value is accepted. Only the optional transformation matters
13661 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13663 }
13664
13665 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13666 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13667 if (!parent && isSgForInitStatement(stmt->get_parent()))
13668 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13669 assert (parent);
13670 // cout << "parent is a " << parent->sage_class_name() << endl;
13671 // cout << "parent is " << parent->unparseToString() << endl;
13672 // cout << "stmt is " << stmt->unparseToString() << endl;
13673 SgName varname = "rose_temp__";
13674 if (newName == "") {
13675 varname << ++SageInterface::gensym_counter;
13676 } else {
13677 varname = newName;
13678 }
13679
13680 SgType* vartype = from->get_type();
13681 SgNode* fromparent = from->get_parent();
13682 vector<SgExpression*> ancestors;
13683 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13684 expr = anc, anc = isSgExpression(anc->get_parent()))
13685 {
13686 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13687 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13688 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13689 ancestors.push_back(anc); // Closest first
13690 }
13691 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13692 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13693 {
13694 StatementGenerator* gen;
13695 switch ((*ai)->variantT()) {
13696 case V_SgAndOp:
13697 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13698 case V_SgOrOp:
13699 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13700 case V_SgConditionalExp:
13701 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13702 default: assert (!"Should not happen"); abort();
13703 }
13705 delete gen;
13706 } // for
13707 if (ancestors.size() != 0) {
13708 return splitExpression(from);
13709 // Need to recompute everything if there were ancestors
13710 }
13711 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13713 ROSE_ASSERT (sym);
13714 SgInitializedName* initname = sym->get_declaration();
13715 ROSE_ASSERT (initname);
13717 replaceExpressionWithExpression(from, varref);
13718 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13719 // cout << "From is a " << from->sage_class_name() << endl;
13721 initname->set_initializer(ai);
13722 ai->set_parent(initname);
13723 myStatementInsert(stmt, vardecl, true);
13724 // vardecl->set_parent(stmt->get_parent());
13725 // FixSgTree(vardecl);
13726 // FixSgTree(parent);
13727 return ai;
13728
13729#else
13730 return NULL;
13731#endif
13732
13733} //splitExpression()
13734
13737 struct SplitStatementGenerator: public StatementGenerator {
13738 SgExpression* expr;
13739 virtual SgStatement* generate(SgExpression* answer) {
13740 using namespace SageBuilder;
13741 return buildBasicBlock(buildAssignStatement(answer, expr));
13742 }
13743 };
13744 SplitStatementGenerator gen;
13745 gen.expr = expr;
13747 }
13748
13750 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13751 V_SgGotoStatement);
13752 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13753 (size_t i = 0; i < gotos.size(); ++i) {
13754 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13755 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13756 if (!gsParent) continue;
13757 SgStatementPtrList& bbStatements = gsParent->get_statements();
13758 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13759 - bbStatements.begin();
13760 ROSE_ASSERT (j != bbStatements.size());
13761 if (j == 0) continue;
13762 if (isSgLabelStatement(bbStatements[j - 1])) {
13763 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13764 gs->get_label();
13765 }
13766 }
13767 for (size_t i = 0; i < gotos.size(); ++i) {
13768 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13769 SgLabelStatement* oldLabel = gs->get_label();
13770 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13771 oldLabel = labelsToReplace[oldLabel];
13772 }
13773 gs->set_label(oldLabel);
13774 }
13775 }
13776
13778 switch (e->variantT()) {
13779#ifdef _MSC_VER
13780 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13781 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13782#else
13783 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13784#endif
13785 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13786 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13787 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13788 case V_SgAddressOfOp: return true;
13789 default: return false;
13790 }
13791 }
13792
13794 switch (e->variantT()) {
13795 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13796 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13797 case V_SgCastExp: return
13798 isConstantFalse(isSgCastExp(e)->get_operand());
13799 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13800 default: return false;
13801 }
13802 }
13803
13805 SgExpression* e) {
13806 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13807 if (!fc) return false;
13808 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13809 if (fr == NULL) return false;
13810 return fr->get_symbol()->get_declaration() == decl;
13811 }
13812
13813 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13814 arity, SgExpression* e) {
13815 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13816 if (!fc) return false;
13817 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13818 if (fr == NULL) return false;
13819 string name =
13820 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13821 return (name == qualifiedName &&
13822 fc->get_args()->get_expressions().size() == arity);
13823 }
13824
13826 {
13827 ROSE_ASSERT( e != NULL);
13828 // We enforce that the source expression is fully attached to the AST
13829 // Too strict, the source expression can be just built and not attached.
13830 // Liao, 9/21/2009
13831// ROSE_ASSERT( e->get_parent() != NULL);
13832 return deepCopy(e);
13833 }
13834
13836 {
13837 return deepCopy(s);
13838 }
13839
13840 //----------------- add into AST tree --------------------
13842 {
13843 ROSE_ASSERT(expList);
13844 ROSE_ASSERT(exp);
13845 expList->append_expression(exp);
13846 exp->set_parent(expList);
13847 }
13848
13849 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13850 {
13851 for (size_t i = 0; i < exp.size(); ++i)
13852 appendExpression(expList, exp[i]);
13853 }
13854
13855# if 0
13856 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13857
13858 // TODO consider the difference between C++ and Fortran
13859 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13860template <class actualFunction>
13861void
13862// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13863SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13864 {
13865 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13866 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13867 // function derived classes).
13868
13869 ROSE_ASSERT(func);
13870 ROSE_ASSERT(paralist);
13871
13872 // Warn to users if a paralist is being shared
13873 if (paralist->get_parent() !=NULL)
13874 {
13875 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13876 << (func->get_name()).getString()<<endl
13877 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13878 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13879 // ROSE_ASSERT(false);
13880 }
13881
13882 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13883 if (func->get_parameterList() != NULL)
13884 if (func->get_parameterList() != paralist)
13885 delete func->get_parameterList();
13886
13887 func->set_parameterList(paralist);
13888 paralist->set_parent(func);
13889 }
13890#endif
13891
13892// static
13893SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
13894 {
13895 ROSE_ASSERT(paraList != NULL);
13896 ROSE_ASSERT(initName != NULL);
13897
13898 if (isPrepend == true)
13899 paraList->prepend_arg(initName);
13900 else
13901 paraList->append_arg(initName);
13902
13903 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
13904 // initName->set_parent(paraList);
13905 if (initName->get_parent() == NULL)
13906 initName->set_parent(paraList);
13907
13908 ROSE_ASSERT(initName->get_parent() == paraList);
13909
13910 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
13911
13912 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
13913 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
13914 // ROSE_ASSERT(paraList->get_parent() != NULL);
13915 // ROSE_ASSERT(func_decl != NULL);
13916
13917 SgScopeStatement* scope = NULL;
13918 if (func_decl != NULL)
13919 {
13920 if ((func_decl->get_definingDeclaration()) == func_decl )
13921 {
13922 // defining function declaration, set scope and symbol table
13923 SgFunctionDefinition* func_def = func_decl->get_definition();
13924 ROSE_ASSERT(func_def);
13925 scope = func_def;
13926 }
13927 else
13928 {
13929 // nondefining declaration, set scope only, currently set to decl's scope, TODO
13930 scope = func_decl->get_scope();
13931 }
13932
13933 // fix up declptr of the init name
13934 initName->set_declptr(func_decl);
13935 }
13936
13937 // Liao 11/21/2012. Part of this function's work is to set scope for initName which is freshly created. So we should not assert
13938 // that initName already has a scope.
13939 //
13940 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
13941 // ROSE_ASSERT(initName->get_scope() != NULL);
13942 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
13943
13944 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
13945
13946 initName->set_scope(scope);
13947 if (scope != NULL)
13948 {
13949 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
13950 if (sym == NULL)
13951 {
13952 sym = new SgVariableSymbol(initName);
13953 scope->insert_symbol(initName->get_name(), sym);
13954 sym->set_parent(scope->get_symbol_table());
13955 }
13956 return sym;
13957 }
13958 else
13959 {
13960 return NULL;
13961 }
13962 }
13963
13965{
13966 return addArg(paraList,initName,false);
13967}
13968
13970{
13971 return addArg(paraList,initName,true);
13972}
13973
13975{
13976 ROSE_ASSERT(decl);
13977 ROSE_ASSERT(pragma);
13978 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
13979 decl->set_pragma(pragma);
13980 pragma->set_parent(decl);
13981}
13982
13983
13985//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
13986//It might be well legal to append the first and only statement in a scope!
13988 {
13989 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
13990 void testAstForUniqueNodes ( SgNode* node );
13991
13992#if 0
13993 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
13994#endif
13995
13996 // DQ (6/19/2012): Exit as a test...
13997 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
13998
13999 if (scope == NULL)
14000 {
14001#if 0
14002 printf (" --- scope was not specified as input! \n");
14003#endif
14005 }
14006
14007 ROSE_ASSERT(stmt != NULL);
14008 ROSE_ASSERT(scope != NULL);
14009
14010#if 0
14011 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14012#endif
14013
14014#if 0
14015 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
14016 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
14017 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
14018 if (declarationStatement != NULL)
14019 {
14020 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
14021 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
14022 }
14023#endif
14024
14025#if 0
14026 // This fix breaks other transformations.
14027 // It is better to do this explicitly as needed before calling appendStatement();
14028 // Liao 10/19/2010
14029 // In rare cases, we are moving the statement from its original scope to another scope
14030 // We have to remove it from its original scope before append it to the new scope
14031 SgNode* old_parent= stmt->get_parent();
14032 if (old_parent)
14033 {
14034 removeStatement(stmt);
14035 }
14036#endif
14037
14038#if 0
14039 // catch-all for statement fixup
14040 // Must fix it before insert it into the scope,
14041 fixStatement(stmt,scope);
14042
14043 //-----------------------
14044 // append the statement finally
14045 // scope->append_statement (stmt);
14046 scope->insertStatementInScope(stmt,false);
14047 stmt->set_parent(scope); // needed?
14048#else
14049 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
14050 bool skipAddingStatement = false;
14051 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
14052 if (classDeclaration != NULL)
14053 {
14054 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14055#if 0
14056 if (classDeclaration->get_parent() != NULL)
14057 {
14058 printf ("Since the parent of this SgClassDeclaration is set, it must have been previously added to the AST: classDeclaration = %p = %s \n",classDeclaration,classDeclaration->class_name().c_str());
14059 }
14060#endif
14061
14062#if 1
14063 // DQ (6/9/2013): This is the original code...
14064 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
14065#else
14066 // DQ (6/9/2013): We have no other way to detect if the SgClassDeclaration has previously been added to the AST (short of searching the AST directly).
14067 // This fails to add enough statements to the AST.
14068 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
14069#endif
14070
14071 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
14072 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
14073 // twice as a result of a template argument being instantiated and we only want to add it into
14074 // the scope once. This happens for test2013_198.C and I can't find a better solution.
14075 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
14076 {
14077 // Check if this instnatiated template has already been added to the scope.
14078
14079 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
14080 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
14081 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
14082 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
14083 if (statementAlreadyExistsInScope == true)
14084 {
14085 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14086 {
14087// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14088// #if 1
14089#if PRINT_DEVELOPER_WARNINGS
14090 printf ("RARE ISSUE #1: In SageInterface::appendStatement(): This template instantiation has previously been added to the scope, so avoid doing so again (see test2013_198.C): classDeclaration = %p = %s scope = %p = %s \n",
14091 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14092#endif
14093 }
14094#if 1
14095 else
14096 {
14097#if 1
14098 printf ("RARE ISSUE #2: In SageInterface::appendStatement(): This statement has previously been added to the scope, so avoid doing so again (see rose.h): stmt = %p = %s scope = %p = %s \n",
14099 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14100#endif
14101 }
14102#endif
14103 skipAddingStatement = true;
14104 }
14105 }
14106 }
14107 else
14108 {
14109 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14110 if (enumDeclaration != NULL)
14111 {
14112 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14113 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14114 }
14115 }
14116
14117#if 0
14118 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14119 // that would be inserted into the current scope. This is however a bit expensive so we are using
14120 // this as a way to also debug the new cases where this happens.
14121 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14122 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14123 {
14124#if 0
14125 printf ("RARE ISSUE #2: In SageInterface::appendStatement(): This statement has previously been added to the scope, so avoid doing so again (see rose.h): stmt = %p = %s scope = %p = %s \n",
14126 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14127#endif
14128#if 0
14129 printf ("Exiting as a test! \n");
14130 ROSE_ABORT();
14131#endif
14132 skipAddingStatement = true;
14133 }
14134#endif
14135
14136#if 0
14137 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14138#endif
14139
14140 if (skipAddingStatement == false)
14141 {
14142 // catch-all for statement fixup
14143 // Must fix it before insert it into the scope,
14144 // printf ("In appendStatementList(): Calling fixStatement() \n");
14145 fixStatement(stmt,scope);
14146 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14147
14148 //-----------------------
14149 // append the statement finally
14150 // scope->append_statement (stmt);
14151#if 0
14152 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14153#endif
14154 scope->insertStatementInScope(stmt,false);
14155
14156 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14157 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14158 // other declarations (e.g. "typedef struct { int x; } y;").
14159 stmt->set_parent(scope); // needed?
14160 }
14161#endif
14162
14163 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14164 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14165 // this). Also since this is only operating within a single scope it is likely too specific to C
14166 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14167 // use name qualification).
14168 // update the links after insertion!
14170 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14171 {
14172 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14173 }
14174
14175#if 0
14176 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14177 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14178 // statement in a single scope.
14179 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14180 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14181 testAstForUniqueNodes(scope);
14182#else
14183 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14184#endif
14185 }
14186
14189{
14190 ROSE_ASSERT (stmt != NULL);
14191 ROSE_ASSERT (for_init_stmt != NULL);
14192
14193#if 0
14194 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14195#endif
14196
14197 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14198 // to record it being moved (and thus the macroExpansions that it might be associated with having
14199 // to force the macroExpansion's associated statements to be marked as a transformation.
14201
14202#if 0
14203 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14204#endif
14205
14206 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14207 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14208 // prepend, we only need to look at the scope.
14210
14211 for_init_stmt->append_init_stmt (stmt);
14212}
14213
14214void
14215SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14216 {
14217 for (size_t i = 0; i < stmts.size(); ++i)
14218 {
14219#if 0
14220#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14221 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14222 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14223#endif
14224#endif
14225 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14226#if 0
14227 if (stmts[i]->get_parent() != NULL)
14228 {
14229#if 0
14230#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14231 printf (" --- In appendStatementList(): stmts[i = %" PRIuPTR "] will be added to scope (because stmts[i]->get_parent() != NULL (= %p = %s) \n",i,stmts[i]->get_parent(),stmts[i]->get_parent()->class_name().c_str());
14232#endif
14233#endif
14234 appendStatement(stmts[i], scope);
14235 }
14236 else
14237 {
14238 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14239 }
14240#endif
14241 }
14242 }
14243
14246 {
14247 ROSE_ASSERT (stmt != NULL);
14248
14249#if 0
14250 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14251#endif
14252
14253 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14254
14255 if (scope == NULL)
14256 {
14258 }
14259
14260 ROSE_ASSERT(scope != NULL);
14261 // TODO handle side effect like SageBuilder::appendStatement() does
14262
14263 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14264
14265 // Must fix it before insert it into the scope,
14266 // otherwise assertions in insertStatementInScope() would fail
14267 fixStatement(stmt,scope);
14268
14269#if 0
14270 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14271 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14272#endif
14273
14274 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14275
14276 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14277 // to record it being moved (and thus the macroExpansions that it might be associated with having
14278 // to force the macroExpansion's associated statements to be marked as a transformation.
14280
14281#if 0
14282 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14283 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14284#endif
14285
14286 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14287
14288 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14289 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14290 // prepend, we only need to look at the scope.
14292
14293#if 0
14294 printf ("Calling insertStatementInScope() \n");
14295#endif
14296
14297 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14298 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14299
14300 scope->insertStatementInScope(stmt,true);
14301 stmt->set_parent(scope); // needed?
14302
14303 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14304
14305 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14306 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14307 // this). Also since this is only operating within a single scope it is likely too specific to C
14308 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14309 // use name qualification).
14310 // update the links after insertion!
14312 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14313 {
14314 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14315 }
14316
14317 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14318
14319#if 0
14320 printf ("Leaving SageInterface::prependStatement() \n");
14321#endif
14322 } // prependStatement()
14323
14324
14327{
14328 ROSE_ASSERT (stmt != NULL);
14329 ROSE_ASSERT (for_init_stmt != NULL);
14330
14331#if 0
14332 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14333#endif
14334
14335 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14336 // to record it being moved (and thus the macroExpansions that it might be associated with having
14337 // to force the macroExpansion's associated statements to be marked as a transformation.
14339
14340#if 0
14341 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14342#endif
14343
14344 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14345 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14346 // prepend, we only need to look at the scope.
14348
14349 for_init_stmt->prepend_init_stmt (stmt);
14350}
14351
14352void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14353 {
14354 for (size_t i = stmts.size(); i > 0; --i)
14355 {
14356 prependStatement(stmts[i - 1], scope);
14357 }
14358 }
14359
14364{
14365 bool rt = false;
14366 ROSE_ASSERT (scope != NULL);
14367 switch (scope->variantT())
14368 {
14369 case V_SgBasicBlock:
14370 case V_SgClassDefinition:
14371 case V_SgFunctionDefinition:
14372 case V_SgGlobal:
14373 case V_SgNamespaceDefinitionStatement: //?
14374 rt = true;
14375 break;
14376
14377 case V_SgAssociateStatement :
14378 case V_SgBlockDataStatement :
14379 case V_SgCatchOptionStmt:
14380 case V_SgDoWhileStmt:
14381 case V_SgForAllStatement:
14382 case V_SgForStatement:
14383 case V_SgFortranDo:
14384 case V_SgIfStmt:
14385 case V_SgSwitchStatement:
14386 case V_SgUpcForAllStatement:
14387 case V_SgWhileStmt:
14388 rt = false;
14389 break;
14390
14391 default:
14392 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14393 break;
14394 }
14395 return rt;
14396}
14397
14398
14399// DQ (11/21/2018): We need to sometimes insert something after the last statement of the collection from rose_edg_required_macros_and_functions.h.
14401 {
14402 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14403 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14404
14405 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14406
14407 SgStatement* last_statement = NULL;
14408 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14409 // while (i != declarationList.end())
14410 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14411 {
14412#if 0
14413 printf ("(*i)->get_file_info()->get_file_id() = %d isFrontendSpecific = %s \n",(*i)->get_file_info()->get_file_id(),(*i)->get_file_info()->isFrontendSpecific() ? "true" : "false");
14414#endif
14415 last_statement = *i;
14416
14417 i++;
14418 }
14419
14420 ROSE_ASSERT(last_statement != NULL);
14421#if 1
14422 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14423#endif
14424#if 0
14425 printf ("Exiting as a test! \n");
14426 ROSE_ABORT();
14427#endif
14428
14429 return last_statement;
14430 }
14431
14432
14433 //TODO handle more side effect like SageBuilder::append_statement() does
14434 //Merge myStatementInsert()
14435 // insert SageInterface::insertStatement()
14436void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14437 {
14438 ROSE_ASSERT(targetStmt &&newStmt);
14439 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14440
14441 if (isSgGlobal(targetStmt) ||
14442 isSgClassDefinition(targetStmt)||
14443 isSgNamespaceDefinitionStatement(targetStmt)||
14444 isSgFunctionParameterList(targetStmt)||
14445 isSgFunctionDefinition(targetStmt)||
14446 isSgCtorInitializerList(targetStmt))
14447 {
14448 string className = targetStmt->class_name();
14449 string err_msg = "targetStmt cannot be a " + className + ". Its parent does not implement insert_child(). Please revise your code to avoid inserting a stmt as a sibling of this type of targetStmt.";
14450 cerr<<err_msg<<endl;
14451 ROSE_ASSERT (false);
14452 }
14453
14454#if 0 // it is allowed to have different types of statements inserted after SgCaseOptionStmt
14455 if (isSgCaseOptionStmt(targetStmt))
14456 {
14457 if (!isSgCaseOptionStmt(newStmt))
14458 {
14459 cerr<<"Target statment is a case option stmt. The new stmt should also be the same type to be a sibling. But it is "<< newStmt->class_name() << " instead. This is not semantically correct." <<endl;
14460 ROSE_ASSERT(false);
14461 }
14462 }
14463#endif
14464 SgNode* parent = targetStmt->get_parent();
14465 if (parent == NULL)
14466 {
14467 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14468 ROSE_ASSERT(parent);
14469 }
14470
14471 // Issuing an error due to variable initialization inside a switch statement block without enclosing braces {}.
14472 //
14473 // This is a tricky situation: C++ allows a flat list of statements following case option statement, even though they are indented
14474 //case HORIZONTAL_TAB:
14475 // foundHorizontalTab = true;
14476 // break;
14477 // case VERTICAL_TAB:
14478 // foundVerticalTab = true;
14479 // break;
14480 // ...
14481 //
14482 // Unparser will flatten them out.
14483 //
14484 // when we try to inserat a variable decl stmt into the list after case option statement, compilers will complain
14485 // error: jump to case label
14486 // crosses initialization of "int variablexyz"
14487 //
14488 //
14489 // if targetStmt's parent is SgCaseOptionStmt,
14490 if (/* SgCaseOptionStmt * case_opt_stmt = */ isSgCaseOptionStmt(parent))
14491 {
14492 if (/* SgVariableDeclaration* var_stmt = */ isSgVariableDeclaration(newStmt))
14493 {
14494 cerr<<"Error: you cannot insert a variable declaration stmt inside a case option statement without enclosing brances in between."<<endl;
14495 cerr<<"parent of target is a case option stmt:"<<parent <<endl;
14496 cerr<<"new statement is a variable statement:"<<newStmt <<endl;
14497 ASSERT_require(false);
14498 }
14499 }
14500
14501 if (isSgLabelStatement(parent) != nullptr)
14502 {
14503 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14504 parent = labelStatement->get_parent();
14505 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14506 }
14507
14508 if (isSgFunctionDefinition(parent) ||
14509 isSgTypedefDeclaration(parent) ||
14510 isSgSwitchStatement(parent) ||
14511 isSgVariableDeclaration(parent))
14512 {
14513 string className = parent->class_name();
14514 string err_msg = "targetStmt's parent cannot be a " + className + ". This parent does not implement insert() function. Please revise your code to avoid inserting a stmt as a child of this type of parent.";
14515 cerr<<err_msg<<endl;
14516 if (SgSwitchStatement * switch_stmt = isSgSwitchStatement(parent))
14517 {
14518 if (switch_stmt->get_item_selector() == targetStmt)
14519 {
14520 cerr<<"The target statement is the item selector of a switch statement. You cannot insert any statement before or after it."<<endl;
14521 }
14522 }
14523
14524 ROSE_ASSERT (false);
14525 }
14526
14527#if 0
14528 printf ("In SageInterface::insertStatement(): insert newStmt = %p = %s before/after targetStmt = %p = %s \n",newStmt,newStmt->class_name().c_str(),targetStmt,targetStmt->class_name().c_str());
14529#endif
14530
14531 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14532 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14533 // ROSE_ASSERT(functionDefinition != NULL);
14534
14535 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14536 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14537 // We now have single statement true/false body for IfStmt etc
14538 // However, IfStmt::insert_child() is ambiguous and not implemented
14539 // So we make SgBasicBlock out of the single statement and
14540 // essentially call SgBasicBlock::insert_child() instead.
14541 // TODO: add test cases for If, variable, variable/struct inside if, etc
14542 // parent = ensureBasicBlockAsParent(targetStmt);
14543
14544 // must get the new scope after ensureBasicBlockAsParent ()
14545 SgScopeStatement* scope = targetStmt->get_scope();
14546 ROSE_ASSERT(scope);
14547
14548#if 0
14549 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14550 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14551#endif
14552
14553 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14554 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14555 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14556 // be to set the parent to the scope of the target instead. This would be just as correct in the general case, but also make
14557 // more sense in this special case of a SgLabelStatement.
14558 // newStmt->set_parent(targetStmt->get_parent());
14559 newStmt->set_parent(scope);
14560
14561 // DQ (11/16/2014): This function had a bug that is now fixed. It allowed a 2nd SgLableSymbol to be built when an initial one was found.
14562 // The fix was the reuse the one that was found.
14563 fixStatement(newStmt,scope);
14564
14565 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14566 // However, if this is required to be true then what about statements in
14567 // SgStatementExpression IR nodes?
14568 ROSE_ASSERT(isSgStatement(parent) != NULL);
14569
14570 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14571 // appear before the statement to be attached to the inserted statement (and marked
14572 // to appear before that statement).
14573 ROSE_ASSERT(targetStmt != NULL);
14574 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14575
14576#if 0
14577 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14578 reportNodesMarkedAsModified(scope);
14579#endif
14580
14581 // TODO refactor this portion of code into a separate function
14582 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14583 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14584 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14585 {
14586 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14587 {
14588 vector<int> captureList;
14589#if 0
14590 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14591 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14592#endif
14593 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14594 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14595 {
14596 // If the inserted statment has attached comments or CPP directives then this is gets a little
14597 // bit more comple and we don't support that at present.
14598 printf ("Warning: at present statements being inserted should not have attached comments of CPP directives (could be a problem, but comment relocation is not disabled). \n");
14599 }
14600 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14601 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14602
14603 int commentIndex = 0;
14604 AttachedPreprocessingInfoType::iterator i;
14605 for (i = comments->begin(); i != comments->end(); i++)
14606 {
14607 ROSE_ASSERT ( (*i) != NULL );
14608#if 0
14609 printf (" Attached Comment (relativePosition=%s): %s\n",
14610 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14611 (*i)->getString().c_str());
14612 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14613 (*i)->get_file_info()->display("comment/directive location");
14614#endif
14615 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14616 if ((*i)->getRelativePosition() == relativePosition)
14617 {
14618 // accumulate into list
14619 captureList.push_back(commentIndex);
14620 }
14621
14622 commentIndex++;
14623 }
14624
14625 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14626 if (captureList.empty() == false)
14627 {
14628 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14629 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14630 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14631 SgStatement* surroundingStatement = newStmt;
14632 ROSE_ASSERT(surroundingStatement != targetStmt);
14633 ROSE_ASSERT(surroundingStatement != NULL);
14634#if 0
14635 if (surroundingStatement == NULL)
14636 {
14637 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14638 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14639 }
14640#endif
14641 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14642 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14643 vector<int>::iterator j = captureList.begin();
14644 while (j != captureList.end())
14645 {
14646 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14647 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14648 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14649
14650 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14651 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14652 (*comments)[*j] = NULL;
14653
14654 j++;
14655 }
14656
14657 // Now remove each NULL entries in the comments vector.
14658 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14659 for (size_t n = 0; n < captureList.size(); n++)
14660 {
14661 AttachedPreprocessingInfoType::iterator k = comments->begin();
14662 while (k != comments->end())
14663 {
14664 // Only modify the list once per iteration over the captureList
14665 if (*k == NULL)
14666 {
14667 comments->erase(k);
14668 break;
14669 }
14670 k++;
14671 }
14672 }
14673 }
14674 }
14675 else
14676 {
14677 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14678 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14679 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14680 if (comments != NULL)
14681 {
14682 printf ("Warning: special rules appear to apply to the insertion of a SgBasicBlock which has attached comments and/or CPP directives (comment relocation disabled). \n");
14683 }
14684 }
14685 } // end if autoMovePreprocessingInfo
14686
14687
14688#if 0
14689 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14690 reportNodesMarkedAsModified(scope);
14691#endif
14692
14693 if (isSgIfStmt(parent))
14694 {
14695 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14696 {
14697 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14698 }
14699 else
14700 {
14701 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14702 {
14703 // Liao 3/2/2012
14704 // We have some choices:
14705 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14706 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14707 // Since the targetStmt will have new content inside of it, which is not the semantics of
14708 // inserting anything before/or after it.
14709 // 2) always insert a padding basic block between parent and targetStmt
14710 // and we can legally insert before/after the target statement within the
14711 // padding basic block.
14712 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14713 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14714 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14715 isSgIfStmt(parent)->set_true_body(newparent);
14716 newparent->set_parent(parent);
14717 insertStatement(targetStmt, newStmt,insertBefore);
14718 }
14719 else
14720 {
14721 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14722 {
14723 // ensureBasicBlockAsParent(targetStmt);
14724 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14725 isSgIfStmt(parent)->set_false_body(newparent);
14726 newparent->set_parent(parent);
14727 insertStatement(targetStmt, newStmt,insertBefore);
14728 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14729 }
14730 }
14731 }
14732 }
14733 else
14734 {
14735 if (isSgWhileStmt(parent))
14736 {
14737 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14738 {
14739 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14740 }
14741 else
14742 {
14743 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14744 {
14745 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14746 isSgWhileStmt(parent)->set_body(newparent);
14747 newparent->set_parent(parent);
14748 insertStatement(targetStmt, newStmt,insertBefore);
14749 // ensureBasicBlockAsParent(targetStmt);
14750 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14751 }
14752 }
14753 }
14754 else
14755 {
14756 if (isSgDoWhileStmt(parent))
14757 {
14758 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14759 {
14760 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14761 }
14762 else
14763 {
14764 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14765 {
14766 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14767 isSgDoWhileStmt(parent)->set_body(newparent);
14768 newparent->set_parent(parent);
14769 insertStatement(targetStmt, newStmt,insertBefore);
14770 // ensureBasicBlockAsParent(targetStmt);
14771 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14772 }
14773 }
14774 }
14775 else
14776 {
14777 if (isSgForStatement(parent))
14778 {
14779 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14780 {
14781 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14782 isSgForStatement(parent)->set_loop_body(newparent);
14783 newparent->set_parent(parent);
14784 insertStatement(targetStmt, newStmt,insertBefore);
14785 // ensureBasicBlockAsParent(targetStmt);
14786 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14787 }
14788 else
14789 {
14790 if (isSgForStatement(parent)->get_test()==targetStmt)
14791 {
14792 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14793 }
14794 }
14795 }
14796 else // \pp (2/24/2011) added support for UpcForAll
14797 {
14798 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14799 {
14800 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14801
14802 // \pp \todo what if !stmt_present
14803 // ROSE_ASSERT(stmt_present != NULL);
14804 insertStatement(p, newStmt, insertBefore);
14805 }
14806 else
14807 {
14808 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14809 {
14810 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14811 p->set_body(newparent);
14812 newparent->set_parent(parent);
14813 insertStatement(targetStmt, newStmt,insertBefore);
14814 }
14815 else
14816 {
14817 // It appears that all of the recursive calls are untimately calling this location.
14818 SgStatement* stmnt = isSgStatement(parent);
14819 ROSE_ASSERT(stmnt != NULL);
14820 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14821 }
14822 }
14823 }
14824 }
14825 }
14826 }
14827
14828 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14829 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14830 // this). Also since this is only operating within a single scope it is likely too specific to C
14831 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14832 // use name qualification).
14833 // update the links after insertion!
14835 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14836 {
14837 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14838 }
14839
14840#if 0
14841 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14842 reportNodesMarkedAsModified(scope);
14843#endif
14844 }
14845
14846
14847void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14848 {
14849 if (insertBefore)
14850 {
14851 for (size_t i = 0; i < newStmts.size(); ++i)
14852 {
14853 insertStatementBefore(targetStmt, newStmts[i]);
14854 }
14855 }
14856 else
14857 {
14858 for (size_t i = newStmts.size(); i > 0; --i)
14859 {
14860 insertStatementAfter(targetStmt, newStmts[i - 1]);
14861 }
14862 }
14863 }
14864
14865void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14866 {
14867 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14868 }
14869
14870void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14871 {
14872 insertStatementList(targetStmt,newStmts,false);
14873 }
14874
14877 {
14878 ROSE_ASSERT (stmt != NULL);
14879 ROSE_ASSERT (scope != NULL);
14880 // Insert to be the declaration after current declaration sequence, if any
14881 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14882 if (l_stmt)
14883 insertStatementAfter(l_stmt,stmt);
14884 else
14885 prependStatement(stmt, scope);
14886 }
14887
14889void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
14890 {
14891 ROSE_ASSERT (scope != NULL);
14892 vector <SgStatement* >::iterator iter;
14893 SgStatement* prev_stmt = NULL;
14894 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
14895 {
14896 if (iter == stmt_list.begin())
14897 {
14899 }
14900 else
14901 {
14902 ROSE_ASSERT (prev_stmt != NULL);
14903 insertStatementAfter (prev_stmt, *iter);
14904 }
14905 prev_stmt = *iter;
14906 }
14907 }
14908
14910{
14911 ROSE_ASSERT(newStmt!=NULL);
14912 ROSE_ASSERT(scope!=NULL);
14913 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14914 if (!isSgDeclarationStatement(targetStmt)) {
14915 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
14916 return;
14917 }
14918 }
14919 appendStatement(newStmt, scope);
14920}
14921
14922void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
14923{
14924 ROSE_ASSERT(scope!=NULL);
14925 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14926 if (!isSgDeclarationStatement(targetStmt)) {
14927 insertStatementListBefore(targetStmt, newStmts);
14928 return;
14929 }
14930 }
14931 appendStatementList(newStmts, scope);
14932}
14933
14934void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
14935 {
14936 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
14937 }
14938
14939void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14940 {
14941 insertStatementList(targetStmt,newStmts,true);
14942 }
14943
14944 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
14945 // special concern for lvalue, parent,
14946 // todo: warning overwriting existing operands
14948 {
14949 ROSE_ASSERT(target);
14950 ROSE_ASSERT(operand);
14951 ROSE_ASSERT(target!=operand);
14952 switch (target->variantT())
14953 {
14954 case V_SgActualArgumentExpression:
14955 isSgActualArgumentExpression(target)->set_expression(operand);
14956 break;
14957 case V_SgAsmOp:
14958 isSgAsmOp(target)->set_expression(operand);
14959 break;
14960 case V_SgSizeOfOp:
14961 isSgSizeOfOp(target)->set_operand_expr(operand);
14962 break;
14963 case V_SgTypeIdOp:
14964 isSgTypeIdOp(target)->set_operand_expr(operand);
14965 break;
14966 case V_SgVarArgOp:
14967 isSgVarArgOp(target)->set_operand_expr(operand);
14968 break;
14969 case V_SgVarArgStartOneOperandOp:
14970 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
14971 break;
14972 case V_SgAssignInitializer:
14973 isSgAssignInitializer (target)->set_operand(operand);
14974 break;
14975 default:
14976 if (isSgUnaryOp(target)!=NULL)
14977 isSgUnaryOp(target)->set_operand_i(operand);
14978 else
14979 {
14980 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
14981 <<target->class_name()<<endl;
14982 ROSE_ABORT();
14983 }
14984 }// end switch
14985 operand->set_parent(target);
14986 markLhsValues(target);
14987 }
14988
14989 // binary and SgVarArgCopyOp, SgVarArgStartOp
14991 {
14992 ROSE_ASSERT(target);
14993 ROSE_ASSERT(lhs);
14994 ROSE_ASSERT(target!=lhs);
14995 bool hasrhs = false;
14996
14997 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14998 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14999 SgBinaryOp* binary = isSgBinaryOp(target);
15000
15001 if (varargcopy!=NULL)
15002 {
15003 varargcopy->set_lhs_operand(lhs);
15004 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
15005 }
15006 else if(varargstart!=NULL)
15007 {
15008 varargstart->set_lhs_operand(lhs);
15009 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
15010 }
15011 else if(binary!=NULL)
15012 {
15013 binary->set_lhs_operand(lhs);
15014 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
15015 }
15016 else
15017 {
15018 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
15019 <<target->class_name()<<endl;
15020 ROSE_ABORT();
15021 }
15022 lhs->set_parent(target);
15023// only when both lhs and rhs are available, can we set lvalue
15024// there is assertion(rhs!=NULL) in markLhsValues()
15025 if (hasrhs)
15026 markLhsValues(target);
15027 }
15028
15030 {
15031 ROSE_ASSERT(target);
15032 ROSE_ASSERT(rhs);
15033 ROSE_ASSERT(target!=rhs);
15034 bool haslhs = false;
15035
15036 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
15037 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
15038 SgBinaryOp* binary = isSgBinaryOp(target);
15039
15040 if (varargcopy!=NULL)
15041 {
15042 varargcopy->set_rhs_operand(rhs);
15043 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
15044 }
15045 else if(varargstart!=NULL)
15046 {
15047 varargstart->set_rhs_operand(rhs);
15048 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
15049 }
15050 else if(binary!=NULL)
15051 {
15052 binary->set_rhs_operand(rhs);
15053 if( binary->get_lhs_operand()!=NULL) haslhs= true;
15054 }
15055 else
15056 {
15057 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
15058 <<target->class_name()<<endl;
15059 ROSE_ABORT();
15060 }
15061 rhs->set_parent(target);
15062// only when both lhs and rhs are available, can we set lvalue
15063 if (haslhs)
15064 markLhsValues(target);
15065 }
15066
15067// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
15068void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
15069 {
15070 // This support makes use of the new SgDirectory IR node. It causes the unparser to
15071 // generate a subdirectory and unparse the file into the subdirectory. It works
15072 // by internally calling the system function "system()" to call "mkdir directoryName"
15073 // and then chdir()" to change the current directory. These steps are handled by the
15074 // unparser.
15075
15076 // This function just does the transformation to insert a SgDirectory IR node between
15077 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
15078
15079 // Add a directory and unparse the code (to the new directory)
15080 SgDirectory* directory = new SgDirectory(directoryName);
15081
15082 SgFileList* parentFileList = isSgFileList(file->get_parent());
15083 ROSE_ASSERT(parentFileList != NULL);
15084 directory->set_parent(file->get_parent());
15085
15086 SgProject* project = NULL;
15087 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
15088
15089 if (parentDirectory != NULL)
15090 {
15091 // Add a directory to the list in the SgDirectory node.
15092 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
15093
15094 // Erase the reference to the file in the project's file list.
15095 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
15096 }
15097 else
15098 {
15099 project = isSgProject(parentFileList->get_parent());
15100 ROSE_ASSERT(project != NULL);
15101
15102 // Add a directory to the list in the SgProject node.
15103 project->get_directoryList()->get_listOfDirectories().push_back(directory);
15104
15105 // Erase the reference to the file in the project's file list.
15106 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
15107 }
15108
15109 // Put the file into the new directory.
15110 directory->get_fileList()->get_listOfFiles().push_back(file);
15111
15112 // Erase the reference to the file in the project's file list.
15113 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
15114
15115 file->set_parent(directory);
15116}
15117
15118
15119//------------------------- AST repair----------------------------
15120//----------------------------------------------------------------
15122 {
15123 ROSE_ASSERT(structDecl != NULL);
15124 ROSE_ASSERT(scope != NULL);
15125 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
15126 ROSE_ASSERT(nondefdecl != NULL);
15127
15128 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
15129 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
15130 // ROSE_ASSERT(defdecl != NULL);
15131
15132 // Liao, 9/2/2009
15133 // fixup missing scope when bottomup AST building is used
15134 if (structDecl->get_scope() == NULL)
15135 structDecl->set_scope(scope);
15136 if (nondefdecl->get_scope() == NULL)
15137 nondefdecl->set_scope(scope);
15138
15139#if 0
15140 if (structDecl->get_parent() == NULL)
15141 structDecl->set_parent(scope);
15142 if (nondefdecl->get_parent() == NULL)
15143 nondefdecl->set_parent(scope);
15144#else
15145 // printf ("*** WARNING: In SageInterface::fixStructDeclaration(): Commented out the setting of the parent (of input class declaration and the nondefining declaration) to be the same as the scope (set only if NULL) \n");
15146
15147 // DQ (7/21/2012): Can we assert this here? NO!
15148 // ROSE_ASSERT(structDecl->get_parent() == NULL);
15149 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
15150#endif
15151
15152 SgName name = structDecl->get_name();
15153
15154 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15155 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15156 // But symbols are associated with nondefining declarations whenever possible
15157 // and AST consistent check will check the nondefining declarations first
15158 // Liao, 9/2/2009
15159 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15160 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15161
15162 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15163 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15164 // ROSE_ASSERT(mysymbol != NULL);
15165
15166 if (mysymbol == NULL)
15167 {
15168 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15169
15170 // DQ (12/3/2011): This will be an error for C++ if the scope of the statment is different from the scope where it is located structurally...
15171 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15172 ROSE_ASSERT(structDecl->get_scope() != NULL);
15173
15174 if (scope == structDecl->get_scope())
15175 {
15176 mysymbol = new SgClassSymbol(nondefdecl);
15177 ROSE_ASSERT(mysymbol);
15178
15179 // I need to check the rest of these functions.
15180 printf ("############## DANGER:DANGER:DANGER ################\n");
15181
15182 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15183 scope->insert_symbol(name, mysymbol);
15184
15185 // ROSE_ASSERT(defdecl != NULL);
15186 if (defdecl)
15187 defdecl->set_scope(scope);
15188 nondefdecl->set_scope(scope);
15189
15190 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15191#if 0
15192 if (defdecl)
15193 defdecl->set_parent(scope);
15194 nondefdecl->set_parent(scope);
15195#endif
15196 }
15197 else
15198 {
15199 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15200 }
15201 }
15202
15203 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15204 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15205
15206 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15207 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15208
15209 // DQ (9/4/2012): This should be a SgClassType IR node.
15210 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15211
15212 // fixup SgClassType, which is associated with the first non-defining declaration only
15213 // and the other declarations share it.
15214 if (nondefdecl->get_type() == NULL)
15215 {
15216 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15217 }
15218 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15219
15220 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15221 if (defdecl != NULL)
15222 {
15223 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15224 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15225
15226 // DQ (9/4/2012): This should be a SgClassType IR node.
15227 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15228 }
15229
15230 // ROSE_ASSERT(defdecl != NULL);
15231 if (defdecl != NULL)
15232 {
15233 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15234 ROSE_ASSERT(defdecl->get_type() != NULL);
15235 if (defdecl->get_type() != nondefdecl->get_type())
15236 {
15237 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15238 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15239 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15240 if (namedType_definingDecl != NULL)
15241 {
15242 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15243 }
15244 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15245 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15246 if (namedType_nondefiningDecl != NULL)
15247 {
15248 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15249 }
15250 }
15251 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15252 }
15253 }
15254
15255
15257 {
15258 fixStructDeclaration(classDecl,scope);
15259 }
15260
15261
15263 {
15264 ROSE_ASSERT(structDecl);
15265 ROSE_ASSERT(scope);
15266 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15267 ROSE_ASSERT(nondefdecl);
15268 // Liao, 9/2/2009
15269 // fixup missing scope when bottomup AST building is used
15270 if (structDecl->get_parent() == NULL)
15271 structDecl->set_parent(scope);
15272 if (nondefdecl->get_parent() == NULL)
15273 nondefdecl->set_parent(scope);
15274
15275 // tps : (09/03/2009) Namespace should not have a scope
15276 /*
15277 if (structDecl->get_scope() == NULL)
15278 structDecl->set_scope(scope);
15279 if (nondefdecl->get_scope() == NULL)
15280 nondefdecl->set_scope(scope);
15281 */
15282
15283 SgName name= structDecl->get_name();
15284 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15285 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15286 if (mysymbol==NULL)
15287 {
15288 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15289 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15290 if (scope == structDecl->get_scope())
15291 {
15292 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15293 ROSE_ASSERT(mysymbol);
15294
15295 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15296 scope->insert_symbol(name, mysymbol);
15297
15298 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15299 ROSE_ASSERT(defdecl);
15300 defdecl->set_scope(scope);
15301 nondefdecl->set_scope(scope);
15302
15303 defdecl->set_parent(scope);
15304 nondefdecl->set_parent(scope);
15305 }
15306 }
15307 }
15308
15309#define DEBUG__SageInterface__fixVariableDeclaration 0
15310
15312 {
15313 ROSE_ASSERT(varDecl != NULL);
15314 ROSE_ASSERT(scope != NULL);
15315
15316 SgInitializedNamePtrList namelist = varDecl->get_variables();
15317 SgTemplateVariableInstantiation * tplinst = isSgTemplateVariableInstantiation(varDecl);
15318
15319 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15320
15321#if DEBUG__SageInterface__fixVariableDeclaration
15322 printf ("In SageInterface::fixVariableDeclaration():\n");
15323 printf (" varDecl = %p scope = %p = %s \n", varDecl);
15324 printf (" scope = %p : %s \n", scope, scope->class_name().c_str());
15325#endif
15326
15327 ROSE_ASSERT(namelist.size() > 0);
15328
15329 SgInitializedNamePtrList::iterator i;
15330 for (i = namelist.begin(); i != namelist.end(); i++)
15331 {
15332 SgInitializedName *initName = *i;
15333 ROSE_ASSERT(initName != NULL);
15334#if DEBUG__SageInterface__fixVariableDeclaration
15335 printf (" initName = %p\n", initName);
15336 printf (" initName->get_scope() = %p : %s\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15337#endif
15338
15339 SgName name = initName->get_name();
15340#if DEBUG__SageInterface__fixVariableDeclaration
15341 printf (" name = %s\n", name.str());
15342#endif
15343 if (tplinst) {
15344 name = appendTemplateArgumentsToName(name, tplinst->get_templateArguments());
15345 }
15346#if DEBUG__SageInterface__fixVariableDeclaration
15347 printf (" name = %s\n", name.str());
15348#endif
15349
15350 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15351 // and be using name qualification, so might not be associated with the current scope.
15352 SgScopeStatement* requiredScope = scope;
15353 SgScopeStatement* preAssociatedScope = initName->get_scope();
15354 if (preAssociatedScope != NULL) {
15355 requiredScope = preAssociatedScope;
15356 }
15357
15358 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15359 initName->set_scope(requiredScope);
15360 if (topScopeStack() != NULL) {
15361 varDecl->set_parent(topScopeStack());
15362 ROSE_ASSERT(varDecl->get_parent() != NULL);
15363 }
15364 ROSE_ASSERT(requiredScope != NULL);
15365 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15366#if DEBUG__SageInterface__fixVariableDeclaration
15367 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15368#endif
15369 if (varSymbol == NULL) {
15370 if (scope == initName->get_scope()) {
15371 if (isSgTemplateVariableDeclaration(varDecl)) {
15372 varSymbol = new SgTemplateVariableSymbol(initName);
15373 } else {
15374 varSymbol = new SgVariableSymbol(initName);
15375 }
15376 ROSE_ASSERT(varSymbol);
15377 scope->insert_symbol(name, varSymbol);
15378 }
15379 } else {
15380 SgInitializedName* prev_decl = varSymbol->get_declaration();
15381 ROSE_ASSERT(prev_decl);
15382 if (initName != prev_decl) {
15383 initName->set_prev_decl_item(prev_decl);
15384 }
15385 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15386 }
15387#if DEBUG__SageInterface__fixVariableDeclaration
15388 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15389#endif
15390 } //end for
15391
15392 // Liao 12/8/2010
15393 // For Fortran, a common statement may refer to a variable which is declared later.
15394 // In this case, a fake symbol is used for that variable reference.
15395 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15397 {
15398 fixVariableReferences(scope);
15399 }
15400 }
15401
15402int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15403{
15404 ROSE_ASSERT(root);
15405 int counter=0;
15406 Rose_STL_Container<SgNode*> varList;
15407
15408 SgVarRefExp* varRef=NULL;
15409 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15410 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15411 {
15412 varRef= isSgVarRefExp(*i);
15413 ROSE_ASSERT(varRef->get_symbol());
15414 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15415
15416 ROSE_ASSERT (initname != NULL);
15417 if (initname->get_type()==SgTypeUnknown::createType())
15418 {
15419 SgName varName=initname->get_name();
15420 SgSymbol* realSymbol = NULL;
15421
15422#if 1
15423 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15424 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15425 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15426 // operators, and static members using :: operators.
15427 //
15428 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15429 {
15430 if (varRef == arrowExp->get_rhs_operand_i())
15431 {
15432 // make sure the lhs operand has been fixed
15433 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15434 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15435 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15436 SgPointerType* ptrType = isSgPointerType(lhs_type);
15437 ROSE_ASSERT(ptrType);
15438 SgClassType* clsType = isSgClassType(ptrType->get_base_type()-> stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE));
15439 ROSE_ASSERT(clsType);
15440 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15441 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15442 ROSE_ASSERT(decl);
15443
15444 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15445 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15446 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15447 }
15448 else
15449 {
15450 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15451 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15452 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15453 }
15454 }
15455 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15456 {
15457 if (varRef == dotExp->get_rhs_operand_i())
15458 {
15459 // make sure the lhs operand has been fixed
15460 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15461
15462 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15463 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15464 SgClassType* clsType = isSgClassType(lhs_type);
15465 ROSE_ASSERT(clsType);
15466 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15467 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15468 ROSE_ASSERT(decl);
15469
15470 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15471 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15472 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15473 }
15474 else
15475 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15476 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15477 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15478 }
15479 else
15480#endif
15481 {
15482 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15483 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15484 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15485 }
15486
15487 // should find a real symbol at this final fixing stage!
15488 // This function can be called any time, not just final fixing stage
15489 if (realSymbol==NULL)
15490 {
15491 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15492 //ROSE_ASSERT(realSymbol);
15493 }
15494 else {
15495 // release placeholder initname and symbol
15496 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15497#if 0
15498 // CH (5/12/2010):
15499 // To delete a symbol node, first check if there is any node in memory
15500 // pool which points to this symbol node. Only if no such node exists,
15501 // this symbol together with its initialized name can be deleted.
15502 //
15503 bool toDelete = true;
15504
15505 SgSymbol* symbolToDelete = varRef->get_symbol();
15506 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15507 counter ++;
15508
15509 if (varList.empty())
15510 {
15511 VariantVector vv(V_SgVarRefExp);
15512 varList = NodeQuery::queryMemoryPool(vv);
15513 }
15514
15515 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15516 i != varList.end(); ++i)
15517 {
15518 if (SgVarRefExp* var = isSgVarRefExp(*i))
15519 {
15520 if (var->get_symbol() == symbolToDelete)
15521 {
15522 toDelete = false;
15523 break;
15524 }
15525 }
15526 }
15527 if (toDelete)
15528 {
15529 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15530 delete symbolToDelete;
15531 }
15532
15533#else
15534
15535 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15536 // which point to them. We will delay this clear just before AstTests.
15537#if 0
15538 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15539 delete (varRef->get_symbol());
15540#endif
15541
15542 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15543 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15544 counter ++;
15545#endif
15546 }
15547 }
15548 } // end for
15549 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15550 if (cleanUnusedSymbols)
15552 return counter;
15553}
15554
15556{
15557 Rose_STL_Container<SgNode*> symbolList;
15558 VariantVector sym_vv(V_SgVariableSymbol);
15559 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15560
15561 Rose_STL_Container<SgNode*> varList;
15562 VariantVector var_vv(V_SgVarRefExp);
15563 //varList = NodeQuery::queryMemoryPool(var_vv);
15564 if (root != NULL)
15565 {
15566 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15567 }
15568
15569 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15570 i != symbolList.end(); ++i)
15571 {
15572 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15573 ROSE_ASSERT(symbolToDelete);
15574 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15575 continue;
15576 // symbol with a declaration of SgTypeUnknown will be deleted
15577 bool toDelete = true;
15578
15579 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15580 {
15581 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15582 j != varList.end(); ++j)
15583 {
15584 SgVarRefExp* var = isSgVarRefExp(*j);
15585 ROSE_ASSERT(var);
15586
15587 if (var->get_symbol() == symbolToDelete)
15588 {
15589 toDelete = false;
15590 break;
15591 }
15592 }
15593 }
15594
15595 if (toDelete)
15596 {
15597#if 0
15598 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15599 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15600#endif
15601 delete symbolToDelete->get_declaration();
15602 delete symbolToDelete;
15603 }
15604 }
15605}
15606
15607
15609/*
15610 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15611 */
15613 {
15614 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15615 ROSE_ASSERT(label_stmt);
15616 SgName name = label_stmt->get_label();
15617
15618 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15619 const bool symbolAtFunctionLevel = !is_Ada_language();
15620 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15621 : scope;
15622
15623 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15624 if (isSgFunctionDefinition(scope) != nullptr)
15625 {
15626 ASSERT_not_null(label_scope);
15627 }
15628
15629 if (label_scope) //Should we assert this instead? No for bottom up AST building
15630 {
15631 label_stmt->set_scope(label_scope);
15632 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15633
15634 if (lsymbol == nullptr)
15635 {
15636 // SgLabelStatement should always be in the function scope
15637 // PP (07/18/23): in Ada symbols should be at the innermost scope
15638 lsymbol= new SgLabelSymbol(label_stmt);
15639 ASSERT_not_null(lsymbol);
15640 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15641 }
15642 }
15643 }
15644
15645
15647//efExp are created transparently as needed.
15649 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15650 {
15651 ROSE_ASSERT (stmt != NULL);
15652 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15653
15654 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15655 if (label_scope == NULL)
15656 {
15657 label_scope = getEnclosingFunctionDefinition(stmt);
15658 }
15659 ROSE_ASSERT (label_scope != NULL);
15660 SgName label_name(StringUtility::numberToString(label_value));
15661 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15662 if (symbol == NULL)
15663 {
15664 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15665 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15666 // symbol = new SgLabelSymbol(NULL);
15667 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15668 ROSE_ASSERT(symbol != NULL);
15669 symbol->set_fortran_statement(stmt);
15670 symbol->set_numeric_label_value(label_value);
15671 label_scope->insert_symbol(label_name,symbol);
15672 }
15673 else
15674 {
15675 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15676 ROSE_ASSERT (false);
15677 }
15678
15679 // SgLabelRefExp
15680 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15681 ref_exp->set_parent(stmt);
15682
15683 switch(label_type)
15684 {
15685 case SgLabelSymbol::e_start_label_type:
15686 {
15687 stmt->set_numeric_label(ref_exp);
15688 break;
15689 }
15690 case SgLabelSymbol::e_end_label_type:
15691 {
15692 stmt->set_end_numeric_label(ref_exp);
15693 break;
15694 }
15695 default:
15696 {
15697 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15698 ROSE_ABORT(); // NOT IMPLEMENTED
15699 }
15700 }
15701
15702 }
15703
15704
15707{
15708 int result =10;
15709 ROSE_ASSERT (func_def != NULL);
15710 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15711 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15712
15713 // find the max label value, +10 to be the suggested next label value
15714 std::set<SgNode*>::iterator iter ;
15715 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15716 {
15717 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15718 if (l_symbol)
15719 {
15720 int cur_val = l_symbol->get_numeric_label_value();
15721 if (result <=cur_val)
15722 result = cur_val +10;
15723 }
15724 }
15725
15726 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15727 return result;
15728}
15729
15731/*
15732 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15733 */
15735 {
15736 // DQ (3/5/2012): Added test.
15737 ROSE_ASSERT(scope != NULL);
15738
15739 // fix function type table's parent edge
15740 // Liao 5/4/2010
15742 ROSE_ASSERT(fTable != NULL);
15743
15744 if (fTable->get_parent() == NULL)
15745 {
15746 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15747 // fTable->set_parent(getGlobalScope(scope));
15748#if 0
15749 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15750#endif
15751 fTable->set_parent(getGlobalScope(scope));
15752 }
15753
15754#if 0
15755 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15756#endif
15757
15758 // Liao 4/23/2010, Fix function symbol
15759 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15760 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15761 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15762 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15763 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15764 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15765 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15766 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15767
15768 if (tmfunc != NULL)
15769 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15770 else if (mfunc != NULL)
15771 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15772 else if (tfunc != NULL)
15773 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15774 else if (procfunc != NULL)
15775 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15776 else if (progfunc != NULL)
15777 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15778 else if (func != NULL)
15779 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15780 else ROSE_ABORT();
15781
15782#if 0
15783 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15784 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15785#endif
15786
15787 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15788 // It is an error to put the symbol for a function into the current scope if the function's scope
15789 // is explicitly set to be different. So this should be allowed only if the function's scope is
15790 // not explicitly set, or if the scopes match. This is an example of something different for C++
15791 // than for C or other simpler languages.
15792 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15793 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15794 {
15795#if 0
15796 printf ("Looking up the function symbol using name = %s and type = %p = %s \n",func->get_name().str(),func->get_type(),func->get_type()->class_name().c_str());
15797#endif
15798 SgFunctionSymbol* func_symbol = NULL;
15799
15800 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15801 // In this case these are unavailable from this point.
15802 if (tmfunc != NULL)
15803 {
15804 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15805 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15806 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15807 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15808 }
15809 else if (mfunc != NULL)
15810 {
15811 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15812 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15813 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15814 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15815 }
15816 else if (tfunc != NULL)
15817 {
15818 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15819#if 0
15820 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15821#endif
15822 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15823 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15824 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15825 }
15826 else if (procfunc != NULL)
15827 {
15828#if 0
15829 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15830#endif
15831 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15832 assert(func_symbol != NULL);
15833 }
15834 else if (progfunc != NULL)
15835 {
15836 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15837 assert(func_symbol != NULL);
15838 }
15839 else if (func != NULL)
15840 {
15841#if 0
15842 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15843#endif
15844 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15845 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15846 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15847 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15848
15849 // DQ (8/23/2013): Adding support for when the symbol is not present. This can happen when building a new function as a copy of an existing
15850 // function the symantics of the copy is that it will not add the symbol (since it does not know the scope). So this function is the first
15851 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15852 if (func_symbol == NULL)
15853 {
15854 // scope->print_symboltable("In SageInterface::fixStatement()");
15855 func_symbol = new SgFunctionSymbol(func);
15856 scope->insert_symbol(func->get_name(), func_symbol);
15857 }
15858 }
15859 else
15860 {
15861 ROSE_ABORT();
15862 }
15863#if 0
15864 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15865#endif
15866 assert(func_symbol != NULL);
15867 }
15868 }
15869
15871/*
15872 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15873 */
15875 {
15876 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15877 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15878 }
15879
15880
15883 {
15884 // fix symbol table
15885 if (isSgVariableDeclaration(stmt))
15886 {
15887 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
15888 }
15889 else if (isStructDeclaration(stmt))
15890 {
15891 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
15892 ROSE_ASSERT(classDeclaration != nullptr);
15893 fixStructDeclaration(classDeclaration,scope);
15894 }
15895 else if (isSgClassDeclaration(stmt))
15896 {
15897 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
15898 }
15899 else if (isSgLabelStatement(stmt))
15900 {
15901 fixLabelStatement(isSgLabelStatement(stmt),scope);
15902 }
15903 else if (isSgFunctionDeclaration(stmt))
15904 {
15905#if 1
15906 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
15907#else
15908 // fix function type table's parent edge
15909 // Liao 5/4/2010
15911 ROSE_ASSERT(fTable);
15912 if (fTable->get_parent() == NULL)
15913 fTable->set_parent(getGlobalScope(scope));
15914
15915 // Liao 4/23/2010, Fix function symbol
15916 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15917 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
15918 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
15919
15920 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15921 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15922
15923 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15924 // It is an error to put the symbol for a function into the current scope if the function's scope
15925 // is explicitly set to be different. So this should be allowed only if the function's scope is
15926 // not explicitly set, or if the scopes match. This is an example of something different for C++
15927 // than for C or other simpler languages.
15928 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15929 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15930 {
15931#if 0
15932 printf ("Looking up the function symbol using name = %s and type = %p = %s \n",func->get_name().str(),func->get_type(),func->get_type()->class_name().c_str());
15933#endif
15934 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
15935
15936 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15937 if (func_symbol == NULL)
15938 {
15939 // DQ (12/3/2011): Added support for C++ member functions.
15940 // func_symbol = new SgFunctionSymbol (func);
15941 if (mfunc != NULL)
15942 {
15943 func_symbol = new SgMemberFunctionSymbol (func);
15944 }
15945 else
15946 {
15947 func_symbol = new SgFunctionSymbol (func);
15948 }
15949 ROSE_ASSERT (func_symbol != NULL);
15950
15951 scope->insert_symbol(func->get_name(), func_symbol);
15952 }
15953 else
15954 {
15955 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
15956 }
15957 }
15958#if 0
15959 // Fix local symbol, a symbol directly refer to this function declaration
15960 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
15961 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
15962 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
15963 if (local_symbol == NULL) //
15964 {
15965 if (func->get_definingDeclaration() == NULL) // prototype function
15966 {
15967 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
15968 if (func != src_func )
15969 {
15970 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
15971 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
15972 }
15973 }
15974 }
15975#endif
15976#endif
15977 }
15978 else if (isSgTemplateDeclaration(stmt) != NULL)
15979 {
15980 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
15981 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
15982 }
15983
15984#if 0
15985 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
15986 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
15987 // This this code is very dangerous.
15988
15989 // fix scope pointer for statements explicitly storing scope pointer
15990 switch (stmt->variantT())
15991 {
15992 // The case of SgLabelStatement should maybe be included.
15993 case V_SgEnumDeclaration:
15994 case V_SgTemplateDeclaration:
15995 case V_SgTypedefDeclaration:
15996 case V_SgFunctionDeclaration:
15997 case V_SgMemberFunctionDeclaration:
15998 case V_SgTemplateInstantiationFunctionDecl:
15999 {
16000 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
16001 // already been set or we can let it default to the current scope where it si located structurally.
16002 // stmt->set_scope(scope);
16003 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
16004 {
16005 stmt->set_scope(scope);
16006 }
16007 break;
16008 }
16009
16010 default:
16011 {
16012 // debugging support...
16013 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
16014 ROSE_ASSERT(stmt->hasExplicitScope() == false);
16015#if 0
16016 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
16017 ROSE_ABORT();
16018#endif
16019 break;
16020 }
16021 }
16022#else
16023 // If the scoep has to be set and it has not yet been set, then set it directly.
16024 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
16025 {
16026 stmt->set_scope(scope);
16027 }
16028#endif
16029 }
16030
16031
16044 {
16045 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
16046 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
16047
16048 ROSE_ASSERT(func != NULL && scope != NULL);
16049
16050 ROSE_ASSERT(func != NULL);
16051 ROSE_ASSERT(scope != NULL);
16052
16053 SgStatementPtrList stmtList, sameFuncList;
16054
16055 // SgFunctionDeclaration* first_nondef = NULL;
16056 // Some annoying part of scope
16057 if (scope->containsOnlyDeclarations())
16058 {
16059 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
16060 SgDeclarationStatementPtrList::iterator i;
16061 for (i=declList.begin();i!=declList.end();i++)
16062 stmtList.push_back(*i);
16063 }
16064 else
16065 {
16066 stmtList = scope->getStatementList();
16067 }
16068
16069 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
16070 if (firstNondefiningFunctionDeclaration != NULL)
16071 {
16072 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
16073 // then use it (unless we want to handle where it might be set wrong).
16074#if 0
16075 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
16076#endif
16077 }
16078
16079 // DQ (3/12/2012): Added assertion
16080 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
16081 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
16082
16083 // DQ (5/25/2013): This test fails for the astInterface test: buildStructDeclaration.C, since this is a new test, make it a warning for now.
16084 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
16085 {
16086 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
16087 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
16089 }
16090 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
16091
16092#if 0
16093 // It would be better to find the first non-defining declaration via the symbol.
16094 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
16095 if (functionSymbol != NULL)
16096 {
16097 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
16098 }
16099 else
16100 {
16101 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
16102 }
16103#endif
16104
16105 // Find the same function declaration list, including func itself
16106 SgStatementPtrList::iterator j;
16107 for (j = stmtList.begin(); j != stmtList.end(); j++)
16108 {
16109 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16110 if (func_decl != NULL)
16111 {
16112 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
16113 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
16114 if (isSameFunction(func_decl, func))
16115 {
16116 // Assume all defining functions have definingdeclaration links set properly already!!
16117 sameFuncList.push_back(func_decl);
16118 }
16119 }
16120 }
16121
16122#if 0
16123 printf ("func = %p \n",func);
16124 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
16125#endif
16126
16127 ROSE_ASSERT(func != NULL);
16128
16129 if (func->get_definingDeclaration() == func)
16130 {
16131 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16132 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
16133 }
16134 else
16135 {
16136 ROSE_ASSERT(func != NULL);
16137
16138 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16139 ROSE_ASSERT(sameFuncList.empty() == false);
16140
16141 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16142 {
16143 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16144 {
16145 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16146#if 0
16147 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16148#endif
16149 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16150 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16151 if (func_decl != func)
16152 {
16153 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16154 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16155 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16156 {
16157#if 0
16158 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16159#endif
16160 func_decl->set_firstNondefiningDeclaration(func);
16161 }
16162 }
16163 }
16164 }
16165 else // is a following nondefining declaration, grab any other's first nondefining link then
16166 {
16167#if 0
16168 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16169#endif
16170 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16171 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16172 if (func->get_firstNondefiningDeclaration() == NULL)
16173 {
16174#if 0
16175 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16176#endif
16177 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16178 }
16179 }
16180 }
16181 }
16182
16183PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16184 assert(source_file != NULL);
16185 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16186
16187 SgGlobal * global_scope = source_file->get_globalScope();
16188
16189 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16190 ROSE_ASSERT(result);
16191
16192 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16193 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16194 // when multiple files are used on the command line.
16195 result->get_file_info()->setTransformation();
16196
16197 global_scope->addToAttachedPreprocessingInfo(result, position);
16198
16199 return result;
16200}
16201
16202//---------------------------------------------------------------
16204 SgLocatedNode* target, const string& content,
16205 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16206 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16207 {
16208 ASSERT_not_null(target); //dangling comment is not allowed
16209
16210 PreprocessingInfo* result = NULL;
16211 PreprocessingInfo::DirectiveType mytype=dtype;
16212 string comment;
16213
16214 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16215 // DQ (5/5/2010): infer comment type from target's language
16216 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16217 {
16218 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16219 if (is_C_language() || is_C99_language())
16220 {
16221 // Comment = "/* "+ content + " */";
16222 mytype = PreprocessingInfo::C_StyleComment;
16223 }
16224 else if (is_Cxx_language() || is_Java_language())
16225 {
16226 // Comment = "// "+ content;
16227 mytype = PreprocessingInfo::CplusplusStyleComment;
16228 }
16229 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16230 {
16231 // Comment = "! "+ content;
16232 mytype = PreprocessingInfo::F90StyleComment;
16233 }
16234 else if (is_Ada_language())
16235 {
16236 // Comment = "-- " + content;
16237 mytype = PreprocessingInfo::AdaStyleComment;
16238 }
16239 else if (is_Jovial_language())
16240 {
16241 // Comment = "% " + content + " %";
16242 mytype = PreprocessingInfo::JovialStyleComment;
16243 }
16244 else
16245 {
16246 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16247 ROSE_ABORT();
16248 }
16249 }
16250
16251 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16252 bool resetPositionInfo = false;
16253 switch (mytype)
16254 {
16255 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16256 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16257 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16258 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16259 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16260 case PreprocessingInfo::JovialStyleComment:
16261 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16262 comment = content;
16263 break;
16264 case PreprocessingInfo::CpreprocessorLineDeclaration:
16265 comment = "#myline " + content;
16266 mytype = PreprocessingInfo::CplusplusStyleComment;
16267 resetPositionInfo = true;
16268 break;
16269 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16270 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16271 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16272 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16273
16274 default:
16275 {
16276 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16277 ROSE_ABORT();
16278 }
16279 }
16280
16281 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16282
16283 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16284 if (resetPositionInfo == true)
16285 {
16286 // Call the Sg_File_Info::operator=() member function.
16287 *(result->get_file_info()) = *(target->get_file_info());
16288 }
16289 else
16290 {
16291 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16292 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16293 // when multiple files are used on the command line.
16294 result->get_file_info()->setTransformation();
16295 }
16296
16297 ASSERT_not_null(result);
16298 target->addToAttachedPreprocessingInfo(result);
16299 return result;
16300 }
16301
16302void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16303 PreprocessingInfo * if_macro = new PreprocessingInfo(
16304 PreprocessingInfo::CpreprocessorIfDeclaration,
16305 "#if " + guard,
16306 "transformation-generated", 0, 0, 0,
16307 PreprocessingInfo::before
16308 );
16309 target->addToAttachedPreprocessingInfo(if_macro);
16310
16311 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16312 PreprocessingInfo::CpreprocessorEndifDeclaration,
16313 "#endif",
16314 "transformation-generated", 0, 0, 0,
16315 PreprocessingInfo::after
16316 );
16317 target->addToAttachedPreprocessingInfo(endif_macro);
16318
16319// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16320// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16321// when multiple files are used on the command line.
16322 if_macro->get_file_info()->setTransformation();
16323 endif_macro->get_file_info()->setTransformation();
16324}
16325
16326// internal hash table to cache the results: fileHeaderDict[file][header-key]
16327// header-key:
16328// system header : <header.h>
16329// non-system headers : "header.h"
16330static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16332PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16333{
16334 string header_key;
16335 if (isSystemHeader)
16336 header_key="<"+header_file_name+">";
16337 else
16338 header_key="\""+header_file_name+"\"";
16339
16340 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16341 return fileHeaderDict[source_file][header_key];
16342
16343 vector<SgLocatedNode*> candidates;
16344 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16345 // check SgGlobal
16346 SgGlobal* global= source_file -> get_globalScope();
16347
16348 candidates.push_back(global);
16349
16350 //check declarations within the global scope
16351 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16352 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16353 candidates.push_back(*iter);
16354
16355 bool found = false;
16356 for (size_t ci=0; ci<candidates.size(); ci++)
16357 {
16358 SgLocatedNode* locatedNode= candidates[ci];
16359 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16360
16361 if (comments == NULL) continue;
16362 AttachedPreprocessingInfoType::iterator i;
16363 for (i = comments->begin (); i != comments->end (); i++)
16364 {
16365 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16366 string content = (*i)->getString ();
16367 if (content.find(header_key) != string::npos)
16368 {
16369 fileHeaderDict[source_file][header_key] = *i;
16370 found =true;
16371 break;
16372 }
16373
16374 } // each comment
16375
16376 if (found) break;
16377 } // each node
16378
16379 if (found)
16380 return fileHeaderDict[source_file][header_key];
16381 return NULL;
16382}
16383
16385SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16386 {
16387 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16388 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16389 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16390 bool supportTokenUnparsing = false;
16391
16392 assert(source_file != NULL);
16393 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16394
16395 SgGlobal * global_scope = source_file->get_globalScope();
16396
16397 string content;
16398 if (isSystemHeader)
16399 content = "#include <" + header_file_name + "> \n";
16400 else
16401 content = "#include \"" + header_file_name + "\" \n";
16402
16403 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16404 ROSE_ASSERT(result);
16405
16406 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16407 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16408 // when multiple files are used on the command line.
16409 result->get_file_info()->setTransformation();
16410
16411 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16412 supportTokenUnparsing = source_file->get_unparse_tokens();
16413 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16414
16415#if 0
16416 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16417 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16418 printf ("source_file = %p \n",source_file);
16419 printf ("global_scope = %p \n",global_scope);
16420#endif
16421#if 0
16422 printf ("Exiting as a test! \n");
16423 ROSE_ABORT();
16424#endif
16425
16426 // global_scope->addToAttachedPreprocessingInfo(result, position);
16427 if (supportTokenUnparsing == false)
16428 {
16429 global_scope->addToAttachedPreprocessingInfo(result, position);
16430 }
16431 else
16432 {
16433 // global_scope->prepend_statement(null_statement);
16434 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16435
16436 if (supportUnparseHeaders == true)
16437 {
16438 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16439 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16440#if 0
16441 printf ("physical_file_id = %d \n",physical_file_id);
16442#endif
16443 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16444 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16445#if 0
16446 printf ("Exiting as a test! \n");
16447 ROSE_ABORT();
16448#endif
16449 }
16450
16451 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16452
16453 global_scope->prepend_statement(emptyDeclaration);
16454 }
16455
16456#if 0
16457 printf ("Exiting as a test! \n");
16458 ROSE_ASSERT(false);
16459#endif
16460
16461 return result;
16462 }
16463
16464PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16465 {
16466 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16467 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16468 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16469 bool supportTokenUnparsing = false;
16470
16471 // DQ (8/12/2020): This is a compiler warning.
16472 // bool successful = false;
16473
16474#if 0
16475 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16476 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16477#endif
16478
16479 if (scope == NULL)
16481
16482 ROSE_ASSERT(scope);
16483
16484 SgGlobal* globalScope = getGlobalScope(scope);
16485 ROSE_ASSERT(globalScope != NULL);
16486
16487 // To support inserting a header file into a header file, we need this srcScope to indicate the src file in which to insert the header
16488 // if the input scope is within a header file,
16489 // its global scope will jump to a .cpp file. Later looping will not find a match.
16490 SgScopeStatement* srcScope = globalScope;
16491 PreprocessingInfo* result=NULL;
16492 string content;
16493 if (isSystemHeader)
16494 content = "#include <" + filename + "> \n";
16495 else
16496 content = "#include \"" + filename + "\" \n";
16497
16498 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16499 // whitespace around the statement has been modified. This will trigger the unparser to output
16500 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16501 // file requires this support else the original token stream will not have the added header file.
16502
16503 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16504 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16505 ROSE_ASSERT(sourceFile != NULL);
16506
16507 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16508
16509 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16510 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16511 if (supportUnparseHeaders)
16512 {
16513 string filename= scope->get_file_info()->get_filename();
16514 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16515
16516 // vector.tcc: This is an internal header file, included by other library headers
16517 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16518 srcScope = scope;
16519 }
16520
16521#if 0
16522 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16523 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16524 printf ("sourceFile = %p \n",sourceFile);
16525 printf ("globalScope = %p \n",globalScope);
16526#endif
16527#if 0
16528 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16529#endif
16530#if 0
16531 printf ("Exiting as a test! \n");
16532 ROSE_ABORT();
16533#endif
16534
16535 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16536
16537#if 0
16538 printf ("stmtList.size() = %zu \n",stmtList.size());
16539#endif
16540
16541 if (stmtList.size() > 0) // the source file is not empty
16542 {
16543 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16544 {
16545 // must have this judgement, otherwise wrong file will be modified!
16546 // It could also be the transformation generated statements with #include attached
16547 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16548 {
16549 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16550 ROSE_ASSERT(result != NULL);
16551#if 0
16552 printf ("Building a PreprocessingInfo: result = %p \n",result);
16553#endif
16554 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16555 // add to the last position
16556 // TODO: support to add to the first,
16557 // TODO: support fine positioning with #include directives
16558 // (*j)->addToAttachedPreprocessingInfo(result,position);
16559
16560 if (supportTokenUnparsing == false)
16561 {
16562 (*j)->addToAttachedPreprocessingInfo(result,position);
16563 }
16564 else
16565 {
16566 (*j)->addToAttachedPreprocessingInfo(result,position);
16567#if 0
16568 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16569#endif
16570#if 1
16571 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16572 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16573#endif
16574#if 0
16575 SgDeclarationStatement* declarationStatement = *j;
16576
16577 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16578 // from the token stream and makrs some token stream elements as already unparsed.
16579 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16580 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16581 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16582 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16583 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16584#endif
16585#if 0
16586 // Liao, let's try the new way.
16587 // global_scope->prepend_statement(null_statement);
16588 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16589
16590 if (supportUnparseHeaders == true)
16591 {
16592 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16593 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16594#if 0
16595 printf ("physical_file_id = %d \n",physical_file_id);
16596#endif
16597 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16598 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16599#if 0
16600 printf ("Exiting as a test! \n");
16601 ROSE_ASSERT(false);
16602#endif
16603 }
16604
16605 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16606
16607 globalScope->insert_statement(*j,emptyDeclaration);
16608#endif
16609 }
16610#if 0
16611 printf ("break out of for loop: result = %p \n",result);
16612#endif
16613 // DQ (8/12/2020): This is a compiler warning.
16614 // successful = true;
16615 break;
16616 }
16617 }
16618 }
16619 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16620 {
16621 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16622 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16623 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16624 ROSE_ASSERT(false);
16625 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16626 ROSE_ASSERT(result);
16627 globalScope->addToAttachedPreprocessingInfo(result,position);
16628
16629 // DQ (8/12/2020): This is a compiler warning.
16630 // successful = true;
16631 }
16632
16633 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16634 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16635 // when multiple files are used on the command line.
16636 // DQ (3/12/2019): This can be NULL for the omp tests.
16637 if (result != NULL)
16638 {
16639 result->get_file_info()->setTransformation();
16640 }
16641
16642 // must be inserted once somehow
16643 // Liao 3/11/2015. We allow failed insertion sometimes, for example when translating an empty file for OpenMP, we don't need to insert any headers
16644 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16645 // ROSE_ASSERT(successful==true);
16646
16647#if 0
16648 printf ("Exiting as a test! \n");
16649 ROSE_ASSERT(false);
16650#endif
16651
16652#if 0
16653 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16654#endif
16655
16656#if 0
16657 printf ("Exiting as a test! \n");
16658 ROSE_ASSERT(false);
16659#endif
16660
16661 return result;
16662 }
16663
16664
16665// insert a new header right before stmt, if there are existing headers attached to stmt, insert it as the last or first header as specified by asLastHeader
16666void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16667{
16668 ROSE_ASSERT (stmt != NULL);
16669 ROSE_ASSERT (newheader != NULL);
16670
16671#if 0
16672 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16673#endif
16674
16676
16677 if (asLastHeader )
16678 position = PreprocessingInfo::after;
16679 else
16680 position = PreprocessingInfo::before;
16681
16682
16683 // Find existing first and last header.
16684 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16685
16686 if (comments != NULL)
16687 {
16688 PreprocessingInfo * firstExistingHeader = NULL;
16689 PreprocessingInfo * lastExistingHeader = NULL;
16690 PreprocessingInfo * firstExistingEndif = NULL;
16691
16692 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16693 // PreprocessingInfo * lastExistingEndif = NULL;
16694
16695 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16696 for (i = comments->begin (); i != comments->end (); i++)
16697 {
16698 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16699 // #ifdef #endif the added include directive might not be visible in the generated file.
16700 // This actually happened in the case of wget application: wget.c source file.
16701#if 0
16702 // Original version of code.
16703 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16704 {
16705 // Only set first header for the first time
16706 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16707 {
16708 if (firstExistingHeader == NULL)
16709 {
16710 firstExistingHeader = (*i);
16711 firsti = i;
16712 }
16713 // always updates last header
16714 lastExistingHeader = (*i);
16715 lasti = i;
16716 }
16717 }
16718#else
16719 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16720 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16721 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16722 {
16723 // Only set first header for the first time
16724 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16725 {
16726 if (firstExistingHeader == NULL)
16727 {
16728 firstExistingHeader = (*i);
16729 firsti = i;
16730 }
16731 // always updates last header
16732 lastExistingHeader = (*i);
16733 lasti = i;
16734 }
16735 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16736 {
16737 if (firstExistingEndif == NULL)
16738 {
16739 firstExistingEndif = (*i);
16740 firsti = i;
16741 }
16742 // always updates last header
16743 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16744 // lastExistingEndif = (*i);
16745 lasti = i;
16746 }
16747 }
16748#endif
16749 }
16750
16751 // based on existing header positions, insert the new header
16752 if (asLastHeader)
16753 {
16754 if (lastExistingHeader == NULL) // No last header at all, just append to after
16755 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16756 else
16757 {
16758 comments->insert (lasti+1, newheader);
16759 }
16760 }
16761 else // add as the first header
16762 {
16763 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16764 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16765 else
16766 {
16767 comments->insert (firsti, newheader);
16768 }
16769 }
16770 }
16771 else // No comments at all, first and last header mean the same, just attach to the located node
16772 stmt->addToAttachedPreprocessingInfo(newheader, position);
16773
16774#if 0
16775 printf ("Exiting as a test! \n");
16776 ROSE_ASSERT(false);
16777#endif
16778
16779}
16780
16781
16782// The recommended version
16783PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16784{
16785 ROSE_ASSERT (source_file != NULL);
16786 SgGlobal* globalScope = source_file->get_globalScope();
16787 ROSE_ASSERT (globalScope != NULL);
16788
16789 PreprocessingInfo* result=NULL;
16790 string content;
16791 if (isSystemHeader)
16792 content = "#include <" + filename + "> \n";
16793 else
16794 content = "#include \"" + filename + "\" \n";
16795
16796#if 0
16797 // DQ (4/6/2021): This is a compiler warning, this variable is set but not used since some unreachable code is now commented out below.
16799
16800 if (asLastHeader )
16801 position = PreprocessingInfo::after;
16802 else
16803 position = PreprocessingInfo::before;
16804#endif
16805
16806 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16807 if (stmtList.size()>0) // the source file is not empty
16808 {
16809 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16810 {
16811 // Attach to the first eligible located statement
16812 //must have this judgement, otherwise wrong file will be modified!
16813 //It could also be the transformation generated statements with #include attached
16814 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16815 {
16816#if 0
16817 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16818 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16819#endif
16820 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16821 ROSE_ASSERT(result);
16822 insertHeader (*j, result, asLastHeader);
16823 //successful = true;
16824#if 0
16825 printf ("Exiting as a test! \n");
16826 ROSE_ABORT();
16827#endif
16828 break;
16829 }
16830 } // end for
16831 }
16832 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16833 {
16834 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16835 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16836 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16837 ROSE_ABORT();
16838#if 0 // [Robb Matzke 2021-03-24]: unreachable
16839 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16840 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16841 ROSE_ASSERT(result);
16842 globalScope->addToAttachedPreprocessingInfo(result,position);
16843#endif
16844 // successful = true;
16845 }
16846
16847#if 0
16848 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16849#endif
16850
16851 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16852 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16853 // when multiple files are used on the command line.
16854 if (result)
16855 result->get_file_info()->setTransformation();
16856
16857#if 0
16858 printf ("Exiting as a test! \n");
16859 ROSE_ASSERT(false);
16860#endif
16861
16862 // must be inserted once somehow
16863 // Liao 3/11/2015. We allow failed insertion sometimes, for example when translating an empty file for OpenMP, we don't need to insert any headers
16864 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16865 // ROSE_ASSERT(successful==true);
16866 return result;
16867
16868} // end insertHeader
16869
16870
16873SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16874 {
16875 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16876
16877 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16878 PreprocessingInfo* result = NULL;
16879
16880 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16881 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16882 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16883 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16884 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16885
16886 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
16887 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
16888
16889 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
16890 ROSE_ASSERT(result);
16891
16892 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16893 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16894 // when multiple files are used on the command line.
16895 result->get_file_info()->setTransformation();
16896
16897 target->addToAttachedPreprocessingInfo(result);
16898
16899 return result;
16900 }
16901
16902
16904// TODO This is a dirty fix since the ideal solution would be having a preprocessed pragma text generated by the compiler. String matching and replacing is never safe.
16906{
16907 // This is part of Wave support in ROSE.
16908// #if CAN_NOT_COMPILE_WITH_ROSE != true
16909// #if CAN_NOT_COMPILE_WITH_ROSE == 0
16910#ifndef USE_ROSE
16911 ROSE_ASSERT(target != NULL);
16912 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
16913 if (info == NULL) return;
16914 AttachedPreprocessingInfoType::iterator j;
16915 for (j = info->begin (); j != info->end (); j++)
16916 {
16917 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
16918 {
16919#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
16920 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
16921 std::ostringstream os;
16922 token_container tc = (*j)->get_macro_call()->expanded_macro;
16923 token_container::const_iterator iter;
16924 for (iter=tc.begin(); iter!=tc.end(); iter++)
16925 os<<(*iter).get_value();
16926 //cout<<"Found a macro call: "<<(*j)->getString()<<
16927 //"\nexpanding it to: "<<os.str()<<endl;
16928 string pragmaText = target->get_pragma()->get_pragma();
16929 string targetString = (*j)->getString();
16930 string replacement = os.str();
16931 // repeat until not found
16932 size_t pos1 = pragmaText.find(targetString);
16933 while (pos1 != string::npos)
16934 {
16935 pragmaText.replace(pos1, targetString.size(), replacement);
16936 pos1 = pragmaText.find(targetString);
16937 }
16938 delete target->get_pragma();
16939 target->set_pragma(buildPragma(pragmaText));
16940#endif
16941 } // end if
16942 } // end for
16943#endif
16944}
16945
16950 using namespace SageBuilder;
16951 SgStatement* body = NULL;
16952 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
16953 isSgForStatement(loopOrSwitch)) {
16954 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
16955 } else if (isSgSwitchStatement(loopOrSwitch)) {
16956 body = isSgSwitchStatement(loopOrSwitch)->get_body();
16957 }
16958 ROSE_ASSERT (body);
16959 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
16960 if (!breaks.empty()) {
16961 static int breakLabelCounter = 0;
16962 SgLabelStatement* breakLabel =
16963 buildLabelStatement("breakLabel" +
16964StringUtility::numberToString(++breakLabelCounter),
16966 isSgScopeStatement(loopOrSwitch->get_parent()));
16967 insertStatement(loopOrSwitch, breakLabel, false);
16968 for (size_t j = 0; j < breaks.size(); ++j) {
16969 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
16970
16971 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
16972 newGoto);
16973 newGoto->set_parent(breaks[j]->get_parent());
16974 }
16975 }
16976 }
16977
16979 {
16980 ROSE_ASSERT(node!=NULL);
16981 SgClassDeclaration *decl = isSgClassDeclaration(node);
16982 if (decl==NULL)
16983 return false;
16984 else
16985 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
16986 }
16987
16989 {
16990 ROSE_ASSERT(node!=NULL);
16991 SgClassDeclaration *decl = isSgClassDeclaration(node);
16992 if (decl==NULL)
16993 return false;
16994 else
16995 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
16996 }
16997
16998
16999void
17000SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
17001 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
17002 {
17003 ROSE_ASSERT(stmt_src != NULL);
17004 ROSE_ASSERT(stmt_dst != NULL);
17005 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
17006
17007 if (infoList == NULL)
17008 {
17009#if 0
17010 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
17011#endif
17012 return;
17013 }
17014
17015 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
17016
17017#if 0
17018 printf ("In SageInterface::movePreprocessingInfo(): \n");
17019 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
17020 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
17021 if (src_declarationStatement != NULL)
17022 {
17023 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
17024 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
17025 }
17026 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
17027 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
17028 if (dst_declarationStatement != NULL)
17029 {
17030 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
17031 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
17032 }
17033 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
17034 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
17035 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
17036
17037 printf (" --- infoList = %p \n",infoList);
17038 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
17039
17040 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
17041 printf (" --- dst_infoList = %p \n",dst_infoList);
17042#endif
17043#if 0
17044 printf ("****************************************************************** \n");
17045 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
17047 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
17049 printf ("****************************************************************** \n");
17050#endif
17051
17052 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
17053 // This is a bug in the support for building a new prototype from a defining function declaration
17054 // and caused this problem. This assertion will prevent this sort of error from happening again.
17055 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
17056
17057
17058#if 0
17059 printf (" --- infoList->size() = %zu \n",infoList->size());
17060 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
17061#endif
17062
17063#if 0
17064 int counter = 0;
17065
17066 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
17067 {
17068 // DQ (11/19/2020): Added assertion.
17069 ROSE_ASSERT(*i != NULL);
17070
17071 // DQ (11/19/2020): Why do we have a dynamic cast here.
17072 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
17073 PreprocessingInfo * info = *i;
17074 ROSE_ASSERT(info != NULL);
17075
17076 // printf ("counter = %d \n",counter);
17077 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
17078 counter++;
17079 }
17080
17081 counter = 0;
17082#endif
17083
17084 PreprocessingInfo* prevItem = NULL;
17085
17086 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
17087 {
17088 ROSE_ASSERT(*i != NULL);
17089
17090 PreprocessingInfo * info = *i;
17091 ROSE_ASSERT(info != NULL);
17092
17093 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
17094 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
17095 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
17096 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
17097 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
17098 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
17099 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
17100 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
17101 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
17102 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
17103 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
17104 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
17105 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
17106 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
17107 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
17108 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
17109 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
17110 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
17111 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
17112 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
17113 // DQ (12/28/2020): Added support for C linkage specifications.
17114 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
17115 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
17116 )
17117 {
17118 // move all source preprocessing info if the desired source type is not specified or matching
17119 // a specified desired source type
17120 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
17121 {
17122 if (usePrepend == true)
17123 {
17124 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
17125 if (prevItem == NULL)
17126 {
17127 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
17128 // to indicate appending or prepending by reusing the type of relative position.
17129 // this is very confusing for users
17130 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
17131 }
17132 else // there is a previous item, insert after it
17133 {
17134 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
17135 }
17136 prevItem = info;
17137 }
17138 else
17139 {
17140 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17141 }
17142 // DQ (1/15/2015): Added support to mark as transformations so that the token-based unparsing can know to NOT use the leading and trailing token stream for whitespace.
17143 info->setAsTransformation();
17144
17145 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17146 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17147 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17148 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17149 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17150 bool isMarkedAsModified = stmt_dst->get_isModified();
17151 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17152 if (isMarkedAsModified == false)
17153 {
17154 if (stmt_dst->get_isModified() == true)
17155 {
17156 stmt_dst->set_isModified(false);
17157 }
17158 }
17159 (*infoToRemoveList).push_back(*i);
17160 }
17161
17162 // adjust dst position if needed
17163 if (dst_position != PreprocessingInfo::undef)
17164 {
17165 info->setRelativePosition(dst_position);
17166 }
17167 } // end if
17168 } // end for
17169
17170 // Remove the element from the list of comments at the current astNode
17171 AttachedPreprocessingInfoType::iterator j;
17172 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17173 {
17174 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17175 }
17176 }
17177
17178
17179//----------------------------
17180// Sometimes, the preprocessing info attached to a declaration has to be
17181// moved 'up' if another declaration is inserted before it.
17182// This is a workaround for the broken LowLevelRewrite::insert() and the private
17183// LowLevelRewrite::reassociatePreprocessorDeclarations()
17184//
17185// input:
17186// *stmt_dst: the new inserted declaration
17187// *stmt_src: the existing declaration with preprocessing information
17188// tasks:
17189// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17190// add them into stmt_dst
17191// delete them from stmt_dst
17192// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17193// LoweLevel::remove(stmt_src)
17195 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17196 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17197 bool usePrepend /*= false */)
17198 {
17199 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17200 } // moveUpPreprocessingInfo()
17201
17202
17207static bool isNotRelPos (const PreprocessingInfo* info,
17209{
17210 return info && (info->getRelativePosition () != pos);
17211}
17212
17217static bool isRelPos (const PreprocessingInfo* info,
17219{
17220 return info && !isNotRelPos (info, pos);
17221}
17222
17223
17225void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17226{
17227 ASSERT_not_null(src_node);
17228
17229 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17230 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17231 if (info)
17232 {
17233 // copy elements to save_buf where isRelPos() is false
17234 remove_copy_if(info->begin(),
17235 info->end(),
17236 back_inserter(save_buf),
17237 [pos](auto x) { return !isRelPos(x, pos); }
17238 );
17239
17240 // delete copied elements from save_buf
17241 AttachedPreprocessingInfoType::iterator
17242 new_end = remove_if(info->begin(),
17243 info->end(),
17244 [pos](auto x) { return isRelPos(x, pos); }
17245 );
17246 info->erase(new_end, info->end());
17247 }
17248}
17249
17250static AttachedPreprocessingInfoType *
17251createInfoList (SgLocatedNode* s)
17252{
17253 ROSE_ASSERT (s);
17254 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17255 if (!info_list)
17256 {
17257 info_list = new AttachedPreprocessingInfoType;
17258 ROSE_ASSERT (info_list);
17259 s->set_attachedPreprocessingInfoPtr (info_list);
17260 }
17261
17262 // Guarantee a non-NULL pointer.
17263 ROSE_ASSERT (info_list);
17264 return info_list;
17265}
17266
17268void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17269{
17270 if (save_buf.size()==0) return;
17271 // if front
17272 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17273 ROSE_ASSERT (info);
17274
17275 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17276 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17277 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17278
17279 // Liao (10/3/2007), vectors can only be appended at the rear
17280 if (pos==PreprocessingInfo::before)
17281 {
17282 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17283 info->insert(info->begin(),*i);
17284 }
17285 // if back
17286 else if (pos==PreprocessingInfo::after)
17287 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17288 else if (pos==PreprocessingInfo::inside)
17289 {
17290 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17291 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17292 save_buf[0]->display("ttt");
17293 }
17294}
17295
17297{
17298 ROSE_ASSERT(locatedNode != NULL);
17299 AttachedPreprocessingInfoType *comments =
17300 locatedNode->getAttachedPreprocessingInfo ();
17301
17302 if (comments != NULL)
17303 {
17304 printf ("-----------------------------------------------\n");
17305 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17306 locatedNode, locatedNode->class_name ().c_str (),
17307 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17308 int counter = 0;
17309 AttachedPreprocessingInfoType::iterator i;
17310 for (i = comments->begin (); i != comments->end (); i++)
17311 {
17312 printf
17313 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17314 counter++,
17315 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17316 c_str (), (*i)->getString ().c_str ());
17317 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17318 printf ("relative position is: inside\n");
17319 else
17320 printf ("relative position is: %s\n", \
17321 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17322 }
17323 }
17324 else
17325 {
17326 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17327 locatedNode->sage_class_name ());
17328 }
17329}
17330
17342template <class ParentNode>
17343static
17344SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17345 SgStatement* (ParentNode::*getter) () const,
17346 void (ParentNode::*setter) (SgStatement*)
17347 )
17348{
17349 SgStatement* const body_stmt = (stmt.*getter)();
17350 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17351
17352 if (basicblock == NULL) {
17353 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17354 (stmt.*setter)(basicblock);
17355 basicblock->set_parent(&stmt);
17356 }
17357
17358 ROSE_ASSERT (basicblock != NULL);
17359 return basicblock;
17360}
17361
17363{
17364 SgStatement* b = fs->get_loop_body();
17365 if (!isSgBasicBlock(b)) {
17367 fs->set_loop_body(b);
17368 b->set_parent(fs);
17369
17370 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17372 }
17373 ROSE_ASSERT (isSgBasicBlock(b));
17374 return isSgBasicBlock(b);
17375}
17376
17378{
17379 SgStatement* b = cs->get_body();
17380 if (!isSgBasicBlock(b)) {
17382 cs->set_body(b);
17383 b->set_parent(cs);
17384
17385 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17387 }
17388 ROSE_ASSERT (isSgBasicBlock(b));
17389 return isSgBasicBlock(b);
17390}
17391
17393{
17394 SgStatement* b = cs->get_body();
17395 if (!isSgBasicBlock(b)) {
17397 cs->set_body(b);
17398 b->set_parent(cs);
17399
17400 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17402 }
17403 ROSE_ASSERT (isSgBasicBlock(b));
17404 return isSgBasicBlock(b);
17405}
17406
17408{
17409 ROSE_ASSERT (fs != NULL);
17410
17411 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17412}
17413
17415 SgStatement* b = fs->get_body();
17416 if (!isSgBasicBlock(b)) {
17418 fs->set_body(b);
17419 b->set_parent(fs);
17420
17421 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17423 }
17424 ROSE_ASSERT (isSgBasicBlock(b));
17425 return isSgBasicBlock(b);
17426 }
17427
17429 SgStatement* b = fs->get_body();
17430 if (!isSgBasicBlock(b)) {
17432 fs->set_body(b);
17433 b->set_parent(fs);
17434
17435 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17437 }
17438 ROSE_ASSERT (isSgBasicBlock(b));
17439 return isSgBasicBlock(b);
17440 }
17441
17443 SgStatement* b = fs->get_body();
17444 if (!isSgBasicBlock(b)) {
17446 fs->set_body(b);
17447 b->set_parent(fs);
17448
17449 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17451 }
17452 ROSE_ASSERT (isSgBasicBlock(b));
17453 return isSgBasicBlock(b);
17454 }
17455
17457 SgStatement* b = fs->get_true_body();
17458 if (!isSgBasicBlock(b)) {
17460 fs->set_true_body(b);
17461 b->set_parent(fs);
17462
17463 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17465#if 0
17466 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17467#endif
17468 }
17469 ROSE_ASSERT (isSgBasicBlock(b));
17470 return isSgBasicBlock(b);
17471 }
17472
17473// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17475 {
17476 // Record where normalization have been done so that we can preform denormalizations as required
17477 // for the token-based unparsing to generate minimal diffs.
17478
17479 SgBasicBlock* bb = isSgBasicBlock(s);
17480 ROSE_ASSERT(bb != NULL);
17481 addedBasicBlockNodes.push_back(bb);
17482#if 0
17483 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17484#endif
17485 }
17486
17487// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17489 {
17490 // Remove unused basic block IR nodes added as part of normalization.
17491 // This function should be called before the unparse step.
17492
17493#if 0
17494 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17495#endif
17496
17497 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17498 {
17499 SgBasicBlock* b = *i;
17500 ROSE_ASSERT(b != NULL);
17501 if (b->get_statements().size() == 1)
17502 {
17503#if 0
17504 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17505#endif
17506 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17507 ROSE_ASSERT(parentOfBlock != NULL);
17508
17509 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17510
17511 SgStatement* s = b->get_statements()[0];
17512 ROSE_ASSERT(s != NULL);
17513
17514 switch (parentOfBlock->variantT())
17515 {
17516 case V_SgIfStmt:
17517 {
17518 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17519 if (b == ifStatement->get_true_body())
17520 {
17521#if 0
17522 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17523#endif
17524 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17525 ifStatement->set_true_body(s);
17526#if 0
17527 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17528#endif
17529 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17530 s->set_parent(ifStatement);
17531#if 0
17532 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17533#endif
17534 *i = NULL;
17535 // delete b;
17536 }
17537 else
17538 {
17539 ROSE_ASSERT(b == ifStatement->get_false_body());
17540#if 0
17541 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17542#endif
17543 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17544 ifStatement->set_false_body(s);
17545#if 0
17546 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17547#endif
17548 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17549 s->set_parent(ifStatement);
17550#if 0
17551 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17552#endif
17553 *i = nullptr;
17554#if 0
17555 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17556#endif
17557#if 0
17558 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17559 ROSE_ABORT();
17560#endif
17561 }
17562 break;
17563 }
17564
17565 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17566 case V_SgWhileStmt:
17567 {
17568 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17569 if (b == whileStatement->get_body())
17570 {
17571 whileStatement->set_body(s);
17572 s->set_parent(whileStatement);
17573 }
17574 break;
17575 }
17576
17577 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17578 case V_SgSwitchStatement:
17579 {
17580 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17581 if (b == switchStatement->get_body())
17582 {
17583 switchStatement->set_body(s);
17584 s->set_parent(switchStatement);
17585 }
17586 break;
17587 }
17588
17589 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17590 case V_SgForStatement:
17591 {
17592 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17593 if (b == forStatement->get_loop_body())
17594 {
17595 forStatement->set_loop_body(s);
17596 s->set_parent(forStatement);
17597 }
17598 break;
17599 }
17600
17601 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17602 case V_SgCaseOptionStmt:
17603 {
17604 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17605 if (b == caseOptionStatement->get_body())
17606 {
17607 caseOptionStatement->set_body(s);
17608 s->set_parent(caseOptionStatement);
17609 }
17610 break;
17611 }
17612
17613 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17614 case V_SgDefaultOptionStmt:
17615 {
17616 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17617 if (b == defaultOptionStatement->get_body())
17618 {
17619 defaultOptionStatement->set_body(s);
17620 s->set_parent(defaultOptionStatement);
17621 }
17622 break;
17623 }
17624
17625 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17626 case V_SgDoWhileStmt:
17627 {
17628 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17629 if (b == doWhileStatement->get_body())
17630 {
17631 doWhileStatement->set_body(s);
17632 s->set_parent(doWhileStatement);
17633 }
17634 break;
17635 }
17636
17637 default:
17638 {
17639 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17640 ROSE_ABORT();
17641 }
17642 }
17643
17644 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17645 if (wasPreviouslyModified == false)
17646 {
17647 if (parentOfBlock->get_isModified() == true)
17648 {
17649#if 0
17650 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): parentOfBlock reset to FALSE after IR node member function call (e.g. set_body()): parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17651#endif
17652 parentOfBlock->set_isModified(false);
17653 }
17654
17655 }
17656#if 0
17657 printf ("Exiting as a test! \n");
17658 ROSE_ABORT();
17659#endif
17660 }
17661 }
17662
17663#if 0
17664 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17665#endif
17666 }
17667
17668
17670 SgStatement* b = fs->get_false_body();
17671 // if no false body at all AND no-create-empty-body
17672 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17673 return NULL;
17674 if (!isSgBasicBlock(b)) {
17675 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17676 fs->set_false_body(b);
17677 b->set_parent(fs);
17678
17679 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17681 }
17682 ROSE_ASSERT (isSgBasicBlock(b));
17683 return isSgBasicBlock(b);
17684 }
17685
17687 SgStatement* b = fs->get_body();
17688 if (!isSgBasicBlock(b)) {
17690 fs->set_body(b);
17691 b->set_parent(fs);
17692 }
17693 ROSE_ASSERT (isSgBasicBlock(b));
17694 return isSgBasicBlock(b);
17695 }
17696
17698{
17699 SgStatement* b = fs->get_body();
17700 if (!isSgBasicBlock(b)) {
17702 fs->set_body(b);
17703 b->set_parent(fs);
17704 }
17705 ROSE_ASSERT (isSgBasicBlock(b));
17706 return isSgBasicBlock(b);
17707}
17708
17710{
17711 bool rt = false;
17712 ROSE_ASSERT(s);
17713 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17714 ROSE_ASSERT(p);
17715
17716 switch (p->variantT())
17717 {
17718 case V_SgForStatement:
17719 {
17720 if (isSgForStatement(p)->get_loop_body() == s)
17721 rt = true;
17722 break;
17723 }
17724 case V_SgUpcForAllStatement: // PP
17725 {
17726 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17727 if (upcforall.get_loop_body() == s)
17728 rt = true;
17729 break;
17730 }
17731 case V_SgWhileStmt:
17732 {
17733 if (isSgWhileStmt(p)->get_body() == s)
17734 rt = true;
17735 break;
17736 }
17737 case V_SgDoWhileStmt:
17738 {
17739 if (isSgDoWhileStmt(p)->get_body() == s)
17740 rt = true;
17741 break;
17742 }
17743 case V_SgSwitchStatement:
17744 {
17745 if (isSgSwitchStatement(p)->get_body() == s)
17746 rt = true;
17747 break;
17748 }
17749 case V_SgCaseOptionStmt:
17750 {
17751 if (isSgCaseOptionStmt(p)->get_body() == s)
17752 rt = true;
17753 break;
17754 }
17755 case V_SgDefaultOptionStmt:
17756 {
17757 if (isSgDefaultOptionStmt(p)->get_body() == s)
17758 rt = true;
17759 break;
17760 }
17761 case V_SgCatchOptionStmt:
17762 {
17763 if (isSgCatchOptionStmt(p)->get_body() == s)
17764 rt = true;
17765 break;
17766 }
17767 case V_SgIfStmt:
17768 {
17769 if (isSgIfStmt(p)->get_true_body() == s)
17770 rt = true;
17771 else if (isSgIfStmt(p)->get_false_body() == s)
17772 rt = true;
17773 break;
17774 }
17775 default:
17776 {
17777 if (isSgOmpBodyStatement(p))
17778 rt = true;
17779 break;
17780 }
17781 }
17782 return rt;
17783}
17784
17786//etc.
17788{
17789 ROSE_ASSERT (singleStmt != NULL); // not NULL
17790 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17791 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17792
17793 SgBasicBlock* rt = NULL;
17794
17795
17796
17797 SgStatement* s = singleStmt;
17798 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17799 ROSE_ASSERT(p);
17800 switch (p->variantT())
17801 {
17802 case V_SgForStatement:
17803 {
17804 if (isSgForStatement(p)->get_loop_body() == s)
17805 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17806 break;
17807 }
17808 case V_SgUpcForAllStatement: // PP
17809 {
17810 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17811
17812 if (upcforall.get_loop_body() == s)
17813 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17814 break;
17815 }
17816 case V_SgWhileStmt:
17817 {
17818 if (isSgWhileStmt(p)->get_body() == s)
17819 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17820 break;
17821 }
17822 case V_SgDoWhileStmt:
17823 {
17824 if (isSgDoWhileStmt(p)->get_body() == s)
17825 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17826 break;
17827 }
17828 case V_SgSwitchStatement:
17829 {
17830 if (isSgSwitchStatement(p)->get_body() == s)
17831 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17832 break;
17833 }
17834 case V_SgCaseOptionStmt:
17835 {
17836 if (isSgCaseOptionStmt(p)->get_body() == s)
17837 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17838 break;
17839 }
17840 case V_SgDefaultOptionStmt:
17841 {
17842 if (isSgDefaultOptionStmt(p)->get_body() == s)
17843 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17844 break;
17845 }
17846 case V_SgCatchOptionStmt:
17847 {
17848 if (isSgCatchOptionStmt(p)->get_body() == s)
17849 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17850 break;
17851 }
17852 case V_SgIfStmt:
17853 {
17854 if (isSgIfStmt(p)->get_true_body() == s)
17855 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17856 else if (isSgIfStmt(p)->get_false_body() == s)
17857 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17858 break;
17859 }
17860 default:
17861 {
17862 if (isSgOmpBodyStatement(p))
17863 {
17864 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17865 }
17866 break;
17867 }
17868 }
17869 ROSE_ASSERT (rt != NULL); // the input statement has been confirmed to be a body statement, it must have being processed to be a basic block at this point.
17870 return rt;
17871}
17872
17873#if 0
17874SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17875{
17876 ROSE_ASSERT(s);
17877
17878 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17879 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17880 ROSE_ASSERT(p);
17881 switch (p->variantT())
17882 {
17883 case V_SgBasicBlock: return isSgBasicBlock(p);
17884 case V_SgForStatement:
17885 {
17886 if (isSgForStatement(p)->get_loop_body() == s)
17887 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17888 else if (isSgForStatement(p)->get_test() == s)
17889 {
17890 }
17891 else if (isSgForStatement(p)->get_for_init_stmt() == s)
17892 {
17893 }
17894 else ROSE_ABORT();
17895 break;
17896 }
17897 case V_SgUpcForAllStatement: // PP
17898 {
17899 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17900
17901 if (upcforall.get_loop_body() == s)
17902 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17903
17904 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
17905 || (s == upcforall.get_test())
17906 );
17907 break;
17908 }
17909 case V_SgWhileStmt:
17910 {
17911 if (isSgWhileStmt(p)->get_body() == s)
17912 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17913 else if (isSgWhileStmt(p)->get_condition() == s)
17914 {
17915 }
17916 else ROSE_ABORT();
17917 break;
17918 }
17919 case V_SgDoWhileStmt:
17920 {
17921 if (isSgDoWhileStmt(p)->get_body() == s)
17922 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17923 else if (isSgDoWhileStmt(p)->get_condition() == s)
17924 {
17925 }
17926 else ROSE_ABORT();
17927 break;
17928 }
17929 case V_SgSwitchStatement:
17930 {
17931 if (isSgSwitchStatement(p)->get_body() == s)
17932 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17933 else if (isSgSwitchStatement(p)->get_item_selector() == s)
17934 {
17935 }
17936 else ROSE_ABORT();
17937 break;
17938 }
17939 case V_SgCatchOptionStmt:
17940 {
17941 if (isSgCatchOptionStmt(p)->get_body() == s)
17942 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17943 else if (isSgCatchOptionStmt(p)->get_condition() == s)
17944 {
17945 }
17946 else ROSE_ABORT();
17947 break;
17948 }
17949 case V_SgIfStmt:
17950 {
17951 if (isSgIfStmt(p)->get_true_body() == s)
17952 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17953 else if (isSgIfStmt(p)->get_false_body() == s)
17954 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17955 else if (isSgIfStmt(p)->get_conditional() == s)
17956 {
17957 }
17958 else ROSE_ABORT();
17959 break;
17960 }
17961 default:
17962 {
17963 if (isSgOmpBodyStatement(p))
17964 {
17965 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17966 }
17967 else
17968 // Liao, 7/3/2008 We allow other conditions to fall through,
17969 // they are legal parents with list of statements as children.
17970 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
17971 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
17972 break;
17973 }
17974 }
17975 return p;
17976}
17977
17978 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
17979 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
17980 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
17982 }
17983
17984#endif
17985 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
17986 class Visitor: public AstSimpleProcessing {
17987 public:
17988 bool allowEmptyBody;
17989 Visitor (bool flag):allowEmptyBody(flag) {}
17990 virtual void visit(SgNode* n) {
17991
17992 bool wasPreviouslyModified = n->get_isModified();
17993
17994 switch (n->variantT()) {
17995 case V_SgForStatement: {
17996 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
17997 break;
17998 }
17999 case V_SgWhileStmt: {
18000 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
18001 break;
18002 }
18003 case V_SgDoWhileStmt: {
18004 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
18005 break;
18006 }
18007 case V_SgSwitchStatement: {
18008 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
18009 break;
18010 }
18011 case V_SgIfStmt: {
18012 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
18013 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
18014#if 0
18015 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
18016 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
18017#endif
18018#if 0
18019 // Reset this to false as a test.
18020 if (n->get_isModified() == true)
18021 {
18022 n->set_isModified(false);
18023 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
18024 }
18025#endif
18026 break;
18027 }
18028 case V_SgCatchOptionStmt: {
18029 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
18030 break;
18031 }
18032 case V_SgUpcForAllStatement: {
18033 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
18034 break;
18035 }
18036
18037 default:
18038 {
18039 if (isSgOmpBodyStatement(n))
18040 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
18041 break;
18042 }
18043 }
18044
18045 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
18046 if (wasPreviouslyModified == false)
18047 {
18048 if (n->get_isModified() == true)
18049 {
18050#if 0
18051 printf ("In SageInterface::changeAllBodiesToBlocks(): parentOfBlock reset to FALSE after IR node member function call (e.g. set_body()): parentOfBlock = %p = %s \n",n,n->class_name().c_str());
18052#endif
18053 n->set_isModified(false);
18054 }
18055
18056 }
18057
18058 }
18059 };
18060 Visitor(createEmptyBody).traverse(top, postorder);
18061 }
18062
18063
18064// Replace a given expression with a list of statements produced by a
18065// generator. The generator, when given a variable as input, must produce
18066// some code which leaves its result in the given variable. The output
18067// from the generator is then inserted into the original program in such a
18068// way that whenever the expression had previously been evaluated, the
18069// statements produced by the generator are run instead and their result is
18070// used in place of the expression.
18071// Assumptions: not currently traversing from or the statement it is in
18072void
18074 {
18075 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
18076 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
18077 // the original assumptions upon which this function was based are not incorrect, hence the bug!
18078 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
18079 // for SgScopeStatement).
18080
18081#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18082 SgStatement* enclosingStatement = getStatementOfExpression(from);
18083 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
18084
18085 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
18086 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
18087 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
18088
18089
18090 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
18091
18092 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
18093
18094 if (varDeclarationStatement)
18095 {
18097 }
18098 else
18099 {
18100 SgExpression* root = getRootOfExpression(from);
18101 ROSE_ASSERT (root);
18102 // printf ("root = %p \n",root);
18103 {
18104 if (forStatement && forStatement->get_increment() == root)
18105 {
18106 // printf ("Convert step of for statement \n");
18107 // Convert step of for statement
18108 // for (init; test; e) body; (where e contains from) becomes
18109 // for (init; test; ) {
18110 // body (with "continue" changed to "goto label");
18111 // label: e;
18112 // }
18113 // std::cout << "Converting for step" << std::endl;
18114 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
18115 forStatement->get_increment()->set_parent(incrStmt);
18116
18117 SageInterface::addStepToLoopBody(forStatement, incrStmt);
18119 forStatement->set_increment(ne);
18120 ne->set_parent(forStatement);
18122 }
18123 else
18124 {
18125 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
18126 assert (enclosingStmtParent);
18127 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
18128 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
18129 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
18130 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
18131 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
18132 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
18133 {
18134 // Convert test of for statement:
18135 // for (init; e; step) body; (where e contains from) becomes
18136 // for (init; true; step) {
18137 // bool temp;
18138 // temp = e;
18139 // if (!temp) break;
18140 // body;
18141 // }
18142 // in which "temp = e;" is rewritten further
18143 // std::cout << "Converting for test" << std::endl;
18144 pushTestIntoBody(enclosingForStatement);
18146 }
18147 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18148 {
18149 // printf ("Convert while statements \n");
18150 // Convert while statement:
18151 // while (e) body; (where e contains from) becomes
18152 // while (true) {
18153 // bool temp;
18154 // temp = e;
18155 // if (!temp) break;
18156 // body;
18157 // }
18158 // in which "temp = e;" is rewritten further
18159 // std::cout << "Converting while test" << std::endl;
18160 pushTestIntoBody(whileStatement);
18161 // FixSgTree(whileStatement);
18163 }
18164 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18165 {
18166 // printf ("Convert do-while statements \n");
18167 // Convert do-while statement:
18168 // do body; while (e); (where e contains from) becomes
18169 // {bool temp = true;
18170 // do {
18171 // body (with "continue" changed to "goto label";
18172 // label:
18173 // temp = e;} while (temp);}
18174 // in which "temp = e;" is rewritten further
18175 // std::cout << "Converting do-while test" << std::endl;
18176 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18177 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18178 assert (doWhileStatement->get_parent());
18179 new_statement->set_parent(doWhileStatement->get_parent());
18180 myStatementInsert(doWhileStatement, new_statement, false);
18181 SageInterface::myRemoveStatement(doWhileStatement);
18182 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18183 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18184 buildBoolValExp(true));
18185 //SageInterface::getBoolType(doWhileStatement));
18187 varname, buildBoolType(), assignInitializer, new_statement);
18188
18189 SgInitializedName* initname = new_decl->get_variables().back();
18190 initname->set_scope(new_statement);
18191
18192 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18193 assignInitializer->set_parent(initname);
18194
18195#if 1
18196 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18198#else
18199 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18200 new_statement->insert_symbol(varname, varsym);
18201 varsym->set_parent(new_statement->get_symbol_table());
18202#endif
18203
18204 SageInterface::appendStatement(new_decl, new_statement);
18205 SageInterface::appendStatement(doWhileStatement, new_statement);
18206 assert (varsym);
18207 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18208 SgVarRefExp* vr = buildVarRefExp(varsym);
18209 vr->set_lvalue(true);
18210
18211 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18212
18213 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18214 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18215
18217 varsymVr->set_parent(condStmt);
18218 doWhileStatement->set_condition(condStmt);
18219 condStmt->set_parent(doWhileStatement);
18221 }
18222 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18223 {
18224 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18225 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18226 assert (ifStatement->get_parent());
18227 new_statement->set_parent(ifStatement->get_parent());
18228 myStatementInsert(ifStatement, new_statement, false);
18230 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18231 SgBoolValExp* trueVal = buildBoolValExp(true);
18232
18234
18236 buildBoolType(), ai,new_statement);
18237 SgInitializedName* initname = new_decl->get_variables().back();
18238 ai->set_parent(initname);
18239 initname->set_scope(new_statement);
18240#if 1
18241 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18243#else
18244 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18245 new_statement->insert_symbol(varname, varsym);
18246 varsym->set_parent(new_statement->get_symbol_table());
18247#endif
18248 SageInterface::appendStatement(new_decl, new_statement);
18249 ifStatement->set_parent(new_statement);
18250 assert (varsym);
18251
18252 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18253 SgVarRefExp* vr = buildVarRefExp(varsym);
18254 vr->set_lvalue(true);
18255 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18256 SageInterface::appendStatement(temp_setup, new_statement);
18257 SageInterface::appendStatement(ifStatement, new_statement);
18260 ifStatement->set_conditional(es);
18261 es->set_parent(ifStatement);
18263 }
18264 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18265 {
18266 SgExpression* switchCond = exprStatement->get_expression();
18267 ROSE_ASSERT (switchCond);
18268 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18269 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18270 assert (switchStatement->get_parent());
18271 new_statement->set_parent(switchStatement->get_parent());
18272 myStatementInsert(switchStatement, new_statement, false);
18273 SageInterface::myRemoveStatement(switchStatement);
18274 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18275 switchCond->set_parent(NULL);
18276 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18278 SageInterface::appendStatement(new_decl, new_statement);
18279 switchStatement->set_parent(new_statement);
18280 assert (varsym);
18281
18282
18283 SageInterface::appendStatement(switchStatement, new_statement);
18286 switchStatement->set_item_selector(es);
18287 es->set_parent(switchStatement);
18289 }
18290 else
18291 {
18292 // printf ("Handles expression and return statements \n");
18293 // Handles expression and return statements
18294 // std::cout << "Converting other statement" << std::endl;
18296 }
18297 }
18298 }
18299 }
18300
18301#endif
18302
18303 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18304 }
18305
18314
18315// Similar to replaceExpressionWithStatement, but with more restrictions.
18316// Assumptions: from is not within the test of a loop or if
18317// not currently traversing from or the statement it is in
18319 {
18320
18321#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18322 SgStatement* stmt = getStatementOfExpression(from);
18323
18324 if (isSgExprStatement(stmt))
18325 {
18326 SgExpression* top = getRootOfExpression(from);
18327
18328
18329 if (top == from)
18330 {
18331 SgStatement* generated = to->generate(0);
18332 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18333 generated->set_parent(stmt->get_parent());
18334 return;
18335 }
18336 else
18337 {
18338 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18339 {
18340 SgAssignOp* t = isSgAssignOp(top);
18341 SgStatement* generated = to->generate(t->get_lhs_operand());
18342 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18343 generated->set_parent(stmt->get_parent());
18344 return;
18345 }
18346 else
18347 {
18348 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18349 }
18350 }
18351 }
18352
18353 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18355 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18356 convertInitializerIntoAssignment(init);
18357 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18358 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18359 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18360 assert (new_stmt != NULL); // Should now have this form because of conversion
18361 replaceAssignmentStmtWithStatement(new_stmt, to);
18362
18363 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18364 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18365
18366#endif
18367 }
18368
18369
18370 // Liao, 6/27/2008
18371 //Tasks
18372 // find all return statements
18373 // rewrite it to temp = expression; return temp; if expression is not a single value.
18374 // insert s right before 'return xxx;'
18376 {
18377 int result = 0;
18378 ROSE_ASSERT(func&&s);
18379 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18380 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18381 //vector<SgReturnStmt*>::iterator i;
18382 Rose_STL_Container<SgNode*>::iterator i;
18383 for (i=stmts.begin();i!=stmts.end();i++)
18384 {
18385 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18386 ROSE_ASSERT(cur_stmt);
18387 SgExpression * exp = cur_stmt->get_expression();
18388 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18389 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18390 if (needRewrite)
18391 {
18392 splitExpression(exp);
18393 }
18394 // avoid reusing the statement
18395 if (result>=1 )
18396 s = copyStatement(s);
18397 insertStatementBefore(cur_stmt,s);
18398 result ++;
18399 } // for
18400 if (stmts.size()==0 ) // a function without any return at all,
18401 {
18402 SgBasicBlock * body = func->get_definition()->get_body();
18403 if (body== NULL)
18404 {
18405 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18406 ROSE_ABORT();
18407 }
18408 appendStatement(s,body);
18409 result ++;
18410 }
18411 return result;
18412 } // instrumentEndOfFunction
18413
18415 {
18416 ROSE_ASSERT(stmt);
18417 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18418 } // isStatic()
18419
18422 {
18423 ROSE_ASSERT(stmt);
18424 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18425 }
18426
18428 {
18429 ROSE_ASSERT(stmt);
18430 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18431 } // isExtern()
18432
18433
18436 {
18437 ROSE_ASSERT(stmt);
18438 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18439 }
18440
18441 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18443 {
18444 ROSE_ASSERT(name);
18445 return name->get_storageModifier().isMutable();
18446 }
18447
18448 // True if a parameter name is a Jovial output parameter
18450 {
18451 return isMutable(name);
18452 }
18453
18454 // Get a vector of Jovial input parameters from the function parameter list
18455 // TODO: Look into making this work for Fortran
18456 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18457 {
18458 std::vector<SgInitializedName*> in_params;
18459 BOOST_FOREACH (SgInitializedName* name, params)
18460 {
18461 if (!isJovialOutParam(name)) in_params.push_back(name);
18462 }
18463 return in_params;
18464 }
18465
18466 // Get a list of Jovial output parameters from the function parameter list
18467 // TODO: Look into making this work for Fortran
18468 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18469 {
18470 std::vector<SgInitializedName*> out_params;
18471 BOOST_FOREACH (SgInitializedName* name, params)
18472 {
18473 if (isJovialOutParam(name)) out_params.push_back(name);
18474 }
18475 return out_params;
18476 }
18477
18479 switch (expr->variantT()) {
18480 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18481 case V_SgSignedCharVal: return (long long)(isSgSignedCharVal(expr)->get_value());
18482 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18483 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18484 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18485 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18486 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18487 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18488 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18489 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18490 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18491 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18492
18493 // DQ (2/18/2015): Make this a better error message.
18494 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18495 default:
18496 {
18497 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18498 ROSE_ASSERT (false);
18499 }
18500
18501 }
18502
18503 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18504 return 0;
18505 }
18506
18507
18508#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18509// tps : 28 Oct 2008 - support for finding the main interpretation
18510// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18514SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18515{
18516 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18517 ROSE_ASSERT(binary!=NULL);
18518
18519 /* Find the only header or the PE header of this file */
18520 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18521 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18522 if (1==headers.size()) {
18523 requisite_header = headers[0];
18524 } else {
18525 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18526 if (isSgAsmPEFileHeader(*hi)) {
18527 requisite_header = isSgAsmPEFileHeader(*hi);
18528 break;
18529 }
18530 }
18531 }
18532 ROSE_ASSERT(requisite_header!=NULL);
18533
18534 /* Find an interpretation that points to this header */
18535 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18536 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18537 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18538 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18539 if ((*hi)==requisite_header)
18540 return *ii;
18541 }
18542 }
18543
18544 ROSE_ASSERT(!"no appropriate interpretation");
18545 return NULL;
18546}
18547#endif
18548
18550 {
18551 public:
18552 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18553 // Note that the root of the does not have its file info set like its children.
18554 virtual SgNode *copyAst(const SgNode *n)
18555 {
18556 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18557 SgNode* copy = n->copy(*this);
18558
18559 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18560 Sg_File_Info* fileInfo = copy->get_file_info();
18561 if (fileInfo != NULL)
18562 {
18563 // Must make this for output (checked in unparser), marking as a transformation is not checked
18564 fileInfo->setOutputInCodeGeneration();
18565 fileInfo->setTransformation();
18566 }
18567
18568 return copy;
18569 }
18570 } collectDependentDeclarationsCopyType;
18571
18572
18574 {
18575 // This traversal collects the includes at the top of a file.
18576
18577 public:
18578 vector<PreprocessingInfo*> cppDirectiveList;
18579
18580 void visit(SgNode *astNode);
18581 };
18582
18583
18584void
18586 {
18587 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18588 if (locatedNode != NULL)
18589 {
18590 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18591
18592 if (comments != NULL)
18593 {
18594#if 0
18595 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18596#endif
18597 AttachedPreprocessingInfoType::iterator i;
18598 for (i = comments->begin(); i != comments->end(); i++)
18599 {
18600 ROSE_ASSERT ( (*i) != NULL );
18601#if 0
18602 printf (" Attached Comment (relativePosition=%s): %s\n",
18603 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18604 (*i)->getString().c_str());
18605 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18606 (*i)->get_file_info()->display("comment/directive location");
18607#endif
18608
18609 // We only save the #include directives, but likely we should be collecting ALL directives to
18610 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18611 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18612 {
18613 // This is an include directive.
18614 cppDirectiveList.push_back(*i);
18615#if 0
18616 printf (" Attached include directive (relativePosition=%s): %s\n",
18617 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18618 (*i)->getString().c_str());
18619#endif
18620 }
18621 }
18622 }
18623 else
18624 {
18625#if 0
18626 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18627#endif
18628 }
18629 }
18630 }
18631
18632
18633// This is part of a mechanism to collect directives from code that is to be outlined.
18634// However if we collect include directives we likely should really be collecting ALL
18635// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18636// This level of detail will be addressed later (in an iterative approach).
18637vector<PreprocessingInfo*>
18638collectCppDirectives ( SgSourceFile* file )
18639 {
18640 // This function is used to collect include directives from the whole file.
18642 t.traverse(file,preorder);
18643
18644 return t.cppDirectiveList;
18645 }
18646
18647
18648vector<PreprocessingInfo*>
18649collectCppDirectives ( SgLocatedNode* n )
18650 {
18651 // This function is used to collect include directives from specific dependent declarations.
18653 t.traverse(n,preorder);
18654
18655 return t.cppDirectiveList;
18656 }
18657
18658// Debugging support.
18659void
18660outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18661 {
18662 // This function support debugging the generated directive lists.
18663
18664 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18665 while ( i != l.end() )
18666 {
18667 printf (" Attached include directive (relativePosition=%s): %s\n",
18668 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18669 (*i)->getString().c_str());
18670 i++;
18671 }
18672 }
18673
18674
18675
18677getAssociatedDeclaration( SgScopeStatement* scope )
18678 {
18679 //TODO This should become a member of SgScopeStatement
18680
18681 SgDeclarationStatement* declaration = NULL;
18682 switch(scope->variantT())
18683 {
18684 case V_SgNamespaceDefinitionStatement:
18685 {
18686 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18687 declaration = namespaceDefinition->get_namespaceDeclaration();
18688 break;
18689 }
18690
18691 case V_SgClassDefinition:
18692 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18693 {
18694 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18695 declaration = classDefinition->get_declaration();
18696 break;
18697 }
18698
18699 default:
18700 {
18701 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18702 ROSE_ABORT();
18703 }
18704 }
18705
18706 // There may be some scopes that don't have an associated declaration.
18707 ROSE_ASSERT(declaration != NULL);
18708
18709 return declaration;
18710 }
18711
18712
18714 {
18715 public:
18716 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18717 // (usually of the outlined functions) to insert in the separate file to support outlining.
18718 vector<SgDeclarationStatement*> declarationList;
18719
18720 // Save the list of associated symbols of dependent declarations identified so that we can
18721 // support their replacement in the new AST.
18722 vector<SgSymbol*> symbolList;
18723
18724 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18725 set<SgDeclarationStatement*> alreadySavedDeclarations;
18726
18727 // Required visit function for the AST traversal
18728 void visit(SgNode *astNode);
18729 private:
18730 void addDeclaration(SgDeclarationStatement* decl);
18731 };
18732
18734getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18735 {
18736 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18737 // outline the reference to the class, we have to declare not the class but the outer scope
18738 // (which will have the class included).
18739
18740 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18741
18742 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18743 SgScopeStatement* scope = inputDeclaration->get_scope();
18744 ROSE_ASSERT(scope != NULL);
18745
18746 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18747
18748 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18749 SgGlobal* globalScope = isSgGlobal(scope);
18750 if (globalScope == NULL)
18751 {
18752 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18753 // printf ("Traverse back to the global scope to include outer declarations \n");
18754
18755 SgScopeStatement* parentScope = scope;
18756 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18757 ROSE_ASSERT(parentScope != NULL);
18758 while (globalScope == NULL)
18759 {
18760 associatedDeclaration = getAssociatedDeclaration(parentScope);
18761 ROSE_ASSERT(associatedDeclaration != NULL);
18762
18763 parentScope = parentScope->get_scope();
18764 globalScope = isSgGlobal(parentScope);
18765 }
18766
18767 returnDeclaration = associatedDeclaration;
18768 }
18769
18770 return returnDeclaration;
18771 }
18772
18773
18774// Debugging support.
18775void
18776outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18777 {
18778 // This function support debugging the generated declarations.
18779
18780 int counter = 0;
18781 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18782 while ( i != l.end() )
18783 {
18784 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18785 i++;
18786 }
18787 }
18788
18789void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18790{
18791 // If there was a declaration found then handle it.
18792 if (declaration != NULL)
18793 {
18794 // Reset the defining declaration in case there is an outer declaration that is more important
18795 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18796 // find the associated outer declaration in the global scope.
18797 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18798
18799 // This declaration is in global scope so we just copy the declaration
18800 // For namespace declarations: they may have the save name but they have to be saved separated.
18801 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18802 {
18803#if 0
18804 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18805 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18806#endif
18807 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18808 declarationList.push_back(dependentDeclaration);
18809
18810 // Record this as a copied declaration
18811 alreadySavedDeclarations.insert(dependentDeclaration);
18812#if 0
18813 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18814 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18815 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18816#endif
18817 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18818 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18819 }
18820 else
18821 {
18822#if 0
18823 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18824 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18825 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18826#endif
18827 }
18828 }
18829}
18830
18832static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18833{
18834 ROSE_ASSERT(type != NULL);
18835 std::vector<SgTypedefDeclaration*> result;
18836 SgType* currentType = type;
18837
18838 SgModifierType* modType = NULL;
18839 SgPointerType* pointType = NULL;
18840 SgReferenceType* refType = NULL;
18841 SgArrayType* arrayType = NULL;
18842 SgTypedefType* typedefType = NULL;
18843
18844 while (true)
18845 {
18846 modType = isSgModifierType(currentType);
18847 if(modType)
18848 {
18849 currentType = modType->get_base_type();
18850 }
18851 else
18852 {
18853 refType = isSgReferenceType(currentType);
18854 if(refType)
18855 {
18856 currentType = refType->get_base_type();
18857 }
18858 else
18859 {
18860 pointType = isSgPointerType(currentType);
18861 if ( pointType)
18862 {
18863 currentType = pointType->get_base_type();
18864 }
18865 else
18866 {
18867 arrayType = isSgArrayType(currentType);
18868 if (arrayType)
18869 {
18870 currentType = arrayType->get_base_type();
18871 }
18872 else
18873 {
18874 typedefType = isSgTypedefType(currentType);
18875 if (typedefType)
18876 {
18877 currentType = typedefType->get_base_type();
18878 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18879 // have to try to get the defining declaration for a defining typedef declaration
18880 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18881 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18882 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18883 if (decl ==NULL)
18884 decl = tdecl;
18885 result.push_back(decl);
18886 }
18887 else
18888 {
18889 // Exit the while(true){} loop!
18890 break;
18891 }
18892 }
18893 }
18894 }
18895 }
18896 }
18897#if 0
18898 // debug here
18899 if (result.size()>0)
18900 {
18901 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
18902 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
18903 iter!=result.end(); iter ++)
18904 cout<<(*iter)->unparseToString()<<endl;
18905 }
18906#endif
18907 return result;
18908}
18909
18911void
18913 {
18914 // Statements that can cause us to have declaration dependences:
18915 // 1) variable declarations (through their types)
18916 // 2) function calls
18917 // 3) typedefs (through their base types)
18918 // Not implemented:
18919 // 4) static member functions (through their class)
18920 // 5) static data members (through their class)
18921 // 6) namespaces
18922 // 7) #include<> CPP directives.
18923
18924 // DQ (2/22/2009): Changing the semantics for this function,
18925 // just save the original declaration, not a copy of it.
18926
18927#if 0
18928 // Debugging support.
18929 Sg_File_Info* fileInfo = astNode->get_file_info();
18930 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
18931 {
18932 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18933 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
18934 int counter = 0;
18935 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
18936 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
18937 {
18938 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
18939 }
18940 }
18941#endif
18942
18943 // The following conditionals set this variable
18944 SgDeclarationStatement* declaration = NULL;
18945
18946 // 1) ------------------------------------------------------------------
18947 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
18948 SgInitializedName* initializedname = isSgInitializedName(astNode);
18949 if (initializedname != NULL)
18950 {
18951 SgType* type = initializedname->get_type();
18952
18953 // handle all dependent typedef declarations, if any
18954 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
18955 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
18956 iter != typedefVec.end(); iter++)
18957 {
18958 SgTypedefDeclaration* typedef_decl = *iter;
18959 addDeclaration(typedef_decl);
18960 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
18961 }
18962
18963 // handle base type:
18964
18965 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
18966 // this also reach to the defining body of a defining typedef declaration
18967 // and treat it as an independent declarations,
18968 // the assumption here is that a defining typedef declaration will only has its
18969 // nondefining declaration copied to avoid redefining of the struct.
18970 // This is also a workaround for an AST copy bug: defining body gets lost after copying
18971 // a defining typedef declaration.
18972 // Liao, 5/8/2009
18973 //
18974 // e.g. typedef struct hypre_BoxArray_struct
18975 // {
18976 // int alloc_size;
18977 // } hypre_BoxArray;
18978 //
18979 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
18980 // will be inserted.
18981 //
18982 SgType* strippedType = type->stripType();
18983 SgNamedType* namedType = isSgNamedType(strippedType);
18984 if (namedType != NULL)
18985 {
18986 // Note that since this was obtained via the types and types are shared, this is the non-defining
18987 // declaration in original program (not the separate file is this is to support outlining into a
18988 // separate file.
18989 SgDeclarationStatement* named_decl = namedType->get_declaration();
18990 // the case of class declaration, including struct, union
18991 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
18992 if (classDeclaration != NULL)
18993 {
18994 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
18995 declaration = classDeclaration->get_definingDeclaration();
18996 // Liao, 12/09/2016.
18997 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
18998 // We should allow this.
18999 if (declaration != NULL)
19000 {
19001 // ROSE_ASSERT(declaration != NULL);
19002 addDeclaration(declaration);
19003 }
19004 else
19005 addDeclaration (classDeclaration); // we use the original forward declaration.
19006
19007 // Note that since types are shared in the AST, the declaration for a named type may be (is)
19008 // associated with the class declaration in the original file. However, we want to associated
19009 // class declaration in the current file, but since the AST copy mechanism work top-down, this
19010 // mapping form the declaration in the original file to the new declaration in the copied AST
19011 // is available in the SgCopyHelp map of copied IR nodes.
19012 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
19013 // these symbols will be mapped to their new symbols.
19014 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
19015 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
19016 ROSE_ASSERT(classSymbol != NULL);
19017
19018 // printf ("Saving classSymbol = %p \n",classSymbol);
19019 symbolList.push_back(classSymbol);
19020 }
19021
19022 // handle Enum types
19023 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
19024 if (enum_decl != NULL)
19025 {
19026 declaration = enum_decl->get_definingDeclaration();
19027 ROSE_ASSERT(declaration != NULL);
19028 addDeclaration(declaration);
19029 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
19030 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
19031 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
19032 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
19033 ROSE_ASSERT(esymbol!= NULL);
19034 symbolList.push_back(esymbol);
19035 }
19036 } // end if namedType
19037#if 0
19038 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
19039#endif
19040 }// end if (initializedname)
19041
19042 // 2) ------------------------------------------------------------------
19043 // Collect declarations associated with function calls.
19044 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
19045 if (functionCallExp != NULL)
19046 {
19047 declaration = functionCallExp->getAssociatedFunctionDeclaration();
19048 //ROSE_ASSERT(declaration != NULL);
19049 // We allow a function pointer to have no specific declaration associated.
19050 if (declaration != NULL)
19051 addDeclaration(declaration);
19052
19053 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
19054 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
19055 //ROSE_ASSERT(functionSymbol != NULL);
19056
19057 // printf ("Saving functionSymbol = %p \n",functionSymbol);
19058 if (functionSymbol)
19059 symbolList.push_back(functionSymbol);
19060 }
19061
19062 // 3) ------------------------------------------------------------------
19063 // Collect enumerate declarations associated with SgEnumVal
19064 SgEnumVal * eval = isSgEnumVal(astNode);
19065 if (eval != NULL)
19066 {
19067 declaration = eval->get_declaration();
19068 ROSE_ASSERT(declaration != NULL);
19069 addDeclaration(declaration);
19071 ROSE_ASSERT(symbol != NULL);
19072 symbolList.push_back(symbol);
19073 }
19074// addDeclaration(declaration); // do it in different cases individually
19075 }
19076
19077static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
19078
19079
19081// Used to separate a function to a new source file and add necessary type declarations into the new file.
19082// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
19083static void
19084getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
19085{
19086 // This function returns a list of the dependent declaration for any input statement.
19087 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19088#if 0
19089 printf ("\n\n********************************************************** \n");
19090 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19091 printf ("********************************************************** \n");
19092#endif
19093 visitedDeclMap[stmt]= true;
19095 t.traverse(stmt,preorder);
19096#if 0
19097 declarationList = t.declarationList;
19098 symbolList = t.symbolList;
19099#else
19100 // Merge to the parent level list
19101 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
19102 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
19103 // make their elements unique
19104 sort (declarationList.begin(), declarationList.end());
19105 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
19106 declarationList.erase(new_end, declarationList.end());
19107
19108 sort (symbolList.begin(), symbolList.end());
19109 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
19110 symbolList.erase(end2, symbolList.end());
19111
19112
19113 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
19114 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
19115 iter !=t.declarationList.end(); iter++)
19116 {
19117 SgDeclarationStatement* decl = *iter;
19118 SgType* base_type = NULL;
19119 SgStatement* body_stmt= NULL;
19120
19121 // grab base type for a declaration
19122 // For class declaration: grab their
19123 if (isSgClassDeclaration(decl))
19124 {
19125 base_type = isSgClassDeclaration(decl)->get_type();
19126 } else
19127 if (isSgTypedefDeclaration(decl))
19128 {
19129
19130 // we don't want to strip of nested typedef declarations
19131 base_type = isSgTypedefDeclaration(decl)->get_base_type()->stripType(SgType::STRIP_POINTER_TYPE|SgType::STRIP_ARRAY_TYPE|SgType::STRIP_REFERENCE_TYPE|SgType::STRIP_RVALUE_REFERENCE_TYPE|SgType::STRIP_MODIFIER_TYPE);
19132 }
19133
19134 //TODO variable declaration, function declaration: parameter list types,
19135 // multiple base_type then
19136
19137 // is the base type associated with a defining body?
19138 // TODO enum type
19139 if (isSgClassType(base_type))
19140 {
19141 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19142 if (class_decl!=NULL)
19143 {
19144 body_stmt = class_decl->get_definition();
19145 }
19146 }
19147 // recursively collect dependent declarations for the body stmt
19148 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19149 { // avoid infinite recursion
19150 getDependentDeclarations(body_stmt, declarationList, symbolList);
19151 }
19152 }
19153#endif
19154} // end void getDependentDeclarations()
19155
19156
19157// Reorder a list of declaration statements based on their appearance order in source files
19158// This is essential to insert their copies into a new file in a right order
19159// Liao, 5/7/2009
19160vector<SgDeclarationStatement*>
19161SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19162{
19163 vector<SgDeclarationStatement*> sortedNode;
19164
19165 if (nodevec.size()==0 )
19166 return sortedNode;
19167 // no need to sort if there is only 1 element
19168 if (nodevec.size() ==1)
19169 return nodevec;
19170
19172 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19173 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19174 iter!= queryResult.end(); iter++)
19175 {
19176 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19177 SgNode* cur_node = *iter;
19178 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19179 ROSE_ASSERT(cur_stmt!=NULL);
19180 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19181 // This is true even if the AST only has a defining function declaration.
19182 //
19183 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19184 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19185 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19186 if (func_decl)
19187 {
19188 if (func_decl->get_definingDeclaration() == func_decl )
19189 {
19190 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19191 ROSE_ASSERT (cur_stmt != func_decl);
19192 }
19193 }
19194 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19195 if (i!=nodevec.end())
19196 {
19197 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19198 // We have to make sure only one copy is inserted.
19199 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19200 if (j == sortedNode.end())
19201 sortedNode.push_back(*i);
19202 }
19203 }
19204
19205 if (nodevec.size() != sortedNode.size())
19206 {
19207 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19208 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19209 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19210 {
19211 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19212 }
19213 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19214 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19215 {
19216 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19217 }
19218
19219 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19220 }
19221 return sortedNode;
19222}
19223
19225// This function clears a history map transparently and return a sorted list of dependent declarations
19226std::vector<SgDeclarationStatement*>
19228 {
19229 // This function returns a list of the dependent declaration for any input statement.
19230 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19231#if 0
19232 printf ("\n\n********************************************************** \n");
19233 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19234 printf ("********************************************************** \n");
19235
19237 t.traverse(stmt,preorder);
19238
19239 return t.declarationList;
19240#else
19241 // share a single implementation for recursive lookup for dependent declaration
19242 visitedDeclMap.clear();
19243 vector<SgDeclarationStatement*> declarationList;
19244 vector<SgSymbol*> symbolList;
19245 getDependentDeclarations(stmt, declarationList, symbolList);
19246 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19247#if 0
19248 printf ("\n\n ********************************************************** \n");
19249 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19250 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19251 iter != declarationList.end(); iter++)
19252 {
19253 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19254 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19255 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19256 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19257 }
19258 printf ("\n ********************************************************** \n");
19259#endif
19260
19261 return declarationList;
19262
19263#endif
19264 }
19265
19266
19267bool
19269 {
19270 bool returnValue = false;
19271
19272#if 0
19273 printf ("In SageInterface::isPrefixOperatorName(): functionName = %s (might have to check the return type to distinguish the deref operator from the multiply operator) \n",functionName.str());
19274#endif
19275
19276 if (functionName.is_null() == false)
19277 {
19278 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19279 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19280 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19281 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19282 {
19283 returnValue = true;
19284 }
19285 }
19286
19287 return returnValue;
19288 }
19289
19290
19291// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19293bool
19295 {
19296 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19297 // Also we now support when they are defined as member functions and non-member functions.
19298
19299 bool returnValue = false;
19300
19301 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19302 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19303 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19304
19305 SgName functionName;
19306 size_t numberOfOperands = 0;
19307
19308 if (memberFunctionRefExp != NULL)
19309 {
19310 ROSE_ASSERT(functionRefExp == NULL);
19311 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19312 if (memberFunctionDeclaration != NULL)
19313 {
19314 functionName = memberFunctionDeclaration->get_name();
19315 numberOfOperands = memberFunctionDeclaration->get_args().size();
19316 }
19317 }
19318 else
19319 {
19320 // This could be "friend bool operator!(const X & x);"
19321 if (functionRefExp != NULL)
19322 {
19323 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19324 if (functionDeclaration != NULL)
19325 {
19326 functionName = functionDeclaration->get_name();
19327 numberOfOperands = functionDeclaration->get_args().size();
19328 }
19329 }
19330 else
19331 {
19332 // Note clear if this should be an error.
19333 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19334 }
19335 }
19336
19337#if 0
19338 printf ("In SageInterface::isPrefixOperator(): functionName = %s numberOfOperands = %" PRIuPTR " (might have to check the return type to distinguish the deref operator from the multiply operator) \n",functionName.str(),numberOfOperands);
19339#endif
19340
19341 if (isPrefixOperatorName(functionName) == true)
19342 {
19343 if (memberFunctionRefExp != NULL)
19344 {
19345 // This case is for member functions.
19346 ROSE_ASSERT(functionRefExp == NULL);
19347 if (numberOfOperands == 0)
19348 {
19349 // This is the C++ signature for the operator++() prefix operator.
19350 returnValue = true;
19351 }
19352 else
19353 {
19354 // This is the C++ signature for the operator++() postfix operator.
19355 returnValue = false;
19356 }
19357 }
19358 else
19359 {
19360 // This case is for non-member functions.
19361 ROSE_ASSERT(functionRefExp != NULL);
19362 ROSE_ASSERT(memberFunctionRefExp == NULL);
19363 if (numberOfOperands == 1)
19364 {
19365 // This is the C++ signature for the operator++() prefix operator.
19366 returnValue = true;
19367 }
19368 else
19369 {
19370 // This is the C++ signature for the operator++() postfix operator.
19371 ROSE_ASSERT(numberOfOperands == 2);
19372 returnValue = false;
19373 }
19374 }
19375 }
19376
19377#if 0
19378 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19379#endif
19380
19381 return returnValue;
19382 }
19383
19384
19386bool
19388 {
19389 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19390 }
19391
19392
19394bool
19396 {
19397 bool returnValue = false;
19398 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19399 if (memberFunctionRefExp == NULL)
19400 return false;
19401
19402 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19403 if (memberFunctionDeclaration != NULL)
19404 {
19405 SgName functionName = memberFunctionDeclaration->get_name();
19406 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19407 {
19408 returnValue = true;
19409 }
19410 else
19411 {
19412 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19413 {
19414 returnValue = true;
19415 }
19416 else
19417 {
19418 returnValue = false;
19419 }
19420 }
19421 }
19422
19423 return returnValue;
19424 }
19425
19426
19427// DQ (1/10/2014): Adding more general support for token based unparsing.
19429SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19430 {
19431 // Return the last statement in the associated scope that has token information.
19432 SgStatement* lastStatement = NULL;
19433
19434 ROSE_ASSERT(scope != NULL);
19435
19436#if 0
19437 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19438#endif
19439
19440 SgIfStmt* ifStatement = isSgIfStmt(scope);
19441 if (ifStatement != NULL)
19442 {
19443 lastStatement = ifStatement->get_false_body();
19444 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19445 {
19446 lastStatement = ifStatement->get_true_body();
19447 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19448 {
19449 lastStatement = NULL;
19450 }
19451 }
19452
19453 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19454 if (lastStatement != NULL)
19455 {
19456 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19457 }
19458
19459 return lastStatement;
19460 }
19461
19462 SgStatementPtrList statementList = scope->generateStatementList();
19463 if (statementList.rbegin() != statementList.rend())
19464 {
19465 // Find the last statement with token stream information.
19466 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19467
19468 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19469 {
19470 i++;
19471 }
19472
19473 if (i == statementList.rend())
19474 {
19475 lastStatement = NULL;
19476 }
19477 else
19478 {
19479 lastStatement = *i;
19480 }
19481 }
19482
19483 return lastStatement;
19484 }
19485
19486
19487void
19489 {
19490 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19491
19492 class DeclarationTraversal : public AstSimpleProcessing
19493 {
19494 public:
19495 // DeclarationTraversal() {}
19496
19497 void visit (SgNode* node)
19498 {
19499 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19500 if (decl != NULL)
19501 {
19502 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19503 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19504 SgDeclarationStatement* otherDeclaration = NULL;
19505
19506 // Output access modifier information for each declaration.
19507 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19508 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19509 {
19510 otherDeclaration = decl;
19511 }
19512
19513 if (definingDeclaration != NULL)
19514 {
19515 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19516 }
19517
19518 if (firstNondefiningDeclaration != NULL)
19519 {
19520 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19521 }
19522
19523 if (otherDeclaration != NULL)
19524 {
19525 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19526 }
19527
19528 // Adding space for formatting.
19529 printf ("\n");
19530 }
19531 }
19532 };
19533
19534 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19535 DeclarationTraversal traversal;
19536 traversal.traverse(astNode, preorder);
19537 }
19538
19539
19540void
19542 {
19543 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19544
19545 class ScopeTraversal : public AstSimpleProcessing
19546 {
19547 public:
19548 void visit (SgNode* node)
19549 {
19550 SgScopeStatement* scope = isSgScopeStatement(node);
19551 if (scope != NULL)
19552 {
19553 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19554 if (functionDefinition != NULL)
19555 {
19556 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19557 ROSE_ASSERT(functionDeclaration != NULL);
19558
19559 string functionName = functionDeclaration->get_name();
19560
19561 printf ("functionName = %s \n",functionName.c_str());
19562
19563 if (functionName == "main")
19564 {
19565
19566 SgBasicBlock* functionBody = functionDefinition->get_body();
19567 ROSE_ASSERT(functionBody != NULL);
19568 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19569 ROSE_ASSERT(symbolTable != NULL);
19570
19571 // Print out the symbol table.
19572 symbolTable->print();
19573 }
19574 }
19575
19576 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19577 if (namespaceDefinition != NULL)
19578 {
19579 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19580 ROSE_ASSERT(namespaceDeclaration != NULL);
19581
19582 string namespaceName = namespaceDeclaration->get_name();
19583
19584 printf ("namespaceName = %s \n",namespaceName.c_str());
19585
19586 if (namespaceName == "B")
19587 {
19588 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19589 ROSE_ASSERT(symbolTable != NULL);
19590
19591 // Print out the symbol table.
19592 symbolTable->print();
19593 }
19594 }
19595 }
19596 }
19597 };
19598
19599 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19600 ScopeTraversal traversal;
19601 traversal.traverse(astNode, preorder);
19602 }
19603
19604//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19605void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19606 {
19607#if 0
19608 Sg_File_Info* fileInfo=node->get_file_info();
19609 if (fileInfo != NULL)
19610 {
19611 fileInfo->setTransformation();
19612 fileInfo->setOutputInCodeGeneration();
19613
19614 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19615 if (locatedNode != NULL)
19616 {
19617 // DQ (7/7/2015): Make the subtree as transformed.
19618 locatedNode->setTransformation();
19619 locatedNode->setOutputInCodeGeneration();
19620
19621 // DQ (7/8/2021): Added assertion.
19622 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19623#if 0
19624 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19625#endif
19626 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19627 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19628#if 1
19629 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19630#endif
19631 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19632 // to call setTransformation() and setOutputInCodeGeneration().
19633 markTransformationsForOutput(node);
19634 }
19635 else
19636 {
19637#if 0
19638 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19639#endif
19640 }
19641 }
19642 else
19643 {
19644#if 0
19645 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19646#endif
19647 }
19648#else
19649 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19650 if (locatedNode != NULL)
19651 {
19652 locatedNode->setTransformation();
19653 locatedNode->setOutputInCodeGeneration();
19654
19655 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19656 if (locatedNode->get_file_info() != NULL)
19657 {
19658#if 0
19659 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19660#endif
19661 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19662 }
19663 else
19664 {
19665#if 1
19666 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19667#endif
19668 }
19669
19670 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19671 // to call setTransformation() and setOutputInCodeGeneration().
19672 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19673 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19674 // markTransformationsForOutput(node);
19675 }
19676#endif
19677 }
19678
19679
19680
19681void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19682 {
19683 RoseAst ast(root);
19684 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19685 {
19686 markNodeToBeUnparsed(*i,physical_file_id);
19687 }
19688 }
19689
19690
19691
19693 {
19694 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19695 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19696 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19697 // This function has been implemented as part of debugging this issue.
19698 (void) root; (void) physical_file_id; // defeat clang warning messages
19699
19700 class InheritedAttribute
19701 {
19702 public:
19703 int physical_file_id;
19704 bool isCastSubtree;
19705 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19706 InheritedAttribute(const InheritedAttribute & X)
19707 {
19708 isCastSubtree = X.isCastSubtree;
19709 physical_file_id = X.physical_file_id;
19710 }
19711 };
19712
19713// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19714// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19715#if (__GNUC__ > 4)
19716
19717 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19718 {
19719 public:
19720 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19721 {
19722 InheritedAttribute returnAttribute(inheritedAttribute);
19723
19724 SgCastExp* castExpression = isSgCastExp(node);
19725 if (castExpression != NULL)
19726 {
19727 returnAttribute.isCastSubtree = true;
19728 }
19729
19730 if (returnAttribute.isCastSubtree == true)
19731 {
19732 // Nothing to do, unless we want to fixup the physical node id.
19733#if 0
19734 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19735 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19736#endif
19737 }
19738 else
19739 {
19740#if 0
19741 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19742 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19743#endif
19744 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19745 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19746 }
19747
19748 return returnAttribute;
19749 }
19750 };
19751
19752 InheritedAttribute inheritedAttribute(physical_file_id);
19753
19754 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19755 SubtreeTraversal traversal;
19756
19757#if 0
19758 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19759#endif
19760
19761 traversal.traverse(root, inheritedAttribute);
19762#else
19763 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19764#endif
19765
19766 }
19767
19768
19769
19770
19772vector<SgDeclarationStatement*>
19773generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19774//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19775 {
19776 // Liao suggests adding the target scope to the parameter list so that the constructed function
19777 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19778 // correct scope as soon as possible.
19779
19780 // This function uses the getDependentDeclarations() function to get the dependent declarations
19781 // and then returns a list of copies of each of them.
19782
19783#if 0
19784 printf ("\n\n********************************************************** \n");
19785 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19786 printf ("********************************************************** \n");
19787#endif
19788
19789 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19790 // avoiding call getDependentDeclarations() twice
19791// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19792
19793#if 0
19794 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19795 outputDeclarationList(dependentDeclarations);
19796#endif
19797#if 0
19798 printf ("************************************************ \n");
19799 printf ("*** Make all copies of dependentDeclarations *** \n");
19800 printf ("************************************************ \n");
19801#endif
19802
19803 // Should have a valid scope, so that symbol tables can be expected to be setup.
19804 ROSE_ASSERT(targetScope != NULL);
19805
19806 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19807 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19808
19809 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19810 {
19811#if 0
19812 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19813#endif
19814 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19815
19816 SgNode* copy_node = NULL;
19817 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19818
19819 // For function declarations we don't want to do deep copies on defining declarations
19820 // since that would violate the One-time Definition Rule (ODR).
19821 if (functionDeclaration != NULL)
19822 {
19823 // the target scope may already have a declaration for this function.
19824 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19825 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19826 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19827 // Liao, 5/8/2009
19828
19829 if ( SgProject::get_verbose() >= 1 )
19830 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19831
19832 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19833 // TV (2/4/2014): can be found in the project wide global scope...
19834 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19835#endif
19836#if 0
19837 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19838
19839 printf ("functionDeclaration = %p \n",functionDeclaration);
19840 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19841 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19842 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19843 printf ("targetScope = %p \n",targetScope);
19844#endif
19845 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19846 assert(copy_functionDeclaration != NULL);
19847
19848 copy_functionDeclaration->set_parent(targetScope);
19849
19850 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19851
19852 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19853 // feature of clearing the symbol table used across multiple files.
19854 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19855
19856 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19857
19858 assert(copy_functionDeclaration->get_scope() != NULL);
19859 assert(copy_functionDeclaration->get_scope() == targetScope);
19860 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19861 copy_functionDeclaration->get_type()) != NULL);
19862 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19863 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19864
19865 copy_node = copy_functionDeclaration;
19866#if 0
19867 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19868 ROSE_ABORT();
19869#endif
19870 }
19871 else
19872 {
19873 // We only copy the non-defining declaration of a defining typedef declaration
19874 // since its defining body will be treated as a separate declaration and inserted to the new file.
19875 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19876 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19877 if (tdecl)
19878 {
19879#if 0
19880 if (tdecl->get_definingDeclaration() == tdecl)
19881 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19882 else
19883 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19884#endif
19886 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19887 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
19888 }
19889 else
19890 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19891
19892 // Set the scope now that we know it (might be the same as the parent which will be set when the copy is inserted into the AST).
19893 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
19894 ROSE_ASSERT(copy_declaration != NULL);
19895
19896 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
19897 if (copy_declaration->hasExplicitScope() == true)
19898 copy_declaration->set_scope(targetScope);
19899 }
19900
19901 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19902 // Build a function prototype, but what scope should be used?
19903 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
19904 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
19905
19906#if 0
19907 printf ("DONE: Copying declaration: original = %p = %s = %s to copy = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str(),copy_node,copy_node->class_name().c_str(),SageInterface::get_name(copy_node).c_str());
19908#endif
19909
19910 ROSE_ASSERT(copy_node != NULL);
19911 ROSE_ASSERT(copy_node->get_file_info() != NULL);
19912
19913 // Note that the root of the does not have its file info set like its children.
19914 copy_node->get_file_info()->setTransformation();
19916 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
19917
19918 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
19919 ROSE_ASSERT(copy_definingDeclaration != NULL);
19920
19921 ROSE_ASSERT( *i != NULL );
19922 ROSE_ASSERT(copy_definingDeclaration != NULL);
19923
19924 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
19925 if (copy_definingDeclaration->get_parent() == NULL)
19926 {
19927 copy_definingDeclaration->set_parent(targetScope);
19928 }
19929 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19930
19931#if 0
19932 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
19933#endif
19934
19935 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
19936 copy_definingDeclaration->set_parent(NULL);
19937
19938 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
19939 // copy_definingDeclaration->set_scope(NULL);
19940
19941 // DQ (2/20/2009): Added assertion.
19942 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
19943
19944#if 0
19945 // DQ (2/20/2009): Added assertion.
19946 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
19947 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
19948 {
19949 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
19950 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
19951 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
19952 }
19953#endif
19954
19955 // DQ (2/21/2009): Commented out as a test.
19956 if ((*i)->get_firstNondefiningDeclaration() != NULL)
19957 {
19958 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
19959 }
19960
19961 // DQ (2/20/2009): Added asertion.
19962 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19963
19964 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
19965 }
19966
19967#if 0
19968 printf ("****************************************************** \n");
19969 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
19970 printf ("****************************************************** \n");
19971 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
19972#endif
19973
19974 // The mapping of copies to original declarations should be 1-to-1.
19975 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
19976 // The class body might have a call to an outlined function, which already has a prototype in the target scope and needs no redundant copy
19977 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
19978
19979 return copiesOfDependentDeclarations;
19980 }
19981
19982
19983bool
19984declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
19985 {
19986 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
19987 bool returnValue = false;
19988
19989#if 0
19990 printf ("\n\n********************************************************** \n");
19991 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
19992 printf ("********************************************************** \n");
19993#endif
19994
19995 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
19996
19997 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
19998 // outputPreprocessingInfoList(locallyDependentDeclarationList);
19999
20000 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
20001 {
20002 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
20003#if 0
20004 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20005#endif
20006 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
20007 if (j != dependentDeclarationList.end())
20008 {
20009 // These identified declaration must be output as members of the class when it is output in the separate header file.
20010 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
20011#if 0
20012 printf ("Found a dependent declaration buried in the class definition: locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20013#endif
20014 returnValue = true;
20015 }
20016 }
20017
20018#if 0
20019 printf ("**************************************************************************** \n");
20020 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
20021 printf ("**************************************************************************** \n");
20022#endif
20023
20024 return returnValue;
20025 }
20028{
20029 ROSE_ASSERT (new_exp != NULL);
20030 ROSE_ASSERT (anchor_exp != NULL);
20031 ROSE_ASSERT (new_exp != anchor_exp);
20032
20033 SgNode* parent = anchor_exp->get_parent();
20034 ROSE_ASSERT (parent != NULL);
20035
20036 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
20037 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
20038 ROSE_ASSERT (result != NULL);
20039 replaceExpression (anchor_exp, result, true);
20040
20041 result->set_rhs_operand(anchor_exp);
20042 anchor_exp->set_parent(result);
20043 return result ;
20044}
20045
20046
20048SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
20049{
20050 ROSE_ASSERT (new_exp != NULL);
20051 ROSE_ASSERT (anchor_exp != NULL);
20052 ROSE_ASSERT (new_exp != anchor_exp);
20053
20054 SgNode* parent = anchor_exp->get_parent();
20055 ROSE_ASSERT (parent != NULL);
20056
20057 // insert TYPE T1; right before the enclosing statement of anchor_exp
20058 SgType * t = anchor_exp ->get_type();
20059 ROSE_ASSERT (t != NULL);
20060 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
20061 ROSE_ASSERT (enclosing_stmt != NULL);
20062
20063 gensym_counter ++;
20064 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
20065 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
20066 insertStatementBefore (enclosing_stmt, t_decl);
20067 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
20068 ROSE_ASSERT (temp_sym != NULL);
20069 if (temp_decl)
20070 *temp_decl = t_decl;
20071
20072 // build ((T1 = anchor_exp, new_exp),T1) )
20073 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
20074 if (temp_ref)
20075 * temp_ref = first_ref;
20076 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
20077 replaceExpression (anchor_exp, result, false);
20078
20079 return result;
20080}
20081
20082void
20084 {
20085 // Put out a message in the separate file to lable the dependent CPP directives.
20086 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
20087 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20088 string fileName = "separate-outlined-file";
20089 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
20090 // requiredDirectivesList.push_back(messageToUser);
20091 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
20092
20093 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
20094 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
20095 // when multiple files are used on the command line.
20096 messageToUser->get_file_info()->setTransformation();
20097 }
20098
20099
20100// DQ (2/6/2009): Added function to support outlining into separate file.
20101// Append a function 'decl' into a 'scope', including any referenced declarations required if the scope is within a compiler generated file. All referenced declarations, including those from headers, are inserted if excludeHeaderFiles is set to true (the new file will not have any headers)
20102void
20104 {
20105 // New function to support outlining of functions into separate files (with their required declarations).
20106
20107#if 0
20108 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
20109 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
20110 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
20111 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
20112 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20113 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
20114 if (decl->get_firstNondefiningDeclaration() != NULL)
20115 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20116 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
20117 if (decl->get_definingDeclaration() != NULL)
20118 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
20119#endif
20120
20121#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20122 // Make sure that the input declaration (decl" is consistent in it's representation across more
20123 // than one file (only a significant test when outlining to a separate file; which is what this
20124 // function supports).
20125 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20126 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20127 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20128
20129 // DQ (2/6/2009): I need to write this function to support the
20130 // insertion of the function into the specified scope. If the
20131 // file associated with the scope is marked as compiler generated
20132 // (or as a transformation) then the declarations referenced in the
20133 // function must be copied as well (those not in include files)
20134 // and the include files must be copies also. If the SgFile
20135 // is not compiler generated (or a transformation) then we just
20136 // append the function to the scope (trivial case).
20137
20138 // This code will be based on the work in:
20139 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20140
20141 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20142 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20143
20144 // ***** Also move different loop IR nodes into a common base class *****
20145
20146 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20147
20148 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20149 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20150 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20151 // symbols generated in the copied AST.
20152 // Collect the declaration that the input declaration depends upon.
20153 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20154
20155 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20156
20157 // Generate the copies of all the dependent statements
20158// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20159// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20160 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20161 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20162
20163 // Make sure that the input declaration (decl" is consistent in it's representation across more
20164 // than one file (only a significant test when outlining to a separate file; which is what this
20165 // function supports).
20166 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20167 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20168 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20169
20170 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20171 std::map<SgNode*, SgNode*> replacementMap;
20172
20173 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20174 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20175 // copy mechanism).
20176 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20177 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20178 while (copyNodeMapItrator != copyNodeMap.end())
20179 {
20180 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20181 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20182 // SgNode* first = copyNodeMapItrator->first;
20183 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20184 SgNode* second = copyNodeMapItrator->second;
20185#if 0
20186 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20187#endif
20188 // Add the SgGlobal referenece to the replacementMap
20189 if (isSgSymbol(first) != NULL)
20190 {
20191#if 0
20192 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20193#endif
20194 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20195 }
20196
20197 copyNodeMapItrator++;
20198 }
20199
20200#if 0
20201 printf ("Exiting after test of new functionality \n");
20202 ROSE_ABORT();
20203#endif
20204
20205 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20206 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20207 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20208 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20209
20210 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20211 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20212 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20213 ROSE_ASSERT(originalFileGlobalScope != NULL);
20214 if ( SgProject::get_verbose() >= 1 )
20215 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20216
20217 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20218 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20219 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20220
20221 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20222 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20223 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20224#if 0
20225 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20226
20227 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20228 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20229 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20230#endif
20231
20232 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20233 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20234
20235 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20236 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20237
20238 // Add the SgGlobal referenece to the replacementMap
20239 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20240
20241 // Add the non-defining declarations of the outlined function to the replacementMap
20242 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20243 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20244 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20245 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20246 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20247
20248
20249 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20250 // while (i != declarationList.end())
20251 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20252
20253// cout<<"\n*******************************************\n"<<endl;
20254// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20255 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20256 {
20257 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20258#if 0
20259 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20260 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20261 printf ("originalDeclaration = %p \n",originalDeclaration);
20262
20263 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20264#endif
20265
20266 // DQ (2/20/2009): Added assertion.
20267 ROSE_ASSERT(d->get_parent() == NULL);
20268
20269 // scope->append_declaration(d);
20270 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20271 ROSE_ASSERT(decl->get_scope() == scope);
20272 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20273 scope->insert_statement (decl, d, /* bool inFront= */ true);
20274 d->set_parent (scope);
20275
20276#if 0
20277 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20278#endif
20279
20280 // For whatever type of declaration we add to the global scope in the new separate
20281 // file we have to add the required symbol information to the symbol table.
20282 switch(d->variantT())
20283 {
20284 case V_SgClassDeclaration:
20285 {
20286 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20287 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20288 break;
20289 }
20290
20291 case V_SgMemberFunctionDeclaration:
20292 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20293 ROSE_ABORT();
20294
20295 case V_SgTemplateInstantiationDecl:
20296 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20297 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20298
20299 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20300 ROSE_ABORT();
20301
20302 case V_SgNamespaceDeclarationStatement:
20303 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20304 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20305 break;
20306
20307 case V_SgFunctionDeclaration:
20308 case V_SgTypedefDeclaration:
20309 case V_SgEnumDeclaration:
20310 break;
20311
20312 default:
20313 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20314 ROSE_ABORT();
20315 }
20316
20317
20318 // Collect include directives that are already attached to this dependent declaration.
20319 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20320
20321#if 0
20322 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20323 outputPreprocessingInfoList(requiredDirectivesList);
20324
20325 printf ("directives already attached to dependent declarations \n");
20326 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20327#endif
20328
20329 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20330 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20331 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20332 {
20333 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20334 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20335 ROSE_ASSERT(entry != requiredDirectivesList.end());
20336
20337 requiredDirectivesList.erase(entry);
20338
20339 j++;
20340 }
20341
20342#if 0
20343 printf ("directives AFTER excluding those already present in dependent declarations \n");
20344 outputPreprocessingInfoList(requiredDirectivesList);
20345#endif
20346 }
20347
20348 // Add a message to the top of the outlined function that has been added
20349 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20350
20351 // Insert the dependent declarations ahead of the input "decl".
20352 SgStatement* firstStatmentInFile = NULL;
20353 if (dependentDeclarationList.empty() == true)
20354 {
20355 firstStatmentInFile = decl;
20356 }
20357 else
20358 {
20359 firstStatmentInFile = dependentDeclarationList[0];
20360 }
20361
20362 ROSE_ASSERT(firstStatmentInFile != NULL);
20363
20364 // Add a message to the top of the dependent declarations that have been added
20365 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20366
20367 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20368 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20369 // declarations (which must be in the header file) so we can automate this step.
20370 if (excludeHeaderFiles == false)
20371 {
20372 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20373 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20374 while ( j != requiredDirectivesList.rend() )
20375 {
20376 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20377 j++;
20378 }
20379 }
20380
20381 // Add a message to the top of the CPP directives that have been added
20382 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20383
20384 // ****************************************************************************
20385 // **************** Fixup AST to Reset References To IR nodes ***************
20386 // ****************************************************************************
20387 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20388 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20389 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20390 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20391 // list for update are added to the intermediateDeleteSet.
20392
20393 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20394 ROSE_ASSERT(outlinedFile != NULL);
20395
20396 // This replacement will be done over the entire file (parts of it are redundant with what has already
20397 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20398 // on the outlined function, I think).
20399#if 0
20400 printf ("\n\n************************************************************\n");
20401 printf ("Calling Utils::edgePointerReplacement() \n");
20402#endif
20403
20404 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20405
20406#if 0
20407 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20408 printf ("************************************************************\n\n");
20409
20410 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20411 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20412#endif
20413
20414 // Repeated test from above
20415 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20416
20417// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20418#endif
20419
20420#if 0
20421 // The replacementMap should include the symbols associated with the dependentDeclarationList
20422 // and the outlined function (so dependentDeclarationList.size() + 1).
20423 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20424 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20425#endif
20426 }
20427
20428void
20430 {
20431 using DeletedStatementContainer = std::unordered_set<SgStatement*>;
20432
20433 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20434 //This class defines the visitors for the MemoryPoolTraversal
20435
20436 class ClassicVisitor : public ROSE_VisitorPattern
20437 {
20438 private:
20439 int SgVariableSymbol_count = 0;
20440 int SgFunctionSymbol_count = 0;
20441 int SgClassDeclaration_count = 0;
20442 int SgTypedefSymbol_count = 0;
20443 int SgMemFuncSymbol_count = 0;
20444 int SgTemplateSymbol_count = 0;
20445 int SgEnumFieldSymbol_count = 0;
20446
20447 SgVariableSymbol* SgVariableSymbolPtr = nullptr;
20448 SgFunctionSymbol* SgFunctionSymbolPtr = nullptr;
20449 SgClassSymbol * SgClassSymbolPtr = nullptr;
20450 SgTypedefSymbol * SgTypedefPtr = nullptr;
20451 SgEnumFieldSymbol * SgEnumFieldSymbolPtr = nullptr;
20452 SgMemberFunctionSymbol * SgMemFuncSymbolPtr = nullptr;
20453 SgTemplateSymbol * SgTemplateSymbolPtr = nullptr;
20454 SgClassDeclaration * class_defining = nullptr;
20455 SgTemplateDeclaration * template_defining = nullptr;
20456 SgMemberFunctionDeclaration * memFunc = nullptr;
20457 SgTypedefDeclaration * typedef_defining = nullptr;
20458 SgFunctionDeclaration * function_decl = nullptr;
20459 SgTemplateInstantiationDecl * templateInstantiate_defining = nullptr;
20460 DeletedStatementContainer& deletedStatements;
20461
20462 void markForDeletion(SgStatement* n) { deletedStatements.insert(n); }
20463
20464
20465 public:
20466 ClassicVisitor(SgVariableSymbol* symbol, DeletedStatementContainer& deletedStmt)
20467 : SgVariableSymbolPtr(symbol), deletedStatements(deletedStmt)
20468 {}
20469
20470 ClassicVisitor(SgFunctionSymbol* symbol, DeletedStatementContainer& deletedStmt)
20471 : SgFunctionSymbolPtr(symbol), deletedStatements(deletedStmt)
20472 {}
20473
20474 ClassicVisitor(SgClassSymbol* symbol, DeletedStatementContainer& deletedStmt)
20475 : SgClassSymbolPtr(symbol), deletedStatements(deletedStmt)
20476 {}
20477
20478 ClassicVisitor(SgTypedefSymbol* symbol, DeletedStatementContainer& deletedStmt)
20479 : SgTypedefPtr(symbol), deletedStatements(deletedStmt)
20480 {}
20481
20482 ClassicVisitor(SgMemberFunctionSymbol* symbol, DeletedStatementContainer& deletedStmt)
20483 : SgMemFuncSymbolPtr(symbol), deletedStatements(deletedStmt)
20484 {}
20485
20486 ClassicVisitor(SgTemplateSymbol* symbol, DeletedStatementContainer& deletedStmt)
20487 : SgTemplateSymbolPtr(symbol), deletedStatements(deletedStmt)
20488 {}
20489
20490 ClassicVisitor(SgEnumFieldSymbol* symbol, DeletedStatementContainer& deletedStmt)
20491 : SgEnumFieldSymbolPtr(symbol), deletedStatements(deletedStmt)
20492 {}
20493
20494 ClassicVisitor(SgClassDeclaration* decl, DeletedStatementContainer& deletedStmt)
20495 : class_defining(decl), deletedStatements(deletedStmt)
20496 {}
20497
20498 ClassicVisitor(SgTemplateDeclaration* decl, DeletedStatementContainer& deletedStmt)
20499 : template_defining(decl), deletedStatements(deletedStmt)
20500 {}
20501
20502 ClassicVisitor(SgFunctionDeclaration* decl, DeletedStatementContainer& deletedStmt)
20503 : function_decl(decl), deletedStatements(deletedStmt)
20504 {}
20505
20506 ClassicVisitor(SgMemberFunctionDeclaration* decl, DeletedStatementContainer& deletedStmt)
20507 : memFunc(decl), deletedStatements(deletedStmt)
20508 {}
20509
20510 ClassicVisitor(SgTypedefDeclaration* decl, DeletedStatementContainer& deletedStmt)
20511 : typedef_defining(decl), deletedStatements(deletedStmt)
20512 {}
20513
20514 ClassicVisitor(SgTemplateInstantiationDecl* decl, DeletedStatementContainer& deletedStmt)
20515 : templateInstantiate_defining(decl), deletedStatements(deletedStmt)
20516 {}
20517
20518
20519 // SgVariableSymbol and SgEnumFieldSymbol
20520 void visit(SgInitializedName* node)
20521 {
20522 if(SgVariableSymbolPtr !=NULL)
20523 {
20524 if(node->get_scope()!=NULL)
20525 {
20526 // DQ (5/21/2013): We want to restrict access to the symbol table.
20527 if(node->get_scope()->get_symbol_table()!=NULL)
20528 {
20530 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20531 }
20532 }
20533 }
20534
20535 if(SgEnumFieldSymbolPtr !=NULL)
20536 {
20537 if(node->get_scope()!=NULL)
20538 {
20539 // DQ (5/21/2013): We want to restrict access to the symbol table.
20540 if(node->get_scope()->get_symbol_table()!=NULL)
20541 {
20543 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20544 }
20545 }
20546 }
20547 }
20548
20549 void visit(SgVarRefExp* node)
20550 {
20551 if(SgVariableSymbolPtr !=NULL){
20552 SgVariableSymbol* s = node->get_symbol();
20553 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20554 }
20555 }
20556
20557 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20558 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20559
20560 void visit(SgFunctionDeclaration* node) {
20561 if(SgFunctionSymbolPtr !=NULL) {
20562 if(node->get_scope()!=NULL){
20563 // DQ (5/21/2013): We want to restrict access to the symbol table.
20564 if(node->get_scope()->get_symbol_table()!=NULL)
20565 {
20567 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20568 }
20569 }
20570 }
20571 }
20572
20573 void visit(SgFunctionRefExp* node)
20574 {
20575 if (SgFunctionSymbolPtr !=NULL)
20576 {
20577 SgFunctionSymbol* s = node->get_symbol_i();
20578 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20579 {
20580 SgFunctionSymbol_count++;
20581 }
20582 }
20583 }
20584
20585 void visit(SgMemberFunctionRefExp* node)
20586 {
20587 if (SgFunctionSymbolPtr !=NULL)
20588 {
20589 SgFunctionSymbol* s = node->get_symbol_i();
20590 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20591 {
20592 SgFunctionSymbol_count++;
20593 }
20594 }
20595 }
20596
20597 void visit(SgUserDefinedBinaryOp* node)
20598 {
20599 if (SgFunctionSymbolPtr !=NULL){
20600 SgFunctionSymbol* s = node->get_symbol();
20601 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20602 }
20603 }
20604
20605 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20606
20607 void visit(SgClassDeclaration* node)
20608 {
20609 if(SgClassSymbolPtr !=NULL){
20610 if(node->get_scope()!=NULL){
20611 if(node->get_scope()->get_symbol_table()!=NULL)
20612 {
20614 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20615 }
20616 }
20617 }
20618
20619 if(class_defining!=NULL) {
20620 if(node->get_symbol_from_symbol_table() == NULL){
20623 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20624 markForDeletion(node);
20625 }
20626 }
20627 }
20628
20629 void visit(SgTemplateInstantiationDecl* node)
20630 {
20631 if(SgClassSymbolPtr !=NULL){
20632 if(node->get_scope()!=NULL){
20633 if(node->get_scope()->get_symbol_table()!=NULL)
20634 {
20636 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20637 }
20638 }
20639 }
20640
20641 if(templateInstantiate_defining!=NULL) {
20642 if(node->get_scope()!=NULL){
20643 if(node->get_scope()->get_symbol_table()!=NULL)
20644 {
20645 if(node->get_symbol_from_symbol_table() == NULL){
20648 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20649 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20650 foreach (SgTemplateArgument* element, tempargs){
20651 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20652 if(temparg){
20653 delete temparg;
20654 }
20655 printf("SgTemplateArg in Memory Pool traversal\n");
20656 }*/
20657 markForDeletion(node);
20658 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20659 }
20660 }
20661 }
20662 }
20663 }
20664 }
20665
20666 void visit(SgThisExp* node)
20667 {
20668 if (SgClassSymbolPtr !=NULL){
20669 SgSymbol* s = node->get_class_symbol();
20670 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20671 }
20672 }
20673
20674 void visit(SgClassNameRefExp* node)
20675 {
20676 if (SgClassSymbolPtr !=NULL){
20677 SgSymbol* s = node->get_symbol();
20678 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20679 }
20680 }
20681
20682
20683 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20684
20685
20686 // SgMemberFunctionSymbol
20687 void visit(SgCtorInitializerList* node)
20688 {
20689 if(memFunc !=NULL){
20691 if(func == memFunc){
20692 markForDeletion(node);
20693 }
20694 }
20695 }
20696
20697
20698 void visit(SgMemberFunctionDeclaration* node)
20699 {
20700 if (SgMemFuncSymbolPtr !=NULL){
20701 if(node->get_scope()!=NULL){
20702 if(node->get_scope()->get_symbol_table()!=NULL)
20703 {
20704 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20705 if(symbol == SgMemFuncSymbolPtr){
20706 SgMemFuncSymbol_count++;
20707 }
20708 }
20709 }
20710 }
20711 }
20712
20714 {
20715 if (SgMemFuncSymbolPtr !=NULL){
20716 if(node->get_scope()!=NULL){
20717 if(node->get_scope()->get_symbol_table()!=NULL)
20718 {
20719 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
20720 if(symbol == SgMemFuncSymbolPtr){
20721 SgMemFuncSymbol_count++;
20722 }
20723 }
20724 }
20725 }
20726 }
20727
20728
20729
20730 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
20731
20732
20733 // SgTypedefSymbol
20734 void visit(SgTypedefDeclaration* node)
20735 {
20736 if(SgTypedefPtr!=NULL){
20737 if(node->get_scope()!=NULL){
20738 if(node->get_scope()->get_symbol_table()!=NULL)
20739 {
20741 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
20742 }
20743 }
20744 }
20745 if(typedef_defining!=NULL){
20747 if(typedef_define == typedef_defining && node != typedef_defining ) {
20748 markForDeletion(node);
20749 }
20750 }
20751 }
20752
20753 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
20754
20755
20756
20757 void visit(SgTemplateDeclaration* node)
20758 {
20759 if (SgTemplateSymbolPtr !=NULL){
20760 if(node->get_scope()!=NULL){
20761 if(node->get_scope()->get_symbol_table()!=NULL)
20762 {
20763 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
20764 if(symbol == SgTemplateSymbolPtr){
20765 SgTemplateSymbol_count++;
20766 }
20767 }
20768 }
20769 }
20770
20771 if(template_defining !=NULL) {
20772 if(node->get_scope()!=NULL){
20773 if(node->get_scope()->get_symbol_table()!=NULL)
20774 {
20775 if(node->get_symbol_from_symbol_table() == NULL){
20778 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
20779 markForDeletion(node);
20780
20781 }
20782 }
20783 }
20784 }
20785 }
20786 }
20787
20788 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
20789 };
20790
20791
20792 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
20793 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
20794 {
20795 public:
20796
20797 void visit (SgNode* node)
20798 {
20799 //These nodes are manually deleted because they cannot be visited by the traversal
20801 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
20803 if(isSgInitializedName(node) !=NULL){
20804 //remove SgVariableDefinition
20805 SgDeclarationStatement* var_def;
20806 var_def = ((SgInitializedName *)node)->get_definition();
20807 if(isSgVariableDefinition(var_def) !=NULL){
20808 markForDeletion(var_def);
20809 //printf("A SgVariableDefinition was deleted\n");
20810 }
20811
20812
20813 //remove SgVariableSymbol
20814 if(isSgInitializedName(node)->get_scope()!=NULL){
20815 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
20816 {
20817 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
20818 if(isSgVariableSymbol(symbol) !=NULL){
20819 ClassicVisitor visitor((SgVariableSymbol*)symbol, deletedStatements);
20820 traverseMemoryPoolVisitorPattern(visitor);
20821 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20822 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20823 delete symbol;
20824 //printf("A SgVariableSymbol was deleted\n");
20825 }
20826 }
20827
20828 if(isSgEnumFieldSymbol(symbol) !=NULL){
20829 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol, deletedStatements);
20830 traverseMemoryPoolVisitorPattern(visitor);
20831 if(visitor.get_num_EnumField_pointers()==1){
20832 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20833 delete symbol;
20834 //printf("A SgEnumFieldSymbol was deleted\n");
20835 }
20836 }
20837
20838 }
20839 }
20840 }
20841
20842 if(isSgVarRefExp(node) !=NULL){
20843 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
20844 ClassicVisitor visitor(symbol, deletedStatements);
20845 traverseMemoryPoolVisitorPattern(visitor);
20846 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20847 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20848 delete symbol;
20849 //printf("A SgVariableSymbol was deleted\n");
20850 }
20851 }
20852
20853 /*////////////////////////////////////////////////
20854 /remove SgFunctionSymbol
20856
20857 {
20858 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
20859 if (funcDecl != NULL){
20860 if (isSgMemberFunctionDeclaration(node) == NULL) {
20861 if (funcDecl->get_scope() != NULL) {
20862 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
20863 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20864 ClassicVisitor visitor((SgFunctionSymbol *)symbol, deletedStatements);
20865 traverseMemoryPoolVisitorPattern(visitor);
20866 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
20867 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
20868 delete symbol;
20869 //printf("A SgFunctionSymbol was deleted\n");
20870 }
20871 ClassicVisitor visitor1((SgFunctionDeclaration *)node, deletedStatements);
20872 traverseMemoryPoolVisitorPattern(visitor1);
20873 }
20874 }
20875 }
20876 }
20877 }
20878
20879 if(isSgFunctionRefExp(node) !=NULL)
20880 {
20881 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
20882 ClassicVisitor visitor(symbol, deletedStatements);
20883 traverseMemoryPoolVisitorPattern(visitor);
20884 if(visitor.get_num_Function_pointers()==1)
20885 {
20886 // only one reference to this FunctionSymbol => safe to delete
20887 delete symbol;
20888 }
20889
20890 }
20891
20892 if(isSgUserDefinedBinaryOp(node) !=NULL){
20893 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
20894 ClassicVisitor visitor(symbol, deletedStatements);
20895 traverseMemoryPoolVisitorPattern(visitor);
20896 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
20897 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20898 delete symbol;
20899 //printf("A SgFunctionSymbol was deleted\n");
20900 }
20901 }
20902
20903 /*/
20904 /remove SgTypedefSymbol
20906
20907 if(isSgTypedefDeclaration(node) !=NULL){
20908 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
20909 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
20910 {
20911 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
20912 if(isSgTypedefSymbol(symbol)){
20913 ClassicVisitor visitor((SgTypedefSymbol*) symbol, deletedStatements);
20914 traverseMemoryPoolVisitorPattern(visitor);
20915 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
20916 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
20917 delete symbol;
20918 //printf("A SgTypedefSymbol was deleted\n");
20919 }
20920 }
20921 }
20922 }
20923
20924 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
20925 ClassicVisitor visitor1((SgTypedefDeclaration*) node, deletedStatements);
20926 traverseMemoryPoolVisitorPattern(visitor1);
20927 }
20928 }
20929
20930 /*////////////////////////////////////////////////
20931 /remove SgNamespaceDeclarationSymbol
20933
20934 if(isSgNamespaceDeclarationStatement(node) !=NULL){
20935 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
20936 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
20937 {
20938 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
20939 if(isSgNamespaceSymbol(symbol)){
20940 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
20941 delete symbol;
20942 //printf("A SgNamespaceSymbol was deleted\n");
20943 }
20944 }
20945 }
20946 }
20947
20948
20949 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
20950 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
20951 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
20952 {
20953 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
20954 if(isSgNamespaceSymbol(symbol)){
20955 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
20956 delete symbol;
20957 //printf("A SgNamespaceSymbol was deleted\n");
20958 }
20959 }
20960 }
20961 }
20962
20963
20964 /*/
20965 /remove SgLabelSymbol
20967
20968 if(isSgLabelStatement(node) !=NULL){
20969 if(((SgLabelStatement*)node)->get_scope()!=NULL){
20970 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
20971 {
20972 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
20973 if(isSgLabelSymbol(symbol)){
20974 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
20975 delete symbol;
20976 //printf("A SgLabelSymbol was deleted\n");
20977 }
20978 }
20979 }
20980 }
20981
20982 if(isSgLabelRefExp(node) !=NULL){
20983 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
20984 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20985 delete symbol;
20986 //printf("A SgLabelSymbol was deleted\n");
20987 }
20988
20989
20990 /*////////////////////////////////////////////////
20991 /remove SgEnumSymbol
20993
20994 if(isSgEnumDeclaration(node) !=NULL){
20995 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
20996 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
20997 {
20998 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
20999 if(isSgEnumSymbol(symbol) !=NULL){
21000 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21001 delete symbol;
21002 //printf("A SgEnumSymbol was deleted\n");
21003 }
21004 }
21005 }
21006 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21007 if(type !=NULL){
21008 delete type;
21009 //printf("A SgEnumType was deleted\n");
21010 }
21011 }
21012
21013
21014 /*/
21015 /remove SgClassSymbol
21017
21018 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21019 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21020 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21021 {
21022 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21023 if(isSgClassSymbol(symbol) !=NULL){
21024 ClassicVisitor visitor((SgClassSymbol*)symbol, deletedStatements);
21025 traverseMemoryPoolVisitorPattern(visitor);
21026 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21027 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21028 delete symbol;
21029 //printf("A SgClassSymbol was deleted\n");
21030 }
21031 }
21032 }
21033 }
21034
21035 ClassicVisitor visitor((SgClassDeclaration*) node, deletedStatements );
21036 traverseMemoryPoolVisitorPattern(visitor);
21037
21038 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21039 if(type !=NULL){
21040 delete type;
21041 //printf("A SgClassType was deleted\n");
21042 }
21043 }
21044
21045 if(isSgThisExp(node) !=NULL){
21046 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21047 ClassicVisitor visitor((SgClassSymbol*)symbol, deletedStatements);
21048 traverseMemoryPoolVisitorPattern(visitor);
21049 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21050 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21051 delete symbol;
21052 //printf("A SgClassSymbol was deleted\n");
21053 }
21054
21055 }
21056
21057 if(isSgClassNameRefExp(node) !=NULL){
21058 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21059 if(isSgClassSymbol(symbol) !=NULL)
21060 {
21061 ClassicVisitor visitor((SgClassSymbol*)symbol, deletedStatements);
21062 traverseMemoryPoolVisitorPattern(visitor);
21063 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21064 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21065 delete symbol;
21066 //printf("A SgClassSymbol was deleted\n");
21067 }
21068 }
21069 }
21070
21071 /*////////////////////////////////////////////////
21072 /remove SgMemberFunctionSymbol
21074
21075
21076 if(isSgMemberFunctionDeclaration(node) !=NULL){
21077 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21078 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21079 {
21080 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21081 if(isSgMemberFunctionSymbol(symbol)){
21082 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol, deletedStatements);
21083 traverseMemoryPoolVisitorPattern(visitor);
21084 if(visitor.get_num_memFunc_pointers()==1){
21085 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21086 delete symbol;
21087 //printf("A SgMemberFunctionSymbol was deleted\n");
21088 }
21089 }
21090 }
21091 }
21092 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node, deletedStatements);
21093 traverseMemoryPoolVisitorPattern(visitor);
21094
21095 }
21096
21097 /*/
21100
21101 if(isSgInterfaceStatement(node) !=NULL){
21102 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21103 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21104 {
21105 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21106 if(isSgInterfaceSymbol(symbol)){
21107 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21108 delete symbol;
21109 //printf("A SgInterfaceSymbol was deleted\n");
21110 }
21111 }
21112 }
21113
21114 }
21115
21116
21117 if(isSgModuleStatement(node) !=NULL){
21118 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21119 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21120 {
21121 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21122 if(isSgModuleSymbol(symbol)){
21123 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21124 delete symbol;
21125 //printf("A SgModuleSymbol was deleted\n");
21126 }
21127 }
21128 }
21129
21130 }
21131
21132 // Normal nodes will be removed in a post-order way
21133 if (SgStatement* stmt = isSgStatement(node))
21134 markForDeletion(stmt);
21135 else
21136 delete node;
21137 }
21138
21139 void cleanUpMacrosThenDeleteStatements(SgSourceFile* file)
21140 {
21141 if (file)
21142 {
21143 std::map<SgStatement*,MacroExpansion*>& macroMap = file->get_macroExpansionMap();
21144
21145 for (SgStatement* deletedStmt : deletedStatements)
21146 {
21147 auto pos = macroMap.find(deletedStmt);
21148 if (pos == macroMap.end()) continue;
21149
21150 ASSERT_not_null(pos->second);
21151 std::vector<SgStatement*>& vec = pos->second->associatedStatementVector;
21152 auto const vecLim = vec.end();
21153
21154 vec.erase(std::remove(vec.begin(), vecLim, deletedStmt), vecLim);
21155
21156 macroMap.erase(pos);
21157 }
21158 }
21159
21160 for (SgStatement* deletedStmt : deletedStatements)
21161 delete deletedStmt;
21162 }
21163
21164 void markForDeletion(SgStatement* n) { deletedStatements.insert(n); }
21165
21166 // Delete statements from macros referencing them.
21167 private:
21168 DeletedStatementContainer deletedStatements;
21169 };
21170
21171
21172 // query source file before anything is deleted
21173 SgSourceFile* const sourceFile = getEnclosingSourceFile(n);
21174 DeleteAST deleteTree;
21175
21176 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21177 deleteTree.traverse(n,postorder);
21178 deleteTree.cleanUpMacrosThenDeleteStatements(sourceFile);
21179 }
21180
21181
21182#ifndef USE_ROSE
21183// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21184// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21185// In the post-processing either:
21186// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21187// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21188// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21189// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21190// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21191// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21192// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21193// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21194// that are not use post-processed. This is the special purpose function that we need.
21195//
21196// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21197//
21199 {
21200 struct Visitor: public AstSimpleProcessing
21201 {
21202 virtual void visit(SgNode* n)
21203 {
21204 SgExpression* expression = isSgExpression(n);
21205 if (expression != NULL)
21206 {
21207 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21208 }
21209
21210 delete (n);
21211 }
21212 };
21213
21214 Visitor().traverse(root, postorder);
21215 }
21216#endif
21217 // move symbol table from one scope to another
21218static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21219{
21220 // Move the symbol table
21221 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21222 ASSERT_not_null(sourceBlock->get_symbol_table());
21223 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21224 for (SgInitializedName* iname : initname_vec)
21225 {
21226 SgSymbol* symbol = s_table->find(iname);
21227 ASSERT_not_null(symbol);
21228 }
21229 // entirely move source block's symbol table to target block
21230 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21231
21232 ASSERT_not_null(sourceBlock);
21233 ASSERT_not_null(targetBlock);
21234 ASSERT_not_null(targetBlock->get_symbol_table());
21235 ASSERT_not_null(sourceBlock->get_symbol_table());
21236 targetBlock->get_symbol_table()->set_parent(targetBlock);
21237
21238 ASSERT_not_null(sourceBlock->get_symbol_table());
21239 sourceBlock->set_symbol_table(nullptr);
21240
21241 // Reset with a valid symbol table
21242 sourceBlock->set_symbol_table(new SgSymbolTable());
21243 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21244
21245 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21246 for (SgInitializedName* iname : initname_vec)
21247 {
21248 SgSymbol* symbol = s_table->find(iname);
21249 ASSERT_not_null(symbol);
21250 }
21251
21252 // Liao, 11/26/2019 make sure init names have symbols after the move.
21253 for (SgInitializedName* iname : initname_vec)
21254 {
21255 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21256 ASSERT_not_null(symbol);
21257 }
21258}
21259
21260// helper function to move a single statement or declaration from a block to another
21261static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21262{
21263 // append statement to the target block
21264 targetBlock->append_statement(stmt);
21265
21266 // Make sure that the parents are set.
21267 ASSERT_require(stmt->get_parent() == targetBlock);
21268 if (stmt->hasExplicitScope())
21269 {
21270 if (stmt->get_scope() != targetBlock)
21271 {
21272 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21273 {
21274 // why only move if it is a first nondefining declaration?
21275 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21276 // comment out the if condition for now. 1/20/2021
21277 //
21278 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21279 // The func declaration should be moved along with the call site.
21280 // The scope should be set to the new block also
21281 // Liao 1/14/2011
21282 func->set_scope(targetBlock);
21283 // This is needed to move functions in Ada package body into C++ namespace
21284 // We may have compiler generated first nondefining declaration. We need to move its scope also
21285 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21286 if (func != nondef_decl)
21287 {
21288 ASSERT_not_null(nondef_decl);
21289 ASSERT_not_null(nondef_decl->get_file_info());
21290 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21291 nondef_decl->set_scope(targetBlock);
21292 }
21293 }
21294 }
21295 else if (auto labelStmt = isSgLabelStatement(stmt))
21296 {
21297 if (labelStmt->get_scope() == sourceBlock) {
21298 labelStmt->set_scope(targetBlock);
21299 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21300 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21301 }
21302 }
21303 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21304 {
21305 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21306 // The issues are fixed in the switch statement below but this test is needed
21307 // so that the warning message immediately below is not triggered.
21308 }
21309 else
21310 {
21311 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21312 << stmt->class_name() << "\n";
21313 }
21314 }
21315 }
21316
21317 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21318 if (declaration != nullptr)
21319 {
21320 // Need to reset the scope from sourceBlock to targetBlock.
21321 switch(declaration->variantT())
21322 {
21323 // There will be other cases to handle, but likely not all declaration will be possible to support.
21324
21325 case V_SgVariableDeclaration:
21326 {
21327 // Reset the scopes on any SgInitializedName objects.
21328 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21329 SgInitializedNamePtrList & l = varDecl->get_variables();
21330 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21331 {
21332 // reset the scope, but make sure it was set to sourceBlock to make sure.
21333 // This might be an issue for extern variable declaration that have a scope
21334 // in a separate namespace of a static class member defined external to
21335 // its class, etc. I don't want to worry about those cases right now.
21336
21337 SgInitializedName * init_name = (*ii);
21338
21339 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21340 SgType* var_type = init_name->get_type();
21341 if (SgModifierType* mod_type = isSgModifierType(var_type))
21342 {
21343 var_type = mod_type->get_base_type();
21344 }
21345
21346 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21347 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21348 // be that class types are not moved correctly either.
21349 //
21350 if (isSgEnumType(var_type))
21351 {
21352 SgEnumType* enum_type = isSgEnumType(var_type);
21353 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21354 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21355 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21356
21357 if (decl->get_scope() == sourceBlock)
21358 {
21359 // Needs to be moved
21360 def_decl->set_scope(targetBlock);
21361 nondef_decl->set_scope(targetBlock);
21362 nondef_decl->set_parent(targetBlock);
21363
21364 // Move the scope of the enumerators to the new block as well
21365 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21366 {
21367 enumerator->set_scope(targetBlock);
21368 }
21369 }
21370 }
21371 else if (isSgJovialTableType(var_type))
21372 {
21373 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21374 SgDeclarationStatement* decl = table_type->get_declaration();
21375 if (decl->get_scope() == sourceBlock)
21376 {
21377 // Needs to be moved
21380 def_decl->set_scope(targetBlock);
21381 nondef_decl->set_scope(targetBlock);
21382 nondef_decl->set_parent(targetBlock);
21383 }
21384 }
21385
21386 // Must also move the symbol into the source block, Liao 2019/8/14
21387 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21388 ASSERT_not_null(var_sym);
21389 SgScopeStatement * old_scope = var_sym -> get_scope();
21390#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21391 if (old_scope != sourceBlock)
21392 {
21393 old_scope->remove_symbol (var_sym);
21394 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21395 }
21396#endif
21397 init_name->set_scope(targetBlock);
21398 initname_vec.push_back(init_name);
21399 }
21400 break;
21401 }
21402 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21403 {
21404 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21405 ASSERT_not_null(funcDecl);
21406#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21407 // move function symbols also: search_for_symbol_from_symbol_table()
21409 if (func_sym)
21410 {
21411 SgScopeStatement * old_scope = func_sym -> get_scope();
21412 if (old_scope != sourceBlock)
21413 {
21414 old_scope->remove_symbol (func_sym);
21415 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21416 }
21417 }
21418#endif
21419 break;
21420 }
21421 // needed to move Ada record into definition of C++ namespace
21422 case V_SgProgramHeaderStatement:
21423 case V_SgProcedureHeaderStatement:
21424 case V_SgClassDeclaration:
21425 case V_SgEnumDeclaration:
21426 {
21427 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21428 ASSERT_not_null(nondef_decl);
21429
21430 nondef_decl->set_parent(targetBlock);
21431 nondef_decl->set_scope(targetBlock);
21432
21433 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21434 if (def_decl)
21435 {
21436 def_decl->set_parent(targetBlock);
21437 def_decl->set_scope(targetBlock);
21438 }
21439 else
21440 {
21441 // Set the scope of the function arguments
21442 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21443 for (auto arg : proc->get_parameterList()->get_args()) {
21444 if (arg->get_scope() != proc->get_scope()) {
21445 // Note: arg (is an SgInitializedName) from the parameter list does not have
21446 // a symbol in the scope of the procedure declaration (proc). Should add
21447 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21448 arg->set_scope(proc->get_scope());
21449 }
21450 }
21451 }
21452 }
21453
21454 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21455 if (enum_decl)
21456 {
21457 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21458 for (SgInitializedName* name : enum_decl->get_enumerators())
21459 {
21460 name->set_scope(targetBlock);
21461 }
21462 }
21463 break;
21464 }
21465 case V_SgJovialTableStatement:
21466 {
21467 // [RC-135, Rasmussen 9/21/2020]
21468 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21469 ROSE_ASSERT (table);
21470
21473 nondef_decl->set_parent(targetBlock);
21474 nondef_decl->set_scope(targetBlock);
21475 def_decl->set_scope(targetBlock);
21476 break;
21477 }
21478 case V_SgTypedefDeclaration:
21479 {
21480 // [RC-227, Rasmussen 10/19/2020]
21481 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21482 ASSERT_not_null(typedef_decl);
21483 typedef_decl->set_parent(targetBlock);
21484 typedef_decl->set_scope(targetBlock);
21485 break;
21486 }
21487 case V_SgAttributeSpecificationStatement:
21488 case V_SgEmptyDeclaration:
21489 case V_SgFortranIncludeLine:
21490 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21491 case V_SgJovialDefineDeclaration:
21492 case V_SgJovialDirectiveStatement:
21493 case V_SgJovialLabelDeclaration:
21494 case V_SgJovialOverlayDeclaration:
21495 case V_SgPragmaDeclaration:
21496 case V_SgAdaAttributeClause:
21497 break;
21498 default:
21499 {
21500 printf ("Moving this declaration = %p = %s = %s between blocks is not yet supported \n",declaration,declaration->class_name().c_str(), SageInterface::get_name(declaration).c_str());
21501 declaration->get_file_info()->display("file info");
21502 ROSE_ABORT();
21503 }
21504 }
21505 } // end if
21506}
21507
21508// different handling for scopes with declarations only
21509template <class T1, class T2>
21510void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21511{
21512 // This function moves statements from one block to another (used by the outliner).
21513 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21514 ROSE_ASSERT (sourceBlock && targetBlock);
21515 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21516 if ((void*)sourceBlock == (void*)targetBlock)
21517 {
21518 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21519 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21520 return;
21521 }
21522
21523 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21524 std::vector <SgInitializedName*> initname_vec;
21525
21526 for (auto stmt : srcStmts)
21527 {
21528 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21529 }
21530
21531 // Remove the statements in the sourceBlock
21532 srcStmts.clear();
21533 ROSE_ASSERT(srcStmts.empty() == true);
21534 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21535
21536 // move symbol table from one scope to another
21537 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21538
21539 // Liao 2/4/2009
21540 // Finally , move preprocessing information attached inside the source block to the target block
21541 // Outliner uses this function to move a code block to the outlined function.
21542 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21543 // to the target block to match #if (which is attached
21544 // before some statement moved to the target block)
21545 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21546}
21547
21548
21549// source and destination class, both are derived classes of scope statement but with support of get_statements()
21550template <class T1, class T2>
21551void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21552{
21553 // This function moves statements from one block to another (used by the outliner).
21554 ROSE_ASSERT (sourceBlock && targetBlock);
21555 if ((void*)sourceBlock == (void*)targetBlock)
21556 {
21557 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21558 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21559 return;
21560 }
21561
21562 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
21563 std::vector <SgInitializedName*> initname_vec;
21564
21565 for (SgStatement* stmt : srcStmts)
21566 {
21567 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21568 }
21569
21570 // Remove the statements in the sourceBlock
21571 srcStmts.clear();
21572 ROSE_ASSERT(srcStmts.empty() == true);
21573 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
21574
21575 // move symbol table from one scope to another
21576 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21577
21578 // Liao 2/4/2009
21579 // Finally , move preprocessing information attached inside the source block to the target block
21580 // Outliner uses this function to move a code block to the outlined function.
21581 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21582 // to the target block to match #if (which is attached
21583 // before some statement moved to the target block)
21584 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21585
21586}
21587
21588static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
21589{
21590 ASSERT_not_null(decl);
21592 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
21593
21594 ASSERT_require(local_def && global_def && (local_def!=global_def));
21595
21596 for (auto symbol : local_def->get_symbol_table()->get_symbols())
21597 {
21598 SgSymbol *orig_sym = isSgSymbol(symbol);
21599 ASSERT_not_null(orig_sym);
21600 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
21601 global_def->get_symbol_table()->insert (asym->get_name(), asym);
21602 }
21603}
21604
21605//TODO: now with more types, we need to use template functions
21607{
21608 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21609 //create alias symbols in its global definition
21610 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21611}
21612
21614{
21615 moveStatementsBetweenScopes(sourceBlock, targetBlock);
21616 //create alias symbols in its global definition
21617 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21618}
21619
21621{
21622 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21623}
21624
21625void
21627{
21628 moveStatementsBetweenScopes (sourceBlock, targetBlock);
21629}
21630
21632// TODO, expose to SageInterface namespace
21634{
21635 bool rt = false;
21636 ROSE_ASSERT (func != NULL);
21637 SgNode* p = func->get_parent();
21638 ROSE_ASSERT (p != NULL);
21639 SgLambdaExp* le = isSgLambdaExp (p);
21640 if (le && le->get_lambda_function() == func)
21641 rt = true;
21642 return rt;
21643}
21644
21645// check if a variable reference is this->a[i] inside of a lambda function
21646// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
21647// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
21648// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
21650{
21651 bool rt = false;
21652#ifdef _MSC_VER
21653 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
21654#else
21655 ROSE_ASSERT (varRef!= NULL);
21656 SgNode* parent = varRef->get_parent();
21657 if (SgArrowExp *p = isSgArrowExp(parent))
21658 {
21659 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
21660 if (te != NULL)
21661 {
21662 SgClassSymbol* csym = te->get_class_symbol();
21663 ROSE_ASSERT (csym!= NULL);
21664 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
21665 // each this exp should have a class decl
21666 ROSE_ASSERT (xdecl != NULL);
21667 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
21668 if (le != NULL)
21669 {
21670 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
21671 rt = true;
21672 }
21673 }
21674 }
21675#endif
21676 return rt;
21677}
21678
21681//TODO consult AstInterface::IsVarRef() for more cases
21683{
21684 SgInitializedName* name = NULL;
21685 SgExpression* nameExp = NULL;
21686 ROSE_ASSERT(current != NULL);
21687
21688 if (isSgInitializedName(current))
21689 {
21690 name = isSgInitializedName(current);
21691 }
21692 else if (isSgPntrArrRefExp(current) != NULL)
21693 {
21694 bool suc=false;
21695 SgExpression* exp = isSgExpression(current);
21696 ROSE_ASSERT(exp != NULL);
21697 suc = SageInterface::isArrayReference(exp,&nameExp);
21698 ROSE_ASSERT(suc == true);
21699 // has to resolve this recursively
21700 return convertRefToInitializedName(nameExp, coarseGrain);
21701 }
21702 else if (isSgVarRefExp(current) != NULL)
21703 {
21704 if (coarseGrain)
21705 {
21706 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
21707 SgNode* parent = current->get_parent();
21708 if (isSgDotExp(parent))
21709 {
21710 if (isSgDotExp(parent)->get_rhs_operand() == current)
21711 return convertRefToInitializedName(parent, coarseGrain);
21712 }
21713 // avoid backtracking to parent if this is part of lambda function
21714 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
21715 {
21716 if (isSgArrowExp(parent)->get_rhs_operand() == current)
21717 return convertRefToInitializedName(parent, coarseGrain);
21718 }
21719 }
21720 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
21721 }
21722 else if (isSgFunctionRefExp(current) != NULL ||
21723 isSgTemplateFunctionRefExp(current) != NULL ||
21724 isSgMemberFunctionRefExp(current) != NULL ||
21725 isSgTemplateMemberFunctionRefExp(current) != NULL)
21726 {
21727 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
21728 return NULL;
21729 }
21730 else if (isSgNonrealRefExp(current) != NULL)
21731 {
21732 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
21733 return NULL;
21734 }
21735 else if (isSgDotExp(current))
21736 {
21737 SgExpression* child = NULL;
21738 if (coarseGrain)
21739 child= isSgDotExp(current)->get_lhs_operand();
21740 else
21741 child= isSgDotExp(current)->get_rhs_operand();
21742 ROSE_ASSERT(child);
21743 // has to resolve this recursively
21744 return convertRefToInitializedName(child, coarseGrain);
21745 }
21746 else if (isSgArrowExp(current))
21747 {
21748 SgExpression* child = NULL;
21749 if (coarseGrain)
21750 {
21751 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
21752 ROSE_ASSERT(lhs);
21753 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
21754 // They capture variables outside of the lambda function.
21755 // They are represented as a class variable of an anonymous class, this->a[i]
21756 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
21757 // has to resolve this recursively
21759
21760 if (isLambdaFunction (efunc) )
21761 child= isSgArrowExp(current)->get_rhs_operand();
21762 else
21763 child = lhs;
21764 }
21765 else
21766 child = isSgArrowExp(current)->get_rhs_operand();
21767 ROSE_ASSERT(child);
21768 // has to resolve this recursively
21769
21770 return convertRefToInitializedName(child, coarseGrain);
21771 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
21772 else if (isSgThisExp(current))
21773 {
21774 //SgThisExp* texp = isSgThisExp(current);
21775 name = NULL; // inside a class, there is no initialized name at all!! what to do??
21776 }
21777 else if (isSgPointerDerefExp(current))
21778 {
21779 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
21780 }
21781 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
21782 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
21783 }
21784 else if (isSgCastExp(current))
21785 {
21786 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
21787 }
21788 // Scientific applications often use *(address + offset) to access array elements
21789 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
21790 else if (isSgAddOp(current))
21791 {
21792 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
21793 return convertRefToInitializedName(lhs, coarseGrain);
21794 }
21795 else if (isSgSubtractOp(current))
21796 {
21797 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
21798 return convertRefToInitializedName(lhs, coarseGrain);
21799 }
21800 // operator->() may be called upon a class object.
21801 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
21802 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
21803 {
21804 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
21805 }
21806 else if (isSgIntVal(current))
21807 {
21808 //It is very rare, but sometimes a constant is treated as a
21809 //variable. In which case we don't need an SgInitializdName
21810 return NULL;
21811 }
21812
21813 else
21814 {
21815 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
21816 if (!isSgConstructorInitializer(current))
21817 {
21818 mlog[Sawyer::Message::Common::WARN] <<
21819 "convertRefToInitializedName: " <<
21820 current->get_file_info()->get_filename() << ":" <<
21821 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
21822 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
21823 ROSE_ABORT();
21824 }
21825 }
21826 //ROSE_ASSERT(name != NULL);
21827 return name;
21828}
21829
21832{
21833#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
21834 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
21835 ROSE_ABORT();
21836#else
21838
21839 // trim off the possible leading handle for project: "Project<numbering,1>::"
21840 size_t pos = input_string.find("SourceFile<");
21841 ROSE_ASSERT (pos != string::npos);
21842 string trimed_string = input_string.substr(pos);
21843 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
21844 if (handle)
21845 {
21846 if (handle->getNode()!=NULL)
21847 {
21848#ifdef _MSC_VER
21849 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
21850 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
21851#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
21852 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
21853 ROSE_ABORT();
21854#else
21855 SgNode* result = (SgNode*)(handle->getNode()->getNode());
21856#endif
21857 // deallocate memory, should not do this!!
21858 // May corrupt the internal std maps used in abstract handle namespace
21859 //delete handle->getNode();
21860 //delete handle;
21861 return result;
21862 }
21863 }
21864#endif
21865
21866 return NULL;
21867}
21868
21869
21871// unparseToString() is too strict for debugging purpose
21872// we provide this instead.
21873void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
21874{
21875 ROSE_ASSERT(node != NULL);
21876 cout<<desc<<endl;
21877 // base information for all SgNode:
21878 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
21879 cout<<"--------------base info. for SgNode---------------"<<endl;
21880 cout<<node<<" "<<node->class_name()<<endl;
21881 SgLocatedNode* snode = isSgLocatedNode(node);
21882 if (snode)
21883 {
21884 // source file info. dump
21885 cout<<"--------------source location info. for SgNode---------------"<<endl;
21886 cout<<snode->get_file_info()->get_filename()
21887 << ":"<<snode->get_file_info()->get_line()<<"-"
21888 << snode->get_file_info()->get_col()<<endl;
21889 // preprocessing info dump
21890 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
21891 if (comments)
21892 {
21893 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
21894 AttachedPreprocessingInfoType::iterator i;
21895 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
21896 for (i = comments->begin (); i != comments->end (); i++)
21897 {
21898 PreprocessingInfo * pinfo = *i;
21899 pinfo->display("");
21900 }
21901 }
21902 cout<<"--------------name info. for SgNode---------------"<<endl;
21903 // print out namea for named nodes
21904 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
21905 if (decl)
21906 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
21907 SgVarRefExp * varRef = isSgVarRefExp(snode);
21908 if (varRef)
21909 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
21910 }
21911 SgInitializedName * iname = isSgInitializedName(snode);
21912 if (iname)
21913 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
21914
21915 cout<<endl;
21916 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
21917}
21918
21924bool
21925SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
21926{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
21927 bool retVal = true;
21928
21929 ROSE_ASSERT(stmt !=NULL);
21930
21931#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
21932 // We should allow accumulate the effects for multiple statements
21933 // ROSE_ASSERT(readRefs.size() == 0);
21934 // ROSE_ASSERT(writeRefs.size() == 0);
21935
21936 // convert a request for a defining function declaration to its function body
21937 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
21938 if (funcDecl != NULL)
21939 {
21940 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
21941 if (funcDecl == NULL)
21942 {
21943 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
21944 }
21945 else
21946 stmt = funcDecl->get_definition()->get_body();
21947 }
21948
21949 // get function level information
21950 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
21951 if (!funcDef)
21953
21954 ROSE_ASSERT(funcDef != NULL);
21955 SgBasicBlock* funcBody = funcDef->get_body();
21956 ROSE_ASSERT(funcBody!= NULL);
21957
21958 // prepare Loop transformation environment
21959 AstInterfaceImpl faImpl(funcBody);
21960 AstInterface fa(&faImpl);
21961 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
21962 if( useCachedDefUse ){
21963 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
21964 LoopTransformInterface::set_arrayInfo(array_interface);
21965 } else {
21966 ArrayInterface array_interface(*annot);
21967 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
21968// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
21969 array_interface.observe(fa);
21970 LoopTransformInterface::set_arrayInfo(&array_interface);
21971 }
21972 LoopTransformInterface::set_astInterface(fa);
21973 // Liao, 3/27/2015. connect to annotations for function side effect
21974 LoopTransformInterface::set_sideEffectInfo(annot);
21975
21976 // variables to store results
21977 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
21978 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
21979 AstNodePtr s1 = AstNodePtrImpl(stmt);
21980
21981 // Actual side effect analysis
21982 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
21983 {
21984 //False returned here just means that the function called a
21985 //function that was not annotated with Qing's RWset annotation
21986 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
21987 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
21988 retVal = false;
21989 }
21990
21991 // transfer results into STL containers.
21992 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
21993 {
21994 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
21995 p = rRef1.Next(p);
21996 AstNodePtr cur = p1->GetEntry();
21997 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
21998 ROSE_ASSERT(sgRef != NULL);
21999 readRefs.push_back(sgRef);
22000 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22001 // " sage type:"<< sgRef->class_name()<< endl;
22002 }
22003
22004 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22005 {
22006 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22007 p = wRef1.Next(p);
22008 AstNodePtr cur = p1->GetEntry();
22009 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22010 ROSE_ASSERT(sgRef != NULL);
22011 writeRefs.push_back(sgRef);
22012 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22013 // " sage type:"<< sgRef->class_name()<< endl;
22014 }
22015
22016#endif
22017
22018 return retVal;
22019}
22020#if 0
22021// The side effect analysis will report three references for a statement like this->x = ...
22022// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22023// We only need to keep SgVarRefExp and skip the other two.
22024static bool skipSomeRefs(SgNode* n)
22025{
22026 ROSE_ASSERT (n);
22027 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22028}
22029#endif
22031bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22032{
22033 ROSE_ASSERT(stmt != NULL);
22034 vector <SgNode* > readRefs, writeRefs;
22035
22036 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22037 // process read references
22038 vector<SgNode*>::iterator iter = readRefs.begin();
22039 for (; iter!=readRefs.end();iter++)
22040 {
22041 SgNode* current = *iter;
22042 //if (skipSomeRefs(current)) continue;
22043
22044 ROSE_ASSERT (current != NULL);
22045 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22046 //ROSE_ASSERT (name); // this pointer will return NULL
22047 if (!name) continue;
22048 // Only insert unique ones
22049 // We use std::set to ensure uniqueness now
22050 readVars.insert(name);
22051 }
22052 // process write references
22053 vector<SgNode*>::iterator iterw = writeRefs.begin();
22054 for (; iterw!=writeRefs.end();iterw++)
22055 {
22056 SgNode* current = *iterw;
22057 ROSE_ASSERT (current != NULL);
22058 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22059 if (!name) continue;
22060 //ROSE_ASSERT (name); // this pointer will return NULL
22061 // Only insert unique ones
22062 // We use std::set to ensure uniqueness now
22063 writeVars.insert(name);
22064 }
22065 return retVal;
22066}
22067
22069void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22070{
22071 ROSE_ASSERT(stmt != NULL);
22072 set<SgInitializedName*> readVars, writeVars;
22073 // Only collect read only variables if collectReadWriteVariables() succeeded.
22074 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22075 {
22076 // read only = read - write
22077 set_difference(readVars.begin(), readVars.end(),
22078 writeVars.begin(), writeVars.end(),
22079 std::inserter(readOnlyVars, readOnlyVars.begin()));
22080 }
22081 else // Qing's side effect analysis often fails, we do a simple type based read only variable collection, find all referenced variables of const type
22082 {
22083 RoseAst ast(stmt);
22084
22085 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22086 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22087 {
22088 if (isConstType(v_ref->get_type()))
22089 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22090 }
22091 } // end for
22092 } // end else
22093}
22094
22095
22097void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22098{
22099 set<SgInitializedName*> temp;
22100 collectReadOnlyVariables(stmt, temp, coarseGrain);
22101
22102 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22103 iter!=temp.end(); iter++)
22104 {
22105 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22106 ROSE_ASSERT(symbol != NULL );
22107 ROSE_ASSERT(isSgVariableSymbol(symbol));
22108 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22109 }
22110
22111}
22112
22115{
22116 bool result = false;
22117 ROSE_ASSERT(ref != NULL);
22118 ROSE_ASSERT(ref->get_parent() != NULL);
22119 // case 1: ref is used as an operator for & (SgAddressofOp)
22120 // TODO tolerate possible type casting operations in between ?
22121 if (isSgAddressOfOp(ref->get_parent()))
22122 {
22123 result = true;
22124 }
22125 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22126 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22127 {
22128 SgNode* grandparent = ref->get_parent()->get_parent();
22129 ROSE_ASSERT(grandparent);
22130 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22131 {
22132 // find which parameter ref is in SgExpressionPtrList
22133
22134 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22135 // int param_index = 0;
22136 size_t param_index = 0;
22137
22138 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22139 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22140 for (; iter!=expList.end(); iter++)
22141 {
22142 if (*iter == ref)
22143 break;
22144 else
22145 param_index++;
22146 }
22147 // find the parameter type of the corresponding function declaration
22148 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22149 ROSE_ASSERT (func_exp);
22150 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22151 if (funcRef) // regular functions
22152 {
22153 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22154 SgInitializedNamePtrList nameList = funcDecl->get_args();
22155 //TODO tolerate typedef chains
22156 // printf() has only two arguments to express variable arguments.
22157 // The third argument index ==2 will be out of bounds for nameList[index]
22158 // So we must check the bound first.
22159 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22160 {
22161 if (isSgReferenceType(ref))
22162 result = true;
22163 }
22164 else // now within the bound: two situations,
22165 if (isSgReferenceType(nameList[param_index]->get_type()))
22166 {
22167 result = true;
22168 }
22169 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22170 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22171 {
22172 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22173 ROSE_ASSERT (binOp);
22174 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22175 ROSE_ASSERT (mfuncRef);
22176 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22177 ROSE_ASSERT (mfuncDecl);
22178 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22179 //TODO tolerate typedef chains
22180 if (isSgReferenceType(nameList[param_index]->get_type()))
22181 {
22182 result = true;
22183 }
22184 }
22185
22186 }
22187 }
22188 return result;
22189}
22190
22191
22193void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22194{
22195 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22196
22197 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22198 for (; iter!=var_refs.end(); iter++)
22199 {
22200 SgVarRefExp* ref = isSgVarRefExp(*iter);
22201 ROSE_ASSERT(ref != NULL);
22202 ROSE_ASSERT(ref->get_parent() != NULL);
22203#if 0
22204 // case 1: ref is used as an operator for & (SgAddressofOp)
22205 // TODO tolerate possible type casting operations in between ?
22206 if (isSgAddressOfOp(ref->get_parent()))
22207 {
22208 varSetB.insert(ref);
22209 }
22210 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22211 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22212 {
22213 SgNode* grandparent = ref->get_parent()->get_parent();
22214 ROSE_ASSERT(grandparent);
22215 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22216 {
22217 // find which parameter ref is in SgExpressionPtrList
22218 int param_index =0;
22219 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22220 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22221 for (; iter!=expList.end(); iter++)
22222 {
22223 if (*iter == ref)
22224 break;
22225 else
22226 param_index++;
22227 }
22228 // find the parameter type of the corresponding function declaration
22229 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22230 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22231 SgInitializedNamePtrList nameList = funcDecl->get_args();
22232 //TODO tolerate typedef chains
22233 if (isSgReferenceType(nameList[param_index]->get_type()))
22234 {
22235 varSetB.insert(ref);
22236 }
22237 }
22238 }
22239#endif
22241 varSetB.insert(ref);
22242 }
22243}
22244
22245#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22247LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22248{
22249 // We expect this function to be called multiple times but always return the result generated from the first execution.
22250 static LivenessAnalysis* liv = NULL; // one instance
22251 if (liv!=NULL)
22252 return liv;
22253
22254 static DFAnalysis * defuse = NULL; // only one instance
22255 // Prepare def-use analysis
22256 if (defuse==NULL)
22257 {
22258 ROSE_ASSERT(project != NULL);
22259 defuse = new DefUseAnalysis(project);
22260 }
22261
22262 ROSE_ASSERT(defuse != NULL);
22263 defuse->run(debug);
22264
22265 if (debug)
22266 defuse->dfaToDOT();
22267
22268 //Prepare variable liveness analysis
22269 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22270 ROSE_ASSERT(liv != NULL);
22271
22272 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22273 NodeQuerySynthesizedAttributeType vars =
22274 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22275 NodeQuerySynthesizedAttributeType::const_iterator i;
22276 bool abortme=false;
22277 // run liveness analysis on each function body
22278 for (i= vars.begin(); i!=vars.end();++i)
22279 {
22280 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22281 ROSE_ASSERT(func != NULL);
22282 if (debug)
22283 {
22284 std::string name = func->class_name();
22285 string funcName = func->get_declaration()->get_qualified_name().str();
22286 cout<< " .. running liveness analysis for function: " << funcName << endl;
22287 }
22288 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22289 // propagate results to statement level
22290 liv->fixupStatementsINOUT(func);
22291 if (rem_source.getNode()!=NULL)
22292 dfaFunctions.push_back(rem_source);
22293 if (abortme)
22294 break;
22295 } // end for ()
22296 if(debug)
22297 {
22298 cout << "Writing out liveness analysis results into var.dot... " << endl;
22299 std::ofstream f2("var.dot");
22300 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22301 f2.close();
22302 }
22303 if (abortme) {
22304 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22305 ROSE_ABORT();
22306 }
22307 return liv;
22308 //return !abortme;
22309}
22310#endif
22311
22312#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22314void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22315{
22316 ROSE_ASSERT(liv != NULL);
22317 ROSE_ASSERT(loop != NULL);
22318 SgForStatement *forstmt = loop;
22319 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22320
22321 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22322 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22323 // We have to check the full control flow graph to find all SgForStatement's nodes,
22324 // check the index numbers from 0 , find the one with two out edges (true, false)
22325 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22326 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22327 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22328 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22329 CFGNode cfgnode(forstmt,2);
22330 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22331 // This one does not return the one we want even its getNode returns the
22332 // right for statement
22333 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22334 ROSE_ASSERT(filternode.getNode()==forstmt);
22335
22336 // Check out edges
22337 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22338 ROSE_ASSERT(out_edges.size()==2);
22339 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22340
22341 for (; iter!=out_edges.end();iter++)
22342 {
22343 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22344 //SgForStatement should have two outgoing edges based on the loop condition
22345 // one true(going into the loop body) and one false (going out the loop)
22346 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22347 if (edge.condition()==eckTrue)
22348 {
22349 SgNode* firstnode= edge.target().getNode();
22350 liveIns0 = liv->getIn(firstnode);
22351 // cout<<"Live-in variables for loop:"<<endl;
22352 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22353 iter!=liveIns0.end(); iter++)
22354 {
22355 // SgInitializedName* name = *iter;
22356 liveIns.insert(*iter);
22357 // cout<< name->get_qualified_name().getString()<<endl;
22358 }
22359 }
22360 //x. live-out(loop) = live-in (first-stmt-after-loop)
22361 else if (edge.condition()==eckFalse)
22362 {
22363 SgNode* firstnode= edge.target().getNode();
22364 liveOuts0 = liv->getIn(firstnode);
22365 // cout<<"Live-out variables for loop:"<<endl;
22366 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22367 iter!=liveOuts0.end(); iter++)
22368 {
22369 // SgInitializedName* name = *iter;
22370 // cout<< name->get_qualified_name().getString()<<endl;
22371 liveOuts.insert(*iter);
22372 }
22373 }
22374 else
22375 {
22376 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22377 ROSE_ABORT();
22378 }
22379 } // end for (edges)
22380
22381}
22382#endif
22383
22384//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22385static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22386{
22387 bool isReduction = false;
22388 // Sanity check
22389 ROSE_ASSERT (ref_exp1!= NULL);
22390 ROSE_ASSERT (ref_exp2!= NULL);
22391 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22392 // must be scalar type
22393 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22394
22397 if (stmt != stmt2) return false; // early return false;
22398
22399 // must be assignment statement using
22400 // x= x op expr, x = expr op x (except for subtraction)
22401 // one reference on left hand, the other on the right hand of assignment expression
22402 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22403 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22404 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22405 {
22406 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22407 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22408 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22409 ROSE_ASSERT(assign_lhs && assign_rhs);
22410 // x must show up in both lhs and rhs in any order:
22411 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22412 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22413 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22414 {
22415 // assignment's rhs must match the associative binary operations
22416 // +, *, -, &, ^ ,|, &&, ||
22417 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22418 if (binop!=NULL){
22419 SgExpression* op_lhs = binop->get_lhs_operand();
22420 SgExpression* op_rhs = binop->get_rhs_operand();
22421
22422 // double check that the binary expression has either ref1 or ref2 as one operand
22423 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22424 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22425 return false; // early return false;
22426
22427 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22428 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22429 (op_lhs==ref_exp2))
22430 isOnLeft = true;
22431 switch (binop->variantT())
22432 {
22433 case V_SgAddOp:
22434 {
22435 optype = OmpSupport::e_reduction_plus;
22436 isReduction = true;
22437 break;
22438 }
22439 case V_SgMultiplyOp:
22440 {
22441 optype = OmpSupport::e_reduction_mul;
22442 isReduction = true;
22443 break;
22444 }
22445 case V_SgSubtractOp: // special handle here!!
22446 {
22447 optype = OmpSupport::e_reduction_minus;
22448 if (isOnLeft) // cannot allow (exp - x)a
22449 {
22450 isReduction = true;
22451 }
22452 break;
22453 }
22454 case V_SgBitAndOp:
22455 {
22456 optype = OmpSupport::e_reduction_bitand ;
22457 isReduction = true;
22458 break;
22459 }
22460 case V_SgBitXorOp:
22461 {
22462 optype = OmpSupport::e_reduction_bitxor;
22463 isReduction = true;
22464 break;
22465 }
22466 case V_SgBitOrOp:
22467 {
22468 optype = OmpSupport::e_reduction_bitor;
22469 isReduction = true;
22470 break;
22471 }
22472 case V_SgAndOp:
22473 {
22474 optype = OmpSupport::e_reduction_logand;
22475 isReduction = true;
22476 break;
22477 }
22478 case V_SgOrOp:
22479 {
22480 optype = OmpSupport::e_reduction_logor;
22481 isReduction = true;
22482 break;
22483 }
22484 default:
22485 break;
22486 }
22487 } // end matching associative operations
22488 }
22489 } // end if assignop
22490 return isReduction;
22491}
22492// A helper function for reduction recognition
22493// check if two references to the same variable form a reduction idiom using if-statement
22494// example 1: if (array[i]> maxV) maxV = array[i]
22495// example 2: if (array[i]< minV) minV = array[i]
22496// If it matches, return true and the reduction operator type
22497static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22498{
22499 bool matchStmt1 = false;
22500 bool matchStmt2 = false;
22501
22502 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22503 // SgExpression* reduction_var_ref = NULL;
22504 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22505
22506 // Sanity check
22507 ROSE_ASSERT (ref1 != NULL);
22508 ROSE_ASSERT (ref2 != NULL);
22509 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22510 // must be scalar type
22511 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22512
22515
22516 //early return if the same stmt
22517 if (stmt1 == stmt2) return false;
22518
22519 // check stmt2 first. It is easier.
22520 // stmt2 should be an assignment stmt like:
22521 // reduction_variable = else;
22522 // minV = array[i];
22523 SgExpression* lhs2 = NULL;
22524 SgExpression* rhs2 = NULL;
22525 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22526 {
22527 // lhs2 must be ref2
22528 if (lhs2 == ref2 )
22529 {
22530 matchStmt2 = true;
22531 // reduction_var_ref = lhs2;
22532 // source_var_ref= rhs2;
22533 }
22534 } // end assignment stmt
22535
22536 // stmt1 should be a if-stmt's conditional expression stmt
22537 // and its body should be stmt2
22538 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22539 {
22540 bool matchBody = false;
22541 bool matchCondition= false;
22542 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22543 {
22544 if (SgStatement* body = if_stmt->get_true_body())
22545 {
22546 if (SgBasicBlock* block = isSgBasicBlock (body))
22547 {
22548 // stmt2 must be the only child of the if true body
22549 ROSE_ASSERT(stmt2 != NULL);
22550 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22551 matchBody = true;
22552 }
22553 else
22554 {
22555 if (body == stmt2)
22556 matchBody = true;
22557 }
22558 } // body match test
22559
22560 // match condition SgExprStatement ref1 SgLessThanOp source_var
22561 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
22562 {
22563 SgExpression* cond_exp = cond_exp_stmt->get_expression();
22564 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
22565 {
22566 if (ref1 == binop->get_lhs_operand_i())
22567 {
22568 // minV > array[i] ;
22569 if (isSgLessThanOp (binop))
22570 {
22571 optype = OmpSupport::e_reduction_max;
22572 matchCondition= true;
22573 }
22574 else if (isSgGreaterThanOp(binop))
22575 {
22576 optype = OmpSupport::e_reduction_min;
22577 matchCondition= true;
22578 }
22579 }
22580 else if ( ref1 == binop->get_rhs_operand_i() )
22581 {
22582 // array[i] < minV
22583 if (isSgLessThanOp (binop))
22584 {
22585 optype = OmpSupport::e_reduction_min;
22586 matchCondition= true;
22587 }
22588 else if (isSgGreaterThanOp(binop))
22589 {
22590 optype = OmpSupport::e_reduction_max;
22591 matchCondition= true;
22592 }
22593 }
22594 } // end if binary op
22595 // TODO the source_var should match the source_var from stmt2
22596 }
22597 }
22598 matchStmt1 = matchBody && matchCondition;
22599 } // end if-stmt
22600
22601
22602 return (matchStmt2 && matchStmt1);
22603}
22604
22605// check if a var ref is a form of
22606// --x, x--, ++x, x++
22607// x+= .., x-= ..., etc.
22608// The reduction variable appears only once in the reduction idiom.
22609static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
22610{
22611 bool isReduction = false;
22612
22613 ROSE_ASSERT (ref1 != NULL);
22614 // must be scalar type
22615 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22616
22618
22619 if (isSgExprStatement(stmt))
22620 {
22621 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
22622 SgExpression* binop = isSgBinaryOp(exp);
22623 if (isSgPlusPlusOp(exp)) // x++ or ++x
22624 { // Could have multiple reduction clause with different operators!!
22625 // So the variable list is associated with each kind of operator
22626 optype = OmpSupport::e_reduction_plus;
22627 isReduction = true;
22628 }
22629 else if (isSgMinusMinusOp(exp)) // x-- or --x
22630 {
22631 optype = OmpSupport::e_reduction_minus;
22632 isReduction = true;
22633 }
22634 else
22635 // x binop= expr where binop is one of + * - & ^ |
22636 // x must be on the left hand side
22637 if (binop!=NULL) {
22638 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
22639 if (lhs==ref1)
22640 {
22641 switch (exp->variantT())
22642 {
22643 case V_SgPlusAssignOp:
22644 {
22645 optype = OmpSupport::e_reduction_plus;
22646 isReduction = true;
22647 break;
22648 }
22649 case V_SgMultAssignOp:
22650 {
22651 optype = OmpSupport::e_reduction_mul;
22652 isReduction = true;
22653 break;
22654 }
22655 case V_SgMinusAssignOp:
22656 {
22657 optype = OmpSupport::e_reduction_minus;
22658 isReduction = true;
22659 break;
22660 }
22661 case V_SgAndAssignOp:
22662 {
22663 optype = OmpSupport::e_reduction_bitand;
22664 isReduction = true;
22665 break;
22666 }
22667 case V_SgXorAssignOp:
22668 {
22669 optype = OmpSupport::e_reduction_bitxor;
22670 isReduction = true;
22671 break;
22672 }
22673 case V_SgIorAssignOp:
22674 {
22675 optype = OmpSupport::e_reduction_bitor;
22676 isReduction = true;
22677 break;
22678 }
22679 default:
22680 break;
22681 } // end
22682 }// end if on left side
22683 }
22684 }
22685 return isReduction;
22686}
22687
22689/* This code is refactored from project/autoParallelization/autoParSupport.C
22690 std::vector<SgInitializedName*>
22691 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
22692 * Algorithms:
22693 * for each scalar candidate which are both live-in and live-out for the loop body
22694 * (We don't use liveness analysis here for simplicity)
22695 * and which is not the loop invariant variable (loop index).
22696 * Consider those with only 1 or 2 references
22697 * 1 reference
22698 * the operation is one of x++, ++x, x--, --x, x binop= expr
22699 * 2 references belonging to the same operation
22700 * operations: one of x= x op expr, x = expr op x (except for subtraction)
22701 * The reduction description from the OpenMP 3.0 specification.
22702 * x is not referenced in exp
22703 * expr has scalar type (no array, objects etc)
22704 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
22705 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
22706 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
22707 */
22708void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
22709{
22710 //x. Collect variable references of scalar types as candidates, excluding loop index
22711 SgInitializedName* loopindex;
22712 if (!(isCanonicalForLoop(loop, &loopindex)))
22713 {
22714// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
22715 return;
22716 }
22717 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
22718 //Store the references for each scalar variable
22719 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
22720
22721 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
22722 SgStatement* lbody= loop->get_loop_body();
22723 ROSE_ASSERT(lbody != NULL);
22724 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
22725 for (; iter!=reflist.end(); iter++)
22726 {
22727 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
22728 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
22729 // candidates are of scalar types and are not the loop index variable
22730 // And also should be live-in:
22731 // not declared locally (var_scope equal or lower than loop body )
22732 // or redefined (captured by ref count)
22733 SgScopeStatement* var_scope = initname->get_scope();
22734 ROSE_ASSERT(var_scope != NULL);
22735 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
22736 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
22737 {
22738 candidateVars.insert(initname);
22739 var_references[initname].push_back(ref_exp);
22740 }
22741 }
22742
22743 //Consider variables referenced at most twice
22744 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
22745 for (; niter!=candidateVars.end(); niter++)
22746 {
22747 SgInitializedName* initname = *niter;
22748 bool isReduction = false;
22749 OmpSupport::omp_construct_enum optype;
22750 // referenced once only
22751 if (var_references[initname].size()==1)
22752 {
22753 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
22754 SgVarRefExp* ref_exp = *(var_references[initname].begin());
22755 if (isSingleAppearanceReduction (ref_exp, optype))
22756 isReduction = true;
22757 }
22758 // referenced twice within a same statement
22759 else if (var_references[initname].size()==2)
22760 {
22761 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
22762 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
22763 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
22764 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
22765 // TODO: recognize maxV = max (maxV, array[i])
22766 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
22767 {
22768 isReduction = true;
22769 }
22770
22771 }// end referenced twice
22772
22773 if (isReduction)
22774 results.insert(make_pair(initname,optype));
22775 }// end for ()
22776}
22777
22780{
22781 ROSE_ASSERT(r!=NULL);
22782#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22783 ConstantFolding::constantFoldingOptimization(r,false);
22784#endif
22785}
22786
22789{
22791 {
22792 public:
22793 virtual void visit (SgNode * n)
22794 {
22795 SgExpression* exp = isSgExpression(n);
22796 if (exp)
22797 {
22798 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
22799 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
22800 ROSE_ASSERT (name_attribute != NULL);
22801 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
22802 }
22803 }
22804 };
22805 visitorTraversal exampleTraversal;
22806 //Sriram FIX: should traverse using the traverse function
22807 // exampleTraversal.traverseInputFiles(project,preorder);
22808 exampleTraversal.traverse(project, preorder);
22809}
22810
22811
22812 //
22813 // wrap free-standing function body in another function
22814
22816 {
22817 ROSE_ASSERT(vardecl.get_variables().size());
22818
22819 return *vardecl.get_variables().front();
22820 }
22821
22822#if 0
22823 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
22824 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
22825
22833 static
22835 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
22836 {
22837 namespace SB = SageBuilder;
22838
22839 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
22840 const SgInitializedNamePtrList& orig_decls = params.get_args();
22841
22842 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
22843
22844 return copy;
22845 }
22846#endif
22847
22848#if 0
22849 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
22850
22852 static
22853 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
22854 {
22855 // swap definitions
22856 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
22857 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
22858
22859 // \todo do we need to swap also exception spec, decorator_list, etc. ?
22860 }
22861#endif
22862
22863#if 0
22864 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
22865 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
22866
22867 std::pair<SgStatement*, SgInitializedName*>
22868 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
22869 {
22870 namespace SB = SageBuilder;
22871
22872 // handles freestanding functions only
22873 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
22874 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
22875
22876 // clone function parameter list
22877 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
22878
22879 // create new function definition/declaration in the same scope
22880 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
22881 SgType* result_type = definingDeclaration.get_type()->get_return_type();
22882 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
22883
22884 // DQ (4/9/2015): Suggested fix for this function.
22885 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
22886 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
22887
22888 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
22889 ROSE_ASSERT(wrapperdef);
22890
22891 // copy the exception specification
22892 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
22893
22894 // swap the original's function definition w/ the clone's function def
22895 // and the original's func parameter list w/ the clone's parameters
22896 swapDefiningElements(definingDeclaration, *wrapperfn);
22897
22898 // call original function from within the defining decl's body
22899 SgBasicBlock* body = wrapperdef->get_body();
22900 SgExprListExp* args = SB::buildExprListExp();
22901 SgInitializedNamePtrList& param_decls = param_list.get_args();
22902
22903 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
22904
22905 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
22906 SgInitializedName* resultName = NULL;
22907 SgStatement* callStatement = NULL;
22908
22909 // \todo skip legal qualifiers that could be on top of void
22910 if (!isSgTypeVoid(result_type))
22911 {
22912 // add call to original function and assign result to variable
22913 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
22914 SgVarRefExp* resref = SB::buildVarRefExp( res );
22915
22916 appendStatement(res, body);
22917
22918 // add return statement, returning result
22919 resultName = &getFirstVariable(*res);
22920 callStatement = res;
22921
22922 appendStatement(SB::buildReturnStmt(resref), body);
22923 }
22924 else
22925 {
22926 // add function call statement to original function
22927 callStatement = SB::buildExprStatement(callWrapped);
22928 appendStatement(callStatement, body);
22929 }
22930
22931 ROSE_ASSERT(callStatement);
22932
22933 // create non defining declaration
22934 SgExprListExp* decorator_proto = deepCopy( decorators );
22935 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
22936
22937 // add the new functions at the proper location of the surrounding scope
22938 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
22939 insertStatementAfter (&definingDeclaration, wrapperfn);
22940
22941 return std::make_pair(callStatement, resultName);
22942 }
22943#endif
22944
22945 //
22946 // flatten C/C++ array dimensions
22947 namespace
22948 {
22949 struct VarrefBuilder
22950 {
22951 virtual SgVarRefExp* get() const = 0;
22952
22953 static
22954 SgVarRefExp* build(const SgVarRefExp& n)
22955 {
22956 return SageInterface::deepCopy(&n);
22957 }
22958
22959 static
22961 {
22962 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
22963
22964 return SageBuilder::buildVarRefExp(&n, scope);
22965 }
22966 };
22967
22968 template <class AstNode>
22969 struct VarrefCreator : VarrefBuilder
22970 {
22971 AstNode& origin;
22972
22973 explicit
22974 VarrefCreator(AstNode& orig)
22975 : origin(orig)
22976 {}
22977
22978 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
22979 };
22980
22981 template <class AstNode>
22982 VarrefCreator<AstNode>
22983 varrefCreator(AstNode& n)
22984 {
22985 return VarrefCreator<AstNode>(n);
22986 }
22987
22988 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
22989 {
22990 namespace SB = SageBuilder;
22991 namespace SI = SageInterface;
22992
22993 // we own the lhs (intermediate result),
22994 // but we do not own the rhs (another top-level expression)
22995 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
22996 }
22997
22998 std::pair<std::vector<SgExpression*>, SgType*>
22999 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23000 {
23001 namespace SB = SageBuilder;
23002 namespace SI = SageInterface;
23003
23004 const SgArrayType* arrtype = &arr_type;
23005 std::vector<SgExpression*> indices;
23006 SgType* undertype = NULL;
23007
23008 // \todo when get_index() does not return a nullptr anymore
23009 // the condition can be removed
23010 if (arrtype->get_index() == NULL)
23011 {
23012 indices.push_back(SB::buildNullExpression());
23013 undertype = arrtype->get_base_type();
23014 arrtype = isSgArrayType(undertype);
23015 }
23016
23017 while (arrtype)
23018 {
23019 SgExpression* indexexpr = arrtype->get_index();
23020 ROSE_ASSERT(indexexpr);
23021
23022 indices.push_back(SI::deepCopy(indexexpr));
23023 undertype = arrtype->get_base_type();
23024 arrtype = isSgArrayType(undertype);
23025 }
23026
23027 ROSE_ASSERT((!indices.empty()) && undertype);
23028 return std::make_pair(indices, undertype);
23029 }
23030
23032 std::vector<SgExpression*>
23033 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23034 {
23035 namespace SB = SageBuilder;
23036
23037 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23038 const std::vector<SgExpression*>::iterator first = res.first.begin();
23039
23040 // if the first dimension was open, create the expression for it
23041 if (isSgNullExpression(*first))
23042 {
23043 // handle implicit first dimension for array initializers
23044 // for something like
23045 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23046 // we can calculate the first dimension as
23047 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23048
23049 const std::vector<SgExpression*>::iterator aa = first+1;
23050 const std::vector<SgExpression*>::iterator zz = res.first.end();
23051
23052 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23053 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23054 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23055 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23056
23057 std::swap(*first, sz);
23058 delete sz;
23059 }
23060
23061 return res.first;
23062 }
23063 }
23064
23065 std::vector<SgExpression*>
23067 {
23068 return get_C_array_dimensions_aux(arrtype).first;
23069 }
23070
23071 std::vector<SgExpression*>
23073 {
23074 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23075 }
23076
23077 std::vector<SgExpression*>
23079 {
23080 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23081 }
23082
23083// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23085 {
23086 public:
23087 set<unsigned int> sourceSequenceSet;
23088
23089 void visit ( SgNode* astNode );
23090 };
23091
23092// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23093void
23095 {
23096 Sg_File_Info* fileInfo = astNode->get_file_info();
23097 if (fileInfo != NULL)
23098 {
23099 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23100#if 0
23101 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23102#endif
23103 sourceSequenceSet.insert(source_sequence_number);
23104 }
23105 }
23106
23107// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23108set<unsigned int>
23110 {
23112
23113 traversal.traverse(astNode,preorder);
23114
23115 return traversal.sourceSequenceSet;
23116
23117 }
23118
23119/*Winnie, loop collapse, collapse nested for loops into one large for loop
23120 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23121 * loop scope, and used inside the loop scope.
23122 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23123 * transOmpCollpase(..) function in omp_lowering.cpp.
23124 *
23125 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23126 *
23127 *
23128 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23129 *
23130 * to collapse two level of loops:
23131 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23132 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23133 * total_iteration_count = iteration_count_one * iteration_count_two
23134 *
23135 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23136 *
23137 * Example 1:
23138 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23139 * {
23140 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23141 * {
23142 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23143 * {
23144 * a[i][j][l]=i+j+l;
23145 * }
23146 * }
23147 * }
23148 *
23149 *==> translated output code ==>
23150 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23151 * int j_nom_2_total_iters = (lb1 - (ub1 + 1) + 1) % (inc1 * -1) == 0?(lb1 - (ub1 + 1) + 1) / (inc1 * -1) : (lb1 - (ub1 + 1) + 1) / (inc1 * -1) + 1;
23152 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23153 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23154 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23155 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23156 * int l_nom_3_interval = 1;
23157 *
23158 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23159 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23160 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23161 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23162 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23163 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23164 * }
23165 *
23166 * Example 2 with concrete numbers:
23167 *
23168 * // collapse the following two level of for loops:
23169 * for (i=1; i<=9; i+=1) //incremental for loop
23170 * {
23171 * for(j=10; j>=1; j+=-2) //decremental for loop
23172 * {
23173 * a[i][j]=i+j;
23174 * }
23175 * }
23176 * // it becomes
23177 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23178 * // ub = 45
23179 * // lb = 0
23180 *
23181 * int i_nom_1_total_iters = 9;
23182 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23183 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23184 *
23185 * int i_nom_1_interval = 5;
23186 *
23187 * for (z=0; z<=44; z+=1)
23188 * {
23189 * i_nom_1 = z / 5 + 1;
23190 * j_nom_2 = -(z % 5 * 2) + 10;
23191 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23192 * }
23193 * // for the generated loop, a few compiler generated variables are introduced
23194 * final_total_iters for the collapsed loop
23195 * i_interval for each of the n-1 loops
23196 **
23197*/
23198
23199#ifndef USE_ROSE
23201{
23202#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23203 //Handle 0 and 1, which means no collapsing at all
23204 if (collapsing_factor <= 1)
23205 return NULL;
23206
23207 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23208
23209 /*
23210 *step 1: grab the target loops' header information
23211 */
23212 SgForStatement *& target_loop = loop;
23213
23214 // we use global scope to help generate unique variable name later
23215 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23216 SgGlobal* global_scope = getGlobalScope (loop);
23217 ROSE_ASSERT (global_scope != NULL);
23218 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23219 SgExpression** lb = new SgExpression*[collapsing_factor];
23220 SgExpression** ub = new SgExpression*[collapsing_factor];
23221 SgExpression** step = new SgExpression*[collapsing_factor];
23222 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23223
23224 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23225 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23226 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23227
23228
23229 //Winnie, get loops info first
23230 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23231 ROSE_ASSERT(loops.size()>=collapsing_factor);
23232
23233 SgForStatement* temp_target_loop = NULL;
23234 SgExpression* temp_range_exp = NULL; //Raw iteration range
23235 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23236 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23237 SgExpression* temp_total_iter = NULL;
23238 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23239
23240 /*
23241 * get lb, ub, step information for each level of the loops
23242 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23243 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23244 */
23245
23246 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23247 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23248
23249 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23250
23251 while(scope == NULL)
23252 {
23253 parent = isSgStatement(parent->get_parent());
23254 scope = isSgScopeStatement(parent);
23255 }
23256
23257 SgStatement* insert_target = findLastDeclarationStatement(scope);
23258 if (insert_target != NULL)
23259 insert_target = getNextStatement(insert_target);
23260 else
23261 insert_target = getFirstStatement(scope);
23262
23263 ROSE_ASSERT(scope != NULL);
23264
23265
23266 for(size_t i = 0; i < collapsing_factor; i ++)
23267 {
23268 temp_target_loop = loops[i];
23269
23270 // normalize the target loop first // adjust to numbering starting from 0
23271 forLoopNormalization(temp_target_loop);
23272
23273 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23274 {
23275 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23276 dumpInfo(target_loop);
23277
23278 // release memory
23279 delete[] ivar;
23280 delete[] lb;
23281 delete[] ub;
23282 delete[] step;
23283 delete[] orig_body;
23284 delete[] total_iters;
23285 delete[] interval;
23286 delete[] isPlus;
23287
23288 return NULL;
23289 }
23290
23291 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23292
23293
23294//Winnie, (ub[i]-lb[i]+1)%step[i] ==0?(ub[i]-lb[i]+1)/step[i]: (ub[i]-lb[i]+1)/step[i]+1; (need ceiling) total number of iterations in this level (ub[i] - lb[i] + 1)/step[i]
23295 if(isPlus[i] == true)
23296 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23297 else{
23298 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23299 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23300 }
23301 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23302
23303 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23304
23305 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23306
23307 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23308 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23309 string iter_var_name= "_total_iters";
23310 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23311 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23312 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23313 insertStatementBefore(insert_target, total_iter);
23314 constantFolding (total_iter);
23315 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23316 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23317 }
23318
23319
23320 /*
23321 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23322 */
23323
23324 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23325 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23326 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23327 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23328 insertStatementBefore(insert_target, final_total_iter);
23329 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23330 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23331
23332 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23333 for(unsigned int i = 0; i < collapsing_factor; i++)
23334 {
23335 interval[i] = buildIntVal(1);
23336 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23337 {
23338 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23339 }
23340 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23341 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23342 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23343 insertStatementBefore(insert_target, temp_interval);
23344 interval[i] = buildVarRefExp(interval_name, scope);
23345 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23346 }
23347
23348
23349 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23350 scope = getScope(target_loop);
23351
23352 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23353 //Winnie, declare a brand new var as the new index
23354 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23355 ROSE_ASSERT(insert_target != NULL);
23356 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23357 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23358 insertStatementBefore(insert_target, new_index_decl);
23359 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23360 new_var_list->append_expression(clps_index_ref);
23361
23362// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23363
23364
23365 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23366 ROSE_ASSERT(body != NULL);
23367 SgExpression* new_exp = NULL;
23368 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23369 std::vector<SgStatement*> new_stmt_list;
23370
23371 SgExprStatement* assign_stmt = NULL;
23372
23373 /* Winnie
23374 * express old iterator variables (i_norm, j_norm ...) with new_index,
23375 * new_exp, create new expression for each of the iterators
23376 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23377 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23378 * create a new var to store total_iters[i]
23379 */
23380 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23381 {
23382 if(isPlus[i] == true)
23383 new_exp = buildAddOp(buildMultiplyOp(buildDivideOp(copyExpression(remain_exp_temp), copyExpression(interval[i])), step[i]), copyExpression(lb[i])); //Winnie, (i_remain/interval[i])*step[i] + lb[i]
23384 else
23385 new_exp = buildAddOp(buildMinusOp(buildMultiplyOp(buildDivideOp(copyExpression(remain_exp_temp), copyExpression(interval[i])), step[i])), copyExpression(lb[i])); //Winnie, -(i_remain/interval[i])*step[i] + lb[i], for decremental loop
23386
23387 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23388 new_stmt_list.push_back(assign_stmt);
23389 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23390
23391 if(i != collapsing_factor - 2){ //Winnie, if this is the second last level of loop, no need to create new variable to hold the remain_value, or remove the original index variable declaration
23392 string remain_var_name= "_remainder";
23393 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23394 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23395 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23396 new_stmt_list.push_back(loop_index_decl);
23397 }
23398 new_exp = NULL;
23399 }
23400
23401//Winnie, the inner most loop, iter
23402 if(isPlus[collapsing_factor - 1] == true)
23403 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23404 else
23405 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23406 new_stmt_list.push_back(assign_stmt);
23407 prependStatementList(new_stmt_list, body);
23408
23409 /*
23410 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23411 */
23412 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23413
23414 //Winnie, build the new conditional expression/ub
23415 SgExprStatement* cond_stmt = NULL;
23416 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23417 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23418 ROSE_ASSERT(cond_stmt != NULL);
23419
23420 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23421 new_loop->set_parent(scope); //TODO: what's the correct parent?
23422
23423 replaceStatement(target_loop, new_loop);
23424
23425 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23426 // constant folding for the transformed AST
23427 ConstantFolding::constantFoldingOptimization(scope->get_parent(),false); //Winnie, "scope" is the scope that contains new_loop, this is the scope where we insert some new variables to store interation count and intervals
23428
23429 delete [] ivar;
23430 delete [] lb;
23431 delete [] ub;
23432 delete [] step;
23433 delete [] orig_body;
23434 delete [] total_iters;
23435 delete [] interval;
23436 delete [] isPlus;
23437
23438 #endif
23439
23440 return new_var_list;
23441}
23442
23443
23444
23445bool
23447 {
23448 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23449
23450#ifndef USE_CMAKEx
23451 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23452
23453 // This is AST container for the ROSE AST that will provide an iterator.
23454 // We want two iterators (one for the copy of the snippet and one for the
23455 // original snippet so that we can query the original snippet's AST
23456 // as we process each IR node of the AST for the copy of the snippet.
23457 // Only the copy of the snippet is inserted into the target AST.
23458 RoseAst ast_of_copy(tree1);
23459 RoseAst ast_of_original(tree2);
23460
23461 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23462
23463 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23464 RoseAst::iterator i_copy = ast_of_copy.begin();
23465 RoseAst::iterator i_original = ast_of_original.begin();
23466
23467 // Iterate of the copy of the snippet's AST.
23468 while (i_copy != ast_of_copy.end())
23469 {
23470#if 0
23471 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23472 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23473#endif
23474 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23475 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23476 if ((*i_copy)->variantT() != (*i_original)->variantT())
23477 {
23478#if 0
23479 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23480#endif
23481#if 0
23482 printf ("Making this an error! \n");
23483 ROSE_ABORT();
23484#endif
23485 return false;
23486 }
23487
23488 i_copy++;
23489
23490 // Verify that we have not reached the end of the ast for the original (both the
23491 // copy and the original are the same structurally, and thus the same size).
23492 ROSE_ASSERT(i_original != ast_of_original.end());
23493 i_original++;
23494 }
23495
23496 // We have reached the end of both ASTs.
23497 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23498#endif
23499
23500 return true;
23501 }
23502
23503
23504#endif
23505
23507 SgForStatement * for_loop,
23508 SgVariableSymbol * & iterator,
23509 SgExpression * & lower_bound,
23510 SgExpression * & upper_bound,
23511 SgExpression * & stride
23512) {
23515
23516 iterator = NULL;
23517 lower_bound = NULL;
23518 upper_bound = NULL;
23519 stride = NULL;
23520
23521 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23522 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23523 assert(init_stmts.size() == 1);
23524 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23525 assert(init_stmt != NULL);
23526 SgExpression * init = init_stmt->get_expression();
23527
23528 SgAssignOp * assign_init = isSgAssignOp(init);
23529 assert(assign_init != NULL);
23530 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23531 assert(iterator_init_ref != NULL);
23532 iterator = iterator_init_ref->get_symbol();
23533 assert(iterator != NULL);
23534 lower_bound = assign_init->get_rhs_operand_i();
23535
23536 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23537 assert(test_stmt != NULL);
23538 SgExpression * test = test_stmt->get_expression();
23539 SgBinaryOp * bin_test = isSgBinaryOp(test);
23540 assert(bin_test);
23541
23542 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23543 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23544 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23545 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23546
23547 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23548 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23549 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23550#ifndef NDEBUG
23551 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23552
23553// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23554// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
23555// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
23556// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
23557// value. Since these are boolean typed values we can use "a != b", directly.
23558// assert(lhs_it xor rhs_it);
23559 assert(lhs_it != rhs_it);
23560#endif
23561
23562 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
23563
23564 bool inclusive;
23565 bool reversed;
23566
23567 switch (test->variantT()) {
23568 case V_SgGreaterOrEqualOp:
23569 inclusive = lhs_it;
23570 reversed = lhs_it;
23571 break;
23572 case V_SgGreaterThanOp:
23573 inclusive = !lhs_it;
23574 reversed = lhs_it;
23575 break;
23576 case V_SgLessOrEqualOp:
23577 inclusive = lhs_it;
23578 reversed = !lhs_it;
23579 break;
23580 case V_SgLessThanOp:
23581 inclusive = !lhs_it;
23582 reversed = !lhs_it;
23583 break;
23584 case V_SgEqualityOp:
23585 case V_SgNotEqualOp:
23586 default:
23587 ROSE_ABORT();
23588 }
23589
23590 SgExpression * increment = for_loop->get_increment();
23591 switch (increment->variantT()) {
23592 case V_SgPlusPlusOp:
23593 assert(!reversed);
23594 stride = SageBuilder::buildIntVal(1);
23595 break;
23596 case V_SgMinusMinusOp:
23597 assert(reversed);
23598 stride = SageBuilder::buildIntVal(-1);
23599 break;
23600 case V_SgPlusAssignOp:
23601 {
23602 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23603#ifndef NDEBUG
23604 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23605 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23606#endif
23607 stride = bin_op->get_rhs_operand_i();
23608 break;
23609 }
23610 case V_SgMinusAssignOp:
23611 {
23612 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23613#ifndef NDEBUG
23614 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23615 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23616#endif
23617 stride = bin_op->get_rhs_operand_i();
23618 break;
23619 }
23620 case V_SgAssignOp:
23621 {
23622 SgAssignOp * assign_op = (SgAssignOp *)increment;
23623#ifndef NDEBUG
23624 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
23625 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
23626#endif
23627 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
23628 assert(inc_assign_rhs != NULL);
23629 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
23630 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
23631 stride = inc_assign_rhs->get_rhs_operand_i();
23632 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
23633 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
23634 stride = inc_assign_rhs->get_lhs_operand_i();
23635 break;
23636 }
23637 default:
23638 ROSE_ABORT();
23639 }
23640
23641 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
23642 if (!inclusive)
23643 {
23644 if (reversed)
23645 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
23646 else
23647 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
23648 }
23649
23650 return true;
23651}
23652
23653//------------------------------------------------------------------------------
23654#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
23655//------------------------------------------------------------------------------
23656
23661 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
23662
23663 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
23664 ROSE_ASSERT(utf8);
23665 string directory_name = utf8;
23666 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
23667
23668 list<string> sourcepath = project -> get_Java_sourcepath();
23669 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
23670 project -> set_Java_sourcepath(sourcepath);
23671
23672 return directory_name;
23673}
23674
23675
23679void SageInterface::destroyTempDirectory(string directory_name) {
23680 string command = string("rm -fr ") + directory_name;
23681 int status = system(command.c_str());
23682 ROSE_ASSERT(status == 0);
23683}
23684
23685
23689SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
23690 //
23691 // Set up the new source file for processing "a la Rose".
23692 //
23693 project -> get_sourceFileNameList().push_back(filename);
23694 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
23695 arg_list.push_back(filename);
23696 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
23697 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
23698 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
23699 SgFile *file = determineFileType(arg_list, error_code, project);
23700 SgSourceFile *sourcefile = isSgSourceFile(file);
23701 ROSE_ASSERT(sourcefile);
23702 sourcefile -> set_parent(project);
23703
23704 //
23705 // Insert the file into the list of files in the project.
23706 //
23707 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
23708 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
23709
23710 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
23711
23712 if (! unparse) { // if we are not supposed to unparse this file,
23713 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
23714 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
23715 }
23716
23717 // DQ (7/2/2020): Added assertion (fails for snippet tests).
23718 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
23719
23720 return file;
23721}
23722
23723
23728string SageInterface::preprocessPackage(SgProject *project, string package_name) {
23729 string command = "package " + package_name + ";";
23730
23731 //
23732 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
23733 //
23734 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23735 Rose::Frontend::Java::Ecj::createTempFileMethod,
23736 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23737
23738 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23739 ROSE_ASSERT(utf8);
23740 string filename = (string) utf8;
23741 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23742
23743 processFile(project, filename); // translate the file
23744
23745 return package_name;
23746}
23747
23748
23753string SageInterface::preprocessImport(SgProject *project, string import_string) {
23754 string command = "import " + import_string + ";";
23755
23756 //
23757 // Call the Java side to create an input file with the relevant import statement.
23758 //
23759 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23760 Rose::Frontend::Java::Ecj::createTempFileMethod,
23761 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23762
23763 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23764 ROSE_ASSERT(utf8);
23765 string filename = (string) utf8;
23766 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23767
23768 processFile(project, filename); // translate the file
23769
23770 return import_string;
23771}
23772
23773
23778SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
23779 //
23780 // Call the Java side to create an input file with the relevant import statement.
23781 //
23782 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23783 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
23784 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
23785 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
23786
23787 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23788 ROSE_ASSERT(utf8);
23789 string filename = (string) utf8;
23790 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23791
23792 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
23793}
23794
23795
23800 ROSE_ASSERT(scope);
23801 SgClassDefinition *package_definition = NULL;
23802 for (int index = 0, length = package_name.size(); index < length; index++) {
23803 int n;
23804 for (n = index; n < length; n++) {
23805 if (package_name[n] == '.') {
23806 break;
23807 }
23808 }
23809 string name = package_name.substr(index, n - index);
23810
23811 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
23812 if (package_symbol == NULL) { // package not found?
23813 return NULL;
23814 }
23815
23816 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
23817 ROSE_ASSERT(package_declaration);
23818 package_definition = package_declaration -> get_definition();
23819 ROSE_ASSERT(package_definition);
23820 scope = package_definition;
23821
23822 index = n;
23823 }
23824
23825 return package_definition;
23826}
23827
23828
23832SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
23833 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
23834 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
23835 if (package_definition == NULL) { // try again after loading the package
23836 preprocessPackage(project, package_name);
23837
23838 //
23839 // If requested, Create the directory associated with this package_name.
23840 //
23841 if (create_directory) {
23842 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23843 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
23844 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
23845 }
23846
23847 package_definition = findJavaPackage(global_scope, package_name);
23848 }
23849
23850 return package_definition;
23851}
23852
23857 ROSE_ASSERT(package_definition);
23858 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
23859 SgClassDeclaration *class_declaration = (class_symbol == NULL
23860 ? NULL
23861 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
23862 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
23863 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
23864 preprocessImport(project, qualified_name);
23865 class_symbol = package_definition -> lookup_class_symbol(class_name);
23866 }
23867
23868 class_declaration = (class_symbol == NULL
23869 ? NULL
23870 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
23871
23872 return class_declaration;
23873}
23874
23875
23879SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
23880 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
23881}
23882
23883
23888 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
23889 ROSE_ASSERT(class_declaration);
23890 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
23891 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
23892 class_declaration = isSgClassDeclaration(scope -> get_parent());
23893 ROSE_ASSERT(class_declaration);
23894 scope = isSgClassDefinition(class_declaration -> get_scope());
23895 }
23896
23897 if (! scope) { // a local type !!!
23898 return NULL;
23899 }
23900
23901 string class_name = class_declaration -> get_name().getString();
23902 return findOrImportJavaClass(project, scope, class_name);
23903}
23904
23905
23910 ROSE_ASSERT(class_definition);
23912 ROSE_ASSERT(type_list);
23913 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
23914 ROSE_ASSERT(string_array_type);
23915 type_list -> append_argument(string_array_type);
23916
23917 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
23918 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
23919 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
23920
23921 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
23922 delete type_list;
23923 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
23924}
23925
23926
23931 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
23932 ROSE_ASSERT(class_declaration);
23933 SgClassDefinition *class_definition = class_declaration -> get_definition();
23934 return findJavaMain(class_definition);
23935}
23936
23937//------------------------------------------------------------------------------
23938#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
23939//------------------------------------------------------------------------------
23940
23942// Essentially replace variable a with b.
23944{
23945 ROSE_ASSERT (old_sym != NULL);
23946 ROSE_ASSERT (new_sym != NULL);
23947 ROSE_ASSERT (old_sym != new_sym);
23948 ROSE_ASSERT (scope != NULL);
23949
23950 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
23951 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
23952 {
23953 SgVarRefExp *vRef = isSgVarRefExp(*i);
23954 if (vRef->get_symbol() == old_sym)
23955 vRef->set_symbol(new_sym);
23956 }
23957}
23958
23959
23960// DQ (11/12/2018): Adding test to avoid issues that we can't test for in the unparsing of header files using the token based unparsing.
23965bool
23967 {
23968 bool result = true;
23969
23970 bool includingSelf = false;
23971 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
23972
23973 if (sourceFile == NULL)
23974 {
23975 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
23976 }
23977
23978 // I think we can assert this!
23979 ROSE_ASSERT(sourceFile != NULL);
23980
23981 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
23982 {
23983 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
23984 // There could be at least one other file is this is a header file that was included twice, but it should have a different path.
23985 string source_filename = stmt->getFilenameString();
23986#if 0
23987 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
23988 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
23989#endif
23990
23991 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
23992 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
23993 {
23994 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
23995 ROSE_ASSERT(include_file != NULL);
23996#if 0
23997 printf ("include_file->get_can_be_supported_using_token_based_unparsing() = %s \n",include_file->get_can_be_supported_using_token_based_unparsing() ? "true" : "false");
23998#endif
23999 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24000 {
24001#if 0
24002 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24003#endif
24004 result = false;
24005 }
24006 }
24007 else
24008 {
24009 // DQ (5/13/2021): I think that the default (returing true) will work well.
24010 // This is likely just the original input source file (not a header file).
24011#if 0
24012 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24013#endif
24014#if 0
24015 printf ("Exiting as a test! \n");
24016 ROSE_ABORT();
24017#endif
24018 }
24019
24020#if 0
24021 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24022 ROSE_ABORT();
24023#endif
24024 }
24025
24026 return result;
24027 }
24028
24029
24030//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24033{
24034 ROSE_ASSERT (decl!= NULL);
24035 ROSE_ASSERT (target_scope != NULL);
24036 ROSE_ASSERT (target_scope != decl->get_scope());
24037
24038#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24039 // Special handling for If-Stmt, may need to climb up one level of scope when:
24040 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24041 // If-stmt will be the innermost common scope for the variable.
24042 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24043 if (isSgIfStmt (target_scope))
24044 {
24045 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24046 if (target_scope == )
24047 }
24048# endif
24049
24050 // Move the declaration
24051 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24053
24054 switch (target_scope->variantT())
24055 {
24056 case V_SgBasicBlock:
24057 {
24058 SageInterface::prependStatement (decl, target_scope);
24059 break;
24060 }
24061#if 0 // this check should be done earlier before any side effects can happen
24062 case V_SgIfStmt:
24063 {
24064 // adjust to parent scope of if-stmt
24065 break;
24066 }
24067#endif
24068 case V_SgForStatement:
24069 {
24070 // we move int i; to be for (int i=0; ...);
24071 SgForStatement* stmt = isSgForStatement (target_scope);
24072 ROSE_ASSERT(stmt != NULL);
24073 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24074 // Try to match a pattern like for (i=0; ...) here
24075 // assuming there is only one assignment like i=0
24076 // We don't yet handle more complex cases
24077 if (stmt_list.size() !=1)
24078 {
24079 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24080 ROSE_ASSERT (stmt_list.size() ==1);
24081 }
24082 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24083 ROSE_ASSERT (exp_stmt != NULL);
24084 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24085 ROSE_ASSERT (assign_op != NULL);
24086
24087 // remove the existing i=0; preserve its right hand operand
24089 stmt_list.clear();
24090 SageInterface::deepDelete (exp_stmt);
24091
24092 // modify the decl's rhs to be the new one
24095 if (init_name->get_initptr() != NULL)
24096 SageInterface::deepDelete (init_name->get_initptr());
24097 init_name->set_initptr(initor);
24098 initor->set_parent(init_name);
24099
24100 stmt_list.insert (stmt_list.begin(), decl );
24101 break;
24102 }
24103
24104 default:
24105 {
24106 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24107 ROSE_ASSERT (false);
24108 }
24109 }
24110
24111 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24113 ROSE_ASSERT(sym != NULL);
24114 SgScopeStatement* orig_scope = sym->get_scope();
24115 if (orig_scope != target_scope)
24116 {
24117 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24118 // it somehow always reuses previously associated scope.
24120 init_name->set_scope(target_scope);
24121 SgName sname = sym->get_name();
24122 orig_scope->remove_symbol(sym);
24123 target_scope->insert_symbol(sname, sym);
24124 }
24125 // This is difficult since C++ variables have namespaces
24126 // Details are in SageInterface::fixVariableDeclaration()
24127 ROSE_ASSERT (target_scope->symbol_exists(sym));
24128}
24129
24130class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24131 public:
24133 }
24134
24135 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24136 struct SageInterface::const_int_expr_t subtreeVal;
24137 subtreeVal.hasValue_ = true;
24138
24139 if (isSgIntVal(valExp)) {
24140 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24141 } else if (isSgLongIntVal(valExp)) {
24142 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24143 } else if (isSgLongLongIntVal(valExp)) {
24144 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24145 } else if (isSgShortVal(valExp)) {
24146 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24147 } else if (isSgUnsignedIntVal(valExp)) {
24148 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24149 } else if (isSgUnsignedLongVal(valExp)) {
24150 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24151 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24152 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24153 } else if (isSgUnsignedShortVal(valExp)) {
24154 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24155 }
24156 return subtreeVal;
24157 }
24158
24159 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24160 if (isSgModifierType(vRef->get_type()) == NULL) {
24162 val.value_ = -1;
24163 val.hasValue_ = false;
24164 return val;
24165 }
24166 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24167 // We know that the var value is const, so get the initialized name and evaluate it
24168 SgVariableSymbol *sym = vRef->get_symbol();
24169 SgInitializedName *iName = sym->get_declaration();
24170 SgInitializer *ini = iName->get_initializer();
24171
24172 if (isSgAssignInitializer(ini)) {
24173 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24174 SgExpression *rhs = initializer->get_operand();
24175 SimpleExpressionEvaluator variableEval;
24176
24177 return variableEval.traverse(rhs);
24178 }
24179 }
24181 val.hasValue_ = false;
24182 val.value_ = -1;
24183 return val;
24184 }
24185
24186 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24187 if (isSgExpression(node) != NULL) {
24188 SgValueExp* valueExp = isSgValueExp(node);
24189 if (valueExp != NULL) {
24190 return this->getValueExpressionValue(valueExp);
24191 }
24192
24193 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24194 if (varRefExp != NULL) {
24195 // std::cout << "Hit variable reference expression!" << std::endl;
24196 return evaluateVariableReference(varRefExp);
24197 }
24198 // Early break out for assign initializer // other possibility?
24199 if (isSgAssignInitializer(node)) {
24200 if(synList.at(0).hasValue_){
24201 return synList.at(0);
24202 } else {
24204 val.value_ = -1;
24205 val.hasValue_ = false;
24206 return val;
24207 }
24208 }
24209 struct SageInterface::const_int_expr_t evaluatedValue;
24210 evaluatedValue.hasValue_ = false;
24211 evaluatedValue.value_ = -1;
24212#if 0
24213 if(synList.size() != 2){
24214 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24215 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24216 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24217 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24218 }
24219 }
24220#endif
24221 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24222 if((*it).hasValue_){
24223 if (isSgAddOp(node)) {
24224 assert(synList.size() == 2);
24225 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24226 evaluatedValue.hasValue_ = true;
24227 } else if (isSgSubtractOp(node)) {
24228 assert(synList.size() == 2);
24229 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24230 evaluatedValue.hasValue_ = true;
24231 } else if (isSgMultiplyOp(node)) {
24232 assert(synList.size() == 2);
24233 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24234 evaluatedValue.hasValue_ = true;
24235 } else if (isSgDivideOp(node)) {
24236 assert(synList.size() == 2);
24237 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24238 evaluatedValue.hasValue_ = true;
24239 } else if (isSgModOp(node)) {
24240 assert(synList.size() == 2);
24241 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24242 evaluatedValue.hasValue_ = true;
24243 }
24244 } else {
24245 std::cerr << "Expression is not evaluatable" << std::endl;
24246 evaluatedValue.hasValue_ = false;
24247 evaluatedValue.value_ = -1;
24248 return evaluatedValue;
24249 }
24250 }
24251 evaluatedValue.hasValue_ = true;
24252 return evaluatedValue;
24253 }
24254 struct SageInterface::const_int_expr_t evaluatedValue;
24255 evaluatedValue.hasValue_ = false;
24256 evaluatedValue.value_ = -1;
24257 return evaluatedValue;
24258 }
24259};
24260
24264 return eval.traverse(expr);
24265}
24266
24267bool
24269
24270 class TypeEquivalenceChecker {
24271 public:
24272 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24273 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24274 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24275 {
24276 }
24277
24278 SgNode * getBasetypeIfApplicable(SgNode *t){
24279 SgNode * node = t;
24280 if (isSgTypedefType(t)) {
24281// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24282 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24283 }
24284 if(useSemanticEquivalence_){
24285 if(isSgModifierType(t)){
24286 SgModifierType *modType = isSgModifierType(t);
24287 ROSE_ASSERT(modType != NULL);
24288 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24289 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24290 // like classes
24291 // restrict seems to have no impact on the type itself.
24292 if(SageInterface::isVolatileType(modType)){
24293 // handle volatile case
24294 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24295 node = modType->get_base_type();
24296 }
24297 if(SageInterface::isRestrictType(modType)){
24298 // handle restrict case
24299 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24300 node = modType->get_base_type();
24301 }
24302 }
24303 }
24304 ROSE_ASSERT(node != NULL);
24305 return node;
24306}
24307
24308bool typesAreEqual(SgType *t1, SgType *t2) {
24309 bool equal = false;
24310 if(t1 == NULL || t2 == NULL){
24311 std::string wasNull;
24312 if(t1 == NULL){
24313 wasNull = "t1";
24314 } else {
24315 wasNull = "t2";
24316 }
24317 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24318 return equal;
24319 }
24320 // if both pointers point to same location the types MUST be equal!
24321 if(t1 == t2){
24322// std::cout << "Pointers are equal, returning true" << std::endl;
24323 return true;
24324 }
24325#ifndef USE_CMAKEx
24326 RoseAst subT1(t1);
24327 RoseAst subT2(t2);
24328
24329 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24330 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24331 SgNode *nodeT1 = *i;
24332 SgNode *nodeT2 = *j;
24333
24334// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24335 nodeT1 = getBasetypeIfApplicable(nodeT1);
24336 nodeT2 = getBasetypeIfApplicable(nodeT2);
24337
24338 if (nodeT1->variantT() == nodeT2->variantT()) {
24339// std::cout << "variantT is the same" << std::endl;
24340 if(isSgModifierType(nodeT1)){
24341 // we need to check whether the modifier is the same or not
24342 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24343 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24344 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24345 return false;
24346 }
24347 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24348 return false;
24349 }
24350 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24351 if (profile_) {
24352 namedType_++;
24353 }
24354 i.skipChildrenOnForward();
24355 j.skipChildrenOnForward();
24356 SgNamedType *c1 = isSgNamedType(nodeT1);
24357 SgNamedType *c2 = isSgNamedType(nodeT2);
24358
24359 // XXX A function to check whether a named type is anonymous or not would speed
24360 // up this check, since we could get rid of this string compare.
24361 if(!c1->get_autonomous_declaration()){
24362 return false;
24363 }
24364 if (!c2->get_autonomous_declaration()){
24365 return false;
24366 }
24367 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24368 return true;
24369 } else {
24370 return false;
24371 }
24372
24373 } else if (isSgPointerType(nodeT1)) {
24374 if (profile_) {
24375 pointerType_++;
24376 }
24377 SgPointerType *t1 = isSgPointerType(nodeT1);
24378 SgPointerType *t2 = isSgPointerType(nodeT2);
24379
24380 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24381
24382 } else if(isSgReferenceType(nodeT1)){
24383 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24384 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24385
24386 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24387 } else if (isSgArrayType(nodeT1)) {
24388 if (profile_) {
24389 arrayType_++;
24390 }
24391 SgArrayType *a1 = isSgArrayType(nodeT1);
24392 SgArrayType *a2 = isSgArrayType(nodeT2);
24393
24394 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24395
24398 bool arrayIndexExpressionIsEquivalent = false;
24399 if(t1Index.hasValue_ && t2Index.hasValue_){
24400 if(t1Index.value_ == t2Index.value_){
24401 arrayIndexExpressionIsEquivalent = true;
24402 }
24403 }
24404 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24405 return arraysAreEqual;
24406 } else if (isSgFunctionType(nodeT1)) {
24407 if(profile_) {
24408 functionType_++;
24409 }
24410 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24411 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24412// std::cout << "Inside SgFunctionType" << std::endl;
24413// assert(funcTypeA != funcTypeB);
24414 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24415 // If functions don't have the same number of arguments, they are not type-equal
24416 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24417 return false;
24418 }
24419 // This should always be the same as the if before...
24420 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24421 return false;
24422 }
24423
24424 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24425 jj = funcTypeB->get_arguments().begin();
24426 ii != funcTypeA->get_arguments().end() &&
24427 jj != funcTypeB->get_arguments().end();
24428 ++ii, ++jj) {
24429// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24430 // For all argument types check whether they are equal
24431 if(!typesAreEqual((*ii), (*jj))) {
24432 return false;
24433 }
24434 }
24435 return true;
24436 }
24437 return false;
24438 } else {
24439 // We don't have a named type, pointer type or array type, so they are equal
24440 // This is for the primitive type - case
24441 return true;
24442 }
24443 } else {
24444 // In this case the types are not equal, since its variantT is not equal.
24445 return false;
24446 }
24447 }
24448 // this should be unreachable code...
24449 return equal;
24450#else
24451 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24452 ROSE_ABORT();
24453#endif
24454}
24455
24456int getNamedTypeCount() {
24457 return namedType_;
24458}
24459
24460int getPointerTypeCount() {
24461 return pointerType_;
24462}
24463
24464int getArrayTypeCount() {
24465 return arrayType_;
24466}
24467
24468int getFunctionTypeCount() {
24469 return functionType_;
24470}
24471 private:
24472// SgNode * getBasetypeIfApplicable(SgNode *t);
24473 bool profile_, useSemanticEquivalence_;
24474 int namedType_, pointerType_, arrayType_, functionType_;
24475};
24476
24477TypeEquivalenceChecker tec(false, false);
24478return tec.typesAreEqual(typeA, typeB);
24479}
24480
24481
24482std::set<SgStatement*>
24484 {
24485 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24486 // It is useful for debugging the token-based unparsing.
24487
24488 class StatementTraversal : public AstSimpleProcessing
24489 {
24490 public:
24491 StatementTraversal() : count (0) {}
24492 void visit (SgNode* node)
24493 {
24494 SgStatement* statement = isSgStatement(node);
24495 if (statement != nullptr && statement->isTransformation() == true)
24496 {
24497 returnset.insert(statement);
24498 count++;
24499 }
24500 }
24501
24502 int count; // running total of statements found marked as transformations in the input AST
24503 std::set<SgStatement*> returnset;
24504 };
24505
24506 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24507 StatementTraversal traversal;
24508 traversal.traverse(node, preorder);
24509
24510 return traversal.returnset;
24511 }
24512
24513std::set<SgStatement*>
24515 {
24516 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24517 // It is useful for debugging the token-based unparsing.
24518
24519#if 1
24520 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24521#endif
24522
24523 class StatementTraversal : public AstSimpleProcessing
24524 {
24525 public:
24526 StatementTraversal() : count (0) {}
24527 void visit (SgNode* node)
24528 {
24529 SgStatement* statement = isSgStatement(node);
24530 if (statement != NULL && statement->get_isModified() == true)
24531 {
24532 returnset.insert(statement);
24533 count++;
24534 }
24535 }
24536
24537 int count; // running total of statements found marked as transformations in the input AST
24538 std::set<SgStatement*> returnset;
24539 };
24540
24541 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24542 StatementTraversal traversal;
24543 traversal.traverse(node, preorder);
24544
24545 return traversal.returnset;
24546 }
24547
24548
24549void
24551 {
24552 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24553
24554#if 0
24555 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
24556#endif
24557
24558 class LocatedNodeTraversal : public AstSimpleProcessing
24559 {
24560 public:
24561 LocatedNodeTraversal() {}
24562 void visit (SgNode* node)
24563 {
24564 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24565 if (locatedNode != NULL)
24566 {
24567#if 0
24568 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
24569 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
24570#endif
24571 }
24572 else
24573 {
24574 SgInitializedName* initializedName = isSgInitializedName(node);
24575 if (initializedName != NULL)
24576 {
24577 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
24578 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
24579 }
24580 }
24581 }
24582 };
24583
24584 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24585 LocatedNodeTraversal traversal;
24586 traversal.traverse(node, preorder);
24587
24588#if 0
24589 printf ("Exiting as a test! \n");
24590 ROSE_ABORT();
24591#endif
24592 }
24593
24594
24595std::set<SgLocatedNode*>
24597 {
24598 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24599 // It is useful for debugging the token-based unparsing.
24600
24601#if 0
24602 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
24603#endif
24604
24605 class LocatedNodeTraversal : public AstSimpleProcessing
24606 {
24607 public:
24608 LocatedNodeTraversal() : count (0) {}
24609 void visit (SgNode* node)
24610 {
24611 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24612 if (locatedNode != NULL && locatedNode->get_isModified() == true)
24613 {
24614#if 0
24615 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
24616#endif
24617 returnset.insert(locatedNode);
24618 count++;
24619 }
24620 }
24621
24622 int count; // running total of statements found marked as transformations in the input AST
24623 std::set<SgLocatedNode*> returnset;
24624 };
24625
24626 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24627 LocatedNodeTraversal traversal;
24628 traversal.traverse(node, preorder);
24629
24630 return traversal.returnset;
24631 }
24632
24633
24635void
24636SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
24637 {
24638 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
24639
24640#if 0
24641 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
24642#endif
24643
24644 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
24645 while (i != modifiedNodeSet.end())
24646 {
24647 SgLocatedNode* node = *i;
24648#if 0
24649 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
24650#endif
24651 node->set_isModified(true);
24652
24653 i++;
24654 }
24655 }
24656
24657
24658void
24660 {
24661 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
24662 // It is useful for debugging the token-based unparsing.
24663
24664 printf ("\n\n##################################################### \n");
24665 printf ("Report on modified statements: label = %s \n",label.c_str());
24666
24667 SgSourceFile* sourceFile = isSgSourceFile(node);
24668 if (sourceFile != NULL)
24669 {
24670 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24671 }
24672 else
24673 {
24674 SgGlobal* globalScope = isSgGlobal(node);
24675 if (globalScope != NULL)
24676 {
24677 sourceFile = isSgSourceFile(globalScope->get_parent());
24678 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24679 }
24680 }
24681
24682 ROSE_ASSERT(node != NULL);
24683 std::set<SgStatement*> collection = collectModifiedStatements(node);
24684
24685#if 0
24686 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
24687#endif
24688
24689 std::set<SgStatement*>::iterator i = collection.begin();
24690 while (i != collection.end())
24691 {
24692 // DQ (10/9/2019): Adding filename to debug output.
24693 string filename = (*i)->get_file_info()->get_filename();
24694
24695 // DQ (10/14/2019): Get the best name possible.
24696 if (filename == "transformation")
24697 {
24698#if 0
24699 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24700#endif
24701 // filename = (*i)->get_file_info()->get_physical_filename();
24702 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24703 if (sourceFile != NULL)
24704 {
24705 filename = sourceFile->getFileName();
24706 }
24707 }
24708
24709 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24710
24711 i++;
24712 }
24713
24714#if 1
24715 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24716 // output spew else the message output at the top of this function will scroll off the screen.
24717 printf ("########################################################## \n");
24718 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
24719#endif
24720 printf ("########################################################## \n\n\n");
24721
24722#if 0
24723 printf ("Exiting as a test! \n");
24724 ROSE_ASSERT(false);
24725#endif
24726 }
24727
24728
24729
24730void
24732 {
24733 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
24734 // It is useful for debugging the token-based unparsing.
24735
24736 printf ("\n\n##################################################### \n");
24737 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
24738
24739 SgSourceFile* sourceFile = isSgSourceFile(node);
24740 if (sourceFile != NULL)
24741 {
24742 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24743 }
24744 else
24745 {
24746 SgGlobal* globalScope = isSgGlobal(node);
24747 if (globalScope != NULL)
24748 {
24749 sourceFile = isSgSourceFile(globalScope->get_parent());
24750 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24751 }
24752 }
24753
24754 ROSE_ASSERT(node != NULL);
24755 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
24756
24757#if 0
24758 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
24759#endif
24760
24761 std::set<SgLocatedNode*>::iterator i = collection.begin();
24762 while (i != collection.end())
24763 {
24764 // DQ (10/9/2019): Adding filename to debug output.
24765 string filename = (*i)->get_file_info()->get_filename();
24766
24767 // DQ (10/14/2019): Get the best name possible.
24768 if (filename == "transformation")
24769 {
24770#if 0
24771 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24772#endif
24773 // filename = (*i)->get_file_info()->get_physical_filename();
24774 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24775 if (sourceFile != NULL)
24776 {
24777 filename = sourceFile->getFileName();
24778 }
24779 }
24780
24781 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24782
24783 i++;
24784 }
24785
24786#if 1
24787 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24788 // output spew else the message output at the top of this function will scroll off the screen.
24789 printf ("########################################################## \n");
24790 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
24791#endif
24792 printf ("########################################################## \n\n\n");
24793
24794#if 0
24795 printf ("Exiting as a test! \n");
24796 ROSE_ASSERT(false);
24797#endif
24798 }
24799
24800
24801
24802
24803// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
24804
24805void
24807 {
24808 // Debugging function to print out comments in the statements (added by DQ)
24809
24810 ROSE_ASSERT(locatedNode != NULL);
24811 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
24812
24813#if 0
24814 curprint ("/* Inside of printOutComments() */");
24815#endif
24816
24817 if (comments != NULL)
24818 {
24819#if 0
24820 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
24821 curprint ("/* Inside of printOutComments(): comments != NULL */");
24822#endif
24823
24824 AttachedPreprocessingInfoType::iterator i;
24825 for (i = comments->begin(); i != comments->end(); i++)
24826 {
24827 ROSE_ASSERT ( (*i) != NULL );
24828 printf (" Attached Comment (relativePosition=%s): %s \n",
24829 // DQ (2/11/2021): Fixed to report correct relative locations.
24830 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
24831 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
24832 (*i)->getString().c_str());
24833 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
24834 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
24835
24836#if 0
24837 (*i)->get_file_info()->display("comment/directive location");
24838#endif
24839 }
24840 }
24841 else
24842 {
24843#if 0
24844 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
24845#endif
24846 }
24847 }
24848
24849
24850
24851bool
24853 {
24854 bool returnValue = false;
24855
24856 ROSE_ASSERT(currentPreprocessingInfo != NULL);
24857
24858 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
24859
24860 if (directive == PreprocessingInfo::C_StyleComment ||
24861 directive == PreprocessingInfo::CplusplusStyleComment ||
24862 directive == PreprocessingInfo::FortranStyleComment ||
24863 directive == PreprocessingInfo::CpreprocessorBlankLine ||
24864 directive == PreprocessingInfo::ClinkageSpecificationStart ||
24865 directive == PreprocessingInfo::ClinkageSpecificationEnd)
24866 {
24867 returnValue = true;
24868 }
24869
24870 return returnValue;
24871 }
24872
24873std::vector<SgC_PreprocessorDirectiveStatement*>
24875 {
24876 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
24877
24878 // Find existing first and last header.
24879 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
24880
24881 if (comments != nullptr)
24882 {
24883 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
24884 for (i = comments->begin (); i != comments->end(); i++)
24885 {
24886 if (skipTranslateToUseCppDeclaration(*i) == true)
24887 {
24888 // We are not processing these types of directives into IR nodes (new IR nodes would have to be added and this can be done later if required).
24889 }
24890 else
24891 {
24892 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
24893 ROSE_ASSERT(directive != NULL);
24894 directiveList.push_back(directive);
24895 }
24896
24897 printf ("directiveList.size() = %zu \n",directiveList.size());
24898 }
24899 }
24900
24901 return directiveList;
24902 }
24903
24904
24905void
24907 {
24908 bool declarationsOnly = scope->containsOnlyDeclarations();
24909
24910 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
24911
24912 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
24913
24914 if (declarationsOnly == true)
24915 {
24916 // These are scopes such as global scope, namespace definitions, class definitions, etc.
24917 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
24918 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
24919 while (i != declarationList.end())
24920 {
24921 SgDeclarationStatement* declaration = *i;
24922 ROSE_ASSERT(declaration != NULL);
24923
24924 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
24925
24926 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
24927
24928 if (attachDirectives.empty() == false)
24929 {
24930 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
24931 }
24932
24933 i++;
24934 }
24935
24936 // Need to save the list of things that will be added so we can avoid iterator invalidation.
24937 }
24938 else
24939 {
24940 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
24941 SgStatementPtrList & statementList = scope->getStatementList();
24942 SgStatementPtrList::iterator i = statementList.begin();
24943 while (i != statementList.end())
24944 {
24945 SgStatement* statement = *i;
24946 ROSE_ASSERT(statement != NULL);
24947
24948 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
24949
24950 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
24951
24952 if (attachDirectives.empty() == false)
24953 {
24954 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
24955 }
24956
24957 i++;
24958 }
24959 }
24960
24961 printf ("directiveMap.size() = %zu \n",directiveMap.size());
24962
24963 printf ("Processing the directiveMap: \n");
24964 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
24965 while (i != directiveMap.end())
24966 {
24967 SgStatement* statement = i->first;
24968 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
24969
24970 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
24971 printf ("directives.size() = %zu \n",directives.size());
24972 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
24973 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
24974 while (j != directives.end())
24975 {
24976 scope->insert_statement(statement,*j);
24977
24978 j++;
24979 }
24980
24981 // Remove the directives there were attached to the statement.
24982 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
24983 ROSE_ASSERT(comments != NULL);
24984
24985 AttachedPreprocessingInfoType deleteList;
24986 // std::vector<PreprocessingInfo*> deleteList;
24987
24988 // comments->erase();
24989 // statement->setAttachedPreprocessingInfo(NULL);
24990 AttachedPreprocessingInfoType::iterator k;
24991 for (k = comments->begin(); k != comments->end(); k++)
24992 {
24993#if 1
24994 ROSE_ASSERT ( (*k) != NULL );
24995 printf (" Attached Comment (relativePosition=%s): %s\n",
24996 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
24997 (*k)->getString().c_str());
24998 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
24999#endif
25000
25001 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25002 if (skipTranslateToUseCppDeclaration(*k) == true)
25003 {
25004 // We are not processing these types of directives into IR nodes (new IR nodes would have to be added and this can be done later if required).
25005 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25006 }
25007 else
25008 {
25009 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25010
25011 deleteList.push_back(*k);
25012 // delete *k;
25013 // *k = NULL;
25014 }
25015 }
25016
25017 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25018 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25019 while (m != deleteList.end())
25020 {
25021 // comments->erase(m);
25022 // std::remove(comments->begin(), comments->end(), *m);
25023 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25024
25025 printf (" --- comments->size() = %zu \n",comments->size());
25026
25027 m++;
25028 }
25029
25030 // comments->clear();
25031 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25032 // statement->set_attachedPreprocessingInfoPtr(NULL);
25033
25034 i++;
25035 }
25036
25037 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25038 }
25039
25040
25041void
25043 {
25044 class CppTranslationTraversal : public AstSimpleProcessing
25045 {
25046 public:
25047 CppTranslationTraversal() {}
25048 void visit (SgNode* node)
25049 {
25050 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25051
25052 SgScopeStatement* scope = isSgScopeStatement(node);
25053 SgGlobal* globalScope = isSgGlobal(scope);
25054 if (globalScope != NULL)
25055 {
25056 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25058 }
25059 else
25060 {
25061 if (scope != NULL)
25062 {
25063 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25064 }
25065 }
25066 }
25067 };
25068
25069 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25070 CppTranslationTraversal traversal;
25071
25072 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25073
25074 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25075 // traversal.traverse(n, preorder);
25076 traversal.traverse(n, postorder);
25077
25078 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25079 }
25080
25082{
25083 // print current level's info
25084 if (!n) return;
25085 cout<<"--------------"<<endl;
25086 cout<<n<<":"<<n->class_name()<< endl;
25087 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25088 {
25089 cout<<"file info:\t ";
25090 lnode->get_file_info()->display();
25091 cout<<"\n unparseToString:\t ";
25092 lnode->unparseToString();
25093 }
25094
25095 // track back to its parent
25097}
25098// forward declaration is needed here,
25099//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25100
25101#if 0 // made it into a template function to handle various ptr lists in AST
25102// A special node in the AST text dump
25103static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25104{
25105 out<<prefix;
25106 out<< (hasRemaining?"|---": "|___");
25107
25108// out<<"+"<<edgeLabel<<"+>";
25109 out<<" "<<edgeLabel<<" ->";
25110 // print address
25111 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25112
25113 out<<endl;
25114
25115 int last_non_null_child_idx =-1;
25116 for (int i = (int) (plist.size())-1; i>=0; i--)
25117 {
25118 if (plist[i])
25119 {
25120 last_non_null_child_idx = i;
25121 break;
25122 }
25123 }
25124
25125 for (size_t i=0; i< plist.size(); i++ )
25126 {
25127 bool n_hasRemaining=false;
25128#if 0
25129 if (i+1 < plist.size())
25130 n_hasRemaining=true;
25131#else
25132 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25133#endif
25134 string suffix= hasRemaining? "| " : " ";
25135 string n_prefix = prefix+suffix;
25136 string n_edge_label="";
25137 if (plist[i])
25138 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25139 }
25140}
25141#endif
25142
25143// print essential information from any AST node
25144// hasRemaining if this node has a sibling node to be visited next.
25145void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25146{
25147 // there may be NULL children!!
25148 //if (!node) return;
25149
25150 out<<prefix;
25151 out<< (hasRemaining?"|---": "|___");
25152
25153 out<<" "<<edgeLabel<<" ->";
25154 if (!node)
25155 {
25156 out<<" NULL "<<endl;
25157 return;
25158 }
25159
25160 // print address
25161 out<<"@"<<node<<" "<< node->class_name()<<" ";
25162
25163 //optionally file info
25164 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25165 {
25166 //Rose::StringUtility::stripPathFromFileName()
25167 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25168 // also preprocessing info. attached.
25169 AttachedPreprocessingInfoType *comments =
25170 lnode->getAttachedPreprocessingInfo ();
25171
25172 if (comments != NULL)
25173 {
25174// printf ("Found an IR node with preprocessing Info attached:\n");
25175 out<<" AttachedPreprocessingInfoType@"<<comments;
25176 int counter = 0;
25177 AttachedPreprocessingInfoType::iterator i;
25178 out <<"{";
25179 for (i = comments->begin (); i != comments->end (); i++)
25180 {
25181 if (i!=comments->begin ())
25182 out<<endl;
25183 out<<"<id=";
25184 out<<counter++<<" ";
25185 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25186 // printf("classification = %s:\n String format = %s\n",
25187 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25188 // (*i)->getString ().c_str ());
25189 if (*i==NULL)
25190 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25191 else
25192 {
25193 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25194 out<<" string="<<(*i)->getString ().c_str ();
25195 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25196#if 1
25197 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25198 out<<"inside";
25199 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25200 out<<"before";
25201 else
25202 out<<"after";
25203#endif
25204 }
25205 out<<">";
25206 }
25207 out <<"}";
25208 }
25209 }
25210
25211 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25212 {
25213 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25214 out<<" defining decl@"<< v->get_definingDeclaration();
25215 }
25216
25217 if (SgEnumVal* f = isSgEnumVal(node) )
25218 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25219 // optionally qualified name
25220
25221 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25222 out<<" "<< f->get_qualified_name();
25223
25224 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25225 out<<" renamed_function "<< f->get_renamed_function();
25226
25227 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25228 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25229
25230 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25231 out<<" "<< f->get_qualified_name();
25232
25233 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25234 out<<" "<< f->get_qualified_name();
25235
25236 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25237 out<<" "<< f->get_qualified_name();
25238
25239 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25240 out<<" enumType="<< f->get_enumType();
25241
25242 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25243 {
25244 // out<<" "<< v->get_qualified_name();
25245 //out<<" "<< v->get_name();
25246 // PP (2/18/22) updated to reflect properties in AdaAccessType
25247 //~ out<<" is_object_type"<< v->get_is_object_type();
25248 out<<" is_general_access"<< v->get_is_general_access();
25249 //~ out<<" is_constant:"<< v->get_is_constant();
25250 //~ out<<" is_protected:"<< v->get_is_protected ();
25251 out<<" is_anonymous:"<< v->get_is_anonymous ();
25252 }
25253
25254 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25255 {
25256 out<<" is_protected"<< v->get_is_protected();
25257 }
25258
25259 if (SgInitializedName * v = isSgInitializedName(node) )
25260 {
25261 out<<" "<< v->get_qualified_name();
25262 out<<" type@"<< v->get_type();
25263 out<<" initializer@"<< v->get_initializer();
25264 out<<" scope@"<< v->get_scope();
25265// type_set.insert (v->get_type());
25266 }
25267
25268 // associated class, function and variable declarations
25269 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25270 out<<" template class decl@"<< f->get_templateDeclaration();
25271
25272 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25273 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25274
25275 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25276 {
25277 out<<" member function decl@"<< ctor->get_declaration();
25278 }
25279
25280 if (SgIntVal* v= isSgIntVal(node))
25281 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25282
25283 if (SgShortVal* v= isSgShortVal(node))
25284 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25285
25286 if (SgLongIntVal* v= isSgLongIntVal(node))
25287 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25288
25289 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25290 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25291
25292 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25293 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25294
25295 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25296 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25297
25298 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25299 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25300
25301 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25302 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25303
25304 if (SgFloatVal* v= isSgFloatVal(node))
25305 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25306
25307 if (SgDoubleVal* v= isSgDoubleVal(node))
25308 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25309
25310 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25311 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25312
25313 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25314 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25315
25316 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25317 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25318
25319 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25320 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25321
25322 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25323 {
25324 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25325 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25326 }
25327
25328 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25329 {
25330 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25331 out<<" ada renaming decl@"<< renaming_decl;
25332 }
25333
25334 // base type of several types of nodes:
25335 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25336 {
25337 out<<" base_type@"<< v->get_base_type();
25338// type_set.insert (v->get_base_type());
25339 }
25340
25341 if (SgArrayType* v= isSgArrayType(node))
25342 out<<" base_type@"<< v->get_base_type();
25343
25344 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25345 out<<" base_type@"<< v->get_base_type();
25346
25347 if (SgTypeExpression* v= isSgTypeExpression(node))
25348 out<<" type@"<< v->get_type();
25349
25350 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25351 out<<" attribute@"<< v->get_attribute();
25352
25353 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25354 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25355
25356 out<<endl;
25357
25358 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25359#if 0
25360 int total_count = children.size();
25361 int current_index=0;
25362#endif
25363
25364 int last_non_null_child_idx =-1;
25365 for (int i = (int) (children.size())-1; i>=0; i--)
25366 {
25367 if (children[i])
25368 {
25369 last_non_null_child_idx = i;
25370 break;
25371 }
25372 }
25373
25374#if 0
25375 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25376 // we sum all children into single total_count to tell if there is remaining children.
25377 if (isSgTemplateInstantiationDecl (node))
25378 total_count += 1; // sn->get_templateArguments().size();
25379#endif
25380
25381 // handling SgTemplateArgumentPtrList first
25382 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25383 {
25384 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25385 bool n_hasRemaining=false;
25386 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25387 string suffix= hasRemaining? "| " : " ";
25388 string n_prefix = prefix+suffix;
25389 string n_edge_label= "";
25390 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25391 }
25392 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25393 {
25394 SgExpressionPtrList& plist = import_stmt->get_import_list();
25395 bool n_hasRemaining=false;
25396 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25397 string suffix= hasRemaining? "| " : " ";
25398 string n_prefix = prefix+suffix;
25399 string n_edge_label= "";
25400 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25401 }
25402
25403 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25404
25405 // finish sucessors
25406 for (size_t i =0; i< children.size(); i++)
25407 {
25408 bool n_hasRemaining=false;
25409#if 0
25410 if (current_index+1<total_count)
25411 n_hasRemaining=true;
25412 current_index++;
25413#else
25414 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25415#endif
25416 string suffix= hasRemaining? "| " : " ";
25417 string n_prefix = prefix+suffix;
25418 if (children[i])
25419 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25420 }
25421}
25422
25424{
25425 ostringstream oss;
25426 string prefix;
25427 string label="";
25428 serialize(node, prefix, false, oss, label);
25429 cout<<oss.str();
25430}
25431
25432void SageInterface::printAST(SgNode* node, const char* filename)
25433{
25434 printAST2TextFile(node, filename, true);
25435}
25436
25437void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25438{
25439 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25440// ROSE_ABORT();
25441 printAST2TextFile (node, filename.c_str(), printType);
25442}
25443
25444void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25445{
25446 ostringstream oss;
25447 string prefix;
25448 string label="";
25449 serialize(node, prefix, false, oss, label);
25450 ofstream textfile;
25451 textfile.open(filename, ios::out);
25452 textfile<<oss.str();
25453
25454 if (printType)
25455 {
25456 // append type information also
25457 textfile<<"Types encountered ...."<<endl;
25458 ostringstream oss2;
25459 VariantVector vv(V_SgType);
25460 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25461 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25462 {
25463 serialize (*i, prefix, false, oss2, label);
25464 }
25465 textfile<<oss2.str();
25466 }
25467
25468 textfile.close();
25469}
25470
25472{
25473 saveToPDF(node, string("temp.pdf.json") );
25474}
25476// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25477void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25478{
25479 ROSE_ASSERT(node != NULL);
25480 AstJSONGeneration json;
25481 json.generateWithinFile(filename, getEnclosingFileNode(node));
25482}
25483
25485{
25486 bool rtval = false;
25487 ROSE_ASSERT (node != NULL);
25488 Sg_File_Info* finfo = node->get_file_info();
25489 if (finfo!=NULL)
25490 {
25491 string fname = finfo->get_filenameString();
25492 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25493 string buildtree_str2 = string("include-staging/g++_HEADERS");
25494 string installtree_str1 = string("include/edg/gcc_HEADERS");
25495 string installtree_str2 = string("include/edg/g++_HEADERS");
25496 string system_headers = string("/usr/include");
25497 // if the file name has a sys header path of either source or build tree
25498 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25499 (fname.find (buildtree_str2, 0) != string::npos) ||
25500 (fname.find (installtree_str1, 0) != string::npos) ||
25501 (fname.find (installtree_str2, 0) != string::npos) ||
25502 (fname.find (system_headers, 0) != string::npos)
25503 )
25504 rtval = true;
25505 }
25506 return rtval;
25507}
25508
25509
25510// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25512 {
25513 // Check if a node is from a header file
25514
25515 bool returnValue = false;
25516
25517 Sg_File_Info* fileInfo = node->get_file_info();
25518 ROSE_ASSERT(fileInfo != NULL);
25519 string filename = fileInfo->get_filenameString();
25520
25521#if 0
25522 printf ("In SageInterface::insideHeader(): node = %s line: %d column: %d file: %s \n",node->class_name().c_str(),fileInfo->get_line(),fileInfo->get_col(),filename.c_str());
25523#endif
25524
25525 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25526 // so the test is only if the filename is in the list.
25527 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25528 {
25529#if 0
25530 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25531#endif
25532 }
25533 else
25534 {
25535#if 0
25536 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25537#endif
25538 returnValue = true;
25539 }
25540
25541 return returnValue;
25542 }
25543
25544
25547{
25548 ROSE_ASSERT(return_type != NULL);
25549 ROSE_ASSERT(typeList != NULL);
25551 ROSE_ASSERT(fTable);
25552
25553 // This function make clever use of a static member function which can't be built
25554 // for the case of a SgMemberFunctionType (or at least not without more work).
25555 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
25556 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
25557
25558 return funcType;
25559}
25560
25565{
25566 ROSE_ASSERT (lhs != NULL);
25567 ROSE_ASSERT (rhs != NULL);
25568 if (lhs == rhs)
25569 return true;
25570
25571 bool rt = false;
25572 SgType* rt1 = lhs->get_return_type();
25573 SgType* rt2 = rhs->get_return_type();
25574
25575 if (isEquivalentType (rt1, rt2))
25576 {
25577 SgTypePtrList f1_arg_types = lhs->get_arguments();
25578 SgTypePtrList f2_arg_types = rhs->get_arguments();
25579 // Must have same number of argument types
25580 if (f1_arg_types.size() == f2_arg_types.size())
25581 {
25582 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
25583 // int counter = 0;
25584 size_t counter = 0;
25585 // iterate through all argument types
25586 // for (int i=0; i< f1_arg_types.size(); i++)
25587 for (size_t i=0; i< f1_arg_types.size(); i++)
25588 {
25589 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
25590 counter ++; // count the number of equal arguments
25591 else
25592 break; // found different type? jump out the loop
25593 }
25594 // all arguments are equivalent, set to true
25595 if (counter == f1_arg_types.size())
25596 rt = true;
25597 }
25598 } // end if equivalent return types
25599
25600 return rt;
25601}
25602
25603bool
25605 {
25606 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
25607
25608 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
25609
25610 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
25611 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
25612 // Note that this is only required within the change to use this isEquivalentType() function in the
25613 // support to replace:
25614 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
25615 // in ROSETTA/Grammar/Support.code
25616
25617 ROSE_ASSERT(lhs != NULL);
25618 ROSE_ASSERT(rhs != NULL);
25619
25620 bool isSame = false;
25621
25622 // While debugging avoid infinte loops (most type chains in STL and boost are only a 3-4 long in test2015_127.C, nesting is how it goes wild).
25623 static int counter = 0;
25624
25625 const SgType & X = *lhs;
25626 const SgType & Y = *rhs;
25627
25628 // DQ (11/28/2015): We don't want to strip off everything.
25629 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
25630
25631 // I think we need to compute the type chain to evaluate equalence.
25632 // Rose_STL_Container< SgType*> getInternalTypes () const
25633
25634#define DEBUG_TYPE_EQUIVALENCE 0
25635
25636#if DEBUG_TYPE_EQUIVALENCE
25637 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25638 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
25639 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
25640#endif
25641
25642#if DEBUG_TYPE_EQUIVALENCE || 0
25643 if (counter == 0)
25644 {
25645 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25646 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
25647 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
25648 }
25649#endif
25650
25651#if DEBUG_TYPE_EQUIVALENCE || 0
25652 // Debugging output.
25653 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
25654 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
25655
25656 // Debugging output.
25657 printf ("Output of type chain for lhs: \n");
25658 for (size_t i = 0; i < X_typeChain.size(); i++)
25659 {
25660 SgType* element_type = X_typeChain[i];
25661 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25662 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25663 SgModifierType* modifierType = isSgModifierType(element_type);
25664 if (modifierType != NULL)
25665 {
25666 // modifierType->get_typeModifier().display("X type chain");
25667 string s = modifierType->get_typeModifier().displayString();
25668 printf (" --- type chain modifier: %s \n",s.c_str());
25669 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25670 }
25671 }
25672
25673 printf ("Output of type chain for rhs: \n");
25674 for (size_t i = 0; i < Y_typeChain.size(); i++)
25675 {
25676 SgType* element_type = Y_typeChain[i];
25677 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25678 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25679 SgModifierType* modifierType = isSgModifierType(element_type);
25680 if (modifierType != NULL)
25681 {
25682 // modifierType->get_typeModifier().display("Y type chain");
25683 string s = modifierType->get_typeModifier().displayString();
25684 printf (" --- type chain modifier: %s \n",s.c_str());
25685 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25686 }
25687 }
25688#endif
25689
25690 // Increment the static variable to control the recursive depth while we debug this.
25691 counter++;
25692
25693 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
25694 // if (counter >= 280)
25695 // if (counter >= 500)
25696 if (counter >= 280)
25697 {
25698 // printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %s Y_element_type = %s \n",counter,X.class_name().c_str(),Y.class_name().c_str());
25699 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %s = %p Y_element_type = %s = %p \n",counter,X.class_name().c_str(),lhs,Y.class_name().c_str(),rhs);
25700 }
25701
25702 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
25703 // DQ (11/28/2015): exit in stead of infinte recursion.
25704 // if (counter > 300)
25705 // if (counter > 600)
25706 // if (counter > 5000)
25707 // if (counter > 300)
25708 if (counter > 350)
25709 {
25710 // DQ (11/28/2015): I think this is a reasonable limit.
25711 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
25712 ROSE_ABORT();
25713 }
25714
25715 // bool exit = false;
25716
25717 // Strip off any typedefs since they are equivalent by definition.
25718 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
25719 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
25720
25721 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
25722 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
25723 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
25724
25725 if (X_referenceType != NULL && Y_referenceType != NULL)
25726 {
25727 X_element_type = X_referenceType->get_base_type();
25728 Y_element_type = Y_referenceType->get_base_type();
25729
25730 counter--;
25731
25732 // Recursive call.
25733 // return (*X_element_type) == (*Y_element_type);
25734 return isEquivalentType(X_element_type,Y_element_type);
25735 }
25736 else
25737 {
25738 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25739 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
25740 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
25741
25742 if (X_pointerType != NULL && Y_pointerType != NULL)
25743 {
25744 X_element_type = X_pointerType->get_base_type();
25745 Y_element_type = Y_pointerType->get_base_type();
25746
25747 counter--;
25748
25749 // Recursive call.
25750 // return (*X_element_type) == (*Y_element_type);
25751 return isEquivalentType(X_element_type,Y_element_type);
25752 }
25753 else
25754 {
25755 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25756 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
25757 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
25758
25759 // DQ (12/8/2015): We need to check that the array size is the same.
25760 if (X_arrayType != NULL && Y_arrayType != NULL)
25761 {
25762 X_element_type = X_arrayType->get_base_type();
25763 Y_element_type = Y_arrayType->get_base_type();
25764
25765 SgExpression* X_array_index_expression = X_arrayType->get_index();
25766 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
25767
25768 if (X_array_index_expression == Y_array_index_expression)
25769 {
25770#if DEBUG_TYPE_EQUIVALENCE || 0
25771 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
25772#endif
25773 counter--;
25774
25775 // Recursive call.
25776 // return (*X_element_type) == (*Y_element_type);
25777 return isEquivalentType(X_element_type,Y_element_type);
25778 }
25779 else
25780 {
25781 // Need more complex test for expression equivalence.
25782#if DEBUG_TYPE_EQUIVALENCE || 0
25783 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
25784 string str1 = X_array_index_expression->unparseToString();
25785 string str2 = Y_array_index_expression->unparseToString();
25786 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
25787#endif
25788 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
25789 counter--;
25790
25791 // Recursive call.
25792 return isEquivalentType(X_element_type,Y_element_type);
25793 }
25794 }
25795 else
25796 {
25797 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25798 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
25799 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
25800
25801 // DQ (12/15/2015): We need to check that the array size is the same.
25802 if (X_templateType != NULL && Y_templateType != NULL)
25803 {
25804 string X_name = X_templateType->get_name();
25805 string Y_name = Y_templateType->get_name();
25806
25807 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
25808 ROSE_ASSERT(X_templateDecl != NULL);
25809 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
25810 ROSE_ASSERT(Y_templateDecl != NULL);
25811
25812 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
25813 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
25814
25815 SgNode * X_parent = X_templateDecl->get_parent();
25816 SgNode * Y_parent = Y_templateDecl->get_parent();
25817
25818#if DEBUG_TYPE_EQUIVALENCE
25819 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
25820 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
25821 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
25822 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
25823 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
25824 printf (" -- X_parent = %p (%s) Y_parent = %p (%s)\n", X_parent, X_parent ? X_parent->class_name().c_str() : "", Y_parent, Y_parent ? Y_parent->class_name().c_str() : "");
25825 printf (" -- X_parent_parent = %p (%s) Y_parent_parent = %p (%s)\n", X_parent_parent, X_parent_parent ? X_parent_parent->class_name().c_str() : "", Y_parent_parent, Y_parent_parent ? Y_parent_parent->class_name().c_str() : "");
25826 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
25827 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
25828#endif
25829 bool value = (X_parent == Y_parent);
25830
25831 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
25832 value = (X_template_parameter_position == Y_template_parameter_position);
25833 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
25834 value = (X_name == Y_name);
25835 }
25836
25837 counter--;
25838
25839 return value;
25840 }
25841 else
25842 {
25843 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
25844 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
25845#if 0
25846 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
25847 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
25848 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
25849 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
25850 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
25851#endif
25852#if DEBUG_TYPE_EQUIVALENCE
25853 printf ("In SageInterface::isEquivalentType(): loop: Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
25854#endif
25855 }
25856 }
25857 }
25858 } // end if reference type, pointer type, array type, and template type
25859
25860 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
25861 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
25862
25863#if DEBUG_TYPE_EQUIVALENCE
25864 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
25865 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
25866#endif
25867
25868 if (X_modifierType != NULL && Y_modifierType != NULL)
25869 {
25870 // Handle the case of both modifiers.
25871#if DEBUG_TYPE_EQUIVALENCE
25872 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
25873#endif
25874 if (X_modifierType == Y_modifierType)
25875 {
25876 isSame = true;
25877#if DEBUG_TYPE_EQUIVALENCE
25878 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
25879#endif
25880 }
25881 else
25882 {
25883 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
25884 {
25885#if DEBUG_TYPE_EQUIVALENCE
25886 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
25887#endif
25888 // Recursive call.
25889 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
25890 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
25891 }
25892 else
25893 {
25894#if DEBUG_TYPE_EQUIVALENCE
25895 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
25896#endif
25897 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
25898 bool skippingOverIdentityModifier = false;
25899
25900 if (X_modifierType->get_typeModifier().isIdentity() == true)
25901 {
25902#if DEBUG_TYPE_EQUIVALENCE
25903 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
25904#endif
25905 X_element_type = X_modifierType->get_base_type();
25906
25907 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
25908 skippingOverIdentityModifier = true;
25909 }
25910
25911 if (Y_modifierType->get_typeModifier().isIdentity() == true)
25912 {
25913#if DEBUG_TYPE_EQUIVALENCE
25914 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
25915#endif
25916 Y_element_type = Y_modifierType->get_base_type();
25917
25918 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
25919 skippingOverIdentityModifier = true;
25920 }
25921
25922 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
25923#if DEBUG_TYPE_EQUIVALENCE
25924 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
25925#endif
25926 // Recursive call on non-default modifier base types.
25927 // isSame = (*X_element_type) == (*Y_element_type);
25928 // isSame = isEquivalentType(X_element_type,Y_element_type);
25929 if (skippingOverIdentityModifier == true)
25930 {
25931#if DEBUG_TYPE_EQUIVALENCE
25932 printf ("In SageInterface::isEquivalentType(): loop: recursive call on different adjusted modifier types: before recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
25933#endif
25934 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
25935 isSame = isEquivalentType(X_element_type,Y_element_type);
25936 }
25937 else
25938 {
25939 // If we have not skipped over an identity modifier then noting will change in the recursive call and these types are not equivalent (return false).
25940 isSame = false;
25941#if DEBUG_TYPE_EQUIVALENCE
25942 printf ("In SageInterface::isEquivalentType(): loop: no progress was made in resolving the base type, so returning isSame set to false: isSame = %s \n",isSame ? "true" : "false");
25943#endif
25944 }
25945
25946#if DEBUG_TYPE_EQUIVALENCE
25947 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
25948#endif
25949 }
25950 }
25951 }
25952 else
25953 {
25954 // At least one of these is not a SgModifierType.
25955
25956 if (X_modifierType != NULL || Y_modifierType != NULL)
25957 {
25958 bool isReduceable = false;
25959
25960 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
25961 {
25962#if DEBUG_TYPE_EQUIVALENCE
25963 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
25964#endif
25965 X_element_type = X_modifierType->get_base_type();
25966 isReduceable = true;
25967 }
25968
25969 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
25970 {
25971#if DEBUG_TYPE_EQUIVALENCE
25972 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
25973#endif
25974 Y_element_type = Y_modifierType->get_base_type();
25975 isReduceable = true;
25976 }
25977
25978 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
25979#if DEBUG_TYPE_EQUIVALENCE
25980 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
25981#endif
25982 if (isReduceable == true)
25983 {
25984 // Recursive call on non-default modifier base types.
25985 // isSame = (*X_element_type) == (*Y_element_type);
25986 isSame = isEquivalentType(X_element_type,Y_element_type);
25987 }
25988 else
25989 {
25990 // Neither of these types were reducable.
25991 isSame = false;
25992 }
25993
25994#if DEBUG_TYPE_EQUIVALENCE
25995 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
25996 isReduceable ? "true" : "false",isSame ? "true" : "false");
25997#endif
25998 }
25999 else
26000 {
26001 // Neither of these are SgModifierType nodes.
26002 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26003 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26004
26005 if (X_element_type == Y_element_type)
26006 {
26007 isSame = true;
26008#if DEBUG_TYPE_EQUIVALENCE || 0
26009 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26010 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26011 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26012#endif
26013#if DEBUG_TYPE_EQUIVALENCE || 0
26014 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26015 // still might not be interchangable if one is defined in a restrcited scope.
26016 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26017 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26018
26019 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26020 {
26021#if 0
26022 if (lhs_typedefType != NULL)
26023 {
26024 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26025 }
26026 if (rhs_typedefType != NULL)
26027 {
26028 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26029 }
26030#else
26031 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26032 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26033#endif
26034 }
26035#endif
26036 }
26037 else
26038 {
26039 // DQ (3/20/2016): This is reported by GNU as set but not used.
26040 // bool isReduceable = false;
26041
26042 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26043 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26044 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26045
26046 if (X_referenceType != NULL || Y_referenceType != NULL)
26047 {
26048#if 0
26049 if (X_referenceType != NULL)
26050 {
26051 X_element_type = X_referenceType->get_base_type();
26052
26053 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26054 // isReduceable = true;
26055 isReduceable = false;
26056 }
26057
26058 if (Y_referenceType != NULL)
26059 {
26060 Y_element_type = Y_referenceType->get_base_type();
26061
26062 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26063 // isReduceable = true;
26064 isReduceable = false;
26065 }
26066
26067 if (isReduceable == true)
26068 {
26069 // Recursive call on non-default modifier base types.
26070 // isSame = (*X_element_type) == (*Y_element_type);
26071 isSame = isEquivalentType(X_element_type,Y_element_type);
26072 }
26073 else
26074 {
26075 // Neither of these types were reducable.
26076 isSame = false;
26077 }
26078#else
26079 isSame = false;
26080#endif
26081 }
26082 else
26083 {
26084 // Recursive call on non-typedef base types.
26085 // isSame = (*X_element_type) == (*Y_element_type);
26086 // isSame = isEquivalentType(X_element_type,Y_element_type);
26087
26088#if DEBUG_TYPE_EQUIVALENCE
26089 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26090#endif
26091
26092 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26093 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26094 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26095
26096 if (X_pointerType != NULL || Y_pointerType != NULL)
26097 {
26098#if 0
26099 if (X_pointerType != NULL)
26100 {
26101 X_element_type = X_pointerType->get_base_type();
26102
26103 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26104 // isReduceable = true;
26105 isReduceable = false;
26106 }
26107
26108 if (Y_pointerType != NULL)
26109 {
26110 Y_element_type = Y_pointerType->get_base_type();
26111
26112 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26113 // isReduceable = true;
26114 isReduceable = false;
26115 }
26116
26117 if (isReduceable == true)
26118 {
26119 // Recursive call on non-default modifier base types.
26120 // isSame = (*X_element_type) == (*Y_element_type);
26121 isSame = isEquivalentType(X_element_type,Y_element_type);
26122 }
26123 else
26124 {
26125 // Neither of these types were reducable.
26126 isSame = false;
26127 }
26128#else
26129 isSame = false;
26130#endif
26131 }
26132 else
26133 {
26134 // Recursive call on non-typedef base types.
26135 // isSame = (*X_element_type) == (*Y_element_type);
26136 // isSame = isEquivalentType(X_element_type,Y_element_type);
26137
26138#if DEBUG_TYPE_EQUIVALENCE
26139 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26140#endif
26141
26142 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26143 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26144 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26145
26146 if (X_arrayType != NULL || Y_arrayType != NULL)
26147 {
26148#if 0
26149 if (X_arrayType != NULL)
26150 {
26151 X_element_type = X_arrayType->get_base_type();
26152
26153 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26154 // isReduceable = true;
26155 isReduceable = false;
26156 }
26157
26158 if (Y_arrayType != NULL)
26159 {
26160 Y_element_type = Y_arrayType->get_base_type();
26161
26162 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26163 // isReduceable = true;
26164 isReduceable = false;
26165 }
26166
26167 if (isReduceable == true)
26168 {
26169 // Recursive call on non-default modifier base types.
26170 // isSame = (*X_element_type) == (*Y_element_type);
26171 isSame = isEquivalentType(X_element_type,Y_element_type);
26172 }
26173 else
26174 {
26175 // Neither of these types were reducable.
26176 isSame = false;
26177 }
26178#else
26179 isSame = false;
26180#endif
26181 }
26182 else
26183 {
26184 // Recursive call on non-typedef base types.
26185 // isSame = (*X_element_type) == (*Y_element_type);
26186 // isSame = isEquivalentType(X_element_type,Y_element_type);
26187
26188#if DEBUG_TYPE_EQUIVALENCE
26189 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26190#endif
26191
26192 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26193 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26194 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26195
26196 if (X_functionType != NULL || Y_functionType != NULL)
26197 {
26198 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26199 //TODO: Liao, 9/15/2016, better comparison of function types
26200 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26201#if DEBUG_TYPE_EQUIVALENCE || 0
26202 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26203#endif
26204 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26205 // isSame == value;
26206 isSame = value;
26207
26208 // DQ (3/20/2016): This is reported by GNU as set but not used.
26209 // isReduceable = false;
26210 }
26211 else
26212 {
26213 // Recursive call on non-typedef base types.
26214 // isSame = isEquivalentType(X_element_type,Y_element_type);
26215
26216 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26217 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26218 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26219
26220 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26221 {
26222 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26223 printf ("This should be unreachable code \n");
26224 ROSE_ABORT();
26225
26226#if 0 // [Robb Matzke 2021-03-24]: unreachable
26227 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26228#if DEBUG_TYPE_EQUIVALENCE || 0
26229 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26230#endif
26231 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26232 // isSame == value;
26233 isSame = value;
26234#endif
26235 }
26236 else
26237 {
26238 // Recursive call on non-typedef base types.
26239 // isSame = isEquivalentType(X_element_type,Y_element_type);
26240#if 0
26241 // Check for irreducable types.
26242 bool X_isReduceable = true;
26243 if (isSgTypeSignedLong(X_element_type) != NULL ||
26244 isSgTypeUnsignedInt(X_element_type) != NULL ||
26245 isSgTypeBool(X_element_type) != NULL ||
26246 isSgTypeInt(X_element_type) != NULL)
26247 {
26248 X_isReduceable = false;
26249 }
26250
26251 bool Y_isReduceable = true;
26252 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26253 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26254 isSgTypeBool(Y_element_type) != NULL ||
26255 isSgTypeInt(Y_element_type) != NULL)
26256 {
26257 Y_isReduceable = false;
26258 }
26259#if DEBUG_TYPE_EQUIVALENCE || 0
26260 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26261 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26262#endif
26263 if (X_isReduceable == true || Y_isReduceable == true)
26264 {
26265 // Recursive call on non-default modifier base types.
26266 isSame = isEquivalentType(X_element_type,Y_element_type);
26267 }
26268 else
26269 {
26270 // Neither of these types were reducable.
26271 isSame = false;
26272 }
26273#else
26274 // DQ (12/20/2015): This is the default case for irreducable types.
26275 if (X_element_type->variantT() == Y_element_type->variantT())
26276 {
26277#if DEBUG_TYPE_EQUIVALENCE || 0
26278 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26279 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26280#endif
26281 // DQ (5/26/2016): It is not good enough that the variants match.
26282 // isSame = true;
26283 // isSame = isEquivalentType(X_element_type,Y_element_type);
26284 isSame = (X_element_type == Y_element_type);
26285 }
26286 else
26287 {
26288 // Neither of these types were reducable or equal.
26289 isSame = false;
26290 }
26291#endif
26292 }
26293 }
26294 }
26295 }
26296 }
26297 }
26298 }
26299 }
26300
26301 // Decrement the static variable to control the recursive depth while we debug this.
26302 counter--;
26303
26304#if DEBUG_TYPE_EQUIVALENCE || 0
26305 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26306#endif
26307
26308#if DEBUG_TYPE_EQUIVALENCE || 0
26309 if (counter == 1 && isSame == true)
26310 {
26311 printf ("In SageInterface::isEquivalentType(): counter = %d: isSame = %s type chain X_element_type = %s Y_element_type = %s \n",counter,isSame ? "true" : "false",X.class_name().c_str(),Y.class_name().c_str());
26312
26313 // Debugging output.
26314 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26315 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26316
26317 // Debugging output.
26318 printf (" --- Output of type chain for lhs: \n");
26319 for (size_t i = 0; i < X_typeChain.size(); i++)
26320 {
26321 SgType* element_type = X_typeChain[i];
26322 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26323 SgModifierType* modifierType = isSgModifierType(element_type);
26324 if (modifierType != NULL)
26325 {
26326 // modifierType->get_typeModifier().display("X type chain");
26327 string s = modifierType->get_typeModifier().displayString();
26328 printf (" --- type chain modifier: %s \n",s.c_str());
26329 }
26330 }
26331
26332 printf (" --- Output of type chain for rhs: \n");
26333 for (size_t i = 0; i < Y_typeChain.size(); i++)
26334 {
26335 SgType* element_type = Y_typeChain[i];
26336 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26337 SgModifierType* modifierType = isSgModifierType(element_type);
26338 if (modifierType != NULL)
26339 {
26340 // modifierType->get_typeModifier().display("Y type chain");
26341 string s = modifierType->get_typeModifier().displayString();
26342 printf (" --- --- type chain modifier: %s \n",s.c_str());
26343 }
26344 }
26345 }
26346#endif
26347
26348#if 0
26349 if (counter == 0)
26350 {
26351 if (isSame == true)
26352 {
26353 // printf ("In SageInterface::isEquivalentType(): counter = %d: isSame = %s type chain X_element_type = %s Y_element_type = %s \n",counter,isSame ? "true" : "false",X.class_name().c_str(),Y.class_name().c_str());
26354 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26355 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26356 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26357 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26358 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26359 }
26360 else
26361 {
26362 // printf ("In SageInterface::isEquivalentType(): counter = %d: isSame = %s type chain X_element_type = %s Y_element_type = %s \n",counter,isSame ? "true" : "false",X.class_name().c_str(),Y.class_name().c_str());
26363 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26364 }
26365 }
26366 else
26367 {
26368 printf (" --- counter = %d \n",counter);
26369 }
26370#endif
26371
26372 return isSame;
26373 }
26374
26375
26376#if 0
26377// This is modified to be a template function and so must be moved to the header file.
26378// DQ (8/30/2016): Added function to detect EDG AST normalization.
26379bool
26380SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26381 {
26382 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26383 // function template instnatiations (which come from normalized template functions and member functions).
26384
26385 bool retval = false;
26386
26387#if 1
26388 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26389 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26390 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26391 // But we still need to look at if the location of the parent template is something that we wnat to output.
26392 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26393 // it is not compiler generated.
26394 retval = function->get_marked_as_edg_normalization();
26395#else
26396 // Test for this to be a template instantation (in which case it was marked as
26397 // compiler generated but we may want to allow it to be used in the call graph,
26398 // if it's template was a part was defined in the current directory).
26399 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26400 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26401
26402 if (templateInstantiationFunction != NULL)
26403 {
26404 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26405 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26406 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26407 if (templateFunctionDeclaration != NULL)
26408 {
26409 // retval = operator()(templateFunctionDeclaration);
26410 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26411 }
26412 else
26413 {
26414 // Assume false.
26415 }
26416
26417#if DEBUG_SELECTOR
26418 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26419#endif
26420 }
26421 else
26422 {
26423 if (templateInstantiationMemberFunction != NULL)
26424 {
26425 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26426 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26427 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26428 if (templateMemberFunctionDeclaration != NULL)
26429 {
26430 // retval = operator()(templateMemberFunctionDeclaration);
26431 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26432 }
26433 else
26434 {
26435 // Assume false.
26436 }
26437
26438#if DEBUG_SELECTOR
26439 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26440#endif
26441 }
26442 }
26443#endif
26444
26445 return retval;
26446 }
26447#endif
26448
26449void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26450#if 0
26451 printf("In detectCycleInType():\n");
26452 printf(" -- from = %s\n", from.c_str());
26453 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26454#endif
26455 std::vector<SgType *> seen_types;
26456
26457 while (type != NULL) {
26458
26459 // DQ (4/15/2019): Added assertion.
26460 ROSE_ASSERT(type != NULL);
26461
26462 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26463 if (it != seen_types.end()) {
26464 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26465 size_t i = 0;
26466 for (; it != seen_types.end(); it++) {
26467 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26468 i++;
26469 }
26470 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26471 ROSE_ABORT();
26472 }
26473 seen_types.push_back(type);
26474
26475 SgModifierType * modType = isSgModifierType(type);
26476 SgPointerType * pointType = isSgPointerType(type);
26477 SgReferenceType * refType = isSgReferenceType(type);
26478 SgArrayType * arrayType = isSgArrayType(type);
26479 SgTypedefType * typedefType = isSgTypedefType(type);
26480
26481#if 0
26482 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26483 if (isSgPointerMemberType(type) != NULL)
26484 {
26485 pointType = NULL;
26486 }
26487#endif
26488
26489 if ( modType ) {
26490 type = modType->get_base_type();
26491 } else if ( refType ) {
26492 type = refType->get_base_type();
26493 } else if ( pointType ) {
26494 type = pointType->get_base_type();
26495 // } else if ( pointerMemberType ) {
26496 // type = pointerMemberType->get_base_type();
26497 } else if ( arrayType ) {
26498 type = arrayType->get_base_type();
26499 } else if ( typedefType ) {
26500 type = typedefType->get_base_type();
26501 } else {
26502 break;
26503 }
26504 ROSE_ASSERT(type != NULL);
26505 }
26506}
26507
26508
26509#if 0
26510// DQ (11/10/2019): Older original version of the function.
26511
26512// DQ (6/6/2019): Move this to the SageInteface namespace.
26513void
26515 {
26516 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26517 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26518 // declarations in the outlined code we can support the outpiled code with those references. This
26519 // approach has the added advantage of also supporting the same include file tree as the original
26520 // file where the outlined code is being taken from.
26521
26522 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26523 {
26524 public:
26525 std::vector<SgFunctionDeclaration*> functionList;
26526 SgSourceFile* sourceFile;
26527 int sourceFileId;
26528 string filenameWithPath;
26529
26530 public:
26531 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26532
26533 void visit (SgNode* node)
26534 {
26535#if 0
26536 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26537#endif
26538 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26539 if (temp_sourceFile != NULL)
26540 {
26541 sourceFile = temp_sourceFile;
26542 sourceFileId = sourceFile->get_file_info()->get_file_id();
26543
26544 // The file_id is not sufficnet, not clear why, but the filenames match.
26545 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26546
26547 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26548
26549 }
26550
26551 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26552 if (functionDeclaration != NULL)
26553 {
26554 // This should have been set already.
26555 ROSE_ASSERT(sourceFile != NULL);
26556
26557 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
26558 if (functionDeclaration == definingFunctionDeclaration)
26559 {
26560#if 1
26561 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
26562 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26563
26564 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26565 printf (" --- source file: file_info: id = %d name = %s \n",
26566 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
26567#endif
26568 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
26569 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
26570 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
26571#if 1
26572 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
26573#endif
26574 // Remove the defining declaration as a test.
26575 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
26576 if (isInSourceFile == true && functionDeclarationScope != NULL)
26577 {
26578#if 1
26579 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
26580 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
26581#endif
26582 // functionDeclarationScope->removeStatement(functionDeclaration);
26583 // removeStatement(functionDeclaration);
26584 functionList.push_back(functionDeclaration);
26585 }
26586 }
26587 }
26588 }
26589 };
26590
26591 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
26592 TransformFunctionDefinitionsTraversal traversal;
26593 traversal.traverse(node, preorder);
26594
26595 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
26596
26597#if 1
26598 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
26599#endif
26600
26601 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
26602 while (i != functionList.end())
26603 {
26604 SgFunctionDeclaration* functionDeclaration = *i;
26605 ROSE_ASSERT(functionDeclaration != NULL);
26606
26607 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
26608 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26609
26610#if 1
26611 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
26612 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26613#endif
26614 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
26615 // removeStatement(functionDeclaration);
26616 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
26617
26618 i++;
26619 }
26620
26621#if 0
26622 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
26623 ROSE_ABORT();
26624#endif
26625 }
26626#endif
26627
26628
26629void
26631 {
26632 // DQ (10/31/2020): Display function for scopes (useful for debugging).
26633 ROSE_ASSERT(scope != NULL);
26634
26635 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
26636
26637 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
26638 SgStatementPtrList statementList = scope->generateStatementList();
26639 for (size_t i = 0; i < statementList.size(); i++)
26640 {
26641 SgStatement* statement = statementList[i];
26642 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
26643 }
26644
26645#if 0
26646 printf ("Exiting as a test at the end of evaluation of global scope! \n");
26647 ROSE_ABORT();
26648#endif
26649 }
26650
26651
26654 {
26655 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
26656 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
26657
26658#if 0
26659 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
26660 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26661#endif
26662
26663 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
26664 bool isConstructor = false;
26665 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
26666 if (tmp_memberFunctionDeclaration != NULL)
26667 {
26668 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
26669
26670#if 0
26671 if (isConstructor == true)
26672 {
26673 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
26674 return;
26675 }
26676#endif
26677 }
26678
26679 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
26680 // bool replaceWithEmptyDeclaration = false;
26681 // SgDeclarationStatement* emptyDeclaration = NULL;
26682
26683 SgName name = functionDeclaration->get_name();
26684 SgType* return_type = functionDeclaration->get_type()->get_return_type();
26685
26686#if 0
26687 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
26688 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
26689 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
26690 // this function that builds the function prototype from the defining function.
26691
26692 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
26693 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
26694 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
26695
26696 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
26697 // are specified in the function declarations, and make sure the prototype reproduces them.
26698 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
26699 {
26700 SgInitializedName* arg = functionDeclaration->get_args()[i];
26701#if 1
26702 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
26703 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
26704 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
26705#endif
26706 if (arg->get_file_info()->isDefaultArgument() == true)
26707 {
26708 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
26709 }
26710 }
26711#endif
26712
26713#if 1
26714 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26715#else
26716 // DQ (9/26/2019): We need to avoid building SgFunctionParameterList IR nodes and then not attaching them to anything (parent pointers are checked in AST consistancy testing).
26717 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
26718 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
26719 SgFunctionParameterList* param_list = NULL;
26720
26721 if (templateInstantiationFunctionDecl == NULL)
26722 {
26723 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26724 }
26725 else
26726 {
26727 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
26728 if (templateInstantiationMemberFunctionDecl == NULL)
26729 {
26730 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26731 }
26732 }
26733#endif
26734
26735
26736 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
26737 bool isTemplateInstantiationMemberFunctionDecl = false;
26738
26739 SgScopeStatement* scope = functionDeclaration->get_scope();
26740 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
26741 SgExprListExp* python_decoratorList = NULL;
26742 bool buildTemplateInstantiation = false;
26743 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
26744
26745 // DQ (9/26/2019): Tracing down a null parent pointer.
26746 // ROSE_ASSERT(param_list->get_parent() != NULL);
26747 // ROSE_ASSERT(param_list->get_parent() == NULL);
26748 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
26749
26750 switch (functionDeclaration->variantT())
26751 {
26752 case V_SgTemplateMemberFunctionDeclaration:
26753 {
26754#if 0
26755 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
26756#endif
26757 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
26758 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
26759
26760 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
26761
26762 unsigned int functionConstVolatileFlags = 0;
26763
26764 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
26765
26766 // Need to call:
26767 // unsigned int get_mfunc_specifier();
26768
26769 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
26770 ROSE_ASSERT(memberFunctionType != NULL);
26771
26772 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
26773
26774 // SgTemplateMemberFunctionDeclaration*
26775 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26776 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
26777
26778 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
26779 // ROSE_ASSERT(templateParameterList != NULL);
26780
26781 templateMemberFunctionDeclaration =
26782 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
26783#if 0
26784 printf ("ERROR: Template functions are not yet supported! \n");
26785 ROSE_ABORT();
26786#endif
26787 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
26788
26789 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26790
26791 // DQ (11/21/2019): Handle constructors.
26792 if (isConstructor == true)
26793 {
26794 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
26795 }
26796
26797 break;
26798 }
26799
26800 case V_SgTemplateFunctionDeclaration:
26801 {
26802#if 0
26803 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
26804#endif
26805 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
26806 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
26807
26808 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
26809
26810 // SgTemplateFunctionDeclaration*
26811 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26812 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
26813
26814 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
26815
26816 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
26817#if 0
26818 printf ("ERROR: Template functions are not yet supported! \n");
26819 ROSE_ABORT();
26820#endif
26821 nondefiningFunctionDeclaration = templateFunctionDeclaration;
26822
26823 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26824
26825 break;
26826 }
26827
26828 // DQ (10/29/2020): Added new case.
26829 case V_SgTemplateInstantiationMemberFunctionDecl:
26830 {
26831 buildTemplateInstantiation = true;
26832
26833 isTemplateInstantiationMemberFunctionDecl = true;
26834
26835 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
26836 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
26837 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
26838#if 0
26839 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
26840 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
26841 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
26842 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
26843 if (templateDeclaration != NULL)
26844 {
26845 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
26846 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
26847 }
26848#endif
26849 // name = functionDeclaration->get_name();
26850 // name = templateInstantiationMemberFunctionDecl->get_template_name();
26851 name = templateInstantiationMemberFunctionDecl->get_templateName();
26852#if 0
26853 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
26854#endif
26855 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
26856 }
26857 // fall through
26858 case V_SgMemberFunctionDeclaration:
26859 {
26860#if 0
26861 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
26862#endif
26863 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
26864 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
26865
26866 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
26867
26868 // SgMemberFunctionDeclaration*
26869 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26870 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
26871
26872 unsigned int functionConstVolatileFlags = 0;
26873
26874 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
26875
26876 // Need to call:
26877 // unsigned int get_mfunc_specifier();
26878
26879 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
26880 // since they is not allowed to be declared outside of the class they are a member of.
26881
26882 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
26883 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
26884#if 0
26885 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
26886#endif
26887 if (buildPrototype == true)
26888 {
26889 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
26890 ROSE_ASSERT(memberFunctionType != NULL);
26891#if 0
26892 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
26893#endif
26894 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
26895
26896 memberFunctionDeclaration =
26898 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
26899 buildTemplateInstantiation,templateArgumentsList );
26900#if 0
26901 printf ("ERROR: Member functions are not yet supported! \n");
26902 ROSE_ABORT();
26903#endif
26904 // DQ (11/21/2019): Handle constructors.
26905 if (isConstructor == true)
26906 {
26907 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
26908 }
26909
26910 nondefiningFunctionDeclaration = memberFunctionDeclaration;
26911
26912 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26913 }
26914 else
26915 {
26916 // Case of member function defined outside of it's class.
26917#if 0
26918 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
26919#endif
26920 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
26921 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
26922 nondefiningFunctionDeclaration = NULL;
26923#if 0
26924 nondefiningFunctionDeclaration = NULL;
26925
26926 replaceWithEmptyDeclaration = true;
26927 emptyDeclaration = buildEmptyDeclaration();
26928 ROSE_ASSERT(emptyDeclaration != NULL);
26929#endif
26930 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
26931 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26932
26933 // Since we din't build a member function we don't need the parameter list.
26934 delete param_list;
26935 param_list = NULL;
26936#if 0
26937 printf ("Exiting as a test! \n");
26938 ROSE_ABORT();
26939#endif
26940 }
26941
26942 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
26943 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26944 break;
26945 }
26946
26947 case V_SgFunctionDeclaration:
26948 {
26949 // This is for a non-member non-template function declaration.
26950 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
26951 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26952 break;
26953 }
26954
26955 // DQ (10/29/2020): Added new case.
26956 case V_SgTemplateInstantiationFunctionDecl:
26957 {
26958 // This is for a non-member non-template function declaration.
26959 buildTemplateInstantiation = true;
26960 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
26961 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
26962 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
26963#if 0
26964 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
26965 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
26966 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
26967 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
26968 if (templateDeclaration != NULL)
26969 {
26970 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
26971 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
26972 }
26973#endif
26974 name = templateInstantiationFunctionDecl->get_templateName();
26975#if 0
26976 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
26977#endif
26978 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
26979 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26980 break;
26981 }
26982
26983 default:
26984 {
26985 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
26986 // These cases would be only template instantiations.
26987
26988 // Nothing to do, except delete the parameter list we built, and return.
26989 delete param_list;
26990 param_list = NULL;
26991
26992 return NULL;
26993 }
26994 }
26995
26996 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
26997 // DQ (9/26/2019): Tracing down a null parent pointer.
26998 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
26999 // ROSE_ASSERT(param_list != NULL);
27000 // ROSE_ASSERT(param_list->get_parent() != NULL);
27001
27002 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27003
27004 if (nondefiningFunctionDeclaration != NULL)
27005 {
27006 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27007 {
27008#if 0
27009 printf ("Setting the firstNondefiningDeclaration \n");
27010#endif
27011 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27012 }
27013
27014 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27015 {
27016#if 0
27017 printf ("Setting the definingDeclaration \n");
27018#endif
27019 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27020 }
27021
27022 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27023 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27024
27025 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27026 if (nondefiningFunctionDeclaration != NULL)
27027 {
27028 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27029 // This is a bug in the support for building a new prototype from a defining function declaration
27030 // and caused this problem. This assertion will prevent this sort of error from happening again.
27031 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27032 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27033 }
27034 }
27035
27036 return nondefiningFunctionDeclaration;
27037 }
27038
27039
27040// DQ (10/27/2020): Need to return the generated function prototype (incase we want to mark it for output or template unparsing from the AST).
27043 {
27044 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27045 ROSE_ASSERT(functionDeclaration != NULL);
27046
27047#if 0
27048 printf ("****************************************************************** \n");
27049 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27050 SageInterface::printOutComments (functionDeclaration);
27051 printf ("****************************************************************** \n");
27052#endif
27053
27054 // DQ (10/15/2019): Find the file_id associated with the current file, and make the transformation with the same file_id value so that it will be unparsed.
27055
27056 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27057
27058 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27059 if (nondefiningFunctionDeclaration != NULL)
27060 {
27061 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27062 // This is a bug in the support for building a new prototype from a defining function declaration
27063 // and caused this problem. This assertion will prevent this sort of error from happening again.
27064 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27065 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27066 }
27067
27068 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27069
27070 if (templateInstantiationFunctionDecl == NULL)
27071 {
27072 if (nondefiningFunctionDeclaration != NULL)
27073 {
27074 // DQ (10/29/2020): Match the associated declaration modifiers.
27075 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27076
27077 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27078 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27079 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27080
27081 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27082 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27083
27084 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27085
27086 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27087 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27088 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27089
27090 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27091 // removeStatement(functionDeclaration);
27092 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27093 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27094 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27095 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27096 // DQ (11/15/2020): Note that the default is false, and we need true.
27097 bool movePreprocessingInfo = true;
27098 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27099
27100 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27101 // DQ (11/24/2020): Maybe we should set the parent of the functionDeclaration to NULL, so that we will know to set it properly later.
27102 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27103 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27104 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27105 }
27106 }
27107 else
27108 {
27109 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27110 nondefiningFunctionDeclaration = NULL;
27111 }
27112
27113 // Check that static declaration is preserved.
27114 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27115 {
27116 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27117 }
27118
27119 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27120 return nondefiningFunctionDeclaration;
27121 }
27122
27123
27124std::vector<SgFunctionDeclaration*>
27126 {
27127 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27128 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27129 // declarations in the outlined code we can support the outpiled code with those references. This
27130 // approach has the added advantage of also supporting the same include file tree as the original
27131 // file where the outlined code is being taken from.
27132
27133 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27134 {
27135 public:
27136 std::vector<SgFunctionDeclaration*> functionList;
27137 FunctionDefinitionsTraversal() {}
27138
27139 void visit (SgNode* node)
27140 {
27141 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27142 if (functionDeclaration != NULL)
27143 {
27144 // This should have been set already.
27145 // ROSE_ASSERT(sourceFile != NULL);
27146
27147 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27148 if (functionDeclaration == definingFunctionDeclaration)
27149 {
27150 // Remove the defining declaration as a test.
27151 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27152 if (functionDeclarationScope != NULL)
27153 {
27154 functionList.push_back(functionDeclaration);
27155 }
27156 }
27157 }
27158 }
27159 };
27160
27161 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27162 FunctionDefinitionsTraversal traversal;
27163
27164 traversal.traverseWithinFile(node, preorder);
27165
27166 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27167
27168 return functionList;
27169 }
27170
27171
27172void
27174 {
27175 ROSE_ASSERT(node != NULL);
27176
27177 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27178 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27179
27180 while (i != functionList.end())
27181 {
27182 SgFunctionDeclaration* functionDeclaration = *i;
27183 ROSE_ASSERT(functionDeclaration != NULL);
27184 // Transform into prototype.
27186 i++;
27187 }
27188 }
27189
27190
27191
27192// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27193void
27195 {
27196 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27197 // support for variable declarations initialized using lambda functions is that the initalizer
27198 // is discarded at some point in the processing of the AST. This function reports on all
27199 // variable declarations and if they contain initializers and if so what kind of initializer.
27200
27201 ROSE_ASSERT(node != nullptr);
27202
27203 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27204 class CheckInitializerTraversal : public AstSimpleProcessing
27205 {
27206 public:
27207 void visit (SgNode* node)
27208 {
27209 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27210 if (variableDeclaration != NULL)
27211 {
27212 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27213 SgExpression* initializer = initializedName->get_initializer();
27214
27215 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27216 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27217
27218 if (initializer != NULL)
27219 {
27220 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27221 }
27222 }
27223 }
27224 };
27225
27226 // Now buid the traveral object and call the traversal (preorder) on the project.
27227 CheckInitializerTraversal traversal;
27228 traversal.traverse(node, preorder);
27229 }
27230
27231namespace
27232{
27233 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27234 {
27235 void setResult(SgNamedType* ty) { res = ty; }
27236 void setResult(SgType*) { /* not a named type */ }
27237
27238 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27239
27240 template <class SageDeclarationStatement>
27241 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27242 {
27243 // SgDeclarationStatement::get_type is not a virtual function
27244 // => find overloaders returning SgNamedType in subclasses
27245 // by using the full type (SageDeclarationStatement).
27246 setResult(n.get_type());
27247 }
27248
27249 template <class SageNode>
27250 void handle(SageNode& n)
27251 {
27252 handle(n, n);
27253 }
27254 };
27255}
27256
27258{
27259 return sg::dispatch(DeclaredType{}, declaration);
27260}
27261
27263 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27264 ROSE_ASSERT(gsaf != nullptr);
27265 SgSymbolTable * st = gsaf->get_symbol_table();
27266 ROSE_ASSERT(st != nullptr);
27267 rose_hash_multimap * hmm = st->get_table();
27268 ROSE_ASSERT(hmm != nullptr);
27269 hmm->clear();
27270
27271 st = SgNode::get_globalTypeTable()->get_type_table();
27272 ROSE_ASSERT(st != nullptr);
27273 hmm = st->get_table();
27274 ROSE_ASSERT(hmm != nullptr);
27275 hmm->clear();
27276
27278 ROSE_ASSERT(st != nullptr);
27279 hmm = st->get_table();
27280 ROSE_ASSERT(hmm != nullptr);
27281 hmm->clear();
27282}
27283
27285/*
27286
27287By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27288
27289--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27290 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27291 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27292 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27293
27294
27295TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27296
27297 * */
27298int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27299{
27300 int match_count = 0;
27301 ROSE_ASSERT (root);
27302
27303 // find all SgArrowExp, then try to match the expected pattern
27304 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27305 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27306
27307 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27308 // So we need to make sure the same subtree is only processed once
27309 boost::unordered::unordered_map <SgNode*, bool> visited;
27310
27311 // reverse iterator is safer to use than forward iterator to support translation
27312 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27313 {
27314 // skip a node if it is previously processed.
27315 if (visited.count(*i)==1)
27316 continue;
27317
27318 visited[*i]=true;
27319
27320 SgArrowExp* a_exp = isSgArrowExp(*i);
27321
27322 if (!a_exp)
27323 {
27324 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27325 ROSE_ASSERT (a_exp);
27326 }
27327
27328 if (transformationGeneratedOnly)
27329 {
27330 if (!(a_exp->get_file_info()->isTransformation()))
27331 continue;
27332 }
27333
27334 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27335 {
27336 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27337 {
27338 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27339 {
27340 // do the transformation: copy two operands, making a dot exp instead
27341 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27342 replaceExpression (a_exp, dot_exp);
27343 match_count++;
27344 }
27345 }
27346 }
27347 } // end for
27348
27349 return match_count;
27350}
27351
27352bool
27354 {
27355 class Traversal : public AstSimpleProcessing
27356 {
27357 public:
27358 bool found;
27359 Traversal() : found(false) {}
27360 void visit (SgNode* node)
27361 {
27362 SgCastExp* castExpression = isSgCastExp(node);
27363 if (castExpression != NULL)
27364 {
27365 // SgNode* parent = castExpression->get_parent();
27366 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27367 if (initializer == NULL)
27368 {
27369 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27370 if (castExpression->get_file_info()->isTransformation() == true)
27371 {
27372 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27373 found = true;
27374#if 0
27375 printf ("Exiting as a test! \n");
27376 ROSE_ASSERT(false);
27377#endif
27378 }
27379 else
27380 {
27381#if 0
27382 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27383#endif
27384 }
27385 }
27386 else
27387 {
27388 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27389#if 1
27390 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27391#endif
27392 }
27393 }
27394 else
27395 {
27396#if 0
27397 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27398#endif
27399 }
27400 }
27401 };
27402
27403#if 1
27404 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27405#endif
27406
27407 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27408 Traversal traversal;
27409 traversal.traverse(n, preorder);
27410
27411#if 1
27412 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27413#endif
27414#if 0
27415 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27416 if (traversal.found == true)
27417 {
27418 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27419 }
27420
27421 return false;
27422#else
27423 return traversal.found;
27424#endif
27425 }
27426
27427// A helper function to check
27428// begin: return 1
27429// middle (#else, #elif): return 2
27430// end directive: return -1
27431// othewise return 0;
27432static int isBeginDirective (PreprocessingInfo* info)
27433{
27434 ROSE_ASSERT (info != NULL);
27435 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27436 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27437 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27438 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27439 {
27440 return 1;
27441 }
27442 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27443 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27444 {
27445 return 2;
27446 }
27447 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27448 {
27449 return -1;
27450 }
27451
27452 return 0;
27453}
27454
27455// a helper function to move things, the associated directive in the middle
27456static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27457{
27458// AttachedPreprocessingInfoType* infoList = (*ki).first;
27459// int cidx= (*ki).second;
27460
27461 relatedInfoList.insert (infoList);
27462
27463 PreprocessingInfo* info = (*infoList)[cidx];
27464 // rewrite relative position
27465 info->setRelativePosition(PreprocessingInfo::after);
27466
27467 // insert after lnode
27468 lnode->addToAttachedPreprocessingInfo (info);
27469 retVal++;
27470
27471 // zero out from original list
27472 (*infoList)[cidx]= NULL;
27473}
27474
27475// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27477{
27478 int retVal=0;
27479 ROSE_ASSERT(lnode);
27480
27481 // collecting NULL entries
27482 RoseAst ast(lnode);
27483 RoseAst::iterator ast_i=ast.begin();
27484
27485 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27486 for(;ast_i!=ast.end();++ast_i) {
27487 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27488 if (current ==NULL ) // skip non located nodes
27489 continue;
27490
27491 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27492 if (infoList == NULL) continue;
27493
27494 int commentIndex=0;
27495 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27496 {
27497 // fundamentally, we want to move individual PreprocessingInfo objects
27498 // Or just duplicate them (easier)
27499 PreprocessingInfo * info = *ci;
27500 if (info==NULL)
27501 empty_entries.push_back( make_pair (infoList, commentIndex) );
27502 commentIndex++;
27503 }
27504 }
27505
27506 // using reverse iterator to remove from backwards
27507 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27508 {
27509 AttachedPreprocessingInfoType* infoList = (*ki).first;
27510 int cidx= (*ki).second;
27511
27512 PreprocessingInfo* info = (*infoList)[cidx];
27513 ROSE_ASSERT (info==NULL);
27514
27515 // erase start+offset
27516 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27517 infoList->erase(k+cidx);
27518// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27519 retVal ++;
27520 }
27521 return retVal;
27522}
27523
27524//TODO: expose this to header file?
27525// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27526// Should this be maintained by librose or user space code?
27527static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27528
27529void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27530{
27531 // stop condition
27532 if (current == NULL)
27533 return;
27534
27535 // Three possible locations: before, inside, and after
27536 // immediately add prepression info that is before and inside of current node
27537 // delayed additions of these that are located after the current node
27538 vector<PreprocessingInfo*> afterList;
27539 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27540 {
27541 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27542
27543 if (comments != nullptr)
27544 {
27545 AttachedPreprocessingInfoType::iterator i;
27546 int idx=0;
27547 for (i = comments->begin (); i != comments->end (); i++)
27548 {
27549 PreprocessingInfo* info= *i;
27550
27551 // prepare the data just in case
27553 data.container=comments;
27554 data.index = idx;
27555 data.depth = depth;
27556
27557 // put directives with before location into the infoList
27558 if (info->getRelativePosition () == PreprocessingInfo::before)
27559 {
27560 infoList.push_back (info);
27561 infoMap[info] = data;
27562 }
27563 // How about inside position?
27564 // why it should be intepreted as the last one after all inner statment's preprocessingInfo?
27565 // because if it should be unparsed before all of them, it should have been attached to the first stmt's before location instead!
27566 else if (info->getRelativePosition () == PreprocessingInfo::after
27567 || info->getRelativePosition () == PreprocessingInfo::inside
27568 )
27569 {
27570 afterList.push_back (info); // if attached to be after, save to afterList
27571 infoMap[info] = data;
27572 }
27573 else
27574 {
27575 mlog[Sawyer::Message::Common::WARN] <<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
27576 // ROSE_ASSERT (false); // Jovial has end_of
27577 }
27578
27579 idx++;
27580 } // end for
27581 }
27582 } // end if
27583
27584 // handling children nodes
27585 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
27586 for (auto c: children)
27587 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
27588
27589 // append after locations after recursively handling children nodes.
27590 for (auto fi : afterList)
27591 infoList.push_back(fi);
27592}
27593
27594// This may be expensive to run since it is called anytime replace() is called.
27596// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
27597// This should be done before removing or replace the statement: lnode
27598// TODO: this may need to be a recursive function for multiple levels of nested directives.
27599//
27600// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
27601//
27603{
27604 int retVal=0;
27605 ROSE_ASSERT(lnode);
27606
27607// algorithm: using a queue (vector to simulate it)
27608// queue <PreProcessingInfo* > q;
27609// start from 2nd node: ignore the first root node
27610// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
27611// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
27612//
27613// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
27614// They cannot neutralize each other.
27615// They should be attached to be after lnode !
27616 RoseAst ast(lnode);
27617 RoseAst::iterator ast_i=ast.begin();
27618 ++ast_i; // skip the root node itself
27619
27620 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
27621 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
27622 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
27623 // it is not always an independent decision.
27624 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
27625 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
27626
27627 // store the associated middle directives what should be erased in the end
27628 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
27629 // associated_directives[BeginInfo] will not retrieve them!
27630 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
27631
27632 // Two steps here
27633 // Step 1: We build the list first, then go through them to neutralize them
27634 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
27635 //
27636 // The list must provide the following information
27637 // infoList (container), index of the directive, PreprocessingInfo* itself
27638 vector<PreprocessingInfo*> candidateInfoList;
27639 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
27640 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
27641 // now we have both candidateInfoList and infoMap.
27642
27643 for (auto candidate: candidateInfoList)
27644 {
27645 // fundamentally, we want to move individual PreprocessingInfo objects
27646 // Or just duplicate them (easier)
27647 PreprocessingInfo * info = candidate;
27648
27649 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
27650 if (infoMap[info].depth ==0)
27651 continue;
27652
27653 int commentIndex = infoMap[info].index;
27654 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
27655
27656 // begin directives
27657 if ( isBeginDirective(info) == 1)
27658 {
27659 keepers.push_back(make_pair (infoList,commentIndex));
27660 }
27661 // the middle #else, #elif,
27662 else if (isBeginDirective(info) == 2)
27663 {
27664 // two situtations for immediate decision of unbalanced status
27665 //1. empty stack, or
27666 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27667 if (keepers.size()==0)
27668 keepers.push_back(make_pair (infoList, commentIndex));
27669 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27670 {
27671 keepers.push_back(make_pair (infoList,commentIndex));
27672 }
27673 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27674 {
27675 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27676 // we associated this middle directive with the beginning directive
27677 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27678 }
27679 }
27680 // end directive
27681 else if ( isBeginDirective(info) == -1)
27682 {
27683 bool neutralized = false;
27684 // neutralize an internall matched pair, if any
27685 if (keepers.size()>0)
27686 {
27687 AttachedPreprocessingInfoType* comments = keepers.back().first;
27688 int idx = keepers.back().second;
27689
27690 if(isBeginDirective( (*comments)[idx] )==1)
27691 {
27692 keepers.pop_back();
27693 neutralized = true;
27694 }
27695 }
27696
27697 if (!neutralized)
27698 keepers.push_back(make_pair (infoList,commentIndex));
27699 }
27700
27701 }
27702
27703#if 0 // old and wrong linear search of directives
27704
27705 // Then we go through the list, extract keepers, neutralize anything else.
27706 for(;ast_i!=ast.end();++ast_i) {
27707 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27708 if (current ==NULL ) // skip non located nodes
27709 continue;
27710
27711 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27712 if (infoList == NULL) continue;
27713
27714 int commentIndex=0;
27715 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27716 {
27717 ROSE_ASSERT(*ci != NULL);
27718 // fundamentally, we want to move individual PreprocessingInfo objects
27719 // Or just duplicate them (easier)
27720 PreprocessingInfo * info = *ci;
27721
27722 // begin directives
27723 if ( isBeginDirective(info) == 1)
27724 {
27725 keepers.push_back(make_pair (infoList,commentIndex));
27726 }
27727 // the middle #else, #elif,
27728 else if (isBeginDirective(info) == 2)
27729 {
27730 // two situtations for immediate decision of unbalanced status
27731 //1. empty stack, or
27732 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27733 if (keepers.size()==0)
27734 keepers.push_back(make_pair (infoList,commentIndex));
27735 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27736 {
27737 keepers.push_back(make_pair (infoList,commentIndex));
27738 }
27739 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27740 {
27741 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27742 // we associated this middle directive with the beginning directive
27743 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27744 }
27745 }
27746 // end directive
27747 else if ( isBeginDirective(info) == -1)
27748 {
27749 bool neutralized = false;
27750 // neutralize an internall matched pair, if any
27751 if (keepers.size()>0)
27752 {
27753 AttachedPreprocessingInfoType* comments = keepers.back().first;
27754 int idx = keepers.back().second;
27755
27756 if(isBeginDirective( (*comments)[idx] )==1)
27757 {
27758 keepers.pop_back();
27759 neutralized = true;
27760 }
27761 }
27762
27763 if (!neutralized)
27764 keepers.push_back(make_pair (infoList,commentIndex));
27765 }
27766 commentIndex++;
27767 }
27768 }
27769#endif
27770// TODO this variable is not used in the end.
27771 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
27772 // now we go through the keepers: those to be moved to the new location!! They are also the ones to be erased from original location!
27773 // move from old containers, and add into lnode's after position
27774 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
27775 {
27776 AttachedPreprocessingInfoType* infoList = (*ki).first;
27777 int cidx= (*ki).second;
27778 // TODO replace the code block below with moveInofListToNewPlace()
27779 relatedInfoList.insert (infoList);
27780
27781 PreprocessingInfo* info = (*infoList)[cidx];
27782 // rewrite relative position
27783 info->setRelativePosition(PreprocessingInfo::after);
27784
27785 // insert after lnode
27786 lnode->addToAttachedPreprocessingInfo (info);
27787 retVal++;
27788
27789 // we additionally process the associated directives, if any, TODO: reverse processing also??
27790 if (associated_directives.count (info)!=0)
27791 {
27792 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
27793 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
27794 {
27795 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
27796 int aidx= (*vec_i).second;
27797 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
27798 associated_erase.push_back(make_pair (a_infoList, aidx));
27799 }
27800 } // each begin directive may associate multiple other middle directives
27801
27802 // Doing this after the associated directives are processed.
27803 // zero out from original list, Note this element slot is NULL now!
27804 (*infoList)[cidx]= NULL;
27805
27806 }
27808 return retVal;
27809}
to specify a construct using a specifier Can be used alone or with parent handles when relative speci...
virtual void * getNode() const
Get the raw IR node associated with the current abstract node.
Base class for all IR node attribute values.
Attribute Evaluator for synthesized attributes.
SynthesizedAttributeType traverse(SgNode *node)
evaluates attributes on the entire AST
Attribute storing an SgNode.
Class for traversing the AST.
void traverse(SgNode *node, Order treeTraversalOrder)
traverse the entire AST. Order defines preorder (preorder) or postorder (postorder) traversal....
void visit(SgNode *astNode)
this method is called at every traversed node.
void visit(SgNode *astNode)
visitor function for each node to collect non-builtin types' declarations
void visit(SgNode *astNode)
this method is called at every traversed node.
For preprocessing information including source comments, include , if, define, etc.
RelativePositionType
MK: Enum type to store if the directive goes before or after the corresponding line of source code.
AST iterator.
Definition RoseAst.h:54
Interface for iterating over an AST.
Definition RoseAst.h:26
iterator begin()
Iterator positioned at root of subtree.
iterator end()
Iterator positioned at the end of the traversal.
const Digest & digest() override
Return the digest.
void insert(const std::string &)
Insert data into the digest.
uint64_t toU64()
Returns the hash as a 64 bit int.
void visit(SgNode *node)
this method is called at every traversed node.
Interface for creating a statement whose computation writes its answer into a given variable.
A persistent attribute to represent a unique name for an expression.
SgName get_name() const override
Access function for getting name from declarations or types internally.
Base class for binary files.
SgAsmGenericHeaderList *const & get_headers() const
Property: List of all headers in file.
SgAsmGenericHeaderPtrList const & get_headers() const
Property: List of file header nodes.
Base class for container file headers.
SgAsmInterpretationPtrList const & get_interpretations() const
Property: Interpretation list.
Represents an interpretation of a binary container.
This class represents the concept of a C Assembler statement.
This class represents the rhs of a variable declaration which includes an optional assignment (e....
void set_operand(SgExpression *exp)
This sets the rhs expression.
SgExpression * get_operand() const
Returns the rhs.
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.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a binary operator. It is derived from a SgExpression because oper...
SgExpression * get_lhs_operand() const
returns SgExpression pointer to the lhs operand associated with this binary operator.
void set_rhs_operand(SgExpression *exp)
This function allows the p_rhs_operand pointer to be set (used internally).
void set_lhs_operand(SgExpression *exp)
This function allows the p_lhs_operand pointer to be set (used internally).
SgExpression * get_rhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
SgExpression * get_lhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
virtual VariantT variantT() const override
returns new style SageIII enum values
SgExpression * get_rhs_operand() const
returns SgExpression pointer to the rhs operand associated with this binary operator.
This class represents a boolean value (expression value).
This class represents the notion of a break statement (typically used in a switch statment).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a C and C++ case option (used within a switch statement).
SgStatement * get_body() const
Returns pointer to a SgBasicBlock object.
void set_key(SgExpression *key)
Access function for pointer to SgExpression object wrapped by SgExpressionRoot in p_key_root.
void set_body(SgStatement *body)
Access function for p_body.
SgExpression * get_key() const
Returns pointer to a SgExpression object wrapped by SgExpressionRoot in p_key_root.
This class represents a cast of one type to another.
SgType * get_type() const override
unparsing support for pragmas
This class represents the concept of a catch within a try-catch construct used in C++ exception handl...
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Access function for p_body.
This class represents the concept of a class declaration statement. It includes the concept of an ins...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a class definition in C++.
SgClassDeclaration * get_declaration() const
returns the class declaration associated with this class decinition.
const SgDeclarationStatementPtrList & get_members() const
Returns a const list to the data member declarations.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a C++ expression built from a class name.
SgClassSymbol * get_symbol() const
Returns pointer to SgSymbol.
This class represents the concept of a class name within the compiler.
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
static SgClassType * createType(SgDeclarationStatement *decl=NULL, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgClassType (types whose constructors take par...
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.
void set_false_exp(SgExpression *false_exp)
Access function for p_false_exp.
SgExpression * get_conditional_exp() const
Access function for p_conditional_exp.
SgExpression * get_false_exp() const
Access function for p_false_exp.
void set_true_exp(SgExpression *true_exp)
Access function for p_true_exp.
void set_conditional_exp(SgExpression *conditional_exp)
Access function for p_conditional_exp.
This class represents the call of a class constructor to initialize a variable. For example "Foo foo;...
SgType * get_expression_type() const
Access function for p_expression_type, returns pointer to SgType associated with constructor.
This class represents the concept of a C or C++ continue statement.
Supporting class from copy mechanism within ROSE.
Definition sageCopy.h:26
This class represents the concept of a contructor initializer list (used in constructor (member funct...
bool isFriend() const
declaration modifier is friend.
This class represents the concept of a declaration statement.
SgSymbol * search_for_symbol_from_symbol_table() const
User interface for retrieving the associated symbol from the declaration.
void set_definingDeclaration(SgDeclarationStatement *definingDeclaration)
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
void set_firstNondefiningDeclaration(SgDeclarationStatement *firstNondefiningDeclaration)
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
SgDeclarationStatement * get_definingDeclaration() const
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
bool isForward() const
Returns boolean value indicating if this is a forward declaration.
SgDeclarationStatement * get_firstNondefiningDeclaration() const
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool hasAssociatedSymbol() const
Returns boolean value true of this type of declaration has an associated sysmbol.
SgName get_template_name() const
This function returns the template name (taken from the template declaration for the class,...
This class represents the concept of a C or C++ default case within a switch statement.
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Returns pointer to SgBasicBlock.
This class represents a directory within a projects file structure of files and directories.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_condition(SgStatement *condition)
Access function for p_condition.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the notion of an value (expression value).
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.
void set_scope(SgScopeStatement *scope) override
Access function for p_scope.
const SgInitializedNamePtrList & get_enumerators() const
Access function for p_enumerators.
This class represents the concept of a C and C++ expression list.
int replace_expression(SgExpression *o, SgExpression *n) override
This class represents the base class of all the expressions within this grammar.
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,...
virtual std::string class_name() const override
returns a string representing the class name
void set_need_paren(bool need_paren)
This function allows the p_need_paren flag to be set (used internally).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgType * get_type() const
unparsing support for pragmas
virtual int replace_expression(SgExpression *oldChild, SgExpression *newChild)
This class represents the base class of all the expressions within this grammar.
virtual const char * sage_class_name() const override
virtual Sg_File_Info * get_file_info(void) const override
Interface function to implement original SAGE interface to SgFile_Info objects.
void set_lvalue(bool lvalue)
This function allows the p_lvalue flag to be set (used internally).
bool get_lvalue() const
Returns a bool value if the current expression is assigned to.
This class represents a source file for a project (which may contian many source files and or directo...
std::string getFileName() const
associated filename
Sg_File_Info * get_file_info() const override
Access function calling get_startOfConstruct(), provided to support older interface.
This class represents the notion of an value (expression value).
This class represents the variable declaration or variable initialization withn a for loop.
const SgStatementPtrList & get_init_stmt() const
Returns const reference to a SgStatementPtrList (typedef to a STL list).
This class represents the concept of a for loop.
SgExpression * get_test_expr() const
Access function for p_test_expr_root.
SgForInitStatement * get_for_init_stmt() const
Access function for p_for_init_stmt.
void set_loop_body(SgStatement *loop_body)
Access function for p_loop_body.
SgStatement * get_loop_body() const
Access function for p_loop_body.
void set_for_init_stmt(SgForInitStatement *for_init_stmt)
Access function for p_for_init_stmt.
This class represents the concept of a C++ function call (which is an expression).
SgFunctionSymbol * getAssociatedFunctionSymbol() const
Returns the associated function symbol, if it can be resolved statically.
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a function declaration statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool isTemplateFunction() const
Determines if function is a template or non-template function.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
virtual std::string class_name() const override
returns a string representing the class name
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.
const SgTypePtrList & get_arguments() const
Get a const list of input types (types of the parameters list) to this function type (from a cost fun...
This class represents the function being called and must be assembled in the SgFunctionCall with the ...
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the function type table (stores all function types so that they can be shared i...
SgSymbolTable * get_function_type_table() const
Returns pointer to SgSymbolTable used for function type symbols only.
This class represents a type for all functions.
virtual std::string class_name() const override
returns a string representing the class name
const SgTypePtrList & get_arguments() const
This is a const convience access function to the STL container of types in the child IR node (SgFunct...
virtual SgName get_mangled(void) const override
Mangled name support for unparser support.
This class represents the concept of a namespace definition.
virtual std::string class_name() const override
returns a string representing the class name
const SgDeclarationStatementPtrList & get_declarations() const
Returns a const list to the global scope declarations.
This class represents the concept of a C or C++ goto statement.
SgLabelStatement * get_label() const
Returns pointer to SgLabelStatement where control flow will be transfered during execution.
void set_label(SgLabelStatement *label)
Access function for p_label.
InheritedAttributeType traverse(SgGraphNode *basenode, SgIncidenceDirectedGraph *g, InheritedAttributeType inheritedValue, InheritedAttributeType nullInherit, SgGraphNode *endnode, bool insep=false, bool pcHk=false)
This is the function that is used by the user directly to start the algorithm.
This class represents the concept of an "if" construct.
void set_false_body(SgStatement *false_body)
Access function for p_false_body.
virtual std::string class_name() const override
returns a string representing the class name
void set_true_body(SgStatement *true_body)
Access function for p_true_body.
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.
void set_conditional(SgStatement *conditional)
Access function for p_conditional.
This class represents the notion of a declared variable.
SgName get_qualified_name() const
Returns the name with appropriate qualified names representing nested scopes.
SgSymbol * get_symbol_from_symbol_table() const
Get the associated SgSymbol from the symbol table located in the scope, without considering possible ...
virtual std::string class_name() const override
returns a string representing the class name
SgDeclarationStatement * get_declaration() const
Equal operator : it checks if all the data members are the same or point to the same objects.
This class represents the notion of an initializer for a variable declaration or expression in a func...
This class represents the concept of a C or C++ label statement.
SgName get_label() const
Returns SgName by value.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
label_type_enum
Type of label used (fortran only)
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of an expression or statement which has a position within the source...
virtual std::string class_name() const override
returns a string representing the class name
virtual const char * sage_class_name() const override
Sg_File_Info * get_endOfConstruct() const override
New function interface for Sg_File_Info data stores ending location of contruct (typically the closin...
void setTransformation()
Allow IR nodes (mostly SgLocatedNode) to be marked as a transformation.
virtual void addNewAttribute(std::string s, AstAttribute *a) override
Add a new attribute represented by the named string.
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 addToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo::RelativePositionType locationInList=PreprocessingInfo::after)
This function adds comment or CPP directives to the current IR node.
virtual AstAttribute * getAttribute(std::string s) const override
Returns attribute of name 's'.
void set_startOfConstruct(Sg_File_Info *startOfConstruct)
This function sets the current source location position of the start of the current construct.
bool isCompilerGenerated() const
Simple test for if this is a compiler generated node.
void insertToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo *anchorInfoPtr, bool insertAfter=true)
Insert prepInfo After (or before if last parameter is false) an anchor info ptr in the list of prepro...
virtual VariantT variantT() const override
returns new style SageIII enum values
void setOutputInCodeGeneration()
Allow IR nodes (mostly SgLocatedNode) to be marked as to when the information was unavilable in the f...
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
bool isTransformation() const
Simple test for if this is a part of a transformation.
AttachedPreprocessingInfoType *& getAttachedPreprocessingInfo()
This function gets the adds comment or CPP directives to the current IR node.
This class represents the notion of an value (expression value).
This class represents the concept of a member function declaration statement.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the member function being called and must be assembled in the SgFunctionCall wi...
SgMemberFunctionDeclaration * getAssociatedMemberFunctionDeclaration() const
This is helpful in chasing down the associated declaration to this member function reference.
SgName get_name() const override
Access function for getting name from declarations or types internally.
SgTypeModifier & get_typeModifier()
Access function for modifier.
This class represents strings within the IR nodes.
virtual SgName get_name() const
Gets name of the type (useful for debugging, unparsing, etc.)
SgName get_qualified_name() const
Used for the SgNamedType object (base class for the SgClassType, SgTypedefType and the SgEnumType obj...
This class represents the concept of a C++ namespace alias declaration statement.
SgName get_name() const
Access function for p_name.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the concept of a C++ namespace declaration.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_name() const
Access function for p_name.
SgNamespaceDefinitionStatement * get_definition() const
Returns pointer to SgNamespaceDefinitionStatement.
This class represents the concept of a namespace definition.
This class represents the concept of a namespace name within the compiler.
This class represents the base class for all IR nodes within Sage III.
static SgTypeTable * get_globalTypeTable()
Access function for symbol table specific to non-function types.
virtual std::vector< std::string > get_traversalSuccessorNamesContainer() const
container of names of variables or container indices used used in the traversal to access AST success...
SgNode * get_parent() const
Access function for parent node.
void set_isModified(bool isModified)
All nodes in the AST contain a isModified flag used to track changes to the AST.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() const
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
virtual VariantT variantT() const
returns new style SageIII enum values
void set_parent(SgNode *parent)
All nodes in the AST contain a reference to a parent node.
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
virtual std::string class_name() const
returns a string representing the class name
static std::map< SgNode *, std::string > & get_globalMangledNameMap()
Access function for performance optimizing global mangled name map.
virtual void checkDataMemberPointersIfInMemoryPool()
FOR INTERNAL USE This is used in internal tests to verify that all IR nodes are allocated from the he...
virtual AstAttribute * getAttribute(std::string s) const
Returns attribute of name 's'.
static SgFunctionTypeTable * get_globalFunctionTypeTable()
Access function for symbol table specific to function types.
virtual Sg_File_Info * get_file_info(void) const
File information containing filename, line number, column number, and if the SgNode is a part of a ne...
virtual bool attributeExists(std::string s) const
Tests if attribute of name 's' is present.
virtual std::vector< std::pair< SgNode *, std::string > > returnDataMemberPointers() const
FOR INTERNAL USE Returns STL vector of pairs of SgNode* and strings for use in AST tools
virtual void addNewAttribute(std::string s, AstAttribute *a)
Add a new attribute represented by the named string.
static std::map< std::string, uint64_t > & get_shortMangledNameCache()
Access function for lower level optimizing of global mangled name map.
bool get_isModified() const
Acess function for isModified flag.
SgName get_name() const override
Support for some classes which have pure virtual function in base classes.
This class represents the concept of a C Assembler statement (untested).
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents a source project, with a list of SgFile objects and global information about th...
std::vector< std::string > getAbsolutePathFileNames() const
This function generates a list of files resolved to absolute paths (symbolic links should not be reso...
static void visitRepresentativeNode(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for type-based traversal.
static int get_verbose(void)
DQ: Modified to accept a value on the command line (no longer a boolean variable) value of 0 means qu...
This class represents a OLD concept of the structure require for qualified names when they were in th...
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,...
bool supportsDefiningFunctionDeclaration()
Reports if scope can support defining function declarations. Not all scopes permit function declarati...
const SgStatementPtrList generateStatementList() const
Generate s list of statements from either the existing list of statements or the list of declarations...
bool isNamedScope()
Some scopes have associated names for purposed of name qualification. This returns true if the scope ...
SgSymbolTable * get_symbol_table() const
Returns a pointer to the locally strored SgSymbolTable.
virtual const char * sage_class_name() const override
SgDeclarationStatementPtrList & getDeclarationList()
Gets reference to internal STL list of pointers to SgDeclarationStatement objects (only defined for s...
SgStatementPtrList & getStatementList()
Gets reference to internal STL list of pointers to SgStatement objects (only defined for scopes conta...
void append_statement(SgStatement *stmt)
Higher level function to handle statements and declarations is scopes.
void set_symbol_table(SgSymbolTable *symbol_table)
Sets the pointer to the locally strored SgSymbolTable.
virtual std::string class_name() const override
returns a string representing the class name
bool statementExistsInScope(SgStatement *statement)
Test for existence of statement is scope.
bool containsOnlyDeclarations() const
This function is used to indicate if either the getDeclarationList() or getStatementList() can be cal...
void insert_symbol(const SgName &n, SgSymbol *s)
Puts a SgSymbol object into the local symbol table.
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_qualified_name() const
Returns SgName (a string) representing the name of the current scope.
This class represents the "sizeof()" operator (applied to any type).
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a statement.
virtual std::string class_name() const override
returns a string representing the class name
void insert_statement(SgStatement *target, SgStatement *newstmt, bool inFront=true)
This function inserts a single statement at the position indicated by target.
virtual void set_scope(SgScopeStatement *newScope)
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual bool hasExplicitScope() const
Support for where the scope is explicitly required.
virtual SgSymbol * get_symbol_from_symbol_table() const
Get the associated symbol from the symbol table in the stored scope.
virtual SgScopeStatement * get_scope(void) const
Returns scope of current statement.
void remove_statement(SgStatement *)
This function removes the target statement from the AST.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() const override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
void replace_statement(SgStatement *target, SgStatement *newstmt)
This function replaces the target statement with a single statement.
virtual VariantT variantT() const override
returns new style SageIII enum values
bool isStatic() const
Storage modifier is static (always false for the SgStorageModifier in the SgInitializedName).
This class represents the base class of a numbr of IR nodes that don't otherwise fit into the existin...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a switch.
void set_item_selector(SgStatement *item_selector)
Access function for p_item_selector.
SgStatement * get_body() const
Access function for p_body.
SgStatement * get_item_selector() const
Access function for p_item_selector_root.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the symbol tables used in both SgScopeStatement and the SgFunctionTypeSymbolTab...
std::set< SgNode * > get_symbols() const
Complexity O(n)
void print(std::string label, VariantT nodeType=V_SgSymbol)
Outputs symbol table information (useful for debugging)
int size() const
Computes the number of symbols in the symbol table (forced to count them, I think,...
void remove(const SgSymbol *symbol)
Complexity O(n)
This class represents the concept of a name within the compiler.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_name() const =0
Access function for getting name from declarations or types internally.
virtual SgType * get_type() const =0
This function returns the type associated with the named entity.
This class represents template argument within the use of a template to build an instantiation.
SgExpression * get_expression() const
This function returns argumentExpression.
SgType * get_type() const
This function returns argumentType.
SgTemplateArgument::template_argument_enum get_argumentType() const
This function returns argumentType.
This class represents the concept of a template declaration.
SgName get_string() const
Returns stringified template declaration.
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const
Returns name of template declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of an instantiated class template.
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_templateName() const
Returns name of class template, the name excludes template arguments.
SgTemplateClassDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
This class represents the concept of a class definition in C++.
This class represents the concept of a C++ template instantiation directive.
SgDeclarationStatement * get_declaration() const
Returns pointer to SgDeclarationStatement.
This class represents the concept of an instantiation of function template.
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgTemplateFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
This class represents the concept of an instantiation of member function template or a member functio...
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
SgTemplateMemberFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the "this" operator (can be applied to any member data).
Supporting class for "Deep" copies of the AST.
Definition sageCopy.h:86
static SgTypeBool * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeInt * createType(int sz=0, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgTypeInt (types whose constructors take param...
static SgTypeUnknown * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeVoid * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
This class represents the base class for all types.
std::vector< SgType * > getInternalTypes() const
Generate a container of types hidden in the input type.
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...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of a typedef declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_typedefBaseTypeContainsDefiningDeclaration() is true,...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
SgType * get_base_type() const
This is used in the SgTypedefType object (is not associated with a base_type data field)
void set_operand_i(SgExpression *operand_i)
This function allows the p_operand_i pointer to be set (used internally).
SgExpression * get_operand() const
returns SgExpression pointer to the operand associated with this unary operator.
This class represents the concept of a C++ using declaration.
SgDeclarationStatement * get_declaration() const
Access function for p_declaration.
SgInitializedName * get_initializedName() const
Access function for p_initializedName.
This class represents the concept of a C++ using directive.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the notion of an value (expression value).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
This class represents the variable refernece in expressions.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the concept of a C or C++ variable declaration.
const SgInitializedNamePtrList & get_variables() const
Access function for p_variables.
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_variableDeclarationContainsBaseTypeDefiningDeclaration() is t...
bool get_variableDeclarationContainsBaseTypeDefiningDeclaration() const
Access function for p_variableDeclarationContainsBaseTypeDefiningDeclaration.
This class represents the definition (initialization) of a variable.
SgInitializedName * get_vardefn() const
Access function for SgInitializedName stored in p_vardefn.
This class represents the concept of a variable name within the compiler (a shared container for the ...
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
void set_condition(SgStatement *condition)
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the location of the code associated with the IR node in the original source cod...
void setTransformation()
Marks an IR node to be a transformation if it is not one already.
const char * get_filename() const
Returns filename of source code associated with IR node.
bool isOutputInCodeGeneration() const
Returns true only if required to be unparsed in generated code.
int get_line() const
Returns the line number of the associated code for this IR node.
bool isCompilerGenerated() const
Returns true only if compiler generated (either by the front-end or by ROSE).
int get_col() const
Returns the column number of the associated code for this IR node.
static Sg_File_Info * generateDefaultFileInfoForTransformationNode()
Static function to return new Sg_File_Info object set to default values appropriate for transformatio...
bool isTransformation() const
Access function for classification bit field.
bool isShared() const
Returns true only if shared internally (either by the front-end or by ROSE).
static Sg_File_Info * generateDefaultFileInfo()
Static function to return new Sg_File_Info object set to default values.
void setOutputInCodeGeneration()
Marks IR node as compiler generated but required in the generated source (e.g. requied templates).
Hash table support for symbol tables within ROSE.
ROSE_DLL_API abstract_handle * buildAbstractHandle(SgNode *snode)
A default builder function handles all details: file use name, others use numbering
ROSE_DLL_API std::vector< std::string > generateSourceFilenames(std::vector< std::string > argList, bool binaryMode)
Build the list of isolated file names from the command line.
ROSE_UTIL_API void removeAllFileNamesExcept(std::vector< std::string > &argv, std::vector< std::string > filenameList, std::string exceptFilename)
Remove file names specified in filenameList from argv, except for 'exceptFilename'.
void edgePointerReplacement(replacement_map_t const &)
For all nodes in the memory pool, it looks for the edges in the replacement map. If a match is found ...
ROSE_DLL_API std::string toBase62String(uint64_t)
Converts a 64 bit int to base 62.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C:50
void serialize(std::ostream &output, Graph &graph)
Serialize a graph into a stream of bytes.
ROSE_UTIL_API std::string stripFileSuffixFromFileName(const std::string &fileNameWithSuffix)
Get the file name without the ".suffix".
ROSE_UTIL_API std::string numberToString(long long)
Convert an integer to a string.
ROSE_UTIL_API std::string copyEdit(const std::string &inputString, const std::string &oldToken, const std::string &newToken)
Replace all occurrences of a string with another string.
ROSE_UTIL_API std::string stripPathFromFileName(const std::string &fileNameWithPath)
Returns the last component of a path in a filesystem.
The ROSE library.
SgStatement * getPreviousStatement(SgStatement *targetStatement, bool climbOutScope=true)
Functions to move to SgStatement object in SAGE III later.
Functions that build an AST.
Definition sageBuilder.h:32
ROSE_DLL_API SgAddOp * buildAddOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgFunctionDeclaration * buildNondefiningFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, bool buildTemplateInstantiation=false, SgTemplateArgumentPtrList *templateArgumentsList=NULL, SgStorageModifier::storage_modifier_enum sm=SgStorageModifier::e_default)
Build a prototype for a function, handle function type, symbol etc transparently.
SourcePositionClassification
intended to be a private member, don't access it directly. could be changed any time
@ e_sourcePosition_last
Specify as source position to be filled in as part of AST construction in the front-end.
@ e_sourcePositionNullPointers
Classify as compiler generated code (e.g. template instantiation).
@ e_sourcePositionCompilerGenerated
Classify as a transformation.
@ e_sourcePositionFrontendConstruction
Set pointers to Sg_File_Info objects to NULL.
@ e_sourcePositionDefault
Error value for enum.
@ e_sourcePositionTransformation
Default source position.
ROSE_DLL_API SgPragma * buildPragma(const std::string &name)
Build SgPragma.
ROSE_DLL_API SourcePositionClassification getSourcePositionClassificationMode()
Get the current source position classification (defines how IR nodes built by the SageBuilder interfa...
ROSE_DLL_API SgEqualityOp * buildEqualityOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgTemplateMemberFunctionDeclaration * buildNondefiningTemplateMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList *templateParameterList)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgLabelStatement * buildLabelStatement(const SgName &name, SgStatement *stmt=NULL, SgScopeStatement *scope=NULL)
Build a label statement, name is the label's name. Handling label symbol and scope internally.
ROSE_DLL_API SgAddressOfOp * buildAddressOfOp(SgExpression *op=NULL)
ROSE_DLL_API SgTemplateFunctionDeclaration * buildNondefiningTemplateFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope=NULL, SgExprListExp *decoratorList=NULL, SgTemplateParameterPtrList *templateParameterList=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgMultiplyOp * buildMultiplyOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgGotoStatement * buildGotoStatement(SgLabelStatement *label=NULL)
Build a goto statement.
ROSE_DLL_API std::string display(SourcePositionClassification &scp)
display function for debugging
ROSE_DLL_API SgLabelRefExp * buildLabelRefExp(SgLabelSymbol *s)
Build a Fortran numeric label ref exp.
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 SgMemberFunctionType * buildMemberFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList, SgScopeStatement *struct_name, unsigned int mfunc_specifier)
Built in simple types.
ROSE_DLL_API SgWhileStmt * buildWhileStmt(SgStatement *condition, SgStatement *body, SgStatement *else_body=NULL)
Build while statement.
ROSE_DLL_API SgForStatement * buildForStatement(SgStatement *initialize_stmt, SgStatement *test, SgExpression *increment, SgStatement *loop_body, SgStatement *else_body=NULL)
Build a for statement, assume none of the arguments is NULL.
ROSE_DLL_API SgEmptyDeclaration * buildEmptyDeclaration()
Build an empty declaration (useful for adding precission to comments and CPP handling under token-bas...
ROSE_DLL_API SgConditionalExp * buildConditionalExp(SgExpression *test=NULL, SgExpression *a=NULL, SgExpression *b=NULL)
Build a conditional expression ?:
ROSE_DLL_API SgTypeInt * buildIntType()
Built in simple types.
SourcePositionClassification SourcePositionClassificationMode
C++ SageBuilder namespace specific state for storage of the source code position state (used to contr...
ROSE_DLL_API SgMinusOp * buildMinusOp(SgExpression *op=NULL)
ROSE_DLL_API SgExprListExp * buildExprListExp(SgExpression *expr1=NULL, SgExpression *expr2=NULL, SgExpression *expr3=NULL, SgExpression *expr4=NULL, SgExpression *expr5=NULL, SgExpression *expr6=NULL, SgExpression *expr7=NULL, SgExpression *expr8=NULL, SgExpression *expr9=NULL, SgExpression *expr10=NULL)
Build a SgExprListExp, used for function call parameter list etc.
ROSE_DLL_API SgPlusAssignOp * buildPlusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgVarRefExp * buildVarRefExp(const SgName &name, SgScopeStatement *scope=NULL)
Build SgVarRefExp based on a variable's Sage name. It will lookup the name in the symbol table intern...
bool symbol_table_case_insensitive_semantics
Support for construction of case sensitive/insensitive symbol table handling in scopes.
Definition sageBuilder.C:93
ROSE_DLL_API SgDotExp * buildDotExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgAssignInitializer * buildAssignInitializer(SgExpression *operand_i=NULL, SgType *expression_type=NULL)
Build the rhs of a variable declaration which includes an assignment.
ROSE_DLL_API SgArrayType * getUniqueJavaArrayType(SgType *, int)
Build a SgFile node and attach it to SgProject.
ROSE_DLL_API SgVariableDeclaration * buildVariableDeclaration(const SgName &name, SgType *type, SgInitializer *varInit=NULL, SgScopeStatement *scope=NULL)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgScopeStatement * topScopeStack()
intended to be a private member, don't access it directly. could be changed any time
ROSE_DLL_API SgNullExpression * buildNullExpression()
Build a null expression, set file info as the default one.
ROSE_DLL_API SgGreaterOrEqualOp * buildGreaterOrEqualOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgReferenceType * buildReferenceType(SgType *base_type=nullptr)
Build a reference type.
ROSE_DLL_API SgExprStatement * buildExprStatement(SgExpression *exp=NULL)
Build a SgExprStatement, set File_Info automatically.
ROSE_DLL_API SgIfStmt * buildIfStmt(SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Build if statement.
ROSE_DLL_API SgFunctionParameterList * buildFunctionParameterList(SgInitializedName *in1=NULL, SgInitializedName *in2=NULL, SgInitializedName *in3=NULL, SgInitializedName *in4=NULL, SgInitializedName *in5=NULL, SgInitializedName *in6=NULL, SgInitializedName *in7=NULL, SgInitializedName *in8=NULL, SgInitializedName *in9=NULL, SgInitializedName *in10=NULL)
Build an empty SgFunctionParameterList, possibly with some initialized names filled in.
ROSE_DLL_API SgPointerDerefExp * buildPointerDerefExp(SgExpression *op=NULL)
ROSE_DLL_API SgTypeBool * buildBoolType()
Built in simple types.
ROSE_DLL_API SgAssignOp * buildAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgPointerType * buildPointerType(SgType *base_type=nullptr)
Build a pointer type.
ROSE_DLL_API SgBoolValExp * buildBoolValExp(int value=0)
Build a bool value expression, the name convention of SgBoolValExp is little different from others fo...
ROSE_DLL_API SgName appendTemplateArgumentsToName(const SgName &name, const SgTemplateArgumentPtrList &templateArgumentsList)
DQ (7/27/2012): changed semantics from removing the template arguments in names to adding the templat...
ROSE_DLL_API SgFunctionParameterTypeList * buildFunctionParameterTypeList(SgFunctionParameterList *paralist)
Build SgFunctionParameterTypeList from SgFunctionParameterList.
ROSE_DLL_API SgLessThanOp * buildLessThanOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgCastExp * buildCastExp(SgExpression *operand_i=NULL, SgType *expression_type=NULL, SgCastExp::cast_type_enum cast_type=SgCastExp::e_C_style_cast)
Build a type casting expression.
ROSE_DLL_API SgMinusAssignOp * buildMinusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgDivideOp * buildDivideOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgBasicBlock * buildBasicBlock(SgStatement *stmt1=NULL, SgStatement *stmt2=NULL, SgStatement *stmt3=NULL, SgStatement *stmt4=NULL, SgStatement *stmt5=NULL, SgStatement *stmt6=NULL, SgStatement *stmt7=NULL, SgStatement *stmt8=NULL, SgStatement *stmt9=NULL, SgStatement *stmt10=NULL)
Build a SgBasicBlock, setting file info internally.
ROSE_DLL_API SgModOp * buildModOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgExprStatement * buildAssignStatement(SgExpression *lhs, SgExpression *rhs)
Build an assignment statement from lefthand operand and right hand operand.
ROSE_DLL_API SgMemberFunctionDeclaration * buildNondefiningMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList *templateArgumentsList)
Build a prototype member function declaration.
ROSE_DLL_API SgMemberFunctionDeclaration * buildDefaultConstructor(SgClassType *classType)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgCommaOpExp * buildCommaOpExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgIntVal * buildIntVal(int value=0)
Build an integer value expression.
SgDeclarationStatement * associatedDeclaration(const SgSymbol &n)
returns the associated declaration for symbol n or nullptr if there is none.
Functions that are useful when operating on the AST.
Definition sageBuilder.h:25
ROSE_DLL_API void checkSgNodePointers()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool isLastStatement(SgStatement *stmt)
Check if a statement is the last statement within its closed scope.
ROSE_DLL_API bool isUnionDeclaration(SgNode *node)
Check if a SgNode is a declaration for a union.
ROSE_DLL_API void translateScopeToUseCppDeclarations(SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
void initializeIfStmt(SgIfStmt *ifstmt, SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void deepDelete(SgNode *root)
Deep delete a sub AST tree. It uses postorder traversal to delete each child node....
void annotateExpressionsWithUniqueNames(SgProject *project)
Generate unique names for expressions and attach the names as persistent attributes ("UniqueNameAttri...
ROSE_DLL_API bool hasMultipleInitStatmentsOrExpressions(SgForStatement *for_loop)
Check if a for loop uses C99 style initialization statement with multiple expressions like for (int i...
ROSE_DLL_API void fixNamespaceDeclaration(SgNamespaceDeclarationStatement *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void serialize(SgNode *node, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
we have two serialize() functions, one for a single node, the other for a list of pointers
ROSE_DLL_API void deleteExpressionTreeWithOriginalExpressionSubtrees(SgNode *root)
Special purpose function for deleting AST expression tress containing valid original expression trees...
void setSourcePositionAsTransformation(SgNode *node)
DQ (5/1/2012): New function with improved name.
ROSE_DLL_API void insertStatementList(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts, bool insertBefore=true)
Insert a list of statements before or after the target statement within the.
void whereAmI(SgNode *node)
Diagnostic function for tracing back through the parent list to understand at runtime where in the AS...
ROSE_DLL_API SgStatement * getLastStatement(SgScopeStatement *scope)
get the last statement within a scope, return NULL if it does not exit
ROSE_DLL_API void addStepToLoopBody(SgScopeStatement *loopStmt, SgStatement *step)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool is_UPC_dynamic_threads()
ROSE_DLL_API SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCallExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_mixed_Fortran_and_C_language()
ROSE_DLL_API void addTextForUnparser(SgNode *astNode, std::string s, AstUnparseAttribute::RelativePositionType inputlocation)
Add a string to be unparsed to support code generation for back-end specific tools or compilers.
ROSE_DLL_API std::string getTempDirectory(SgProject *project)
Create a temporary directory if it does not yet exist and return its name.
ROSE_DLL_API void displayScope(SgScopeStatement *scope)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_Jovial_language()
ROSE_DLL_API SgMemberFunctionDeclaration * findJavaMain(SgClassDefinition *)
Find a main method in a Java class.
ROSE_DLL_API bool is_Cxx_language()
void resetScopeNumbers(SgFunctionDefinition *functionDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API SgFunctionDeclaration * replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool hasSameGlobalScope(SgStatement *statement_1, SgStatement *statement_2)
This is supporting the recognition of functions in header files from two different ASTs.
SgCommaOpExp * insertBeforeUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp)
Insert an expression (new_exp )before another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API void fixFunctionDeclaration(SgFunctionDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
ROSE_DLL_API std::string preprocessImport(SgProject *, std::string)
Using the import_string parameter, create a file with the relevant import statement; translate the fi...
ROSE_DLL_API bool collectReadWriteRefs(SgStatement *stmt, std::vector< SgNode * > &readRefs, std::vector< SgNode * > &writeRefs, bool useCachedDefUse=false)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void prependStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
prepend a list of statements to the beginning of the current scope, handling side effects as appropri...
ROSE_DLL_API SgInitializer * getInitializerOfExpression(SgExpression *n)
Get the initializer containing an expression if it is within an initializer.
ROSE_DLL_API std::vector< SgInitializedName * > getInParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial input parameters from the function parameter list (may work for Fortran in the...
ROSE_DLL_API bool language_may_contain_nondeclarations_in_scope()
ROSE_DLL_API std::set< SgStatement * > collectTransformedStatements(SgNode *node)
This collects the statements that are marked as transformed (useful in debugging).
ROSE_DLL_API void cleanupNontransformedBasicBlockNode()
Remove unused basic block IR nodes added as part of normalization.
ROSE_DLL_API bool skipTranslateToUseCppDeclaration(PreprocessingInfo *currentPreprocessingInfo)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API AbstractHandle::abstract_handle * buildAbstractHandle(SgNode *)
Build an abstract handle from an AST node, reuse previously built handle when possible.
ROSE_DLL_API void insertStatementListBefore(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts)
Insert a list of statements before a target statement.
ROSE_DLL_API void fixStructDeclaration(SgClassDeclaration *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void recursivePrintCurrentAndParent(SgNode *n)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void appendExpressionList(SgExprListExp *, const std::vector< SgExpression * > &)
Append an expression list to a SgExprListExp, set the parent pointers also.
ROSE_DLL_API void collectReadOnlySymbols(SgStatement *stmt, std::set< SgVariableSymbol * > &readOnlySymbols, bool coarseGrain=true)
Collect read only variable symbols within a statement. The statement can be either of a function,...
bool isOverloaded(SgFunctionDeclaration *functionDeclaration)
Return true if function is overloaded.
ROSE_DLL_API int set_name(SgInitializedName *initializedNameNode, SgName new_name)
set_name of symbol in symbol table.
ROSE_DLL_API SgClassDefinition * findOrInsertJavaPackage(SgProject *, std::string, bool create_directory=false)
Process a qualified package name, if needed, and return its package definition.
ROSE_DLL_API SgClassDeclaration * findOrImportJavaClass(SgProject *, SgClassDefinition *package_definition, std::string)
If the class_name already exists in the scope, return it.
ROSE_DLL_API SgVariableSymbol * getFirstVarSym(SgVariableDeclaration *decl)
Get the variable symbol for the first initialized name of a declaration stmt.
ROSE_DLL_API bool templateArgumentEquivalence(SgTemplateArgument *arg1, SgTemplateArgument *arg2)
Verify that 2 SgTemplateArgument are equivalent (same type, same expression, or same template declara...
ROSE_DLL_API SgFunctionDeclaration * findFirstDefiningFunctionDecl(SgScopeStatement *scope)
Find the first defining function declaration statement in a scope.
ROSE_DLL_API bool is_Jvm_language()
void addMessageStatement(SgStatement *stmt, std::string message)
Function to add "C" style comment to statement.
ROSE_DLL_API bool isLoopIndexVariable(SgInitializedName *ivar, SgNode *subtree_root)
Check if a SgInitializedName is used as a loop index within a AST subtree This function will use a bo...
SgInitializedName & getFirstVariable(SgVariableDeclaration &vardecl)
convenience function that returns the first initialized name in a list of variable declarations.
void initializeSwitchStatement(SgSwitchStatement *switchStatement, SgStatement *item_selector, SgStatement *body)
Support function used for variable declarations in conditionals.
SgExprListExp * loopCollapsing(SgForStatement *target_loop, size_t collapsing_factor)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void fixStatement(SgStatement *stmt, SgScopeStatement *scope)
A wrapper containing fixes (fixVariableDeclaration(),fixStructDeclaration(), fixLabelStatement(),...
ROSE_DLL_API SgStatement * copyStatement(SgStatement *s)
Deep copy a statement.
ROSE_DLL_API int eraseNullPreprocessingInfo(SgLocatedNode *lnode)
Dumps a located node's preprocessing information.
ROSE_DLL_API bool isCanonicalDoLoop(SgFortranDo *loop, SgInitializedName **ivar, SgExpression **lb, SgExpression **ub, SgExpression **step, SgStatement **body, bool *hasIncrementalIterationSpace, bool *isInclusiveUpperBound)
Check if a Fortran Do loop has a complete canonical form: Do I=1, 10, 1.
SgCommaOpExp * insertAfterUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp, SgStatement **temp_decl=NULL, SgVarRefExp **temp_ref=NULL)
Insert an expression (new_exp ) after another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API SgTemplateVariableSymbol * lookupTemplateVariableSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *tplparams, SgTemplateArgumentPtrList *tplargs, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void moveUpPreprocessingInfo(SgStatement *stmt_dst, SgStatement *stmt_src, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Identical to movePreprocessingInfo(), except for the stale name and confusing order of parameters....
ROSE_DLL_API SgStatement * lastStatementOfScopeWithTokenInfo(SgScopeStatement *scope, std::map< SgNode *, TokenStreamSequenceToNodeMapping * > &tokenStreamSequenceMap)
Used to support token unparsing (when the output the trailing token sequence).
ROSE_DLL_API void cutPreprocessingInfo(SgLocatedNode *src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &save_buf)
Cut preprocessing information from a source node and save it into a buffer. Used in combination of pa...
ROSE_DLL_API bool normalizeForLoopTest(SgForStatement *loop)
Normalize a for loop's test expression i<x is normalized to i<= (x-1) and i>x is normalized to i>= (x...
bool declarationPreceedsDefinition(SgDeclarationStatement *nonDefiningDeclaration, SgDeclarationStatement *definingDeclaration)
Check if a defining declaration comes before of after the non-defining declaration.
ROSE_DLL_API bool isSameFunction(SgFunctionDeclaration *func1, SgFunctionDeclaration *func2)
Check if two function declarations refer to the same one. Two function declarations are the same when...
std::vector< SgVariableSymbol * > getSymbolsUsedInExpression(SgExpression *expr)
Find referenced symbols within an expression.
ROSE_DLL_API bool isStructDeclaration(SgNode *node)
Check if a SgNode is a declaration for a structure.
ROSE_DLL_API void moveVariableDeclaration(SgVariableDeclaration *decl, SgScopeStatement *target_scope)
Move a variable declaration to a new scope, handle symbol, special scopes like For loop,...
ROSE_DLL_API std::string preprocessPackage(SgProject *, std::string)
Using the package_name, create a file with a package statement, translate it in order to load the pac...
ROSE_DLL_API void setOneSourcePositionForTransformation(SgNode *root)
Set current node's source position as transformation generated.
NodeType * deepCopy(const NodeType *subtree)
A template function for deep copying a subtree. It is also used to create deepcopy functions with spe...
void clearMangledNameCache(SgGlobal *globalScope)
Support for faster mangled name generation (caching avoids recomputation).
std::vector< SgStatement * > getSwitchCases(SgSwitchStatement *sw)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool isScalarType(SgType *t)
Is this a scalar type?
ROSE_DLL_API void changeBreakStatementsToGotos(SgStatement *loopOrSwitch)
If the given statement contains any break statements in its body, add a new label below the statement...
ROSE_DLL_API SgFunctionDefinition * getEnclosingFunctionDefinition(SgNode *astNode, const bool includingSelf=false)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_CAF_language()
ROSE_DLL_API void printOutComments(SgLocatedNode *locatedNode)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void ReductionRecognition(SgForStatement *loop, std::set< std::pair< SgInitializedName *, OmpSupport::omp_construct_enum > > &results)
Recognize and collect reduction variables and operations within a C/C++ loop, following OpenMP 3....
ROSE_DLL_API bool loopUnrolling(SgForStatement *loop, size_t unrolling_factor)
Unroll a target loop with a specified unrolling factor. It handles steps larger than 1 and adds a fri...
ROSE_DLL_API void setLoopCondition(SgScopeStatement *loop, SgStatement *cond)
Set the condition statement of a loop, including While-loop, For-loop, and Do-While-loop.
bool ROSE_DLL_API isStatic(SgDeclarationStatement *stmt)
Check if a declaration has a "static' modifier.
PreprocessingInfo * attachComment(SgSourceFile *source_file, const std::string &content, PreprocessingInfo::DirectiveType directive_type=PreprocessingInfo::C_StyleComment, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Build and attach comment onto the global scope of a source file.
ROSE_DLL_API SgClassDefinition * getEnclosingClassDefinition(SgNode *astnode, const bool includingSelf=false)
Get the closest class definition enclosing the specified AST node,.
ROSE_DLL_API bool mergeDeclarationAndAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt, bool removeAssignStmt=true)
Merge a variable assignment statement into a matching variable declaration statement....
ROSE_DLL_API void checkAccessPermissions(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgFunctionDeclaration * > generateFunctionDefinitionsList(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void replaceMacroCallsWithExpandedStrings(SgPragmaDeclaration *target)
Check if a pragma declaration node has macro calls attached, if yes, replace macro calls within the p...
std::string generateUniqueNameForUseAsIdentifier(SgDeclarationStatement *declaration)
Generate a useful name to support construction of identifiers from declarations.
ROSE_DLL_API bool isRestrictType(SgType *t)
Is this a restrict type?
ROSE_DLL_API std::string generateProjectName(const SgProject *project, bool supressSuffix=false)
Added mechanism to generate project name from list of file names.
ROSE_DLL_API void resetInternalMapsForTargetStatement(SgStatement *sourceStatement)
Reset internal data structures used for token-based unparsing and macro summaries based on modificati...
ROSE_DLL_API bool is_Cuda_language()
ROSE_DLL_API bool isLambdaCapturedVariable(SgVarRefExp *varRef)
check if a variable reference is this->a[i] inside of a lambda function
ROSE_DLL_API int instrumentEndOfFunction(SgFunctionDeclaration *func, SgStatement *s)
Instrument(Add a statement, often a function call) into a function right before the return points,...
ROSE_DLL_API SgInitializedName * getFirstInitializedName(SgVariableDeclaration *decl)
Get the first initialized name of a declaration statement.
void setSourcePositionPointersToNull(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfDoWhile(SgDoWhileStmt *ws)
Check if the body of a 'do .. while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void reportModifiedStatements(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API std::vector< SgInitializedName * > getOutParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial output parameters from the function parameter list (may work for Fortran in th...
ROSE_DLL_API void setSourcePositionForTransformation(SgNode *root)
Recursively set source position info(Sg_File_Info) as transformation generated.
ROSE_DLL_API SgGlobal * getGlobalScope(const SgNode *astNode)
Traverse back through a node's parents to find the enclosing global scope.
ROSE_DLL_API void insertStatementListAfter(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmt)
Insert a list of statements after a target statement.
ROSE_DLL_API bool isMain(const SgNode *node)
Check if a SgNode is a main() function declaration.
std::map< std::string, int > local_name_collision_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API void fixClassDeclaration(SgClassDeclaration *classDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
ROSE_DLL_API int collectVariableReferencesInArrayTypes(SgLocatedNode *root, Rose_STL_Container< SgNode * > &currentVarRefList)
Collect variable references in array types. The default NodeQuery::querySubTree() will miss variables...
SgBasicBlock * ensureBasicBlockAsBodyOfCaseOption(SgCaseOptionStmt *cs)
Check if the body of a 'case option' statement is a SgBasicBlock, create one if not.
void checkForInitializers(SgNode *node)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void removeUnusedLabels(SgNode *top, bool keepChild=false)
Remove labels which are not targets of any goto statements: its child statement is also removed by de...
ROSE_DLL_API SgProject * getProject()
Get the current SgProject IR Node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfUpcForAll(SgUpcForAllStatement *fs)
Check if the body of a 'upc_forall' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgClassDeclaration * getEnclosingClassDeclaration(SgNode *astNode)
Get the closest class declaration enclosing the specified AST node,.
ROSE_DLL_API void insertStatement(SgStatement *targetStmt, SgStatement *newStmt, bool insertBefore=true, bool autoMovePreprocessingInfo=true)
Insert a statement before or after the target statement within the target's scope....
ROSE_DLL_API void listHeaderFiles(SgIncludeFile *includeFile)
return path prefix for subtree of include files.
ROSE_DLL_API void markSubtreeToBeUnparsedTreeTraversal(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
void saveToPDF(SgNode *node, std::string filename)
Save AST into a pdf file. Start from a node to find its enclosing file node. The entire file's AST wi...
ROSE_DLL_API bool normalizeForLoopInitDeclaration(SgForStatement *loop)
Normalize loop init stmt by promoting the single variable declaration statement outside of the for lo...
void detectCycleInType(SgType *type, const std::string &from)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void deleteAST(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool statementCanBeTransformed(SgStatement *stmt)
If header file unparsing and token-based unparsing are used, then some statements in header files use...
ROSE_DLL_API SgStatement * getNextStatement(SgStatement *currentStmt)
Get next statement within the same scope of current statement.
ROSE_DLL_API std::set< SgLabelStatement * > findUnusedLabels(SgNode *top)
Find unused labels which are not targets of any goto statements.
ROSE_DLL_API void setExtern(SgDeclarationStatement *stmt)
Set a declaration as extern.
ROSE_DLL_API void deleteAllNodes()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool templateArgumentListEquivalence(const SgTemplateArgumentPtrList &list1, const SgTemplateArgumentPtrList &list2)
Verify that 2 SgTemplateArgumentPtrList are equivalent.
ROSE_DLL_API LivenessAnalysis * call_liveness_analysis(SgProject *project, bool debug=false)
Call liveness analysis on an entire project.
ROSE_DLL_API void reportModifiedLocatedNodes(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void fixTemplateDeclaration(SgTemplateDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
SgType * getBoolType(SgNode *n)
Get the right bool type according to C or C++ language input.
void clearSharedGlobalScopes(SgProject *project)
Collect all read and write references within stmt, which can be a function, a scope statement,...
void initializeWhileStatement(SgWhileStmt *whileStatement, SgStatement *condition, SgStatement *body, SgStatement *else_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void setSourcePosition(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API void setPragma(SgPragmaDeclaration *decl, SgPragma *pragma)
Set a pragma of a pragma declaration. handle memory release for preexisting pragma,...
ROSE_DLL_API void insertStatementListBeforeFirstNonDeclaration(const std::vector< SgStatement * > &newStmts, SgScopeStatement *scope)
Insert statements before the first non-declaration statement in a scope. If the scope has no non-decl...
ROSE_DLL_API bool isPostfixOperator(SgExpression *exp)
Is an overloaded operator a postfix operator. (e.g. ).
ROSE_DLL_API SgStatement * findSurroundingStatementFromSameFile(SgStatement *targetStmt, bool &surroundingStatementPreceedsTargetStatement)
Supporting function to comment relocation in insertStatement() and removeStatement().
SgNamespaceDefinitionStatement * enclosingNamespaceScope(SgDeclarationStatement *declaration)
Find the enclosing namespace of a declaration.
ROSE_DLL_API SgStatement * getLoopBody(SgScopeStatement *loop)
Routines to get and set the body of a loop.
ROSE_DLL_API bool is_mixed_C_and_Cxx_language()
bool isStructurallyEquivalentAST(SgNode *tree1, SgNode *tree2)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API PreprocessingInfo * insertHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader, bool asLastHeader)
Insert #include "filename" or #include <filename> (system header) onto the global scope of a source f...
void printAST2TextFile(SgNode *node, const char *filename, bool printType=true)
Pretty print AST horizontally, output to a specified text file. If printType is set to false,...
ROSE_DLL_API SgFunctionSymbol * lookupTemplateFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_language_case_insensitive()
ROSE_DLL_API void replaceStatement(SgStatement *oldStmt, SgStatement *newStmt, bool movePreprocessinInfo=false)
Replace a statement with another. Move preprocessing information from oldStmt to newStmt if requested...
ROSE_DLL_API void recordNormalizations(SgStatement *s)
Record where normalization have been done so that we can preform denormalizations as required for the...
ROSE_DLL_API bool loopInterchange(SgForStatement *loop, size_t depth, size_t lexicoOrder)
Interchange/permutate a n-level perfectly-nested loop rooted at 'loop' using a lexicographical order ...
void printAST(SgNode *node)
Pretty print AST horizontally, output to std output.
ROSE_DLL_API SgFunctionSymbol * lookupTemplateMemberFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_PHP_language()
ROSE_DLL_API bool isEqualToIntConst(SgExpression *e, int value)
Check if a SgIntVal node has a given value.
ROSE_DLL_API void insertStatementBeforeFirstNonDeclaration(SgStatement *newStmt, SgScopeStatement *scope, bool movePreprocessingInfo=true)
Insert a statement before the first non-declaration statement in a scope. If the scope has no non-dec...
ROSE_DLL_API SgFunctionSymbol * lookupFunctionSymbolInParentScopes(const SgName &functionName, SgScopeStatement *currentScope=NULL)
look up the first matched function symbol in parent scopes given only a function name,...
ROSE_DLL_API void appendStatementWithDependentDeclaration(SgDeclarationStatement *decl, SgGlobal *scope, SgStatement *original_statement, bool excludeHeaderFiles)
Append a copy ('decl') of a function ('original_statement') into a 'scope', include any referenced de...
ROSE_DLL_API bool insideHeader(SgLocatedNode *node)
Check if a node is from a header file.
ROSE_DLL_API void markSubtreeToBeUnparsed(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isDataMemberReference(SgVarRefExp *varRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool collectReadWriteVariables(SgStatement *stmt, std::set< SgInitializedName * > &readVars, std::set< SgInitializedName * > &writeVars, bool coarseGrain=true)
Collect unique variables which are read or written within a statement. Note that a variable can be bo...
ROSE_DLL_API void constantFolding(SgNode *r)
Constant folding an AST subtree rooted at 'r' (replacing its children with their constant values,...
std::vector< SgBreakStmt * > findBreakStmts(SgStatement *code, const std::string &fortranLabel="")
Find break statements inside a particular statement, stopping at nested loops or switches.
ROSE_DLL_API SgFile * getEnclosingFileNode(SgNode *astNode)
get the SgFile node from current node
ROSE_DLL_API void setStatic(SgDeclarationStatement *stmt)
Set a declaration as static.
ROSE_DLL_API bool doLoopNormalization(SgFortranDo *loop)
Normalize a Fortran Do loop. Make the default increment expression (1) explicit.
ROSE_DLL_API SgFile * preprocessCompilationUnit(SgProject *, std::string, std::string, bool unparse=true)
Using the file_content string, create a file with the content in question; build its AST and add it t...
ROSE_DLL_API void removeLabeledGotos(SgNode *top)
Remove labeled goto statements.
std::map< SgNode *, std::string > local_node_to_name_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
std::vector< SgGotoStatement * > findGotoStmts(SgStatement *scope, SgLabelStatement *l)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool mergeDeclarationWithAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt)
Merge a declaration statement into a matching followed variable assignment. Callers should make sure ...
ROSE_DLL_API bool isAssignmentStatement(SgNode *_s, SgExpression **lhs=NULL, SgExpression **rhs=NULL, bool *readlhs=NULL)
Check if a SgNode _s is an assignment statement (any of =,+=,-=,&=,/=, ^=, etc)
ROSE_DLL_API bool normalizeCaseAndDefaultBlocks(SgSwitchStatement *switchStmt)
Normalize the structure of case and default blocks within a switch statement.
ROSE_DLL_API void outputSharedNodes(SgNode *node)
Find a node by type using upward traversal.
bool ROSE_DLL_API isAncestor(SgNode *node1, SgNode *node2)
check if node1 is a strict ancestor of node 2. (a node is not considered its own ancestor)
ROSE_DLL_API SgScopeStatement * getEnclosingScope(SgNode *n, const bool includingSelf=false)
Get the enclosing scope from a node n.
ROSE_DLL_API SgNonrealSymbol * lookupNonrealSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgSwitchStatement * findEnclosingSwitch(SgStatement *s)
Find the closest switch outside a given statement (normally used for case and default statements)
ROSE_DLL_API void removeAllOriginalExpressionTrees(SgNode *top)
Set original expression trees to NULL for SgValueExp or SgCastExp expressions, so you can change the ...
ROSE_DLL_API std::vector< SgNode * > astIntersection(SgNode *original, SgNode *copy, SgCopyHelp *help=NULL)
Compute the intersection set for two ASTs.
ROSE_DLL_API bool isPrefixOperator(SgExpression *exp)
Is an overloaded operator a prefix operator (e.g. address operator X * operator&(),...
ROSE_DLL_API void setLhsOperand(SgExpression *target, SgExpression *lhs)
set left hand operand for binary expressions, transparently downcasting target expressions when neces...
ROSE_DLL_API std::vector< SgC_PreprocessorDirectiveStatement * > translateStatementToUseCppDeclarations(SgStatement *statement, SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API int suggestNextNumericLabel(SgFunctionDefinition *func_def)
Suggest next usable (non-conflicting) numeric label value for a Fortran function definition scope.
ROSE_DLL_API std::set< SgStatement * > collectModifiedStatements(SgNode *node)
This collects the statements that are marked as modified (a flag automatically set by all set_* gener...
ROSE_DLL_API SgFunctionDeclaration * getEnclosingFunctionDeclaration(SgNode *astNode, const bool includingSelf=false)
Find the enclosing function declaration, including its derived instances like isSgProcedureHeaderStat...
SgFunctionDeclaration * findFunctionDeclaration(SgNode *root, std::string name, SgScopeStatement *scope, bool isDefining)
Topdown traverse a subtree from root to find the first function declaration matching the given name,...
ROSE_DLL_API bool isPrefixOperatorName(const SgName &functionName)
Check for proper names of possible prefix operators (used in isPrefixOperator()).
ROSE_DLL_API void setLoopStride(SgNode *loop, SgExpression *stride)
Set the stride(step) of a loop 's incremental expression, regardless the expression types (i+=s; i= i...
ROSE_DLL_API bool isInSubTree(SgExpression *subtree, SgExpression *exp)
Find a node by type using upward traversal.
ROSE_DLL_API bool forLoopNormalization(SgForStatement *loop, bool foldConstant=true)
Normalize a for loop, return true if successful.
unsigned long long getIntegerConstantValue(SgValueExp *expr)
Get the constant value from a constant integer expression; abort on everything else.
ROSE_DLL_API bool is_UPC_language()
ROSE_DLL_API void checkSymbolTables(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void updateDefiningNondefiningLinks(SgFunctionDeclaration *func, SgScopeStatement *scope)
Update defining and nondefining links due to a newly introduced function declaration....
ROSE_DLL_API SgNode * deepCopyNode(const SgNode *subtree)
Deep copy an arbitrary subtree.
SgBasicBlock * ensureBasicBlockAsBodyOfDefaultOption(SgDefaultOptionStmt *cs)
Check if the body of a 'default option' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void getLiveVariables(LivenessAnalysis *liv, SgForStatement *loop, std::set< SgInitializedName * > &liveIns, std::set< SgInitializedName * > &liveOuts)
get liveIn and liveOut variables for a for loop from liveness analysis result liv.
ROSE_DLL_API void resetModifiedLocatedNodes(const std::set< SgLocatedNode * > &modifiedNodeSet)
Use the set of IR nodes and set the isModified flag in each IR node to true.
ROSE_DLL_API SgNode * replaceWithPattern(SgNode *anchor, SgNode *new_pattern)
Replace an anchor node with a specified pattern subtree with optional SgVariantExpression....
ROSE_DLL_API bool ROSE_DLL_API isJovialOutParam(SgInitializedName *name)
True if a parameter name is a Jovial output parameter.
ROSE_DLL_API void moveForStatementIncrementIntoBody(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfOmpBodyStmt(SgOmpBodyStatement *ompbodyStmt)
Check if the body of a SgOmpBodyStatement is a SgBasicBlock, create one if not.
ROSE_DLL_API bool is_Python_language()
ROSE_DLL_API bool is_mixed_Fortran_and_Cxx_language()
ROSE_DLL_API SgStatement * getLoopCondition(SgScopeStatement *loop)
Routines to get the condition of a loop. It recognize While-loop, For-loop, and Do-While-loop.
ROSE_DLL_API SgEnumSymbol * lookupEnumSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableAndReferenceForExpression(SgExpression *expression, SgScopeStatement *scope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgTypedefSymbol * lookupTypedefSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfWhile(SgWhileStmt *ws)
Check if the body of a 'while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfFor(SgForStatement *fs)
Check if the body of a 'for' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API PreprocessingInfo * attachArbitraryText(SgLocatedNode *target, const std::string &text, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Attach an arbitrary string to a located node. A workaround to insert irregular statements or vendor-s...
ROSE_DLL_API void markNodeToBeUnparsed(SgNode *node, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstantTrue(SgExpression *e)
Check if a bool or int constant expression evaluates to be a true value.
std::map< std::string, SgNode * > local_name_to_node_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API bool is_binary_executable()
void changeAllBodiesToBlocks(SgNode *top, bool createEmptyBody=true)
Fix up ifs, loops, while, switch, Catch, OmpBodyStatement, etc. to have blocks as body components....
void dumpPreprocInfo(SgLocatedNode *locatedNode)
Dumps a located node's preprocessing information.
void fixupReferencesToSymbols(const SgScopeStatement *this_scope, SgScopeStatement *copy_scope, SgCopyHelp &help)
All the symbol table references in the copied AST need to be reset after rebuilding the copied scope'...
ROSE_DLL_API void moveDeclarationToAssociatedNamespace(SgDeclarationStatement *declarationStatement)
Relocate the declaration to be explicitly represented in its associated namespace (required for some ...
ROSE_DLL_API bool isCanonicalForLoop(SgNode *loop, SgInitializedName **ivar=NULL, SgExpression **lb=NULL, SgExpression **ub=NULL, SgExpression **step=NULL, SgStatement **body=NULL, bool *hasIncrementalIterationSpace=NULL, bool *isInclusiveUpperBound=NULL)
Check if a for-loop has a canonical form, return loop index, bounds, step, and body if requested.
ROSE_DLL_API bool isArrayReference(SgExpression *ref, SgExpression **arrayNameExp=NULL, std::vector< SgExpression * > **subscripts=NULL)
Check if an expression is an array access (SgPntrArrRefExp). If so, return its name expression and su...
ROSE_DLL_API void insertStatementAfterLastDeclaration(SgStatement *stmt, SgScopeStatement *scope)
Insert a statement after the last declaration within a scope. The statement will be prepended to the ...
ROSE_DLL_API void destroyTempDirectory(std::string)
Use the system command to remove a temporary directory and all its containing files.
void serialize_list(T &plist, std::string T_name, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
void resetMangledNameCache(SgGlobal *globalScope)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API SgTemplateInstantiationMemberFunctionDecl * buildForwardFunctionDeclaration(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Generate a non-defining (forward) declaration from a defining function declaration.
ROSE_DLL_API bool is_Fortran_language()
ROSE_DLL_API SgVariableSymbol * lookupVariableSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void outputFileIds(SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API SgExprStatement * splitVariableDeclaration(SgVariableDeclaration *decl)
Split a variable declaration with an rhs assignment into two statements: a declaration and an assignm...
ROSE_DLL_API SgStatement * getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated=false)
Get the first statement within a scope, return NULL if it does not exist. Skip compiler-generated sta...
ROSE_DLL_API SgNamespaceSymbol * lookupNamespaceSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isExtern(SgDeclarationStatement *stmt)
Check if a declaration has an "extern" modifier.
std::string extractPragmaKeyword(const SgPragmaDeclaration *)
Extract a SgPragmaDeclaration's leading keyword . For example "#pragma omp parallel" has a keyword of...
ROSE_DLL_API SgTemplateClassSymbol * lookupTemplateClassSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *templateParameterList, SgTemplateArgumentPtrList *templateArgumentList, SgScopeStatement *cscope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isEquivalentFunctionType(const SgFunctionType *lhs, const SgFunctionType *rhs)
Test if two types are equivalent SgFunctionType nodes.
ROSE_DLL_API void setLoopLowerBound(SgNode *loop, SgExpression *lb)
Set the lower bound of a loop header for (i=lb; ...)
void guardNode(SgLocatedNode *target, std::string guard)
Add preproccessor guard around a given node.
bool checkTypesAreEqual(SgType *typeA, SgType *typeB)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool isReferenceType(SgType *t)
Is this type a const or non-const reference type? (Handles typedefs correctly)
ROSE_DLL_API void moveCommentsToNewStatement(SgStatement *sourceStatement, const std::vector< int > &indexList, SgStatement *destinationStatement, bool destinationStatementPreceedsSourceStatement)
Relocate comments and CPP directives from one statement to another.
ROSE_DLL_API SgStatement * getEnclosingStatement(SgNode *n)
Find the closest enclosing statement, including the given node.
ROSE_DLL_API void translateToUseCppDeclarations(SgNode *n)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void changeContinuesToGotos(SgStatement *stmt, SgLabelStatement *label)
Change continue statements in a given block of code to gotos to a label.
void outputGlobalFunctionTypeSymbolTable()
Output function type symbols in global function type symbol table.
ROSE_DLL_API SgScopeStatement * findEnclosingLoop(SgStatement *s, const std::string &fortranLabel="", bool stopOnSwitches=false)
Find the closest loop outside the given statement; if fortranLabel is not empty, the Fortran label of...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableForExpression(SgExpression *expression, SgScopeStatement *scope, bool initializeInDeclaration, SgAssignOp **reEvaluate=NULL)
Given an expression, generates a temporary variable whose initializer optionally evaluates that expre...
bool isBodyStatement(SgStatement *s)
Check if a statement is a (true or false) body of a container-like parent, such as For,...
bool functionCallExpressionPreceedsDeclarationWhichAssociatesScope(SgFunctionCallExp *functionCall)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void convertAllForsToWhiles(SgNode *top)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool isConstantFalse(SgExpression *e)
Check if a bool or int constant expression evaluates to be a false value.
ROSE_DLL_API void outputLocalSymbolTables(SgNode *node)
Output the local symbol tables.
ROSE_DLL_API void preOrderCollectPreprocessingInfo(SgNode *current, std::vector< PreprocessingInfo * > &infoList, int depth)
Dumps a located node's preprocessing information.
ROSE_DLL_API SgMemberFunctionDeclaration * getDefaultDestructor(SgClassDeclaration *classDeclaration)
Get the default destructor from the class declaration.
void collectVarRefs(SgLocatedNode *root, std::vector< SgVarRefExp * > &result)
Collect all variable references in a subtree.
ROSE_DLL_API void setOperand(SgExpression *target, SgExpression *operand)
Set operands for expressions with single operand, such as unary expressions. handle file info,...
ROSE_DLL_API SgMemberFunctionDeclaration * getDefaultConstructor(SgClassDeclaration *classDeclaration)
Get the default constructor from the class declaration.
ROSE_DLL_API SgInitializedName * getLoopIndexVariable(SgNode *loop)
Return the loop index variable for a for loop.
ROSE_DLL_API SgAssignInitializer * splitExpression(SgExpression *from, std::string newName="")
Replace an expression with a temporary variable and an assignment statement.
ROSE_DLL_API void replaceVariableReferences(SgVariableSymbol *old_sym, SgVariableSymbol *new_sym, SgScopeStatement *scope)
Replace all variable references to an old symbol in a scope to being references to a new symbol.
ROSE_DLL_API bool is_OpenCL_language()
ROSE_DLL_API bool normalizeForLoopIncrement(SgForStatement *loop)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgVariableSymbol * appendArg(SgFunctionParameterList *, SgInitializedName *)
Append an argument to SgFunctionParameterList, transparently set parent,scope, and symbols for argume...
ROSE_DLL_API bool unnormalizeForLoopInitDeclaration(SgForStatement *loop)
Undo the normalization of for loop's C99 init declaration. Previous record of normalization is used t...
ROSE_DLL_API SgStatement * getPreviousStatement(SgStatement *currentStmt, bool climbOutScope=true)
Get previous statement of the current statement. It may return a previous statement of a parent scope...
ROSE_DLL_API void removeJumpsToNextStatement(SgNode *)
Remove jumps whose label is immediately after the jump. Used to clean up inlined code fragments.
bool isPrototypeInScope(SgScopeStatement *scope, SgFunctionDeclaration *functionDeclaration, SgDeclarationStatement *startingAtDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API int moveUpInnerDanglingIfEndifDirective(SgLocatedNode *lnode)
Extract sequences like " #endif #endif ... #if | #ifdef| #ifndef" buried inside subtree of lnode.
SgDeclarationStatement * getNonInstantiatonDeclarationForClass(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstType(SgType *t)
Is this a const type?
SgFunctionDeclaration * getDeclarationOfNamedFunction(SgExpression *func)
Given a SgExpression that represents a named function (or bound member function), return the mentione...
ROSE_DLL_API bool is_C99_language()
ROSE_DLL_API bool addDefaultConstructorIfRequired(SgClassType *classType, int physical_file_id=Sg_File_Info::TRANSFORMATION_FILE_ID)
Get the default destructor from the class declaration.
ROSE_DLL_API void movePreprocessingInfo(SgStatement *stmt_src, SgStatement *stmt_dst, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Move preprocessing information of stmt_src to stmt_dst, Only move preprocessing information from the ...
ROSE_DLL_API int fixVariableReferences(SgNode *root, bool cleanUnusedSymbol=true)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API bool isUseByAddressVariableRef(SgVarRefExp *ref)
Check if a variable reference is used by its address: including &a expression and foo(a) when type2 f...
struct const_int_expr_t evaluateConstIntegerExpression(SgExpression *expr)
The function tries to evaluate const integer expressions (such as are used in array dimension sizes)....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsTrueBodyOfIf(SgIfStmt *ifs)
Check if the true body of a 'if' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void replaceExpression(SgExpression *oldExp, SgExpression *newExp, bool keepOldExp=false)
Replace an expression with another, used for variable reference substitution and others....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsFalseBodyOfIf(SgIfStmt *ifs, bool createEmptyBody=true)
Check if the false body of a 'if' statement is a SgBasicBlock, create one if not when the flag is tru...
ROSE_DLL_API SgExprListExp * getEnclosingExprListExp(SgNode *astNode, const bool includingSelf=false)
Get the enclosing SgExprListExp (used as part of function argument index evaluation in subexpressions...
ROSE_DLL_API void appendStatement(SgStatement *stmt, SgScopeStatement *scope=NULL)
Append a statement to the end of the current scope, handle side effect of appending statements,...
ROSE_DLL_API SgFunctionDeclaration * buildFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
void addVarRefExpFromArrayDimInfo(SgNode *astNode, Rose_STL_Container< SgNode * > &NodeList_t)
Find all SgPntrArrRefExp under astNode, then add SgVarRefExp (if any) of SgPntrArrRefExp's dim_info i...
ROSE_DLL_API bool loopTiling(SgForStatement *loopNest, size_t targetLevel, size_t tileSize)
Tile the n-level (starting from 1) loop of a perfectly nested loop nest using tiling size s.
std::string generateUniqueName(const SgNode *node, bool ignoreDifferenceBetweenDefiningAndNondefiningDeclarations)
Generate unique name from C and C++ constructs. The name may contain space.
ROSE_DLL_API SgGlobal * getFirstGlobalScope(SgProject *project)
return the first global scope under current project
ROSE_DLL_API void setOneSourcePositionNull(SgNode *node)
Set current node's source position as NULL.
ROSE_DLL_API void setRhsOperand(SgExpression *target, SgExpression *rhs)
set left hand operand for binary expression
std::pair< SgStatement *, SgInitializedName * > wrapFunction(SgFunctionDeclaration &definingDeclaration, SgName newName)
moves the body of a function f to a new function f; f's body is replaced with code that forwards the ...
ROSE_DLL_API bool is_mixed_Fortran_and_C_and_Cxx_language()
ROSE_DLL_API bool isVolatileType(SgType *t)
Is this a volatile type?
void clearUnusedVariableSymbols(SgNode *root=NULL)
Clear those variable symbols with unknown type (together with initialized names) which are also not r...
ROSE_DLL_API void fixVariableDeclaration(SgVariableDeclaration *varDecl, SgScopeStatement *scope)
Patch up symbol, scope, and parent information when a SgVariableDeclaration's scope is known.
ROSE_DLL_API SgSymbol * lookupSymbolInParentScopesIgnoringAliasSymbols(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::string generateUniqueVariableName(SgScopeStatement *scope, std::string baseName="temp")
Generate a name like temp# that is unique in the current scope and any parent and children scopes.
ROSE_DLL_API int gensym_counter
An internal counter for generating unique SgName.
ROSE_DLL_API void splitExpressionIntoBasicBlock(SgExpression *expr)
Split long expressions into blocks of statements.
void reset_name_collision_map()
Reset map variables used to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API SgFunctionDefinition * getEnclosingProcedure(SgNode *n, const bool includingSelf=false)
Find the function definition.
std::vector< SgExpression * > get_C_array_dimensions(const SgArrayType &arrtype)
returns the array dimensions in an array as defined for arrtype
ROSE_DLL_API void replaceSubexpressionWithStatement(SgExpression *from, SageInterface::StatementGenerator *to)
Similar to replaceExpressionWithStatement, but with more restrictions.
ROSE_DLL_API void wrapAllTemplateInstantiationsInAssociatedNamespaces(SgProject *root)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
std::string get_name(const SgNode *node)
Generate a useful name to describe the SgNode.
ROSE_DLL_API void setLoopUpperBound(SgNode *loop, SgExpression *ub)
Set the upper bound of a loop header,regardless the condition expression type. for (i=lb; i op up,...
ROSE_DLL_API bool isMemberFunctionMemberReference(SgMemberFunctionRefExp *memberFunctionRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API SgClassDefinition * findJavaPackage(SgScopeStatement *, std::string)
Look for a qualified package name in the given scope and return its package definition.
ROSE_DLL_API bool isOmpStatement(SgNode *)
Check if a node is SgOmp*Statement.
ROSE_DLL_API bool is_Ada_language()
std::string addMangledNameToCache(SgNode *astNode, const std::string &mangledName)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool is_C_language()
ROSE_DLL_API std::list< SgClassType * > getClassTypeChainForMemberReference(SgExpression *refExp)
Find a node by type using upward traversal.
ROSE_DLL_API void collectUseByAddressVariableRefs(const SgStatement *s, std::set< SgVarRefExp * > &varSetB)
Collect variable references involving use by address: including &a expression and foo(a) when type2 f...
std::vector< SgContinueStmt * > findContinueStmts(SgStatement *code, const std::string &fortranLabel="")
Find all continue statements inside a particular statement, stopping at nested loops.
std::string getMangledNameFromCache(SgNode *astNode)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgDeclarationStatement * > sortSgNodeListBasedOnAppearanceOrderInSource(const std::vector< SgDeclarationStatement * > &nodevec)
Reorder a list of declaration statements based on their appearance order in source files.
ROSE_DLL_API std::set< SgLocatedNode * > collectModifiedLocatedNodes(SgNode *node)
This collects the SgLocatedNodes that are marked as modified (a flag automatically set by all set_* g...
SgExpression * forallMaskExpression(SgForAllStatement *stmt)
Get the mask expression from the header of a SgForAllStatement.
void clearScopeNumbers(SgFunctionDefinition *functionDefinition)
Clears the cache of scope,integer pairs for the input function.
ROSE_DLL_API SgInitializedName * convertRefToInitializedName(SgNode *current, bool coarseGrain=true)
Variable references can be introduced by SgVarRef, SgPntrArrRefExp, SgInitializedName,...
ROSE_DLL_API SgNode * getSgNodeFromAbstractHandleString(const std::string &input_string)
Obtain a matching SgNode from an abstract handle string.
ROSE_DLL_API void moveStatementsBetweenBlocks(SgBasicBlock *sourceBlock, SgBasicBlock *targetBlock)
Move statements in first block to the second block (preserves order and rebuilds the symbol table).
ROSE_DLL_API bool templateDefinitionIsInClass(SgTemplateInstantiationMemberFunctionDecl *memberFunctionDeclaration)
Return true if template definition is in the class, false if outside of class.
ROSE_DLL_API void fixLabelStatement(SgLabelStatement *label_stmt, SgScopeStatement *scope)
Fix symbol table for SgLabelStatement. Used Internally when the label is built without knowing its ta...
ROSE_DLL_API void replaceExpressionWithStatement(SgExpression *from, SageInterface::StatementGenerator *to)
Replace a given expression with a list of statements produced by a generator.
ROSE_DLL_API void convertForToWhile(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void insertStatementBefore(SgStatement *targetStmt, SgStatement *newStmt, bool autoMovePreprocessingInfo=true)
Insert a statement before a target statement.
ROSE_DLL_API bool findFirstSgCastExpMarkedAsTransformation(SgNode *n, const std::string &s)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void dumpInfo(SgNode *node, std::string desc="")
Dump information about a SgNode for debugging.
ROSE_DLL_API void convertFunctionDefinitionsToFunctionPrototypes(SgNode *node)
XXX This function operates on the new file used to support outlined function definitions....
ROSE_DLL_API void appendStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
Append a list of statements to the end of the current scope, handle side effect of appending statemen...
SgNamedType * getDeclaredType(const SgDeclarationStatement *declaration)
Returns the type introduced by a declaration.
ROSE_DLL_API bool isIndexOperator(SgExpression *exp)
Is an overloaded operator an index operator (also referred to as call or subscript operators)....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfCatch(SgCatchOptionStmt *cos)
Check if the body of a 'catch' statement is a SgBasicBlock, create one if not.
std::vector< SgFile * > generateFileList()
Returns STL vector of SgFile IR node pointers.
ROSE_DLL_API int normalizeArrowExpWithAddressOfLeftOperand(SgNode *root, bool transformationGeneratedOnly=true)
Convert all code within root matching the patern of (&left)->right, and translate them into left....
bool hasTemplateSyntax(const SgName &name)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void moveToSubdirectory(std::string directoryName, SgFile *file)
Move file to be generated in a subdirectory (will be generated by the unparser).
ROSE_DLL_API bool isAddressTaken(SgExpression *refExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool hasSimpleChildrenList(SgScopeStatement *scope)
Check if a scope statement has a simple children statement list so insert additional statements under...
ROSE_DLL_API SgFunctionDeclaration * findMain(SgNode *currentNode)
top-down traversal from current node to find the main() function declaration
ROSE_DLL_API SgClassSymbol * lookupClassSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void removeConsecutiveLabels(SgNode *top)
Remove consecutive labels.
ROSE_DLL_API void setLoopBody(SgScopeStatement *loop, SgStatement *body)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
bool getForLoopInformations(SgForStatement *for_loop, SgVariableSymbol *&iterator, SgExpression *&lower_bound, SgExpression *&upper_bound, SgExpression *&stride)
ROSE_DLL_API void appendExpression(SgExprListExp *, SgExpression *)
Append an expression to a SgExprListExp, set the parent pointer also.
ROSE_DLL_API bool isLambdaFunction(SgFunctionDeclaration *func)
Check if a function declaration is a C++11 lambda function.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfSwitch(SgSwitchStatement *ws)
Check if the body of a 'switch' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void prependStatement(SgStatement *stmt, SgScopeStatement *scope=NULL)
Prepend a statement to the beginning of the current scope, handling side effects as appropriate.
ROSE_DLL_API bool isCallToParticularFunction(SgFunctionDeclaration *decl, SgExpression *e)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool ROSE_DLL_API isMutable(SgInitializedName *name)
True if an SgInitializedName is "mutable' (has storage modifier set)
ROSE_DLL_API bool isCopyConstructible(SgType *type)
Is a type copy constructible? This may not quite work properly.
ROSE_DLL_API SgVariableSymbol * prependArg(SgFunctionParameterList *, SgInitializedName *)
Prepend an argument to SgFunctionParameterList.
ROSE_DLL_API void setSourcePositionAtRootAndAllChildren(SgNode *root)
Set the source code positon for the subtree (including the root).
ROSE_DLL_API SgExpression * copyExpression(SgExpression *e)
Deep copy an expression.
void setParameterList(actualFunction *func, SgFunctionParameterList *paralist)
Set parameter list for a function declaration, considering existing parameter list etc.
SgStatement * findLastDeclarationStatement(SgScopeStatement *scope, bool includePragma=false)
Find the last declaration statement within a scope (if any). This is often useful to decide where to ...
ROSE_DLL_API bool insideSystemHeader(SgLocatedNode *node)
Set source position info(Sg_File_Info) as transformation generated for all SgNodes in memory pool.
std::vector< SgDeclarationStatement * > getDependentDeclarations(SgStatement *stmt)
Get a statement's dependent declarations which declares the types used in the statement....
SgBasicBlock * makeSingleStatementBodyToBlock(SgStatement *singleStmt)
Make a single statement body to be a basic block. Its parent is if, while, catch, or upc_forall etc.
void computeUniqueNameForUseAsIdentifier(SgNode *astNode)
Traversal to set the global map of names to node and node to names.collisions to support generateUniq...
ROSE_DLL_API void collectReadOnlyVariables(SgStatement *stmt, std::set< SgInitializedName * > &readOnlyVars, bool coarseGrain=true)
Collect read only variables within a statement. The statement can be either of a function,...
std::string generateUniqueNameForUseAsIdentifier_support(SgDeclarationStatement *declaration)
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API PreprocessingInfo * findHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader)
Find the preprocessingInfo node representing #include <header.h> or #include "header....
ROSE_DLL_API void myRemoveStatement(SgStatement *stmt)
A special purpose statement removal function, originally from inlinerSupport.h, Need Jeremiah's atten...
ROSE_DLL_API SgScopeStatement * getScope(const SgNode *astNode)
Get the closest scope from astNode. Return astNode if it is already a scope.
ROSE_DLL_API bool isStrictIntegerType(SgType *t)
Check if a type is an integral type, only allowing signed/unsigned short, int, long,...
ROSE_DLL_API bool is_Java_language()
ROSE_DLL_API void insertStatementAfter(SgStatement *targetStmt, SgStatement *newStmt, bool autoMovePreprocessingInfo=true)
Insert a statement after a target statement, Move around preprocessing info automatically by default.
ROSE_DLL_API bool isEquivalentType(const SgType *lhs, const SgType *rhs)
Test for equivalence of types independent of access permissions (private or protected modes for membe...
ROSE_DLL_API bool isTemplateInstantiationNode(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void removeStatement(SgStatement *stmt, bool autoRelocatePreprocessingInfo=true)
Remove a statement from its attach point of the AST. Automatically keep its associated preprocessing ...
ROSE_DLL_API SgOmpClauseBodyStatement * findEnclosingOmpClauseBodyStatement(SgStatement *s)
Find enclosing OpenMP clause body statement from s. If s is already one, return it directly.
ROSE_DLL_API bool scopeHasStatementsFromSameFile(SgScopeStatement *scope)
This function supports the token-based unparsing when used with unparsing of header files to know whe...
ROSE_DLL_API SgSourceFile * getEnclosingSourceFile(SgNode *n, const bool includingSelf=false)
Find enclosing source file node.
void rebuildSymbolTable(SgScopeStatement *scope)
Regenerate the symbol table.
ROSE_DLL_API SgSymbol * lookupSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
void setBaseTypeDefiningDeclaration(SgVariableDeclaration *var_decl, SgDeclarationStatement *base_decl)
a better version for SgVariableDeclaration::set_baseTypeDefininingDeclaration(), handling all side ef...
ROSE_DLL_API void pastePreprocessingInfo(SgLocatedNode *dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &saved_buf)
Paste preprocessing information from a buffer to a destination node. Used in combination of cutPrepro...
ROSE_DLL_API SgStatement * lastFrontEndSpecificStatement(SgGlobal *globalScope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgFunctionType * findFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList)
Find the function type matching a function signature plus a given return type.
std::set< unsigned int > collectSourceSequenceNumbers(SgNode *astNode)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool is_OpenMP_language()
ROSE_DLL_API std::set< SgNode * > getFrontendSpecificNodes()
Find a node by type using upward traversal.
ROSE_DLL_API bool mergeAssignmentWithDeclaration(SgExprStatement *assign_stmt, SgVariableDeclaration *decl, bool removeAssignStmt=true)
Merge an assignment into its upstream declaration statement. Callers should make sure the merge is se...
ROSE_DLL_API void setFortranNumericLabel(SgStatement *stmt, int label_value, SgLabelSymbol::label_type_enum label_type=SgLabelSymbol::e_start_label_type, SgScopeStatement *label_scope=NULL)
Set a numerical label for a Fortran statement. The statement should have a enclosing function definit...
ROSE_DLL_API SgType * lookupNamedTypeInParentScopes(const std::string &type_name, SgScopeStatement *scope=NULL)
Lookup a named type based on its name, bottomup searching from a specified scope. Note name collison ...
ROSE_DLL_API SgFile * processFile(SgProject *, std::string, bool unparse=false)
Invoke JavaRose to translate a given file and put the resulting AST in the global space of the projec...
bool get(const Word *words, size_t idx)
Return a single bit.
void swap_child(SageNode &lhs, SageNode &rhs, SageChild *(SageNode::*getter)() const, void(SageNode::*setter)(SageChild *))
swaps children (of equal kind) between two ancestor nodes of the same type
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.
This file implements generic (template) sage query functions Currently this includes functions for:
static ROSE_DLL_API DeferredTransformation replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
operator=()
ROSE_DLL_API ~DeferredTransformation(void)
Copy constructor.
ROSE_DLL_API DeferredTransformation & operator=(const DeferredTransformation &X)
Shallow; does not delete fields.
struct DispatchHandler