ROSE 0.11.145.192
sageInterface.C
1
2#include "sage3basic.h"
3#include "markLhsValues.h"
4#include "fixupNames.h"
5#include "FileUtility.h"
6#include <Sawyer/Message.h>
7
8#include "AstJSONGeneration.h"
9
10#include "SgNodeHelper.h" //Markus's helper functions
11
12#include "Rose/AST/Utility.h"
13
14#include "sageInterface.h"
15#include "Combinatorics.h"
16
17
18#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
19#include "replaceExpressionWithStatement.h"
20
21#include "constantFolding.h"
22#endif
23
24// DQ (10/14/2006): Added supporting help functions. tps commented out since it caused no compilation errors
25//#include "rewrite.h"
26
27// Liao 1/24/2008 : need access to scope stack sometimes
28#include "sageBuilder.h"
29
30// DQ (3/14/2017): Try to comment this out since it is not tested (used in get_C_array_dimensions(),
31// from midend/programTransformation/ompLowering/omp_lowering.cpp, but not tested).
32#include "sageGeneric.h"
33
34#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
35// For reusing some code from Qing's loop optimizer
36// Liao, 2/26/2009
37#include "AstInterface_ROSE.h"
38#include "LoopTransformInterface.h"
39
40#include "DepInfoAnal.h" // for AnalyzeStmtRefs()
41#include "ArrayAnnot.h"
42#include "ArrayInterface.h"
43
44#include "LoopUnroll.h"
45#include "abstract_handle.h"
46#include "roseAdapter.h"
47#endif
48
49#include <boost/lexical_cast.hpp>
50#include <boost/foreach.hpp>
51#include <sstream>
52#include <iostream>
53#include <algorithm> // for set operations
54#include <numeric> // for std::accumulate
55#include <map>
56#include <unordered_map>
57
58#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
59# include "jni.h"
60
61namespace Rose {
62 namespace Frontend {
63 namespace Java {
64 namespace Ecj {
65
66 extern jclass currentJavaTraversalClass;
67 extern JNIEnv *currentEnvironment;
68 extern jmethodID mainMethod;
69 extern jmethodID hasConflictsMethod;
70 extern jmethodID getTempDirectoryMethod;
71 extern jmethodID createTempFileMethod;
72 extern jmethodID createTempNamedFileMethod;
73 extern jmethodID createTempNamedDirectoryMethod;
74
75 } // ::Rose::Frontend::Java::Ecj
76 }// ::Rose::frontend::java
77 }// ::Rose::frontend
78}// ::Rose
79
80using namespace Rose::Frontend::Java::Ecj;
81
82#endif
83
84
85// DQ (11/5/2019): Added to support SageInterface::statementCanBeTransformed().
86namespace EDG_ROSE_Translation
87 {
88 // DQ (9/18/2018): Declare this map so that we can use it for the unparse header files option.
89#if defined(ROSE_BUILD_CXX_LANGUAGE_SUPPORT) && !defined(ROSE_USE_CLANG_FRONTEND)
90 // DQ (12/11/2018): Use the definition in the EDG edgRose.C file if C/C++ support IS defined.
91 extern std::map<std::string, SgIncludeFile*> edg_include_file_map;
92#else
93 // DQ (12/11/2018): Allow this to be the definition if C/C++ support is NOT defined.
94 std::map<std::string, SgIncludeFile*> edg_include_file_map;
95#endif
96 }
97
98
99
100// DQ (12/1/2015): Added to support macro handling.
101#include "detectMacroOrIncludeFileExpansions.h"
102
103namespace SageInterface {
104 template<class T> void setSourcePositionToDefault( T* node );
105}
106
107
108#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
109 #include "transformationSupport.h"
110#endif
111
112// We need this so that USE_CMAKE will be seen (set via configure).
113#include "rose_config.h"
114
115// DQ (3/4/2014): We need this feature to support the function: isStructurallyEquivalentAST().
116#include "RoseAst.h"
117
118// DQ (2/13/2022): We need this feature to support the function: deleteAllNodes().
119#include "AST_FILE_IO.h"
120
121
122// 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).
123// The value of 0 allows the old implementation to be tested, and the value of 1 allows the new optimized implementation to be tested.
124#define OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS 1
125
128
129// DQ (3/21/2016): Added support for generateUniqueNameForUseAsIdentifier().
131std::map<std::string,SgNode*> SageInterface::local_name_to_node_map;
132std::map<SgNode*,std::string> SageInterface::local_node_to_name_map;
133
134typedef std::set<SgLabelStatement*> SgLabelStatementPtrSet;
135
136namespace SageInterface
137{
138 Transformation_Record trans_records;
139}
140
141// DQ (12/31/2005): This is OK if not declared in a header file
142using namespace std;
143using namespace Rose;
144using namespace SageBuilder;
145//using namespace Rose::Diagnostics; // for mlog, INFO, WARN, ERROR, FATAL, etc.
146
147// Used by serialize() to collect all types visited
148//std::set<SgType*> type_set;
149// DQ (1/18/2015): Define this container locally in this file only.
150namespace SageInterface
151 {
152 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
153 vector<SgBasicBlock*> addedBasicBlockNodes;
154 }
155
156
157#if 1
158// DQ (2/13/2022): Adding support to delete the whole AST (every SgNode).
159void
161 {
162 // This function uses a memory pool traversal specific to the SgFile IR nodes
163
164 // We need to use this function to get all of the SgNodes.
165 // template <typename NodeType> std::vector<NodeType*> getSgNodeListFromMemoryPool()
166
167 class MyTraversal : public ROSE_VisitTraversal
168 {
169 public:
170 std::vector<SgNode*> resultlist;
171 void visit ( SgNode* node)
172 {
173 SgNode* result = dynamic_cast<SgNode*>(node);
174 ROSE_ASSERT(result != NULL);
175#if 0
176 printf ("In SageInterface::deleteAllNodes(): result = %p = %s \n",result,result->class_name().c_str());
177#endif
178#if 0
179 if (result != NULL)
180 {
181 resultlist.push_back(result);
182 }
183#else
184 resultlist.push_back(result);
185#endif
186 };
187
188 virtual ~MyTraversal() {}
189 };
190
191 // For debugging, recode the number of IR nodes before we delete the AST.
192 size_t numberOfNodes_before = numberOfNodes();
193
194 MyTraversal my_traversal;
195
196 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
197 // NodeType::traverseMemoryPoolNodes(my_traversal);
198 my_traversal.traverseMemoryPool();
199
200 // return my_traversal.resultlist;
201
202
203 // vector<SgNode*> nodeList = getSgNodeListFromMemoryPool<SgNode>();
204 vector<SgNode*> & nodeList = my_traversal.resultlist;
205
206 printf ("In SageInterface::deleteAllNodes(): get list of SgNode: nodeList.size() = %zu \n",nodeList.size());
207
208 vector<SgNode*>::iterator i = nodeList.begin();
209
210 // This loop will call the delete operator on all of the IR nodes in the AST.
211 while (i != nodeList.end())
212 {
213 SgNode* node = *i;
214#if 0
215 // It is an error to be calling get_name() while so many nodes are being deleted.
216 // printf (" --- calling delete (and thus the destructor) node = %p = %s name = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
217 printf (" --- calling delete (and thus the destructor) node = %p = %s \n",node,node->class_name().c_str());
218#endif
219 delete node;
220 node = NULL;
221
222 i++;
223 }
224
225#if 0
226 // This demonstrates that this function only visits the specific IR node that is used as a template parameter.
227 vector<SgFunctionDeclaration*> functionDeclarationList = getSgNodeListFromMemoryPool<SgFunctionDeclaration>();
228 printf ("In SageInterface::deleteAllNodes(): get list of SgFunctionDeclaration: functionDeclarationList.size() = %zu \n",functionDeclarationList.size());
229#endif
230
231 // Now we need to delete the memory pools (implemented by ROSETTA).
232 AST_FILE_IO::clearAllMemoryPools();
233
234 size_t numberOfNodes_after = numberOfNodes();
235
236#if 1
237 printf ("Leaving SageInterface::deleteAllNodes(): numberOfNodes_before = %zu numberOfNodes_after = %zu \n",numberOfNodes_before,numberOfNodes_after);
238#endif
239 }
240#endif
241
242
243#if 0
244// DQ (3/5/2022): Adding support to check AST for invalide poionters.
245void
247 {
248 // This function uses a memory pool traversal to look for any pointers to invalid IR nodes.
249
250 // Step 1: is to build a map of the boundaries of the memory pools for each IR node kind.
251 // Step 2: traverse all of the IR nodes across all of the memory pools and check
252 // a) if the pointer to each node in the list of child IR nodes is in the map from step 1.
253 // b) if it is then we can expect to dereference the pointer and check the value of
254 // get_freepointer(), the value should be 0xffffffffffffffff, else it is an error
255 // (when it is an error it usually should be a value that is in the map from step 1, but it
256 // is a node that was previously deleted, so it is a stale pointer).
257
258 class BuildMapTraversal : public ROSE_VisitTraversal
259 {
260 public:
261 // std::vector<SgNode*> resultlist;
262 // std::map<enum VariantT,std::vector<std::pair<SgNode*,SgNode*>> mapOfMemoryPoolsBounds;
263
264 // We need to get the pools variable for each IR node.
265
266 void visit ( SgNode* node)
267 {
268 // Get list of all pointers to all IR nodes in the current node.
269
270 // $CLASSNAME::pools
272
273 resultlist.push_back(result);
274 };
275
276 virtual ~MyTraversal() {}
277 };
278
279 // For debugging, recode the number of IR nodes before we delete the AST.
280 size_t numberOfNodes_before = numberOfNodes();
281
282 MyTraversal my_traversal;
283
284 // We need to visit all of the IR nodes, not just those of a specific class in ROSE.
285 // NodeType::traverseMemoryPoolNodes(my_traversal);
286 my_traversal.traverseMemoryPool();
287 }
288#endif
289
290void
291SageInterface::DeclarationSets::addDeclaration(SgDeclarationStatement* decl)
292 {
293 // DQ (4/3/2014): This function either builds a new set or inserts declarations into an
294 // existing set based on if a set defined by the key (firstNondefiningDeclaration) is present.
295 ASSERT_not_null(decl);
296
297#if 0
298 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
299#endif
300
301 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
302
303 if (firstNondefiningDeclaration == nullptr)
304 {
305 // It appears that some loop transformations (pass3.C) don't set the firstNondefiningDeclaration.
306#if 0
307 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): firstNondefiningDeclaration == NULL: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
308#endif
309 return;
310 }
311 ASSERT_not_null(firstNondefiningDeclaration);
312
313 if (decl == firstNondefiningDeclaration)
314 {
315#if 0
316 if (isSgTypedefDeclaration(decl) != nullptr)
317 {
318 printf ("TOP of SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
319 }
320#endif
321 if (declarationMap.find(firstNondefiningDeclaration) == declarationMap.end())
322 {
323#if 0
324 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
325#endif
326#if 0
327 if (isSgTypedefDeclaration(decl) != nullptr)
328 {
329 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add a set for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
330 }
331#endif
332 // Add a new set.
333 declarationMap[decl] = new set<SgDeclarationStatement*>();
334
335 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
336 ROSE_ASSERT(declarationMap[decl] != nullptr);
337
338 // Add a declaration to an existing set.
339 declarationMap[firstNondefiningDeclaration]->insert(decl);
340 }
341 else
342 {
343 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
344 {
345#if 0
346 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
347#endif
348#if 0
349 if (isSgTypedefDeclaration(decl) != nullptr)
350 {
351 printf ("In SageInterface::DeclarationSets::addDeclaration(): Add the declaration to the existing set: decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
352 }
353#endif
354 // Add a declaration to an existing set.
355 declarationMap[firstNondefiningDeclaration]->insert(decl);
356 }
357 else
358 {
359#if 0
360 printf ("WARNING: SageInterface::DeclarationSets::addDeclaration(): A set already exists for decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
361#endif
362 // DQ (4/5/2014): The case of SgFunctionParameterList fails only for boost examples (e.g. test2014_240.C).
363 // Problem uses are associated with SgTemplateInstantiationFunctionDecl IR nodes.
364 bool ignore_error = (isSgFunctionParameterList(decl) != nullptr);
365
366 // DQ (4/17/2014): This is required for the EDG version 4.8 and I don't know why.
367 // Currently the priority is to pass our existing tests.
368 // An idea is that this is sharing introduced as a result of the use of default parameters.
369
370 // DQ (7/2/2014): I am seeing that this is required for a new application using GNU 4.4.7.
371 // It allows a boost issue specific to a revisited SgTypedefDeclaration pass, but I still
372 // don't understand the problem. so this needs a better fix.
373
375 bool isInTemplateFunctionDeclaration = enclosingFunction != nullptr && (isSgTemplateMemberFunctionDeclaration(enclosingFunction) || isSgTemplateFunctionDeclaration(enclosingFunction));
376
377 // Use short-circuit evaluation to improve performance.
378 SgClassDefinition* enclosingClassDefinition = isInTemplateFunctionDeclaration == true ? nullptr : getEnclosingClassDefinition(decl);
379 bool isInTemplateClassDefinition = enclosingClassDefinition != nullptr && isSgTemplateClassDefinition(enclosingClassDefinition);
380
381 bool isInTemplateDeclaration = isInTemplateFunctionDeclaration || isInTemplateClassDefinition;
382
383 ignore_error = ignore_error || (isSgTypedefDeclaration(decl) != nullptr) || (isSgTemplateInstantiationDecl(decl) != nullptr) || (isInTemplateDeclaration == true);
384
385 // DQ (2/5/2015): We need to ignore the case of un-named classes (or maybe those classes
386 // from unnamed classes with lambda member functions). See test2015_13.C for an example.
387 // Or maybe these should have been added to the declarationMap in the front-end?
388 if (isSgClassDeclaration(decl) != nullptr)
389 {
390 ignore_error = ignore_error || (isSgClassDeclaration(decl)->get_isUnNamed() == true);
391 }
392 }
393 }
394 }
395 else
396 {
397 // Add the declaration (make sure there is a set that exists).
398 if (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end())
399 {
400 // Make sure it does not already exist in the set.
401 ROSE_ASSERT (declarationMap[firstNondefiningDeclaration] != nullptr);
402 if (declarationMap[firstNondefiningDeclaration]->find(decl) == declarationMap[firstNondefiningDeclaration]->end())
403 {
404 // Add a declaration to an existing set.
405 declarationMap[firstNondefiningDeclaration]->insert(decl);
406 }
407 else
408 {
409#if 0
410 printf ("This declaration is already in the set (skip adding it twice): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
411#endif
412 }
413 }
414 else
415 {
416 // In this case the defining declaration might be the only declaration to be traversed and
417 // so a set has not been built yet.
418#if 0
419 printf ("In SageInterface::DeclarationSets::addDeclaration(): Adding set and declaration for the firstNondefiningDeclaration = %p = %s = %s \n",
420 firstNondefiningDeclaration,firstNondefiningDeclaration->class_name().c_str(),get_name(firstNondefiningDeclaration).c_str());
421#endif
422
423 // DQ (4/5/2014): Just build the set and don't insert the firstNondefiningDeclaration.
424 // If we were to do so then it would be an error to use the insert it later.
425 // Note recursive call.
426 // addDeclaration(firstNondefiningDeclaration);
427 declarationMap[firstNondefiningDeclaration] = new set<SgDeclarationStatement*>();
428
429 ROSE_ASSERT (declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
430
431 // DQ (4/5/2014): We have to insert this since it is different from the firstNondefiningDeclaration.
432 // Add the declaration to the existing set.
433 declarationMap[firstNondefiningDeclaration]->insert(decl);
434
435 // DQ (4/5/2014): Added assertion.
436 ROSE_ASSERT(declarationMap[firstNondefiningDeclaration]->find(decl) != declarationMap[firstNondefiningDeclaration]->end());
437#if 0
438 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());
439 ROSE_ABORT();
440#endif
441 }
442 }
443
444#if 0
445 printf ("Leaving SageInterface::DeclarationSets::addDeclaration(): decl = %p = %s = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
446#endif
447 }
448
449const std::set<SgDeclarationStatement*>*
450SageInterface::DeclarationSets::getDeclarations(SgDeclarationStatement* decl)
451 {
452 // DQ (4/3/2014): This function returns the associated set of declarations.
453 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
454
455 ROSE_ASSERT(declarationMap.find(firstNondefiningDeclaration) != declarationMap.end());
456
457 const set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
458
459 // return this->declarationMap[firstNondefiningDeclaration];
460 return declarationSet;
461 }
462
463std::map<SgDeclarationStatement*,std::set<SgDeclarationStatement*>* > &
464SageInterface::DeclarationSets::getDeclarationMap()
465 {
466 return declarationMap;
467 }
468
469bool
470SageInterface::DeclarationSets::isLocatedInDefiningScope(SgDeclarationStatement* decl)
471 {
472 // DQ (4/7/2014): This function assumes that the input is a friend declaration.
473
474 // The existence of a declaration in a named scope (if a friend function) will cause
475 // subsequent declarations to be qualified where name qualification is required.
476 // A couple of issues:
477 // We likely need to keep track of the order of the declarations in the more
478 // complex cases because name qualification will be required after the declaration
479 // that appears in the named scope; but will not be required before the declaration in
480 // the named scope.
481
482#define DEBUG_LOCATED_IN_DEFINING_SCOPE 0
483
484 SgDeclarationStatement* firstNondefiningDeclaration = decl->get_firstNondefiningDeclaration();
485 ROSE_ASSERT(firstNondefiningDeclaration != nullptr);
486
487 set<SgDeclarationStatement*>* declarationSet = declarationMap[firstNondefiningDeclaration];
488 ROSE_ASSERT(declarationSet != nullptr);
489
490 set<SgDeclarationStatement*>::iterator i = declarationSet->begin();
491
492 bool isDefinedInNamedScope = false;
493
494#if DEBUG_LOCATED_IN_DEFINING_SCOPE
495 printf ("In DeclarationSets::isLocatedInDefiningScope(): decl = %p = %s \n",decl,decl->class_name().c_str());
496 printf (" --- declarationSet->size() = %" PRIuPTR " \n",declarationSet->size());
497#endif
498
499 while (isDefinedInNamedScope == false && i != declarationSet->end())
500 {
501 ROSE_ASSERT(*i != nullptr);
502#if DEBUG_LOCATED_IN_DEFINING_SCOPE
503 printf (" --- *i = %p = %s \n",*i,(*i)->class_name().c_str());
504#endif
505 // We want to know the structural position, not the semantic scope.
506 SgScopeStatement* semantic_scope = (*i)->get_scope();
507 SgScopeStatement* structural_scope = isSgScopeStatement((*i)->get_parent());
508
509#if DEBUG_LOCATED_IN_DEFINING_SCOPE
510 printf (" --- semantic_scope = %p = %s \n",semantic_scope,semantic_scope->class_name().c_str());
511 printf (" --- structural_scope = %p = %s \n",structural_scope,structural_scope->class_name().c_str());
512#endif
513 // 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,
514 SgScopeStatement* scope = isSgClassDefinition(semantic_scope) != nullptr ? semantic_scope : structural_scope;
515 ASSERT_not_null(scope);
516
517#if DEBUG_LOCATED_IN_DEFINING_SCOPE
518 printf (" --- scope = %p = %s \n",scope,scope->class_name().c_str());
519 printf (" --- scope->isNamedScope() = %s \n",scope->isNamedScope() ? "true" : "false");
520#endif
521 SgGlobal* globalScope = isSgGlobal(scope);
522
523 // Friend functions declared in the class definition are not meaningful for determining name qualification.
524 if (globalScope != nullptr || (scope->isNamedScope() == true && isSgClassDefinition(structural_scope) == nullptr) )
525 {
526 // Check if the function is output in the unparing, else it would not be defined.
527 bool willBeOutput = ((*i)->get_file_info()->isCompilerGenerated() == false ||
528 ((*i)->get_file_info()->isCompilerGenerated() &&
529 (*i)->get_file_info()->isOutputInCodeGeneration()) );
530#if DEBUG_LOCATED_IN_DEFINING_SCOPE
531 printf (" --- before: willBeOutput = %s \n",willBeOutput ? "true" : "false");
532#endif
533 // Being output only count when it is output where it is located structurally.
534 willBeOutput = willBeOutput && scope == structural_scope;
535
536#if DEBUG_LOCATED_IN_DEFINING_SCOPE
537 printf (" --- after: willBeOutput = %s \n",willBeOutput ? "true" : "false");
538#endif
539 // DQ (3/20/2016): this is reported by GNU as set but not used.
540 // associatedDeclaration = *i;
541
542 // isDefinedInNamedScope = true;
543 isDefinedInNamedScope = willBeOutput;
544 }
545
546 i++;
547 }
548
549#if DEBUG_LOCATED_IN_DEFINING_SCOPE
550 if (associatedDeclaration != nullptr)
551 {
552 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p = %s \n",associatedDeclaration,associatedDeclaration->class_name().c_str());
553 }
554 else
555 {
556 printf ("Leaving DeclarationSets::isLocatedInDefiningScope(): associatedDeclaration = %p \n",associatedDeclaration);
557 }
558#endif
559
560 return isDefinedInNamedScope;
561 }
562
564SageInterface::buildDeclarationSets(SgNode* n)
565 {
566 DeclarationSets* declarationSet = new DeclarationSets();
567
568 class DeclarationSetTraversal : public AstSimpleProcessing
569 {
570 private:
571 DeclarationSets* declarationSet;
572
573 public:
574 DeclarationSetTraversal(DeclarationSets* ds) : declarationSet(ds) {}
575 void visit (SgNode* node)
576 {
577 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
578 if (decl != nullptr)
579 {
580 declarationSet->addDeclaration(decl);
581 }
582 }
583 };
584
585 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
586 DeclarationSetTraversal traversal(declarationSet);
587 traversal.traverse(n, preorder);
588
589 return declarationSet;
590 }
591
593// DQ: 09/23/03
594// We require a global function for getting the string associated
595// with the definition of a variant (which is a global enum).
596string getVariantName ( VariantT v )
597 {
598 ROSE_ASSERT( int(v) < int(V_SgNumVariants));
599
600 // This code is far simpler (if the function is static)
601
602 // DQ (4/8/2004): Modified code to use new global list of sage
603 // class names (simpler this way)
604 // return string(SgTreeTraversal<int,int>::get_variantName(v));
605 extern const char* roseGlobalVariantNameList[];
606 return string(roseGlobalVariantNameList[v]);
607 }
608
609bool
611 {
612 // DQ (6/7/2012): This refactors the test for template instantiation syntax in names used for classes, member functions, and functions
613 bool usingTemplateSyntax = false;
614 string nameString = name.getString();
615
616 // DQ (6/7/2012): We need to avoid the identification of the "operator<()" as valid template syntax.
617 usingTemplateSyntax = (nameString.find('<') != string::npos) && (nameString.find('>') != string::npos);
618
619 // DQ (5/10/2016): Debugging case of C++11 using the Intel v16 compiler and it's associated mutex header file.
620 // See Cxx11_tests/test2016_32.C for an example that demonstrates this problem.
621 if (nameString == "<unnamed>")
622 {
623 printf ("In SageInterface::hasTemplateSyntax(): Identified case of name == <unnamed> \n");
624
625 usingTemplateSyntax = false;
626 }
627
628 // return (name.getString().find('<') == string::npos);
629 return usingTemplateSyntax;
630 }
631
632
633
634void
636 {
637 // DQ (2/12/2012): Refactoring disagnostic support for detecting where we are when something fails.
638
639 // This highest level node acceptable for us by this function is a SgGlobal (global scope).
640
641 ROSE_ASSERT(node != NULL);
642// printf ("Inside of SageInterface::whereAmI(node = %p = %s) \n",node,node->class_name().c_str());
643
644 // Enforce that some IR nodes should not be acepted inputs.
645 ROSE_ASSERT(isSgFile(node) == NULL);
646 ROSE_ASSERT(isSgFileList(node) == NULL);
647 ROSE_ASSERT(isSgProject(node) == NULL);
648
649 SgNode* parent = node->get_parent();
650
651 // Don't traverse past the SgFile level.
652 while (parent != nullptr && isSgFileList(parent) == nullptr)
653 {
654 // DQ (7/14/2019): These were commented out, but they are intended for debugging, so
655 // if someone does not need this output then the function should not have been called.
656 printf ("--- parent = %p = %s \n",parent,parent->class_name().c_str());
657
658 ROSE_ASSERT(parent->get_file_info() != NULL);
659 parent->get_file_info()->display("In SageInterface::whereAmI() diagnostics support");
660
661 parent = parent->get_parent();
662 }
663 }
664
665void
666SageInterface::initializeIfStmt(SgIfStmt *ifstmt, SgStatement* conditional, SgStatement * true_body, SgStatement * false_body)
667 {
668 // DQ (2/13/2012): Added new function to support proper initialization of a SgIfStmt that has already been built.
669 // This is important when we have to build the scope ahead of the test becasue the text contains a simple
670 // declaration (which must be put into the SgIfStmt scope).
671
672 // SgIfStmt *ifstmt = new SgIfStmt(conditional, true_body, false_body);
673 ROSE_ASSERT(ifstmt);
674
675 if (ifstmt->get_conditional() == nullptr)
676 ifstmt->set_conditional(conditional);
677
678 if (ifstmt->get_true_body() == nullptr)
679 ifstmt->set_true_body(true_body);
680
681 if (ifstmt->get_false_body() == nullptr)
682 ifstmt->set_false_body(false_body);
683
684 // Rasmussen (3/22/2020): Fixed setting case insensitivity
686 ifstmt->setCaseInsensitive(true);
687
689 if (conditional) conditional->set_parent(ifstmt);
690 if (true_body) true_body->set_parent(ifstmt);
691 if (false_body) false_body->set_parent(ifstmt);
692 }
693
694
695void
697 {
698 ROSE_ASSERT(switchStatement != NULL);
699
700 // Rasmussen (3/22/2020): Fixed setting case insensitivity
702 switchStatement->setCaseInsensitive(true);
703
704 if (switchStatement->get_item_selector() == nullptr)
705 switchStatement->set_item_selector(item_selector);
706
707 if (switchStatement->get_body() == nullptr)
708 switchStatement->set_body(body);
709
711 if (item_selector != nullptr)
712 item_selector->set_parent(switchStatement);
713 if (body != nullptr)
714 body->set_parent(switchStatement);
715 }
716
717
718void
720 {
721 ROSE_ASSERT(whileStatement);
722
723 // Rasmussen (3/22/2020): Fixed setting case insensitivity
725 whileStatement->setCaseInsensitive(true);
726
727 if (whileStatement->get_condition() == nullptr)
728 whileStatement->set_condition(condition);
729 if (whileStatement->get_body() == nullptr)
730 whileStatement->set_body(body);
731
732 // Python support.
733 if (whileStatement->get_else_body() == nullptr)
734 whileStatement->set_else_body(else_body);
735
736 setOneSourcePositionNull(whileStatement);
737 if (condition) condition->set_parent(whileStatement);
738 if (body) body->set_parent(whileStatement);
739
740 // DQ (8/10/2011): This is added by Michael to support a Python specific feature.
741 if (else_body != nullptr)
742 {
743 whileStatement->set_else_body(else_body);
744 else_body->set_parent(whileStatement);
745 }
746 }
747
748
749
752 {
753 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
754
755 // This function returns the namespace associated with any declaration.
756 // If the declaration is nested inside of other scopes this function
757 // iterates through these scopes to get the the first namespace.
758 // This is important for details of template handling, namely making sure
759 // that the template specializations (generated by ROSE) are put into the
760 // correct location (namespace) since stricted rules in gnu now enforce
761 // these details. If the declaration is not in a namespace as computed
762 // in the chain of scopes then this function returns nullptr.
763
764 ROSE_ASSERT(declaration != NULL);
765 SgScopeStatement* tempScope = declaration->get_scope();
766
767 // Loop back to the first namespace or stop at global scope (stop on either a namespace or the global scope)
768 while ( isSgNamespaceDefinitionStatement(tempScope) == nullptr && isSgGlobal(tempScope) == nullptr )
769 {
770 tempScope = tempScope->get_scope();
771 ROSE_ASSERT(tempScope != NULL);
772#if 0
773 printf ("Iterating back through scopes: tempScope = %p = %s = %s \n",tempScope,tempScope->class_name().c_str(),SageInterface::get_name(tempScope).c_str());
774#endif
775 }
776
777 SgNamespaceDefinitionStatement* namespaceScope = isSgNamespaceDefinitionStatement(tempScope);
778 return namespaceScope;
779 }
780
781
784 {
785 // DQ (11/4/2007): This function is used in the markTemplateInstantiationsForOutput.C
786 // DQ (11/4/2007): Get the associated declaration that will be in the original source code,
787 // if it is part of a template instantiation then get the original template declaration.
788
789 SgDeclarationStatement* parentDeclaration = nullptr;
790
791 SgScopeStatement* defn = memberFunctionInstantiation->get_class_scope();
792 ASSERT_not_null(defn);
793
794 // SgTemplateDeclaration* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
795 SgDeclarationStatement* templateDeclaration = memberFunctionInstantiation->get_templateDeclaration();
796 ASSERT_not_null(templateDeclaration);
797
798 // 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.
799 SgClassDefinition* cdefn = isSgClassDefinition(defn);
800 SgDeclarationScope* nrscope = isSgDeclarationScope(defn);
801 SgTemplateInstantiationDefn* templateInstatiationClassDefinition = isSgTemplateInstantiationDefn(defn);
802 if (templateInstatiationClassDefinition != nullptr)
803 {
804 // This is the case of a template member function in a templated class (see test2005_172.C).
805 SgTemplateInstantiationDefn* parentTemplateInstantiationDefinition = isSgTemplateInstantiationDefn(templateDeclaration->get_scope());
806 ASSERT_not_null(parentTemplateInstantiationDefinition);
807 SgTemplateInstantiationDecl* parentTemplateInstantiationDeclaration = isSgTemplateInstantiationDecl(parentTemplateInstantiationDefinition->get_declaration());
808 ASSERT_not_null(parentTemplateInstantiationDeclaration);
809
810 parentDeclaration = parentTemplateInstantiationDeclaration->get_templateDeclaration();
811 ASSERT_not_null(parentDeclaration);
812 }
813 else if (cdefn != nullptr)
814 {
815 // This is the case of a template member function in a class definition (see test2005_168.C).
816 parentDeclaration = cdefn->get_declaration();
817 ASSERT_not_null(parentDeclaration);
818 }
819 else if (nrscope != nullptr)
820 {
821 parentDeclaration = isSgDeclarationStatement(nrscope->get_parent());
822 ASSERT_not_null(parentDeclaration);
823 }
824 else
825 {
826 ROSE_ABORT();
827 }
828
829 return parentDeclaration;
830 }
831
835void
837{
838 ASSERT_not_null(var_decl);
839 ASSERT_not_null(base_decl);
840
841 // There is a bug (see gitlab-issue-349.jov) that arises when base_decl has a comment and it is the
842 // first statement, because base_decl will be removed (causing comments to be moved, where? good question!).
843 // Consider moving comments to var_decl first to circumvent (by artfulness or deception) potential problems.
844 // [Rasmussen 2024.04.10]
845
846 // try to remove it from the scope's declaration list
847 // If the struct decl was previously inserted into its scope
848 if (base_decl->get_parent() != nullptr)
849 {
850 if (base_decl->get_scope() == base_decl->get_parent())
851 {
852 SgStatementPtrList stmt_list = base_decl->get_scope()->generateStatementList();
853 if (find(stmt_list.begin(), stmt_list.end(), base_decl) != stmt_list.end())
855 }
856 }
857 base_decl->set_parent(var_decl);
858 var_decl->set_baseTypeDefiningDeclaration(base_decl);
859
860 //Set an internal mangled name for the anonymous declaration, if necessary
861 // resetNamesInAST(); // this will trigger mangleNameMap.size() ==0 assertion.
862 // We call resetEmptyNames directly instead.
863 ResetEmptyNames t1;
864 t1.traverseMemoryPool();
865}
866
867// DQ (11/4/2007): This looks for a forward temple member function declaration of matching name exists in the specified scope.
868bool
870 {
871 // 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.
872
873 bool foundExistingPrototype = false;
874
875 ROSE_ASSERT(scope != NULL);
876 ROSE_ASSERT(functionDeclaration != NULL);
877 ROSE_ASSERT(startingAtDeclaration != NULL);
878
879 // TV (09/17/2018): ROSE-1378
880 if (isSgDeclarationScope(scope)) {
881 printf("TODO: SgDeclarationScope handling in SageInterface::isPrototypeInScope see ROSE-1378\n");
882 return false;
883 }
884
885 // These are the scopes for which get_declarationList() is properly defined.
886 ROSE_ASSERT(scope->containsOnlyDeclarations() == true);
887
888 // Note that this is only defined for certain scopes, but we only want it for THOSE scopes
889 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
890
891 // This is a simple way to restrict the evaluation (still linear, but jumps to initial position to start search).
892 SgDeclarationStatementPtrList::iterator startingLocation = find(declarationList.begin(),declarationList.end(),startingAtDeclaration);
893
894 if (startingLocation != declarationList.end())
895 {
896#if 0
897 printf ("startingLocation = %p = %s = %s \n",*startingLocation,(*startingLocation)->class_name().c_str(),SageInterface::get_name(*startingLocation).c_str());
898#endif
899 // printf ("Found the startingLocation is the global scope, now check if we need to add a new declaration \n");
900 SgDeclarationStatementPtrList::iterator i = startingLocation;
901 SgScopeStatement* targetScope = functionDeclaration->get_scope();
902 SgName targetName = functionDeclaration->get_name();
903
904 while (i != declarationList.end())
905 {
906 // printf ("i = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
907
908 // Look for a prototype like what we want to insert, if we find it then we don't need to add a second one!
909 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(*i);
910 if (templateMemberFunction != nullptr)
911 {
912 // Check the name and the scope
913 if (targetScope == templateMemberFunction->get_scope())
914 {
915 if (targetName == templateMemberFunction->get_name())
916 {
917 // Don't count the defining declaration which may be at the end of the global scope.
918 if (templateMemberFunction->isForward() == true)
919 {
920 foundExistingPrototype = true;
921
922 // Exit the loop (optimization)
923 break;
924 }
925 }
926 }
927 }
928
929 i++;
930 }
931 }
932
933 return foundExistingPrototype;
934 }
935
936bool
938 {
939 ROSE_ASSERT(node1 && node2);
940
941 SgNode* curnode = node2;
942 if (node1==node2)
943 {
944 return false;
945 }
946
947 do {
948 curnode= curnode->get_parent();
949 } while( (curnode!=nullptr) && (curnode!=node1));
950
951 if (curnode==node1)
952 {
953 return true;
954 }
955 else
956 {
957 return false;
958 }
959 }
960
961bool
963 {
964 // DQ (12/7/2020): This is supporting the recognition of functions in header files from two different AST.
965
966#define DEBUG_HAS_SAME_SCOPE 0
967
968#if DEBUG_HAS_SAME_SCOPE
969 printf ("In SageInterface::hasSameGlobalScope(): \n");
970 printf (" --- statement_1 = %p = %s \n",statement_1,statement_1->class_name().c_str());
971 printf (" --- statement_2 = %p = %s \n",statement_2,statement_2->class_name().c_str());
972#endif
973
974 bool includingSelf = true;
975 SgGlobal* global_scope_1 = getEnclosingNode<SgGlobal>(statement_1,includingSelf);
976 SgGlobal* global_scope_2 = getEnclosingNode<SgGlobal>(statement_2,includingSelf);
977
978#if DEBUG_HAS_SAME_SCOPE
979 printf (" --- global_scope_1 = %p = %s \n",global_scope_1,global_scope_1->class_name().c_str());
980 SgSourceFile* sourcefile_1 = isSgSourceFile(global_scope_1->get_parent());
981 printf (" --- --- sourcefile_1 = %p filename = %s \n",sourcefile_1,sourcefile_1->getFileName().c_str());
982
983 printf (" --- global_scope_2 = %p = %s \n",global_scope_2,global_scope_2->class_name().c_str());
984 SgSourceFile* sourcefile_2 = isSgSourceFile(global_scope_2->get_parent());
985 printf (" --- --- sourcefile_2 = %p filename = %s \n",sourcefile_2,sourcefile_2->getFileName().c_str());
986#endif
987
988 bool returnResult = (global_scope_1 == global_scope_2);
989
990#if DEBUG_HAS_SAME_SCOPE
991 printf ("Leaving SageInterface::hasSameGlobalScope(): returning: %s \n",returnResult ? "true" : "false");
992#endif
993
994 return returnResult;
995 }
996
997
998std::vector<SgNode*>
1000 {
1001 std::vector<SgNode*> intersectionSet;
1002
1003 // Collect all the IR nodes for the original AST
1004 std::vector<SgNode*> AST_original = NodeQuery::querySubTree (original,V_SgNode);
1005 std::vector<SgNode*> AST_copy = NodeQuery::querySubTree (copy,V_SgNode);
1006
1007 int AST_original_size = AST_original.size();
1008 int AST_copy_size = AST_copy.size();
1009
1010 if (SgProject::get_verbose() > 0)
1011 {
1012 printf ("Original AST size = %d \n",AST_original_size);
1013 printf ("Copy of original AST size = %d \n",AST_copy_size);
1014 }
1015
1016 int differenceInSizes = AST_original_size - AST_copy_size;
1017 if (differenceInSizes == 0)
1018 {
1019 if (SgProject::get_verbose() > 0)
1020 printf ("Copied AST is the SAME size as the original (size = %d) \n",AST_original_size);
1021 }
1022 else
1023 {
1024 printf ("Warning: Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) \n",AST_original_size,AST_copy_size);
1025 }
1026
1027 // Compute the intersection (reference in the copy that point to the origal AST).
1028 // std::set<SgNode*> AST_set_original = AST_original;
1029 std::set<SgNode*> AST_set_original;
1030 for (int i = 0; i < AST_original_size; i++)
1031 {
1032 AST_set_original.insert(AST_original[i]);
1033 }
1034
1035 std::set<SgNode*> AST_set_copy;
1036 for (int i = 0; i < AST_copy_size; i++)
1037 {
1038 AST_set_copy.insert(AST_copy[i]);
1039 }
1040
1041 int size = AST_original_size;
1042 std::vector<SgNode*> intersectionList(size);
1043
1044 // Is there a better way to do this? Build scratch space and then use the different between begin() and end to build another vector.
1045 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());
1046
1047 // Build a new vector from the relevant elements of the intersectionList scratch space.
1048 std::vector<SgNode*> meaningIntersectionList = std::vector<SgNode*>(intersectionList.begin(),end);
1049 std::vector<SgNode*> deleteList;
1050 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1051 {
1052 if (meaningIntersectionList[i] != nullptr && isSgType(meaningIntersectionList[i]) != nullptr)
1053 {
1054 deleteList.push_back(meaningIntersectionList[i]);
1055 }
1056 }
1057
1058 // Remove the types since they are allowed to be shared...
1059 if (SgProject::get_verbose() > 0)
1060 printf ("Remove the types that are allowed to be shared: deleteList.size() = %ld \n",(long)deleteList.size());
1061
1062 for (std::vector<SgNode*>::iterator i = deleteList.begin(); i != deleteList.end(); i++)
1063 {
1064 meaningIntersectionList.erase(find(meaningIntersectionList.begin(),meaningIntersectionList.end(),*i));
1065 }
1066
1067 if (SgProject::get_verbose() > 0)
1068 printf ("After removing the types there are meaningIntersectionList.size() = %ld \n",(long)meaningIntersectionList.size());
1069
1070 for (int i = 0; i < (int)meaningIntersectionList.size(); i++)
1071 {
1072 printf (" meaningIntersectionList[%d] = %p = %s = %s \n",i,meaningIntersectionList[i],meaningIntersectionList[i]->class_name().c_str(),get_name(meaningIntersectionList[i]).c_str());
1073 }
1074
1075 int unmatchedIRnodes = 0;
1076 if (help != nullptr)
1077 {
1078 std::vector<SgNode*> tmp_AST_original; // = AST_original;
1079 std::vector<SgNode*> tmp_AST_copy; // = AST_copy;
1080
1081 int AST_original_size = AST_original.size();
1082 for (int j = 0; j < AST_original_size; j++)
1083 {
1084 if (AST_original[j] != NULL && isSgType(AST_original[j]) == NULL)
1085 {
1086 tmp_AST_original.push_back(AST_original[j]);
1087 }
1088 }
1089
1090 int AST_copy_size = AST_copy.size();
1091 for (int j = 0; j < AST_copy_size; j++)
1092 {
1093 if (AST_copy[j] != NULL && isSgType(AST_copy[j]) == NULL)
1094 {
1095 tmp_AST_copy.push_back(AST_copy[j]);
1096 }
1097 }
1098
1099 std::vector<SgNode*> deleteList_original;
1100 std::vector<SgNode*> deleteList_copy;
1101 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1102 {
1103 // printf (" (before removing types) meaningIntersectionList[%d] = %p = %s \n",i,meaningIntersectionList[i],(meaningIntersectionList[i] != NULL) ? meaningIntersectionList[i]->class_name().c_str() : "NULL");
1104 SgCopyHelp::copiedNodeMapTypeIterator i = help->get_copiedNodeMap().find(tmp_AST_original[j]);
1105 // printf ("SgCopyHelp::copiedNodeMapTypeIterator i != help->get_copiedNodeMap().end() = %s \n",i != help->get_copiedNodeMap().end() ? "true" : "false");
1106 if (i != help->get_copiedNodeMap().end())
1107 {
1108 // Matched up an original IR node with it's copy
1109 SgNode* associated_node_copy = i->second;
1110 ROSE_ASSERT(associated_node_copy != NULL);
1111 deleteList_original.push_back(tmp_AST_original[j]);
1112 deleteList_copy.push_back(associated_node_copy);
1113#if 0
1114 // printf ("Original IR node = %p = %s copy = %p \n",tmp_AST_original[j],tmp_AST_original[j]->class_name().c_str(),associated_node_copy);
1115 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(tmp_AST_original[j]);
1116 SgTemplateInstantiationMemberFunctionDecl* templateMemberFunction_copy = isSgTemplateInstantiationMemberFunctionDecl(associated_node_copy);
1117 if (templateMemberFunction != NULL)
1118 {
1119 printf ("In SageInterface::astIntersection(): Found a SgTemplateInstantiationMemberFunctionDecl = %p copy = %p \n",templateMemberFunction,associated_node_copy);
1120 // templateMemberFunction->get_startOfConstruct()->display("original: debug");
1121 // templateMemberFunction_copy->get_startOfConstruct()->display("copy: debug");
1122 }
1123#endif
1124 }
1125 }
1126
1127 int deleteList_original_size = deleteList_original.size();
1128 for (int j = 0; j < deleteList_original_size; j++)
1129 {
1130 // tmp_AST_original.erase(find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]));
1131 std::vector<SgNode*>::iterator k = find(tmp_AST_original.begin(),tmp_AST_original.end(),deleteList_original[j]);
1132 if (k != tmp_AST_original.end())
1133 {
1134 tmp_AST_original.erase(k);
1135 }
1136 }
1137
1138 if (SgProject::get_verbose() > 0)
1139 printf ("IR nodes different between the original AST and the copy of the AST = %" PRIuPTR " \n",tmp_AST_original.size());
1140
1141 for (int j = 0; j < (int)tmp_AST_original.size(); j++)
1142 {
1143 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());
1144 // tmp_AST_original[j]->get_startOfConstruct()->display("debug");
1145 }
1146
1147 unmatchedIRnodes = (int)tmp_AST_original.size();
1148 }
1149
1150 // DQ (11/2/2007): Make this an error now!
1151 if (differenceInSizes != 0)
1152 {
1153 SgProject* originalProject = isSgProject(original);
1154 if (originalProject != NULL)
1155 {
1156 printf ("In %s Copied AST and the original are DIFFERENT sizes (original size = %d copyied size = %d) IR nodes different = %d \n",
1157 (*originalProject)[0]->get_sourceFileNameWithoutPath().c_str(),AST_original_size,AST_copy_size,unmatchedIRnodes);
1158 }
1159
1160 if (unmatchedIRnodes > 0)
1161 {
1162 printf ("Make this an error under stricter testing \n");
1163 ROSE_ABORT();
1164 }
1165 }
1166
1167 return intersectionSet;
1168 }
1169
1170// AJ (10/21/2004): Added support for changing the symbol name associated with an SgInitializedName
1171// by updating the symbol table
1172int
1173SageInterface::set_name ( SgInitializedName *initializedNameNode, SgName new_name )
1174 {
1175 // find the appropriate symbol table, delete the symbol
1176 // with the old name and add a symbol with the new name.
1177 ROSE_ASSERT(initializedNameNode != NULL);
1178
1179#define DEBUG_SET_NAME 0
1180
1181 // SgNode * node = this;
1182#if DEBUG_SET_NAME
1183 printf ("In SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1184#endif
1185
1186#if 0
1187 // DQ (12/9/2004): This should likely call the get_scope function (which is more robust than traversing
1188 // parents, there is a reason why we are forced to include the scope explicitly on some IR nodes,
1189 // see test2004_133.C for details).
1190 while((node!=NULL) && ( isSgScopeStatement(node)==NULL))
1191 node = node->get_parent();
1192
1193 ROSE_ASSERT(node!=NULL);
1194
1195 SgScopeStatement * scope_stmt = isSgScopeStatement(node);
1196#else
1197 SgScopeStatement *scope_stmt = initializedNameNode->get_scope();
1198#endif
1199
1200 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1201 if (isSgEnumDeclaration(initializedNameNode->get_parent()) != NULL)
1202 {
1203 ROSE_ASSERT(scope_stmt != NULL);
1204 printf ("scope_stmt = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1205#if 0
1206 printf ("Detected isSgEnumDeclaration as parent: exiting as a test in SageInterface::set_name() \n");
1207 ROSE_ASSERT(false);
1208#endif
1209 }
1210
1211 ROSE_ASSERT(scope_stmt != NULL);
1212 ROSE_ASSERT(scope_stmt->get_symbol_table() != NULL);
1213 ROSE_ASSERT(scope_stmt->get_symbol_table()->get_table() != NULL);
1214
1215 SgDeclarationStatement * parent_declaration = initializedNameNode->get_declaration();
1216
1217 ROSE_ASSERT(parent_declaration != NULL);
1218
1219 // Find the symbols associated with p_name
1220 std::pair<SgSymbolTable::hash_iterator,SgSymbolTable::hash_iterator> pair_it = scope_stmt->get_symbol_table()->get_table()->equal_range(initializedNameNode->get_name());
1221
1222 SgSymbolTable::hash_iterator found_it = scope_stmt->get_symbol_table()->get_table()->end();
1223
1224 for (SgSymbolTable::hash_iterator it = pair_it.first; it != pair_it.second; ++it)
1225 {
1226#if DEBUG_SET_NAME
1227 printf ("Looking for symbol in scope = %p = %s \n",scope_stmt,scope_stmt->class_name().c_str());
1228 printf (" --- *it = %p = %s \n",(*it).second,(*it).second->class_name().c_str());
1229#endif
1230 switch(parent_declaration->variantT())
1231 {
1232 case V_SgFunctionParameterList:
1233 case V_SgVariableDeclaration:
1234 {
1235 if (isSgVariableSymbol((*it).second) != NULL)
1236 found_it = it;
1237 break;
1238 }
1239
1240 case V_SgClassDeclaration:
1241 {
1242 if (isSgClassSymbol((*it).second) != NULL)
1243 found_it = it;
1244 break;
1245 }
1246
1247 case V_SgFunctionDeclaration:
1248 {
1249 if (isSgFunctionSymbol((*it).second) != NULL)
1250 found_it = it;
1251 break;
1252 }
1253
1254 // DQ (2/4/2021): Adding support for enum values (in SgEnumDeclarations).
1255 case V_SgEnumDeclaration:
1256 {
1257 if (isSgEnumFieldSymbol((*it).second) != NULL)
1258 found_it = it;
1259 break;
1260 }
1261
1262 default:
1263 {
1264 printf ("Default reached in switch in SageInterface::set_name() \n");
1265 }
1266 };
1267 }
1268
1269 // there is no Variable, Class or Function symbol associated with p_name
1270 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1271 {
1272 printf ("Warning: There is no Variable, Class, Function, or EnumValue symbol associated with p_name \n");
1273 return 0;
1274 }
1275
1276 // DQ (11/12/2018): In general, this can't be tested if we permit it to be transformed.
1277 if (statementCanBeTransformed(parent_declaration) == false)
1278 {
1279 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");
1280 return 0;
1281 }
1282 else
1283 {
1284#if DEBUG_SET_NAME
1285 printf ("In SageInterface::set_name(): This statement can be transformed! parent_declaration = %p = %s \n",parent_declaration,get_name(parent_declaration).c_str());
1286#endif
1287
1288#if 0
1289 // DQ (11/12/2018): Initial test problem should not permit a transformation!
1290 printf ("Exiting as a test! \n");
1291 ROSE_ABORT();
1292#endif
1293 }
1294
1295 SgSymbol * associated_symbol = (*found_it).second;
1296
1297 // erase the name from there
1298 scope_stmt->get_symbol_table()->get_table()->erase(found_it);
1299
1300 // insert the new_name in the symbol table
1301// CH (4/9/2010): Use boost::unordered instead
1302//#ifdef _MSCx_VER
1303#if 0
1304 // DQ (11/28/2009): Unclear if this code is a problem (testing).
1305
1306// CH (4/7/2010): It seems that the following code can be compiled under MSVC 9.0
1307//#pragma message ("WARNING: this code does not apprear to compile with MSVC.")
1308// printf ("ERROR: this code does not apprear to compile with MSVC. \n");
1309// ROSE_ASSERT(false);
1310 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1311#else
1312 found_it = scope_stmt->get_symbol_table()->get_table()->insert(pair<SgName,SgSymbol*> ( new_name,associated_symbol));
1313#endif
1314 // if insertion failed
1315 if (found_it == scope_stmt->get_symbol_table()->get_table()->end())
1316 {
1317 printf ("Warning: insertion of new symbol failed \n");
1318 return 0;
1319 }
1320
1321#if DEBUG_SET_NAME
1322 // Set the p_name to the new_name
1323 printf ("Reset initializedNameNode->get_name() = %s to new_name = %s \n",initializedNameNode->get_name().str(),new_name.str());
1324#endif
1325
1326 // p_name = new_name;
1327 initializedNameNode->set_name(new_name);
1328
1329 // DQ (11/30/2018): Mark the enclosing statement as modified, so that it will be recognized
1330 // in the header file unparsing as being a header file that should be unparsed.
1331 SgStatement* enclosingStatement = getEnclosingStatement(initializedNameNode);
1332 ROSE_ASSERT(enclosingStatement != NULL);
1333 enclosingStatement->set_isModified(true);
1334 enclosingStatement->setTransformation();
1335
1336 // Invalidate the p_iterator, p_no_name and p_name data members in the Symbol table
1337
1338#if 1
1339 // Search the AST for references to this SgInitializedName (SgVarRefExp), check if the symbol matches
1340 // (we can do this since we only reused the exisitng symbol), and mark those expressions as modified.
1341 class RoseVisitor : public ROSE_VisitTraversal
1342 {
1343 public:
1344 int counter;
1345 SgSymbol* symbol;
1346
1348 void visit (SgNode* node)
1349 {
1350 SgVarRefExp* varRefExp = isSgVarRefExp(node);
1351 SgVariableSymbol* variableSymbol = isSgVariableSymbol(symbol);
1352
1353 ROSE_ASSERT(varRefExp != NULL);
1354 ROSE_ASSERT(variableSymbol != NULL);
1355
1356 if (varRefExp->get_symbol() == variableSymbol)
1357 {
1358#if DEBUG_SET_NAME
1359 printf ("In SageInterface::set_name(): Found associated SgVarRefExp varRefExp = %p to symbol associated_symbol = %p \n",varRefExp,variableSymbol);
1360#endif
1361#if 0
1362 printf ("Exiting as a test! \n");
1363 ROSE_ABORT();
1364#endif
1365 varRefExp->set_isModified(true);
1366 varRefExp->setTransformation();
1367#if 1
1368 // DQ (5/2/2021): The traversal over the file will identify the nesting of and transformations in outer (enclosing) IR nodes.
1369 // 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
1370 // special to the case of using the header file unparsing (any maybe the token-based unparsing with the header
1371 // file unparsing, but I think just the header file unparsing).
1372#if 0
1373 printf ("In SageInterface::set_name(): When unparsing header files, we need to set the physical file id to the correct file \n");
1374#endif
1375 // DQ (4/23/2021): I think it is a problem that the statement is not marked as a transformation so that we
1376 // know how to handle it with the token-based unparsing.
1377 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1378 ROSE_ASSERT(associatedStatement != NULL);
1379 associatedStatement->setTransformation();
1380#endif
1381#if 0
1382 // DQ (11/13/2018): Mark the statement associated with this SgVarRefExp (see test9 in UnparseHeaders_tests).
1383 SgStatement* associatedStatement = getEnclosingStatement(varRefExp);
1384 ROSE_ASSERT(associatedStatement != NULL);
1385 // associatedStatement->set_isModified(true);
1386 // associatedStatement->set_containsTransformation(true);
1387 associatedStatement->setTransformation();
1388#endif
1389 }
1390 }
1391
1392 RoseVisitor(SgSymbol* symbol_parmeter) : counter(0), symbol(symbol_parmeter)
1393 {
1394#if 0
1395 printf ("roseVisitor::visit: counter %4d node = %s \n",counter,symbol_parmeter->class_name().c_str());
1396#endif
1397 counter++;
1398 }
1399 };
1400
1401 // RoseVisitor visitor;
1402 // visitor.traverseMemoryPool();
1403 RoseVisitor t1(associated_symbol);
1405#endif
1406
1407#if DEBUG_SET_NAME
1408 printf ("Leaving SageInterface::set_name(): initializedNameNode = %p name = %s new_name = %s (return 1) \n",initializedNameNode,initializedNameNode->get_name().str(),new_name.str());
1409#endif
1410
1411 // DQ (4/23/2021): I think that we should be returning zero for no error
1412 // and one for an error, this function appears to have this detail reversed.
1413 return 1;
1414 }
1415
1416
1417void
1419 {
1420 printf ("In SageInterface::listHeaderFiles(): includeFile filename = %s \n",includeFile->get_filename().str());
1421
1422 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
1423 class PrefixTraversal : public AstSimpleProcessing
1424 {
1425 public:
1426 void visit (SgNode* node)
1427 {
1428 printf ("In listHeaderFiles visit(): node = %p = %s \n",node,node->class_name().c_str());
1429 SgIncludeFile* includeFile = isSgIncludeFile(node);
1430 if (includeFile != NULL)
1431 {
1432 printf ("include file: filename = %s \n",includeFile->get_filename().str());
1433 }
1434 }
1435 };
1436
1437 // Now buid the traveral object and call the traversal (preorder) on the function definition.
1438 PrefixTraversal traversal;
1439 traversal.traverse(includeFile, preorder);
1440
1441 }
1442
1443
1444bool
1446 {
1447 // DQ (5/9/2021): Adding support for detection of statements in a scope that must be unparsed.
1448 // This function supports the token-based unparsing when used with unparsing of header files
1449 // to know when the scope can be unparsed via it's token stream, even though a statement from
1450 // a header file may contain a transformation.
1451 // returns true if there is a statement in the scope that has to be unparsed (is from the same file as the scope).
1452 // returns false if the scope is empty or contains only statements associated with one or more header files.
1453 // When the scope has statements from the same file, then if there is a transformation contained in any of
1454 // those statements then we have to unparse the scope one statement at a time when using the token-based
1455 // unparsing. If the scope has no statements from the same file, then the existance of any statement that
1456 // contains a transformation does not case the statements to be unparsed individually.
1457
1458 ROSE_ASSERT(scope != NULL);
1459 int scope_file_id = scope->get_file_info()->get_physical_file_id();
1460
1461 bool return_value = false;
1462
1463 if (scope->containsOnlyDeclarations() == true)
1464 {
1465 SgDeclarationStatementPtrList & declarationStatementList = scope->getDeclarationList();
1466#if 1
1467 printf ("In scopeHasStatementsFromSameFile(): DeclarationStatementList not implemented \n");
1468#endif
1469#if 1
1470 printf ("declarationStatementList.size() = %zu \n",declarationStatementList.size());
1471#endif
1472 SgDeclarationStatementPtrList::iterator i = declarationStatementList.begin();
1473
1474 while (i != declarationStatementList.end() && return_value == false)
1475 {
1476 SgDeclarationStatement* statement = *i;
1477 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1478
1479 if (statement_file_id == scope_file_id)
1480 {
1481 return_value = true;
1482 }
1483
1484 i++;
1485 }
1486#if 0
1487 printf ("Exiting as a test! \n");
1488 ROSE_ASSERT(false);
1489#endif
1490 }
1491 else
1492 {
1493 SgStatementPtrList & statementList = scope->getStatementList();
1494#if 1
1495 printf ("In scopeHasStatementsFromSameFile(): StatementList not implemented \n");
1496#endif
1497 SgStatementPtrList::iterator i = statementList.begin();
1498
1499 while (i != statementList.end() && return_value == false)
1500 {
1501 SgStatement* statement = *i;
1502 int statement_file_id = statement->get_file_info()->get_physical_file_id();
1503
1504 if (statement_file_id == scope_file_id)
1505 {
1506 return_value = true;
1507 }
1508
1509 i++;
1510 }
1511 }
1512
1513 return return_value;
1514 }
1515
1516
1517namespace
1518{
1519 template <class SageDecl>
1520 std::string genericGetName(SageDecl* dcl)
1521 {
1522 ROSE_ASSERT(dcl);
1523 return dcl->get_name();
1524 }
1525}
1526
1527
1528
1529
1530string
1532 {
1533 string name = "undefined_name";
1534
1535 ROSE_ASSERT(directive != NULL);
1536
1537 name = directive->class_name();
1538
1539#if 1
1540 // I don't think we need this code now!
1541 switch (directive->variantT())
1542 {
1543 // Separate out these cases...
1544 case V_SgIncludeDirectiveStatement:
1545 case V_SgDefineDirectiveStatement:
1546 case V_SgUndefDirectiveStatement:
1547 case V_SgIfdefDirectiveStatement:
1548 case V_SgIfndefDirectiveStatement:
1549 case V_SgDeadIfDirectiveStatement:
1550 case V_SgIfDirectiveStatement:
1551 case V_SgElseDirectiveStatement:
1552 case V_SgElseifDirectiveStatement:
1553 case V_SgLineDirectiveStatement:
1554 case V_SgWarningDirectiveStatement:
1555 case V_SgErrorDirectiveStatement:
1556 case V_SgEmptyDirectiveStatement:
1557 {
1558 name = directive->class_name();
1559 break;
1560 }
1561
1562 // case ClinkageDeclarationStatement:
1563 case V_SgClinkageStartStatement:
1564 case V_SgClinkageEndStatement:
1565 {
1566 name = directive->class_name();
1567 break;
1568 }
1569
1570 case V_SgFortranIncludeLine:
1571 {
1572 name = directive->class_name();
1573 break;
1574 }
1575
1576 default:
1577 // name = "default name (default case reached: not handled)";
1578 printf ("Warning: default case reached in SageInterface::get_name ( const SgC_PreprocessorDirectiveStatement* directive ), directive = %p = %s \n",
1579 directive,directive->class_name().c_str());
1580 ROSE_ABORT();
1581#if 0 // [Robb Matzke 2021-03-24]: unreachable
1582 name = "directive_default_name_case_reached_not_handled";
1583 break;
1584#endif
1585 }
1586#endif
1587
1588 return name;
1589 }
1590
1591string
1593 {
1594 string name = "undefined_name";
1595
1596 ROSE_ASSERT(declaration != NULL);
1597
1598 // DQ (11/23/2008): Handle the case of a Cpp directive...
1599 const SgC_PreprocessorDirectiveStatement* directive = isSgC_PreprocessorDirectiveStatement(declaration);
1600 if (directive != NULL)
1601 {
1602 return SageInterface::get_name (directive);
1603 }
1604
1605 switch (declaration->variantT())
1606 {
1607 case V_SgTemplateMemberFunctionDeclaration:
1608 name = isSgTemplateMemberFunctionDeclaration(declaration)->get_name().str();
1609 break;
1610
1611 case V_SgTemplateFunctionDeclaration:
1612 name = isSgTemplateFunctionDeclaration(declaration)->get_name().str();
1613 break;
1614
1615 case V_SgTemplateClassDeclaration:
1616 name = isSgTemplateClassDeclaration(declaration)->get_name().str();
1617 break;
1618
1619 case V_SgTemplateDeclaration:
1620 name = isSgTemplateDeclaration(declaration)->get_name().str();
1621 break;
1622
1623 case V_SgTemplateInstantiationDecl:
1624 name = isSgTemplateInstantiationDecl(declaration)->get_templateName().str();
1625 break;
1626
1627 case V_SgClassDeclaration:
1628 case V_SgDerivedTypeStatement:
1629 case V_SgJovialTableStatement:
1630 name = isSgClassDeclaration(declaration)->get_name().str();
1631 break;
1632
1633 // Rasmussen (8/2/2019): Added SgJovialDefineDeclaration and SgJovialDirectiveStatement
1634 // I'm not sure class_name() is correct. Probably get_name() should be fixed.
1635 case V_SgJovialDefineDeclaration:
1636 case V_SgJovialDirectiveStatement:
1637 case V_SgJovialCompoolStatement:
1638 name = "__" + declaration->class_name() + "_";
1639 name += StringUtility::numberToString(declaration);
1640 break;
1641
1642 case V_SgJovialLabelDeclaration:
1643 name = isSgJovialLabelDeclaration(declaration)->get_label();
1644 break;
1645
1646 case V_SgEnumDeclaration:
1647 name = isSgEnumDeclaration(declaration)->get_name().str();
1648 break;
1649
1650 // DQ (11/5/2014): Adding support for template typedef declarations (C++11 feature).
1651 case V_SgTemplateInstantiationTypedefDeclaration:
1652 // DQ (11/3/2014): Adding support for template typedef declarations (C++11 feature).
1653 case V_SgTemplateTypedefDeclaration:
1654 case V_SgTypedefDeclaration:
1655 name = isSgTypedefDeclaration(declaration)->get_name().str();
1656 break;
1657
1658 case V_SgFunctionDeclaration:
1659 case V_SgProgramHeaderStatement:
1660 case V_SgProcedureHeaderStatement:
1661 case V_SgMemberFunctionDeclaration:
1662 case V_SgTemplateInstantiationFunctionDecl:
1663 case V_SgTemplateInstantiationMemberFunctionDecl:
1664 case V_SgAdaFunctionRenamingDecl:
1665 case V_SgAdaEntryDecl:
1666 name = isSgFunctionDeclaration(declaration)->get_name().str();
1667 break;
1668
1669 case V_SgNamespaceDeclarationStatement:
1670 name = isSgNamespaceDeclarationStatement(declaration)->get_name().str();
1671 break;
1672
1673 // DQ (2/12/2006): Added support to get name of SgFunctionParameterList
1674 case V_SgFunctionParameterList:
1675 {
1676 // Parents should be set prior to calling these functions (if not we might have to implement that case)
1677 ROSE_ASSERT(declaration->get_parent() != NULL);
1678
1679 if (SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration->get_parent()))
1680 {
1681 name = get_name(functionDeclaration);
1682 }
1683 else if (SgScopeStatement* scopeStmt = isSgScopeStatement(declaration->get_parent()))
1684 {
1685 name = get_name(scopeStmt);
1686 }
1687 else ROSE_ABORT();
1688
1689 name += "_parameter_list_";
1690 break;
1691 }
1692
1693 // DQ (2/10/2012): Added support for template variable declarations (using base class support).
1694 case V_SgTemplateVariableDeclaration:
1695
1696 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1697 case V_SgVariableDeclaration:
1698 {
1699 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1700 // because we use this mechanism to generate names for unnamed structs and enums).
1701 name = "_variable_declaration_";
1702 const SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declaration);
1703 ROSE_ASSERT(variableDeclaration != NULL);
1704 SgInitializedNamePtrList::const_iterator i = variableDeclaration->get_variables().begin();
1705
1706 // Make sure that we have at least one variable in the list
1707 ROSE_ASSERT(i != variableDeclaration->get_variables().end());
1708 do {
1709 // name += string(" ") + string((*i)->get_name().str());
1710 name += string((*i)->get_name().str());
1711 i++;
1712 }
1713 while (i != variableDeclaration->get_variables().end());
1714 break;
1715 }
1716
1717
1718 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1719 case V_SgVariableDefinition:
1720 {
1721 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1722 // because we use this mechanism to generate names for unnamed structs and enums).
1723 name = "_variable_definition_";
1724 const SgVariableDefinition* variableDefinition = isSgVariableDefinition(declaration);
1725 ROSE_ASSERT(variableDefinition != NULL);
1726
1727 // define this in terms of the associated SgInitializedName
1728 ROSE_ASSERT(variableDefinition->get_vardefn() != NULL);
1729 name += get_name(variableDefinition->get_vardefn());
1730 break;
1731 }
1732
1733 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
1734 case V_SgPragmaDeclaration:
1735 {
1736 name = "_pragma_declaration_";
1737 const SgPragmaDeclaration* pragmaDeclaration = isSgPragmaDeclaration(declaration);
1738 ROSE_ASSERT(pragmaDeclaration != NULL);
1739 ROSE_ASSERT(pragmaDeclaration->get_pragma() != NULL);
1740 name += get_name(pragmaDeclaration->get_pragma());
1741 break;
1742 }
1743
1744 // DQ (4/15/2007): Implemented case for using directive statement (forgot this case)
1745 case V_SgUsingDirectiveStatement:
1746 {
1747 name = "_using_directive_statement_";
1748 const SgUsingDirectiveStatement* usingDeclaration = isSgUsingDirectiveStatement(declaration);
1749 ROSE_ASSERT(usingDeclaration != NULL);
1750 ROSE_ASSERT(usingDeclaration->get_namespaceDeclaration() != NULL);
1751 name += get_name(usingDeclaration->get_namespaceDeclaration());
1752 break;
1753 }
1754
1755 // DQ (6/20/2007): Added new case!
1756 case V_SgNamespaceAliasDeclarationStatement:
1757 {
1758 name = "_namespace_alias_directive_statement_";
1759 const SgNamespaceAliasDeclarationStatement* namespaceAliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
1760 ROSE_ASSERT(namespaceAliasDeclaration != NULL);
1761 ROSE_ASSERT(namespaceAliasDeclaration->get_name().is_null() == false);
1762 name += namespaceAliasDeclaration->get_name();
1763 break;
1764 }
1765
1766 // DQ (6/20/2007): Added new case!
1767 case V_SgUsingDeclarationStatement:
1768 {
1769 name = "_using_declaration_statement_";
1770 const SgUsingDeclarationStatement* usingDeclaration = isSgUsingDeclarationStatement(declaration);
1771 ROSE_ASSERT(usingDeclaration != NULL);
1772 if (usingDeclaration->get_declaration() != NULL)
1773 {
1774 name += get_name(usingDeclaration->get_declaration());
1775 }
1776 else
1777 {
1778 ROSE_ASSERT(usingDeclaration->get_initializedName() != NULL);
1779 name += get_name(usingDeclaration->get_initializedName());
1780 }
1781 break;
1782 }
1783
1784 // DQ (6/20/2007): Added new case!
1785 case V_SgTemplateInstantiationDirectiveStatement:
1786 {
1787 name = "_template_instantiation_directive_statement_";
1788 ROSE_ASSERT(declaration != NULL);
1789 const SgTemplateInstantiationDirectiveStatement* templateInstantiationDirective = isSgTemplateInstantiationDirectiveStatement(declaration);
1790 ROSE_ASSERT(templateInstantiationDirective != NULL);
1791 ROSE_ASSERT(templateInstantiationDirective->get_declaration() != NULL);
1792#if 0
1793 printf ("declaration->get_declaration() = %p = %s \n",templateInstantiationDirective->get_declaration(),templateInstantiationDirective->get_declaration()->class_name().c_str());
1794#endif
1795 name += get_name(templateInstantiationDirective->get_declaration());
1796 break;
1797 }
1798
1799 case V_SgCtorInitializerList:
1800 {
1801 name = "_ctor_list_";
1802 const SgCtorInitializerList* ctorDeclaration = isSgCtorInitializerList(declaration);
1803 ROSE_ASSERT(ctorDeclaration != NULL);
1804 ROSE_ASSERT(ctorDeclaration->get_parent() != NULL);
1805 name += get_name(ctorDeclaration->get_parent());
1806 break;
1807 }
1808
1809 // DQ (8/9/2007): Added case for SgAsmStmt
1810 case V_SgAsmStmt:
1811 {
1812 name = "_asm_stmt_";
1813 const SgAsmStmt* asmStatement = isSgAsmStmt(declaration);
1814 ROSE_ASSERT(asmStatement != NULL);
1815 ROSE_ASSERT(asmStatement->get_parent() != NULL);
1816 name += StringUtility::numberToString(const_cast<SgAsmStmt*>(asmStatement));
1817 break;
1818 }
1819
1820 // DQ (8/22/2007): Added case for SgImplicitStatement
1821 case V_SgImplicitStatement:
1822 {
1823 name = "_fortran_implicit_";
1824 const SgImplicitStatement* implicitStatement = isSgImplicitStatement(declaration);
1825 ROSE_ASSERT(implicitStatement != NULL);
1826 ROSE_ASSERT(implicitStatement->get_parent() != NULL);
1827 name += StringUtility::numberToString(const_cast<SgImplicitStatement*>(implicitStatement));
1828 break;
1829 }
1830
1831 // DQ (8/22/2007): Added case for SgNamelistStatement
1832 case V_SgNamelistStatement:
1833 {
1834 name = "_fortran_namelist_";
1835 const SgNamelistStatement* namelistStatement = isSgNamelistStatement(declaration);
1836 ROSE_ASSERT(namelistStatement != NULL);
1837 ROSE_ASSERT(namelistStatement->get_parent() != NULL);
1838 name += StringUtility::numberToString(const_cast<SgNamelistStatement*>(namelistStatement));
1839 break;
1840 }
1841
1842 // DQ (11/21/2007): Added case for SgEquivalenceStatement
1843 case V_SgEquivalenceStatement:
1844 {
1845 name = "_fortran_equivalence_";
1846 const SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(declaration);
1847 ROSE_ASSERT(equivalenceStatement != NULL);
1848 ROSE_ASSERT(equivalenceStatement->get_parent() != NULL);
1849 name += StringUtility::numberToString(const_cast<SgEquivalenceStatement*>(equivalenceStatement));
1850 break;
1851 }
1852
1853
1854 // DQ (11/21/2007): Added case for SgCommonBlock
1855 case V_SgCommonBlock:
1856 {
1857 name = "_fortran_common_block_";
1858 const SgCommonBlock* commonBlockStatement = isSgCommonBlock(declaration);
1859 ROSE_ASSERT(commonBlockStatement != NULL);
1860 ROSE_ASSERT(commonBlockStatement->get_parent() != NULL);
1861 name += StringUtility::numberToString(const_cast<SgCommonBlock*>(commonBlockStatement));
1862 break;
1863 }
1864
1865 // DQ (11/21/2007): Added case for SgImportStatement
1866 case V_SgImportStatement:
1867 {
1868 name = "_fortran_import_stmt_";
1869 const SgImportStatement* importStatement = isSgImportStatement(declaration);
1870 ROSE_ASSERT(importStatement != NULL);
1871 ROSE_ASSERT(importStatement->get_parent() != NULL);
1872 name += StringUtility::numberToString(const_cast<SgImportStatement*>(importStatement));
1873 break;
1874 }
1875
1876 // DQ (11/21/2007): Added case for SgFormatStatement
1877 case V_SgFormatStatement:
1878 {
1879 name = "_fortran_format_stmt_";
1880 const SgFormatStatement* formatStatement = isSgFormatStatement(declaration);
1881 ROSE_ASSERT(formatStatement != NULL);
1882 ROSE_ASSERT(formatStatement->get_parent() != NULL);
1883 name += StringUtility::numberToString(const_cast<SgFormatStatement*>(formatStatement));
1884 break;
1885 }
1886
1887 // DQ (12/27/2007): Added case for SgModuleStatement
1888 case V_SgModuleStatement:
1889 {
1890 name = "_fortran_module_stmt_";
1891 const SgModuleStatement* moduleStatement = isSgModuleStatement(declaration);
1892 ROSE_ASSERT(moduleStatement != NULL);
1893 ROSE_ASSERT(moduleStatement->get_parent() != NULL);
1894 name += StringUtility::numberToString(const_cast<SgModuleStatement*>(moduleStatement));
1895 break;
1896 }
1897
1898 // DQ (12/27/2007): Added case for SgUseStatement
1899 case V_SgUseStatement:
1900 {
1901 name = "_fortran_use_stmt_";
1902 const SgUseStatement* useStatement = isSgUseStatement(declaration);
1903 ROSE_ASSERT(useStatement != NULL);
1904 ROSE_ASSERT(useStatement->get_parent() != NULL);
1905 name += StringUtility::numberToString(const_cast<SgUseStatement*>(useStatement));
1906 break;
1907 }
1908
1909 // DQ (12/28/2007): Added case for SgContainsStatement
1910 case V_SgContainsStatement:
1911 {
1912 name = "_fortran_contains_stmt_";
1913 const SgContainsStatement* containsStatement = isSgContainsStatement(declaration);
1914 ROSE_ASSERT(containsStatement != NULL);
1915 ROSE_ASSERT(containsStatement->get_parent() != NULL);
1916 name += StringUtility::numberToString(const_cast<SgContainsStatement*>(containsStatement));
1917 break;
1918 }
1919
1920 // DQ (1/20/2008): Added case for SgEntryStatement
1921 case V_SgEntryStatement:
1922 {
1923 name = "_fortran_entry_stmt_";
1924 const SgEntryStatement* entryStatement = isSgEntryStatement(declaration);
1925 ROSE_ASSERT(entryStatement != NULL);
1926 ROSE_ASSERT(entryStatement->get_parent() != NULL);
1927 name += StringUtility::numberToString(const_cast<SgEntryStatement*>(entryStatement));
1928 break;
1929 }
1930
1931 // DQ (1/23/2008): Added case for SgAttributeSpecificationStatement
1932 case V_SgAttributeSpecificationStatement:
1933 {
1934 name = "_fortran_attribute_specification_stmt_";
1935 const SgAttributeSpecificationStatement* statement = isSgAttributeSpecificationStatement(declaration);
1936 ROSE_ASSERT(statement != NULL);
1937 ROSE_ASSERT(statement->get_parent() != NULL);
1939 break;
1940 }
1941
1942 case V_SgInterfaceStatement:
1943 {
1944 name = "_fortran_interface_stmt_";
1945 const SgInterfaceStatement* statement = isSgInterfaceStatement(declaration);
1946 ROSE_ASSERT(statement != NULL);
1947 ROSE_ASSERT(statement->get_parent() != NULL);
1948 name += StringUtility::numberToString(const_cast<SgInterfaceStatement*>(statement));
1949 break;
1950 }
1951
1952 case V_SgFortranIncludeLine:
1953 {
1954 name = "_fortran_include_line_stmt_";
1955 const SgFortranIncludeLine* statement = isSgFortranIncludeLine(declaration);
1956 ROSE_ASSERT(statement != NULL);
1957 ROSE_ASSERT(statement->get_parent() != NULL);
1958 name += StringUtility::numberToString(const_cast<SgFortranIncludeLine*>(statement));
1959 break;
1960 }
1961
1962 // DQ (4/16/2011): Added Java import statment support.
1963 case V_SgJavaImportStatement:
1964 {
1965 name = "_java_import_stmt_";
1966 const SgJavaImportStatement* statement = isSgJavaImportStatement(declaration);
1967 ROSE_ASSERT(statement != NULL);
1968 ROSE_ASSERT(statement->get_parent() != NULL);
1969 name += StringUtility::numberToString(const_cast<SgJavaImportStatement*>(statement));
1970 break;
1971 }
1972
1973 case V_SgJavaPackageDeclaration:
1974 {
1975 name = "_java_package_declaration_";
1976 const SgJavaPackageDeclaration* package_declaration = isSgJavaPackageDeclaration(declaration);
1977 ROSE_ASSERT(package_declaration != NULL);
1978 ROSE_ASSERT(package_declaration->get_parent() != NULL);
1979 name += StringUtility::numberToString(const_cast<SgJavaPackageDeclaration*>(package_declaration));
1980 break;
1981 }
1982
1983 case V_SgJavaPackageStatement:
1984 {
1985 name = "_java_package_stmt_";
1986 const SgJavaPackageStatement* statement = isSgJavaPackageStatement(declaration);
1987 ROSE_ASSERT(statement != NULL);
1988 ROSE_ASSERT(statement->get_parent() != NULL);
1989 name += StringUtility::numberToString(const_cast<SgJavaPackageStatement*>(statement));
1990 break;
1991 }
1992
1993 // DQ (1/21/2018): Added case for C++11 SgStaticAssertionDeclaration
1994 case V_SgStaticAssertionDeclaration:
1995 {
1996 name = "_static_assertion_declaration_stmt_";
1997 const SgStaticAssertionDeclaration* statement = isSgStaticAssertionDeclaration(declaration);
1998 ROSE_ASSERT(statement != NULL);
1999 ROSE_ASSERT(statement->get_parent() != NULL);
2000 name += StringUtility::numberToString(const_cast<SgStaticAssertionDeclaration*>(statement));
2001 break;
2002 }
2003
2004 case V_SgNonrealDecl:
2005 {
2006 const SgNonrealDecl * nrdecl = isSgNonrealDecl(declaration);
2007 ROSE_ASSERT(nrdecl != NULL);
2008 name = nrdecl->get_name();
2009 break;
2010 }
2011
2012 // DQ (3/26/2019): Adding support for new declaration.
2013 case V_SgEmptyDeclaration:
2014 {
2015 const SgEmptyDeclaration * emptyDeclaration = isSgEmptyDeclaration(declaration);
2016 ROSE_ASSERT(emptyDeclaration != NULL);
2017 name = string("emptyDeclaration") + StringUtility::numberToString(const_cast<SgDeclarationStatement*>(declaration));
2018 break;
2019 }
2020
2021 case V_SgAdaPackageSpecDecl:
2022 {
2023 name = genericGetName(isSgAdaPackageSpecDecl(declaration));
2024 break;
2025 }
2026
2027 case V_SgAdaPackageBodyDecl:
2028 {
2029 name = genericGetName(isSgAdaPackageBodyDecl(declaration));
2030 break;
2031 }
2032
2033 case V_SgAdaFormalTypeDecl:
2034 {
2035 name = genericGetName(isSgAdaFormalTypeDecl(declaration));
2036 break;
2037 }
2038
2039 case V_SgAdaGenericDecl:
2040 {
2041 // need to look inside the declaration wrapped by the generic.
2042 const SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(declaration);
2043 name = get_name(gendcl->get_declaration());
2044 break;
2045#if OBSOLETE_CODE
2046 if (isSgFunctionDeclaration(dcl->get_declaration())) {
2047 name = "_ada_generic_decl_" + genericGetName(isSgFunctionDeclaration(dcl->get_declaration()));
2048 break;
2049 }
2050 if (isSgAdaPackageSpecDecl(dcl->get_declaration())) {
2051 name = "_ada_generic_decl_" + genericGetName(isSgAdaPackageSpecDecl(dcl->get_declaration()));
2052 break;
2053 }
2054
2055 // something malformed in the tree if we get here
2056 ROSE_ABORT();
2057 break;
2058#endif /* OBSOLETE_CODE */
2059 }
2060
2061 case V_SgAdaDiscriminatedTypeDecl:
2062 {
2063 const SgAdaDiscriminatedTypeDecl* dcl = isSgAdaDiscriminatedTypeDecl(declaration);
2064 ROSE_ASSERT(dcl);
2065
2066 if (const SgDeclarationStatement* discrDcl = dcl->get_discriminatedDecl())
2067 {
2068 name = get_name(discrDcl);
2069 }
2070 else
2071 {
2072 name = "_incomplete_Ada_discriminated_type_";
2073 }
2074
2075 break;
2076 }
2077
2078 case V_SgAdaVariantDecl:
2079 {
2080 name = "_ada_variant_decl_";
2081 break;
2082 }
2083
2084 case V_SgAdaAttributeClause:
2085 {
2086 name = "_ada_attribute_clause_";
2087 break;
2088 }
2089
2090 case V_SgAdaRepresentationClause:
2091 {
2092 name = "_ada_representation_clause_";
2093 break;
2094 }
2095
2096 case V_SgAdaEnumRepresentationClause:
2097 {
2098 name = "_ada_enum_representation_clause_";
2099 break;
2100 }
2101
2102 case V_SgAdaComponentClause:
2103 {
2104 name = "_ada_component_clause_";
2105 break;
2106 }
2107
2108 case V_SgAdaTaskTypeDecl:
2109 {
2110 name = genericGetName(isSgAdaTaskTypeDecl(declaration));
2111 break;
2112 }
2113
2114 case V_SgAdaProtectedTypeDecl:
2115 {
2116 name = genericGetName(isSgAdaProtectedTypeDecl(declaration));
2117 break;
2118 }
2119
2120 case V_SgAdaTaskBodyDecl:
2121 {
2122 name = genericGetName(isSgAdaTaskBodyDecl(declaration));
2123 break;
2124 }
2125
2126 case V_SgAdaProtectedBodyDecl:
2127 {
2128 name = genericGetName(isSgAdaProtectedBodyDecl(declaration));
2129 break;
2130 }
2131
2132 case V_SgAdaRenamingDecl:
2133 {
2134 name = genericGetName(isSgAdaRenamingDecl(declaration));
2135 break;
2136 }
2137
2138 case V_SgAdaTaskSpecDecl:
2139 {
2140 name = genericGetName(isSgAdaTaskSpecDecl(declaration));
2141 break;
2142 }
2143
2144 case V_SgAdaProtectedSpecDecl:
2145 {
2146 name = genericGetName(isSgAdaProtectedSpecDecl(declaration));
2147 break;
2148 }
2149
2150 case V_SgAdaGenericInstanceDecl:
2151 {
2152 name = genericGetName(isSgAdaGenericInstanceDecl(declaration));
2153 break;
2154 }
2155
2156 case V_SgAdaFormalPackageDecl:
2157 {
2158 name = genericGetName(isSgAdaFormalPackageDecl(declaration));
2159 break;
2160 }
2161
2162 case V_SgAdaParameterList:
2163 {
2164 const SgAdaParameterList* plst = isSgAdaParameterList(declaration);
2165 ROSE_ASSERT(plst);
2166
2167 name = std::accumulate( plst->get_parameters().begin(), plst->get_parameters().end(),
2168 std::string{"_ada_parameter_list_"},
2169 [](std::string n, SgDeclarationStatement* rhs) -> std::string
2170 {
2171 n += SageInterface::get_name(rhs);
2172 return n;
2173 }
2174 );
2175 break;
2176 }
2177
2178 // Note that the case for SgVariableDeclaration is not implemented
2179 default:
2180 printf ("Warning: default case reached in SageInterface::get_name ( const SgDeclarationStatement* declaration ), declaration = %p = %s \n",
2181 declaration,declaration->class_name().c_str());
2182 ROSE_ABORT();
2183 }
2184
2185 return name;
2186 }
2187
2188string
2190 {
2191 string name = "undefined_name";
2192
2193 ROSE_ASSERT(scope != NULL);
2194
2195 switch (scope->variantT())
2196 {
2197 // DQ (6/11/2011): Added support for new template IR nodes.
2198 case V_SgTemplateClassDefinition:
2199 name = get_name(isSgTemplateClassDefinition(scope)->get_declaration());
2200 break;
2201
2202 case V_SgClassDefinition:
2203 case V_SgTemplateInstantiationDefn:
2204 name = get_name(isSgClassDefinition(scope)->get_declaration());
2205 break;
2206
2207 // DQ (9/8/2012): Added missing case for SgTemplateFunctionDefinition.
2208 case V_SgTemplateFunctionDefinition:
2209 case V_SgFunctionDefinition:
2210 name = get_name(isSgFunctionDefinition(scope)->get_declaration());
2211 break;
2212
2213 case V_SgNamespaceDefinitionStatement:
2214 name = get_name(isSgNamespaceDefinitionStatement(scope)->get_namespaceDeclaration());
2215 break;
2216 case V_SgJavaLabelStatement:
2217 name = (isSgJavaLabelStatement(scope)->get_label()).getString();
2218 break;
2219
2220 // DQ (7/18/2017): Added support for the new declaration scope.
2221 case V_SgDeclarationScope:
2222
2223 // DQ (11/30/2007): Added more fortran support.
2224 case V_SgAssociateStatement:
2225 case V_SgJavaForEachStatement:
2226
2227 case V_SgFunctionParameterScope:
2228 case V_SgAdaPackageSpec:
2229 case V_SgAdaPackageBody:
2230 case V_SgAdaTaskSpec:
2231 case V_SgAdaTaskBody:
2232 case V_SgAdaProtectedSpec:
2233 case V_SgAdaProtectedBody:
2234 case V_SgAdaGenericDefn:
2235 case V_SgAdaAcceptStmt:
2236 case V_SgJovialForThenStatement: //Rasmussen: Jovial for statement
2237 case V_SgMatlabForStatement: //SK: Matlab for statement
2238 case V_SgBasicBlock:
2239 case V_SgCatchOptionStmt:
2240 case V_SgDoWhileStmt:
2241 case V_SgForStatement:
2242 case V_SgGlobal:
2243 case V_SgIfStmt:
2244 case V_SgSwitchStatement:
2245 case V_SgWhileStmt:
2246 case V_SgFortranDo:
2247 case V_SgForAllStatement:
2248 case V_SgRangeBasedForStatement:
2249 name = StringUtility::numberToString(const_cast<SgScopeStatement*>(scope));
2250 break;
2251
2252 default:
2253 printf ("Error: undefined case (SgScopeStatement) in SageInterface::get_name(): node = %s \n",scope->class_name().c_str());
2254 ROSE_ABORT();
2255 }
2256
2257 return name;
2258 }
2259
2260string
2262 {
2263 string name = "undefined_name";
2264
2265 ROSE_ASSERT(stmt != NULL);
2266
2267 const SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
2268 if (declaration != NULL)
2269 {
2270 name = get_name(declaration);
2271 }
2272 else
2273 {
2274 const SgScopeStatement* scope = isSgScopeStatement(stmt);
2275 if (scope != NULL)
2276 {
2277 name = get_name(scope);
2278 }
2279 else
2280 {
2281 // DQ (10/25/2007): This is better since it names the SgLabelStatement case
2282 switch (stmt->variantT())
2283 {
2284#if 0
2285 case V_SgBreakStmt:
2286 case V_SgCaseOptionStmt:
2287 case V_SgCatchStatementSeq:
2288 case V_SgClinkageStartStatement:
2289 case V_SgContinueStmt:
2290 case V_SgDefaultOptionStmt:
2291 case V_SgExprStmt:
2292 case V_SgForInitStmt:
2293 case V_SgFunctionTypeTable:
2294 case V_SgGotoStatement:
2295 case V_SgReturnStmt:
2296 case V_SgSpawnStmt:
2297 case V_SgTryStmt:
2298 name = stmt->class_name();
2299 break;
2300#endif
2301 case V_SgLabelStatement:
2302 {
2303 const SgLabelStatement* labelStatement = isSgLabelStatement(stmt);
2304 name = labelStatement->get_label().str();
2305 break;
2306 }
2307
2308 default:
2309 {
2310 // printf ("Default reached in switch \n");
2311 // name = "default name";
2312 name = stmt->class_name();
2313 break;
2314 }
2315 }
2316 }
2317 }
2318
2319 return name;
2320 }
2321
2322string
2324 {
2325 // This function is useful for debugging
2326 // This is the most general case of a function to return a name for an IR node.
2327 ROSE_ASSERT(node != NULL);
2328
2329 string name = "undefined_name";
2330
2331 ROSE_ASSERT(node != NULL);
2332
2333 switch (node->variantT())
2334 {
2335 case V_SgInitializedName:
2336 {
2337 const SgInitializedName* initializedName = isSgInitializedName(node);
2338 if (initializedName != NULL)
2339 {
2340 name = initializedName->get_name().str();
2341 }
2342 break;
2343 }
2344#if 1
2345 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
2346 case V_SgPragma:
2347 {
2348 name = "_pragma_string_";
2349 const SgPragma* pragma = isSgPragma(node);
2350 ROSE_ASSERT(pragma != NULL);
2351 name += pragma->get_pragma();
2352 break;
2353 }
2354#endif
2355
2356 // DQ (5/31/2007): Implemented case for SgProject
2357 case V_SgProject:
2358 {
2359 name = "_project_";
2360 break;
2361 }
2362
2363 // DQ (5/31/2007): Implemented case for SgFile
2364 // case V_SgFile:
2365 case V_SgSourceFile:
2366#ifdef ROSE_ENABLE_BINARY_ANALYSIS
2367 case V_SgBinaryComposite:
2368#endif
2369 {
2370 name = "_file_";
2371
2372 // DQ (3/1/2009): Added support to include the file name.
2373 const SgFile* file = isSgFile(node);
2374 ROSE_ASSERT(file != NULL);
2375
2376 name += file->getFileName();
2377 break;
2378 }
2379
2380 // DQ (5/31/2007): Implemented case for SgSymbolTable
2381 case V_SgSymbolTable:
2382 {
2383 name = "_symbol_table_";
2384 break;
2385 }
2386
2387 // DQ (5/31/2007): Implemented case for SgStorageModifier
2388 case V_SgStorageModifier:
2389 {
2390 name = "_storage_modifier_";
2391 break;
2392 }
2393
2394
2395 // DQ (5/31/2007): Implemented case for Sg_File_Info
2396 case V_Sg_File_Info:
2397 {
2398 name = "_file_info_";
2399 break;
2400 }
2401
2402 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2403 case V_SgTemplateArgument:
2404 {
2405 name = "_template_argument_";
2406 const SgTemplateArgument* templateArgument = isSgTemplateArgument(node);
2407 ROSE_ASSERT(templateArgument != NULL);
2408 switch(templateArgument->get_argumentType())
2409 {
2411 {
2412 SgType* t = templateArgument->get_type();
2413 ROSE_ASSERT(t != NULL);
2414 name += get_name(t);
2415 break;
2416 }
2417
2419 {
2420 SgExpression* t = templateArgument->get_expression();
2421
2422 // DQ (8/11/2013): Adding support for including an initializedName instead of an expression (for template parameters used as expressions).
2423 // ROSE_ASSERT(t != NULL);
2424 // name += get_name(t);
2425 if (t != NULL)
2426 {
2427 ROSE_ASSERT(templateArgument->get_initializedName() == NULL);
2428 name += get_name(t);
2429 }
2430 else
2431 {
2432 ROSE_ASSERT(t == NULL);
2433 SgInitializedName* initializedName = templateArgument->get_initializedName();
2434 ROSE_ASSERT(initializedName != NULL);
2435
2436 name += get_name(initializedName);
2437 }
2438 break;
2439 }
2440
2442 {
2443 // SgTemplateDeclaration* t = templateArgument->get_templateDeclaration();
2444 SgDeclarationStatement* t = templateArgument->get_templateDeclaration();
2445 ROSE_ASSERT(t != NULL);
2446 name += get_name(t);
2447 break;
2448 }
2449
2450 default:
2451 {
2452 printf ("Error: default case reached in switch on templateArgument->get_argumentType() \n");
2453 ROSE_ABORT();
2454 }
2455 }
2456 break;
2457 }
2458
2459
2460 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2461 case V_SgTypeModifier:
2462 {
2463 const SgTypeModifier* typeModifier = isSgTypeModifier(node);
2464 ROSE_ASSERT(typeModifier != NULL);
2465 name = "_type_modifier_" + typeModifier->displayString();
2466 break;
2467 }
2468
2469 // DQ (11/19/2007): Implemented case for SgNameGroup
2470 case V_SgNameGroup:
2471 {
2472 const SgNameGroup* nameGroup = isSgNameGroup(node);
2473 ROSE_ASSERT(nameGroup != NULL);
2474 name = "_name_group_" + nameGroup->get_group_name();
2475 break;
2476 }
2477
2478 // DQ (11/20/2007): Implemented case for Fortran data statement support
2479 case V_SgDataStatementGroup:
2480 {
2481 const SgDataStatementGroup* dataGroup = isSgDataStatementGroup(node);
2482 ROSE_ASSERT(dataGroup != NULL);
2483 name = "_data_statement_group_";
2484 break;
2485 }
2486
2487 // DQ (11/20/2007): Implemented case for Fortran data statement support
2488 case V_SgDataStatementObject:
2489 {
2490 const SgDataStatementObject* dataObject = isSgDataStatementObject(node);
2491 ROSE_ASSERT(dataObject != NULL);
2492 name = "_data_statement_object_";
2493 break;
2494 }
2495
2496 // DQ (11/20/2007): Implemented case for Fortran data statement support
2497 case V_SgDataStatementValue:
2498 {
2499 const SgDataStatementValue* dataValue = isSgDataStatementValue(node);
2500 ROSE_ASSERT(dataValue != NULL);
2501 name = "_data_statement_value_";
2502 break;
2503 }
2504
2505 // DQ (11/19/2007): Implemented case for SgCommonBlock
2506 case V_SgCommonBlockObject:
2507 {
2508 const SgCommonBlockObject* commonBlockObject = isSgCommonBlockObject(node);
2509 ROSE_ASSERT(commonBlockObject != NULL);
2510 name = "_common_block_object_" + commonBlockObject->get_block_name();
2511 break;
2512 }
2513
2514 // DQ (12/23/2007): Added support for repeat_specification
2515 case V_SgFormatItem:
2516 {
2517 const SgFormatItem* formatItem = isSgFormatItem(node);
2518 ROSE_ASSERT(formatItem != NULL);
2519 name = "_format_item_";
2520 break;
2521 }
2522
2523 // DQ (12/23/2007): Added support for repeat_specification
2524 case V_SgFormatItemList:
2525 {
2526 const SgFormatItemList* formatItemList = isSgFormatItemList(node);
2527 ROSE_ASSERT(formatItemList != NULL);
2528 name = "_format_item_list_";
2529 break;
2530 }
2531
2532 // DQ (12/23/2007): Added support for repeat_specification
2533 case V_SgRenamePair:
2534 {
2535 const SgRenamePair* renamePair = isSgRenamePair(node);
2536 ROSE_ASSERT(renamePair != NULL);
2537 name = renamePair->get_local_name() + "__" + renamePair->get_use_name() + "_rename_pair_";
2538 break;
2539 }
2540
2541 // DQ (12/2/2010): Implemented case for SgName
2542 case V_SgName:
2543 {
2544 const SgName* name_node = isSgName(node);
2545 ROSE_ASSERT(name_node != NULL);
2546 name = "_name_" + name_node->getString();
2547 break;
2548 }
2549
2550 // DQ (8/8/2013): Implemented case for SgTemplateParameter
2551 case V_SgTemplateParameter:
2552 {
2553 const SgTemplateParameter* template_parameter_node = isSgTemplateParameter(node);
2554 ROSE_ASSERT(template_parameter_node != NULL);
2555 name = "_template_parameter_";
2556
2557 switch(template_parameter_node->get_parameterType())
2558 {
2560 {
2561 name += "type_parameter_";
2562 break;
2563 }
2564
2566 {
2567 name += "nontype_parameter_";
2568#if 1
2569 name += template_parameter_node->unparseToString();
2570#else
2571 if (template_parameter_node->get_expression() != NULL)
2572 {
2573 name += template_parameter_node->get_expression()->unparseToString();
2574 }
2575 else
2576 {
2577 ROSE_ASSERT(template_parameter_node->get_initializedName() != NULL);
2578
2579 // DQ (8/8/2013): This does not handle the case of "template <void (foo::*M)()> void test() {}"
2580 // since what is unparsed is: "_template_parameter_nontype_parameter_M"
2581 // instead of a string to represent what is in "void (foo::*M)()"
2582 // and differentiate it from: "int foo::*M" in: "template <void (foo::*M)()> void test() {}"
2583 name += template_parameter_node->get_initializedName()->unparseToString();
2584 }
2585#endif
2586 break;
2587 }
2588
2590 {
2591 name += "template_parameter_";
2592 break;
2593 }
2594
2595 default:
2596 {
2597 printf ("Error: default reached \n");
2598 ROSE_ABORT();
2599 }
2600 }
2601 break;
2602 }
2603
2604 // DQ (1/21/2019): Implemented case for SgBaseClass
2605 case V_SgBaseClass:
2606 {
2607 const SgBaseClass* base_class_node = isSgBaseClass(node);
2608 ROSE_ASSERT(base_class_node != NULL);
2609 ROSE_ASSERT(base_class_node->get_base_class() != NULL);
2610
2611 // Add the access modifier to the output.
2612 string access = "";
2613 const SgBaseClassModifier* baseClassModifier = base_class_node->get_baseClassModifier();
2614 ROSE_ASSERT(baseClassModifier != NULL);
2615 access = baseClassModifier->displayString();
2616
2617 name = "_base_class_" + access + "_" + get_name(base_class_node->get_base_class());
2618 break;
2619 }
2620
2621 default:
2622 {
2623 printf ("Default reached in switch for SgSupport IR node = %s \n",node->class_name().c_str());
2624 name = "default name";
2625 // ROSE_ASSERT(false);
2626 break;
2627 }
2628 }
2629
2630 return name;
2631 }
2632
2633
2634string
2636 {
2637 // This function is useful for debugging
2638 // This is the most general case of a function to return a name for an IR node.
2639 ROSE_ASSERT(symbol != NULL);
2640
2641 string aliasSymbolPrefix = "";
2642 if (isSgAliasSymbol(symbol) != NULL)
2643 {
2644 aliasSymbolPrefix = "_ALIAS";
2645 }
2646
2647 // printf ("In SageInterface::get_name(): symbol->get_symbol_basis() = %p = %s \n",symbol->get_symbol_basis(),symbol->get_symbol_basis()->class_name().c_str());
2648 // printf ("In SageInterface::get_name(): symbol->get_declaration() = %p = %s \n",symbol->get_declaration(),symbol->get_declaration()->class_name().c_str());
2649
2650 // This is a call to the "get_name()" virtual function
2651 return symbol->get_name() + aliasSymbolPrefix + "_symbol_";
2652 }
2653
2654string
2656 {
2657 // This function is useful for debugging
2658 // This is the most general case of a function to return a name for an IR node.
2659 ROSE_ASSERT(type != NULL);
2660
2661 string returnName;
2662
2663 const SgNamedType* namedType = isSgNamedType(type);
2664 if (namedType != NULL)
2665 {
2666 returnName = "named_type_";
2667 returnName = namedType->get_name().getString();
2668 }
2669 else
2670 {
2671 switch(type->variantT())
2672 {
2673 case V_SgPointerType:
2674 {
2675 const SgPointerType* pointerType = isSgPointerType(type);
2676 returnName = "pointer_to_";
2677 returnName += get_name(pointerType->get_base_type());
2678 break;
2679 }
2680
2681 case V_SgReferenceType:
2682 {
2683 const SgReferenceType* referenceType = isSgReferenceType(type);
2684 returnName = "reference_to_";
2685 returnName += get_name(referenceType->get_base_type());
2686 break;
2687 }
2688
2689 case V_SgArrayType:
2690 {
2691 const SgArrayType* arrayType = isSgArrayType(type);
2692 returnName = "array_of_";
2693 returnName += get_name(arrayType->get_base_type());
2694 break;
2695 }
2696
2697 case V_SgModifierType:
2698 {
2699 const SgModifierType* modifierType = isSgModifierType(type);
2700 returnName = get_name(&(modifierType->get_typeModifier()));
2701 returnName += get_name(modifierType->get_base_type());
2702 break;
2703 }
2704
2705 // DQ (8/26/2012): Added case to support template declaration work.
2706 case V_SgTemplateType:
2707 {
2708 const SgTemplateType* templateType = isSgTemplateType(type);
2709 returnName = "templateType_";
2710 returnName += templateType->get_name();
2711 break;
2712 }
2713
2714 default:
2715 {
2716 returnName = type->class_name();
2717 }
2718 }
2719 }
2720
2721 return returnName;
2722 }
2723
2724string
2726 {
2727 string name = "undefined_name";
2728
2729 // ROSE_ASSERT(expr != NULL);
2730 switch(expr->variantT())
2731 {
2732 case V_SgVarRefExp:
2733 {
2734 const SgVarRefExp* varRef = isSgVarRefExp(expr);
2735 name = "var_ref_of_";
2736 ROSE_ASSERT(varRef != NULL);
2737 ROSE_ASSERT(varRef->get_symbol() != NULL);
2738 name += varRef->get_symbol()->get_name();
2739 break;
2740 }
2741
2742 // DQ (2/2/2011): Added case to support fortran use of label references in alternate return parameters.
2743 case V_SgLabelRefExp:
2744 {
2745 const SgLabelRefExp* labelRef = isSgLabelRefExp(expr);
2746 name = "label_ref_of_";
2747 ROSE_ASSERT(labelRef != NULL);
2748 ROSE_ASSERT(labelRef->get_symbol() != NULL);
2749 name += labelRef->get_symbol()->get_name();
2750 break;
2751 }
2752
2753 case V_SgPntrArrRefExp:
2754 {
2755 const SgPntrArrRefExp* arrayRef = isSgPntrArrRefExp(expr);
2756 name = "array_ref_of_";
2757 name += get_name(arrayRef->get_lhs_operand());
2758 name += "_at_";
2759 name += get_name(arrayRef->get_rhs_operand());
2760 break;
2761 }
2762
2763 case V_SgFunctionCallExp:
2764 {
2765 const SgFunctionCallExp* functionCall = isSgFunctionCallExp(expr);
2766 name = "function_call_";
2767 name += get_name(functionCall->get_function());
2768 break;
2769 }
2770
2771 case V_SgFunctionRefExp:
2772 {
2773 const SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(expr);
2774 name = "function_ref_";
2775 name += functionRefExp->get_symbol()->get_name();
2776 break;
2777 }
2778
2779 // DQ (4/19/2013): Added support for SgMemberFunctionRefExp.
2780 case V_SgMemberFunctionRefExp:
2781 {
2782 const SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(expr);
2783 name = "member_function_ref_";
2784 name += memberFunctionRefExp->get_symbol()->get_name();
2785 break;
2786 }
2787
2788 case V_SgIntVal:
2789 {
2790 const SgIntVal* valueExp = isSgIntVal(expr);
2791 name = "integer_value_exp_";
2792 name += StringUtility::numberToString(valueExp->get_value());
2793 break;
2794 }
2795
2796 case V_SgStringVal:
2797 {
2798 const SgStringVal* valueExp = isSgStringVal(expr);
2799 name = "string_value_exp_";
2800 name += valueExp->get_value();
2801 break;
2802 }
2803
2804 case V_SgSubscriptExpression:
2805 {
2806 const SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(expr);
2807 name = "subscript_exp_";
2808 // name += StringUtility::numberToString(subscriptExpression->get_lowerBound());
2809 name += get_name(subscriptExpression->get_lowerBound());
2810 name += "_";
2811 // name += StringUtility::numberToString(subscriptExpression->get_upperBound());
2812 name += get_name(subscriptExpression->get_upperBound());
2813 name += "_";
2814 // name += StringUtility::numberToString(subscriptExpression->get_stride());
2815 name += get_name(subscriptExpression->get_stride());
2816 break;
2817 }
2818
2819 case V_SgNullExpression:
2820 {
2821 name = "null_expression";
2822 break;
2823 }
2824
2825 // DQ (1/17/2011): Added support for SgExprListExp (to support debugging).
2826 case V_SgExprListExp:
2827 {
2828 const SgExprListExp* exprListExp = isSgExprListExp(expr);
2829 name = "expr_list_exp_";
2830 for (size_t i = 0; i < exprListExp->get_expressions().size(); i++)
2831 {
2832 name += get_name(exprListExp->get_expressions()[i]);
2833 }
2834 break;
2835 }
2836
2837 // DQ (1/31/2011): Added to support Fortran debugging.
2838 case V_SgActualArgumentExpression:
2839 {
2840 const SgActualArgumentExpression* actualArgExp = isSgActualArgumentExpression(expr);
2841 name = "actual_arg_exp_name_";
2842 name += actualArgExp->get_argument_name();
2843 name = "_exp_";
2844 name += get_name(actualArgExp->get_expression());
2845 break;
2846 }
2847
2848 // DQ (7/25/2012): Added support for new template IR nodes.
2849 case V_SgTemplateParameterVal:
2850 {
2851 const SgTemplateParameterVal* valueExp = isSgTemplateParameterVal(expr);
2852 name = "template_parameter_value_expression_number_";
2853 // name += valueExp->get_value();
2854 // name += get_name(valueExp);
2855 name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2856 break;
2857 }
2858
2859 // DQ (4/19/2013): Added support for SgDotExp.
2860 case V_SgDotExp:
2861 {
2862 const SgDotExp* dotExp = isSgDotExp(expr);
2863 ROSE_ASSERT(dotExp != NULL);
2864
2865 name = "_dot_exp_lhs_";
2866 name += get_name(dotExp->get_lhs_operand());
2867 name += "_dot_exp_rhs_";
2868 name += get_name(dotExp->get_rhs_operand());
2869 // name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2870 break;
2871 }
2872
2873 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2874 case V_SgLambdaExp:
2875 {
2876 const SgLambdaExp* lambdaExp = isSgLambdaExp(expr);
2877 ROSE_ASSERT (lambdaExp != NULL);
2878 name = "lambda_expression_";
2879 break;
2880 }
2881
2882 // DQ (1/3/2020): Added support for SgThisExp.
2883 case V_SgThisExp:
2884 {
2885 const SgThisExp* thisExp = isSgThisExp(expr);
2886 ROSE_ASSERT(thisExp != NULL);
2887
2888 name = "_this_exp_for_";
2889
2890 SgClassSymbol* classSymbol = thisExp->get_class_symbol();
2891 ROSE_ASSERT(classSymbol != NULL);
2892 // name += get_name(classSymbol->get_name());
2893 // string class_name = classSymbol->get_name();
2894 // name += class_name;
2895 name += classSymbol->get_name();
2896 break;
2897 }
2898
2899 default:
2900 {
2901 // Nothing to do for other IR nodes
2902#if 0
2903 // DQ (7/25/2012): Make this an error.
2904 printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2905 ROSE_ABORT();
2906#endif
2907 // DQ (4/8/2010): define something specific to this function to make debugging more clear.
2908 // printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2909 // name = "undefined_expression_name";
2910 name = expr->class_name() + "_undef_name";
2911 break;
2912 }
2913 }
2914
2915 return name;
2916 }
2917
2918string
2920 {
2921 // This function is useful for debugging
2922 // This is the most general case of a function to return a name for an IR node.
2923 ROSE_ASSERT(node != NULL);
2924
2925 string returnName;
2926
2927 switch(node->variantT())
2928 {
2929 case V_SgRenamePair:
2930 {
2931 const SgRenamePair* n = isSgRenamePair(node);
2932 returnName = "rename_pair_";
2933 returnName += n->get_local_name().str();
2934 returnName += "_from_";
2935 returnName += n->get_use_name().str();
2936 break;
2937 }
2938
2939 case V_SgInitializedName:
2940 {
2941 const SgInitializedName* n = isSgInitializedName(node);
2942 ROSE_ASSERT (n != NULL);
2943 returnName = "initialized_name_";
2944 returnName += n->get_name().str();
2945 break;
2946 }
2947
2948 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2949 case V_SgLambdaCapture:
2950 {
2951 const SgLambdaCapture* n = isSgLambdaCapture(node);
2952 ROSE_ASSERT (n != NULL);
2953 returnName = "lambda_capture_";
2954 // returnName += n->get_name().str();
2955 break;
2956 }
2957
2958#if 0
2959 case V_SgInterfaceBody:
2960 {
2961 const SgInterfaceBody* n = isSgInterfaceBody(node);
2962 returnName = "interface_body";
2963 break;
2964 }
2965#endif
2966 default:
2967 {
2968 returnName = node->class_name();
2969 }
2970 }
2971
2972 return returnName;
2973 }
2974
2975string
2977 {
2978 // This function is useful for debugging
2979 // This is the most general case of a function to return a name for an IR node.
2980 // Later this function will handle expressions, etc.
2981
2982 string name = "undefined_name";
2983
2984 ROSE_ASSERT(node != NULL);
2985
2986 const SgLocatedNode* locatedNode = isSgLocatedNode(node);
2987 if (locatedNode != NULL)
2988 {
2989 const SgStatement* statement = isSgStatement(node);
2990 if (statement != NULL)
2991 {
2992 name = get_name(statement);
2993 }
2994 else
2995 {
2996 const SgExpression* expression = isSgExpression(node);
2997 if (expression != NULL)
2998 {
2999 name = get_name(expression);
3000 }
3001 else
3002 {
3003 const SgLocatedNodeSupport* locatedNodeSupport = isSgLocatedNodeSupport(node);
3004 if (locatedNodeSupport != NULL)
3005 {
3006 name = get_name(locatedNodeSupport);
3007 }
3008 else
3009 {
3010 const SgToken* token = isSgToken(node);
3011 if (token != NULL)
3012 {
3013 name = get_name(token);
3014 }
3015 else
3016 {
3017 printf ("Unknown SgLocatedNode = %p = %s \n",node,node->class_name().c_str());
3018 ROSE_ABORT();
3019 }
3020 }
3021 }
3022 }
3023 }
3024 else
3025 {
3026 const SgSupport* supportNode = isSgSupport(node);
3027 if (supportNode != NULL)
3028 {
3029 name = get_name(supportNode);
3030 }
3031 else
3032 {
3033 // DQ (9/21/2005): I think this is good enough for the more general case (for now)
3034 const SgSymbol* symbol = isSgSymbol(node);
3035 if (symbol != NULL)
3036 {
3037 name = get_name(symbol);
3038 }
3039 else
3040 {
3041 // DQ (8/7/2007): Added support to get names of types (usefult for SgNamedType objects).
3042 const SgType* type = isSgType(node);
3043 if (type != NULL)
3044 {
3045 name = get_name(type);
3046 }
3047 else
3048 {
3049 name = node->class_name();
3050 }
3051 }
3052 }
3053 }
3054
3055 return name;
3056 }
3057
3058
3059string
3061 {
3062 // This function is useful for debugging
3063 string name = "undefined_name";
3064
3065 ROSE_ASSERT(token != NULL);
3066 name = token->get_lexeme_string();
3067
3068 // Handle special cases
3069 if (name == " ")
3070 name = "<space>";
3071 else if (name == "\n")
3072 name = "<eol>";
3073 else if (name == "\t")
3074 name = "<tab>";
3075
3076 return name;
3077 }
3078
3079
3080void
3087
3088
3089string
3091 {
3092 // DQ (3/20/2016): Adding support for generating a unique name from a declaration that
3093 // can be used as an identifier. This functionality is used in the DSL infrastructure
3094 // support (refactored to this location in ROSE). The point of this mechanism is that
3095 // unlike mangled names that are compressed in a way that allows them to only be used
3096 // within a single translation unit, names generated by this function can be used across
3097 // multiple translation units. These names are also easier to interprete in debugging
3098 // (since they explicitly contain the scope, function name, and coding to interprete
3099 // function overloading.
3100
3101 // At present it only supports class declarations, and function declarations (all others
3102 // are trapped as errors).
3103
3104 // Name collision testing, it might be that this should be external to this function.
3105 // static std::map<std::string,int> dsl_attribute_name_collision_map;
3106 // static std::map<std::string,int> local_name_collision_map;
3107
3108 string s;
3109
3110 // string scope = SageInterface::get_name(classDeclaration->get_scope());
3111 string scope = isSgGlobal(declaration->get_scope()) == NULL ? SageInterface::get_name(declaration->get_scope()) : "global";
3112
3113 switch (declaration->variantT())
3114 {
3115 case V_SgClassDeclaration:
3116 case V_SgTemplateClassDeclaration:
3117 // case V_SgTemplateInstantiationDecl:
3118 {
3119 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declaration);
3120 ROSE_ASSERT(classDeclaration != NULL);
3121
3122 string type_name = classDeclaration->get_name();
3123#if 0
3124 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case class or template type: type_name = %s \n",type_name.c_str());
3125#endif
3126 string className = string("scope_") + scope + "_type_name_" + type_name;
3127#if 0
3128 printf ("classDeclaration->get_scope() = %p = %s scope = %s \n",classDeclaration->get_scope(),classDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3129#endif
3130 s = className;
3131 break;
3132 }
3133
3134 // DQ (3/29/2016): Seperate out the case of the SgTemplateInstantiationDecl.
3135 case V_SgTemplateInstantiationDecl:
3136 {
3137 SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(declaration);
3138 ROSE_ASSERT(templateInstantiationDeclaration != NULL);
3139
3140 // Note that we can't use the mangled name because they might not be unique across multiple translation units if seperately compiled).
3141 // string type_name = templateInstantiationDeclaration->get_name();
3142 // string type_name = templateInstantiationDeclaration->get_mangled_name();
3143 // string type_name = templateInstantiationDeclaration->get_templateName();
3144 string type_name = templateInstantiationDeclaration->get_name();
3145#if 0
3146 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgTemplateInstantiationDecl: type_name = %s \n",type_name.c_str());
3147#endif
3148 string className = string("scope_") + scope + "_type_name_" + type_name;
3149
3150 // Note that trimSpaces is defined in the name mangling support.
3151 // string compressedClassName = trimSpaces(className);
3152 // string compressedClassName = SageInterface::get_name(templateInstantiationDeclaration);
3153 // ROSE_UTIL_API std::string copyEdit(const std::string& inputString, const std::string & oldToken, const std::string & newToken);
3154
3155 // We need to turn this template instatiation name into a name that can be used as a C++ identifier.
3156 string compressedClassName = StringUtility::copyEdit(className," ","");
3157 compressedClassName = StringUtility::copyEdit(compressedClassName,"<","_abs_");
3158 compressedClassName = StringUtility::copyEdit(compressedClassName,">","_abe_");
3159 compressedClassName = StringUtility::copyEdit(compressedClassName,",","_comma_");
3160 compressedClassName = StringUtility::copyEdit(compressedClassName,"*","_star_");
3161 compressedClassName = StringUtility::copyEdit(compressedClassName,"&","_ref_");
3162#if 0
3163 printf ("className = %s compressedClassName = %s \n",className.c_str(),compressedClassName.c_str());
3164#endif
3165#if 0
3166 printf ("templateInstantiationDeclaration->get_scope() = %p = %s scope = %s \n",
3167 templateInstantiationDeclaration->get_scope(),templateInstantiationDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3168#endif
3169 // s = className;
3170 s = compressedClassName;
3171#if 0
3172 printf ("Exiting as a test! \n");
3173 ROSE_ABORT();
3174#endif
3175 break;
3176 }
3177
3178 case V_SgFunctionDeclaration:
3179 case V_SgTemplateFunctionDeclaration:
3180 case V_SgTemplateInstantiationFunctionDecl:
3181 {
3182 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration);
3183 ROSE_ASSERT(functionDeclaration != NULL);
3184#if 0
3185 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgFunctionDeclaration: not implemented \n");
3186#endif
3187 // We might at some point want the qualified name.
3188 string original_name = functionDeclaration->get_name();
3189
3190 string function_name_part = mangleFunctionName(original_name,"return_type");
3191 string function_name = string("scope_") + scope + "_function_name_" + function_name_part;
3192
3193 // DQ (3/16/2016): Detect name collisions so that we can
3194 // std::map<std::string,int> dsl_attribute_name_collision_map;
3195 if (local_name_collision_map.find(function_name) == local_name_collision_map.end())
3196 {
3197 local_name_collision_map.insert(pair<string,int>(function_name,0));
3198 }
3199 else
3200 {
3201 local_name_collision_map[function_name]++;
3202
3203 int count = local_name_collision_map[function_name];
3204#if 0
3205 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3206#endif
3207 function_name += StringUtility::numberToString(count);
3208 }
3209
3210 s = function_name;
3211#if 0
3212 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgFunctionDeclaration: Exiting as a test! \n");
3213 ROSE_ABORT();
3214#endif
3215 break;
3216 }
3217
3218 case V_SgMemberFunctionDeclaration:
3219 case V_SgTemplateMemberFunctionDeclaration:
3220 case V_SgTemplateInstantiationMemberFunctionDecl:
3221 {
3222 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(declaration);
3223 ROSE_ASSERT(memberFunctionDeclaration != NULL);
3224#if 0
3225 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgMemberFunctionDeclaration: not implemented \n");
3226#endif
3227 // We might at some point want the qualified name.
3228 string original_name = memberFunctionDeclaration->get_name();
3229
3230 // string member_function_name = memberFunctionDeclaration->get_mangled_name();
3231 // string member_function_name = memberFunctionDeclaration->get_qualified_name();
3232 // string member_function_name = SageInterface::get_name(memberFunctionDeclaration);
3233 // string member_function_scope = SageInterface::get_name(memberFunctionDeclaration->get_scope());
3234 string member_function_name_part = mangleFunctionName(original_name,"return_type");
3235 // string member_function_name = string("scope_") + member_function_scope + "_function_name_" + member_function_name_part;
3236 string member_function_name = string("scope_") + scope + "_member_function_name_" + member_function_name_part;
3237
3238 // DQ (3/16/2016): Detect name collisions so that we can
3239 // std::map<std::string,int> dsl_attribute_name_collision_map;
3240 if (local_name_collision_map.find(member_function_name) == local_name_collision_map.end())
3241 {
3242 local_name_collision_map.insert(pair<string,int>(member_function_name,0));
3243 }
3244 else
3245 {
3246 local_name_collision_map[member_function_name]++;
3247
3248 int count = local_name_collision_map[member_function_name];
3249#if 0
3250 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3251#endif
3252 member_function_name += StringUtility::numberToString(count);
3253 }
3254
3255 s = member_function_name;
3256#if 0
3257 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgMemberFunctionDeclaration: Exiting as a test! \n");
3258 ROSE_ABORT();
3259#endif
3260 break;
3261 }
3262
3263 default:
3264 {
3265 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Unsupported declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3266// ROSE_ASSERT(false);
3267 }
3268 }
3269
3270#if 0
3271 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3272#endif
3273#if 0
3274 if (s != "")
3275 {
3276 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3277 }
3278#endif
3279
3280#if 0
3281 printf ("Exiting as a test! \n");
3282 ROSE_ABORT();
3283#endif
3284
3285 return s;
3286 }
3287
3288// Generate unique name for use as a class name for the generated attribute classes.
3289// std::string AttributeGeneratorTraversal::generateUniqueNameForUseAsIdentifier ( SgDeclarationStatement* declaration )
3290// std::string AttributeGeneratorTraversal::generateUniqueName ( SgDeclarationStatement* declaration )
3291std::string
3293 {
3294 // DQ (3/21/2016): The support for unique name generation for use across translation
3295 // units is not refactored into the SageInterface.
3296 // string s = SageInterface::generateUniqueNameForUseAsIdentifier(declaration);
3297 string s;
3298
3299#if 0
3300 printf ("In generateUniqueNameForUseAsIdentifier(): evaluating declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3301#endif
3302
3303 ROSE_ASSERT(local_node_to_name_map.empty() == false);
3304 ROSE_ASSERT(local_name_to_node_map.empty() == false);
3305
3307 {
3309 }
3310 else
3311 {
3312 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3313 if (definingDeclaration != NULL)
3314 {
3315#if 0
3316 printf ("In generateUniqueName(): Using the defining declaration = %p since %p was not in the map \n",definingDeclaration,declaration);
3317#endif
3318 // s = generateUniqueName(definingDeclaration);
3319 s = generateUniqueNameForUseAsIdentifier_support(definingDeclaration);
3320 }
3321 else
3322 {
3323 // Note that builtin functions will not have a defining declaration.
3324 printf ("Warning: defining declaration not in SageInterface::local_node_to_name_map: declaration = %p = %s using name = %s \n",
3325 declaration,declaration->class_name().c_str(),SageInterface::get_name(declaration).c_str());
3326 // ROSE_ASSERT(false);
3327
3328 // If there is no defining declaration then go ahead and use the non-defining one.
3329 // s = SageInterface::get_name(declaration);
3330 SgDeclarationStatement* nondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3331 ROSE_ASSERT(nondefiningDeclaration != NULL);
3332 s = generateUniqueNameForUseAsIdentifier_support(nondefiningDeclaration);
3333 }
3334 }
3335
3336#if 0
3337 printf ("Exiting as a test! \n");
3338 ROSE_ABORT();
3339#endif
3340
3341 return s;
3342 }
3343
3344
3345void
3347 {
3348 ROSE_ASSERT(astNode != NULL);
3349
3350 ROSE_ASSERT(local_name_collision_map.empty() == true);
3351 ROSE_ASSERT(local_name_to_node_map.empty() == true);
3352 ROSE_ASSERT(local_node_to_name_map.empty() == true);
3353
3354 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
3355 class UniqueNameTraversal : public AstSimpleProcessing
3356 {
3357 public:
3358 void visit (SgNode* node)
3359 {
3360 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
3361 if (decl != NULL)
3362 {
3363 SgClassDeclaration* classDeclaration = isSgClassDeclaration(decl);
3364 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(decl);
3365 if (classDeclaration != NULL || functionDeclaration != NULL)
3366 {
3368 local_name_to_node_map.insert(pair<string,SgNode*>(s,decl));
3369 local_node_to_name_map.insert(pair<SgNode*,string>(decl,s));
3370 }
3371 }
3372 }
3373 };
3374
3375 // Now buid the traveral object and call the traversal (preorder) on the function definition.
3376 UniqueNameTraversal traversal;
3377 traversal.traverse(astNode, preorder);
3378 }
3379
3380
3381
3384 {
3385 SgMemberFunctionDeclaration* defaultConstructor = NULL;
3386
3387 ROSE_ASSERT(classDeclaration != NULL);
3388 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3389 ROSE_ASSERT(definingDeclaration != NULL);
3390 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3391
3392 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3393 // would be associated with a class declaration but no definition would exist).
3394 if (definingClassDeclaration != NULL)
3395 {
3396 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3397 ROSE_ASSERT(classDefinition != NULL);
3398
3399 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3400 while ( i != classDefinition->get_members().end() )
3401 {
3402 // Check the parent pointer to make sure it is properly set
3403 ROSE_ASSERT( (*i)->get_parent() != NULL);
3404 ROSE_ASSERT( (*i)->get_parent() == classDefinition);
3405
3406 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3407 if (memberFunction != NULL)
3408 {
3409 // printf ("memberFunction = %p = %s \n",memberFunction,memberFunction->get_name().str());
3410 if ( memberFunction->get_specialFunctionModifier().isConstructor() == true )
3411 defaultConstructor = memberFunction;
3412 }
3413
3414 // iterate through the class members
3415 i++;
3416 }
3417 }
3418
3419 // This should be true for the specific case that we are currently debugging!
3420 // ROSE_ASSERT(defaultConstructor != NULL);
3421
3422 return defaultConstructor;
3423 }
3424
3427 {
3428 SgMemberFunctionDeclaration* defaultDestructor = NULL;
3429
3430 ROSE_ASSERT(classDeclaration != NULL);
3431 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3432 if (definingDeclaration != NULL)
3433 {
3434 ROSE_ASSERT(definingDeclaration != NULL);
3435 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3436
3437 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3438 // would be associated with a class declaration but no definition would exist).
3439 if (definingClassDeclaration != NULL)
3440 {
3441 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3442 ROSE_ASSERT(classDefinition != NULL);
3443
3444 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3445 while ( i != classDefinition->get_members().end() )
3446 {
3447 // Check the parent pointer to make sure it is properly set
3448 SgNode* i_parent = (*i)->get_parent();
3449 ROSE_ASSERT(i_parent != NULL);
3450
3451 // DQ (11/1/2005): Note that a template instantiation can have a parent which is the
3452 // variable which forced it's instantiation. Since it does not really exist in the
3453 // source code explicitly (it is compiler generated) this is as reasonable as anything else.
3454 if ( i_parent != classDefinition )
3455 {
3456 printf ("Error: (*i)->get_parent() = %p = %s \n",i_parent,i_parent->class_name().c_str());
3457 printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),(*i)->unparseToString().c_str());
3458 (*i)->get_file_info()->display("Called from SageInterface::getDefaultDestructor: debug");
3459 }
3460 ROSE_ASSERT( i_parent == classDefinition);
3461
3462 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3463 if (memberFunction != NULL)
3464 {
3465 if ( memberFunction->get_specialFunctionModifier().isDestructor() == true )
3466 defaultDestructor = memberFunction;
3467 }
3468
3469 // iterate through the class members
3470 i++;
3471 }
3472 }
3473 }
3474
3475 return defaultDestructor;
3476 }
3477
3478
3479
3480bool
3481SageInterface::addDefaultConstructorIfRequired ( SgClassType* classType, int physical_file_id /* = Sg_File_Info::TRANSFORMATION_FILE_ID */ )
3482 {
3483 // DQ (11/9/2020): Added function to support adding a default constructor definition to a class
3484 // if it does not have a default constructor, but has any other constructor that would prevent
3485 // a compiler generated default constructor from being generated by the compiler.
3486
3487#define DEBUG_ADD_DEFAULT_CONSTRUCTOR 0
3488
3489 // Note the physical_file_id is so that it can be marked to be unparsed when header file unparsing is active.
3490
3491 ASSERT_not_null(classType);
3492
3493 bool returnValue = false;
3494
3495 // To setup this transformation we need to see if there is a default constructor in the associated class.
3496 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
3497 ROSE_ASSERT(classDeclaration != NULL);
3498 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(classDeclaration->get_definingDeclaration());
3499 ROSE_ASSERT(definingClassDeclaration != NULL);
3500 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3501 ROSE_ASSERT(classDefinition != NULL);
3502
3503 SgDeclarationStatementPtrList & declarationList = classDefinition->get_members();
3504
3505 bool foundConstructor = false;
3506 bool foundDefaultConstructor = false;
3507
3508#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3509 printf ("In addDefaultConstructorIfRequired(): class name = %s \n",classDeclaration->get_name().str());
3510#endif
3511
3512 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
3513 while (i != declarationList.end())
3514 {
3515 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(*i);
3516 if (memberFunctionDeclaration != NULL)
3517 {
3518 bool isConstructor = memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
3519 if (isConstructor == true)
3520 {
3521 foundConstructor = true;
3522
3523#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3524 printf ("Found a constructor! \n");
3525#endif
3526 SgFunctionParameterList* functionParameterList = memberFunctionDeclaration->get_parameterList();
3527 ROSE_ASSERT(functionParameterList != NULL);
3528
3529 // DQ (7/19/2021): Fixed to allow for previously found default constructor to be registered as found.
3530 // foundDefaultConstructor = (functionParameterList->get_args().size() == 0);
3531 foundDefaultConstructor = ((foundDefaultConstructor == true) || (functionParameterList->get_args().size() == 0));
3532
3533#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3534 if (foundDefaultConstructor == true)
3535 {
3536 printf ("Found a default constructor! \n");
3537 }
3538 else
3539 {
3540 printf ("This is not a default constructor: functionParameterList->get_args().size() = %zu \n",functionParameterList->get_args().size());
3541 }
3542#endif
3543 }
3544 else
3545 {
3546#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3547 printf ("This is not a constructor \n");
3548#endif
3549 }
3550 }
3551
3552 i++;
3553 }
3554
3555#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3556 printf ("foundConstructor = %s \n",foundConstructor ? "true" : "false");
3557 printf ("foundDefaultConstructor = %s \n",foundDefaultConstructor ? "true" : "false");
3558#endif
3559
3560 if (foundConstructor == true)
3561 {
3562 // Since there is at least one constructor, we can't rely on compiler generated constructors.
3563#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3564 printf ("Since there is at least one constructor, we can't rely on compiler generated constructors \n");
3565#endif
3566 if (foundDefaultConstructor == true)
3567 {
3568 // We can use the existing default constructor.
3569#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3570 printf ("We can use the existing default constructor (no need to build one) \n");
3571#endif
3572 }
3573 else
3574 {
3575 // We don't have a default constructor, so we need to build one explicitly, and insert it into the class definition.
3576
3577#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3578 printf ("########################################################### \n");
3579 printf ("Need to build a default constructor in the associated class \n");
3580#endif
3581 SgMemberFunctionDeclaration* constructorDeclaration = SageBuilder::buildDefaultConstructor(classType);
3582 ROSE_ASSERT(constructorDeclaration != NULL);
3583
3584#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3585 printf (" --- constructorDeclaration = %p = %s name = %s \n",constructorDeclaration,constructorDeclaration->class_name().c_str(),constructorDeclaration->get_name().str());
3586#endif
3587 ROSE_ASSERT (constructorDeclaration->get_declarationModifier().get_accessModifier().isPublic() == true);
3588
3589 classDefinition->prepend_statement(constructorDeclaration);
3590
3591 // constructorDeclaration->set_parent(classDefinition);
3592 ROSE_ASSERT(constructorDeclaration->get_parent() != NULL);
3593
3594 // int physical_file_id = variableDeclaration->get_startOfConstruct()->get_physical_file_id();
3595 markSubtreeToBeUnparsed(constructorDeclaration,physical_file_id);
3596
3597 returnValue = true;
3598#if 0
3599 constructorDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3600 constructorDeclaration->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3601
3602 // We also need to set the source position of the function definition, else the
3603 // function declaration will not be output.
3604 ROSE_ASSERT(constructorDeclaration->get_definition() != NULL);
3605 ROSE_ASSERT(constructorDeclaration->get_definition()->get_startOfConstruct() != NULL);
3606 ROSE_ASSERT(constructorDeclaration->get_definition()->get_endOfConstruct() != NULL);
3607 constructorDeclaration->get_definition()->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3608 constructorDeclaration->get_definition()->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3609#endif
3610
3611#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3612 printf ("DONE: Need to build a default constructor in the associated class \n");
3613 printf ("################################################################# \n");
3614#endif
3615#if 0
3616 printf ("Exiting as a test! \n");
3617 ROSE_ABORT();
3618#endif
3619 }
3620 }
3621 else
3622 {
3623 // No constructors found, so we don't need to add an explicit default constructor.
3624
3625#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3626 printf ("No constructors found, so we don't need to add an explicit default constructor \n");
3627#endif
3628 }
3629
3630#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3631 printf ("Leaving addDefaultConstructorIfRequired(): returnValue = %s \n",returnValue ? "true" : "false");
3632#endif
3633
3634 return returnValue;
3635 }
3636
3637
3638
3639
3640void
3642 {
3643 // DQ (6/27/2005): This function outputs the global table of function type symbols
3644 // it is built during the EDG/Sage translation phase, and it built initially with
3645 // the EDG names of all instantiated templates. At a later phase (incomplete at
3646 // the moment) the AST fixup rebuilds the table to use the modified template names
3647 // (that is mangled names built from the modified template names used in Sage III).
3648
3649 // DQ (1/31/2006): Modified to build all types in the memory pools
3650 // extern SgFunctionTypeTable Sgfunc_type_table;
3651 // Sgfunc_type_table.print_functypetable();
3652 ROSE_ASSERT(SgNode::get_globalFunctionTypeTable() != NULL);
3653 SgNode::get_globalFunctionTypeTable()->print_functypetable();
3654 }
3655
3656void
3658 {
3659 // This simplifies how the traversal is called!
3660 OutputLocalSymbolTables astTraversal;
3661
3662 // I think the default should be preorder so that the interfaces would be more uniform
3663 astTraversal.traverse(node,preorder);
3664 }
3665
3666void
3668 {
3669 // DQ (6/27/2005): Output the local symbol table from each scope.
3670 // printf ("node = %s \n",node->sage_class_name());
3671
3672#if 0
3673 printf ("Exiting as a test! \n");
3674 ROSE_ABORT();
3675#endif
3676
3677 SgScopeStatement* scope = isSgScopeStatement(node);
3678 if (scope != NULL)
3679 {
3680 // SgSymbolTable* symbolTable = scope->get_symbol_table();
3681 // ROSE_ASSERT(symbolTable != NULL);
3682
3683 printf ("Symbol Table from %p = %s at: \n",scope,scope->sage_class_name());
3684 scope->get_file_info()->display("Symbol Table Location (Called from SageInterface::OutputLocalSymbolTables::visit())");
3685 // symbolTable->print("Called from SageInterface::OutputLocalSymbolTables::visit()");
3686 scope->print_symboltable("Called from SageInterface::OutputLocalSymbolTables::visit()");
3687 }
3688 }
3689
3690#if 0
3691// DQ (8/28/2005): This is already a member function of the SgFunctionDeclaration
3692// (so that it can handle template functions and member functions)
3693
3694// DQ (8/27/2005):
3695bool
3696SageInterface::isTemplateMemberFunction( SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration )
3697 {
3698 // This function determines if the member function is associated with a template
3699 // or just a template class (where it is a normal non-template member function).
3700
3701 bool result = false;
3702
3703 result = memberFunctionDeclaration->isTemplateFunction();
3704
3705 return result;
3706 }
3707#endif
3708
3709// DQ (8/27/2005):
3710bool
3712 {
3713 // This function determines if the template declaration associated withthis member function instantiation is
3714 // defined in the class or outside of the class.
3715
3716 bool result = false;
3717
3718#if 0
3719 // Check if this is a template or non-template member function
3720 if (isTemplateMemberFunction(memberFunctionDeclaration) == true)
3721 {
3722 SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3723 printf ("templateDeclaration = %p parent of templateDeclaration = %p \n",templateDeclaration,templateDeclaration->get_parent());
3724
3725 // SgTemplateInstantiationDecl* classTemplateInstantiation = memberFunctionDeclaration->get_class_scope()->get_declaration();
3726 SgClassDeclaration* classDeclaration = memberFunctionDeclaration->get_class_scope()->get_declaration();
3727 ROSE_ASSERT(classDeclaration != NULL);
3728 SgTemplateInstantiationDecl* classTemplateInstantiation = isSgTemplateInstantiationDecl(classDeclaration);
3729
3730 if (classTemplateInstantiation != NULL)
3731 {
3732 SgTemplateDeclaration* classTemplateDeclaration = classTemplateInstantiation->get_templateDeclaration();
3733 if (classTemplateDeclaration != NULL && classTemplateDeclaration != templateDeclaration)
3734 {
3735 result = true;
3736 }
3737 }
3738 }
3739#endif
3740
3741 // Alternative approach
3742 // SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3743 SgDeclarationStatement* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3744// printf ("In templateDefinitionIsInClass(): templateDeclaration = %p parent of templateDeclaration = %p = %s \n",templateDeclaration,
3745// templateDeclaration->get_parent(),templateDeclaration->get_parent()->class_name().c_str());
3746
3747 if (templateDeclaration != NULL && templateDeclaration->get_parent() != NULL)
3748 {
3749 SgScopeStatement* parentScope = isSgScopeStatement(templateDeclaration->get_parent());
3750 if (isSgClassDefinition(parentScope) != NULL)
3751 {
3752 result = true;
3753 }
3754 }
3755
3756 return result;
3757 }
3758#if 0
3760generateUniqueDeclaration ( SgDeclarationStatement* declaration )
3761 {
3762 // DQ (10/11/2007): This is no longer used.
3763 printf ("Error: This is no longer used. \n");
3764 ROSE_ABORT();
3765
3766 // Get the defining or first non-defining declaration so that we can use it as a key to know
3767 // when we have found the same function. So we don't count a redundant forward declaration
3768 // found outside of the class as matching the first non-defining declaration or the defining
3769 // declaration in the class by mistake. All declarations share the same firstNondefining
3770 // declaration and defining declaration so either could be a key declaration, but there are
3771 // times when either one of then (but not both) can be NULL (function defined withouth forward
3772 // declaration or not defined at all).
3773 SgDeclarationStatement* firstNondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3774 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3775 SgDeclarationStatement* keyDeclaration = NULL;
3776 if (firstNondefiningDeclaration != NULL)
3777 keyDeclaration = firstNondefiningDeclaration;
3778 else
3779 keyDeclaration = definingDeclaration;
3780 ROSE_ASSERT(keyDeclaration != NULL);
3781
3782 return keyDeclaration;
3783 }
3784#endif
3787{
3788 string pragmaString = pragmaDeclaration->get_pragma()->get_pragma();
3789 istringstream istr(pragmaString);
3790 std::string key;
3791 istr >> key;
3792 return key;
3793}
3794
3796// TODO: move all Omp*statement under a parent SgOmpStatement
3798{
3799 ROSE_ASSERT (n != NULL);
3800 bool result = false;
3801 if (isSgOmpBarrierStatement(n)||
3802 isSgOmpBodyStatement(n)||
3803 isSgOmpDeclareSimdStatement(n) ||
3804 isSgOmpFlushStatement(n)||
3805 isSgOmpThreadprivateStatement(n)||
3806 isSgOmpTaskwaitStatement(n) )
3807 result = true;
3808
3809 return result;
3810
3811}
3812// DQ (8/28/2005):
3813bool
3815 {
3816 // This function looks for any other function that might overload the input function.
3817 // for member functions we only look in the scope where the member function is defined.
3818 // for non-member functions we look only in the scope where the function is declared.
3819
3820 // Note that there are scenarios where this approach of searching only these locations
3821 // might not catch an overloaded function.
3822 // * member functions:
3823 // - overloaded functions might be declared in base classes
3824 // * non-member functions:
3825 // - function declarations might be friend functions in classes
3826 // - functions might be declared in differen namespace definitions
3827 // (SgNamespaceDefinitionStatement), since a namespace in re-entrant
3828 // and can have many namespace declarations and definitions.
3829
3830 // bool result = false;
3831 int counter = 0;
3832
3833 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
3834 if (memberFunctionDeclaration != NULL)
3835 {
3836 // This is a member function declaration
3837
3838 // DQ (10/11/2007): Fix this to NOT use the generateUniqueDeclaration() function.
3839 // Generate a key to use for comparision (avoids false positives)
3840 // SgMemberFunctionDeclaration* keyDeclaration = isSgMemberFunctionDeclaration(generateUniqueDeclaration(functionDeclaration));
3841 // ROSE_ASSERT(keyDeclaration != NULL);
3842
3843 SgScopeStatement * scope = memberFunctionDeclaration->get_scope();
3844 ROSE_ASSERT(scope != NULL);
3845
3846 // TV (09/17/2018): ROSE-1378
3847 if (isSgDeclarationScope(scope)) {
3848 printf("TODO SageInterface::isOverloaded case when scope is SgDeclarationScope. See ROSE-1378.\n");
3849 return false;
3850 }
3851
3852 // Get the class definition
3853 SgClassDefinition* classDefinition =
3854 isSgClassDefinition(memberFunctionDeclaration->get_scope());
3855 ROSE_ASSERT(classDefinition != NULL);
3856
3857 // Get the class declaration associated with the class definition
3858 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classDefinition->get_declaration());
3859 ROSE_ASSERT(classDeclaration != NULL);
3860
3861 // Get the list of member declarations in the class
3862 SgDeclarationStatementPtrList & memberList = classDefinition->get_members();
3863#if 0
3864 // DQ (10/11/2007): Fix this function better by checking for more than one member function declaration in the class definition.
3865 printf (" memberList.size() = %" PRIuPTR " \n",memberList.size());
3866#endif
3867 for (SgDeclarationStatementPtrList::iterator i = memberList.begin(); i != memberList.end(); i++)
3868 {
3869#if 0
3870 printf (" counter = %d declaration = %p = %s \n",counter,*i,(*i)->class_name().c_str());
3871#endif
3872 SgMemberFunctionDeclaration* tempMemberFunction = isSgMemberFunctionDeclaration(*i);
3873 SgTemplateDeclaration* tempTemplateDeclaration = isSgTemplateDeclaration(*i);
3874
3875 // Member functions could be overloaded
3876 if (tempMemberFunction != NULL)
3877 {
3878#if 0
3879 // 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.
3880 // Check using the key declaration
3881 if ( keyDeclaration == generateUniqueDeclaration(tempMemberFunction) )
3882 {
3883#if 0
3884 printf ("Skipping the case of keyDeclaration == generateUniqueDeclaration(tempMemberFunction) = %p \n",keyDeclaration);
3885#endif
3886 continue;
3887 }
3888#endif
3889 ROSE_ASSERT(tempMemberFunction->get_name() != "");
3890#if 0
3891 printf (" tempMemberFunction = (name) %s = (qualified) %s \n",
3892 tempMemberFunction->get_name().str(),
3893 tempMemberFunction->get_qualified_name().str());
3894#endif
3895 if (tempMemberFunction->get_name() == memberFunctionDeclaration->get_name())
3896 {
3897#if 0
3898 printf (" Found a matching overloaded member function! \n");
3899#endif
3900 // result = true;
3901 counter++;
3902 }
3903 }
3904 else
3905 {
3906 // Or templates could be overloaded, but nothing else.
3907 if (tempTemplateDeclaration != NULL)
3908 {
3909 // If this is a template declaration, it could be a template
3910 // declaration for an overloaded member function of the same name.
3911#if 0
3912 // printf ("keyDeclaration->get_name() = %s \n",keyDeclaration->get_name().str());
3913 printf ("tempTemplateDeclaration->get_name() = %s \n",tempTemplateDeclaration->get_name().str());
3914#endif
3915 if (memberFunctionDeclaration->get_name() == tempTemplateDeclaration->get_name())
3916 {
3917#if 0
3918 printf (" Found a matching overloaded member function! \n");
3919#endif
3920 // result = true;
3921 counter++;
3922 }
3923 }
3924 else
3925 {
3926 // DQ (10/12/2007): Could friend functions defined in a class be overloaded? Need to check this!
3927 if (functionDeclaration->variantT() == V_SgFunctionDeclaration)
3928 {
3929 printf ("In SageInterface::isOverloaded(): could friend functions be overloaded in a class? \n");
3930 }
3931 }
3932 }
3933
3934 // If we have detected two, so we have an overloaded function.
3935 if (counter > 1)
3936 break;
3937 }
3938 }
3939 else
3940 {
3941 // This is a non-member function declaration
3942 printf ("In SageInterface::isOverloaded(): case of non-member function not yet implemented! \n");
3943 ROSE_ABORT();
3944 }
3945
3946 // DQ (10/11/2007): Fixup to use the counter and consider more than 1 function with the same name an overloaded member function.
3947 // This might be a problem for friend functions, so test this separately.
3948 // return result;
3949 return (counter > 1);
3950 }
3951
3952
3953
3954
3957 {
3958 // DQ (9/6/2005): This function builds a copy of the input function for the
3959 // construction of a forward declaration of the function. Required in the
3960 // instantiated functions definition is to be output as a specialization by ROSE.
3961 // Since the shallow copy mechanism will cause IR nodes to be shared, we have
3962 // to fix it up with deep copies of the parameter list and the CtorInitializerList.
3963
3964 ROSE_ASSERT(memberFunctionInstantiation != NULL);
3965
3966#if 0
3967 printf ("buildForwardFunctionDeclaration: Member function = %p = %s = definition = %p \n",
3968 memberFunctionInstantiation,
3969 memberFunctionInstantiation->get_name().str(),
3970 memberFunctionInstantiation->get_definition());
3971 memberFunctionInstantiation->get_file_info()->display("memberFunctionInstantiation: debug");
3972#endif
3973
3974 // This is a better implementation using a derived class from SgCopyHelp to control the
3975 // copying process (skipping the copy of any function definition). This is a variable
3976 // declaration with an explicitly declared class type.
3977 class NondefiningFunctionDeclarationCopyType : public SgCopyHelp
3978 {
3979 // DQ (9/26/2005): This class demonstrates the use of the copy mechanism
3980 // within Sage III (originally designed and implemented by Qing Yi).
3981 // One problem with it is that there is no context information permitted.
3982
3983 public:
3984 virtual SgNode *copyAst(const SgNode *n)
3985 {
3986 // If still NULL after switch then make the copy
3987 SgNode* returnValue = NULL;
3988
3989 switch(n->variantT())
3990 {
3991 // DQ (10/21/2007): Now that s bug is fixed in the SgDeclarationStatement::fixupCopy()
3992 // member function, I think we might not need this case.
3993
3994 // Don't copy the associated non-defining declaration when building a function prototype!
3995 case V_SgFunctionDeclaration:
3996 case V_SgMemberFunctionDeclaration:
3997 case V_SgTemplateInstantiationFunctionDecl:
3998 case V_SgTemplateInstantiationMemberFunctionDecl:
3999 {
4000 // printf ("Skip copying an associated non-defining declaration if it is present \n");
4001 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n);
4002 ROSE_ASSERT(functionDeclaration != NULL);
4003 if (functionDeclaration == functionDeclaration->get_definingDeclaration())
4004 {
4005 // This is the defining declaration (make a shallow copy)
4006 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the DEFINING declaration! \n");
4007 // return const_cast<SgNode *>(n);
4008 returnValue = const_cast<SgNode *>(n);
4009 }
4010 else
4011 {
4012 // This is the non-defining declaration where we want to make a deep copy.
4013 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the NONDEFINING declaration! \n");
4014 }
4015
4016 break;
4017 }
4018
4019 // Don't copy the function definitions (roughly the body of the function)
4020 case V_SgFunctionDefinition:
4021 {
4022 printf ("Skip copying the function definition if it is present \n");
4023 // return const_cast<SgNode *>(n);
4024 returnValue = const_cast<SgNode *>(n);
4025 break;
4026 }
4027
4028 default:
4029 {
4030 // Nothing to do here
4031 break;
4032 }
4033 }
4034
4035 // return n->copy(*this);
4036
4037 // If not set at this point then make the copy!
4038 if (returnValue == NULL)
4039 returnValue = n->copy(*this);
4040
4041 ROSE_ASSERT(returnValue != NULL);
4042 return returnValue;
4043 }
4044 } nondefiningFunctionDeclarationCopy;
4045
4046 // DQ (10/20/2007): The more accurate copy mechanism now builds us a defining declaration to go with the non-defining declaration!
4047 // 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!
4048 // delete copyOfMemberFunction->get_definingDeclaration();
4049 if (memberFunctionInstantiation->get_definition() != NULL)
4050 {
4051 printf ("\n\nNEED TO REMOVE POINTERS IN THE NON-DEFINING DECLARATION TO THE SgClassDefinition objects. \n");
4052 ROSE_ABORT();
4053
4054 // If we see the assertion above fail then we might want to use this code:
4055 ROSE_ASSERT( memberFunctionInstantiation != memberFunctionInstantiation->get_definingDeclaration() );
4056 memberFunctionInstantiation->set_definition(NULL);
4057 }
4058 SgNode* copyOfMemberFunctionNode = memberFunctionInstantiation->copy(nondefiningFunctionDeclarationCopy);
4059 SgTemplateInstantiationMemberFunctionDecl* copyOfMemberFunction = static_cast<SgTemplateInstantiationMemberFunctionDecl*>(copyOfMemberFunctionNode);
4060
4061 // printf ("\n\nHOW DO WE KNOW WHEN TO NOT COPY THE DEFINING DECLARATION SO THAT WE CAN JUST BUILD A FUNCTION PROTOTYPE! \n");
4062 // ROSE_ASSERT(false);
4063
4064#if 0
4065 printf ("copyOfMemberFunction->get_firstNondefiningDeclaration() = %p \n",copyOfMemberFunction->get_firstNondefiningDeclaration());
4066#endif
4067 // DQ (10/11/2007): The copy function sets the firstNondefiningDeclaration to itself if in the original declaration it had the
4068 // firstNondefiningDeclaration set to itself, this is incorrect in the case where we only make a copy of function declaration,
4069 // and causes the symbol table tests for get_declaration_associated_with_symbol() to fail because it uses the
4070 // firstNondefiningDeclaration which is not the one associated with the symbol in the parent scope. So reset the
4071 // firstNondefiningDeclaration in the copy of the member function.
4072 copyOfMemberFunction->set_firstNondefiningDeclaration(memberFunctionInstantiation->get_firstNondefiningDeclaration());
4073
4074#if 0
4075 printf ("memberFunctionInstantiation->get_firstNondefiningDeclaration() = %p \n",memberFunctionInstantiation->get_firstNondefiningDeclaration());
4076
4077 printf ("copyOfMemberFunction->isForward() = %s \n",copyOfMemberFunction->isForward() ? "true" : "false");
4078 printf ("memberFunctionInstantiation->isForward() = %s \n",memberFunctionInstantiation->isForward() ? "true" : "false");
4079#endif
4080#if 0
4081 printf ("memberFunctionInstantiation->isSpecialization() = %s \n",memberFunctionInstantiation->isSpecialization() ? "true" : "false");
4082 printf ("copyOfMemberFunctionNode = %p = %s = %s memberFunctionInstantiation->isSpecialization() = %s \n",
4083 copyOfMemberFunction,copyOfMemberFunction->class_name().c_str(),SageInterface::get_name(copyOfMemberFunction).c_str(),copyOfMemberFunction->isSpecialization() ? "true" : "false");
4084 copyOfMemberFunction->get_file_info()->display("copyOfMemberFunction: debug");
4085#endif
4086
4087 // Make sure that we have the same number of arguments on the copy that we build
4088 ROSE_ASSERT(memberFunctionInstantiation->get_args().size() == copyOfMemberFunction->get_args().size());
4089
4090 // DQ (11/5/2007): Additional tests
4091 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isOutputInCodeGeneration() == copyOfMemberFunction->get_startOfConstruct()->isOutputInCodeGeneration());
4092 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isCompilerGenerated() == copyOfMemberFunction->get_startOfConstruct()->isCompilerGenerated());
4093
4094 ROSE_ASSERT(copyOfMemberFunction != NULL);
4095 return copyOfMemberFunction;
4096 }
4097
4098
4099void
4100supportForBaseTypeDefiningDeclaration ( SgSymbolTable* symbolTable, SgDeclarationStatement* declarationForType )
4101 {
4102 // DQ (10/14/2007): Supporting function for
4103
4104 ROSE_ASSERT(declarationForType != NULL);
4105
4106 // DQ (11/7/2007): Added more cases...
4107 switch(declarationForType->variantT())
4108 {
4109 // DQ (12/26/2012): Added support for templates.
4110 case V_SgTemplateInstantiationDecl:
4111 case V_SgTemplateClassDeclaration:
4112
4113 case V_SgClassDeclaration:
4114 {
4115 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationForType);
4116 // SgSymbol* symbol = new SgClassSymbol(classDeclaration);
4117 SgSymbol* symbol = NULL;
4118 if (isSgTemplateClassDeclaration(declarationForType) != NULL)
4119 {
4120 symbol = new SgTemplateClassSymbol(classDeclaration);
4121 }
4122 else
4123 {
4124 symbol = new SgClassSymbol(classDeclaration);
4125 }
4126
4127 ROSE_ASSERT(symbol != NULL);
4128 SgName name = classDeclaration->get_name();
4129 symbolTable->insert(name,symbol);
4130 break;
4131 }
4132
4133 case V_SgEnumDeclaration:
4134 {
4135 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(declarationForType);
4136 SgSymbol* symbol = new SgEnumSymbol(enumDeclaration);
4137 ROSE_ASSERT(symbol != NULL);
4138 SgName name = enumDeclaration->get_name();
4139 symbolTable->insert(name,symbol);
4140 break;
4141 }
4142
4143 case V_SgFunctionDeclaration:
4144 {
4145 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declarationForType);
4146 SgSymbol* symbol = new SgFunctionSymbol(functionDeclaration);
4147 ROSE_ASSERT(symbol != NULL);
4148 SgName name = functionDeclaration->get_name();
4149 symbolTable->insert(name,symbol);
4150 break;
4151 }
4152
4153 case V_SgMemberFunctionDeclaration:
4154 {
4155 SgMemberFunctionDeclaration* functionDeclaration = isSgMemberFunctionDeclaration(declarationForType);
4156 SgSymbol* symbol = new SgMemberFunctionSymbol(functionDeclaration);
4157 ROSE_ASSERT(symbol != NULL);
4158
4159 // printf ("In supportForBaseTypeDefiningDeclaration(): symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4160
4161 SgName name = functionDeclaration->get_name();
4162 symbolTable->insert(name,symbol);
4163 break;
4164 }
4165
4166 default:
4167 {
4168 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());
4169 ROSE_ABORT();
4170 }
4171 }
4172 }
4173
4174
4175void
4176supportForVariableLists ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgInitializedNamePtrList & variableList )
4177 {
4178 // DQ (11/1/2007): Added supporting function to refactor code.
4179 SgInitializedNamePtrList::iterator i = variableList.begin();
4180 while (i != variableList.end())
4181 {
4183 ROSE_ASSERT(variable != NULL);
4184 if (variable->get_scope() == scope)
4185 {
4186 // printf ("Scopes match, OK! \n");
4187 }
4188 else
4189 {
4190 if (SgProject::get_verbose() > 0)
4191 {
4192 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());
4193 }
4194 }
4195
4196 SgSymbol* symbol = new SgVariableSymbol(variable);
4197 ROSE_ASSERT(symbol != NULL);
4198 SgName name = variable->get_name();
4199 symbolTable->insert(name,symbol);
4200
4201 i++;
4202 }
4203 }
4204#if 0
4205// DQ (3/2/2014): Added a new interface function (used in the snippet insertion support).
4206void
4207SageInterface::supportForInitializedNameLists ( SgScopeStatement* scope, SgInitializedNamePtrList & variableList )
4208 {
4209 SgSymbolTable* symbolTable = scope->get_symbol_table();
4210 ROSE_ASSERT(symbolTable != NULL);
4211
4212 supportForVariableLists(scope,symbolTable,variableList);
4213 }
4214#endif
4215
4216void
4217supportForVariableDeclarations ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgVariableDeclaration* variableDeclaration )
4218 {
4219 // DQ (10/24/2007): Added supporting function to refactor code.
4220 SgInitializedNamePtrList & variableList = variableDeclaration->get_variables();
4221 supportForVariableLists(scope,symbolTable,variableList);
4222
4223 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4224 // that also force symbols to be built in the current scope!
4225 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4226 if (variableDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4227 {
4228 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4229 ROSE_ASSERT(symbolTable != NULL);
4230 ROSE_ASSERT(variableDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4231 supportForBaseTypeDefiningDeclaration ( symbolTable, variableDeclaration->get_baseTypeDefiningDeclaration() );
4232 }
4233 }
4234
4235void
4236supportForLabelStatements ( SgScopeStatement* scope, SgSymbolTable* symbolTable )
4237 {
4238 // Update the symbol table in SgFunctionDefinition with all the labels in the function.
4239
4240 std::vector<SgNode*> labelList = NodeQuery::querySubTree (scope,V_SgLabelStatement);
4241
4242 int numberOfLabels = labelList.size();
4243 for (int i=0; i < numberOfLabels; i++)
4244 {
4245 SgLabelStatement* labelStatement = isSgLabelStatement(labelList[i]);
4246
4247 ROSE_ASSERT(labelStatement != NULL);
4248 ROSE_ASSERT(labelStatement->get_scope() == scope);
4249
4250 SgSymbol* symbol = new SgLabelSymbol(labelStatement);
4251 ROSE_ASSERT(symbol != NULL);
4252
4253 // printf ("In SageInterface::rebuildSymbolTable() labelStatement = %p building a new SgLabelSymbol = %p \n",labelStatement,symbol);
4254
4255 SgName name = labelStatement->get_name();
4256 symbolTable->insert(name,symbol);
4257 }
4258 }
4259
4260
4261void
4263 {
4264 // This function is called from the implementation of the copy member functions.
4265
4266 ROSE_ASSERT(scope != NULL);
4267#if 0
4268 printf ("In SageInterface::rebuildSymbolTable(): Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4269#endif
4270#if 0
4271 printf ("Exiting as a test \n");
4272 ROSE_ABORT();
4273#endif
4274
4275 SgSymbolTable* symbolTable = scope->get_symbol_table();
4276
4277 if (symbolTable != NULL)
4278 {
4279 // This must be an empty symbol table!
4280 if (symbolTable->size() != 0)
4281 {
4282 printf ("symbolTable->size() = %d \n",symbolTable->size());
4283 }
4284 ROSE_ASSERT(symbolTable->size() == 0);
4285#if 0
4286 printf ("Symbol Table from %p = %s of size = %" PRIuPTR " \n",scope,scope->class_name().c_str(),symbolTable->size());
4287 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
4288#endif
4289 }
4290 else
4291 {
4292#if 0
4293 printf ("In SageInterface::rebuildSymbolTable(): No symbol table found \n");
4294#endif
4295 ROSE_ASSERT(symbolTable == NULL);
4296
4297 // DQ (10/8/2007): Build a new symbol table if there was not already one built.
4298 symbolTable = new SgSymbolTable();
4299
4300 ROSE_ASSERT(symbolTable != NULL);
4301 ROSE_ASSERT(symbolTable->get_table() != NULL);
4302
4303 // DQ (2/16/2006): Set this parent directly (now tested)
4304 symbolTable->set_parent(scope);
4305 ROSE_ASSERT(symbolTable->get_parent() != NULL);
4306
4307 scope->set_symbol_table(symbolTable);
4308 }
4309
4310 // 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.
4311 ROSE_ASSERT(scope->get_symbol_table() != NULL);
4312 ROSE_ASSERT(scope->get_symbol_table()->get_table() != NULL);
4313
4314 // This implements SgScopeStatement specific details (e.g function declarations have parameters and their declaration causes variable
4315 // symbols to be placed into the SgFunctionDefinition scope (but only for defining declarations).
4316 switch(scope->variantT())
4317 {
4318 case V_SgForStatement:
4319 {
4320 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4321 // printf ("Symbol tables could contain symbols outside of the inclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4322
4323 SgForStatement* forStatement = isSgForStatement(scope);
4324
4325 SgStatementPtrList::iterator i = forStatement->get_init_stmt().begin();
4326
4327 // printf ("i != forStatement->get_init_stmt().end() = %s \n",i != forStatement->get_init_stmt().end() ? "true" : "false");
4328
4329 while (i != forStatement->get_init_stmt().end())
4330 {
4331 // printf ("For statement initialization list: *i = %p = %s \n",*i,(*i)->class_name().c_str());
4332 SgVariableDeclaration* variableDeclarationInitializer = isSgVariableDeclaration(*i);
4333 if (variableDeclarationInitializer != NULL)
4334 {
4335 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4336 // 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());
4337 // ROSE_ASSERT(false);
4338 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationInitializer );
4339 }
4340
4341 i++;
4342 }
4343
4344 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(forStatement->get_test());
4345 if (variableDeclarationCondition != NULL)
4346 {
4347 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4348 // 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());
4349 // ROSE_ASSERT(false);
4350 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4351 }
4352
4353 return;
4354 break;
4355 }
4356
4357 case V_SgJovialForThenStatement:
4358 case V_SgMatlabForStatement:
4359 {
4360 return;
4361 break;
4362 }
4363
4364
4365 // DQ (12/23/2012): Added support for templates.
4366 case V_SgTemplateFunctionDefinition:
4367
4368 case V_SgFunctionDefinition:
4369 {
4370 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4371 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4372
4373 // DQ (10/8/2007): If this is a SgFunctionDefinition, then include the parameters in the SgFunctionDeclaration.
4374 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
4375 if (functionDefinition != NULL)
4376 {
4377 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
4378 // printf ("In SageInterface::rebuildSymbolTable(): functionDefinition = %p functionDeclaration = %p \n",functionDefinition,functionDeclaration);
4379
4380 // 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!
4381 if (functionDeclaration != NULL)
4382 {
4383 // 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.
4384 if (functionDeclaration->isForward() == true)
4385 {
4386 printf ("ERROR: functionDeclaration = %p = %s = %s \n",functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
4387 printf (" --- functionDeclaration (get_name()) = %s \n",get_name(functionDeclaration).c_str());
4388 printf (" --- functionDeclaration (mangled name) = %s \n",functionDeclaration->get_mangled_name().str());
4389 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
4390 if (memberFunctionDeclaration != NULL)
4391 {
4392 printf ("memberFunctionDeclaration != NULL \n");
4393 }
4394 }
4395 ROSE_ASSERT(functionDeclaration->isForward() == false);
4396 SgInitializedNamePtrList & argumentList = functionDeclaration->get_args();
4397 supportForVariableLists(scope,symbolTable,argumentList);
4398 }
4399 else
4400 {
4401 // This happens in the copy function because the function definition is copied from the SgFunctionDeclaration
4402 // and only after the copy is made is the parent of the definition set to be the function declaration. Thus
4403 // the get_declaration() member function returns NULL.
4404 // printf ("There is no function declaration associated with this function definition! \n");
4405 // ROSE_ASSERT(functionDeclaration->isForward() == true);
4406 }
4407 }
4408
4409 // DQ (10/25/2007): Label symbols are now places into the SgFunctionDefinition (they have to be collected from the function).
4410 supportForLabelStatements(scope,symbolTable);
4411
4412 return;
4413 break;
4414 }
4415
4416 case V_SgIfStmt:
4417 {
4418 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4419 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4420
4421 SgIfStmt* ifStatement = isSgIfStmt(scope);
4422 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(ifStatement->get_conditional());
4423 if (variableDeclarationCondition != NULL)
4424 {
4425 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4426 // printf ("There is a variable declaration in the conditional, it needs to be added to the symbol table \n");
4427 // ROSE_ASSERT(false);
4428 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4429 }
4430 return;
4431 break;
4432 }
4433
4434 case V_SgSwitchStatement:
4435 {
4436 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4437 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4438
4439 SgSwitchStatement* switchStatement = isSgSwitchStatement(scope);
4440 SgVariableDeclaration* variableDeclarationSelector = isSgVariableDeclaration(switchStatement->get_item_selector());
4441 if (variableDeclarationSelector != NULL)
4442 {
4443 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4444 // printf ("There is a variable declaration in the item selector of the switch statement, it needs to be added to the symbol table \n");
4445
4446 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationSelector );
4447 }
4448 return;
4449 break;
4450 }
4451
4452 case V_SgWhileStmt:
4453 {
4454 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4455 // commented out like for others, otherwise show up each time a While is being copied. Liao, 1/31/2008
4456 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4457
4458 SgWhileStmt* whileStatement = isSgWhileStmt(scope);
4459 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(whileStatement->get_condition());
4460 if (variableDeclarationCondition != NULL)
4461 {
4462 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4463 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4464 // ROSE_ASSERT(false);
4465
4466 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4467 }
4468 return;
4469 break;
4470 }
4471
4472 case V_SgCatchOptionStmt:
4473 case V_SgDoWhileStmt:
4474 {
4475 // These scopes contain a SgBasicBlock as a data member and the scope is held there.
4476 // printf ("Symbol tables can must be computed by the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4477 return;
4478 break;
4479 }
4480
4481 // DQ (12/24/2012): Added support for templates.
4482 case V_SgTemplateClassDefinition:
4483
4484 case V_SgBasicBlock:
4485 case V_SgClassDefinition:
4486 case V_SgTemplateInstantiationDefn:
4487 case V_SgGlobal:
4488 case V_SgNamespaceDefinitionStatement:
4489 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
4490 {
4491 // printf ("Used the list of statements/declarations that are held deirectly by this scope \n");
4492 break;
4493 }
4494
4495 // DQ (3/29/2014): Added support for SgJavaForEachStatement.
4496 case V_SgJavaForEachStatement:
4497 {
4498 SgJavaForEachStatement* javaForEachStatement = isSgJavaForEachStatement(scope);
4499 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(javaForEachStatement->get_element());
4500 if (variableDeclarationCondition != NULL)
4501 {
4502 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4503 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4504 // ROSE_ASSERT(false);
4505
4506 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4507 }
4508 return;
4509 break;
4510 }
4511
4512 default:
4513 {
4514 printf ("Default reached in SageInterface::rebuildSymbolTable() scope = %p = %s \n",scope,scope->class_name().c_str());
4515 ROSE_ABORT();
4516 }
4517 }
4518
4519#if 0
4520 printf ("In SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4521#endif
4522
4523 // Generate a copy of the statement list (this is simpler than handling the cases of a
4524 // declaration list and a statement list separately for the scopes that contain one or the other.
4525 SgStatementPtrList statementList = scope->generateStatementList();
4526
4527 // Loop through the statements and for each declaration build a symbol and add it to the symbol table
4528 for (SgStatementPtrList::iterator i = statementList.begin(); i != statementList.end(); i++)
4529 {
4530 // At some point we should move this mechanism in to a factory patterns for SgSymbol
4531
4532 // printf ("Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4533
4534 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
4535 if (declaration != NULL)
4536 {
4537 // DQ (11/7/2007): Where there can be multiple declaration (e.g. function declarations with prototypes) only use one of them.
4538 bool useThisDeclaration = (declaration->get_firstNondefiningDeclaration() == declaration) ||
4539 ( (declaration->get_firstNondefiningDeclaration() == NULL) && (declaration->get_definingDeclaration() == declaration) );
4540
4541 list<SgSymbol*> symbolList;
4542 switch(declaration->variantT())
4543 {
4544 case V_SgTemplateInstantiationMemberFunctionDecl:
4545 {
4546 SgTemplateInstantiationMemberFunctionDecl* derivedDeclaration = isSgTemplateInstantiationMemberFunctionDecl(declaration);
4547 // 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
4548 if (scope == derivedDeclaration->get_scope())
4549 {
4550 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4551 ROSE_ASSERT(symbol != NULL);
4552
4553 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4554
4555 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s inserting a symbol = %p \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str(),symbol);
4556
4557 SgName name = derivedDeclaration->get_name();
4558 symbolTable->insert(name,symbol);
4559 }
4560 else
4561 {
4562 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4563
4564 // These IR nodes might only exist as a template declaration and thus not be structureally present in their scope.
4565 // So we would never traverse them in the correct scope and so never build sysmbols for them and add the symbols
4566 // to the correct symbol table. This is a fundamental problem. So we have to try to add these sorts of symbols
4567 // to the scope were they belong.
4568 SgScopeStatement* derivedDeclarationScope = derivedDeclaration->get_scope();
4569 ROSE_ASSERT(derivedDeclarationScope != NULL);
4570
4571 // If this is a copy then it would be nice to make sure that the scope has been properly set.
4572 // Check this by looking for the associated template declaration in the scope.
4573 // SgTemplateDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4574 // SgDeclarationStatement* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4575 SgTemplateMemberFunctionDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4576 ROSE_ASSERT(templateDeclaration != NULL);
4577 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_name());
4578
4579 // DQ (8/13/2013): Fixed the interface to avoid use of lookup_template_symbol() (removed).
4580 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
4581 // In this case these are unavailable from this point.
4582 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name());
4583 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4584 SgType* functionType = templateDeclaration->get_type();
4585 SgTemplateParameterPtrList & templateParameterList = templateDeclaration->get_templateParameters();
4586 // SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4587 SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_member_function_symbol(templateDeclaration->get_template_name(),functionType,&templateParameterList);
4588 if (templateSymbol != NULL)
4589 {
4590 // The symbol is not present, so we have to build one and add it.
4591#if 0
4592 printf ("Building a symbol for derivedDeclaration = %p = %s to an alternative symbol table in derivedDeclarationScope = %p \n",
4593 derivedDeclaration,get_name(derivedDeclaration).c_str(),derivedDeclarationScope);
4594#endif
4595 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4596 ROSE_ASSERT(symbol != NULL);
4597 SgName name = derivedDeclaration->get_name();
4598 derivedDeclarationScope->insert_symbol(name,symbol);
4599 }
4600 else
4601 {
4602 // printf ("The symbol was already present in the derivedDeclarationScope = %p \n",derivedDeclarationScope);
4603 }
4604 }
4605 break;
4606 }
4607
4608 // DQ (12/26/2012): Added support for templates.
4609 case V_SgTemplateMemberFunctionDeclaration:
4610
4611 case V_SgMemberFunctionDeclaration:
4612 {
4613 SgMemberFunctionDeclaration* derivedDeclaration = isSgMemberFunctionDeclaration(declaration);
4614
4615 // 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
4616 if (scope == derivedDeclaration->get_scope())
4617 {
4618 // SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4619 SgSymbol* symbol = NULL;
4620 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4621 symbol = new SgTemplateMemberFunctionSymbol(derivedDeclaration);
4622 else
4623 symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4624
4625 ROSE_ASSERT(symbol != NULL);
4626
4627 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4628
4629 SgName name = derivedDeclaration->get_name();
4630 symbolTable->insert(name,symbol);
4631 }
4632 else
4633 {
4634 // This happens when a defining declaration is located outside of the class where it is associated.
4635 // printf ("SgMemberFunctionDeclaration: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4636 }
4637 break;
4638 }
4639
4640 // DQ (2/26/2009): These have to be reformatted from where someone removed the formatting previously.
4641 case V_SgTemplateInstantiationFunctionDecl:
4642 {
4643 SgTemplateInstantiationFunctionDecl* derivedDeclaration = isSgTemplateInstantiationFunctionDecl(declaration);
4644 // 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)
4645 if (scope == derivedDeclaration->get_scope())
4646 {
4647 SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4648 ROSE_ASSERT(symbol != NULL);
4649 SgName name = derivedDeclaration->get_name();
4650 symbolTable->insert(name,symbol);
4651 }
4652 else
4653 {
4654 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4655 {
4656#if PRINT_DEVELOPER_WARNINGS
4657 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4658#endif
4659 }
4660 }
4661
4662 break;
4663 }
4664
4665 // DQ (12/24/2012): Added support for templates.
4666 case V_SgTemplateFunctionDeclaration:
4667
4668 case V_SgFunctionDeclaration:
4669 {
4670 SgFunctionDeclaration* derivedDeclaration = isSgFunctionDeclaration(declaration);
4671
4672 // 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)
4673
4674 if (useThisDeclaration == true)
4675 {
4676 if (scope == derivedDeclaration->get_scope())
4677 {
4678 // DQ (12/24/2012): Added support for templates.
4679 // SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4680 SgSymbol* symbol = NULL;
4681 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4682 symbol = new SgTemplateFunctionSymbol(derivedDeclaration);
4683 else
4684 symbol = new SgFunctionSymbol(derivedDeclaration);
4685
4686 ROSE_ASSERT(symbol != NULL);
4687 SgName name = derivedDeclaration->get_name();
4688 symbolTable->insert(name,symbol);
4689 }
4690 else
4691 {
4692 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4693 {
4694#if PRINT_DEVELOPER_WARNINGS
4695 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4696#endif
4697 }
4698 }
4699 }
4700 break;
4701 }
4702
4703 // DQ (12/28/2012): Adding support for templates.
4704 case V_SgTemplateVariableDeclaration:
4705
4706 case V_SgVariableDeclaration:
4707 {
4708 SgVariableDeclaration* derivedDeclaration = isSgVariableDeclaration(declaration);
4709 SgInitializedNamePtrList & variableList = derivedDeclaration->get_variables();
4710 SgInitializedNamePtrList::iterator i = variableList.begin();
4711 while ( i != variableList.end() )
4712 {
4714 ROSE_ASSERT(variable != NULL);
4715
4716 // DQ (10/20/2007): static data members declared outside the class scope don't generate symbols.
4717 if (variable->get_scope() == scope)
4718 {
4719 SgSymbol* symbol = new SgVariableSymbol(variable);
4720 ROSE_ASSERT(symbol != NULL);
4721
4722 // printf ("In SageInterface::rebuildSymbolTable() variable = %p building a new SgVariableSymbol = %p \n",variable,symbol);
4723
4724 SgName name = variable->get_name();
4725 symbolTable->insert(name,symbol);
4726 }
4727 else
4728 {
4729 // I think there is nothing to do in this case
4730 // 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);
4731 }
4732
4733 i++;
4734 }
4735
4736 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4737 // that also force symbols to be built in the current scope!
4738 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4739 if (derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4740 {
4741 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4742 ROSE_ASSERT(symbolTable != NULL);
4743 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4744 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4745 }
4746
4747 // ROSE_ASSERT(symbolList.empty() == false);
4748 break;
4749 }
4750
4751 case V_SgTemplateInstantiationDecl:
4752 {
4753 SgTemplateInstantiationDecl* derivedDeclaration = isSgTemplateInstantiationDecl(declaration);
4754#if 1
4755 // printf ("case SgTemplateInstantiationDecl: derivedDeclaration name = %s derivedDeclaration->get_declarationModifier().isFriend() = %s \n",
4756 // derivedDeclaration->get_name().str(),derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4757
4758 if (scope == derivedDeclaration->get_scope())
4759 {
4760 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4761 // printf ("Inserting SgClassSymbol = %p into scope = %p = %s \n",symbol,scope,scope->class_name().c_str());
4762 ROSE_ASSERT(symbol != NULL);
4763 SgName name = derivedDeclaration->get_name();
4764#if 0
4765 // DQ (10/21/2007): The scopes should match
4766 if (scope != derivedDeclaration->get_scope())
4767 {
4768 printf ("Error: scopes don't match for derivedDeclaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4769 }
4770 ROSE_ASSERT(scope == derivedDeclaration->get_scope());
4771#endif
4772 symbolTable->insert(name,symbol);
4773 }
4774 else
4775 {
4776 // printf ("SgTemplateInstantiationDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4777
4778 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4779 {
4780#if PRINT_DEVELOPER_WARNINGS
4781 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4782#endif
4783 }
4784 }
4785#else
4786 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4787 ROSE_ASSERT(symbol != NULL);
4788 SgName name = derivedDeclaration->get_name();
4789 symbolTable->insert(name,symbol);
4790#endif
4791 break;
4792 }
4793
4794
4795 // DQ (12/24/2012): Added support for templates.
4796 case V_SgTemplateClassDeclaration:
4797
4798 case V_SgClassDeclaration:
4799 {
4800 SgClassDeclaration* derivedDeclaration = isSgClassDeclaration(declaration);
4801#if 1
4802 if (scope == derivedDeclaration->get_scope())
4803 {
4804 SgSymbol* symbol = NULL;
4805 if (isSgTemplateClassDeclaration(declaration) != NULL)
4806 symbol = new SgTemplateClassSymbol(derivedDeclaration);
4807 else
4808 symbol = new SgClassSymbol(derivedDeclaration);
4809
4810 ROSE_ASSERT(symbol != NULL);
4811 SgName name = derivedDeclaration->get_name();
4812 symbolTable->insert(name,symbol);
4813 }
4814 else
4815 {
4816 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4817 {
4818#if PRINT_DEVELOPER_WARNINGS
4819 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4820#endif
4821 }
4822 }
4823#else
4824 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4825 ROSE_ASSERT(symbol != NULL);
4826 SgName name = derivedDeclaration->get_name();
4827 symbolTable->insert(name,symbol);
4828#endif
4829 break;
4830 }
4831
4832 case V_SgEnumDeclaration:
4833 {
4834 SgEnumDeclaration* derivedDeclaration = isSgEnumDeclaration(declaration);
4835 ROSE_ASSERT(derivedDeclaration != NULL);
4836 SgSymbol* symbol = new SgEnumSymbol(derivedDeclaration);
4837 ROSE_ASSERT(symbol != NULL);
4838 SgName name = derivedDeclaration->get_name();
4839 symbolTable->insert(name,symbol);
4840
4841 // DQ (10/18/2007): Fixed construction of symbol tabel to include enum fields.
4842 SgInitializedNamePtrList & enumFieldList = derivedDeclaration->get_enumerators();
4843 SgInitializedNamePtrList::iterator i = enumFieldList.begin();
4844
4845 // Iterate over enum fields and add each one to the symbol table.
4846 while (i != enumFieldList.end())
4847 {
4848 SgSymbol* enum_field_symbol = new SgEnumFieldSymbol(*i);
4849 ROSE_ASSERT(enum_field_symbol != NULL);
4850 SgName enum_field_name = (*i)->get_name();
4851 symbolTable->insert(enum_field_name,enum_field_symbol);
4852
4853 i++;
4854 }
4855
4856 break;
4857 }
4858
4859
4860 // DQ (2/18/2017): Added support for C++11 SgTemplateTypedefDeclaration.
4861 case V_SgTemplateTypedefDeclaration:
4862
4863 case V_SgTypedefDeclaration:
4864 {
4865 SgTypedefDeclaration* derivedDeclaration = isSgTypedefDeclaration(declaration);
4866 SgSymbol* symbol = new SgTypedefSymbol(derivedDeclaration);
4867 ROSE_ASSERT(symbol != NULL);
4868 SgName name = derivedDeclaration->get_name();
4869 symbolTable->insert(name,symbol);
4870#if 0
4871 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration \n");
4872#endif
4873 // DQ (10/13/2007): Need to look into typedefs to see if there are defining declaration
4874 // that also force symbols to be built in the current scope!
4875 // ROSE_ASSERT(derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == false);
4876 if (derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == true)
4877 {
4878 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4879 ROSE_ASSERT(symbolTable != NULL);
4880 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4881#if 0
4882 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == true calling supportForBaseTypeDefiningDeclaration() \n");
4883#endif
4884 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4885 }
4886 else
4887 {
4888 // DQ (11/7/2007): If the typedef has a definition (e.g. function pointer) then build a symbol.
4889 SgDeclarationStatement* declaration = derivedDeclaration->get_declaration();
4890 if (declaration != NULL)
4891 {
4892#if 0
4893 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false calling supportForBaseTypeDefiningDeclaration() \n");
4894#endif
4895 // 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).
4896 // supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_declaration() );
4897
4898 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false: skipping call to supportForBaseTypeDefiningDeclaration() \n");
4899 }
4900 }
4901#if 0
4902 printf ("In SageInterface::rebuildSymbolTable(): Leaving case of SgTypedefDeclaration \n");
4903#endif
4904 break;
4905 }
4906
4907 case V_SgTemplateDeclaration:
4908 {
4909 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4910#if 1
4911 // 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)
4912#if 0
4913 printf ("case V_SgTemplateDeclaration: derivedDeclaration = %p \n",derivedDeclaration);
4914 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_declarationModifier().isFriend() = %s \n",derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4915 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_name() = %s \n",derivedDeclaration->get_name().str());
4916 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_string() = %s \n",derivedDeclaration->get_string().str());
4917#endif
4918 if (scope == derivedDeclaration->get_scope())
4919 {
4920 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4921 ROSE_ASSERT(symbol != NULL);
4922 SgName name = derivedDeclaration->get_name();
4923 symbolTable->insert(name,symbol);
4924 }
4925 else
4926 {
4927 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4928 {
4929#if PRINT_DEVELOPER_WARNINGS
4930 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4931#endif
4932 }
4933 }
4934#else
4935 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4936 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4937 ROSE_ASSERT(symbol != NULL);
4938 SgName name = derivedDeclaration->get_name();
4939 symbolTable->insert(name,symbol);
4940#endif
4941 break;
4942 }
4943
4944 // Does this cause a symbol to be built? Seems that it should,
4945 // unless we always reference the non-aliased symbol (reuse it)!
4946 case V_SgNamespaceAliasDeclarationStatement:
4947 {
4948 SgNamespaceAliasDeclarationStatement* aliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
4949 ROSE_ASSERT(aliasDeclaration != NULL);
4950 ROSE_ASSERT(aliasDeclaration->get_namespaceDeclaration() != NULL);
4951
4952 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(aliasDeclaration->get_namespaceDeclaration());
4953 ROSE_ASSERT(derivedDeclaration != NULL);
4954
4955 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4956 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4957 ROSE_ASSERT(symbol != NULL);
4958 SgName name = derivedDeclaration->get_name();
4959 symbolTable->insert(name,symbol);
4960 // symbolList.push_back(symbol);
4961 // ROSE_ASSERT(symbolList.empty() == false);
4962 break;
4963 }
4964
4965 // Does this cause a symbol to be built? Seems that it should,
4966 // unless we always reference the non-aliased symbol (reuse it)!
4967 case V_SgNamespaceDeclarationStatement:
4968 {
4969 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(declaration);
4970 ROSE_ASSERT(derivedDeclaration != NULL);
4971
4972 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4973 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4974 ROSE_ASSERT(symbol != NULL);
4975 SgName name = derivedDeclaration->get_name();
4976 symbolTable->insert(name,symbol);
4977 // symbolList.push_back(symbol);
4978 // ROSE_ASSERT(symbolList.empty() == false);
4979 break;
4980 }
4981
4982 case V_SgUsingDirectiveStatement:
4983 case V_SgPragmaDeclaration:
4984 case V_SgTemplateInstantiationDirectiveStatement:
4985 case V_SgUsingDeclarationStatement:
4986 {
4987 // DQ (10/22/2005): Not sure if we have to worry about this declaration's appearance in the symbol table!
4988#if 0
4989 printf ("This declaration is ignored in rebuilding symbol table %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4990#endif
4991 break;
4992 }
4993
4994 case V_SgAsmStmt:
4995 {
4996 // DQ (8/13/2006): This is not really a declaration (I think). This will be fixed later.
4997#if 0
4998 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());
4999#endif
5000 break;
5001 }
5002
5003 // Cases where declations are not used or referenced and so symbols are not required!
5004 case V_SgVariableDefinition:
5005 case V_SgFunctionParameterList:
5006 case V_SgCtorInitializerList:
5007 // These are not referenced so they don't need a symbol!
5008 {
5009 printf ("Special cases not handled %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5010 ROSE_ABORT();
5011 }
5012
5013 case V_SgStaticAssertionDeclaration:
5014 {
5015 // DQ (2/18/2017): This is not really a declaration (I think). This will be fixed later.
5016#if 0
5017 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());
5018#endif
5019 break;
5020 }
5021
5022 default:
5023 {
5024 printf ("Error: Default reached in rebuildSymbolTable declaration = %p = %s \n",declaration,declaration->class_name().c_str());
5025 ROSE_ABORT();
5026 }
5027 }
5028
5029 ROSE_ASSERT(symbolTable != NULL);
5030 ROSE_ASSERT(symbolTable->get_table() != NULL);
5031 }
5032 // printf ("DONE: Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5033
5034 }
5035
5036 ROSE_ASSERT(symbolTable != NULL);
5037 ROSE_ASSERT(symbolTable->get_table() != NULL);
5038
5039#if 0
5040 printf ("Leaving SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
5041#endif
5042
5043#if 0
5044 printf ("Symbol Table from %p = %s at: \n",scope,scope->class_name().c_str());
5045 scope->get_file_info()->display("Symbol Table Location");
5046 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
5047#endif
5048 }
5049
5050
5051// #ifndef USE_ROSE
5052
5053void
5055 {
5056 // This function is called by the SageInterface::rebuildSymbolTable().
5057 // It resets references to old symbols to the new symbols (just built).
5058 // All pairs of old/new symbols are also saved in the object:
5059 // SgCopyHelp::copiedNodeMapType copiedNodeMap
5060
5061#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
5062 ROSE_ASSERT(this_scope != NULL);
5063 ROSE_ASSERT(copy_scope != NULL);
5064
5065#if 0
5066 printf ("In fixupReferencesToSymbols(this_scope = %p = %s = %s, copy_scope = %p = %s = %s) \n",
5067 this_scope,this_scope->class_name().c_str(),get_name(this_scope).c_str(),
5068 copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5069#endif
5070
5071 SgSymbolTable* this_symbolTable = this_scope->get_symbol_table();
5072 SgSymbolTable* copy_symbolTable = copy_scope->get_symbol_table();
5073#if 0
5074 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());
5075 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());
5076#endif
5077
5078 // DQ (3/4/2009): For now just output a warning, but this might be a more serious problem.
5079 // Since the symbol table size of the copy is larger than that of the original it might
5080 // be that a symbol is enterted twice by the copy mechanism. If so I want to fix this.
5081 if (this_symbolTable->get_table()->size() != copy_symbolTable->get_table()->size())
5082 {
5083 if (SgProject::get_verbose() > 0)
5084 {
5085 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());
5086 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());
5087 printf ("Warning the symbols tables in these different scopes are different sizes \n");
5088 }
5089 }
5090 // ROSE_ASSERT(this_symbolTable->get_table()->size() <= copy_symbolTable->get_table()->size());
5091
5092 SgSymbolTable::hash_iterator i = this_symbolTable->get_table()->begin();
5093
5094 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
5095 std::map<SgNode*, SgNode*> replacementMap;
5096 int counter = 0;
5097 while (i != this_symbolTable->get_table()->end())
5098 {
5099 ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL );
5100
5101 SgName name = (*i).first;
5102 // SgSymbol* symbol = isSgSymbol((*i).second);
5103 SgSymbol* symbol = (*i).second;
5104 ROSE_ASSERT ( symbol != NULL );
5105
5106 SgSymbol* associated_symbol = NULL;
5107#if 0
5108 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());
5109#endif
5110 // Look for the associated symbol in the copy_scope's symbol table.
5111 SgSymbolTable::hash_iterator associated_symbol_iterator = copy_symbolTable->get_table()->find(name);
5112
5113 // Note that this is a multi-map and for C++ a number of symbols can have the same name
5114 // (though not the same type of symbol) so we have to iterator over the symbols of the
5115 // same name so that we can identify the associated symbol.
5116 while (associated_symbol_iterator != copy_symbolTable->get_table()->end() && associated_symbol_iterator->first == name)
5117 {
5118 if ( associated_symbol_iterator->second->variantT() == symbol->variantT() )
5119 {
5120 associated_symbol = associated_symbol_iterator->second;
5121 }
5122
5123 associated_symbol_iterator++;
5124 }
5125
5126 if (associated_symbol != NULL)
5127 {
5128 ROSE_ASSERT ( associated_symbol != NULL );
5129
5130 // Check to make sure that this is correct
5131 ROSE_ASSERT(copy_scope->symbol_exists(associated_symbol) == true);
5132
5133 // Add the SgGlobal referenece to the replacementMap
5134 // replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
5135 // DQ (23/1/2009): Find the reference to symbol and replace it with associated_symbol.
5136 replacementMap.insert(pair<SgNode*,SgNode*>(symbol,associated_symbol));
5137
5138 // DQ (3/1/2009): This is backwards
5139 // replacementMap.insert(pair<SgNode*,SgNode*>(associated_symbol,symbol));
5140
5141 // DQ (3/2/2009): accumulate the symbol pair into the SgCopyHelp object (to support the outliner).
5142 // Actually this should also improve the robustness of the outliner.
5143 help.get_copiedNodeMap().insert(pair<const SgNode*,SgNode*>(symbol,associated_symbol));
5144 }
5145 else
5146 {
5147 // DQ (3/4/2009): This case was broken out because copytest2007_14.C fails here.
5148 if (SgProject::get_verbose() > 0)
5149 {
5150 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());
5151 printf ("Warning: associated_symbol == NULL, need to investigate this (ignoring for now) \n");
5152 }
5153 }
5154
5155 counter++;
5156
5157 i++;
5158 }
5159
5160#if 0
5161 printf ("\n\n************************************************************\n");
5162 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());
5163#endif
5164
5165 Rose::AST::Utility::edgePointerReplacement(copy_scope,replacementMap);
5166
5167#if 0
5168 printf ("fixupReferencesToSymbols(): calling Utils::edgePointerReplacement(): DONE \n");
5169 printf ("************************************************************\n\n");
5170
5171 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
5172 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
5173
5174 printf ("After fixup: this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_symbolTable->get_table()->size());
5175 printf ("After fixup: copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_symbolTable->get_table()->size());
5176#endif
5177
5178 // DQ (3/1/2009): find a case where this code is tested.
5179 // ROSE_ASSERT(this_symbolTable->get_table()->size() == 0);
5180 // ROSE_ASSERT(isSgClassDefinition(copy_scope) == NULL);
5181#endif
5182
5183#if 0
5184 printf ("Exiting as a test in fixupReferencesToSymbols() \n");
5185 ROSE_ABORT();
5186#endif
5187 }
5188
5189// #endif
5190
5191#ifndef USE_ROSE
5192
5193std::vector<SgFile*>
5195 {
5196 // This function uses a memory pool traversal specific to the SgFile IR nodes
5197 class FileTraversal : public ROSE_VisitTraversal
5198 {
5199 public:
5200 vector<SgFile*> fileList;
5201 void visit ( SgNode* node)
5202 {
5203 SgFile* file = isSgFile(node);
5204 ROSE_ASSERT(file != NULL);
5205 if (file != NULL)
5206 {
5207 fileList.push_back(file);
5208 }
5209 };
5210
5211 virtual ~FileTraversal() {}
5212 };
5213
5214 FileTraversal fileTraversal;
5215
5216 // traverse just the SgFile nodes (both the SgSourceFile and SgBinaryComposite IR nodes)!
5217 // SgFile::visitRepresentativeNode(fileTraversal);
5219#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5221#endif
5222
5223 // This would alternatively traverse all IR nodes in thememory pool!
5224 // fileTraversal.traverseMemoryPool();
5225
5226 // TV (06/24/2013): This fail when calling SageBuilder::buildVariableDeclaration(...) without any file created.
5227 // DQ (10/11/2014): This is allowed to be empty (required for new aterm support).
5228 // ROSE_ASSERT(fileTraversal.fileList.empty() == false);
5229
5230 return fileTraversal.fileList;
5231 }
5232
5233#endif
5234
5235// #ifndef USE_ROSE
5236
5237// DQ (4/17/2015): I think this function should be removed since it interferes
5238// with the concept of having more than one SgProject node.
5239// This function uses a memory pool traversal specific to the SgProject IR nodes
5240SgProject*
5242{
5243#if 0
5244 class ProjectTraversal : public ROSE_VisitTraversal
5245 {
5246 public:
5247 SgProject * project;
5248 void visit ( SgNode* node)
5249 {
5250 project = isSgProject(node);
5251 ROSE_ASSERT(project!= NULL);
5252 };
5253 virtual ~ProjectTraversal() {}
5254 };
5255
5256 ProjectTraversal projectTraversal;
5257 SgProject::visitRepresentativeNode(projectTraversal);
5258 return projectTraversal.project;
5259#endif
5260 std::vector<SgProject* > resultlist = getSgNodeListFromMemoryPool<SgProject>();
5261 if (resultlist.empty())
5262 return NULL;
5263 ROSE_ASSERT(resultlist.size()==1);
5264 return resultlist[0];
5265}
5266
5267SgProject*
5269 return getEnclosingNode<SgProject>(node, true /*includingSelf*/);
5270}
5271
5273 SgFunctionDeclaration * ret = NULL;
5274 if (isSgFunctionRefExp(func))
5275 {
5276 return isSgFunctionRefExp(func)->get_symbol()->get_declaration();
5277 }
5278 else if (isSgDotExp(func) || isSgArrowExp(func))
5279 {
5280 SgExpression* func2 = isSgBinaryOp(func)->get_rhs_operand();
5281 if (isSgMemberFunctionRefExp(func2))
5282 return isSgMemberFunctionRefExp(func2)->get_symbol()->get_declaration();
5283 else
5284 {
5285 cerr<<"Warning in SageInterface::getDeclarationOfNamedFunction(): rhs operand of dot or arrow operations is not a member function, but a "<<func2->class_name()<<endl;
5286 }
5287 }
5288
5289 return ret;
5290}
5291
5293 SgExprListExp* el = stmt->get_forall_header();
5294 const SgExpressionPtrList& ls = el->get_expressions();
5295 if (ls.empty()) return 0;
5296 if (isSgAssignOp(ls.back())) return 0;
5297 return ls.back();
5298}
5299
5300//Find all SgPntrArrRefExp under astNode, add the referenced dim_info SgVarRefExp (if any) into NodeList_t
5301void SageInterface::addVarRefExpFromArrayDimInfo(SgNode * astNode, Rose_STL_Container<SgNode *>& NodeList_t)
5302{
5303 ASSERT_not_null(astNode);
5304 Rose_STL_Container<SgNode*> arr_exp_list = NodeQuery::querySubTree(astNode,V_SgPntrArrRefExp);
5305 for (SgNode* expr : arr_exp_list)
5306 {
5307 SgPntrArrRefExp* arr_exp = isSgPntrArrRefExp(expr);
5308 ASSERT_not_null(arr_exp);
5309 Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp);
5310 for (SgNode* ref : refList)
5311 {
5312 SgVarRefExp* cur_ref = isSgVarRefExp(ref);
5313 ASSERT_not_null(cur_ref);
5314 SgVariableSymbol * sym = cur_ref->get_symbol();
5315 ASSERT_not_null(sym);
5316 SgInitializedName * iname = sym->get_declaration();
5317 ASSERT_not_null(iname);
5318 SgArrayType * a_type = isSgArrayType(iname->get_typeptr());
5319 if (a_type && a_type->get_dim_info())
5320 {
5321 Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp);
5322 for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++)
5323 {
5324 SgVarRefExp* dim_ref = isSgVarRefExp(*iter2);
5325 NodeList_t.push_back(dim_ref);
5326 }
5327 }
5328 }
5329 } // end for
5330}
5331
5332
5333// DQ (11/25/2020): This disables these non-inlined functions in favor of
5334// inlined versions of the functions in the sageInterface.h (header file).
5335#if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5336bool
5338 {
5339#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5340 // 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).
5341 return Rose::is_Ada_language;
5342#else
5343 bool returnValue = false;
5344
5345 vector<SgFile*> fileList = generateFileList();
5346
5347 int size = (int)fileList.size();
5348 for (int i = 0; i < size; i++)
5349 {
5350 if (fileList[i]->get_Ada_only() == true)
5351 returnValue = true;
5352 }
5353
5354 return returnValue;
5355#endif
5356 }
5357
5358bool
5360 {
5361#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5362 // 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).
5363 return Rose::is_C_language;
5364#else
5365 bool returnValue = false;
5366
5367 vector<SgFile*> fileList = generateFileList();
5368
5369 int size = (int)fileList.size();
5370 for (int i = 0; i < size; i++)
5371 {
5372 if (fileList[i]->get_C_only() == true)
5373 returnValue = true;
5374 }
5375
5376 return returnValue;
5377#endif
5378 }
5379
5380bool
5382 {
5383#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5384 // 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).
5385 return Rose::is_OpenMP_language;
5386#else
5387 bool returnValue = false;
5388
5389 vector<SgFile*> fileList = generateFileList();
5390
5391 int size = (int)fileList.size();
5392 for (int i = 0; i < size; i++)
5393 {
5394 if (fileList[i]->get_openmp() == true)
5395 returnValue = true;
5396 }
5397
5398 return returnValue;
5399#endif
5400 }
5401
5402bool
5404 {
5405#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5406 // 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).
5407 return Rose::is_UPC_language;
5408#else
5409 bool returnValue = false;
5410
5411 vector<SgFile*> fileList = generateFileList();
5412
5413 int size = (int)fileList.size();
5414 for (int i = 0; i < size; i++)
5415 {
5416 if (fileList[i]->get_UPC_only() == true)
5417 returnValue = true;
5418 }
5419
5420 return returnValue;
5421#endif
5422 }
5423
5424//FMZ
5425bool
5427 {
5428#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5429 // 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).
5430 return Rose::is_CAF_language;
5431#else
5432 bool returnValue = false;
5433
5434 vector<SgFile*> fileList = generateFileList();
5435
5436 int size = (int)fileList.size();
5437 for (int i = 0; i < size; i++)
5438 {
5439 if (fileList[i]->get_CoArrayFortran_only()==true)
5440 returnValue = true;
5441 }
5442
5443 return returnValue;
5444#endif
5445 }
5446
5447
5448// true if any of upc_threads is set to >0 via command line: -rose:upc_threads n
5449bool
5451 {
5452#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5453 // 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).
5454 return Rose::is_UPC_dynamic_threads;
5455#else
5456 bool returnValue = false;
5457
5458 vector<SgFile*> fileList = generateFileList();
5459
5460 int size = (int)fileList.size();
5461 for (int i = 0; i < size; i++)
5462 {
5463 if (fileList[i]->get_upc_threads() > 0)
5464 returnValue = true;
5465 }
5466
5467 return returnValue;
5468#endif
5469 }
5470
5471
5472
5473bool
5475 {
5476#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5477 // 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).
5478 return Rose::is_C99_language;
5479#else
5480 bool returnValue = false;
5481
5482 vector<SgFile*> fileList = generateFileList();
5483
5484 int size = (int)fileList.size();
5485 for (int i = 0; i < size; i++)
5486 {
5487 if (fileList[i]->get_C99_only() == true)
5488 returnValue = true;
5489 }
5490
5491 return returnValue;
5492#endif
5493 }
5494
5495bool
5497 {
5498#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5499 // 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).
5500 return Rose::is_Cxx_language;
5501#else
5502 bool returnValue = false;
5503
5504 vector<SgFile*> fileList = generateFileList();
5505
5506 int size = (int)fileList.size();
5507 for (int i = 0; i < size; i++)
5508 {
5509 // DQ (8/19/2007): Make sure this is not a Fortran code!
5510 if (fileList[i]->get_Cxx_only() == true)
5511 {
5512 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);
5513
5514 returnValue = true;
5515 }
5516 }
5517
5518 return returnValue;
5519#endif
5520 }
5521
5522bool
5524 {
5525#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5526 // 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).
5527 return Rose::is_Java_language;
5528#else
5529 bool returnValue = false;
5530
5531 vector<SgFile*> fileList = generateFileList();
5532
5533 int size = (int)fileList.size();
5534 for (int i = 0; i < size; i++)
5535 {
5536 if (fileList[i]->get_Java_only() == true)
5537 returnValue = true;
5538 }
5539
5540 return returnValue;
5541#endif
5542 }
5543
5544bool
5546 {
5547#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5548 // 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).
5549 return Rose::is_Jvm_language;
5550#else
5551 bool returnValue = false;
5552
5553 vector<SgFile*> fileList = generateFileList();
5554
5555 int size = (int)fileList.size();
5556 for (int i = 0; i < size; i++)
5557 {
5558 if (fileList[i]->get_Jvm_only() == true)
5559 returnValue = true;
5560 }
5561
5562 return returnValue;
5563#endif
5564 }
5565
5566// Rasmussen (4/4/2018): Added Jovial
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_Jovial_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_Jovial_only() == true)
5582 returnValue = true;
5583 }
5584
5585 return returnValue;
5586#endif
5587 }
5588
5589
5590bool
5592 {
5593#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5594 // 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).
5595 return Rose::is_Fortran_language;
5596#else
5597 bool returnValue = false;
5598
5599 vector<SgFile*> fileList = generateFileList();
5600
5601 int size = (int)fileList.size();
5602 for (int i = 0; i < size; i++)
5603 {
5604 if (fileList[i]->get_Fortran_only() == true)
5605 returnValue = true;
5606 }
5607
5608 return returnValue;
5609#endif
5610 }
5611
5612
5613bool
5615 {
5616#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5617 // 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).
5618 return Rose::is_binary_executable;
5619#else
5620 bool returnValue = false;
5621
5622 vector<SgFile*> fileList = generateFileList();
5623
5624 int size = (int)fileList.size();
5625 for (int i = 0; i < size; i++)
5626 {
5627 if (fileList[i]->get_binary_only() == true)
5628 returnValue = true;
5629 }
5630
5631 return returnValue;
5632#endif
5633 }
5634
5635bool
5637 {
5638#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5639 // 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).
5640 return Rose::is_PHP_language;
5641#else
5642 bool returnValue = false;
5643
5644 vector<SgFile*> fileList = generateFileList();
5645
5646 int size = (int)fileList.size();
5647 for (int i = 0; i < size; i++)
5648 {
5649 if (fileList[i]->get_PHP_only() == true)
5650 returnValue = true;
5651 }
5652
5653 return returnValue;
5654#endif
5655 }
5656
5657bool
5659 {
5660#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5661 // 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).
5662 return Rose::is_Python_language;
5663#else
5664 bool returnValue = false;
5665
5666 vector<SgFile*> fileList = generateFileList();
5667
5668 int size = (int)fileList.size();
5669 for (int i = 0; i < size; i++)
5670 {
5671 if (fileList[i]->get_Python_only() == true)
5672 returnValue = true;
5673 }
5674
5675 return returnValue;
5676#endif
5677 }
5678
5679bool
5681 {
5682#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5683 // 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).
5684 return Rose::is_Cuda_language;
5685#else
5686 bool returnValue = false;
5687
5688 vector<SgFile*> fileList = generateFileList();
5689
5690 int size = (int)fileList.size();
5691 for (int i = 0; i < size; i++)
5692 {
5693 if (fileList[i]->get_Cuda_only() == true)
5694 returnValue = true;
5695 }
5696
5697 return returnValue;
5698#endif
5699 }
5700
5701bool
5703 {
5704#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5705 // 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).
5706 return Rose::is_OpenCL_language;
5707#else
5708 bool returnValue = false;
5709
5710 vector<SgFile*> fileList = generateFileList();
5711
5712 int size = (int)fileList.size();
5713 for (int i = 0; i < size; i++)
5714 {
5715 if (fileList[i]->get_OpenCL_only() == true)
5716 returnValue = true;
5717 }
5718
5719 return returnValue;
5720#endif
5721 }
5722
5723// for if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5724#endif
5725
5730
5735
5740
5745
5750
5751// Languages that may have scopes that contain statements that are not only declarations.
5752// For Fortran and Jovial (at least), function definitions may be declared at the end of procedures.
5757
5758// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5759// labels for scopes in a function (as required for name mangling).
5760void
5762 {
5763 ASSERT_not_null(functionDefinition);
5764 std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5765
5766 // Clear the cache of stored (scope,integer) pairs
5767 scopeMap.erase(scopeMap.begin(),scopeMap.end());
5768
5769 ASSERT_require(scopeMap.empty() == true);
5770 ASSERT_require(functionDefinition->get_scope_number_list().empty() == true);
5771 }
5772
5773#ifndef USE_ROSE
5774
5775// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5776// labels for scopes in a function (as required for name mangling).
5777void
5779 {
5780 ROSE_ASSERT(functionDefinition != NULL);
5781 // std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5782 // ROSE_ASSERT(scopeMap.empty() == true);
5783 ROSE_ASSERT(functionDefinition->get_scope_number_list().empty() == true);
5784
5785 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5786 class ScopeNumberingTraversal : public AstSimpleProcessing
5787 {
5788 public:
5789 ScopeNumberingTraversal() : count (0), storedFunctionDefinition(NULL) {}
5790 void visit (SgNode* node)
5791 {
5792 SgScopeStatement* scope = isSgScopeStatement (node);
5793 if (scope != NULL)
5794 {
5795 // Set the function definition
5796 SgFunctionDefinition* testFunctionDefinition = isSgFunctionDefinition(scope);
5797 if (testFunctionDefinition != NULL && storedFunctionDefinition == NULL)
5798 {
5799 ROSE_ASSERT(storedFunctionDefinition == NULL);
5800 storedFunctionDefinition = testFunctionDefinition;
5801 }
5802
5803 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5804 ROSE_ASSERT(storedFunctionDefinition != NULL);
5805
5806 count++;
5807
5808 std::map<SgNode*,int> & scopeMap = storedFunctionDefinition->get_scope_number_list();
5809 scopeMap.insert(pair<SgNode*,int>(scope,count));
5810#if 0
5811 string functionName = storedFunctionDefinition->get_declaration()->get_name().str();
5812 printf ("In function = %s insert scope = %p = %s with count = %d into local map (size = %d) \n",
5813 functionName.c_str(),scope,scope->class_name().c_str(),count,scopeMap.size());
5814#endif
5815 }
5816 }
5817
5818 private:
5819 int count; // running total of scopes found in the input function
5820 SgFunctionDefinition* storedFunctionDefinition;
5821 };
5822
5823 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5824 ScopeNumberingTraversal traversal;
5825 traversal.traverse(functionDefinition, preorder);
5826 }
5827
5828#endif
5829
5830#ifndef USE_ROSE
5831
5832#if 0
5833// DQ (6/26/2007): These are removed and the support is added to SgNode to support a single mangled name cache.
5834// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5835// labels for scopes in a function (as required for name mangling).
5836void
5838 {
5839 ROSE_ASSERT(globalScope != NULL);
5840 std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5841
5842 // Clear the cache of stored (scope,integer) pairs
5843 mangledNameCache.erase(mangledNameCache.begin(),mangledNameCache.end());
5844
5845 ROSE_ASSERT(mangledNameCache.empty() == true);
5846 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5847 }
5848
5849// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5850// labels for scopes in a function (as required for name mangling).
5851void
5853 {
5854 ROSE_ASSERT(globalScope != NULL);
5855 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5856
5857 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5858 class MangledNameTraversal : public AstSimpleProcessing
5859 {
5860 public:
5861 MangledNameTraversal() : storedGlobalScope(NULL) {}
5862 void visit (SgNode* node)
5863 {
5864 SgFunctionDeclaration* mangleableNode = isSgFunctionDeclaration(node);
5865 if ( (mangleableNode != NULL) || (isSgGlobal(node) != NULL) )
5866 {
5867 // Set the global scope
5868 SgGlobal* testGlobalScope = isSgGlobal(mangleableNode);
5869 if (testGlobalScope != NULL && storedGlobalScope == NULL)
5870 {
5871 ROSE_ASSERT(storedGlobalScope == NULL);
5872 storedGlobalScope = testGlobalScope;
5873 }
5874
5875 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5876 ROSE_ASSERT(storedGlobalScope != NULL);
5877
5878 string mangledName = mangleableNode->get_mangled_name();
5879 // printf ("mangledName = %s \n",mangledName.c_str());
5880
5881 std::map<SgNode*,std::string> & mangledNameCache = storedGlobalScope->get_mangledNameCache();
5882 mangledNameCache.insert(pair<SgNode*,std::string>(mangleableNode,mangledName));
5883#if 0
5884 string nodeName = get_name(mangleableNode);
5885 printf ("At node = %p = %s = %s in local map (size = %d) \n",
5886 mangleableNode,mangleableNode->class_name().c_str(),nodeName.c_str(),mangledNameCache.size());
5887#endif
5888 }
5889 }
5890
5891 private:
5892 SgGlobal* storedGlobalScope;
5893 };
5894
5895 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5896 MangledNameTraversal traversal;
5897 traversal.traverse(globalScope, preorder);
5898 }
5899#endif
5900
5901
5902string
5904 {
5905 // The TransformationSupport is not defined yet (I forget the
5906 // details but I recall that there is a reason why this is this way).
5907 // SgGlobal* globalScope = TransformationSupport::getGlobalScope(astNode);
5908#if 0
5909 SgGlobal* globalScope = isSgGlobal(astNode);
5910
5911 if (globalScope == NULL && isSgFile(astNode) != NULL)
5912 {
5913 globalScope = isSgFile(astNode)->get_globalScope();
5914 ROSE_ASSERT(globalScope != NULL);
5915 }
5916
5917 if (globalScope == NULL && isSgProject(astNode) != NULL)
5918 {
5919 // Check to make sure that the SgFile can be uniquely determined
5920 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5921 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5922 ROSE_ASSERT(globalScope != NULL);
5923 }
5924
5925 SgNode* temp = astNode;
5926 while (temp->get_parent() != NULL && globalScope == NULL)
5927 {
5928 temp = temp->get_parent();
5929 globalScope = isSgGlobal(temp);
5930 }
5931 ROSE_ASSERT(globalScope != NULL);
5932#endif
5933
5934 // std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5935 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
5936
5937 // Build an iterator
5938 std::map<SgNode*,std::string>::iterator i = mangledNameCache.find(astNode);
5939
5940 string mangledName;
5941 if (i != mangledNameCache.end())
5942 {
5943 // get the precomputed mangled name!
5944 //~ printf ("Mangled name IS found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5945 mangledName = i->second;
5946 }
5947 else
5948 {
5949 // mangled name not found in cache!
5950 //~ printf ("Mangled name NOT found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5951 }
5952
5953 return mangledName;
5954 }
5955
5956#define DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE 0
5957#define DEBUG_MANGLED_SHORTNAME 1
5958
5959//#ifdef DEBUG_MANGLED_SHORTNAME
5960//std::unordered_map<uint64_t, std::string> SageInterface::mangledNameHashCollisionCheckMap;
5961//#endif
5962
5963std::string
5964SageInterface::addMangledNameToCache( SgNode* astNode, const std::string & oldMangledName)
5965 {
5966#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
5967 printf ("In SageInterface::addMangledNameToCache(): TOP: astNode = %p = %s oldMangledName = %s \n",astNode,astNode->class_name().c_str(),oldMangledName.c_str());
5968#endif
5969
5970//#define DEBUG_MANGLED_SHORTNAME 1
5971#ifdef DEBUG_MANGLED_SHORTNAME
5972 static std::unordered_map<uint64_t, std::string> mangledNameHashCollisionCheckMap;
5973#endif
5974
5975
5976#if 0
5977 SgGlobal* globalScope = isSgGlobal(astNode);
5978
5979 if (globalScope == NULL && isSgFile(astNode) != NULL)
5980 {
5981 globalScope = isSgFile(astNode)->get_globalScope();
5982 ROSE_ASSERT(globalScope != NULL);
5983 }
5984
5985 if (globalScope == NULL && isSgProject(astNode) != NULL)
5986 {
5987 // Check to make sure that the SgFile can be uniquely determined
5988 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5989 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5990 ROSE_ASSERT(globalScope != NULL);
5991 }
5992
5993 SgNode* temp = astNode;
5994 while (temp->get_parent() != NULL && globalScope == NULL)
5995 {
5996 temp = temp->get_parent();
5997 globalScope = isSgGlobal(temp);
5998 }
5999 ROSE_ASSERT(globalScope != NULL);
6000#endif
6001
6002 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
6003
6004 std::string mangledName;
6005
6006 if (SgProject::get_mangled_noshortname() == false) {
6007 std::map<std::string, uint64_t> & shortMangledNameCache = SgNode::get_shortMangledNameCache();
6008
6009 if (oldMangledName.size() > 40) {
6010 std::map<std::string, uint64_t>::const_iterator shortMNIter = shortMangledNameCache.find(oldMangledName);
6011 uint64_t idNumber = 0;
6012 if (shortMNIter != shortMangledNameCache.end())
6013 {
6014 idNumber = shortMNIter->second;
6015
6016#ifdef DEBUG_MANGLED_SHORTNAME
6017 //Check for hash colisions, if we found an idNumber, but the long mangled name is different, we have a problem
6018 auto collisionIt = mangledNameHashCollisionCheckMap.find(idNumber);
6019 if(collisionIt != mangledNameHashCollisionCheckMap.end() &&
6020 oldMangledName != shortMNIter->first)
6021 {
6022 mlog[Sawyer::Message::Common::ERROR] <<" Got a short mangled name collision. \n "<<
6023 oldMangledName << " and \n " << shortMNIter->first << " \n" <<
6024 "have the same idNumber of: " << Combinatorics::toBase62String(idNumber) << " " << shortMNIter->second << endl;
6025 exit(12);
6026 } else {
6027 mangledNameHashCollisionCheckMap[idNumber] = oldMangledName;
6028 }
6029#endif //DEBUG_MANGLED_SHORTNAME
6030
6031 }
6032 else
6033 {
6035 hasher.insert(oldMangledName);
6036 hasher.digest();
6037 idNumber = hasher.make64Bits();
6038 shortMangledNameCache.insert(std::pair<std::string, uint64_t>(oldMangledName, idNumber));
6039 }
6040
6041 std::ostringstream mn;
6042 mn << 'L' << Combinatorics::toBase62String(idNumber) << 'R';
6043 mangledName = mn.str();
6044 } else {
6045 mangledName = oldMangledName;
6046 }
6047 } else {
6048
6049 // DQ (7/24/2012): Note that using this option can cause some test codes using operators that have
6050 // difficult names (conversion operators to user-defined types) to fail. See test2004_141.C for example.
6051 // The conversion operator "operator T&() const;" will fail because the character "&" will remain in
6052 // mangled name. The substring coding changes the strings for the mangled names and this effectively
6053 // removes the special characters, but there could be cases where they might remain.
6054
6055 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6056 static unsigned long counter = 0;
6057
6058 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6059 // This supports debugging the new EDG 4.x interface...
6060 if (counter++ % 500 == 0)
6061 {
6062 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");
6063 }
6064 mangledName = oldMangledName;
6065}
6066
6067 // DQ (6/26/2007): Output information useful for understanding Jeremiah's shortended name merge caching.
6068 // std::cerr << "Changed MN " << oldMangledName << " to " << mangledName << std::endl;
6069
6070#if 0
6071 printf ("Updating mangled name cache for node = %p = %s with mangledName = %s \n",astNode,astNode->class_name().c_str(),mangledName.c_str());
6072#endif
6073
6074#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
6075 SgStatement* statement = isSgStatement(astNode);
6076 if (statement != NULL && statement->hasExplicitScope() == true)
6077 {
6078 if (statement->get_scope() == NULL)
6079 {
6080 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",
6081 statement,statement->class_name().c_str(),oldMangledName.c_str());
6082 }
6083 }
6084#endif
6085
6086 mangledNameCache.insert(pair<SgNode*,string>(astNode,mangledName));
6087
6088#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
6089 printf ("In SageInterface::addMangledNameToCache(): returning mangledName = %s \n",mangledName.c_str());
6090#endif
6091
6092 return mangledName;
6093 }
6094
6095
6096// #endif
6097
6098#ifndef USE_ROSE
6099
6100bool
6102 {
6103 // This function is used in the unparser, but might be more generally useful. Since it is
6104 // related to general AST tests, I have put it here. It might be alternatively put in the
6105 // src/backend/unparser or related utility directory.
6106
6107 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6108 // declarations in the preorder traversal of the AST.
6109 class DeclarationOrderTraversal : public AstSimpleProcessing
6110 {
6111 public:
6112 DeclarationOrderTraversal( SgDeclarationStatement* nonDefiningDeclaration, SgDeclarationStatement* definingDeclaration )
6113 : storedNondefiningDeclaration(nonDefiningDeclaration),
6114 storedDefiningDeclaration(definingDeclaration)
6115 {
6116 storedDeclarationFound = false;
6117 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6118 }
6119
6120 void visit (SgNode* node)
6121 {
6122 ROSE_ASSERT(storedNondefiningDeclaration != NULL);
6123 ROSE_ASSERT(storedDefiningDeclaration != NULL);
6124 ROSE_ASSERT(storedNondefiningDeclaration != storedDefiningDeclaration);
6125 // ROSE_ASSERT(storedNondefiningDeclaration->get_definingDeclaration() == storedDefiningDeclaration);
6126
6127 // Even though we only care about the SgClassDeclaration IR nodes we have to traverse them
6128 // in the AST in the order defined by the traversal (order of apprearance in the AST). We
6129 // also can't just search the declarations of a single scope (since the nondefining declaration
6130 // can appear in a different scope than the defining declaration).
6131 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6132 if ( declaration != NULL )
6133 {
6134 if (storedDeclarationFound == false)
6135 {
6136 if (declaration == storedDefiningDeclaration)
6137 {
6138 storedDeclarationFound = true;
6139 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6140 }
6141 if (declaration == storedNondefiningDeclaration)
6142 {
6143 storedDeclarationFound = true;
6144 nonDefiningDeclarationPreceedsDefiningDeclaration = true;
6145 }
6146 }
6147 }
6148 }
6149
6150 public:
6151 bool storedDeclarationFound;
6152 bool nonDefiningDeclarationPreceedsDefiningDeclaration;
6153
6154 private:
6155 SgDeclarationStatement* storedNondefiningDeclaration;
6156 SgDeclarationStatement* storedDefiningDeclaration;
6157 };
6158
6159 ROSE_ASSERT(nonDefiningDeclaration != NULL);
6160#if 0
6161 printf ("In SageInterface::declarationPreceedsDefinition(): \n");
6162 printf (" nondefiningDeclaration = %p = %s \n",nonDefiningDeclaration,nonDefiningDeclaration->class_name().c_str());
6163 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6164 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6165 printf (" definingDeclaration = %p = %s \n",definingDeclaration,definingDeclaration->class_name().c_str());
6166 definingDeclaration->get_file_info()->display("definingDeclaration");
6167 printf ("************************************************************* \n");
6168#endif
6169
6170#if 0
6171 // The nonDefiningDeclaration can be a different type of declaration than the definingDeclaration
6172 if (nonDefiningDeclaration->get_definingDeclaration() != definingDeclaration)
6173 {
6174 printf ("In SageInterface::declarationPreceedsDefinition() (warning): \n");
6175 printf (" nondefiningDeclaration = %p \n",nonDefiningDeclaration);
6176 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6177 printf (" definingDeclaration = %p \n",definingDeclaration);
6178 }
6179#endif
6180
6181 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6182 bool returnResult = false;
6183 if (nonDefiningDeclaration != definingDeclaration)
6184 {
6185 // Get the global scope from a traversal back (up) through the AST.
6186 SgGlobal* globalScope = TransformationSupport::getGlobalScope(definingDeclaration);
6187 ROSE_ASSERT(globalScope != NULL);
6188
6189 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6190 DeclarationOrderTraversal traversal (nonDefiningDeclaration,definingDeclaration);
6191
6192#if 0
6193 traversal.traverse(globalScope, preorder);
6194#else
6195 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6196 printf ("Skipping traversal within SageInterface::declarationPreceedsDefinition() \n");
6197 traversal.storedDeclarationFound = true;
6198 traversal.nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6199#endif
6200
6201 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6202 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6203 // nondefining declarations that are not in the traversal).
6204
6205 if (traversal.storedDeclarationFound == false)
6206 {
6207#if 0
6208 printf ("In SageInterface::declarationPreceedsDefinition(): warning, nonDefiningDeclaration not found in the AST \n");
6209 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6210 definingDeclaration->get_file_info()->display("definingDeclaration");
6211 printf ("---------------------------------------------------- \n\n");
6212#endif
6213 // Set this error case to return true so that we will not assume incorrectly
6214 // that the classNonDefiningDeclaration apears after the classDefiningDeclaration.
6215 returnResult = true;
6216 }
6217 else
6218 {
6219 returnResult = traversal.nonDefiningDeclarationPreceedsDefiningDeclaration;
6220 }
6221
6222 // ROSE_ASSERT(traversal.storedDeclarationFound == true);
6223 }
6224#if 0
6225 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6226 printf ("************************************************************* \n\n");
6227#endif
6228 return returnResult;
6229 }
6230
6231
6232bool
6234 {
6235 // This function is used in the unparser, but might be more generally useful. Since it is
6236 // related to general AST tests, I have put it here. It might be alternatively put in the
6237 // src/backend/unparser or related utility directory.
6238
6239 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6240 // declarations in the preorder traversal of the AST.
6241 class DeclarationOrderTraversal : public AstSimpleProcessing
6242 {
6243 public:
6244 DeclarationOrderTraversal( SgFunctionCallExp* functionCall )
6245 : storedFunctionCall(functionCall)
6246 {
6247 ROSE_ASSERT(functionCall != NULL);
6248 ROSE_ASSERT(functionCall->get_function() != NULL);
6249 SgExpression* functionExpression = functionCall->get_function();
6250
6251 switch (functionExpression->variantT())
6252 {
6253 // these are the acceptable cases
6254 case V_SgDotExp:
6255 case V_SgDotStarOp:
6256 case V_SgArrowExp:
6257 case V_SgArrowStarOp:
6258 case V_SgPointerDerefExp:
6259 {
6260 // These are the acceptable cases, but not handled yet.
6261 printf ("These are the acceptable cases, but not handled yet... \n");
6262 ROSE_ABORT();
6263 }
6264
6265 case V_SgFunctionRefExp:
6266 {
6267 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression);
6268 ROSE_ASSERT(functionRefExp != NULL);
6269 SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol();
6270 ROSE_ASSERT(functionSymbol != NULL);
6271
6272 // Make sure that the function has a valid declaration
6273 ROSE_ASSERT(functionSymbol->get_declaration() != NULL);
6274 storedFunctionDeclaration = functionSymbol->get_declaration();
6275 break;
6276 }
6277
6278 case V_SgMemberFunctionRefExp:
6279 {
6280 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression);
6281 ROSE_ASSERT(memberFunctionRefExp != NULL);
6282 SgMemberFunctionSymbol* memberFunctionSymbol = memberFunctionRefExp->get_symbol();
6283 ROSE_ASSERT(memberFunctionSymbol != NULL);
6284
6285 storedFunctionDeclaration = memberFunctionSymbol->get_declaration();
6286
6287 printf ("V_SgMemberFunctionRefExp case not handled yet... \n");
6288 ROSE_ABORT();
6289 }
6290
6291 default:
6292 {
6293 printf ("default reached in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() functionExpression = %s \n",
6294 functionExpression->class_name().c_str());
6295 ROSE_ABORT();
6296 }
6297 }
6298 // ROSE_ASSERT(functionCall->get_declaration() != NULL);
6299 // ROSE_ASSERT(functionCall->get_function()->get_firstNondefiningDeclaration() != NULL);
6300 // storedFunctionDeclaration = functionCall->get_declaration()->get_firstNondefiningDeclaration();
6301 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6302
6303 storedFunctionCallFound = false;
6305 }
6306
6307 void visit (SgNode* node)
6308 {
6309 ROSE_ASSERT(storedFunctionCall != NULL);
6310 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6311 // ROSE_ASSERT(storedFunctionCall != storedFunctionDeclaration);
6312
6313 if (storedFunctionCallFound == false)
6314 {
6315 SgFunctionCallExp* functionCall = isSgFunctionCallExp(node);
6316 if ( functionCall != NULL )
6317 {
6318 if (functionCall == storedFunctionCall)
6319 {
6320 storedFunctionCallFound = true;
6321
6322 // A declaration for the function in a scope where the function could be defined
6323 // (and a scope associated with it) has not been found so the function call
6324 // preceeds such a declaration (if it even exists).
6326 }
6327 }
6328
6329 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6330 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6331
6332 // Note that all firstNondefiningDeclaration are set to the same declaration (for all associated declarations).
6333 // Need to check the result of get_firstNondefiningDeclaration() since this will be the same for all declarations
6334 // of the same function and thus can be used to match that we have an associated declaration for the same function.
6335 if ( declaration != NULL && declaration->get_firstNondefiningDeclaration() == storedFunctionDeclaration->get_firstNondefiningDeclaration())
6336 {
6337 // Test if this is a declaration is a scope where the existance of the forward
6338 // declaration will define the scope fo the function declaration.
6339 SgScopeStatement* parentScopeOfDeclaration = isSgScopeStatement(declaration->get_parent());
6340 if (parentScopeOfDeclaration != NULL && parentScopeOfDeclaration->supportsDefiningFunctionDeclaration() == true)
6341 {
6342 // We are done so we can skip further testing
6343 storedFunctionCallFound = true;
6344
6345 // We have found a declaration which will associated the scope of a function declaration
6346 // (so all function calls after this point can be qualified (and might have to be).
6348#if 0
6349 printf ("Found a declaration which preceeds the function \n");
6350 declaration->get_file_info()->display("Found a declaration which preceeds the function: declaration");
6351 storedFunctionCall->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionCall");
6352 storedFunctionDeclaration->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionDeclaration");
6353#endif
6354 }
6355 else
6356 {
6357 // Error checking!
6358 if (parentScopeOfDeclaration == NULL)
6359 {
6360 // This might be a function declaration (non-defining) used in a type or buried deeply in some sort of declaration!
6361 printf ("Strange case of parentScopeOfDeclaration == NULL in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6362 SgNode* parent = declaration->get_parent();
6363 if (parent != NULL) {
6364 printf ("declaration->get_parent() = %s \n",parent->class_name().c_str());
6365 }
6366 else {
6367 printf ("declaration->get_parent() = NULL \n");
6368 }
6369 declaration->get_file_info()->display("case of parentScopeOfDeclaration == NULL");
6370 ROSE_ABORT();
6371 }
6372 }
6373 }
6374 }
6375 }
6376
6377 public:
6378 bool storedFunctionCallFound;
6380
6381 private:
6382 SgFunctionCallExp* storedFunctionCall;
6383 SgDeclarationStatement* storedFunctionDeclaration;
6384 };
6385
6386 ROSE_ASSERT(functionCall != NULL);
6387#if 0
6388 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): \n");
6389 printf (" storedFunctionCall = %p = %s \n",functionCall,functionCall->class_name().c_str());
6390 functionCall->get_file_info()->display("storedFunctionCall");
6391 printf (" storedFunctionCall->get_function() = %p = %s \n",functionCall->get_function(),functionCall->get_function()->class_name().c_str());
6392 printf ("************************************************************* \n");
6393#endif
6394
6395 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6396 bool returnResult = false;
6397
6398 // Get the global scope from a traversal back (up) through the AST.
6399 SgGlobal* globalScope = TransformationSupport::getGlobalScope(functionCall);
6400 ROSE_ASSERT(globalScope != NULL);
6401
6402 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6403 DeclarationOrderTraversal traversal (functionCall);
6404
6405#if 0
6406 traversal.traverse(globalScope, preorder);
6407#else
6408 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6409 printf ("Skipping traversal within SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6410 traversal.storedFunctionCallFound = true;
6411 traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope = false;
6412#endif
6413
6414 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6415 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6416 // nondefining declarations that are not in the traversal).
6417
6418 if (traversal.storedFunctionCallFound == false)
6419 {
6420#if 0
6421 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): warning, storedFunctionCall not found in the AST \n");
6422 functionCall->get_file_info()->display("functionCall");
6423 printf ("---------------------------------------------------- \n\n");
6424#endif
6425 // Set this error case to return true so that we will not assume incorrectly
6426 // that the function call is used after a declaration that associated the scope
6427 // with the function. This still causes the global name qualifier to be omitted.
6428 returnResult = true;
6429 }
6430 else
6431 {
6432 returnResult = traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope;
6433 }
6434
6435 // I hope that this is nearly always be true!
6436 ROSE_ASSERT(traversal.storedFunctionCallFound == true);
6437#if 0
6438 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6439 printf ("************************************************************* \n\n");
6440#endif
6441 return returnResult;
6442 }
6443
6444#endif
6445
6446// #ifndef USE_ROSE
6447
6448string
6449SageInterface::generateProjectName( const SgProject* project, bool supressSuffix )
6450 {
6451 // This function generates a string to use as a unique project name for
6452 // a collection of files. The last file will include it's suffix so that
6453 // we generate proper names that communicate the source language.
6454 // Also also allows the single file case to be consistant with the previous
6455 // version of names generated for "DOT" files in the tutorial.
6456
6457 // DQ (9/6/2008): Introduced optional parameter to supresse the suffix in the
6458 // generation of the project name so that we can support more complex name
6459 // construction as required for the generation of names for the whole AST
6460 // graphs which append an additional suffix to avoid filename collision.
6461
6462 ROSE_ASSERT(project != NULL);
6463 string projectName;
6464
6465 // DQ (9/2/2008): Removed the redundant function getFileNames().
6466 // Rose_STL_Container<string> fileList = project->get_sourceFileNameList();
6467 Rose_STL_Container<string> fileList = project->getAbsolutePathFileNames();
6468
6469 Rose_STL_Container<string>::iterator i = fileList.begin();
6470
6471 // Handle the case of an empty list (e.g. for link lines).
6472 if ( fileList.empty() == true )
6473 {
6474 return "empty_file_list";
6475 }
6476
6477 do {
6478 string filename = *i;
6479
6480 // printf ("In SageInterface::generateProjectName(): absolute filename = %s \n",filename.c_str());
6481
6482 // string filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6483
6484 if (i != fileList.begin())
6485 projectName += "--";
6486
6487 i++;
6488
6489 string filenameWithoutSuffix;
6490 if ( i != fileList.end() || supressSuffix == true )
6491 filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6492 else
6493 filenameWithoutSuffix = filename;
6494
6495 string filenameWithoutPathOrSuffix = StringUtility::stripPathFromFileName(filenameWithoutSuffix);
6496
6497 // printf ("filenameWithoutSuffix = %s \n",filenameWithoutSuffix.c_str());
6498 // printf ("filenameWithoutPathOrSuffix = %s \n",filenameWithoutPathOrSuffix.c_str());
6499
6500 filename = filenameWithoutPathOrSuffix;
6501
6502 unsigned long int n = 0;
6503 while (n < filename.size())
6504 {
6505 if (filename[n] == '/')
6506 filename[n] = '_';
6507 n++;
6508 }
6509
6510 // printf ("In SageInterface:generateProjectName(): modified absolute filename = %s \n",filename.c_str());
6511
6512 projectName += filename;
6513
6514 // printf ("In SageInterface:generateProjectName(): evolving projectName = %s \n",projectName.c_str());
6515 }
6516 while (i != fileList.end());
6517
6518 // printf ("In SageInterface:generateProjectName(): projectName = %s \n",projectName.c_str());
6519
6520 return projectName;
6521 }
6522
6523// #endif
6524
6525// #ifndef USE_ROSE
6526
6529 {
6530 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6531 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6532
6533 // enable default search from top of StackScope, Liao, 1/24/2008
6534 SgFunctionSymbol* functionSymbol = NULL;
6535 if (currentScope == NULL)
6536 currentScope = SageBuilder::topScopeStack();
6537 ROSE_ASSERT(currentScope != NULL);
6538
6539 SgScopeStatement* tempScope = currentScope;
6540 while ((functionSymbol == NULL) && (tempScope != NULL))
6541 {
6542 functionSymbol = tempScope->lookup_function_symbol(functionName);
6543#if 0
6544 printf ("In lookupFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6545#endif
6546 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6547 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6548 else
6549 tempScope = NULL;
6550 }
6551 return functionSymbol;
6552 }
6553
6555SageInterface::lookupTemplateFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6556 {
6557 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6558 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6559
6560 // enable default search from top of StackScope, Liao, 1/24/2008
6561 SgFunctionSymbol* functionSymbol = NULL;
6562 if (currentScope == NULL)
6563 currentScope = SageBuilder::topScopeStack();
6564 ROSE_ASSERT(currentScope != NULL);
6565
6566 SgScopeStatement* tempScope = currentScope;
6567 while ((functionSymbol == NULL) && (tempScope != NULL))
6568 {
6569 functionSymbol = tempScope->lookup_template_function_symbol(functionName, ftype, tplparams);
6570#if 0
6571 printf ("In lookupTemplateFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6572#endif
6573 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6574 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6575 else
6576 tempScope = NULL;
6577 }
6578 return functionSymbol;
6579 }
6580
6582SageInterface::lookupTemplateMemberFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6583 {
6584 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6585 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6586
6587 // enable default search from top of StackScope, Liao, 1/24/2008
6588 SgFunctionSymbol* functionSymbol = NULL;
6589 if (currentScope == NULL)
6590 currentScope = SageBuilder::topScopeStack();
6591 ROSE_ASSERT(currentScope != NULL);
6592
6593 SgScopeStatement* tempScope = currentScope;
6594 while ((functionSymbol == NULL) && (tempScope != NULL))
6595 {
6596 functionSymbol = tempScope->lookup_template_member_function_symbol(functionName, ftype, tplparams);
6597#if 0
6598 printf ("In lookupTemplateMemberFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6599#endif
6600 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6601 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6602 else
6603 tempScope = NULL;
6604 }
6605 return functionSymbol;
6606 }
6607
6608void
6609SageInterface::addTextForUnparser ( SgNode* astNode, string s, AstUnparseAttribute::RelativePositionType inputlocation )
6610 {
6611 // printf ("addText(): using new attribute interface (s = %s) \n",s.c_str());
6612
6613 if (isSgType(astNode) != NULL)
6614 {
6615 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");
6616 ROSE_ABORT();
6617 }
6618
6619 if (astNode->attributeExists(AstUnparseAttribute::markerName) == true)
6620 {
6621 AstUnparseAttribute* code = dynamic_cast<AstUnparseAttribute*>(astNode->getAttribute(AstUnparseAttribute::markerName));
6622 ROSE_ASSERT(code != NULL);
6623
6624 // DQ (2/23/2009): commented added.
6625 // Since there is at least one other string (there is an existing attribute) the relative order of the strings is significant.
6626 code->addString(s,inputlocation);
6627 }
6628 else
6629 {
6630 // DQ (2/25/2016): I think it is significant, because inputlocation refers to the order relative to
6631 // the statement, not relative to other AstUnparseAttribute objects. Fixed to use the inputlocation.
6632 // DQ (2/23/2009): commented added.
6633 // Note that this will be the only string in the attribute, so inputlocation is not significant (and e_before is the default used).
6634 // AstUnparseAttribute* code = new AstUnparseAttribute(s,AstUnparseAttribute::e_before);
6635 AstUnparseAttribute* code = new AstUnparseAttribute(s,inputlocation);
6636 ROSE_ASSERT(code != NULL);
6637
6638 astNode->addNewAttribute(AstUnparseAttribute::markerName,code);
6639 }
6640 }
6641
6642
6643#if 0
6644// DQ (7/20/2011): Resolving conflict, this was added in previous work in dq-cxx-rc branch.
6645// DQ (7/17/2011): Added function from cxx branch that I need here for the Java support.
6648 {
6649 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6650 SgClassSymbol* symbol = NULL;
6651 if (cscope == NULL)
6652 cscope = SageBuilder::topScopeStack();
6653 ROSE_ASSERT(cscope != NULL);
6654
6655 while ((cscope != NULL) && (symbol == NULL))
6656 {
6657 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6658 symbol = cscope->lookup_class_symbol(name,NULL);
6659
6660 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6661 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6662 else
6663 cscope = NULL;
6664 }
6665
6666 return symbol;
6667 }
6668#endif
6669
6670
6671
6672SgType* SageInterface::lookupNamedTypeInParentScopes(const std::string& type_name, SgScopeStatement* scope/*=NULL*/)
6673 {
6674 if (scope == NULL)
6676
6677 // DQ (8/16/2013): Added NULL pointers to at least handle the API change.
6678 SgSymbol* symbol = lookupSymbolInParentScopes (type_name,scope,NULL,NULL);
6679
6680 if (symbol == NULL)
6681 return NULL;
6682 else
6683 return symbol->get_type();
6684 }
6685
6687 const SgType* t,
6688 SgScopeStatement *currentScope)
6689 //SgScopeStatement *currentScope=NULL)
6690{
6691 SgFunctionSymbol* functionSymbol = NULL;
6692 if (currentScope == NULL)
6693 currentScope = SageBuilder::topScopeStack();
6694 ROSE_ASSERT(currentScope != NULL);
6695 SgScopeStatement* tempScope = currentScope;
6696 while (functionSymbol == NULL && tempScope != NULL)
6697 {
6698 functionSymbol = tempScope->lookup_function_symbol(functionName,t);
6699 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6700 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6701 else tempScope = NULL;
6702 }
6703 return functionSymbol;
6704}
6705
6706SgSymbol*
6707SageInterface::lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6708 {
6709 SgSymbol* symbol = nullptr;
6710 if (cscope == nullptr) {
6711 cscope = SageBuilder::topScopeStack();
6712 }
6713 ASSERT_not_null(cscope);
6714
6715 while ((cscope != nullptr) && (symbol == nullptr))
6716 {
6717 symbol = cscope->lookup_symbol(name,templateParameterList,templateArgumentList);
6718 if (cscope->get_parent() != nullptr) // avoid calling get_scope when parent is not set
6719 cscope = isSgGlobal(cscope) ? nullptr : cscope->get_scope();
6720 else
6721 cscope = nullptr;
6722 }
6723
6724 return symbol;
6725 }
6726
6727
6728
6729SgSymbol*
6730SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols (const SgName & name, SgScopeStatement *currentScope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6731 {
6732// DQ (8/5/2020): the "using namespace" directive will not hide existing visability of symbols in resolving visability.
6733// So we need to test if a symbol is visible exclusing matching alises due to using direectives before we can decide to
6734// persue name space qualification. This is best demonstrated by Cxx_tests/test2020_18.C, test2020_19.C, test2020_20.C,
6735// and test2020_21.C.
6736
6737 SgSymbol* symbol = NULL;
6738 if (currentScope == NULL)
6739 {
6740 currentScope = SageBuilder::topScopeStack();
6741 }
6742
6743 ROSE_ASSERT(currentScope != NULL);
6744
6745#define DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS 0
6746
6747#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6748 printf ("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): currentScope = %p = %s (templateParameterList = %p templateArgumentList = %p) \n",
6749 currentScope,currentScope->class_name().c_str(),templateParameterList,templateArgumentList);
6750#endif
6751
6752 while ((currentScope != NULL) && (symbol == NULL))
6753 {
6754#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6755 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): name = %s currentScope = %p = %s \n",
6756 name.str(),currentScope,currentScope->class_name().c_str());
6757#endif
6758
6759 // DQ (8/16/2013): Changed API to support template parameters and template arguments.
6760 // symbol = cscope->lookup_symbol(name);
6761 symbol = currentScope->lookup_symbol(name,templateParameterList,templateArgumentList);
6762
6763 if (isSgAliasSymbol(symbol) != NULL)
6764 {
6765#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6766 printf ("Found a SgAliasSymbol: reset to NULL: symbol = %p = %s \n",symbol,symbol->class_name().c_str());
6767#endif
6768 symbol = NULL;
6769 }
6770
6771#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS && 1
6772 // debug
6773 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): symbol = %p \n",symbol);
6774 currentScope->print_symboltable("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): debug");
6775#endif
6776 if (currentScope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6777 currentScope = isSgGlobal(currentScope) ? NULL : currentScope->get_scope();
6778 else
6779 currentScope = NULL;
6780
6781#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6782 printf (" --- In SageInterface:: (base of loop) lookupSymbolInParentScopesIgnoringAliasSymbols(): cscope = %p symbol = %p \n\n",currentScope,symbol);
6783#endif
6784 }
6785
6786 if (symbol == NULL)
6787 {
6788#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6789 printf ("Warning: In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): could not locate the specified name %s in any outer symbol table (templateParameterList = %p templateArgumentList = %p) \n",
6790 name.str(),templateParameterList,templateArgumentList);
6791#endif
6792 // ROSE_ASSERT(false);
6793 }
6794
6795#if 0
6796 printf ("Support for lookupSymbolInParentScopesIgnoringAliasSymbols() is not yet implemented \n");
6797 ROSE_ABORT();
6798#endif
6799
6800 return symbol;
6801 }
6802
6803
6804
6805
6806
6807
6808
6809
6810#if 0
6811// DQ (7/13/2011): This was part of a merge conflict with the above modified function.
6812// It appeas they are the same so this one is commented out.
6814{
6815 SgSymbol* symbol = NULL;
6816 if (cscope == NULL)
6817 cscope = SageBuilder::topScopeStack();
6818 ROSE_ASSERT(cscope);
6819
6820 while ((cscope!=NULL)&&(symbol==NULL))
6821 {
6822 symbol = cscope->lookup_symbol(name);
6823 //debug
6824 // cscope->print_symboltable("debug sageInterface.C L3749...");
6825 if (cscope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6826 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6827 else
6828 cscope = NULL;
6829 }
6830
6831 if (symbol==NULL)
6832 {
6833 // printf ("Warning: could not locate the specified name %s in any outer symbol table \n"e,
6834 // name.str());
6835 // ROSE_ASSERT(false);
6836 }
6837 return symbol;
6838}
6839#endif
6840
6843 {
6844 // DQ (1/24/2011): This function is inconsistant with an implementation that would correctly handle SgAliasSymbols.
6845 // Also this function might get a SgClassSymbol instead of a SgVariableSymbol when both names are used.
6846 // This function needs to be fixed to handle the multi-map semantics of the symbol tables.
6847
6848#if 0
6849 // DQ (5/7/2011): I think this implementation is not correct (does not resolve past hidden types) and so should
6850 // be fixed to be consistant with the implementation of SageInterface::lookupClassSymbolInParentScopes().
6851 // Since I don't know where this function is used, I don't want to change it just yet.
6852 printf ("WARNING: SageInterface::lookupVariableSymbolInParentScopes() should be implemented similar to SageInterface::lookupClassSymbolInParentScopes() \n");
6853
6854 SgVariableSymbol* result = NULL;
6855 SgSymbol* symbol=lookupSymbolInParentScopes(name,cscope);
6856 if (symbol != NULL)
6857 {
6858 if (isSgAliasSymbol(symbol) != NULL)
6859 {
6860 printf ("Error: This SageInterface::lookupVariableSymbolInParentScopes() function does not handle SgAliasSymbols \n");
6861 ROSE_ABORT();
6862 }
6863 result = isSgVariableSymbol(symbol);
6864 }
6865 return result;
6866#else
6867 // I think this is the better implementation.
6868 SgVariableSymbol* symbol = NULL;
6869 if (cscope == NULL)
6870 cscope = SageBuilder::topScopeStack();
6871 ROSE_ASSERT(cscope != NULL);
6872
6873 while ((cscope != NULL) && (symbol == NULL))
6874 {
6875 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6876 symbol = cscope->lookup_variable_symbol(name);
6877
6878 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6879 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6880 else
6881 cscope = NULL;
6882 }
6883
6884 return symbol;
6885#endif
6886 }
6887
6888#define DEBUG_LOOKUP_TEMPLATE_VARIABLE 0
6889
6891SageInterface::lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *cscope)
6892 {
6893#if DEBUG_LOOKUP_TEMPLATE_VARIABLE
6894 printf ("In SageInterface::lookupTemplateVariableSymbolInParentScopes():\n");
6895 printf (" -- name = %s\n", name.str());
6896 printf (" -- tplparams = %p [%zd]\n", tplparams, tplparams ? tplparams->size() : 0);
6897 printf (" -- tplargs = %p [%zd]\n", tplargs, tplargs ? tplargs->size() : 0);
6898 printf (" -- cscope = %p (%s)\n", cscope, cscope ? cscope->class_name().c_str() : "");
6899#endif
6900
6901 SgTemplateVariableSymbol* symbol = NULL;
6902 if (cscope == NULL)
6903 cscope = SageBuilder::topScopeStack();
6904 ROSE_ASSERT(cscope != NULL);
6905
6906 while ((cscope != NULL) && (symbol == NULL))
6907 {
6908 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6909 symbol = cscope->lookup_template_variable_symbol(name, tplparams, tplargs);
6910
6911 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6912 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6913 else
6914 cscope = NULL;
6915 }
6916
6917 return symbol;
6918 }
6919
6920// SgClassSymbol* SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6922SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateArgumentPtrList* templateArgumentList)
6923 {
6924 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6925 SgClassSymbol* symbol = NULL;
6926 if (cscope == NULL)
6927 cscope = SageBuilder::topScopeStack();
6928 ROSE_ASSERT(cscope != NULL);
6929
6930 while ((cscope != NULL) && (symbol == NULL))
6931 {
6932 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6933 // symbol = cscope->lookup_class_symbol(name,NULL);
6934 symbol = cscope->lookup_class_symbol(name,templateArgumentList);
6935
6936 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6937 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6938 else
6939 cscope = NULL;
6940 }
6941
6942 return symbol;
6943 }
6944
6946SageInterface::lookupNonrealSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6947 {
6948 SgNonrealSymbol* symbol = NULL;
6949 if (cscope == NULL)
6950 cscope = SageBuilder::topScopeStack();
6951 ROSE_ASSERT(cscope != NULL);
6952
6953 while ((cscope != NULL) && (symbol == NULL))
6954 {
6955 symbol = cscope->lookup_nonreal_symbol(name,templateParameterList,templateArgumentList);
6956
6957 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6958 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6959 else
6960 cscope = NULL;
6961 }
6962
6963 return symbol;
6964 }
6965
6968 {
6969 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6970 SgTypedefSymbol* symbol = NULL;
6971 if (cscope == NULL)
6972 cscope = SageBuilder::topScopeStack();
6973 ROSE_ASSERT(cscope != NULL);
6974
6975#if 0
6976 printf ("In lookupTypedefSymbolInParentScopes(): name = %s starting with cscope = %p = %s \n",name.str(),cscope,cscope->class_name().c_str());
6977 printf ("--- parent scope = %p = %s \n",cscope->get_scope(),(cscope->get_scope() != NULL) ? cscope->get_scope()->class_name().c_str() : "null");
6978#endif
6979
6980 while ((cscope != NULL) && (symbol == NULL))
6981 {
6982 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6983 symbol = cscope->lookup_typedef_symbol(name);
6984
6985 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6986 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6987 else
6988 cscope = NULL;
6989
6990#if 0
6991 printf ("In lookupTypedefSymbolInParentScopes(): symbol = %p next cscope = %p = %s \n",symbol,cscope,(cscope != NULL) ? cscope->class_name().c_str() : "null");
6992#endif
6993 }
6994
6995#if 0
6996 printf ("Leaving lookupTypedefSymbolInParentScopes(): symbol = %p \n",symbol);
6997#endif
6998
6999 return symbol;
7000 }
7001
7002#if 0
7003// DQ (8/13/2013): This function does not make since any more, now that we have make the symbol
7004// table handling more precise and we have to provide template parameters for any template lookup.
7005// We also have to know if we want to lookup template classes, template functions, or template
7006// member functions (since each have specific requirements).
7008SageInterface::lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
7009 {
7010 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7011 SgTemplateSymbol* symbol = NULL;
7012 if (cscope == NULL)
7013 cscope = SageBuilder::topScopeStack();
7014 ROSE_ASSERT(cscope != NULL);
7015
7016 while ((cscope != NULL) && (symbol == NULL))
7017 {
7018 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7019 // In this case these are unavailable from this point.
7020 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7021 // symbol = cscope->lookup_template_symbol(name);
7022 symbol = cscope->lookup_template_symbol(name,NULL,NULL);
7023#if 0
7024 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7025#endif
7026 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7027 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7028 else
7029 cscope = NULL;
7030 }
7031
7032 return symbol;
7033 }
7034#endif
7035
7036
7038SageInterface::lookupTemplateClassSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope)
7039 {
7040 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7041 SgTemplateClassSymbol* symbol = NULL;
7042 if (cscope == NULL)
7043 cscope = SageBuilder::topScopeStack();
7044 ROSE_ASSERT(cscope != NULL);
7045
7046 while ((cscope != NULL) && (symbol == NULL))
7047 {
7048 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7049 // In this case these are unavailable from this point.
7050 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7051 // symbol = cscope->lookup_template_symbol(name);
7052 symbol = cscope->lookup_template_class_symbol(name,templateParameterList,templateArgumentList);
7053#if 0
7054 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7055#endif
7056 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7057 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7058 else
7059 cscope = NULL;
7060 }
7061
7062 return symbol;
7063 }
7064
7065
7068 {
7069 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7070 // A templated solution might make for a better implementation.
7071 SgEnumSymbol* symbol = NULL;
7072 if (cscope == NULL)
7073 cscope = SageBuilder::topScopeStack();
7074 ROSE_ASSERT(cscope != NULL);
7075
7076 while ((cscope != NULL) && (symbol == NULL))
7077 {
7078 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7079 symbol = cscope->lookup_enum_symbol(name);
7080
7081 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7082 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7083 else
7084 cscope = NULL;
7085 }
7086
7087 return symbol;
7088 }
7089
7092 {
7093 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7094 SgNamespaceSymbol* symbol = NULL;
7095 if (cscope == NULL)
7096 cscope = SageBuilder::topScopeStack();
7097 ROSE_ASSERT(cscope != NULL);
7098
7099 while ((cscope != NULL) && (symbol == NULL))
7100 {
7101 // I think this will resolve SgAliasSymbols to be a SgNamespaceSymbol where the alias is of a SgNamespaceSymbol.
7102 symbol = cscope->lookup_namespace_symbol(name);
7103
7104 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7105 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7106 else
7107 cscope = NULL;
7108 }
7109
7110 return symbol;
7111 }
7112
7113template<class T>
7114void
7115SageInterface::setSourcePositionToDefault( T* node )
7116 {
7117 // This is a templated function because SgPragma is not yet derived from SgLocatedNode.
7118
7119 // DQ (2/17/2013): This function is called a lot, so it might be a performance issue.
7120 // All IR nodes built by the Build Interface are assighed source position information
7121 // using this function and then reset afterward as we use information within EDG to
7122 // reset the source position information. Ideally, the EDG/ROSE connection would
7123 // use NULL pointers as the behavior for the front-end mode. We can move to that
7124 // later to maek the source position handling more efficient.
7125
7126 // DQ (1/24/2009): It might be that this function is only called from the Fortran support.
7127
7128 // This function sets the source position to be marked as not
7129 // available (since we often don't have token information)
7130 // These nodes WILL be unparsed in the conde generation phase.
7131
7132 // The SgLocatedNode has both a startOfConstruct and endOfConstruct source position.
7133 ROSE_ASSERT(node != NULL);
7134
7135 // We have to support this being called where the Sg_File_Info have previously been set.
7136 if (node->get_endOfConstruct() == NULL && node->get_startOfConstruct() == NULL)
7137 {
7138#if 0
7139 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());
7140#endif
7141 // Check the endOfConstruct first since it is most likely NULL (helpful in debugging)
7142 ROSE_ASSERT(node->get_endOfConstruct() == NULL);
7143 ROSE_ASSERT(node->get_startOfConstruct() == NULL);
7144
7147
7148 // DQ (5/2/2012): I think we don't want to do this.
7149#if 0
7150 printf ("In SageInterface::setSourcePositionToDefault(): Calling setSourcePositionUnavailableInFrontend() \n");
7151#endif
7152 start_fileInfo->setSourcePositionUnavailableInFrontend();
7153 end_fileInfo->setSourcePositionUnavailableInFrontend();
7154
7155 // DQ (5/2/2012): I think we don't want to do this.
7156#if 0
7157 printf ("In SageInterface::setSourcePositionToDefault(): Calling setOutputInCodeGeneration() \n");
7158#endif
7159 // This is required for the unparser to output the code from the AST.
7160 start_fileInfo->setOutputInCodeGeneration();
7161 end_fileInfo->setOutputInCodeGeneration();
7162
7163 node->set_startOfConstruct(start_fileInfo);
7164 node->set_endOfConstruct (end_fileInfo);
7165
7166 node->get_startOfConstruct()->set_parent(node);
7167 node->get_endOfConstruct ()->set_parent(node);
7168 }
7169 else
7170 {
7171 // If both the starting and ending Sg_File_Info pointers are not NULL then both must be valid.
7172 // We don't want to support partially completed source code position information.
7173#if 0
7174 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());
7175#endif
7176 if (node->get_startOfConstruct() == NULL)
7177 {
7178 printf ("ERROR: startOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7179 }
7180 if (node->get_endOfConstruct() == NULL)
7181 {
7182 printf ("ERROR: endOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7183 }
7184
7185 ROSE_ASSERT(node->get_startOfConstruct() != NULL);
7186 ROSE_ASSERT(node->get_endOfConstruct() != NULL);
7187 ROSE_ASSERT(node->get_endOfConstruct() != NULL && node->get_startOfConstruct() != NULL);
7188 }
7189
7190 // DQ (11/2/2012): This is an important fix to support the new EDG 4.x branch.
7191 // Note that because the unparser will use the function isFromAnotherFile() in the unparsing
7192 // of expressions, specifically: SgAggregateInitializer, SgCompoundInitializer, and anything
7193 // in their expression lists (which could be any expression). The isFromAnotherFile() will
7194 // use the get_file_info() function on the SgExpression IR nodes and the data from that
7195 // Sg_File_Info object to determine if that expression subtree should be unparsed. This
7196 // expression level granularity of unparsing capability is extremely useful in handling
7197 // now #includes and other CPP directives are woven back into the AST. But since the
7198 // get_file_info() function is used, and it returns the value of get_operatorPosition(),
7199 // it is critically important to have correct data in the SgExpression::p_operatorPosition
7200 // Sg_File_Info object (it counts more that the startOfConstruct and endOfConstruct
7201 // Sg_File_Info objects in controlling what expressions are unparsed. So we have to set these
7202 // up for all expressions (since any SgExpression could appear in the list contained in
7203 // a SgAggregateInitializer or SgCompoundInitializer.
7204
7205 // DQ (11/2/2012): Set the operator source position information to default values.
7206 // This will trigger it to be reset to valid source position information in the front-end.
7207 SgExpression* expression = isSgExpression(node);
7208 if (expression != NULL)
7209 {
7210#if 0
7211 SgBinaryOp* binaryOp = isSgBinaryOp(expression);
7212 if (binaryOp != NULL)
7213 {
7214 if (binaryOp->get_operatorPosition() == NULL)
7215 {
7217 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7218 operator_fileInfo->setOutputInCodeGeneration();
7219 binaryOp->set_operatorPosition(operator_fileInfo);
7220
7221 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7222 binaryOp->get_operatorPosition()->set_parent(binaryOp);
7223 }
7224 }
7225#else
7226 // Setup all of the SgExpression operatorPosition pointers to default objects.
7227 if (expression->get_operatorPosition() == NULL)
7228 {
7230 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7231 operator_fileInfo->setOutputInCodeGeneration();
7232 expression->set_operatorPosition(operator_fileInfo);
7233
7234 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7235 // expression->get_operatorPosition()->set_parent(expression);
7236 operator_fileInfo->set_parent(expression);
7237 ROSE_ASSERT(expression->get_operatorPosition()->get_parent() == expression);
7238 }
7239#endif
7240 }
7241 }
7242
7243
7244void
7246 {
7247 // DQ (5/1/2012): Older depricated function.
7248#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
7249 printf ("+++++ Depricated function (use setSourcePositionAsTransformation() instead) (no using internal source position mode) \n");
7250#endif
7251
7252 // setSourcePositionAsTransformation(node);
7253 setSourcePosition(node);
7254 }
7255
7256
7257void
7259 {
7260 // DQ (5/1/2012): Newer function to support specification of IR nodes being a part of a transformation.
7261
7262 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionAsTransformation(SgNode *node)"
7263 // The logic should be make more independent of if (locatedNode->get_startOfConstruct() == NULL)
7264 // Since that make understanding where the function is applied too complex.
7265 // If (locatedNode->get_startOfConstruct() != NULL), then we should just make that Sg_File_Info as
7266 // a transforamtion directly, this function misses that step.
7267
7268 ROSE_ASSERT(node != NULL);
7269
7270 // DQ (10/12/2012): Commented out since we are past AST regression tests passing and now trying to get this work checked in.
7271// printf ("In SageInterface::setSourcePositionAsTransformation() for node = %p = %s (make this an error while debugging AST construction) \n",node,node->class_name().c_str());
7272 // ROSE_ASSERT(false);
7273
7274 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7275 SgExpression* expression = isSgExpression(node);
7276 // SgInitializedName* initName = isSgInitializedName(node);
7277 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7278 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7279
7280#if 0
7281 SgVariableDefinition * v_d = isSgVariableDefinition(node);
7282 if (v_d )
7283 printf ("Debug, Found a variable definition: %p\n", v_d);
7284#endif
7285
7286 if (locatedNode != NULL)
7287 {
7289 locatedNode->get_startOfConstruct()->set_parent(locatedNode);
7290
7291 if (global==NULL)
7292 {
7294 locatedNode->get_endOfConstruct ()->set_parent(locatedNode);
7295 }
7296
7297 // Only SgExpression IR nodes have a 3rd source position data structure.
7298 if (expression!=NULL)
7299 {
7300 expression->set_operatorPosition(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7301 expression->get_operatorPosition()->set_parent(expression);
7302 }
7303 }
7304 else // special non-located node with file info
7305 {
7306 if ( (pragma != NULL) && (pragma->get_startOfConstruct() == NULL) )
7307 {
7308 pragma->set_startOfConstruct(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7309 pragma->get_startOfConstruct()->set_parent(pragma);
7310 }
7311 }
7312 }
7313
7314
7315void
7317 {
7318 // DQ (5/1/2012): Older depricated function (use setSourcePositionPointersToNull() instead).
7319#if 0
7320 printf ("+++++ Depricated name setOneSourcePositionNull() (use setSourcePositionPointersToNull() instead) (no using internal source position mode) \n");
7321#endif
7322
7323 setSourcePosition(node);
7324 }
7325
7326// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
7327void
7329 {
7330 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionToNULL(SgNode *node)"
7331 // However, if this is doen then the logic should be that it asserts that: (locatedNode->get_startOfConstruct() == NULL)
7332 // so that we know when we are leaking memory. Similarly, we should assert that:
7333 // (locatedNode->get_endOfConstruct() == NULL).
7334 // But then this function just asserts that everything is already NULL and is less about setting them to NULL.
7335 // If (locatedNode->get_startOfConstruct() != NULL), should we delete the existing Sg_File_Info object?
7336 // This function misses that step.
7337
7338 ROSE_ASSERT(node != NULL);
7339
7340 SgLocatedNode * locatedNode = isSgLocatedNode(node);
7341 SgExpression* expression = isSgExpression(node);
7342 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7343 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7344
7345 // DQ (1/24/2009): If the point is to set the source position to NULL pointers,
7346 // why do we only handle the case when (get_startOfConstruct() == NULL)
7347 // (i.e. when the start source postion is already NULL).
7348
7349 if (locatedNode != NULL)
7350 {
7351 if (locatedNode->get_startOfConstruct() != NULL)
7352 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of startOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7353
7354 locatedNode->set_startOfConstruct(NULL);
7355
7356 // Note that SgGlobal should have NULL endOfConstruct()
7357 if (global == NULL)
7358 {
7359 if (locatedNode->get_endOfConstruct() != NULL)
7360 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of endOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7361
7362 locatedNode->set_endOfConstruct(NULL);
7363 }
7364
7365 // Only SgExpression IR nodes have a 3rd source position data structure.
7366 if (expression != NULL)
7367 {
7368 if (expression->get_operatorPosition() != NULL)
7369 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of operatorPosition Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7370
7371 expression->set_operatorPosition(NULL);
7372 }
7373 }
7374 else
7375 {
7376 if ( (pragma != NULL) && (pragma->get_startOfConstruct() != NULL) )
7377 {
7378 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7379
7380 pragma->set_startOfConstruct(NULL);
7381 }
7382 }
7383 }
7384
7385// DQ (1/24/2009): Could we change the name to be "setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)"
7386void
7388 {
7389#if 1
7390#if 0
7391 printf ("+++++ Depricated name setSourcePositionForTransformation() (use setSourcePositionAtRootAndAllChildrenAsTransformation() instead) \n");
7392#endif
7393
7394 // This is the semantically correct function to call.
7395 // setSourcePositionAtRootAndAllChildrenAsTransformation(root);
7396
7397 // 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.
7398 // setSourcePosition(root);
7399 // Liao 11/21/2012. This function should only be called when the mode is transformation
7400 // Liao 8/2/2013. It can actually be called inside frontend by OmpSupport::lower_omp().
7401 //ROSE_ASSERT(SageBuilder::SourcePositionClassificationMode == SageBuilder::e_sourcePositionTransformation);
7403#else
7404 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7405 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7406 {
7408 }
7409#endif
7410 }
7411
7412
7413#if 0
7414// DQ (5/1/2012): New function with improved name (still preserving the previous interface).
7415void
7416SageInterface::setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)
7417 {
7418 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7419 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7420 {
7422 }
7423 }
7424#endif
7425
7426#if 0
7427void
7428SageInterface::setSourcePositionAtRootAndAllChildrenAsDefault(SgNode *root)
7429 {
7430 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7431 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7432 {
7433 setSourcePositionAsDefault(*i);
7434 }
7435 }
7436#endif
7437
7438void
7440 {
7441 // DQ (2/17/2013): This is a relatively expensive operation so we might look into this.
7442
7443 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7444
7445#if 0
7446 printf ("In setSourcePositionAtRootAndAllChildren(): nodeList.size() = %" PRIuPTR " \n",nodeList.size());
7447#endif
7448
7449 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
7450 {
7451#if 0
7452 printf ("In setSourcePositionAtRootAndAllChildren(): *i = %p = %s \n",*i,(*i)->class_name().c_str());
7453#endif
7455 }
7456 }
7457
7458// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
7459// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects). This
7460// function is the only function that should be called directly (though in a namespace we can't define permissions).
7461void
7463 {
7464 // Check the mode and build the correct type of source code position.
7466
7467 // DQ (2/17/2013): Note that the SourcePositionClassification will be e_sourcePositionFrontendConstruction
7468 // during construction of the AST from the EDG frontend.
7469
7470#if 0
7471 printf ("In SageInterface::setSourcePosition(): SourcePositionClassification scp = %s \n",display(scp).c_str());
7472#endif
7473
7474 switch(scp)
7475 {
7476 case e_sourcePositionError: // Error value for enum.
7477 {
7478 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7479 ROSE_ABORT();
7480 }
7481
7482 case e_sourcePositionDefault: // Default source position.
7483 {
7484#if 0
7485 printf ("e_sourcePositionDefault in SageInterface::setSourcePosition() \n");
7486#endif
7487 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7488 if (locatedNode != NULL)
7489 {
7490 setSourcePositionToDefault(locatedNode);
7491 }
7492 else
7493 {
7494 // This is not supported (not clear if it need be).
7495 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionDefault with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7496 ROSE_ABORT();
7497 }
7498 break;
7499 }
7500
7501 case e_sourcePositionTransformation: // Classify as a transformation.
7502 {
7503#if 0
7504 printf ("e_sourcePositionTransformation in SageInterface::setSourcePosition() \n");
7505#endif
7506 // setSourcePositionAtRootAndAllChildrenAsTransformation(node);
7508 break;
7509 }
7510
7511 case e_sourcePositionCompilerGenerated: // Classify as compiler generated code (e.g. template instantiation).
7512 {
7513 printf ("e_sourcePositionCompilerGenerated in SageInterface::setSourcePosition() \n");
7514
7515 printf ("Sorry, not implemented \n");
7516 ROSE_ABORT();
7517 }
7518
7519 case e_sourcePositionNullPointers: // Set pointers to Sg_File_Info objects to NULL.
7520 {
7521 // DQ (2/17/2013): We want to move to this mode as the one used for EDG/ROSE connection so that we can
7522 // avoid building and rebuilding source position information.
7523#if 0
7524 printf ("e_sourcePositionNullPointers in SageInterface::setSourcePosition() \n");
7525#endif
7527 break;
7528 }
7529
7530 case e_sourcePositionFrontendConstruction: // Specify as source position to be filled in as part of AST construction in the front-end.
7531 {
7532 // DQ (2/17/2013): The setSourcePositionToDefault() function is called a lot, so it might be a performance issue.
7533 // All IR nodes built by the Build Interface are assighed source position information
7534 // using this function and then reset afterward as we use information within EDG to
7535 // reset the source position information. Ideally, the EDG/ROSE connection would
7536 // use NULL pointers as the behavior for the front-end mode. We can move to that
7537 // later to make the source position handling more efficient.
7538
7539 // This function builds an empty Sg_File_Info entry (valid object but filled with default values; must be reset in front-end processing).
7540#if 0
7541 printf ("e_sourcePositionFrontendConstruction in SageInterface::setSourcePosition() \n");
7542#endif
7543 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7544 if (locatedNode != NULL)
7545 {
7546 // setSourcePositionAtRootAndAllChildrenAsDefault(locatedNode);
7547 setSourcePositionToDefault(locatedNode);
7548 }
7549 else
7550 {
7551 // This is not supported (not clear if it need be).
7552 SgPragma* pragma = isSgPragma(node);
7553 if (pragma != NULL)
7554 {
7555 setSourcePositionToDefault(pragma);
7556 }
7557 else
7558 {
7559 // printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7560 // ROSE_ASSERT(false);
7561 SgType* type = isSgType(node);
7562 if (type != NULL)
7563 {
7564 // Ignore this case, OK.
7565 }
7566 else
7567 {
7568 SgFunctionParameterTypeList* functionParameterTypeList = isSgFunctionParameterTypeList(node);
7569 if (functionParameterTypeList != NULL)
7570 {
7571 // Ignore this case, OK.
7572 }
7573 else
7574 {
7575 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7576 ROSE_ABORT();
7577 }
7578 }
7579 }
7580 }
7581
7582 break;
7583 }
7584
7585
7587 {
7588 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7589 ROSE_ABORT();
7590 }
7591
7592 default:
7593 {
7594 printf ("Error: default reached in SageInterface::setSourcePosition() \n");
7595 break;
7596 }
7597 }
7598
7599#if 0
7600 if (node->get_file_info() != NULL)
7601 {
7602 node->get_file_info()->display("Leaving SageInterface::setSourcePosition()");
7603 }
7604#endif
7605 }
7606
7607#if 0
7608void
7609SageInterface::setSourcePositionForTransformation_memoryPool()
7610 {
7611 // DQ (1/24/2009): This seems like a very dangerous function to have, is it required!
7612
7613 // DQ (5/1/2012): Make it an error to call this function.
7614 printf ("ERROR: In setSourcePositionForTransformation_memoryPool(): This seems like a very dangerous function to have, is it required? \n");
7615 ROSE_ABORT();
7616
7617 VariantVector vv(V_SgNode);
7618 Rose_STL_Container<SgNode*> nodeList = NodeQuery::queryMemoryPool(vv);
7619 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++ )
7620 {
7622 }
7623 }
7624#endif
7625
7627 {
7628 // Liao, 1/9/2008, get the first global scope from current project
7629 // mostly used to prepare for AST construction under the global scope
7630 ROSE_ASSERT(project != NULL);
7631
7632 // DQ (1/24/2009): Added a check to make sure STL list is non-empty.
7633 ROSE_ASSERT(project->get_fileList().empty() == false);
7634
7635 // SgGlobal* global = project->get_file(0).get_root();
7636 SgSourceFile* file = isSgSourceFile(project->get_fileList()[0]);
7637 SgGlobal* global = file->get_globalScope();
7638
7639#if 0
7640 SgFilePtrListPtr fileList = project->get_fileList();
7641 SgFilePtrList::const_iterator i= fileList->begin();
7642
7643 SgGlobal* global = (*i)->get_globalScope();
7644#endif
7645 ROSE_ASSERT(global != NULL);
7646
7647 return global;
7648 }
7649
7650// Liao, 1/10/2008, get the last stmt from the scope
7651// two cases
7652// SgScopeStatement::getDeclarationList
7653// SgScopeStatement::getStatementList()
7655 {
7656 ROSE_ASSERT(scope);
7657 SgStatement* stmt = NULL;
7658
7659 if (scope->containsOnlyDeclarations())
7660 {
7661 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7662 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7663 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7664
7665 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7666 if (declList.empty() == false)
7667 {
7668 stmt = isSgStatement(declList.back());
7669 }
7670 }
7671 else
7672 {
7673 // DQ (2/17/2013): Fixed stmtList to be a reference instead of a copy.
7674 SgStatementPtrList & stmtList = scope->getStatementList();
7675
7676 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7677 if (stmtList.empty() == false)
7678 {
7679 stmt = stmtList.back();
7680 }
7681 }
7682
7683 return stmt;
7684 }
7685
7686
7687SgStatement* SageInterface::getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated/*=false*/)
7688 {
7689 // DQ (2/17/2013): This function appears to be a performance problem (so a pass was made to
7690 // use lower complexity operations that are equivalent in funcionality for this context).
7691
7692 ROSE_ASSERT(scope);
7693 SgStatement* stmt = NULL;
7694
7695 if (scope->containsOnlyDeclarations())
7696 {
7697 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7698 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7699 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7700 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7701 if (includingCompilerGenerated)
7702 {
7703 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7704 // DQ Note: (declList.empty() == false) is a much faster test O(1) than (declList.size() > 0), which is O(n).
7705 if (declList.empty() == false)
7706 {
7707 stmt = isSgStatement(declList.front());
7708 }
7709 }
7710 else
7711 {
7712 // skip compiler-generated declarations
7713 SgDeclarationStatementPtrList::iterator i=declList.begin();
7714 while (i != declList.end())
7715 {
7716 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7717 // some content from headers included are not marked as compiler-generated
7718 //
7719 // cout<<(*i)->unparseToString()<<endl;
7720 // ((*i)->get_file_info())->display("debug.......");
7721 Sg_File_Info * fileInfo = (*i)->get_file_info();
7722 // include transformation-generated statements, but not the hidden ones
7723 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7724 if ((fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation() && fileInfo->isOutputInCodeGeneration()))
7725 {
7726 stmt = *i;
7727 break;
7728 }
7729 else
7730 {
7731 i++;
7732 continue;
7733 }
7734 }
7735 }
7736 }
7737 else
7738 {
7739 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7740 SgStatementPtrList & stmtList = scope->getStatementList();
7741 if (includingCompilerGenerated)
7742 {
7743 // DQ (2/17/2013): Fixed evaluation of empty list use SgStatementPtrList::empty() member function for faster performance.
7744 // DQ Note: (stmtList.empty() == false) is a much faster test O(1) than (stmtList.size() > 0), which is O(n).
7745 if (stmtList.empty() == false)
7746 {
7747 stmt = stmtList.front();
7748 }
7749 }
7750 else
7751 {
7752 // skip compiler-generated declarations
7753 SgStatementPtrList::iterator i = stmtList.begin();
7754 while (i!=stmtList.end())
7755 {
7756 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7757 // some content from headers included are not marked as compiler-generated
7758 //
7759 // cout<<(*i)->unparseToString()<<endl;
7760 // ((*i)->get_file_info())->display("debug.......");
7761 Sg_File_Info * fileInfo = (*i)->get_file_info();
7762 // include transformation-generated statements, but not the hidden ones
7763 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7764 if ( (fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration()))
7765 {
7766 stmt=*i;
7767 break;
7768 }
7769 else
7770 {
7771 i++;
7772 continue;
7773 }
7774 }
7775 }
7776 }
7777
7778 return stmt;
7779 }
7780
7781
7783 {
7784 ROSE_ASSERT(scope);
7785 SgFunctionDeclaration* result = NULL;
7786 if (scope->containsOnlyDeclarations())
7787 {
7788 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7789 SgDeclarationStatementPtrList::iterator i=declList.begin();
7790 while (i!=declList.end())
7791 {
7792 Sg_File_Info * fileInfo = (*i)->get_file_info();
7793
7794 if ((fileInfo->isSameFile(scope->get_file_info()))||
7795 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7796 )
7797 {
7798 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7799 if (func)
7800 {
7801 if (func->get_definingDeclaration ()==func)
7802 {
7803 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7804 result=func;
7805 break;
7806 }
7807 }
7808 }
7809 i++;
7810 }//end while
7811 } else
7812 {
7813 SgStatementPtrList stmtList = scope->getStatementList();
7814 SgStatementPtrList::iterator i=stmtList.begin();
7815 while (i!=stmtList.end())
7816 {
7817 Sg_File_Info * fileInfo = (*i)->get_file_info();
7818 if ( (fileInfo->isSameFile(scope->get_file_info()))||
7819 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7820 )
7821 {
7822 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7823 if (func)
7824 {
7825 if (func->get_definingDeclaration ()==func)
7826 {
7827 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7828 result=func;
7829 break;
7830 }// if defining
7831 } // if func
7832 }// if fileInof
7833 i++;
7834 }//while
7835 } // end if
7836 return result;
7837 }
7838
7839
7841{
7842 bool result = false;
7843 // Liao 1/5/2010, handle Fortran main entry: SgProgramHeaderStatement
7845 if (isSgProgramHeaderStatement(n)) {
7846 result = true;
7847 }
7848 }
7849 else {
7850 if (isSgFunctionDeclaration(n) != nullptr) {
7851 bool either = false;
7853 either = true;
7854 }
7855 else {
7856 const SgStatement* stmnt = isSgStatement(n);
7857 ROSE_ASSERT(stmnt != nullptr);
7858 if (isSgGlobal(stmnt->get_scope())) {
7859 either = true;
7860 }
7861 }
7862 if (either) {
7863 const SgFunctionDeclaration* funcDefn = isSgFunctionDeclaration(n);
7864 ROSE_ASSERT(funcDefn != nullptr);
7865 if (funcDefn->get_name() == "main") {
7866 result = true;
7867 }
7868 }
7869 }
7870 }
7871 return result;
7872}
7873
7874// Originally from ompTranslator.C
7875// DQ (1/6/2007): The correct qualified name for "main" is "::main", at least in C++.
7876// however for C is should be "main". Our name qualification is not language specific,
7877// however, for C is makes no sense to as for the qualified name, so the name we
7878// want to search for could be language specific. The test code test2007_07.C
7879// demonstrates that the function "main" can exist in both classes (as member functions)
7880// and in namespaces (as more meaningfully qualified names). Because of this C++
7881// would have to qualify the global main function as "::main", I think.
7882
7883// Revised by Jeremiah,
7884// Added check to see if the scope is global: Liao
7886 if (!n) return 0;
7887 if (isMain(n))
7888 {
7889 return isSgFunctionDeclaration(n);
7890 }
7891 vector<SgNode*> children = n->get_traversalSuccessorContainer();
7892 for (vector<SgNode*>::const_iterator i = children.begin();
7893 i != children.end(); ++i) {
7894
7895 SgFunctionDeclaration* mainDecl = findMain(*i);
7896 if (mainDecl)
7897 if (mainDecl->get_definingDeclaration() == mainDecl) // skip non-defining main() declaration, Liao 8/27/2010
7898 return mainDecl;
7899 }
7900 return 0;
7901}
7902
7904// another declaration statement can be inserted.
7905// This is useful to find a safe place to insert a declaration statement with special requirements about where it can be inserted.
7906// e.g. a variable declaration statement should not be inserted before IMPLICIT none in Fortran
7907// If it returns NULL, a declaration statement should be able to be prepended to the scope
7909{
7910 SgStatement* rt = NULL;
7911 ROSE_ASSERT (scope != NULL);
7912
7913 SgStatementPtrList stmt_list = scope->generateStatementList ();
7914
7915 for (size_t i = 0; i<stmt_list.size(); i++)
7916 {
7917 SgStatement* cur_stmt = stmt_list[i];
7918 // We should exclude pragma decl. We don't want to insert things after pragmas.
7919 if (isSgDeclarationStatement(cur_stmt))
7920 {
7921 if (isSgPragmaDeclaration (cur_stmt))
7922 {
7923 if (includePragma)
7924 rt = cur_stmt;
7925 }
7926 else
7927 rt = cur_stmt;
7928 }
7929 //if (isSgImplicitStatement(cur_stmt)) || isSgFortranIncludeLine(cur_stmt) || isSgDeclarationStatement
7930 }
7931
7932 return rt;
7933}
7934
7936{
7937 SgNode* rt = NULL;
7938 SgTreeCopy g_treeCopy; // should use a copy object each time of usage!
7939 if (n!= NULL)
7940 {
7941 rt = n->copy (g_treeCopy);
7943 }
7944 // return n ? n->copy (g_treeCopy) : 0;
7945 return rt;
7946}
7947
7948// by Jeremiah
7949// Return bool for C++ code, and int for C code
7951 bool isC = TransformationSupport::getSourceFile(n)->get_outputLanguage() == SgFile::e_C_language;
7952 if (isC) {
7953 return SgTypeInt::createType();
7954 } else {
7955 return SgTypeBool::createType();
7956 }
7957}
7958
7959#if 1
7960// Change continue statements in a given block of code to gotos to a label
7962 {
7963#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
7964 std::vector<SgContinueStmt*> continues = SageInterface::findContinueStmts(stmt);
7965 for (std::vector<SgContinueStmt*>::iterator i = continues.begin(); i != continues.end(); ++i)
7966 {
7967 SgGotoStatement* gotoStatement = SageBuilder::buildGotoStatement(label);
7968 // printf ("Building gotoStatement #1 = %p \n",gotoStatement);
7969#ifndef _MSC_VER
7970 LowLevelRewrite::replace(*i, make_unit_list( gotoStatement ) );
7971#else
7972 ROSE_ABORT();
7973#endif
7974 }
7975#else
7976 printf ("Not supported in mode: ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT (LowLevelRewrite::replace() is unavailable)");
7977 ROSE_ABORT();
7978#endif
7979 }
7980
7981#define DEBUG_TEMPLATE_ARG_EQUIVALENCE 0
7982
7984 {
7985 if (arg1 == arg2)
7986 {
7987#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7988 printf ("In templateArgumentEquivalence(): same pointer to template argument: returning true \n");
7989#endif
7990 return true;
7991 }
7992
7993 if (arg1->get_argumentType() != arg2->get_argumentType())
7994 {
7995#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
7996 printf ("In templateArgumentEquivalence(): different argumentType(): returning false \n");
7997#endif
7998 return false;
7999 }
8000
8001 switch (arg1->get_argumentType())
8002 {
8004 {
8005 ROSE_ASSERT(arg1->get_type() != NULL);
8006 ROSE_ASSERT(arg2->get_type() != NULL);
8007
8008#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8009 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: arg1->get_type() = %p = %s arg2->get_type() = %p = %s \n",
8010 arg1->get_type(),arg1->get_type()->class_name().c_str(),
8011 arg2->get_type(),arg2->get_type()->class_name().c_str());
8012#endif
8013 // DQ (5/19/2016): Rewrote to support debugging.
8014 // return arg1->get_type() == arg2->get_type();
8015 if (arg1->get_type() == arg2->get_type())
8016 {
8017#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8018 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: returning true \n");
8019#endif
8020 return true;
8021 }
8022 else
8023 {
8024 // ROSE_ASSERT(!"NIY: non-type template argument comparaison."); /// \todo
8025
8026 // DQ (5/19/2016): Use type equivalence mechanism to handle the case where
8027 // these are different pointers to what might still be the same type.
8028 // return false;
8029 bool typesAreEqual = isEquivalentType(arg1->get_type(),arg2->get_type());
8030
8031#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8032 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: pointers are different: returning typesAreEqual = %s \n",typesAreEqual ? "true" : "false");
8033#endif
8034 return typesAreEqual;
8035 }
8036 }
8037
8039 {
8040 SgExpression * expr1 = arg1->get_expression();
8041 SgExpression * expr2 = arg2->get_expression();
8042 if (expr1 == expr2) {
8043#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8044 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: checking for the same expression: returning true \n");
8045#endif
8046 return true;
8047 } else if (expr1->variantT() == expr2->variantT() ) {
8048#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8049 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: same variant of expression: %s\n", expr1->class_name().c_str());
8050#endif
8051 switch (expr1->variantT()) {
8052 case V_SgLongIntVal: {
8053 return ((SgLongIntVal *)expr1)->get_value() == ((SgLongIntVal *)expr2)->get_value();
8054 }
8055 // DQ (7/21/2024): Adding support for another type (from processing nlohmann/json.hpp with ROSE)
8056 case V_SgUnsignedLongVal:
8057 {
8058 return ((SgUnsignedLongVal*) expr1)->get_value() == ((SgUnsignedLongVal*) expr2)->get_value();
8059 }
8060 default: {
8061 printf ("FATAL: In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: expression have the same variant %s but comparison is not NIY!\n", expr1->class_name().c_str());
8062 ROSE_ABORT();
8063 }
8064 }
8065 } else {
8066#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8067 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: different variant of expression: returning false \n");
8068#endif
8069 return false;
8070 }
8071 }
8072
8074 {
8075 if (arg1->get_templateDeclaration() == arg2->get_templateDeclaration())
8076 {
8077#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8078 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::template_template_argument: checking for the same templateDeclaration: returning true \n");
8079#endif
8080 return true;
8081 }
8082 else
8083 {
8084 ROSE_ASSERT(!"NIY: template template argument comparaison.");
8085 }
8086 }
8087
8089 {
8090 ROSE_ASSERT(!"Try to compare template arguments of unknown type...");
8091 }
8092
8093 // DQ (7/19/2015): Added missing case:
8095 {
8096 // Liao 6/24/2016. Handle the simplest case: both arguments are parameter pack.
8098 return true;
8099 ROSE_ASSERT(!"Try to compare template arguments of unknown type start_of_pack_expansion_argument");
8100 }
8101
8102 // DQ (7/19/2015): Added missing default case: we always want to ahve a default case to catch errors and missing cases.
8103 default:
8104 {
8105 printf ("Error: default case not handled! \n");
8106 ROSE_ABORT();
8107 }
8108 }
8109
8110 ROSE_ABORT(); // unreachable code
8111 }
8112
8113#define DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE 0
8114
8115bool SageInterface::templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2)
8116 {
8117 if (list1.size() != list2.size())
8118 {
8119#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8120 printf ("In templateArgumentListEquivalence(): different list sizes: returning false \n");
8121 printf (" --- list1.size() = %zu \n",list1.size());
8122 printf (" --- list2.size() = %zu \n",list2.size());
8123#endif
8124 return false;
8125 }
8126
8127 if (list1 == list2)
8128 {
8129#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8130 printf ("In templateArgumentListEquivalence(): same list using STL equality operator: returning true \n");
8131#endif
8132 return true;
8133 }
8134
8135 // for (unsigned i = 0; i < list1.size(); i++)
8136 for (size_t i = 0; i < list1.size(); i++)
8137 {
8138#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8139 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu \n",i);
8140#endif
8141 // if (!templateArgumentEquivalence(list1[i], list2[i]))
8142 if (templateArgumentEquivalence(list1[i], list2[i]) == false)
8143 {
8144#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8145 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu --- returned false: returning false \n",i);
8146#endif
8147 return false;
8148 }
8149 }
8150
8151#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8152 printf ("In templateArgumentListEquivalence(): reached base of function: returning true \n");
8153#endif
8154
8155 return true;
8156 }
8157
8158// Add a step statement to the end of a loop body
8159// Add a new label to the end of the loop, with the step statement after
8160// it; then change all continue statements in the old loop body into
8161// jumps to the label
8162//
8163// For example:
8164// while (a < 5) {if (a < -3) continue;} (adding "a++" to end) becomes
8165// while (a < 5) {if (a < -3) goto label; label: a++;}
8167 using namespace SageBuilder;
8169 SgStatement* old_body = SageInterface::getLoopBody(loopStmt);
8170 SgBasicBlock* new_body = buildBasicBlock();
8171// printf ("Building IR node #13: new SgBasicBlock = %p \n",new_body);
8172 SgName labelname = "rose_label__";
8173 labelname << ++gensym_counter;
8174 SgLabelStatement* labelstmt = buildLabelStatement(labelname,
8175buildBasicBlock(), proc);
8176 changeContinuesToGotos(old_body, labelstmt);
8177 appendStatement(old_body, new_body);
8178 appendStatement(labelstmt, new_body);
8179 appendStatement(step, new_body);
8180 SageInterface::setLoopBody(loopStmt, new_body);
8181}
8182
8183
8185 if (isSgNullExpression(f->get_increment())) return;
8186 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(f->get_increment());
8187 f->get_increment()->set_parent(incrStmt);
8190 f->set_increment(ne);
8191 ne->set_parent(f);
8192}
8193
8194static
8195bool hasEmptyCondition(SgForStatement* f)
8196{
8197 ROSE_ASSERT(f);
8198
8199 SgStatement* condstmt = f->get_test();
8200 ROSE_ASSERT(condstmt);
8201
8202 if (isSgNullStatement(condstmt)) return true;
8203
8204 SgExprStatement* exprStmt = isSgExprStatement(condstmt);
8205
8206 return isSgNullExpression(exprStmt->get_expression());
8207}
8208
8213 SgStatementPtrList& bbStmts = bb->get_statements();
8214 SgStatementPtrList& initStmts = inits->get_init_stmt();
8215 bbStmts = initStmts;
8216 for (size_t i = 0; i < bbStmts.size(); ++i) {
8217 bbStmts[i]->set_parent(bb);
8218 }
8219
8220 const bool testIsNull = hasEmptyCondition(f);
8222 : f->get_test();
8224
8225 appendStatement(ws, bb);
8226 isSgStatement(f->get_parent())->replace_statement(f, bb);
8227}
8228
8230 Rose_STL_Container<SgNode*> fors = NodeQuery::querySubTree(top,
8231V_SgForStatement);
8232 for (size_t i = 0; i < fors.size(); ++i) {
8233 convertForToWhile(isSgForStatement(fors[i]));
8234 }
8235}
8236
8237 vector<SgGotoStatement*> SageInterface::findGotoStmts(SgStatement* scope, SgLabelStatement* l) {
8238 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8239 // But we still need the copy since the return type is IR node specific.
8240 Rose_STL_Container<SgNode*> allGotos = NodeQuery::querySubTree(scope, V_SgGotoStatement);
8241
8242 vector<SgGotoStatement*> result;
8243 for (Rose_STL_Container<SgNode*>::const_iterator i = allGotos.begin(); i != allGotos.end(); ++i) {
8244 if (isSgGotoStatement(*i)->get_label() == l) {
8245 result.push_back(isSgGotoStatement(*i));
8246 }
8247 }
8248 return result;
8249 }
8250
8251#if 0 // Liao 5/21/2010. This is a bad function in terms of performance
8252 // vectors are created/destroyed multiple times
8253 vector<SgReturnStmt*> SageInterface::findReturnStmts(SgStatement* scope) {
8254 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8255 // But we still need the copy since the return type is IR node specific.
8256 Rose_STL_Container<SgNode*> returns = NodeQuery::querySubTree(scope, V_SgReturnStmt);
8257
8258 vector<SgReturnStmt*> result;
8259 for (Rose_STL_Container<SgNode*>::const_iterator i = returns.begin(); i != returns.end(); ++i) {
8260 result.push_back(isSgReturnStmt(*i));
8261 }
8262 return result;
8263 }
8264
8265#endif
8266static void getSwitchCasesHelper(SgStatement* top, vector<SgStatement*>& result) {
8267 ROSE_ASSERT (top);
8268 if (isSgSwitchStatement(top)) return; // Don't descend into nested switches
8269 if (isSgCaseOptionStmt(top) || isSgDefaultOptionStmt(top)) {
8270 result.push_back(top);
8271 }
8272 vector<SgNode*> children = top->get_traversalSuccessorContainer();
8273 for (unsigned int i = 0; i < children.size(); ++i) {
8274 if (isSgStatement(children[i])) {
8275 getSwitchCasesHelper(isSgStatement(children[i]), result);
8276 }
8277 }
8278 }
8279
8281 vector<SgStatement*> result;
8282 getSwitchCasesHelper(sw->get_body(), result);
8283 return result;
8284 }
8285
8286
8287#endif
8288
8295SgScopeStatement* SageInterface::getEnclosingScope(SgNode* n, const bool includingSelf/* =false*/)
8296{
8297 SgScopeStatement* result = getScope (n);
8298 if (result == n)
8299 {
8300 if (!includingSelf)
8301 result = getScope(n->get_parent());
8302 }
8303 return result;
8304}
8305
8306// from transformationSupport.C
8309 {
8310
8311 // Case 1: directly call get_scope() for some types of nodes
8312 if (const SgSymbol* symbol = isSgSymbol(astNode))
8313 return symbol->get_scope();
8314 else if (const SgInitializedName* initName = isSgInitializedName(astNode))
8315 return initName->get_scope();
8316 else if (const SgTemplateArgument* tempArg = isSgTemplateArgument(astNode))
8317 return tempArg->get_scope();
8318 else if (const SgQualifiedName* qualifiedName = isSgQualifiedName(astNode))
8319 return qualifiedName->get_scope();
8320
8321 // DQ (6/9/2007): This function traverses through the parents to the first scope (used for name qualification support of template arguments)
8322 const SgNode* parentNode = astNode;
8323 while (!isSgScopeStatement(parentNode))
8324 {
8325 //George Vulov (11/29/2010)
8326 //Function parameter lists are siblings of SgFunctionDefinition, so just going up to parents
8327 //produces SgGlobal.
8328 if (isSgFunctionParameterList(parentNode) || isSgCtorInitializerList(parentNode))
8329 {
8330 const SgFunctionDeclaration* funcDeclaration = isSgFunctionDeclaration(parentNode->get_parent());
8331 ROSE_ASSERT(funcDeclaration != NULL);
8332 funcDeclaration = isSgFunctionDeclaration(funcDeclaration->get_definingDeclaration());
8333 if (funcDeclaration != NULL)
8334 {
8335 return funcDeclaration->get_definition();
8336 }
8337 }
8338
8339 parentNode = parentNode->get_parent();
8340 if (parentNode == NULL)
8341 {
8342 break;
8343 }
8344 }
8345
8346 // Check to see if we made it back to the root (current root is SgProject).
8347 // It is also OK to stop at a node for which get_parent() returns NULL (SgType and SgSymbol nodes).
8348 if ( isSgScopeStatement(parentNode) == NULL &&
8349 dynamic_cast<const SgType*>(parentNode) == NULL &&
8350 dynamic_cast<const SgSymbol*>(parentNode) == NULL )
8351 {
8352 printf ("Error: In SageInterface::getScope(): could not trace back to SgScopeStatement node \n");
8353 ROSE_ABORT();
8354 }
8355 else
8356 {
8357 if ( dynamic_cast<const SgType*>(parentNode) != NULL || dynamic_cast<const SgSymbol*>(parentNode) != NULL )
8358 {
8359 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());
8360 return NULL;
8361 }
8362 }
8363
8364 // Make sure we have a SgStatement node
8365 const SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8366 //SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8367 ROSE_ASSERT (scopeStatement != NULL);
8368
8369 // ensure the search is inclusive
8370 if (isSgScopeStatement(astNode))
8371 if (isSgScopeStatement(parentNode))
8372 {
8373 ROSE_ASSERT (astNode == parentNode);
8374 }
8375
8376 // return scopeStatement;
8377 return const_cast<SgScopeStatement*>(scopeStatement);
8378 }
8379
8380
8381// from outliner, ASTtools
8382// ------------------------------------------------
8383
8391static
8392const SgVariableSymbol *
8393getVarSymFromName_const (const SgInitializedName* name)
8394 {
8395 SgVariableSymbol* v_sym = NULL;
8396
8397 if (name != NULL)
8398 {
8399#if 0
8400 printf ("In getVarSymFromName(): name->get_name() = %s \n",name->get_name().str());
8401#endif
8402 SgScopeStatement* scope = name->get_scope();
8403 ROSE_ASSERT (scope != NULL);
8404#if 0
8405 printf ("In getVarSymFromName(): name->get_name() = %s scope = %p = %s \n",name->get_name().str(),scope,scope->class_name().c_str());
8406#endif
8407 v_sym = scope->lookup_var_symbol (name->get_name());
8408
8409 if (!v_sym) // E.g., might be part of an 'extern' declaration.
8410 {
8411 // Try the declaration's scope.
8412 SgDeclarationStatement* decl = name->get_declaration ();
8413 ROSE_ASSERT (decl);
8414
8415 SgScopeStatement* decl_scope = decl->get_scope ();
8416 if (decl_scope != NULL)
8417 v_sym = decl_scope->lookup_var_symbol (name->get_name());
8418
8419 if (!v_sym)
8420 cerr << "\t\t*** WARNING: Can't seem to find a symbol for '"
8421 << name->get_name ().str ()
8422 << "' ***" << endl;
8423 }
8424 }
8425
8426 return v_sym;
8427 }
8428
8429#if 0
8437static
8439getVarSymFromName (SgInitializedName* name)
8440{
8441 const SgVariableSymbol* v_sym = getVarSymFromName_const (name);
8442 return const_cast<SgVariableSymbol *> (v_sym);
8443}
8444#endif
8449static
8450const SgVariableSymbol *
8451getVarSym_const (const SgNode* n)
8452{
8453 const SgVariableSymbol* v_sym = 0;
8454 switch (n->variantT ())
8455 {
8456 case V_SgVarRefExp:
8457 v_sym = isSgVarRefExp (n)->get_symbol ();
8458 break;
8459 case V_SgInitializedName:
8460 v_sym = getVarSymFromName_const (isSgInitializedName (n));
8461 break;
8462 default:
8463 break;
8464 }
8465 return v_sym;
8466}
8467
8468#if 0
8473static
8475getVarSym (SgNode* n)
8476{
8477 const SgVariableSymbol* v_sym = getVarSym_const (n);
8478 return const_cast<SgVariableSymbol *> (v_sym);
8479}
8480#endif
8481
8482static
8483const SgVariableSymbol *
8484getFirstVarSym_const (const SgVariableDeclaration* decl)
8485{
8486 if (!decl) return 0;
8487 const SgInitializedNamePtrList& names = decl->get_variables ();
8488 if (names.begin () != names.end ())
8489 {
8490 const SgInitializedName* name = *(names.begin ());
8491 return getVarSym_const (name);
8492 }
8493 else
8494 return 0;
8495}
8496
8499{
8500 const SgVariableSymbol* sym = getFirstVarSym_const (decl);
8501 return const_cast<SgVariableSymbol *> (sym);
8502}
8503
8504
8507{
8508 ROSE_ASSERT(decl);
8509 SgInitializedNamePtrList& names = decl->get_variables ();
8510 if (names.begin () != names.end ())
8511 return *(names.begin ());
8512 else
8513 return NULL;
8514}
8515
8516
8517static void findBreakStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgBreakStmt*>& breakStmts) {
8518 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code) || isSgSwitchStatement(code)) {
8519 if (fortranLabel == "") {
8520 // Outermost loop only
8521 return;
8522 } else {
8523 // Set this for query on children
8524 inOutermostBody = false;
8525 }
8526 }
8527 if (isSgBreakStmt(code)) {
8528 SgBreakStmt* bs = isSgBreakStmt(code);
8529 bool breakMatchesThisConstruct = false;
8530 if (bs->get_do_string_label() == "") {
8531 // Break matches closest construct
8532 breakMatchesThisConstruct = inOutermostBody;
8533 } else {
8534 breakMatchesThisConstruct = (fortranLabel == bs->get_do_string_label());
8535 }
8536 if (breakMatchesThisConstruct) {
8537 breakStmts.push_back(bs);
8538 }
8539 return;
8540 }
8541 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8542 for (unsigned int i = 0; i < children.size(); ++i) {
8543 if (isSgStatement(children[i])) {
8544 findBreakStmtsHelper(isSgStatement(children[i]), fortranLabel, inOutermostBody, breakStmts);
8545 }
8546 }
8547}
8548
8549vector<SgBreakStmt*> SageInterface::findBreakStmts(SgStatement* code, const std::string& fortranLabel) {
8550 // Run this on the body of a loop or switch, because it stops at any
8551 // construct which defines a new scope for break statements
8552 vector<SgBreakStmt*> result;
8553 findBreakStmtsHelper(code, fortranLabel, true, result);
8554 return result;
8555}
8556
8557
8558static void findContinueStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgContinueStmt*>& continueStmts) {
8559 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code)) {
8560 if (fortranLabel == "") {
8561 // Outermost loop only
8562 return;
8563 } else {
8564 // Set this for query on children
8565 inOutermostBody = false;
8566 }
8567 }
8568 if (isSgContinueStmt(code)) {
8569 SgContinueStmt* cs = isSgContinueStmt(code);
8570 bool continueMatchesThisConstruct = false;
8571 if (cs->get_do_string_label() == "") {
8572 // Continue matches closest construct
8573 continueMatchesThisConstruct = inOutermostBody;
8574 } else {
8575 continueMatchesThisConstruct = (fortranLabel == cs->get_do_string_label());
8576 }
8577 if (continueMatchesThisConstruct) {
8578 continueStmts.push_back(cs);
8579 }
8580 return;
8581 }
8582 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8583 for (unsigned int i = 0; i < children.size(); ++i) {
8584 SgStatement* stmnt = isSgStatement(children[i]);
8585 if (stmnt != NULL) {
8586 findContinueStmtsHelper(stmnt, fortranLabel, inOutermostBody, continueStmts);
8587 }
8588 }
8589}
8590
8591vector<SgContinueStmt*> SageInterface::findContinueStmts(SgStatement* code, const std::string& fortranLabel) {
8592 // Run this on the body of a loop, because it stops at any construct which
8593 // defines a new scope for continue statements
8594 vector<SgContinueStmt*> result;
8595 findContinueStmtsHelper(code, fortranLabel, true, result);
8596 return result;
8597}
8598
8599
8600// Get the initializer containing an expression if it is within an
8601// initializer.
8602// from replaceExpressionWithStatement.C
8604 assert(n);
8605#if 0
8606 std::cout << "Starting getInitializerOfExpression on 0x" << std::hex << (int)n << ", which has type " << n->sage_class_name() << std::endl;
8607#endif
8608 while (!isSgInitializer(n)) {
8609 n = isSgExpression(n->get_parent());
8610#if 0
8611 std::cout << "Continuing getInitializerOfExpression on 0x" << std::hex << (int)n;
8612 if (n) std::cout << ", which has type " << n->sage_class_name();
8613 std::cout << std::endl;
8614#endif
8615 assert(n);
8616 }
8617 return isSgInitializer(n);
8618}
8619
8620#ifndef USE_ROSE
8621// Get all symbols used in a given expression
8623 class GetSymbolsUsedInExpressionVisitor: public AstSimpleProcessing {
8624 public:
8625 std::vector<SgVariableSymbol*> symbols;
8626
8627 virtual void visit(SgNode* n) {
8628 if (isSgVarRefExp(n))
8629 symbols.push_back(isSgVarRefExp(n)->get_symbol());
8630 }
8631 };
8632
8633 GetSymbolsUsedInExpressionVisitor vis;
8634 vis.traverse(expr, preorder);
8635 return vis.symbols;
8636}
8637#endif
8638
8641 return getEnclosingNode<SgSourceFile>(n, includingSelf);
8642}
8643
8644
8646{
8647 return findDeclarationStatement<SgFunctionDeclaration> (root, name, scope, isDefining);
8648}
8649
8650
8652{
8653 return getEnclosingFunctionDefinition(n,includingSelf);
8654}
8655
8658 return getEnclosingNode<SgFunctionDefinition>(n, includingSelf);
8659}
8660
8661
8664 return getEnclosingNode<SgFunctionDeclaration>(astNode, includingSelf);
8665}
8666
8667// #endif
8668
8669// #ifndef USE_ROSE
8670
8671SgGlobal*
8673 // should including itself in this case
8674 return getEnclosingNode<SgGlobal>(astNode, true /*includingSelf*/);
8675}
8676
8678SageInterface::getEnclosingClassDefinition(SgNode* astNode, const bool includingSelf/* =false*/) {
8679 return getEnclosingNode<SgClassDefinition>(astNode, includingSelf);
8680}
8681
8682
8685 // DQ (1/24/2019): This might have to get the SgClassDefinition and then the SgClassDeclaration from that.
8686 // I'm having trouble making this work for a member function declared outside of the class definition.
8687 return getEnclosingNode<SgClassDeclaration>(astNode, true);
8688}
8689
8691SageInterface::getEnclosingExprListExp(SgNode* astNode, const bool includingSelf/* =false*/) {
8692 return getEnclosingNode<SgExprListExp>(astNode, includingSelf);
8693}
8694
8695bool
8697 {
8698 bool returnValue = false;
8699
8700 struct Visitor: public AstSimpleProcessing
8701 {
8702 SgExpression* expression_target;
8703 bool in_subtree;
8704 virtual void visit(SgNode* n)
8705 {
8706 if (n == expression_target)
8707 {
8708 in_subtree = true;
8709 }
8710 }
8711
8712 Visitor(SgExpression* expr) : expression_target(expr), in_subtree(false) {}
8713 };
8714
8715 Visitor traversal(exp);
8716
8717 traversal.traverse(subtree, preorder);
8718
8719 returnValue = traversal.in_subtree;
8720
8721 return returnValue;
8722 }
8723
8724
8727 {
8728 // DQ (2/7/2019): Added more general function to support extraction of the associated function declaration.
8729 // The lower level functions are more robust on the SgFunctionRefExp and SgMemberFunctionRefExp than
8730 // when called on the SgFunctionCallExp for example.
8731
8732 // SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
8733 ROSE_ASSERT (functionCallExp != NULL);
8734
8735 SgExpression* expression = functionCallExp->get_function();
8736 ROSE_ASSERT (expression != NULL);
8737
8738 SgFunctionDeclaration* returnDeclaration = NULL;
8739
8740 SgDotExp* dotExp = isSgDotExp(expression);
8741 if (dotExp != NULL)
8742 {
8743 ROSE_ASSERT (dotExp != NULL);
8744
8745 SgExpression* rhsOperand = dotExp->get_rhs_operand();
8746 ROSE_ASSERT (rhsOperand != NULL);
8747
8748 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8749
8750 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8751 if (memberFunctionRefExp != NULL)
8752 {
8753 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8754 }
8755 }
8756
8757 SgFunctionRefExp* functionReferenceExp = isSgFunctionRefExp(expression);
8758 if (functionReferenceExp != NULL)
8759 {
8760 returnDeclaration = functionReferenceExp->getAssociatedFunctionDeclaration();
8761 }
8762
8763 SgArrowExp* arrowExp = isSgArrowExp(expression);
8764 if ( arrowExp != NULL)
8765 {
8766 ROSE_ASSERT (arrowExp != NULL);
8767
8768 SgExpression* rhsOperand = arrowExp->get_rhs_operand();
8769 ROSE_ASSERT (rhsOperand != NULL);
8770
8771 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8772
8773 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8774 if (memberFunctionRefExp != NULL)
8775 {
8776 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8777 }
8778 }
8779
8780 return returnDeclaration;
8781 }
8782
8783
8784
8785std::list<SgClassType*>
8787 {
8788 // DQ (2/16/2019): This version support for data member name qualification return type chains.
8789
8790#define DEBUG_DATA_MEMBER_TYPE_CHAIN 0
8791
8792 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
8793 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
8794 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
8795
8796 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
8797
8798 std::list<SgClassType*> returnTypeChain;
8799
8800 // Internal list used to filter the class chain generated from chained SgCastExp objects to identify the subset containing an ambiguity.
8801 std::list<SgClassType*> classChain;
8802
8803 // Make sure this is at least a reference to a data or member function member.
8804 // The requirements for these functions are different, however, if they were
8805 // virtual functions it might be a more attractive design.
8806 if (varRefExp != NULL)
8807 {
8808 ROSE_ASSERT(isDataMemberReference(varRefExp) == true);
8809 }
8810 else
8811 {
8812 ROSE_ASSERT(memberFunctionRefExp != NULL);
8813 ROSE_ASSERT(isMemberFunctionMemberReference(memberFunctionRefExp) == true);
8814 }
8815
8816 SgNode* parent = refExp->get_parent();
8817 ROSE_ASSERT(parent != NULL);
8818
8819#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8820 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): parent = %p = %s \n",parent,parent->class_name().c_str());
8821#endif
8822
8823 SgArrowExp* arrowExp = isSgArrowExp(parent);
8824 SgDotExp* dotExp = isSgDotExp(parent);
8825
8826 SgBinaryOp* binaryOperator = NULL;
8827
8828 if (arrowExp != NULL)
8829 {
8830#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8831 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an arrow expression \n");
8832#endif
8833 binaryOperator = arrowExp;
8834 }
8835
8836 if (dotExp != NULL)
8837 {
8838#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8839 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an dot expression \n");
8840#endif
8841 binaryOperator = dotExp;
8842 }
8843
8844 // ROSE_ASSERT(binaryOperator != NULL);
8845 if (binaryOperator != NULL)
8846 {
8847 SgExpression* lhs = binaryOperator->get_lhs_operand();
8848 ROSE_ASSERT(lhs != NULL);
8849
8850#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8851 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs = %p = %s \n",lhs,lhs->class_name().c_str());
8852#endif
8853
8854 // Looking for a chain of SgCastExp expressions.
8855 SgExpression* temp_lhs = lhs;
8856 SgCastExp* cast = NULL;
8857 while (isSgCastExp(temp_lhs) != NULL)
8858 {
8859 cast = isSgCastExp(temp_lhs);
8860 ROSE_ASSERT(cast != NULL);
8861 temp_lhs = cast->get_operand();
8862
8863#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8864 printf ("Top of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8865#endif
8866 ROSE_ASSERT(cast->get_type() != NULL);
8867 SgClassType* classType = isSgClassType(cast->get_type());
8868 if (classType == NULL)
8869 {
8870#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8871 printf (" --- looking for base type: In SageInterface::getClassTypeChainForDataMemberReference(): classType == NULL: cast->get_type() = %p = %s \n",
8872 cast->get_type(),cast->get_type()->class_name().c_str());
8873#endif
8874 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);
8875 ROSE_ASSERT(baseType != NULL);
8876
8877#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8878 printf (" --- baseType = %p = %s name = %s \n",baseType,baseType->class_name().c_str(),get_name(baseType).c_str());
8879#endif
8880 classType = isSgClassType(baseType);
8881 }
8882 // ROSE_ASSERT(classType != NULL);
8883
8884 ROSE_ASSERT(temp_lhs != NULL);
8885
8886#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8887 printf (" --- temp_lhs = %p = %s name = %s \n",temp_lhs,temp_lhs->class_name().c_str(),get_name(temp_lhs).c_str());
8888#endif
8889
8890#if 1
8891 // DQ (1/20/2020): This (original) code works fine.
8892 // returnTypeChain.push_front(classType);
8893 if (classType != NULL)
8894 {
8895 classChain.push_front(classType);
8896 }
8897#else
8898 // DQ (1/20/2020): This (new) code works for Cxx11_tests/test2020_61.C.
8899 if (classType != NULL)
8900 {
8901 // DQ (1/20/2020): We might want to fully resolve the class types associated with this cast here directly
8902 // (see Cxx11_tests/test2020_61.C). The point is that we need a qualified name that will reflect all of
8903 // the class declarations from the temp_lhs to the declarations associated with the classType.
8904 // The steps are:
8905 // 1) Get the target class definition for the type represented by the temp_lhs.
8906 // 2) Get the source class definition for the classType.
8907 // 3) Iterate from the source class definition to the target class definition, and save the associated
8908 // types associated with the class declarations associated with the scopes visited.
8909 SgType* target_type = temp_lhs->get_type();
8910 ROSE_ASSERT(target_type != NULL);
8911 SgClassType* target_classType = isSgClassType(target_type);
8912 // ROSE_ASSERT(target_classType != NULL);
8913 if (target_classType != NULL)
8914 {
8915 SgDeclarationStatement* target_declaration = target_classType->get_declaration();
8916 ROSE_ASSERT(target_declaration != NULL);
8917 SgClassDeclaration* target_classDeclaration = isSgClassDeclaration(target_declaration);
8918 ROSE_ASSERT(target_classDeclaration != NULL);
8919 SgClassDeclaration* target_definingClassDeclaration = isSgClassDeclaration(target_classDeclaration->get_definingDeclaration());
8920 ROSE_ASSERT(target_definingClassDeclaration != NULL);
8921 SgScopeStatement* target_scope = target_definingClassDeclaration->get_definition();
8922 ROSE_ASSERT(target_scope != NULL);
8923
8924#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8925 printf ("target_classDeclaration = %p = %s name = %s target_scope = %p = %s \n",
8926 target_classDeclaration,target_classDeclaration->class_name().c_str(),target_classDeclaration->get_name().str(),target_scope,target_scope->class_name().c_str());
8927#endif
8928 SgClassType* source_classType = classType;
8929 ROSE_ASSERT(source_classType != NULL);
8930 SgDeclarationStatement* source_declaration = source_classType->get_declaration();
8931 ROSE_ASSERT(source_declaration != NULL);
8932 SgClassDeclaration* source_classDeclaration = isSgClassDeclaration(source_declaration);
8933 ROSE_ASSERT(source_classDeclaration != NULL);
8934 SgClassDeclaration* source_definingClassDeclaration = isSgClassDeclaration(source_classDeclaration->get_definingDeclaration());
8935 ROSE_ASSERT(source_definingClassDeclaration != NULL);
8936 SgScopeStatement* source_scope = source_definingClassDeclaration->get_definition();
8937 ROSE_ASSERT(source_scope != NULL);
8938
8939#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8940 printf ("source_classDeclaration = %p = %s name = %s source_scope = %p = %s \n",
8941 source_classDeclaration,source_classDeclaration->class_name().c_str(),source_classDeclaration->get_name().str(),source_scope,source_scope->class_name().c_str());
8942#endif
8943 SgScopeStatement* tmp_scope = source_scope;
8944 while (tmp_scope != NULL && tmp_scope != target_scope)
8945 {
8946#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8947 printf ("tmp_scope = %p = %s \n",tmp_scope,tmp_scope->class_name().c_str());
8948#endif
8949 SgClassDefinition* tmp_classDefinition = isSgClassDefinition(tmp_scope);
8950 ROSE_ASSERT(tmp_classDefinition != NULL);
8951 SgClassDeclaration* tmp_classDeclaration = tmp_classDefinition->get_declaration();
8952 ROSE_ASSERT(tmp_classDeclaration != NULL);
8953
8954#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8955 SgName scope_name = tmp_classDeclaration->get_name();
8956 printf ("scope_name = %s \n",scope_name.str());
8957#endif
8958 SgClassType* tmp_classType = tmp_classDeclaration->get_type();
8959 ROSE_ASSERT(tmp_classType != NULL);
8960
8961 // classChain.push_front(tmp_classDefinition);
8962 classChain.push_front(tmp_classType);
8963
8964 tmp_scope = tmp_scope->get_scope();
8965
8966 if (isSgGlobal(tmp_scope) != NULL)
8967 {
8968 tmp_scope = NULL;
8969 }
8970 }
8971 }
8972 else
8973 {
8974#if 1
8975 printf ("In loop processing cast: target_type = %p = %s \n",target_type,target_type->class_name().c_str());
8976#endif
8977 }
8978 }
8979#endif
8980
8981#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8982 printf ("Bottom of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8983#endif
8984 }
8985
8986 // 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.
8987
8988 ROSE_ASSERT(temp_lhs != NULL);
8989
8990#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8991 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
8992#endif
8993
8994 SgVarRefExp* derivedClassVarRefExp = isSgVarRefExp(temp_lhs);
8995 if (derivedClassVarRefExp != NULL)
8996 {
8997 SgVariableSymbol* derivedClassVariableSymbol = derivedClassVarRefExp->get_symbol();
8998 ROSE_ASSERT(derivedClassVariableSymbol != NULL);
8999
9000 SgName derivedClassVariableName = derivedClassVariableSymbol->get_name();
9001
9002#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9003 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): derivedClassVariableName = %s \n",derivedClassVariableName.str());
9004#endif
9005 // SgType* type = cast->get_type();
9006 SgType* type = temp_lhs->get_type();
9007 ROSE_ASSERT(type != NULL);
9008
9009#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9010 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s \n",type,type->class_name().c_str());
9011#endif
9012
9013 // 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);
9014 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);
9015
9016#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9017 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type = %p = %s \n",stripped_type,stripped_type->class_name().c_str());
9018#endif
9019
9020 // SgClassType* classType = isSgClassType(type);
9021 SgClassType* classType = isSgClassType(stripped_type);
9022
9023 // ROSE_ASSERT(classType != NULL);
9024 if (classType != NULL)
9025 {
9026#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9027 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classType = %p = %s \n",classType,classType->class_name().c_str());
9028 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
9029 ROSE_ASSERT(classDeclaration != NULL);
9030 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classDeclaration = %p = %s name = %s \n",
9031 classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9032#endif
9033 // This is where we want the SgVarRefExp data member qualification to start.
9034 // returnType = classType;
9035 // returnTypeChain.push_front(classType);
9036 classChain.push_front(classType);
9037 }
9038 else
9039 {
9040#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9041 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type is not a SgClassType \n");
9042#endif
9043 }
9044 }
9045 else
9046 {
9047#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9048 printf ("Need to support alternative to SgVarRefExp: temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9049#endif
9050 SgType* type = temp_lhs->get_type();
9051 ROSE_ASSERT(type != NULL);
9052
9053#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9054 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s name = %s \n",type,type->class_name().c_str(),get_name(type).c_str());
9055#endif
9056
9057 // DQ (1/3/2019): Need to strip the type to get to a possible SgClassType.
9058 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);
9059
9060#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9061 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());
9062#endif
9063 // SgClassType* classType = isSgClassType(type);
9064 SgClassType* classType = isSgClassType(stripped_type);
9065 // returnTypeChain.push_front(classType);
9066 if (classType != NULL)
9067 {
9068 classChain.push_front(classType);
9069 }
9070 }
9071
9072#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9073 printf ("classChain.size() = %zu \n",classChain.size());
9074 std::list<SgClassType*>::iterator iter = classChain.begin();
9075 while(iter != classChain.end())
9076 {
9077 printf (" --- *iter = %p = %s name = %s \n",*iter,(*iter)->class_name().c_str(),(*iter)->get_name().str());
9078
9079 iter++;
9080 }
9081#endif
9082
9083 // Test the first element in the list to see if there is an ambiguity in the associated classDefinition
9084 // for the input variable referenced SgVarRefExp).
9085
9086 // SgVariableSymbol* variableSymbol = varRefExp->get_symbol();
9087 // ROSE_ASSERT(variableSymbol != NULL);
9088 // SgName variableName = variableSymbol->get_name();
9089 SgSymbol* referenceSymbol = NULL;
9090 if (varRefExp != NULL)
9091 {
9092 ROSE_ASSERT(varRefExp != NULL);
9093 ROSE_ASSERT(memberFunctionRefExp == NULL);
9094
9095 referenceSymbol = varRefExp->get_symbol();
9096 }
9097 else
9098 {
9099 ROSE_ASSERT(varRefExp == NULL);
9100 ROSE_ASSERT(memberFunctionRefExp != NULL);
9101
9102 referenceSymbol = memberFunctionRefExp->get_symbol();
9103 }
9104 ROSE_ASSERT(referenceSymbol != NULL);
9105 SgName symbolName = referenceSymbol->get_name();
9106
9107#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9108 printf ("referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9109 printf ("symbolName = %s \n",symbolName.str());
9110#endif
9111
9112 // Generate the name without the template arguments.
9113 SgFunctionSymbol* functionSymbol = isSgFunctionSymbol(referenceSymbol);
9114 if (functionSymbol != NULL)
9115 {
9116 // 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.
9117 // SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(referenceSymbol->get_declaration());
9118 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(functionSymbol->get_declaration());
9119 if (templateInstantiationMemberFunctionDeclaration != NULL)
9120 {
9121#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9122 printf ("This is a template name, we want the name without template arguments \n");
9123 printf ("templateInstantiationMemberFunctionDeclaration = %p \n",templateInstantiationMemberFunctionDeclaration);
9124 printf ("templateInstantiationMemberFunctionDeclaration->get_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_name().str());
9125#endif
9126
9127 // DQ (2/24/2019): This is an error (calls base class function).
9128 // printf ("templateInstantiationMemberFunctionDeclaration->get_template_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_template_name().str());
9129
9130 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration =
9131 isSgTemplateMemberFunctionDeclaration(templateInstantiationMemberFunctionDeclaration->get_templateDeclaration());
9132 if (templateMemberFunctionDeclaration != NULL)
9133 {
9134#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9135 printf ("templateMemberFunctionDeclaration = %p \n",templateMemberFunctionDeclaration);
9136 printf ("templateMemberFunctionDeclaration->get_name() = %s \n",templateMemberFunctionDeclaration->get_name().str());
9137#endif
9138 // We need the template name without template arguments.
9139 symbolName = templateMemberFunctionDeclaration->get_name();
9140 }
9141 else
9142 {
9143#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9144 printf ("templateMemberFunctionDeclaration == NULL: template declaration not available from template instantiation (rare, I think) \n");
9145#endif
9146 }
9147#if 0
9148 printf ("Exiting as a test! \n");
9149 ROSE_ABORT();
9150#endif
9151 }
9152 else
9153 {
9154 // DQ (2/24/2019): This might indicate another case to handle: finding SgMemberFunctionDeclaration (but this is not a template).
9155 SgDeclarationStatement* declarationStatement = functionSymbol->get_declaration();
9156 ROSE_ASSERT(declarationStatement != NULL);
9157#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9158 printf ("functionSymbol != NULL: but declaration is not a member function: declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
9159#endif
9160 }
9161 }
9162 else
9163 {
9164 SgVariableSymbol* variableSymbol = isSgVariableSymbol(referenceSymbol);
9165 if (variableSymbol != NULL)
9166 {
9167 // Nothing to do in this case of a SgVariableSymbol.
9168 }
9169 else
9170 {
9171#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9172 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): NOTE: referenceSymbol is not a SgFunctionSymbol or SgVariableSymbol \n");
9173#endif
9174#if 1
9175 printf ("Exiting as a test! \n");
9176 ROSE_ABORT();
9177#endif
9178 }
9179
9180 }
9181
9182#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9183 printf ("symbolName = %s \n",symbolName.str());
9184#endif
9185
9186 // SgClassType* firstDetectedAmbiguity = NULL;
9187 // SgClassType* lastDetectedAmbiguity = NULL;
9188
9189 // bool nameQualificationRequired = false;
9190
9191 // std::list<SgClassType*> deleteList;
9192 std::list<SgClassType*> saveList;
9193
9194#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9195 printf ("classChain.size() = %zu \n",classChain.size());
9196#endif
9197
9198 std::list<SgClassType*>::iterator i = classChain.begin();
9199 std::list<SgClassType*>::iterator save_iter = i;
9200
9201 // 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.
9202 save_iter++;
9203
9204 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9205 bool ambiguityDetectedSoSaveWholeChain = false;
9206
9207 while(i != classChain.end())
9208 {
9209#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9210 printf ("******** TOP OF WHILE LOOP ******** \n");
9211 printf (" --- *i = %p = %s name = %s \n",*i,(*i)->class_name().c_str(),(*i)->get_name().str());
9212 printf (" --- --- referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9213#endif
9214 bool ambiguityDetected = false;
9215
9216 SgDeclarationStatement* declarationStatement = (*i)->get_declaration();
9217 ROSE_ASSERT(declarationStatement != NULL);
9218 SgDeclarationStatement* definingDeclarationStatement = declarationStatement->get_definingDeclaration();
9219 if (definingDeclarationStatement != NULL)
9220 {
9221 SgClassDeclaration* classDeclaration = isSgClassDeclaration(definingDeclarationStatement);
9222 ROSE_ASSERT(classDeclaration != NULL);
9223 SgClassDefinition* classDefinition = classDeclaration->get_definition();
9224
9225#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9226 printf (" --- classDeclaration = %p = %s name = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9227 printf (" --- classDefinition = %p = %s \n",classDefinition,classDefinition->class_name().c_str());
9228#endif
9229 // This works for any SgName and SgSymbol, so it need not be specific to variables.
9230 ambiguityDetected = classDefinition->hasAmbiguity(symbolName,referenceSymbol);
9231
9232#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9233 printf (" --- ambiguityDetected = %s \n",ambiguityDetected ? "true" : "false");
9234#endif
9235 }
9236
9237 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9238 if (ambiguityDetected == true || ambiguityDetectedSoSaveWholeChain == true)
9239 {
9240 ambiguityDetectedSoSaveWholeChain = true;
9241
9242 if (save_iter != classChain.end())
9243 {
9244#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9245 printf (" --- add to saveList: *save_iter = %p \n",*save_iter);
9246#endif
9247 saveList.push_back(*save_iter);
9248 }
9249 else
9250 {
9251#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9252 printf (" --- save_iter == classChain.end() \n");
9253#endif
9254 }
9255 }
9256
9257#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9258 printf ("******** BOTTOM OF WHILE LOOP ******** \n");
9259#endif
9260 i++;
9261
9262 // Also increment the save_iter.
9263 save_iter++;
9264 }
9265
9266 // Now build a list of class types to use in the name qualification from firstDetectedAmbiguity to lastDetectedAmbiguity (inclusive).
9267
9268#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9269 printf ("saveList.size() = %zu \n",saveList.size());
9270 std::list<SgClassType*>::iterator saveList_iterator = saveList.begin();
9271 while (saveList_iterator != saveList.end())
9272 {
9273 printf (" --- *saveList_iterator = %p = %s name = %s \n",*saveList_iterator,(*saveList_iterator)->class_name().c_str(),(*saveList_iterator)->get_name().str());
9274
9275 saveList_iterator++;
9276 }
9277#endif
9278
9279 returnTypeChain = saveList;
9280
9281 // End of branch for binaryOperator != NULL.
9282 }
9283
9284 return returnTypeChain;
9285 }
9286
9287
9288
9289bool
9291 {
9292 // DQ (2/17/2019): This may share a design in common with isDataMemberReference() below.
9293
9294#define DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE 0
9295
9296 ROSE_ASSERT(memberFunctionRefExp != NULL);
9297
9298 bool returnValue = false;
9299
9300 // 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;")
9301 SgNode* parent = memberFunctionRefExp->get_parent();
9302
9303 SgArrowExp* arrowExp = isSgArrowExp(parent);
9304 SgDotExp* dotExp = isSgDotExp(parent);
9305
9306 // I don't know that the SgAddressOfOp is as relevant for the case of SgMemberFunctionRefExp, but I think
9307 // it is because we would have to support membr pointeds to functions the same a member pointers to data.
9308 // I need some examples test codes to verify that name qualification is important in this case.
9309 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9310
9311 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9312 {
9313 // Use a SgFunctionSymbol instead of a SgMemberFunctionSymbol for generality (I hope this works).
9314 SgFunctionSymbol* symbol = memberFunctionRefExp->get_symbol();
9315 ROSE_ASSERT(symbol != NULL);
9316
9317 SgFunctionDeclaration* functionDeclaration = symbol->get_declaration();
9318 ROSE_ASSERT(functionDeclaration != NULL);
9319
9320 // Check if this is a statically declared variable.
9321 if (functionDeclaration != NULL)
9322 {
9323 bool isStatic = functionDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9324#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9325 printf ("isStatic = %s \n",isStatic ? "true" : "false");
9326#endif
9327 if (isStatic == false)
9328 {
9329 SgScopeStatement* scope = functionDeclaration->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_MEMBER_FUNCTION_MEMBER_REFERENCE
9342 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp 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_MEMBER_FUNCTION_MEMBER_REFERENCE
9349 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9350#endif
9351 }
9352
9353#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9354 printf ("Leaving SageInterface::isMemberFunctionMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9355#endif
9356
9357 return returnValue;
9358 }
9359
9360
9361
9362bool
9364 {
9365 // This function is used to support the name qualification of data member references seperate from name qualification
9366 // of variables that might be members (e.g. "X x; x.A::y;" instead of "A::y" (which is just simple name qualification)).
9367
9368 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9369
9370 // DQ (2/17/2019): I think we need to make sure this is not a static data member reference (since those are qualified
9371 // differently (not member data name qualification). Consider changing the name of this function to indicate non-static.
9372
9373#define DEBUG_IS_DATA_MEMBER_REFERENCE 0
9374
9375 ROSE_ASSERT(varRefExp != NULL);
9376
9377 bool returnValue = false;
9378
9379 // 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;")
9380 SgNode* parent = varRefExp->get_parent();
9381
9382 SgArrowExp* arrowExp = isSgArrowExp(parent);
9383 SgDotExp* dotExp = isSgDotExp(parent);
9384
9385 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9386
9387 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9388 {
9389 if (arrowExp != NULL)
9390 {
9391 // DQ (2/17/2019): Check if this is part of a sizeof operand for which is is_objectless_nonstatic_data_member_reference == true.
9392 SgNode* parentOfArrowExp = arrowExp->get_parent();
9393 ROSE_ASSERT(parentOfArrowExp != NULL);
9394 SgSizeOfOp* sizeOfOp = isSgSizeOfOp(parentOfArrowExp);
9395 if (sizeOfOp != NULL && sizeOfOp->get_is_objectless_nonstatic_data_member_reference() == true)
9396 {
9397 // This is not to be qualified using data member name qualification (it should use standard name qualification).
9398#if DEBUG_IS_DATA_MEMBER_REFERENCE
9399 printf ("In SageInterface::isDataMemberReference(): Found case of expression used in sizeof with objectless_nonstatic_data_member_reference \n");
9400#endif
9401 return false;
9402 }
9403 }
9404
9405 SgVariableSymbol* symbol = varRefExp->get_symbol();
9406 ROSE_ASSERT(symbol != NULL);
9407
9408 SgInitializedName* initializedName = symbol->get_declaration();
9409 ROSE_ASSERT(initializedName != NULL);
9410
9411 // Check if this is a statically declared variable.
9412 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(initializedName->get_parent());
9413 if (variableDeclaration != NULL)
9414 {
9415 bool isStatic = variableDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9416 if (isStatic == false)
9417 {
9418 SgScopeStatement* scope = initializedName->get_scope();
9419 ROSE_ASSERT(scope != NULL);
9420
9421 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9422 if (classDefinition != NULL)
9423 {
9424 returnValue = true;
9425 }
9426 }
9427 }
9428 else
9429 {
9430#if DEBUG_IS_DATA_MEMBER_REFERENCE
9431 printf ("In SageInterface::isDataMemberReference(): varRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9432#endif
9433 }
9434 }
9435 else
9436 {
9437#if DEBUG_IS_DATA_MEMBER_REFERENCE
9438 printf ("In SageInterface::isDataMemberReference(): varRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9439#endif
9440 }
9441
9442#if DEBUG_IS_DATA_MEMBER_REFERENCE
9443 printf ("Leaving SageInterface::isDataMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9444#endif
9445
9446 return returnValue;
9447 }
9448
9449
9450#if 0
9451bool
9453 {
9454 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9455 ROSE_ASSERT(varRefExp != NULL);
9456
9457 bool returnValue = false;
9458
9459 SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9460
9461 if (addressOfOp != NULL)
9462 {
9463 returnValue = true;
9464 }
9465
9466 return returnValue;
9467 }
9468#endif
9469
9470bool
9472 {
9473 // DQ (2/17/2019): Need to generalize this function to apply to member functions references as well.
9474
9475 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
9476 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
9477 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
9478
9479 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
9480
9481 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9482 // ROSE_ASSERT(varRefExp != NULL);
9483 ROSE_ASSERT(refExp != NULL);
9484
9485 bool returnValue = false;
9486
9487 // SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9488 SgAddressOfOp* addressOfOp = isSgAddressOfOp(refExp->get_parent());
9489
9490 if (addressOfOp != NULL)
9491 {
9492 returnValue = true;
9493 }
9494
9495 return returnValue;
9496 }
9497
9499 {
9500 // DQ (3/4/2014): This new version of this function supports both C/C++ and also Java.
9501 // If the SgJavaPackageDeclaration is noticed then the previous parent is a
9502 // SgClassDefinition and the previous previous parent is a SgClassDeclaration whose
9503 // name can be used to match the filename in the SgProject's list of files.
9504 // A better implementation usign an attribute (not in place until tomorrow) and
9505 // from the attribute the pointer to the associated file is directly available.
9506 // The later implementation is as fast as possible.
9507
9508 ROSE_ASSERT (astNode != NULL);
9509
9510 // Make sure this is not a project node (since the SgFile exists below
9511 // the project and could not be found by a traversal of the parent list)
9512 ROSE_ASSERT (isSgProject(astNode) == NULL);
9513
9514 SgNode* previous_parent = NULL;
9515 SgNode* previous_previous_parent = NULL;
9516
9517 SgNode* parent = astNode;
9518 // while ( (parent != NULL) && (isSgFile(parent) == NULL) )
9519 while ( (parent != NULL) && (isSgFile(parent) == NULL) && isSgJavaPackageDeclaration(parent) == NULL)
9520 {
9521#if 0
9522 printf ("In getEnclosingFileNode(): parent = %p = %s \n",parent,parent->class_name().c_str());
9523#endif
9524 previous_previous_parent = previous_parent;
9525 previous_parent = parent;
9526
9527 parent = parent->get_parent();
9528 }
9529
9530 if (previous_previous_parent != NULL && previous_parent != NULL && isSgJavaPackageDeclaration(parent) != NULL)
9531 {
9532 // This is for a Java program and is contained within a SgJavaPackageDeclaration
9533#if 0
9534 printf ("parent = %p = %s \n",parent,parent->class_name().c_str());
9535 printf ("previous_parent = %p = %s \n",previous_parent,previous_parent->class_name().c_str());
9536 printf ("previous_previous_parent = %p = %s \n",previous_previous_parent,previous_previous_parent->class_name().c_str());
9537#endif
9538 SgClassDeclaration* classDeclaration = isSgClassDeclaration(previous_previous_parent);
9539 if (classDeclaration != NULL)
9540 {
9541#if 0
9542 printf ("Class name = %p = %s = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9543#endif
9544 // Find the associated Java class file.
9545#if 0
9546 // DQ (3/4/2014): This is the code we want to use until we get Philippe's branch in place with the attribute.
9547 SgProject* project = TransformationSupport::getProject(parent);
9548 ROSE_ASSERT(project != NULL);
9549 SgFileList* fileList = project->get_fileList_ptr();
9550 ROSE_ASSERT(fileList != NULL);
9551 SgFilePtrList & vectorFile = fileList->get_listOfFiles();
9552#if 0
9553 printf ("Output list of files: \n");
9554#endif
9555 SgFilePtrList::iterator i = vectorFile.begin();
9556 while (i != vectorFile.end())
9557 {
9558 SgFile* file = *i;
9559 ROSE_ASSERT(file != NULL);
9560#if 0
9561 printf (" --- filename = %s \n",file->getFileName().c_str());
9562#endif
9563 string filename = file->getFileName();
9564 string filenameWithoutPath = file->get_sourceFileNameWithoutPath();
9565 string classname = classDeclaration->get_name();
9566 string matchingfilename = classname + ".java";
9567#if 0
9568 printf (" --- --- filename = %s \n",filename.c_str());
9569 printf (" --- --- filenameWithoutPath = %s \n",filenameWithoutPath.c_str());
9570 printf (" --- --- classname = %s \n",classname.c_str());
9571 printf (" --- --- matchingfilename = %s \n",matchingfilename.c_str());
9572#endif
9573 if (filenameWithoutPath == matchingfilename)
9574 {
9575#if 0
9576 printf (" return file = %p \n",file);
9577#endif
9578 return file;
9579 }
9580
9581 i++;
9582 }
9583#else
9584 // DQ (3/4/2014): This is the code we want to use when the attribute is in place (philippe's branch).
9585 AstSgNodeAttribute *attribute = (AstSgNodeAttribute *) classDeclaration->getAttribute("sourcefile");
9586
9587 // "This simpler and more efficent code requires the latest work in Java support (3/6/2014)"
9588
9589 if (attribute)
9590 {
9591 // true for all user-specified classes and false for all classes fom libraries
9592 SgSourceFile *sourcefile = isSgSourceFile(attribute->getNode());
9593 ROSE_ASSERT(sourcefile != NULL);
9594 return sourcefile;
9595 }
9596#endif
9597 }
9598 }
9599 else
9600 {
9601 // previous_parent was uninitialized to a non-null value or astNode is a SgJavaPackageDeclaration or SgFile.
9602 if (previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9603 {
9604 // The input was a SgJavaPackageDeclaration (so there is no associated SgFile).
9605 ROSE_ASSERT(isSgJavaPackageDeclaration(astNode) != NULL);
9606 return NULL;
9607 }
9608 else
9609 {
9610 if (previous_previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9611 {
9612 // The input was a SgClassDefinition (so there is no associated SgFile).
9613 ROSE_ASSERT(isSgClassDefinition(astNode) != NULL);
9614 return NULL;
9615 }
9616 else
9617 {
9618 // This could be a C/C++ file (handled below).
9619 }
9620 }
9621 }
9622
9623 // This is where we handle the C/C++ files.
9624 if (parent == nullptr)
9625 {
9626 return nullptr;
9627 }
9628 else
9629 {
9630 return isSgFile(parent);
9631 }
9632 }
9633
9635 struct FrontendSpecificTraversal : public ROSE_VisitTraversal {
9636 std::set<SgNode*> specific;
9637 std::set<SgNode*> non_specific;
9638
9639 static void recursive_collect( SgNode* node , std::set<SgNode *> & collection ) {
9640 // Stop on sinks and loops
9641 if (node == NULL || !collection.insert(node).second) return;
9642
9643 std::vector<std::pair<SgNode*, std::string> > data_members = node->returnDataMemberPointers();
9644 for (std::vector<std::pair<SgNode*, std::string> >::iterator i = data_members.begin(); i != data_members.end(); ++i) {
9645 recursive_collect(i->first, collection);
9646 }
9647 }
9648
9649 void visit (SgNode* n) {
9650 Sg_File_Info * fileInfo = n->get_file_info();
9651
9652 if (fileInfo != NULL) {
9653 if (fileInfo->isFrontendSpecific()) {
9654 specific.insert(n);
9655 recursive_collect(n, specific);
9656 } else {
9657 non_specific.insert(n);
9658 recursive_collect(n, non_specific);
9659 }
9660 } else {
9661 fileInfo = isSg_File_Info(n);
9662 if (fileInfo != NULL) {
9663 if (fileInfo->isFrontendSpecific()) {
9664 specific.insert(n);
9665 } else {
9666 non_specific.insert(n);
9667 }
9668 }
9669 }
9670 }
9671
9672 std::set<SgNode*> apply() {
9673 traverseMemoryPool();
9674
9675 std::set<SgNode*> result;
9676
9677 std::set_difference(
9678 specific.begin(), specific.end(),
9679 non_specific.begin(), non_specific.end(),
9680 std::insert_iterator<set<SgNode*> >(result, result.begin())
9681 );
9682
9683 return result;
9684 }
9685 };
9686
9687 FrontendSpecificTraversal fst;
9688 return fst.apply();
9689}
9690
9691void
9693 {
9694 // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
9695
9696 class OutputSharedNodesTraversal : public SgSimpleProcessing
9697 {
9698 // This traversal collects the includes at the top of a file.
9699 public:
9700 void visit(SgNode *astNode)
9701 {
9702 ROSE_ASSERT(astNode != NULL);
9703 Sg_File_Info* file_info = astNode->get_file_info();
9704 if (file_info != NULL)
9705 {
9706 if (file_info->isShared() == true)
9707 {
9708 printf ("Found shared node: astNode = %p = %s \n",astNode,astNode->class_name().c_str());
9709 }
9710 }
9711 }
9712 };
9713
9714 OutputSharedNodesTraversal tt;
9715 tt.traverse(node,preorder);
9716 }
9717
9718
9719
9720
9721
9723 while (n && !isSgStatement(n)) n = n->get_parent();
9724 return isSgStatement(n);
9725}
9726
9727
9728
9729#if 1
9730// DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
9731// So I need to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.
9732
9733SageInterface::DeferredTransformation::DeferredTransformation()
9734 : deferredTransformationKind(e_default),
9735 statementToRemove(NULL),
9736 statementToAdd(NULL),
9737 class_definition(NULL),
9738 target_class_member(NULL),
9739 new_function_prototype(NULL),
9740 // DQ (2/28/2021): Added new data member to support deferred transformations.
9741 locationToOverwriteWithTransformation(NULL),
9742 transformationToOverwriteFirstStatementInInterval(NULL),
9743 blockOfStatementsToOutline(NULL)
9744 {
9745 // Default constructor (not particularly useful).
9746#if 0
9747 printf ("In SageInterface::DeferredTransformation default constructor called \n");
9748#endif
9749 }
9750
9751// DQ (2/28/2021): Added new data member to support deferred transformations.
9752// IntervalType statementInterval;
9753// SgStatement* locationToOverwriteWithTransformation;
9754
9755SageInterface::DeferredTransformation::DeferredTransformation(
9756 SgClassDefinition* input_class_definition,
9757 SgDeclarationStatement* input_target_class_member,
9758 SgDeclarationStatement* input_new_function_prototype)
9759 : deferredTransformationKind(e_outliner),
9760 statementToRemove(NULL),
9761 statementToAdd(NULL),
9762 class_definition(input_class_definition),
9763 target_class_member(input_target_class_member),
9764 new_function_prototype(input_new_function_prototype),
9765 // DQ (2/28/2021): Added new data member to support deferred transformations.
9766 locationToOverwriteWithTransformation(NULL),
9767 transformationToOverwriteFirstStatementInInterval(NULL),
9768 blockOfStatementsToOutline(NULL)
9769 {
9770 // This constructor is used by the outliner.
9771#if 0
9772 printf ("In SageInterface::DeferredTransformation constructor for outliner called \n");
9773#endif
9774 }
9775
9778 {
9779#if 0
9780 printf ("In SageInterface::DeferredTransformation constructor for replaceDefiningFunctionDeclarationWithFunctionPrototype called \n");
9781#endif
9782 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9783 // This constructor is used by tool_G and supports the use of the transformation represented
9784 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9786 X.deferredTransformationKind = e_replaceDefiningFunctionDeclarationWithFunctionPrototype;
9787 X.statementToRemove = functionDeclaration;
9788 X.statementToAdd = NULL;
9789 X.class_definition = NULL;
9790 X.target_class_member = NULL;
9791 X.new_function_prototype = NULL;
9792
9793 // DQ (2/28/2021): Added new data member to support deferred transformations.
9794 X.locationToOverwriteWithTransformation = NULL;
9795 X.transformationToOverwriteFirstStatementInInterval = NULL;
9796 X.blockOfStatementsToOutline = NULL;
9797
9798 return X;
9799 }
9800
9802SageInterface::DeferredTransformation::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool /*movePreprocessingInfo = false*/)
9803 {
9804#if 0
9805 printf ("In SageInterface::DeferredTransformation constructor for replaceStatement called \n");
9806#endif
9807 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9808 // This constructor is used by tool_G and supports the use of the transformation represented
9809 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9811 X.deferredTransformationKind = e_replaceStatement;
9812 X.statementToRemove = oldStmt;
9813 X.statementToAdd = newStmt;
9814 X.class_definition = NULL;
9815 X.target_class_member = NULL;
9816 X.new_function_prototype = NULL;
9817
9818 // DQ (2/28/2021): Added new data member to support deferred transformations.
9819 X.locationToOverwriteWithTransformation = NULL;
9820 X.transformationToOverwriteFirstStatementInInterval = NULL;
9821 X.blockOfStatementsToOutline = NULL;
9822
9823 return X;
9824 }
9825
9826SageInterface::DeferredTransformation::DeferredTransformation (const DeferredTransformation& X)
9827#if 0
9828 : deferredTransformationKind(X.deferredTransformationKind),
9829 statementToRemove(X.statementToRemove),
9830 statementToAdd(X.StatementToAdd),
9831 class_definition(X.class_definition),
9832 target_class_member(X.target_class_member),
9833 new_function_prototype(X.new_function_prototype),
9834 targetClasses(X.targetClasses),
9835 targetFriends(X.targetFriends)
9836 {
9837 }
9838#else
9839 {
9840#if 0
9841 printf ("In SageInterface::DeferredTransformation copy constructor called \n");
9842#endif
9843 // DQ (11/19/2020): Leverage the operator=() implementation to reduce complexity (one place to update).
9844 *this = X;
9845 }
9846#endif
9847
9849 {
9850#if 0
9851 printf ("Inside of SageInterface::DeferredTransformation::operator= (const DeferredTransformation& X) \n");
9852#endif
9853
9854#if 0
9855 // Original code.
9856 targetFriends = X.targetFriends;
9857 targetClasses = X.targetClasses;
9858#else
9859
9860 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9861 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9862 // definitions in the dynamic library file with function prototypes.
9863 transformationLabel = X.transformationLabel;
9864
9865 // New code added to support more general usage.
9866 deferredTransformationKind = X.deferredTransformationKind;
9867 statementToRemove = X.statementToRemove;
9868 statementToAdd = X.statementToAdd;
9869
9870 class_definition = X.class_definition;
9871 target_class_member = X.target_class_member;
9872 new_function_prototype = X.new_function_prototype;
9873 targetClasses = X.targetClasses;
9874 targetFriends = X.targetFriends;
9875
9876 // DQ (2/28/2021): Added new data member to support deferred transformations.
9877 statementInterval = X.statementInterval;
9878 locationToOverwriteWithTransformation = X.locationToOverwriteWithTransformation;
9879 transformationToOverwriteFirstStatementInInterval = X.transformationToOverwriteFirstStatementInInterval;
9880
9881 // DQ (3/1/2021): Added new data member to support deferred transformations.
9882 blockOfStatementsToOutline = X.blockOfStatementsToOutline;
9883#endif
9884
9885 return *this;
9886 }
9887
9892
9893std::string SageInterface::DeferredTransformation::outputDeferredTransformationKind(const TransformationKind & kind)
9894 {
9895 string returnValue = "uninitialized";
9896 switch (kind)
9897 {
9898 case e_error: returnValue = "e_error"; break;
9899 case e_default: returnValue = "e_default"; break;
9900 case e_outliner: returnValue = "e_outliner"; break;
9901 case e_replaceStatement: returnValue = "e_replaceStatement"; break;
9902 case e_removeStatement: returnValue = "e_removeStatement"; break;
9903 case e_replaceDefiningFunctionDeclarationWithFunctionPrototype: returnValue = "e_replaceDefiningFunctionDeclarationWithFunctionPrototype"; break;
9904 case e_last: returnValue = "e_last"; break;
9905 default:
9906 {
9907 printf ("Error: SageInterface::DeferredTransformation::get_deferredTransformationKind_string(): default reached \n");
9908 ROSE_ABORT();
9909 }
9910 }
9911
9912 return returnValue;
9913 }
9914
9915void SageInterface::DeferredTransformation::display ( std::string label ) const
9916 {
9917 printf ("SageInterface::DeferredTransformation::display(): label = %s \n",label.c_str());
9918
9919 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9920 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9921 // definitions in the dynamic library file with function prototypes.
9922 printf (" --- transformationLabel = %s \n",transformationLabel.c_str());
9923
9924 printf (" --- deferredTransformationKind = %s \n",outputDeferredTransformationKind(deferredTransformationKind).c_str());
9925 if (statementToRemove != NULL)
9926 {
9927 printf (" --- statementToRemove = %p = %s name = %s \n",statementToRemove,statementToRemove->class_name().c_str(),get_name(statementToRemove).c_str());
9928 }
9929 else
9930 {
9931 printf (" --- statementToRemove == NULL \n");
9932 }
9933
9934 if (statementToAdd != NULL)
9935 {
9936 printf (" --- statementToAdd = %p = %s name = %s \n",statementToAdd,statementToAdd->class_name().c_str(),get_name(statementToAdd).c_str());
9937 }
9938 else
9939 {
9940 printf (" --- statementToAdd == NULL \n");
9941 }
9942
9943 if (class_definition != NULL)
9944 {
9945 // printf (" --- class_definition = %p = %s name = %s \n",class_definition,class_definition->class_name().c_str(),get_name(class_definition).c_str());
9946 printf (" --- class_definition = %p \n",class_definition);
9947 }
9948
9949 if (target_class_member != NULL)
9950 {
9951 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());
9952 }
9953
9954 if (new_function_prototype != NULL)
9955 {
9956 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());
9957 }
9958
9959 // DQ (2/28/2021): Added new data member to support deferred transformations.
9960 if (locationToOverwriteWithTransformation != NULL)
9961 {
9962 // printf (" --- locationToOverwriteWithTransformation = %p = %s name = %s \n",locationToOverwriteWithTransformation,
9963 // locationToOverwriteWithTransformation->class_name().c_str(),get_name(locationToOverwriteWithTransformation).c_str());
9964 printf (" --- locationToOverwriteWithTransformation = %p \n",locationToOverwriteWithTransformation);
9965 }
9966
9967 // DQ (2/28/2021): Added new data member to support deferred transformations.
9968 if (transformationToOverwriteFirstStatementInInterval != NULL)
9969 {
9970 // printf (" --- transformationToOverwriteFirstStatementInInterval = %p = %s name = %s \n",transformationToOverwriteFirstStatementInInterval,
9971 // transformationToOverwriteFirstStatementInInterval->class_name().c_str(),get_name(transformationToOverwriteFirstStatementInInterval).c_str());
9972 printf (" --- transformationToOverwriteFirstStatementInInterval = %p \n",transformationToOverwriteFirstStatementInInterval);
9973 }
9974
9975 // DQ (3/1/2021): Added new data member to support deferred transformations.
9976 if (blockOfStatementsToOutline != NULL)
9977 {
9978 printf (" --- blockOfStatementsToOutline = %p \n",blockOfStatementsToOutline);
9979 }
9980
9981 printf ("targetClasses.size() = %zu \n",targetClasses.size());
9982 printf ("targetFriends.size() = %zu \n",targetFriends.size());
9983
9984 // DQ (2/28/2021): Added new data member to support deferred transformations.
9985 printf ("statementInterval.size() = %zu \n",statementInterval.size());
9986
9987 }
9988#endif
9989
9990
9991
9992
9993
9994// DQ (/20/2010): Control debugging output for SageInterface::removeStatement() function.
9995#define REMOVE_STATEMENT_DEBUG 0
9996
9998void SageInterface::removeStatement(SgStatement* targetStmt, bool autoRelocatePreprocessingInfo /*= true*/)
9999 {
10000#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
10001 // This function removes the input statement.
10002 // If there are comments and/or CPP directives then those comments and/or CPP directives will
10003 // be moved to a new SgStatement. The new SgStatement is selected using the findSurroundingStatementFromSameFile()
10004 // function and if there is not statement found then the SgGlobal IR node will be selected.
10005 // this work is tested by the tests/nonsmoke/functional/roseTests/astInterfaceTests/removeStatementCommentRelocation.C
10006 // translator and a number of input codes that represent a range of contexts which exercise different
10007 // cases in the code below.
10008
10009#ifndef _MSC_VER
10010 // This function only supports the removal of a whole statement (not an expression within a statement)
10011 ASSERT_not_null(targetStmt);
10012
10013 SgStatement * parentStatement = isSgStatement(targetStmt->get_parent());
10014
10015 // Can't assert this since SgFile is the parent of SgGlobal, and SgFile is not a statement.
10016 // Even so SgGlobal can't be removed from SgFile, but isRemovableStatement() takes a SgStatement.
10017 // ROSE_ASSERT (parentStatement != NULL);
10018
10019 bool isRemovable = (parentStatement != NULL) ? LowLevelRewrite::isRemovableStatement(targetStmt) : false;
10020
10021#if REMOVE_STATEMENT_DEBUG || 0
10022 printf ("In SageInterface::removeStatement(): parentStatement = %p = %s remove targetStatement = %p = %s (isRemovable = %s) \n",
10023 parentStatement,parentStatement->class_name().c_str(),targetStmt,targetStmt->class_name().c_str(),isRemovable ? "true" : "false");
10024#endif
10025
10026 if (isRemovable == true)
10027 {
10028 // DQ (9/19/2010): Disable this new (not completely working feature) so that I can checkin the latest UPC/UPC++ work.
10029#if 1
10030 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
10031 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
10032 // Liao 10/28/2010. Sometimes we want remove the statement with all its preprocessing information
10033 if (autoRelocatePreprocessingInfo == true)
10034 {
10035 // WE need to move up inner danglinge #endif or #if directives first.
10037 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
10038 // appear before the statment to be attached to the inserted statement (and marked
10039 // to appear before that statement).
10040 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
10041
10042
10043 if (comments != nullptr && isSgBasicBlock(targetStmt) == nullptr )
10044 {
10045 vector<int> captureList;
10046#if REMOVE_STATEMENT_DEBUG
10047 printf ("Found attached comments (removing %p = %s): comments->size() = %" PRIuPTR " \n",targetStmt,targetStmt->class_name().c_str(),comments->size());
10048#endif
10049
10050 // Liao 10/28/2010. relinking AST statements may be achieved by remove it and attach it to somewhere else.
10051 // In this case, preprocessing information sometimes should go with the statements and not be relocated to the original places.
10052 // Dan: Since this statement will be removed we have to relocate all the associated comments and CPP directives.
10053 int commentIndex = 0;
10054 AttachedPreprocessingInfoType::iterator i;
10055 for (i = comments->begin(); i != comments->end(); i++)
10056 {
10057 ROSE_ASSERT ( (*i) != NULL );
10058#if REMOVE_STATEMENT_DEBUG
10059 printf (" Attached Comment (relativePosition=%s): %s\n",
10060 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
10061 (*i)->getString().c_str());
10062 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
10063 (*i)->get_file_info()->display("comment/directive location debug");
10064#endif
10065 captureList.push_back(commentIndex);
10066 commentIndex++;
10067 }
10068
10069#if REMOVE_STATEMENT_DEBUG
10070 printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
10071#endif
10072
10073 if (captureList.empty() == false)
10074 {
10075 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
10076 // Find the surrounding statement by first looking up in the sequence of statements in this block, then down, we need another
10077 // statement from the same file. SgGlobal may be returned if nothing else is found.
10078 bool surroundingStatementPreceedsTargetStatement = false;
10079 SgStatement* surroundingStatement = findSurroundingStatementFromSameFile(targetStmt,surroundingStatementPreceedsTargetStatement);
10080
10081 if (surroundingStatement != nullptr)
10082 {
10083 // If we have identified a valid surrounding statemen, then move the comments and CPP directives to that statement.
10084#if REMOVE_STATEMENT_DEBUG
10085 printf ("In removeStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10086 printf (" --- moving comments from targetStmt = %p = %s name = %s \n",targetStmt,targetStmt->class_name().c_str(),get_name(targetStmt).c_str());
10087 printf (" --- moving comments to surroundingStatement = %p = %s name = %s \n",surroundingStatement,surroundingStatement->class_name().c_str(),get_name(surroundingStatement).c_str());
10088#endif
10089 moveCommentsToNewStatement(targetStmt,captureList,surroundingStatement,surroundingStatementPreceedsTargetStatement);
10090 }
10091 }
10092 } // end if (comments)
10093 }// end if (autoRelocatePreprocessingInfo)
10094#endif // end #if 1
10095
10096 // DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
10098
10099 parentStatement->remove_statement(targetStmt);
10100 }
10101#else
10102 printf ("Error: This is not supported within Microsoft Windows (I forget why). \n");
10103 ROSE_ABORT();
10104#endif
10105
10106#endif
10107 }
10108
10109
10110
10112void
10114 {
10115 // This function allows the modification of the input statement to trigger operations on internal
10116 // data structures that hold references to such statements. An example is the macroExpansion
10117 // data structures that have a reference to the statements that are associated with and macro expansion.
10118 // if a statement assocated with a macro expansion is removed, then the macroExpansion needs to be
10119 // updated to force all of the statements to be marked as transformed (so that the AST will be unparsed
10120 // instead of the tokens representing the macro or some partial representation of the transformed
10121 // statements and the macro call (worse).
10122
10123#if 0
10124 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10125#endif
10126
10127 SgSourceFile* sourceFile = getEnclosingSourceFile(sourceStatement);
10128
10129 // NOTE: if the statment has not yet been added to the AST then it will not return a valid pointer.
10130 // ROSE_ASSERT(sourceFile != NULL);
10131
10132#if 0
10133 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceFile = %p \n",sourceFile);
10134#endif
10135
10136 if (sourceFile != NULL)
10137 {
10138 std::map<SgStatement*,MacroExpansion*> & macroExpansionMap = sourceFile->get_macroExpansionMap();
10139
10140 if (macroExpansionMap.find(sourceStatement) != macroExpansionMap.end())
10141 {
10142 MacroExpansion* macroExpansion = macroExpansionMap[sourceStatement];
10143 ROSE_ASSERT(macroExpansion != NULL);
10144#if 0
10145 printf ("In resetInternalMapsForTargetStatement(): macroExpansion = %p = %s \n",macroExpansion,macroExpansion->macro_name.c_str());
10146#endif
10147 if (macroExpansion->isTransformed == false)
10148 {
10149 // Mark all of the statements in the macro expansion to be transformed.
10150 std::vector<SgStatement*> & associatedStatementVector = macroExpansion->associatedStatementVector;
10151
10152 for (size_t i = 0; i < associatedStatementVector.size(); i++)
10153 {
10154 // I am concerned that some of these statements might have been deleted.
10155 SgStatement* statement = associatedStatementVector[i];
10156#if 0
10157 printf ("Mark as transformation to be output: statement = %p = %s \n",statement,statement->class_name().c_str());
10158#endif
10159 // Note that any new statement might not yet have valid Sg_File_Info objects setup at this point.
10160 // Then again, now did it make it into the associatedStatementVector unless it was via memory
10161 // recycling through the mmory pool.
10162 if (statement->get_file_info() != NULL)
10163 {
10164 // Mark each of the statements as a transformation.
10165 statement->setTransformation();
10166
10167 // This is required, else the statement will not be output in the generated code.
10168 // To understand this, consider that statements in header files could be transformed,
10169 // but we would not want that to cause them to be unparse in the source file.
10170 statement->setOutputInCodeGeneration();
10171
10172 // Not clear if we should also remove the statement from the associatedStatementVector.
10173 // This would be important to do to avoid having the same location in the memory pool
10174 // be reused for another statement. Since we makr the macro expansion as transformed
10175 // we likely don't have to worry about this.
10176 }
10177 }
10178 }
10179
10180 // Mark this macro expansion as having been processed.
10181 macroExpansion->isTransformed = true;
10182 }
10183
10184 // Other data strucutes that may have to be updated include:
10185 // representativeWhitespaceStatementMap (should be required, but only effects whitespace details)
10186 // redundantlyMappedTokensToStatementMultimap (might not be required)
10187
10188 }
10189 }
10190
10191
10193void
10194SageInterface::moveCommentsToNewStatement(SgStatement* sourceStatement, const vector<int> & indexList, SgStatement* destinationStatement , bool destinationStatementProceedsSourceStatement)
10195 {
10196 AttachedPreprocessingInfoType* comments = sourceStatement->getAttachedPreprocessingInfo();
10197
10198#if REMOVE_STATEMENT_DEBUG || 0
10199 printf ("In moveCommentsToNewStatement(): destinationStatementProceedsSourceStatement = %s \n",destinationStatementProceedsSourceStatement ? "true" : "false");
10200 printf (" --- sourceStatement = %p = %s name = %s \n",sourceStatement,sourceStatement->class_name().c_str(),get_name(sourceStatement).c_str());
10201 printf (" --- destinationStatement = %p = %s name = %s \n",destinationStatement,destinationStatement->class_name().c_str(),get_name(destinationStatement).c_str());
10202#endif
10203 // Liao 2024/1/24
10204 // 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.
10205 // A solution : pcounter++ whenever a leading #if #ifdef #ifndef is encountered.
10206 // pcounter -- if #endif is countered
10207 // Normally the final pcounter ==0, if pcounter>=1, a #endif is missing somewhere. We should patch it up.
10208
10209#if REMOVE_STATEMENT_DEBUG
10210 printf ("Output the comments attached to sourceStatement: \n");
10211 printOutComments(sourceStatement);
10212 printf ("Output the comments attached to destinationStatement: \n");
10213 printOutComments(destinationStatement);
10214#endif
10215
10216 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
10217 vector<int>::const_iterator j = indexList.begin();
10218 PreprocessingInfo* prevTargetAnchorComment = NULL;
10219 while (j != indexList.end())
10220 {
10221 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
10222 ROSE_ASSERT(destinationStatement->get_file_info() != NULL);
10223#if REMOVE_STATEMENT_DEBUG || 0
10224 printf ("Attaching comments to destinationStatement = %p = %s on file = %s line %d \n",
10225 destinationStatement,destinationStatement->class_name().c_str(),
10226 destinationStatement->get_file_info()->get_filenameString().c_str(),
10227 destinationStatement->get_file_info()->get_line());
10228
10229 printf ("(*comments)[*j]->getRelativePosition() = %s \n",PreprocessingInfo::relativePositionName((*comments)[*j]->getRelativePosition()).c_str());
10230#endif
10231
10232 // Liao 2024/3/27: special handling when surrounding statement is SgGlobal
10233 // It should not be treated as either before or after the source statement we want to move comments from
10234 // SgGlobal should be treated as the enclosing scope of the source statement
10235 // The comments of the source statements should be attached to inside position of SgGlobal.
10236 // This is a variant of the before position (SgGlobal vs. source statement).
10237 // We do not treate SgGlobal as the same as if sgGlobal is preceeding source
10238 // because the comments of source statement would be attached to ::after of SgGlobal and
10239 // all comments will show up in the end of the file.
10240 // The ::inside location relies on the unparser to properly handle them later.
10241 if (destinationStatementProceedsSourceStatement == true || isSgGlobal(destinationStatement) != NULL )
10242 {
10243 // dest
10244 // src // comments to be moved up: all before positions become after position
10245 // // then append to dest's commments
10246 // adjust relative position one by one
10247 auto commentPosition = (*comments)[*j]->getRelativePosition();
10248 if (commentPosition == PreprocessingInfo::before)
10249 {
10250 // Mark comments that were before the preceeding statement to be after the preceeding statement
10251 (*comments)[*j]->setRelativePosition(PreprocessingInfo::after);
10252 }
10253 else if (commentPosition == PreprocessingInfo::after ||
10254 commentPosition == PreprocessingInfo::end_of)
10255 {
10256 // Leave position alone [Rasmussen 2023.01.09]
10257 }
10258 else
10259 {
10260 ROSE_ASSERT(false && "Comment relative position neither, before, after, nor end_of");
10261 }
10262
10263 // special handling of inside position
10264 // The surrounding statement will accept the comments. It also preceeds the source statement providing the comments.
10265 // If it is an enclosing scope statement, the comments should be attached to inside position, not before nor after.
10266 // if ( isSgGlobal(destinationStatement) || isSgBasicBlock(destinationStatement) )
10267 // Handle all SgScopeStatement variants.
10268 // We do this only for C/C++ language. Otherwise the code may break Jovial and other languages.
10270 {
10271 if (SageInterface::isAncestor(destinationStatement, sourceStatement))
10272 (*comments)[*j]->setRelativePosition(PreprocessingInfo::inside);
10273 }
10274 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10275
10276 }
10277 else // the target statement is after the source statment: we want to move comments from src to target
10278 {
10279 // src : comments : before or after (when moved to dest, it should become before)
10280 // all should be prepend to dest's first comment
10281 // dest: comments
10282 // adjust relative position one by one
10283 if ((*comments)[*j]->getRelativePosition() == PreprocessingInfo::before)
10284 {
10285 // Leave the comments marked as being before the removed statement
10286 // as before the following statement
10287 }
10288 else
10289 {
10290 // If is is not before, I hope it can only be after.
10291 ASSERT_require((*comments)[*j]->getRelativePosition() == PreprocessingInfo::after);
10292 (*comments)[*j]->setRelativePosition(PreprocessingInfo::before);
10293 }
10294 AttachedPreprocessingInfoType* targetInfoList = destinationStatement->getAttachedPreprocessingInfo();
10295 // source stmt has a list of comments c1, c2, c3
10296 // we want to keep their order and prepend to target stmt's existing comments
10297 // The solution is to define an anchor comment in target stmt
10298 // first time anchor is NULL, we prepend c1 to before the target stmt's first comment
10299 // after that, we insert after the anchor comment (previous anchor)
10300 // all anchor comments must come from source statement
10301 if (targetInfoList==NULL)
10302 {
10303 // we can just use append to the end. the same effect.
10304 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10305 }
10306 else
10307 {
10308 // target stmt has comments
10309 // first time to grab thing
10310 if( prevTargetAnchorComment==NULL)
10311 {
10312 PreprocessingInfo * origFirstTargetComment = *(targetInfoList->begin());
10313 // insert before this original first one
10314 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],origFirstTargetComment,false);
10315 }
10316 else
10317 {
10318 // now we have non null prev comment from target statement. insert after it!
10319 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],prevTargetAnchorComment ,true);
10320 }
10321 }
10322
10323 prevTargetAnchorComment = (*comments)[*j];
10324 }
10325
10326
10327 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
10328#if REMOVE_STATEMENT_DEBUG
10329 printf ("Marking entry from comments list as NULL on sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10330#endif
10331 (*comments)[*j] = nullptr;// Why do we need to make it NULL??
10332
10333 j++;
10334 }
10335
10336 // Now remove each NULL entries in the comments vector.
10337 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
10338 for (size_t n = 0; n < indexList.size(); n++)
10339 {
10340#if REMOVE_STATEMENT_DEBUG || 0
10341 printf ("Erase entry from comments list on comments->size() %" PRIuPTR " \n",comments->size());
10342#endif
10343 bool modifiedList = false;
10344 AttachedPreprocessingInfoType::iterator k = comments->begin();
10345 while (k != comments->end() && modifiedList == false)
10346 {
10347 // Only modify the list once per iteration over the captureList
10348 if (*k == nullptr)
10349 {
10350 k = comments->erase(k);
10351 modifiedList = true;
10352 continue;
10353 }
10354 else
10355 {
10356 k++;
10357 }
10358 }
10359 }
10360 }
10361
10362
10365SageInterface::findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement)
10366 {
10367 // Note that if the return value is SgGlobal (global scope), then surroundingStatementPreceedsTargetStatement is false, but meaningless.
10368 // This function can not return a NULL pointer.
10369
10370 ROSE_ASSERT(targetStmt != NULL);
10371
10372 SgStatement* surroundingStatement = targetStmt;
10373 int surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID; // No file id can have this value.
10374
10375#if REMOVE_STATEMENT_DEBUG || 0
10376 printf ("TOP of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10377#endif
10378
10379 std::set<SgStatement*> previousVisitedStatementSet;
10380
10381 // Only handle relocation for statements that exist in the file (at least for now while debugging).
10382 if (targetStmt->get_file_info()->get_file_id() >= 0)
10383 {
10384 surroundingStatementPreceedsTargetStatement = true;
10385
10386#if REMOVE_STATEMENT_DEBUG
10387 printf (" targetStmt->get_file_info()->get_file_id() = %d \n",targetStmt->get_file_info()->get_file_id());
10388#endif
10389#if REMOVE_STATEMENT_DEBUG
10390 printf ("Before loop: surroundingStatement = %p = %s name = %s surroundingStatement_fileId = %d \n",surroundingStatement,
10391 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str(),surroundingStatement_fileId);
10392#endif
10393 bool returningNullSurroundingStatement = false;
10394 // while (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id())
10395 while ((returningNullSurroundingStatement == false) && (surroundingStatement != NULL) && surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id())
10396 {
10397 // Start by going up in the source sequence.
10398 // This is a declaration from the wrong file so go to the next statement.
10399 // surroundingStatement = (insertBefore == true) ? getNextStatement(surroundingStatement) : getPreviousStatement(surroundingStatement);
10400 // surroundingStatement = (insertBefore == true) ? getPreviousStatement(surroundingStatement) : getNextStatement(surroundingStatement);
10401 surroundingStatement = getPreviousStatement(surroundingStatement);
10402
10403#if REMOVE_STATEMENT_DEBUG
10404 printf ("In loop: after getPreviousStatement(): surroundingStatement = %p = %s name = %s \n",surroundingStatement,
10405 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str());
10406#endif
10407
10408 if (surroundingStatement == NULL)
10409 {
10410 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10411#if REMOVE_STATEMENT_DEBUG
10412 printf (" surroundingStatement_fileId set to Sg_File_Info::BAD_FILE_ID \n");
10413#endif
10414 }
10415 else
10416 {
10417 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10418#if REMOVE_STATEMENT_DEBUG
10419 printf (" surroundingStatement = %p = %s surroundingStatement->get_file_info()->get_file_id() = %d \n",
10420 surroundingStatement,surroundingStatement->class_name().c_str(),surroundingStatement->get_file_info()->get_file_id());
10421#endif
10422 }
10423
10424#if REMOVE_STATEMENT_DEBUG
10425 if (surroundingStatement != NULL)
10426 {
10427 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",
10428 surroundingStatement,surroundingStatement->class_name().c_str(),
10429 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10430 surroundingStatement->get_file_info()->get_file_id(),
10431 surroundingStatement->get_file_info()->get_line());
10432 }
10433 else
10434 {
10435 printf ("surroundingStatement == NULL \n");
10436 }
10437#endif
10438
10439 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10440 if (previousVisitedStatementSet.find(surroundingStatement) != previousVisitedStatementSet.end())
10441 {
10442 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10443
10444 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10445
10446 surroundingStatement = NULL;
10447 // break;
10448 // return NULL;
10449 }
10450 else
10451 {
10452 previousVisitedStatementSet.insert(surroundingStatement);
10453 }
10454
10455 // As a last resort restart and go down in the statement sequence.
10456 if (surroundingStatement == NULL || isSgGlobal(surroundingStatement) != NULL)
10457 {
10458 // This is triggered by rose_inputloopUnrolling.C
10459#if REMOVE_STATEMENT_DEBUG
10460 printf ("We just ran off the start (top) of the file... targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
10461#endif
10462#if 0
10463 ROSE_ABORT();
10464#endif
10465 // A statement in the same file could not be identified, so this is false.
10466 surroundingStatementPreceedsTargetStatement = false;
10467
10468 // Restart by going the other direction (down in the source sequence)
10469 surroundingStatement = targetStmt;
10470 SgStatement* previousStatement = surroundingStatement;
10471 // surroundingStatement = getNextStatement(surroundingStatement);
10472 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10473
10474 std::set<SgStatement*> forwardVisitedStatementSet;
10475
10476 // while ( (surroundingStatement != NULL) && (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id()) )
10477 while ( (surroundingStatement != NULL) && (surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id()) )
10478 {
10479 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10480 if (forwardVisitedStatementSet.find(surroundingStatement) != forwardVisitedStatementSet.end())
10481 {
10482 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10483
10484 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10485
10486 surroundingStatement = NULL;
10487 break;
10488 // return NULL;
10489 }
10490 else
10491 {
10492 forwardVisitedStatementSet.insert(surroundingStatement);
10493 }
10494
10495 previousStatement = surroundingStatement;
10496 surroundingStatement = getNextStatement(surroundingStatement);
10497
10498 if (surroundingStatement == NULL)
10499 {
10500 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10501#if REMOVE_STATEMENT_DEBUG
10502 printf ("We just ran off the end (bottom) of the file... \n");
10503#endif
10504#if 0
10505 ROSE_ABORT();
10506#endif
10507 returningNullSurroundingStatement = true;
10508 }
10509 else
10510 {
10511 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10512#if REMOVE_STATEMENT_DEBUG
10513 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",
10514 surroundingStatement,surroundingStatement->class_name().c_str(),
10515 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10516 surroundingStatement->get_file_info()->get_file_id(),
10517 surroundingStatement->get_file_info()->get_line());
10518#endif
10519 }
10520 }
10521
10522 if (surroundingStatement == NULL)
10523 {
10524#if REMOVE_STATEMENT_DEBUG
10525 printf ("Resetting the surroundingStatement to the previousStatement = %p = %s \n",previousStatement,previousStatement->class_name().c_str());
10526#endif
10527 surroundingStatement = previousStatement;
10528
10529 // Check if this is the input statement we are removing (since the we have to attach comments to the global scope IR node.
10530 if (surroundingStatement == targetStmt)
10531 {
10532 // This can happen if there was only a single statement in a file and it was removed.
10533 // All associated comments would have to be relocated to the SgGlobal IR node.
10534#if REMOVE_STATEMENT_DEBUG
10535 printf ("Setting the surroundingStatement to be global scope \n");
10536#endif
10537 surroundingStatement = TransformationSupport::getGlobalScope(targetStmt);
10538 }
10539 }
10540 }
10541 }
10542
10543 ROSE_ASSERT(surroundingStatement != NULL);
10544 }
10545 else
10546 {
10547 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());
10548 surroundingStatement = NULL;
10549 }
10550
10551#if REMOVE_STATEMENT_DEBUG
10552 printf ("BOTTOM of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s surroundingStatement = %p \n",surroundingStatementPreceedsTargetStatement ? "true" : "false",surroundingStatement);
10553 if (surroundingStatement != NULL)
10554 {
10555 printf ("surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10556 }
10557#endif
10558
10559 // ROSE_ASSERT(surroundingStatement != NULL);
10560
10561 return surroundingStatement;
10562 }
10563
10564
10565#ifndef USE_ROSE
10568{
10569#if 0
10570 struct Visitor: public AstSimpleProcessing {
10571 virtual void visit(SgNode* n) {
10572 delete (n);
10573 }
10574 };
10575 Visitor().traverse(root, postorder);
10576#else
10577 deleteAST(root);
10578#endif
10579}
10580#endif
10581
10583void SageInterface::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessingInfoValue/* = false*/)
10584 {
10585 ROSE_ASSERT(oldStmt);
10586 ROSE_ASSERT(newStmt);
10587
10588 if (oldStmt == newStmt) return;
10589
10590 SgStatement * p = isSgStatement(oldStmt->get_parent());
10591 ROSE_ASSERT(p);
10592
10593#if 0
10594 // TODO handle replace the body of a C/Fortran function definition with a single statement?
10595 // Liao 2/1/2010, in some case, we want to replace the entire body (SgBasicBlock) for some parent nodes.
10596 // the built-in replace_statement() (insert_child() underneath) may not defined for them.
10597 if (SgFortranDo * f_do = isSgFortranDo (p))
10598 {
10599 ROSE_ASSERT (f_do->get_body() == oldStmt);
10600 if (!isSgBasicBlock(newStmt))
10601 newStmt = buildBasicBlock (newStmt);
10602 f_do->set_body(isSgBasicBlock(newStmt));
10603 newStmt->set_parent(f_do);
10604 }
10605 else
10606 {
10607 p->replace_statement(oldStmt,newStmt);
10608 }
10609#endif
10610 p->replace_statement(oldStmt,newStmt);
10611
10612#if 1
10613 // DQ (7/20/2021): Need to make the physical_file_ids match and the parents.
10614 // Acutally this may be too late in the case of a deferred transformation since
10615 // we run the AST consistancy tests as an intermediate step.
10616 int physical_file_id = oldStmt->get_startOfConstruct()->get_physical_file_id();
10617
10618#if 0
10619 printf ("In SageInterface::replaceStatement(): physical_file_id = %d \n",physical_file_id);
10620#endif
10621
10622 newStmt->get_startOfConstruct()->set_physical_file_id(physical_file_id);
10623 newStmt->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
10624
10625 // DQ (7/20/2021): Do we need this when we set the physical_file_id?
10626 newStmt->set_parent(oldStmt->get_parent());
10627#endif
10628
10629 // Some translators have their own handling for this (e.g. the outliner)
10630 if (movePreprocessingInfoValue)
10631 {
10632 // move inner dangling #endif, #if etc to newStmt's after position, otherwise they got lost
10633//A-B test here
10634 // I think we should move up old statement's inner dangling directives
10635 // later , we move directives from old statement to new statement
10637#if 0
10638 printf ("In SageInterface::replaceStatement(): calling moveUpPreprocessingInfo() changed to movePreprocessingInfo() \n");
10639#endif
10640
10641 // DQ (12/28/2020): I think this should be movePreprocessingInfo instead of moveUpPreprocessingInfo
10642 // (which has a collection of defaults that are not appropriate).
10643 // moveUpPreprocessingInfo(newStmt, oldStmt);
10644#if 1
10645 // 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).
10646 moveUpPreprocessingInfo(newStmt, oldStmt);
10647#else
10648 // void SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
10649 // PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
10650 bool usePrepend = true;
10651 // movePreprocessingInfo ( newStmt, oldStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10652 movePreprocessingInfo ( oldStmt, newStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10653#endif
10654 }
10655 }
10656
10657void
10659 {
10660 // Relocate the declaration to be explicitly represented in its associated namespace (required for some backend compilers to process template instantiations).
10661
10662 // DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
10663 // compiler which does not permit name qualification to be used to support the expression of the namespace
10664 // where a template instantiatoon would be places. Such name qualification would also sometimes require
10665 // global qualification which is also not allowed by the GNU g++ compiler. These issues appear to be
10666 // specific to the GNU compiler versions, at least versions 4.4 through 4.8.
10667
10668 // Find the previous statement in this scope so that we can close off the namepsace and start a new one.
10669 SgStatement* previousDeclarationStatement = getPreviousStatement(declarationStatement);
10670 SgStatement* nextDeclarationStatement = getNextStatement(declarationStatement);
10671
10672#if 0
10673 printf ("In SageInterface::moveDeclarationToAssociatedNamespace(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
10674 printf (" --- previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement != NULL ? previousDeclarationStatement->class_name().c_str() : "null");
10675 printf (" --- nextDeclarationStatement = %p \n",nextDeclarationStatement);
10676 printf (" --- nextDeclarationStatement = %p = %s \n",nextDeclarationStatement, nextDeclarationStatement != NULL ? nextDeclarationStatement->class_name().c_str() : "null");
10677#endif
10678
10679 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10680 if (previousDeclarationStatement != NULL)
10681 {
10682 // printf ("previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement->class_name().c_str());
10683 }
10684 else
10685 {
10686 printf ("There is no previous statement so there is no namespace to close off! \n");
10687
10688 // Handle this corner case after we have the most general case working!
10689 printf ("Exiting as a test! \n");
10690 ROSE_ABORT();
10691 }
10692
10693 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10694 if (nextDeclarationStatement != NULL)
10695 {
10696 // printf ("nextDeclarationStatement = %p = %s \n",nextDeclarationStatement,nextDeclarationStatement->class_name().c_str());
10697 }
10698 else
10699 {
10700#if 0
10701 printf ("There is no next statement so there is no namespace to reopen! \n");
10702#endif
10703#if 0
10704 // Handle this corner case after we have the most general case working!
10705 printf ("Exiting as a test! \n");
10706 ROSE_ABORT();
10707#endif
10708 }
10709
10710 if (previousDeclarationStatement != NULL && nextDeclarationStatement != NULL)
10711 {
10712 // DQ (7/19/2015): This is the most common case!
10713#if 0
10714 printf ("Identified the most common case... \n");
10715#endif
10716 // Identify the associated namespace
10717 //SgScopeStatement* declarationScope = declarationStatement->get_scope();
10718#if 0
10719 printf ("declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10720#endif
10721#if 0
10722 // Handle this corner case after we have the most general case working!
10723 printf ("Exiting as a test! \n");
10724 ROSE_ABORT();
10725#endif
10726 }
10727 else
10728 {
10729 if (previousDeclarationStatement != NULL && nextDeclarationStatement == NULL)
10730 {
10731 // This is the case for the last template instantiaton in global scope (so it too is a common case)!
10732#if 0
10733 printf ("Found 2nd most common case: previousDeclarationStatement != NULL && nextDeclarationStatement == NULL \n");
10734#endif
10735#if 0
10736 // Handle this corner case after we have the most general case working!
10737 printf ("Exiting as a test! \n");
10738 ROSE_ABORT();
10739#endif
10740 }
10741 else
10742 {
10743 if (previousDeclarationStatement == NULL && nextDeclarationStatement == NULL)
10744 {
10745 printf ("This case should require no special handling, unless we are still in the wrong namespace \n");
10746
10747 // Handle this corner case after we have the most general case working!
10748 printf ("Exiting as a test! \n");
10749 ROSE_ABORT();
10750 }
10751 else
10752 {
10753 printf ("This case should have been caught above! \n");
10754
10755 // Handle this corner case after we have the most general case working!
10756 printf ("Exiting as a test! \n");
10757 ROSE_ABORT();
10758 }
10759 }
10760 }
10761
10762 SgScopeStatement* declarationParent = isSgScopeStatement(declarationStatement->get_parent());
10763 if (declarationParent == NULL)
10764 {
10765#if 0
10766 printf ("declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10767#endif
10768 }
10769 // This can be a SgTemplateInstantiationDirectiveStatement (bug we want to skip over this case for now).
10770 // ROSE_ASSERT(declarationParent != NULL);
10771
10772 if (declarationParent != NULL)
10773 {
10774 SgScopeStatement* declarationScope = declarationStatement->get_scope();
10775 ROSE_ASSERT(declarationScope != NULL);
10776
10777 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(declarationScope);
10778 if (namespaceDefinition != NULL)
10779 {
10780 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
10781 ROSE_ASSERT(namespaceDeclaration != NULL);
10782#if 0
10783 printf ("The declaration has been identified to be associuated with a valid namespace = %p = %s \n",namespaceDeclaration,namespaceDeclaration->get_name().str());
10784 printf (" --- declarationParent = %p = %s \n",declarationParent,declarationParent->class_name().c_str());
10785 printf (" --- Move declaration from scope = %p = %s to namespace = %p = %s \n",declarationParent,declarationParent->class_name().c_str(),namespaceDeclaration,namespaceDeclaration->get_name().str());
10786#endif
10787#if 0
10788 printf ("Exiting as a test! \n");
10789 ROSE_ABORT();
10790#endif
10791 }
10792 else
10793 {
10794#if 0
10795 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());
10796#endif
10797 }
10798 }
10799 else
10800 {
10801#if 0
10802 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");
10803#endif
10804 // ROSE_ASSERT(declarationParent != NULL);
10805 }
10806
10807 }
10808
10809
10810bool
10812 {
10813 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10814 if (isSgTemplateInstantiationDefn(node) != NULL)
10815 {
10816#if 0
10817 printf ("Note: In SageInterface::isTemplateInstantiationNode(): skipping SgTemplateInstantiationDefn \n");
10818#endif
10819 }
10820
10821 return isSgTemplateInstantiationDecl(node)
10822 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10823// || isSgTemplateInstantiationDefn(node)
10824 || isSgTemplateInstantiationDefn(node)
10825 || isSgTemplateInstantiationFunctionDecl(node)
10826 || isSgTemplateInstantiationMemberFunctionDecl(node)
10827 || isSgTemplateInstantiationTypedefDeclaration(node)
10828 || isSgTemplateInstantiationDirectiveStatement(node)
10829 ;
10830 }
10831
10832#if 0
10833// DQ (5/23/2021): Added (uncommented, and added to the header file) function to support test for template declaration.
10834// Commented back out, since this is not required for what I am debugging currently.
10835// DQ (6/27/2018): This will be the template declaration test version of the template instantiation test function above.
10836bool
10837SageInterface::isTemplateDeclarationNode(SgNode* node)
10838 {
10839 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10840 if (isSgTemplateDefinition(node) != NULL)
10841 {
10842#if 0
10843 printf ("Note: In SageInterface::isTemplateDeclarationNode(): skipping SgTemplateDefinition \n");
10844#endif
10845 }
10846
10847 return isSgTemplateInstantiationDecl(node)
10848 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10849 // || isSgTemplateInstantiationDefn(node)
10850 || isSgTemplateInstantiationDefn(node)
10851 || isSgTemplateInstantiationFunctionDecl(node)
10852 || isSgTemplateInstantiationMemberFunctionDecl(node)
10853 || isSgTemplateInstantiationTypedefDeclaration(node)
10854 || isSgTemplateInstantiationDirectiveStatement(node)
10855 ;
10856 }
10857#endif
10858
10859void
10861 {
10862 // DQ (8/18/2015): This function is called from the tests/nonsmoke/functional/testTemplates translator.
10863
10864 // DQ (7/19/2015): This function can't use an iterator since it will be
10865 // doing transformations on the AST and will cause iterator invalidation errors.
10866
10867 std::vector<SgDeclarationStatement*> templateInstantiationVector;
10868
10869 // DQ (9/24/2015): This feature is not available yet in CMake (Markus is adding the library support for this feature).
10870#ifndef USE_CMAKEx
10871 RoseAst ast(root);
10872
10873 for (RoseAst::iterator i= ast.begin(); i!= ast.end(); ++i)
10874 {
10876 {
10877 // markNodeToBeUnparsed(*i);
10878 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
10879 if (declaration != NULL)
10880 {
10881 templateInstantiationVector.push_back(declaration);
10882 }
10883 else
10884 {
10885 // I think it is OK that not all are a SgDeclarationStatement.
10886 }
10887 }
10888 }
10889#else
10890 std::cerr << "This feature for now is available with autotools only!" << std::endl;
10891 ROSE_ABORT();
10892#endif
10893
10894 std::vector<SgDeclarationStatement*>::iterator j = templateInstantiationVector.begin();
10895 while (j != templateInstantiationVector.end())
10896 {
10898 j++;
10899 }
10900 }
10901
10902
10903
10905// All SgVariantExpression in the pattern will be replaced with copies of the anchor node.
10907{
10908 SgExpression * anchor_exp = isSgExpression(anchor);
10909 SgExpression * pattern_exp = isSgExpression(new_pattern);
10910 ROSE_ASSERT (anchor_exp != NULL);
10911 ROSE_ASSERT (pattern_exp != NULL);
10912
10913 // we replace all SgExpression within the pattern with copies of anchor
10914 Rose_STL_Container<SgNode*> opaque_exp_list = NodeQuery::querySubTree(pattern_exp,V_SgExpression);
10915 for (size_t i = 0; i<opaque_exp_list.size(); i++)
10916 {
10917 SgExpression* opaque_exp = isSgExpression(opaque_exp_list[i]);
10918 ROSE_ASSERT (opaque_exp != NULL);
10919 if (opaque_exp->variantT() == V_SgVariantExpression)
10920 {
10921 SgExpression * anchor_exp_copy = deepCopy(anchor_exp);
10922 replaceExpression(opaque_exp, anchor_exp_copy);
10923 }
10924 }
10925
10926 // finally we replace anchor_exp with the pattern_exp
10927 replaceExpression(anchor_exp, pattern_exp, false);
10928 return new_pattern;
10929}
10933{
10934 //This implementation tends to generate numbers that are unnecessarily high.
10935 static int counter = 0;
10936
10937 string name;
10938 bool collision = false;
10939 do
10940 {
10941 name = "__" + baseName + boost::lexical_cast<string > (counter++) + "__";
10942
10943 // DQ (8/16/2013): Modified to reflect new API.
10944 // Look up the name in the parent scopes
10945 // SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope);
10946 SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope,NULL,NULL);
10947 collision = (nameSymbol != NULL);
10948
10949 //Look up the name in the children scopes
10950 Rose_STL_Container<SgNode*> childScopes = NodeQuery::querySubTree(scope, V_SgScopeStatement);
10951
10952 BOOST_FOREACH(SgNode* childScope, childScopes)
10953 {
10954 SgScopeStatement* childScopeStatement = isSgScopeStatement(childScope);
10955
10956 // DQ (8/16/2013): Modified to reflect new API.
10957 // nameSymbol = childScopeStatement->lookup_symbol(SgName(name));
10958 nameSymbol = childScopeStatement->lookup_symbol(SgName(name),NULL,NULL);
10959
10960 collision = collision || (nameSymbol != NULL);
10961 }
10962 } while (collision);
10963
10964 return name;
10965}
10966
10967
10968std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableForExpression
10969(SgExpression* expression, SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate)
10970{
10971 SgType* expressionType = expression->get_type();
10972 SgType* variableType = expressionType;
10973
10974 //If the expression has a reference type, we need to use a pointer type for the temporary variable.
10975 //Else, re-assigning the variable is not possible
10976 bool isReferenceType = SageInterface::isReferenceType(expressionType);
10977 if (isReferenceType)
10978 {
10979 SgType* expressionBaseType = expressionType->stripType(SgType::STRIP_TYPEDEF_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE);
10980 variableType = SageBuilder::buildPointerType(expressionBaseType);
10981 }
10982
10983 //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.
10984 if (SgArrayType* arrayType=isSgArrayType(expressionType)) {
10985 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
10986 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
10987 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
10988 }
10989 }
10990
10991 // If the expression is a dereferenced pointer, use a reference to hold it.
10992 if (isSgPointerDerefExp(expression))
10993 variableType = SageBuilder::buildReferenceType(variableType);
10994
10995 //Generate a unique variable name
10996 string name = generateUniqueVariableName(scope);
10997
10998 //Initialize the temporary variable to an evaluation of the expression
10999 SgExpression* tempVarInitExpression = SageInterface::copyExpression(expression);
11000 ROSE_ASSERT(tempVarInitExpression != NULL);
11001 if (isReferenceType)
11002 {
11003 //FIXME: the next line is hiding a bug in ROSE. Remove this line and talk to Dan about the resulting assert
11004 tempVarInitExpression->set_lvalue(false);
11005
11006 tempVarInitExpression = SageBuilder::buildAddressOfOp(tempVarInitExpression);
11007 }
11008
11009 //Optionally initialize the variable in its declaration
11010 SgAssignInitializer* initializer = NULL;
11011 if (initializeInDeclaration)
11012 {
11013 SgExpression* initExpressionCopy = SageInterface::copyExpression(tempVarInitExpression);
11014 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11015 }
11016
11017 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11018 ROSE_ASSERT(tempVarDeclaration != NULL);
11019
11020 //Now create the assignment op for reevaluating the expression
11021 if (reEvaluate != NULL)
11022 {
11023 SgVarRefExp* tempVarReference = SageBuilder::buildVarRefExp(tempVarDeclaration);
11024 *reEvaluate = SageBuilder::buildAssignOp(tempVarReference, tempVarInitExpression);
11025 }
11026
11027 //Build the variable reference expression that can be used in place of the original expression
11028 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11029 if (isReferenceType)
11030 {
11031 //The temp variable is a pointer type, so dereference it before using it
11032 varRefExpression = SageBuilder::buildPointerDerefExp(varRefExpression);
11033 }
11034
11035 return std::make_pair(tempVarDeclaration, varRefExpression);
11036}
11037
11038// This function creates a temporary variable for a given expression in the given scope
11039// This is different from SageInterface::createTempVariableForExpression in that it does not
11040// try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
11041// The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
11042// may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
11043
11044std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableAndReferenceForExpression
11045(SgExpression* expression, SgScopeStatement* scope)
11046{
11047 SgType* expressionType = expression->get_type();
11048 SgType* variableType = expressionType;
11049
11050 //MS 10/24/2018: If the expression has array type, we need to use a pointer type for the temporary variable.
11051 if (SgArrayType* arrayType=isSgArrayType(expressionType))
11052 {
11053 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11054 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11055 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11056 }
11057 }
11058
11059 //Generate a unique variable name
11060 string name = generateUniqueVariableName(scope);
11061
11062 //initialize the variable in its declaration
11063 SgAssignInitializer* initializer = NULL;
11064 SgExpression* initExpressionCopy = SageInterface::copyExpression(expression);
11065 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11066
11067 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11068 ROSE_ASSERT(tempVarDeclaration != NULL);
11069
11070 //Build the variable reference expression that can be used in place of the original expression
11071 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11072 return std::make_pair(tempVarDeclaration, varRefExpression);
11073}
11074
11075
11076namespace
11077{
11078 void
11079 replaceExpressionInSgExpressionPtrList(SgExpression* oldExp, SgExpression* newExp, SgExpressionPtrList& lst, bool replAll = false)
11080 {
11081 SgExpressionPtrList::iterator lim = lst.end();
11082 SgExpressionPtrList::iterator pos = lst.begin();
11083 bool chg = false;
11084
11085 do
11086 {
11087 pos = std::find(pos, lim, oldExp);
11088
11089 if (pos != lim) { *pos = newExp; ++pos; chg = true; }
11090 } while (replAll && (pos != lim));
11091
11092 ROSE_ASSERT(chg);
11093 }
11094}
11095
11096// This code is based on OpenMP translator's ASTtools::replaceVarRefExp() and astInling's replaceExpressionWithExpression()
11097// Motivation: It involves the parent node to replace a VarRefExp with a new node
11098// Used to replace shared variables with the dereference expression of their addresses
11099// e.g. to replace shared1 with (*__pp_shared1)
11100
11101void SageInterface::replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp/*=false*/) {
11102 SgExpression* parentExp;
11103
11104 ROSE_ASSERT(oldExp);
11105 ROSE_ASSERT(newExp);
11106 if (oldExp==newExp) return;
11107
11108 if (isSgVarRefExp(newExp))
11109 newExp->set_need_paren(true); // enclosing new expression with () to be safe
11110
11111 SgNode* parent = oldExp->get_parent();
11112 ROSE_ASSERT(parent!=NULL);
11113 newExp->set_parent(parent);
11114
11115 // set lvalue when necessary
11116 if (oldExp->get_lvalue() == true) newExp->set_lvalue(true);
11117
11118 if (isSgExprStatement(parent)) {
11119 isSgExprStatement(parent)->set_expression(newExp);
11120 } else if (isSgForStatement(parent)) {
11121 ROSE_ASSERT (isSgForStatement(parent)->get_increment() == oldExp);
11122 isSgForStatement(parent)->set_increment(newExp);
11123 // TODO: any other cases here??
11124 } else if(SgMatlabForStatement *matlabFor = isSgMatlabForStatement(parent)) {
11125 if(matlabFor->get_index() == oldExp)
11126 matlabFor->set_index(newExp);
11127 else if(matlabFor->get_range() == oldExp)
11128 matlabFor->set_range(newExp);
11129 else
11130 ROSE_ASSERT(!"sub-expression not found");
11131 } else if(SgJovialForThenStatement *jovFor = isSgJovialForThenStatement(parent)) {
11132 if(jovFor->get_initialization() == oldExp)
11133 jovFor->set_initialization(newExp);
11134 else if(jovFor->get_while_expression() == oldExp)
11135 jovFor->set_while_expression(newExp);
11136 else if(jovFor->get_by_or_then_expression() == oldExp)
11137 jovFor->set_by_or_then_expression(newExp);
11138 else
11139 ROSE_ASSERT(!"sub-expression not found");
11140 } else if (SgRangeExp* rngexp = isSgRangeExp(parent)) {
11141 if (rngexp->get_start() == oldExp)
11142 rngexp->set_start(newExp);
11143 else if (rngexp->get_end() == oldExp)
11144 rngexp->set_end(newExp);
11145 else if (rngexp->get_stride() == oldExp)
11146 rngexp->set_stride(newExp);
11147 else
11148 ROSE_ASSERT(!"sub-expression not found");
11149 } else if (isSgReturnStmt(parent)) {
11150 isSgReturnStmt(parent)->set_expression(newExp);
11151 } else if (isSgBinaryOp(parent)!=NULL) {
11152 if (oldExp==isSgBinaryOp(parent)->get_lhs_operand()) {
11153 isSgBinaryOp(parent)->set_lhs_operand(newExp);
11154 } else if (oldExp==isSgBinaryOp(parent)->get_rhs_operand()) {
11155 isSgBinaryOp(parent)->set_rhs_operand(newExp);
11156 } else {
11157 ROSE_ABORT();
11158 }
11159 } else if (isSgUnaryOp(parent)!=NULL){
11160 if (oldExp==isSgUnaryOp(parent)->get_operand_i())
11161 isSgUnaryOp(parent)->set_operand_i(newExp);
11162 else
11163 ROSE_ABORT();
11164 } else if (isSgConditionalExp(parent) != NULL) {
11165 SgConditionalExp* expparent = isSgConditionalExp(parent); //get explicity type parent
11166 if (oldExp==expparent->get_conditional_exp())
11167 expparent->set_conditional_exp(newExp);
11168 else if (oldExp==expparent->get_true_exp())
11169 expparent->set_true_exp(newExp);
11170 else if (oldExp==expparent->get_false_exp())
11171 expparent->set_false_exp(newExp);
11172 else
11173 ROSE_ABORT();
11174 } else if (isSgExprListExp(parent) != NULL) {
11175 SgExpressionPtrList& explist = isSgExprListExp(parent)->get_expressions();
11176 for (Rose_STL_Container<SgExpression*>::iterator i=explist.begin();i!=explist.end();i++) {
11177 if (isSgExpression(*i)==oldExp) {
11178 SgExprListExp* parentExpListExp = isSgExprListExp(parent);
11179 parentExpListExp->replace_expression(oldExp,newExp);
11180 // break; //replace the first occurrence only??
11181 }
11182 }
11183 } else if (isSgValueExp(parent)) {
11184 // For compiler generated code, this could happen.
11185 // We can just ignore this function call since it will not appear in the final AST.
11186 return;
11187 } else if (SgActualArgumentExpression* actexp = isSgActualArgumentExpression(parent)) {
11188 ROSE_ASSERT(oldExp == actexp->get_expression());
11189 actexp->set_expression(newExp);
11190 } else if (SgAdaAttributeExp* attrexp = isSgAdaAttributeExp(parent)) {
11191 if (oldExp == attrexp->get_object()) {
11192 attrexp->set_object(newExp);
11193 } else if (oldExp == attrexp->get_args()) {
11194 SgExprListExp* newLst = isSgExprListExp(newExp);
11195 ASSERT_not_null(newLst);
11196
11197 attrexp->set_args(newLst);
11198 } else {
11199 ROSE_ABORT();
11200 }
11201 /**** ALL expressions must be handled before the next line *****/
11202 } else if ((parentExp=isSgExpression(parent)) != NULL) {
11203 int worked = parentExp->replace_expression(oldExp, newExp);
11204 // ROSE_DEPRECATED_FUNCTION
11205 ROSE_ASSERT (worked);
11206 } else if (isSgInitializedName(parent)) {
11207 SgInitializedName* initializedNameParent = isSgInitializedName(parent);
11208 if (oldExp == initializedNameParent->get_initializer()) {
11209 //We can only replace an initializer expression with another initializer expression
11210 ROSE_ASSERT(isSgInitializer(newExp));
11211 initializedNameParent->set_initializer(isSgInitializer(newExp));
11212 } else {
11213 //What other expressions can be children of an SgInitializedname?
11214 ROSE_ABORT();
11215 }
11216 } else if (isSgCaseOptionStmt(parent)) {
11217 SgCaseOptionStmt * case_stmt = isSgCaseOptionStmt(parent);
11218 if (oldExp == case_stmt->get_key()) {
11219 case_stmt->set_key(newExp);
11220 } else if(oldExp == case_stmt->get_key_range_end()) {
11221 case_stmt->set_key_range_end(newExp);
11222 } else {
11223 ROSE_ABORT();
11224 }
11225 } else if (isSgProcessControlStatement(parent)) {
11227 if (oldExp == ctrl_stmt->get_quiet()) {
11228 ctrl_stmt->set_quiet(newExp);
11229 } else if (oldExp == ctrl_stmt->get_code()) {
11230 ctrl_stmt->set_code(newExp);
11231 } else {
11232 ROSE_ABORT();
11233 }
11234 } else if (isSgFortranDo(parent)) {
11235 SgFortranDo* fortranDo = isSgFortranDo(parent);
11236 if (oldExp == fortranDo->get_initialization()) {
11237 fortranDo->set_initialization(newExp);
11238 } else if(oldExp == fortranDo->get_bound()) {
11239 fortranDo->set_bound(newExp);
11240 } else if (oldExp == fortranDo->get_increment()) {
11241 fortranDo->set_increment(newExp);
11242 } else {
11243 ROSE_ABORT();
11244 }
11245 }
11246 else if (SgAdaExitStmt* stm = isSgAdaExitStmt(parent)) {
11247 ROSE_ASSERT(oldExp == stm->get_condition());
11248 stm->set_condition(newExp);
11249 }
11250 else if (SgAdaModularType* ptype = isSgAdaModularType(parent)) {
11251 ROSE_ASSERT(oldExp == ptype->get_modexpr());
11252 ptype->set_modexpr(newExp);
11253 }
11254 else if (SgAdaDelayStmt* stm = isSgAdaDelayStmt(parent)) {
11255 ROSE_ASSERT(oldExp == stm->get_time());
11256 stm->set_time(newExp);
11257 } else if (SgAdaAttributeClause* clause = isSgAdaAttributeClause(parent)) {
11258 ROSE_ASSERT(oldExp == clause->get_size());
11259 clause->set_size(newExp);
11260 } else if (SgAdaRenamingDecl* dcl = isSgAdaRenamingDecl(parent)) {
11261 ROSE_ASSERT(oldExp == dcl->get_renamed());
11262 dcl->set_renamed(newExp);
11263 } else if (SgAdaEntryDecl* dcl = isSgAdaEntryDecl(parent)) {
11264 ROSE_ASSERT(oldExp == dcl->get_entryBarrier());
11265 dcl->set_entryBarrier(newExp);
11266 } else if (SgAdaSelectAlternativeStmt* stm = isSgAdaSelectAlternativeStmt(parent)) {
11267 ROSE_ASSERT(oldExp == stm->get_guard());
11268 stm->set_guard(newExp);
11269 } else if (SgAdaDeltaConstraint* delc = isSgAdaDeltaConstraint(parent)) {
11270 ROSE_ASSERT(oldExp == delc->get_delta());
11271 delc->set_delta(newExp);
11272 } else if (SgAdaDigitsConstraint* digc = isSgAdaDigitsConstraint(parent)) {
11273 ROSE_ASSERT(oldExp == digc->get_digits());
11274 digc->set_digits(newExp);
11275 } else if (SgAdaDiscriminantConstraint* disc = isSgAdaDiscriminantConstraint(parent)) {
11276 replaceExpressionInSgExpressionPtrList(oldExp, newExp, disc->get_discriminants());
11277 } else if (SgAdaRangeConstraint* rngc = isSgAdaRangeConstraint(parent)) {
11278 ROSE_ASSERT(oldExp == rngc->get_range());
11279 rngc->set_range(newExp);
11280 } else if (SgAdaIndexConstraint* idxc = isSgAdaIndexConstraint(parent)) {
11281 replaceExpressionInSgExpressionPtrList(oldExp, newExp, idxc->get_indexRanges());
11282 } else if (SgAdaVariantDecl* vtdcl = isSgAdaVariantDecl(parent)) {
11283 ROSE_ASSERT(oldExp == vtdcl->get_discriminant());
11284 vtdcl->set_discriminant(newExp);
11285 } else if (SgAdaRepresentationClause* clause = isSgAdaRepresentationClause(parent)) {
11286 ROSE_ASSERT(oldExp == clause->get_alignment());
11287 clause->set_alignment(newExp);
11288 } else if (SgAdaVariantWhenStmt* vtwhen = isSgAdaVariantWhenStmt(parent)) {
11289 SgExprListExp* newLst = isSgExprListExp(newExp);
11290 if (newLst && (oldExp == vtwhen->get_choices()))
11291 vtwhen->set_choices(newLst);
11292 else
11293 ROSE_ABORT();
11294 } else if (SgAdaComponentClause* clause = isSgAdaComponentClause(parent)) {
11295 if (oldExp == clause->get_offset())
11296 clause->set_offset(newExp);
11297 else if (oldExp == clause->get_range() && isSgRangeExp(newExp))
11298 clause->set_range(isSgRangeExp(newExp));
11299 else if (oldExp == clause->get_component() && isSgVarRefExp(newExp))
11300 clause->set_component(isSgVarRefExp(newExp));
11301 else
11302 ROSE_ABORT();
11303 } else if (SgAdaFunctionRenamingDecl* rendcl = isSgAdaFunctionRenamingDecl(oldExp->get_parent())) {
11304 if (oldExp == rendcl->get_renamed_function())
11305 rendcl->set_renamed_function(newExp);
11306 else
11307 ROSE_ABORT();
11308 } else {
11309 cerr<<"SageInterface::replaceExpression(). Unhandled parent expression type of SageIII enum value: " <<parent->class_name()<<endl;
11310 ROSE_ABORT();
11311 }
11312
11313 if (!keepOldExp) {
11314 deepDelete(oldExp); // avoid dangling node in memory pool
11315 } else {
11316 oldExp->set_parent(NULL);
11317 }
11318
11319} //replaceExpression()
11320
11322 {
11323 // reuse the implementation in ROSE namespace from src/roseSupport/utility_functions.C
11324 return Rose::getNextStatement(currentStmt);
11325 }
11326
11327SgStatement* SageInterface::getPreviousStatement(SgStatement * currentStmt, bool climbOutScope /*= true*/)
11328 {
11329 return Rose::getPreviousStatement(currentStmt, climbOutScope);
11330 }
11331
11333 return isSgIntVal(e) && isSgIntVal(e)->get_value() == value;
11334 }
11335
11337 {
11338 ROSE_ASSERT(func1&& func2);
11339 bool result = false;
11340 if (func1 == func2)
11341 result = true;
11342 else
11343 {
11345 {
11346 if (func1->get_name() == func2->get_name())
11347 result = true;
11348 }
11349 else if (is_Cxx_language() || is_Java_language())
11350 {
11351 if (func1->get_qualified_name().getString() +
11352 func1->get_mangled_name().getString() ==
11353 func2->get_qualified_name().getString() +
11354 func2->get_mangled_name().getString()
11355 )
11356 result = true;
11357 }
11358 else if (is_Fortran_language())
11359 {
11360 if (func1->get_name() == func2->get_name())
11361 result = true;
11362 }
11363 else
11364 {
11365 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11366 ROSE_ABORT();
11367 }
11368
11369 } // not identical
11370 return result;
11371 } // isSameFunction()
11372
11375{
11376 bool result =false;
11377 ROSE_ASSERT(stmt != NULL);
11378 SgScopeStatement* p_scope = stmt->get_scope();
11379 ROSE_ASSERT(p_scope != NULL);
11380#if 0
11381 if (p_scope->containsOnlyDeclarations())
11382 {
11383 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11384 if (stmtlist[stmtlist.size()-1] == stmt)
11385 result = true;
11386 }
11387 else
11388 {
11389 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11390 if (stmtlist[stmtlist.size()-1] == stmt)
11391 result = true;
11392 }
11393#endif
11394 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11395 if (stmtlist[stmtlist.size()-1] == stmt)
11396 result = true;
11397
11398 return result;
11399}
11400
11401#ifndef USE_ROSE
11402//-----------------------------------------------
11403// Remove original expression trees from expressions, so you can change
11404// the value and have it unparsed correctly.
11406 struct Visitor: public AstSimpleProcessing {
11407 virtual void visit(SgNode* n) {
11408 SgValueExp* valueExp = isSgValueExp(n);
11409 if (valueExp != NULL) {
11410 valueExp->set_originalExpressionTree(NULL);
11411 }
11412 else {
11413 SgCastExp* cast_exp = isSgCastExp(n);
11414 if (cast_exp != NULL) {
11415 cast_exp->set_originalExpressionTree(NULL);
11416 }
11417 }
11418 }
11419 };
11420 Visitor().traverse(top, preorder);
11421}
11422#endif
11423
11425 while (s && !isSgSwitchStatement(s)) {
11426 s = isSgStatement(s->get_parent());
11427 }
11428 ROSE_ASSERT (s);
11429 return isSgSwitchStatement(s);
11430}
11431
11434 while (s && !isSgOmpClauseBodyStatement(s)) {
11435 s = isSgStatement(s->get_parent());
11436 }
11437 // ROSE_ASSERT (s); // s is allowed to be NULL.
11438 if (s==NULL)
11439 return NULL;
11440 return isSgOmpClauseBodyStatement(s);
11441}
11442
11443
11444SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11445 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11446 for (; s; s = isSgStatement(s->get_parent())) {
11447 SgScopeStatement* sc = isSgScopeStatement(s);
11448 // Need to check for empty label as for java we must detect the
11449 // innermost labeled statement and skip everything in between
11450 switch (s->variantT()) {
11451 case V_SgDoWhileStmt: {
11452 if (label.empty()) {
11453 return sc;
11454 }
11455 break;
11456 }
11457 case V_SgForStatement: {
11458 if (label.empty()) {
11459 return sc;
11460 }
11461 break;
11462 }
11463 case V_SgFortranDo:
11464 case V_SgFortranNonblockedDo: {
11465 if (label.empty() ||
11466 label == isSgFortranDo(sc)->get_string_label()) {
11467 return sc;
11468 }
11469 break;
11470 }
11471 case V_SgWhileStmt: {
11472 if (label.empty() ||
11473 label == isSgWhileStmt(sc)->get_string_label()) {
11474 return sc;
11475 }
11476 break;
11477 }
11478 case V_SgSwitchStatement: {
11479 if (stopOnSwitches) return sc;
11480 break;
11481 }
11482 case V_SgJavaForEachStatement: {
11483 if (label.empty()) {
11484 return sc;
11485 }
11486 break;
11487 }
11488 case V_SgJavaLabelStatement: {
11489 if (label.empty() ||
11490 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11491 return sc;
11492 }
11493 break;
11494 }
11495 default: continue;
11496 }
11497 }
11498 return NULL;
11499}
11500
11501#ifndef USE_ROSE
11503{
11504 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11505 public:
11506 virtual void visit(SgNode* n) {
11507 if (isSgBasicBlock(n)) {
11508 SgBasicBlock* bb = isSgBasicBlock(n);
11509 bool changes = true;
11510 while (changes) {
11511 changes = false;
11512 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11513 i != bb->get_statements().end(); ++i) {
11514 if (isSgGotoStatement(*i)) {
11515 SgGotoStatement* gs = isSgGotoStatement(*i);
11516 SgStatementPtrList::iterator inext = i;
11517 ++inext;
11518 if (inext == bb->get_statements().end())
11519 continue;
11520 if (!isSgLabelStatement(*inext))
11521 continue;
11522 SgLabelStatement* ls = isSgLabelStatement(*inext);
11523 if (gs->get_label() == ls) {
11524 changes = true;
11525 bb->get_statements().erase(i);
11526 break;
11527 }
11528 }
11529 }
11530 }
11531 }
11532 }
11533 };
11534
11535 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11536
11537}
11538#endif
11539
11540// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11542 // assert (LowLevelRewrite::isRemovableStatement(*i));
11543 SgStatement* parent = isSgStatement(stmt->get_parent());
11544 ROSE_ASSERT (parent);
11545 SgBasicBlock* bb = isSgBasicBlock(parent);
11546 SgForInitStatement* fis = isSgForInitStatement(parent);
11547 if (bb || fis) {
11548 ROSE_ASSERT (bb || fis);
11549 SgStatementPtrList& siblings =
11550 (bb ? bb->get_statements() : fis->get_init_stmt());
11551 SgStatementPtrList::iterator j =
11552 std::find(siblings.begin(), siblings.end(), stmt);
11553 ROSE_ASSERT (j != siblings.end());
11554 siblings.erase(j);
11555 // LowLevelRewrite::remove(*i);
11556 } else {
11557 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11558 }
11559}
11560
11561
11562#ifndef USE_ROSE
11563std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11564{
11565 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11566 SgLabelStatementPtrSet& used;
11567 SgLabelStatementPtrSet& all;
11568
11569 public:
11570 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11571 SgLabelStatementPtrSet& all):
11572 used(used), all(all) {}
11573
11574 virtual void visit(SgNode* n) {
11575 if (isSgGotoStatement(n)) {
11576 used.insert(isSgGotoStatement(n)->get_label());
11577 }
11578 if (isSgLabelStatement(n)) {
11579 all.insert(isSgLabelStatement(n));
11580 }
11581 }
11582 };
11583
11584 SgLabelStatementPtrSet used;
11585 SgLabelStatementPtrSet unused;
11586 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11587
11588 for (SgLabelStatementPtrSet::iterator i = used.begin();
11589 i != used.end(); ++i) {
11590 assert (unused.find(*i) != unused.end());
11591 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11592 unused.erase(*i);
11593 }
11594
11595 return unused;
11596}
11597
11598// Remove all unused labels in a section of code.
11599void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11600
11601 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11602
11603 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11604 i != unused.end(); ++i) {
11605
11606 SgLabelStatement* l_stmt = *i;
11607 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11608 if (keepChild)
11609 {
11610 SgStatement* child= l_stmt->get_statement();
11611// l_stmt->set_parent(NULL);
11612 l_stmt->set_statement(NULL);
11613 replaceStatement (l_stmt, child);
11614 }
11615 else
11617 }
11618}
11619#endif
11620
11622 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11623 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11624 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11625
11626 ROSE_ASSERT (!"Bad loop kind");
11627 return NULL;
11628 }
11629
11631 if (isSgWhileStmt(loopStmt)) {
11632 isSgWhileStmt(loopStmt)->set_body(body);
11633 } else if (isSgForStatement(loopStmt)) {
11634 isSgForStatement(loopStmt)->set_loop_body(body);
11635 } else if (isSgDoWhileStmt(loopStmt)) {
11636 isSgDoWhileStmt(loopStmt)->set_body(body);
11637 } else {
11638 ROSE_ASSERT (!"Bad loop kind");
11639 }
11640 body->set_parent(loopStmt);
11641 }
11642
11644 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11645 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11646 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11647
11648 ROSE_ASSERT (!"Bad loop kind");
11649 return NULL;
11650 }
11651
11653 if (isSgWhileStmt(loopStmt)) {
11654 isSgWhileStmt(loopStmt)->set_condition(cond);
11655 } else if (isSgForStatement(loopStmt)) {
11656 isSgForStatement(loopStmt)->set_test(cond);
11657 } else if (isSgDoWhileStmt(loopStmt)) {
11658 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11659 } else {
11660 ROSE_ASSERT (!"Bad loop kind");
11661 }
11662 cond->set_parent(loopStmt);
11663 }
11664
11666// usually useful when compare two expressions to see if they actually refer to the same variable
11667static SgExpression* SkipCasting (SgExpression* exp)
11668{
11669 SgCastExp* cast_exp = isSgCastExp(exp);
11670 if (cast_exp != NULL)
11671 {
11672 SgExpression* operand = cast_exp->get_operand();
11673 assert(operand != 0);
11674 return SkipCasting(operand);
11675 }
11676 else
11677 return exp;
11678}
11679
11682{
11683 ROSE_ASSERT(loop!=NULL);
11684
11685 SgStatementPtrList &init = loop ->get_init_stmt();
11686 if (init.size() !=1) // We only handle one statement case
11687 return false;
11688
11689 SgStatement* init1 = init.front();
11690 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11691 if (decl == NULL) // we only handle for (int i=0; ...)
11692 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11693
11694 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11695 SgInitializedName* ivarname = decl->get_variables().front();
11696 SgExpression* lbast = NULL; // the lower bound, initial state
11697 ROSE_ASSERT(ivarname != NULL);
11698 SgInitializer * initor = ivarname->get_initializer();
11699 if (isSgAssignInitializer(initor))
11700 {
11701 lbast = isSgAssignInitializer(initor)->get_operand();
11702 }
11703 else
11704 { //SgConstructorInitializer etc.
11705 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11706 // they cause a loop to be non-canonical.
11707 return false;
11708 }
11709
11710 // add a new statement like int i; and insert it to the enclosing function
11711 // There are multiple choices about where to insert this statement:
11712 // global scope: max name pollution,
11713 // right before the loop: mess up perfectly nested loops
11714 // So we prepend the statement to the enclosing function's body
11716 ROSE_ASSERT(funcDef!=NULL);
11717 SgBasicBlock* funcBody = funcDef->get_body();
11718 ROSE_ASSERT(funcBody!=NULL);
11719 //TODO a better name
11720 std::ostringstream os;
11721 os<<ivarname->get_name().getString();
11722
11723 // keep the original variable name if possible
11724 SgSymbol * visibleSym = NULL;
11725 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11726 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11727 {
11728 os<<"_nom_";
11729 os<<++gensym_counter;
11730 }
11731
11732 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11733 prependStatement(ndecl, funcBody);
11734 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11735
11736 // replace variable ref to the new symbol
11737 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11738 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11739 {
11740 SgVarRefExp *vRef = isSgVarRefExp((*i));
11741 if (vRef->get_symbol()==osymbol)
11742 vRef->set_symbol(nsymbol);
11743 }
11744 // replace for (int i=0;) with for (i=0;)
11746 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11747 init.push_back(ninit);
11748 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11749 // ninit->set_parent(loop);
11750 ninit->set_parent(loop->get_for_init_stmt ());
11751
11752 // keep record of this normalization
11753 // We may undo it later on.
11754 trans_records.forLoopInitNormalizationTable[loop] = true;
11755 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11756
11757 return true;
11758}
11759
11760/*
11761 int i_norm_1;
11762 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11763Becomes:
11764 for (int i=0; i< upper; i++) ;
11765 * */
11767{
11768 ROSE_ASSERT (loop != NULL);
11769 //If not previously normalized, nothing to do and return false.
11770 if (!trans_records.forLoopInitNormalizationTable[loop])
11771 return false;
11772 // retrieve original and new declaration of the previous normalization
11773 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11774 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11775 ROSE_ASSERT (decl!= NULL);
11776 ROSE_ASSERT (ndecl!= NULL);
11777
11778
11779 // Sanity check
11780 SgStatementPtrList &init = loop ->get_init_stmt();
11781 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11782
11783 // remove the current init_stmt
11784 SgStatement* init1 = init.front();
11785 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11786 ROSE_ASSERT (exp_stmt != NULL);
11787 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11788 ROSE_ASSERT (assign_op != NULL);
11789
11790 // remove the new declaration and the current i_norm=1;
11791 removeStatement(ndecl);
11792 removeStatement (exp_stmt);
11793
11794 // restore the original declaration
11795 init.push_back(decl);
11796 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11797 // ninit->set_parent(loop);
11798 decl->set_parent(loop->get_for_init_stmt ());
11799
11800 // replace variable references
11801 // current symbol in the AST
11802 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11803 // new symbol we want to have: the original decl
11804 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11805 // replace variable ref to the new symbol
11806 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11807 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11808 {
11809 SgVarRefExp *vRef = isSgVarRefExp((*i));
11810 if (vRef->get_symbol()==osymbol)
11811 vRef->set_symbol(nsymbol);
11812 }
11813
11814 // clear record: now the loop is not normalized any more
11815 trans_records.forLoopInitNormalizationTable[loop] = false;
11816 return true;
11817}
11818
11820{
11821 ROSE_ASSERT(loop != NULL);
11822
11823 // Normalized the test expressions
11824 // -------------------------------------
11825#if 0 // this is undecided
11826 // skip for (;;) case
11827 SgStatement* test_stmt = loop->get_test();
11828 if (test_stmt!=NULL)
11829 {
11830 if (isSgNullStatement(test_stmt))
11831 return false;
11832 }
11833#endif
11834 SgExpression* test = loop->get_test_expr();
11835 SgExpression* testlhs=NULL, * testrhs=NULL;
11836 if (isSgBinaryOp(test))
11837 {
11838 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11839 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11840 ROSE_ASSERT(testlhs && testrhs);
11841 }
11842 else
11843 return false;
11844 // keep the variable since test will be removed later on
11845 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11846 if (testlhs_var == NULL )
11847 return false;
11848 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11849 if (var_symbol==NULL)
11850 return false;
11851
11852 switch (test->variantT()) {
11853 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11855 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11856 // deepDelete(test);// replaceExpression() does this already by default.
11857 break;
11858 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11860 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11861 break;
11862 case V_SgLessOrEqualOp:
11863 case V_SgGreaterOrEqualOp:
11864 case V_SgNotEqualOp: //TODO Do we want to allow this?
11865 break;
11866 default:
11867 return false;
11868 }
11869 return true;
11870}
11872{
11873 ROSE_ASSERT(loop != NULL);
11874
11875 SgExpression* test = loop->get_test_expr();
11876 SgExpression* testlhs=NULL, * testrhs=NULL;
11877 if (isSgBinaryOp(test))
11878 {
11879 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11880 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11881 ROSE_ASSERT(testlhs && testrhs);
11882 }
11883 else
11884 return false;
11885 // keep the variable since test will be removed later on
11886 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11887 if (testlhs_var == NULL )
11888 return false;
11889 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11890 if (var_symbol==NULL)
11891 return false;
11892
11893
11894 // -------------------------------------
11895 SgExpression* incr = loop->get_increment();
11896 ROSE_ASSERT(incr != NULL);
11897 switch (incr->variantT()) {
11898 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11899 {
11900 // check if the variables match
11901 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11902 if (incr_var == NULL) return false;
11903 if ( incr_var->get_symbol() != var_symbol)
11904 return false;
11905 replaceExpression(incr,
11906 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11907 break;
11908 }
11909 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11910 {
11911 // check if the variables match
11912 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11913 if (incr_var == NULL) return false;
11914 if ( incr_var->get_symbol() != var_symbol)
11915 return false;
11916 replaceExpression(incr,
11917 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11918 break;
11919 }
11920 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11921 {
11922 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11923 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11924 ROSE_ASSERT (rhs != NULL);
11925 if (incr_var == NULL) return false;
11926 if ( incr_var->get_symbol() != var_symbol)
11927 return false;
11928 replaceExpression(incr,
11929 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11930 break;
11931 }
11932 case V_SgAssignOp:
11933 case V_SgPlusAssignOp:
11934 break;
11935 default:
11936 return false;
11937 }
11938
11939 return true;
11940}
11942// Her loop translation does not pass AST consistency tests so we rewrite some of them here
11943// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
11944bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
11945{
11946 ROSE_ASSERT(loop != NULL);
11947 // Normalize initialization statement of the for loop
11948 // -------------------------------------
11949 // for (int i=0;... ) becomes int i; for (i=0;..)
11950 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
11952 return false;
11953
11954 // Normalized the test expressions
11955 if (!normalizeForLoopTest(loop))
11956 return false;
11957
11958 // Normalize the increment expression
11959 if (!normalizeForLoopIncrement(loop))
11960 return false;
11961
11962 // Normalize the loop body: ensure there is a basic block
11964 ROSE_ASSERT(body!=NULL);
11965 // Liao, 9/22/2009
11966 // folding entire loop may cause decreased accuracy for floating point operations
11967 // we only want to fold the loop controlling expressions
11968 if (foldConstant)
11969 {
11970 //constantFolding(loop->get_parent());
11971 constantFolding(loop->get_test());
11972 constantFolding(loop->get_increment());
11973 }
11974
11975 return true;
11976}
11977
11980{
11981 // TODO, normalize continue to enddo ?
11982 ROSE_ASSERT (loop != NULL);
11983 SgExpression* e_3 = loop->get_increment();
11984 if (isSgNullExpression(e_3))
11985 {
11986 SgIntVal* iv = buildIntVal(1);
11987 loop->set_increment(iv);
11988 iv->set_parent(loop);
11989 delete (e_3);
11990 }
11991 return true;
11992}
11993
11994#if 0
11995bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
11996{
11997 // normalize the loop first
11998 if (!forLoopNormalization(loop))
11999 return false; // input loop cannot be normalized to a canonical form
12000 // prepare Loop transformation environment
12002 ROSE_ASSERT(func!=NULL);
12003 AstInterfaceImpl faImpl(func->get_definition()->get_body());
12004 AstInterface fa(&faImpl);
12005 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
12006 ArrayInterface array_interface (*annot);
12007 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
12008 array_interface.observe(fa);
12009 LoopTransformInterface :: set_astInterface(fa);
12010 LoopTransformInterface :: set_arrayInterface(&array_interface);
12011
12012 // invoke the unrolling defined in Qing's code
12013 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
12014 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
12015
12016 LoopUnrolling lu(unrolling_factor);
12017 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
12018 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
12019 result = lu(lpTrans, result);
12020 return true;
12021}
12022#else
12023
12024// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12025/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12026 * Handle stride (step) >1
12027 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12028 *
12029 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12030 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12031 * fringe ==0 if no leftover iterations
12032 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12033 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12034 * loop body: copy body n times from 0 to factor -1
12035 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12036 * fringe loop: the same as the original loop, except for no init statement
12037 *
12038 * e.g:
12039 * // unrolling 3 times for the following loop with stride !=1
12040 * for (i=0; i<=9; i+=3)
12041 * {
12042 * a[i]=i;
12043 * }
12044 * // it becomes
12045 * // iteration count = 10%3=1 -> 10/3+1 = 4
12046 * // fringe = 4%3 =1 --> 3*3
12047 * // ub-fringe = 9-3*3
12048 * for (i=0; i<=9-3*3; i+=3*3)
12049 * {
12050 * a[i+3*0]=i;
12051 * a[i+3*1]=i;
12052 * a[i+3*2]=i;
12053 * }
12054 * // i=9 is the leftover iteration
12055 * for (; i<=9; i+=3)
12056 * {
12057 * a[i]=i;
12058 * }
12059 *
12060 */
12061bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12062{
12063#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12064 //Handle 0 and 1, which means no unrolling at all
12065 if (unrolling_factor <= 1)
12066 return true;
12067
12068 // normalize the target loop first
12069
12070 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12071 if (!forLoopNormalization(target_loop))
12072 {
12073 // the return value is not reliable
12074 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12075 // dumpInfo(target_loop);
12076 // return false;
12077 }
12078 // grab the target loop's essential header information
12079 SgInitializedName* ivar = NULL;
12080 SgExpression* lb = NULL;
12081 SgExpression* ub = NULL;
12082 SgExpression* step = NULL;
12083 SgStatement* orig_body = NULL;
12084 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12085 {
12086 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12087 dumpInfo(target_loop);
12088 return false;
12089 }
12090 ROSE_ASSERT(ivar&& lb && ub && step);
12091 ROSE_ASSERT(isSgBasicBlock(orig_body));
12092
12093 // generate the fringe loop
12094 bool needFringe = true;
12095 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12096 insertStatementAfter(target_loop,fringe_loop);
12097 removeStatement(fringe_loop->get_for_init_stmt());
12098 fringe_loop->set_for_init_stmt(NULL);
12099
12100 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12102 copyExpression(lb));
12103 raw_range_exp->set_need_paren(true);
12104 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12105 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12106
12107 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12108 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12109 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12110 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12111
12112 SgScopeStatement* scope = target_loop->get_scope();
12113 ROSE_ASSERT(scope != NULL);
12114 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12115 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12116 insertStatementBefore(target_loop, fringe_decl);
12117 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12118 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12119
12120 // compile-time evaluate to see if index is a constant of value 0
12121 // if so, the iteration count can be divided even by the unrolling factor
12122 // and no fringe loop is needed
12123 // WE have to fold on its parent node to get a possible constant since
12124 // constant folding only folds children nodes, not the current node to a constant
12125 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12126 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12127 ROSE_ASSERT(ivarname != NULL);
12128 // points to a new address if constant folding happens
12129 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12130 if (init1)
12131 if (isSgIntVal(init1->get_operand_i()))
12132 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12133 needFringe = false;
12134
12135 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12136 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12137 ROSE_ASSERT(ub_bin_op);
12138 if (needFringe)
12139 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12140 else
12141 {
12142 ub_bin_op->set_rhs_operand(copyExpression(ub));
12143 removeStatement(fringe_decl);
12144 }
12145
12146 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12147 ROSE_ASSERT(step_bin_op != NULL);
12148 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12149
12150 bool isPlus = false;
12151 if (isSgPlusAssignOp(step_bin_op))
12152 isPlus = true;
12153 else if (isSgMinusAssignOp(step_bin_op))
12154 isPlus = false;
12155 else
12156 {
12157 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12158 dumpInfo(step_bin_op);
12159 ROSE_ABORT();
12160 }
12161
12162 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12163 for (size_t i =1; i<unrolling_factor; i++)
12164 {
12165 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12166 ROSE_ASSERT(body);
12167 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12168 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12169 {
12170 SgVarRefExp* refexp = *iter;
12171 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12172 {
12173 // replace reference to ivar with ivar +/- step*i
12174 SgExpression* new_exp = NULL;
12175 //build replacement expression for every appearance
12176 if (isPlus) //ivar +/- step * i
12177 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12178 else
12180
12181 // replace it with the right one
12182 replaceExpression(refexp, new_exp);
12183 }
12184 }
12185 // copy body to loop body, this should be a better choice
12186 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12187 appendStatement(body,isSgBasicBlock(orig_body));
12188 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12189 }
12190
12191 // remove the fringe loop if not needed finally
12192 // it is used to buffering the original loop body before in either cases
12193 if (!needFringe)
12194 removeStatement(fringe_loop);
12195
12196 // constant folding for the transformed AST
12197 ConstantFolding::constantFoldingOptimization(scope,false);
12198 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12199
12200#endif
12201
12202 return true;
12203}
12204#endif
12205
12206// Liao, 6/15/2009
12209static size_t myfactorial (size_t n)
12210{
12211 size_t result=1;
12212 for (size_t i=2; i<=n; i++)
12213 result*=i;
12214 return result;
12215}
12216
12217#endif
12218
12219#ifndef USE_ROSE
12220
12223std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12224{
12225 size_t k = lexicoOrder;
12226 std::vector<size_t> s(n);
12227 // initialize the permutation vector
12228 for (size_t i=0; i<n; i++)
12229 s[i]=i;
12230
12231 //compute (n- 1)!
12232 size_t factorial = myfactorial(n-1);
12233 //check if the number is not in the range of [0, n! - 1]
12234 if (k/n>=factorial)
12235 {
12236 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12237 ROSE_ABORT();
12238 }
12239 // Algorithm:
12240 //check each element of the array, excluding the right most one.
12241 //the goal is to find the right element for each s[j] from 0 to n-2
12242 // method: each position is associated a factorial number
12243 // s[0] -> (n-1)!
12244 // s[1] -> (n-2)! ...
12245 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12246 // so only big enough k can have non-zero value after division
12247 // 0 value means no change to the position for the current iteration
12248 // The non-zero value is further modular by the number of the right hand elements of the current element.
12249 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12250 // choose one of them to be moved to the current position,
12251 // shift elements between the current and the moved element to the right direction for one position
12252 for (size_t j=0; j<n-1; j++)
12253 {
12254 //calculates the next cell from the cells left
12255 //(the cells in the range [j, s.length - 1])
12256 int tempj = (k/factorial) % (n - j);
12257 //Temporarily saves the value of the cell needed
12258 // to add to the permutation this time
12259 int temps = s[j+tempj];
12260 //shift all elements to "cover" the "missing" cell
12261 //shift them to the right
12262 for (size_t i=j+tempj; i>j; i--)
12263 {
12264 s[i] = s[i-1]; //shift the chain right
12265 }
12266 // put the chosen cell in the correct spot
12267 s[j]= temps;
12268 // updates the factorial
12269 factorial = factorial /(n-(j+1));
12270 }
12271#if 0
12272 for (size_t i = 0; i<n; i++)
12273 cout<<" "<<s[i];
12274 cout<<endl;
12275#endif
12276 return s;
12277}
12278
12280/* Translation
12281 Before:
12282 for (i = 0; i < 100; i++)
12283 for (j = 0; j < 100; j++)
12284 for (k = 0; k < 100; k++)
12285 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12286
12287 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12288
12289// added a new controlling loop at the outer most level
12290 int _lt_var_k;
12291 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12292 for (i = 0; i < 100; i++)
12293 for (j = 0; j < 100; j++)
12294 // rewritten loop header , normalized also
12295 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12296 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12297 }
12298 }
12299// finally run constant folding
12300
12301 */
12302bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12303{
12304 ROSE_ASSERT(loopNest != NULL);
12305 ROSE_ASSERT(targetLevel >0);
12306 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12307 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12308 // 1 (no need to tile)
12309 if (tileSize<=1)
12310 return true;
12311 // Locate the target loop at level n
12312 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12313 ROSE_ASSERT(loops.size()>=targetLevel);
12314 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12315
12316 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12317 // normalize the target loop first
12318 if (!forLoopNormalization(target_loop))
12319 {// the return value is not reliable
12320// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12321// dumpInfo(target_loop);
12322// return false;
12323 }
12324 // grab the target loop's essential header information
12325 SgInitializedName* ivar = NULL;
12326 SgExpression* lb = NULL;
12327 SgExpression* ub = NULL;
12328 SgExpression* step = NULL;
12329 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12330 {
12331 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12332 dumpInfo(target_loop);
12333 return false;
12334 }
12335 ROSE_ASSERT(ivar&& lb && ub && step);
12336
12337 // Add a controlling loop around the top loop nest
12338 // Ensure the parent can hold more than one children
12339 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12340 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12341 parent = makeSingleStatementBodyToBlock (loopNest);
12342 else
12343 parent = isSgLocatedNode(loopNest ->get_parent());
12344
12345 ROSE_ASSERT(parent!= NULL);
12346 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12347 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12348 SgScopeStatement* scope = loopNest->get_scope();
12350 (ivar2_name, buildIntType(),NULL, scope);
12351 insertStatementBefore(loopNest, loop_index_decl);
12352 // init statement of the loop header, copy the lower bound
12353 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12354 //two cases <= or >= for a normalized loop
12355 SgExprStatement* cond_stmt = NULL;
12356 SgExpression* orig_test = target_loop->get_test_expr();
12357 if (isSgBinaryOp(orig_test))
12358 {
12359 if (isSgLessOrEqualOp(orig_test))
12360 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12361 else if (isSgGreaterOrEqualOp(orig_test))
12362 {
12363 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12364 }
12365 else
12366 {
12367 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12368 dumpInfo(orig_test);
12369 ROSE_ABORT();
12370 }
12371 }
12372 else
12373 {
12374 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12375 dumpInfo(orig_test);
12376 ROSE_ABORT();
12377 }
12378 ROSE_ASSERT(cond_stmt != NULL);
12379
12380 // build loop incremental I
12381 // expression var+=up*tilesize or var-=upper * tilesize
12382 SgExpression* incr_exp = NULL;
12383 SgExpression* orig_incr_exp = target_loop->get_increment();
12384 if( isSgPlusAssignOp(orig_incr_exp))
12385 {
12386 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12387 }
12388 else if (isSgMinusAssignOp(orig_incr_exp))
12389 {
12390 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12391 }
12392 else
12393 {
12394 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12395 dumpInfo(orig_incr_exp);
12396 ROSE_ABORT();
12397 }
12398 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12399 insertStatementBefore(loopNest, control_loop);
12400 // move loopNest into the control loop
12401 removeStatement(loopNest);
12402 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12403
12404 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12405 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12406 ROSE_ASSERT(assign_op);
12407 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12408 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12409 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12410 ROSE_ASSERT(bin_op);
12411 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12412 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12413 test_exp->set_need_paren(true);
12414 ub->set_need_paren(true);
12415 ub2->set_need_paren(true);
12416 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12417 bin_op->set_rhs_operand(triple_exp);
12418 // constant folding
12419 // folding entire loop may decrease the accuracy of floating point calculation
12420 // we fold loop control expressions only
12421 //constantFolding(control_loop->get_scope());
12422 constantFolding(control_loop->get_test());
12423 constantFolding(control_loop->get_increment());
12424 return true;
12425}
12426
12428bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12429{
12430 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12431 return true;
12432 // parameter verification
12433 ROSE_ASSERT(loop != NULL);
12434 //must have at least two levels
12435 ROSE_ASSERT (depth >1);
12436 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12437 //TODO need to verify the input loop has n perfectly-nested children loops inside
12438 // save the loop nest's headers: init, test, and increment
12439 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12440 ROSE_ASSERT(loopNest.size()>=depth);
12441 std::vector<std::vector<SgNode*> > loopHeads;
12442 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12443 {
12444 SgForStatement* cur_loop = *i;
12445 std::vector<SgNode*> head;
12446 head.push_back(cur_loop->get_for_init_stmt());
12447 head.push_back(cur_loop->get_test());
12448 head.push_back(cur_loop->get_increment());
12449 loopHeads.push_back(head);
12450 }
12451
12452 // convert the lexicographical number to a permutation order array permutation[depth]
12453 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12454 // rewrite the loop nest to reflect the permutation
12455 // set the header to the new header based on the permutation array
12456 for (size_t i=0; i<depth; i++)
12457 {
12458 // only rewrite if necessary
12459 if (i != changedOrder[i])
12460 {
12461 SgForStatement* cur_loop = loopNest[i];
12462 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12463
12464 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12465 //ROSE_ASSERT(init != NULL) // could be NULL?
12466 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12467 cur_loop->set_for_init_stmt(init);
12468 if (init)
12469 {
12470 init->set_parent(cur_loop);
12472 }
12473
12474 SgStatement* test = isSgStatement(newhead[1]);
12475 cur_loop->set_test(test);
12476 if (test)
12477 {
12478 test->set_parent(cur_loop);
12480 }
12481
12482 SgExpression* incr = isSgExpression(newhead[2]);
12483 cur_loop->set_increment(incr);
12484 if (incr)
12485 {
12486 incr->set_parent(cur_loop);
12488 }
12489 }
12490 }
12491 return true;
12492}
12493
12496{
12497 ROSE_ASSERT(loop != NULL);
12498 SgInitializedName* ivarname=NULL;
12499
12500 // Fortran case ------------------
12501 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12502 {
12503 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12504 ROSE_ASSERT (assign_op != NULL);
12505 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12506 ROSE_ASSERT (var != NULL);
12507 ivarname = var->get_symbol()->get_declaration();
12508 ROSE_ASSERT (ivarname != NULL);
12509 return ivarname;
12510 }
12511 // C/C++ case ------------------------------
12512 SgForStatement* fs = isSgForStatement(loop);
12513 if (fs == NULL)
12514 {
12515 return NULL;
12516 }
12517 // we only handle C/C++ for loops and Fortran Do loops.
12518 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12519 // ROSE_ASSERT (fs != NULL);
12520
12521 //Check initialization statement is something like i=xx;
12522 SgStatementPtrList & init = fs->get_init_stmt();
12523 if (init.size() !=1)
12524 {
12525 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12526 //ROSE_ASSERT(false);
12527 return NULL;
12528 }
12529 SgStatement* init1 = init.front();
12530 SgExpression* ivarast=NULL;
12531
12532 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12533 //bool isCase1=false, isCase2=false;
12534
12535 //consider C99 style: for (int i=0;...)
12536 if (isSgVariableDeclaration(init1))
12537 {
12538 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12539 ivarname = decl->get_variables().front();
12540 ROSE_ASSERT(ivarname != NULL);
12541 //SgInitializer * initor = ivarname->get_initializer();
12542 // if (isSgAssignInitializer(initor))
12543 // isCase1 = true;
12544 }// other regular case: for (i=0;..)
12545 else if (isAssignmentStatement(init1, &ivarast))
12546 {
12547 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12548 if (var)
12549 {
12550 ivarname = var->get_symbol()->get_declaration();
12551 //isCase2 = true;
12552 }
12553 }
12554 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12555 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12556 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12557 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12558 {
12559 SgCommaOpExp* leaf_exp = comma_exp;
12560 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12561 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12562 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12563 {
12564 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12565 if (var)
12566 {
12567 ivarname = var->get_symbol()->get_declaration();
12568 }
12569 }
12570 }
12571 }
12572 else
12573 {
12574
12575 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12576 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12577 init1->get_file_info()->display("Debug");
12578
12579 return NULL;
12580 //ROSE_ASSERT (false);
12581 }
12582 // Cannot be both true
12583 // ROSE_ASSERT(!(isCase1&&isCase2));
12584
12585 //Check loop index's type
12586 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12587 return ivarname;
12588}
12589
12593{
12594 ROSE_ASSERT (ivar != NULL);
12595 ROSE_ASSERT (subtree_root != NULL);
12596 bool result = false;
12597 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12598 while (cur_loop)
12599 {
12600 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12601 if (i_index == ivar)
12602 {
12603 result = true;
12604 break;
12605 }
12606 else
12607 { // findEnclosingLoop() is inclusive.
12608 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12609 }
12610 }
12611 return result;
12612}
12613
12615
12620{
12621 ROSE_ASSERT (loop !=NULL);
12622 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12623 if (stmt_list.size() >1) return true; // two var decl statements
12624 if (stmt_list.size() == 0) return false;
12625
12626// generateDOTforMultipleFile(*getProject());
12627 //single variable declaration statement, like int i;
12628 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12629 if (decl_stmt != NULL)
12630 return false;
12631
12632 // single statement, but with comma expression (i=0, j=0)
12633 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12634 ROSE_ASSERT (exp_stmt != NULL);
12635 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12636 {
12637 return true;
12638 }
12639
12640 return false;
12641}
12643bool 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*/)
12644{
12645 ROSE_ASSERT(loop != NULL);
12646 SgFortranDo* fs = isSgFortranDo(loop);
12647 if (fs == NULL)
12648 return false;
12649 // 1. Check initialization statement is something like i=xx;
12650 SgExpression * init = fs->get_initialization();
12651 if (init == NULL)
12652 return false;
12653 SgAssignOp* init_assign = isSgAssignOp (init);
12654 SgExpression *lbast=NULL, *ubast=NULL;
12655 // SgExpression* ivarast=NULL, *stepast=NULL;
12656 SgInitializedName* ivarname=NULL;
12657
12658 bool isCase1=false;
12659 if (init_assign)
12660 {
12661 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12662 if (var)
12663 ivarname = var->get_symbol()->get_declaration();
12664 lbast = init_assign->get_rhs_operand();
12665 if (ivarname && lbast )
12666 isCase1 = true;
12667 }
12668 // if not i=1
12669 if (!isCase1)
12670 return false;
12671
12672 //Check loop index's type
12673 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12674 return false;
12675#if 0
12676 //2. Check test expression i [<=, >=, <, > ,!=] bound
12677 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12678 if (test == NULL)
12679 return false;
12680 switch (test->variantT()) {
12681 case V_SgLessOrEqualOp:
12682 if (isInclusiveUpperBound != NULL)
12683 *isInclusiveUpperBound = true;
12684 if (hasIncrementalIterationSpace != NULL)
12685 *hasIncrementalIterationSpace = true;
12686 break;
12687 case V_SgLessThanOp:
12688 if (isInclusiveUpperBound != NULL)
12689 *isInclusiveUpperBound = false;
12690 if (hasIncrementalIterationSpace != NULL)
12691 *hasIncrementalIterationSpace = true;
12692 break;
12693 case V_SgGreaterOrEqualOp:
12694 if (isInclusiveUpperBound != NULL)
12695 *isInclusiveUpperBound = true;
12696 if (hasIncrementalIterationSpace != NULL)
12697 *hasIncrementalIterationSpace = false;
12698 break;
12699 case V_SgGreaterThanOp:
12700 if (isInclusiveUpperBound != NULL)
12701 *isInclusiveUpperBound = false;
12702 if (hasIncrementalIterationSpace != NULL)
12703 *hasIncrementalIterationSpace = false;
12704 break;
12705// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12706 break;
12707 default:
12708 return false;
12709 }
12710 // check the tested variable is the same as the loop index
12711 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12712 if (testvar == NULL)
12713 return false;
12714 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12715 return false;
12716#endif
12717 //grab the upper bound
12718 ubast = loop->get_bound();
12719 // Fortran Do loops always have inclusive upper bound
12720 if (isInclusiveUpperBound != NULL)
12721 *isInclusiveUpperBound = true;
12722 //3. Check the increment expression
12723 SgExpression* incr = fs->get_increment();
12724 ROSE_ASSERT (incr != NULL);
12725 if (isSgNullExpression(incr))
12726 {
12727 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12728 ROSE_ASSERT (false);
12729 }
12730 if (hasIncrementalIterationSpace != NULL)
12731 {
12732 *hasIncrementalIterationSpace = true;
12733 // We can only tell a few cases
12734 if (SgIntVal* i_v = isSgIntVal(incr))
12735 {
12736 if (i_v->get_value()<0)
12737 *hasIncrementalIterationSpace = false;
12738 }
12739 }
12740#if 0
12741 SgVarRefExp* incr_var = NULL;
12742 switch (incr->variantT()) {
12743 case V_SgPlusAssignOp: //+=
12744 case V_SgMinusAssignOp://-=
12745 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12746 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12747 break;
12748 case V_SgPlusPlusOp: //++
12749 case V_SgMinusMinusOp: //--
12750 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12751 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12752 break;
12753 default:
12754 return false;
12755 }
12756 if (incr_var == NULL)
12757 return false;
12758 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12759 return false;
12760#endif
12761 // return loop information if requested
12762 if (ivar != NULL)
12763 *ivar = ivarname;
12764 if (lb != NULL)
12765 *lb = lbast;
12766 if (ub != NULL)
12767 *ub = ubast;
12768 if (step != NULL)
12769 *step = incr;
12770 if (body != NULL) {
12771 *body = fs->get_body();
12772 }
12773 return true;
12774}
12775//TODO: expose it to the namespace once it matures.
12777// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12778/*
12779From OpenMP 4.5 Specification
12780
127811.2.2 OpenMP Language Terminology
12782
12783For C/C++, an executable statement, possibly compound, with a single entry at the
12784top and a single exit at the bottom, or an OpenMP construct.
12785
12786For Fortran, a block of executable statements with a single entry at the top and a
12787single exit at the bottom, or an OpenMP construct.
12788
12789COMMENTS:
12790
12791For all base languages:
12792* Access to the structured block must not be the result of a branch; and
12793* The point of exit cannot be a branch out of the structured block.
12794
12795 For C/C++:
12796* The point of entry must not be a call to setjmp();
12797* longjmp() and throw() must not violate the entry/exit criteria;
12798* Calls to exit() are allowed in a structured block; and
12799* 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.
12800
12801For Fortran:
12802* STOP statements are allowed in a structured block.
12803
12804*/
12805bool isStructuredBlock(SgStatement* s)
12806{
12807 bool rt = true;
12808 ROSE_ASSERT (s != NULL);
12809
12810 // contain break;
12811 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12812 if (bset.size()!=0 )
12813 rt = false;
12814 //TODO: contain goto statement, jumping to outside targets
12815 // longjump(), throw(),
12816 // calls to exit() are allowed.
12817
12818 return rt;
12819
12820}
12821
12823//TODO check the loop index is not being written in the loop body
12824bool 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*/)
12825{
12826 ROSE_ASSERT(loop != NULL);
12827 SgForStatement* fs = isSgForStatement(loop);
12828 //SgFortranDo* fs2 = isSgFortranDo(loop);
12829 if (fs == NULL)
12830 {
12831 // if (fs2)
12832 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
12833 // else
12834 return false;
12835 }
12836 // 1. Check initialization statement is something like i=xx;
12837 SgStatementPtrList & init = fs->get_init_stmt();
12838 if (init.size() !=1)
12839 return false;
12840 SgStatement* init1 = init.front();
12841 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
12842 SgInitializedName* ivarname=NULL;
12843
12844 bool isCase1=false, isCase2=false;
12845 //consider C99 style: for (int i=0;...)
12846 if (isSgVariableDeclaration(init1))
12847 {
12848 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12849 ivarname = decl->get_variables().front();
12850 ROSE_ASSERT(ivarname != NULL);
12851 SgInitializer * initor = ivarname->get_initializer();
12852 if (isSgAssignInitializer(initor))
12853 {
12854 lbast = isSgAssignInitializer(initor)->get_operand();
12855 isCase1 = true;
12856 }
12857 }// other regular case: for (i=0;..)
12858 else if (isAssignmentStatement(init1, &ivarast, &lbast))
12859 {
12860 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12861 if (var)
12862 {
12863 ivarname = var->get_symbol()->get_declaration();
12864 isCase2 = true;
12865 }
12866 }
12867 // Cannot be both true
12868 ROSE_ASSERT(!(isCase1&&isCase2));
12869 // if not either case is true
12870 if (!(isCase1||isCase2))
12871 return false;
12872
12873 //Check loop index's type
12874 if (!isStrictIntegerType(ivarname->get_type()))
12875 return false;
12876
12877 //2. Check test expression i [<=, >=, <, > ,!=] bound
12878 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12879 if (test == NULL)
12880 return false;
12881 switch (test->variantT()) {
12882 case V_SgLessOrEqualOp:
12883 if (isInclusiveUpperBound != NULL)
12884 *isInclusiveUpperBound = true;
12885 if (hasIncrementalIterationSpace != NULL)
12886 *hasIncrementalIterationSpace = true;
12887 break;
12888 case V_SgLessThanOp:
12889 if (isInclusiveUpperBound != NULL)
12890 *isInclusiveUpperBound = false;
12891 if (hasIncrementalIterationSpace != NULL)
12892 *hasIncrementalIterationSpace = true;
12893 break;
12894 case V_SgGreaterOrEqualOp:
12895 if (isInclusiveUpperBound != NULL)
12896 *isInclusiveUpperBound = true;
12897 if (hasIncrementalIterationSpace != NULL)
12898 *hasIncrementalIterationSpace = false;
12899 break;
12900 case V_SgGreaterThanOp:
12901 if (isInclusiveUpperBound != NULL)
12902 *isInclusiveUpperBound = false;
12903 if (hasIncrementalIterationSpace != NULL)
12904 *hasIncrementalIterationSpace = false;
12905 break;
12906// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12907 break;
12908 default:
12909 return false;
12910 }
12911 // check the tested variable is the same as the loop index
12912 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12913 if (testvar == NULL)
12914 return false;
12915 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12916 return false;
12917 //grab the upper bound
12918 ubast = test->get_rhs_operand();
12919
12920 //3. Check the increment expression
12921 /* Allowed forms
12922 ++var
12923 var++
12924 --var
12925 var--
12926
12927 var += incr
12928 var -= incr
12929
12930 var = var + incr
12931 var = incr + var
12932 var = var - incr
12933 */
12934 SgExpression* incr = fs->get_increment();
12935 SgVarRefExp* incr_var = NULL;
12936 switch (incr->variantT()) {
12937 case V_SgPlusAssignOp: //+=
12938 case V_SgMinusAssignOp://-=
12939 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12940 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12941 break;
12942 case V_SgPlusPlusOp: //++
12943 case V_SgMinusMinusOp: //--
12944 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12945 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12946 break;
12947 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
12948 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12949 if(incr_var == NULL)
12950 return false;
12951 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12952 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
12953 SgBinaryOp* arithOp=0;
12954 if(addOp)
12955 arithOp=addOp;
12956 else if(subtractOp)
12957 arithOp=subtractOp;
12958 else
12959 return false;
12960 ROSE_ASSERT(arithOp!=0);
12961 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
12962 // cases : var + incr, var - incr
12963 incr_var=varRefExp;
12964 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
12965 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
12966 if(isSgAddOp(arithOp)) {
12967 // case : incr + var (not allowed: incr-var)
12968 incr_var=varRefExp;
12969 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
12970 }
12971 }
12972 break;
12973 } // end of V_AssignOp
12974 default:
12975 return false;
12976 }
12977
12978 if (incr_var == NULL)
12979 return false;
12980 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12981 return false;
12982
12983
12984 // single entry and single exit?
12985 // only for C for loop for now
12986 // TODO: Fortran support later
12987 if (fs && !isStructuredBlock(fs->get_loop_body()) )
12988 return false;
12989
12990 // return loop information if requested
12991 if (ivar != NULL)
12992 *ivar = ivarname;
12993 if (lb != NULL)
12994 *lb = lbast;
12995 if (ub != NULL)
12996 *ub = ubast;
12997 if (step != NULL)
12998 *step = stepast;
12999 if (body != NULL) {
13000 *body = fs->get_loop_body();
13001 }
13002 return true;
13003}
13004
13007{
13008 ROSE_ASSERT(loop != NULL);
13009 ROSE_ASSERT(lb != NULL);
13010 SgForStatement* forstmt = isSgForStatement(loop);
13011 SgFortranDo* dostmt = isSgFortranDo(loop);
13012 // ROSE_ASSERT(forstmt!= NULL);
13013
13014 if (forstmt != NULL)
13015 {
13016 // two cases: init_stmt is
13017 // SgExprStatement (assignment) like i=0;
13018 // SgVariableDeclaration int i =0 or
13019 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13020 if (testList.size()>0) // assignment statement
13021 {
13022 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13023 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13024 ROSE_ASSERT(assignop);
13025 if( assignop->get_rhs_operand()->get_lvalue())
13026 lb->set_lvalue(true);
13027 assignop->set_rhs_operand(lb);
13028 lb->set_parent(assignop);
13029 //TODO what happens to the original rhs operand?
13030 }
13031 else // variable declaration case
13032 {
13033 // SgVariableDeclaration
13034 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13035 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13036 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13037 ROSE_ASSERT(init != NULL);
13038 init->set_operand(lb);
13039 lb->set_parent(init);
13040 //TODO what happens to the original rhs operand?
13041 }
13042 }
13043 else if (dostmt != NULL)
13044 {
13045 SgExpression* init = dostmt->get_initialization();
13046 ROSE_ASSERT (init != NULL);
13047 SgAssignOp * a_op = isSgAssignOp (init);
13048 ROSE_ASSERT (a_op!=NULL);
13049 a_op->set_rhs_operand(lb);
13050 lb->set_parent(a_op);
13051 //TODO delete the previous operand?
13052 }
13053 else
13054 {
13055 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13056 ROSE_ASSERT (false);
13057 }
13058}
13059
13062{
13063 ROSE_ASSERT(loop != NULL);
13064 ROSE_ASSERT(ub != NULL);
13065 SgForStatement* forstmt = isSgForStatement(loop);
13066 // ROSE_ASSERT(forstmt!= NULL);
13067 SgFortranDo* dostmt = isSgFortranDo(loop);
13068 if (forstmt != NULL)
13069 {
13070 // set upper bound expression
13071 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13072 ROSE_ASSERT(binop != NULL);
13073 binop->set_rhs_operand(ub);
13074 ub->set_parent(binop);
13075 }
13076 else if (dostmt != NULL)
13077 {
13078 dostmt->set_bound(ub);
13079 ub->set_parent(dostmt);
13080 //TODO delete the original bound expression
13081 }
13082 else
13083 {
13084 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13085 ROSE_ASSERT (false);
13086 }
13087
13088}
13089
13092{
13093 ROSE_ASSERT(loop != NULL);
13094 ROSE_ASSERT(stride != NULL);
13095 SgForStatement* forstmt = isSgForStatement(loop);
13096 SgFortranDo * dostmt = isSgFortranDo (loop);
13097 // ROSE_ASSERT(forstmt!= NULL);
13098 if (dostmt != NULL)
13099 {
13100 dostmt->set_increment(stride);
13101 stride->set_parent(dostmt);
13102 //TODO delete original increment expression
13103 }
13104 else if (forstmt != NULL)
13105 {
13106 // set stride expression
13107 // case 1: i++ change to i+=stride
13108 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13109 if (testList.size()>0)
13110 {
13111 ROSE_ASSERT(testList.size() == 1); // should have only one
13112 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13113 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13114 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13115 forstmt->set_increment(plusassignop);
13116 }
13117
13118 // case 1.5: i-- also changed to i+=stride
13119 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13120 if (testList.size()>0)
13121 {
13122 ROSE_ASSERT(testList.size()==1);// should have only one
13123 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13124 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13125 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13126 forstmt->set_increment(plusassignop);
13127 }
13128
13129 // case 2: i+=X
13130 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13131 if (testList.size()>0)
13132 {
13133 ROSE_ASSERT(testList.size()==1);// should have only one
13134 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13135 ROSE_ASSERT(assignop!=NULL);
13136 assignop->set_rhs_operand(stride);
13137 }
13138
13139 // case 2.5: i-=X changed to i+=stride
13140 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13141 if (testList.size()>0)
13142 {
13143 ROSE_ASSERT(testList.size()==1);// should have only one
13144 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13145 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13146 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13147 ROSE_ASSERT(exprstmt !=NULL);
13148 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13149 exprstmt->set_expression(plusassignop);
13150 }
13151
13152#if 0 // [Robb Matzke 2021-03-17]
13153 // DQ (1/3/2007): I think this is a meaningless statement.
13154 testList.empty();
13155#endif
13156 // case 3: i=i + X or i =X +i i
13157 // TODO; what if users use i*=,etc ??
13158 // send out a warning: not canonical FOR/DO loop
13159 // or do this in the real frontend. MUST conform to canonical form
13160 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13161 if (testList.size()>0)
13162 {
13163 ROSE_ASSERT(testList.size()==1);// should have only one ??
13164 // consider only the top first one
13165 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13166 ROSE_ASSERT(addop!=NULL);
13167 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13168 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13169 {
13170 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13171 addop->set_lhs_operand(stride);
13172 else
13173 addop->set_rhs_operand(stride);
13174 }
13175 else
13176 addop->set_rhs_operand(stride);
13177 }
13178
13179 // case 3.5: i=i - X
13180 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13181 if (testList.size()>0)
13182 {
13183 ROSE_ASSERT(testList.size()==1);// should have only one ??
13184 // consider only the top first one
13185 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13186 ROSE_ASSERT(subtractop!=NULL);
13187 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13188 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13189 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13190 ROSE_ASSERT(assignop !=NULL);
13191 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13192 assignop->set_rhs_operand(plusassignop);
13193 }
13194 }
13195 else
13196 {
13197 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13198 ROSE_ASSERT (false);
13199
13200 }
13201}
13202
13206bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13207{
13208 SgExprStatement *n = isSgExprStatement(s);
13209 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13210 if (exp != 0) {
13211 switch (exp->variantT()) {
13212 case V_SgPlusAssignOp:
13213 case V_SgMinusAssignOp:
13214 case V_SgAndAssignOp:
13215 case V_SgIorAssignOp:
13216 case V_SgMultAssignOp:
13217 case V_SgDivAssignOp:
13218 case V_SgModAssignOp:
13219 case V_SgXorAssignOp:
13220 case V_SgAssignOp:
13221 {
13222 SgBinaryOp* s2 = isSgBinaryOp(exp);
13223 if (lhs != 0)
13224 *lhs = s2->get_lhs_operand();
13225 if (rhs != 0) {
13226 SgExpression* init = s2->get_rhs_operand();
13227 if ( init->variantT() == V_SgAssignInitializer)
13228 init = isSgAssignInitializer(init)->get_operand();
13229 *rhs = init;
13230 }
13231 if (readlhs != 0)
13232 *readlhs = (exp->variantT() != V_SgAssignOp);
13233 return true;
13234 }
13235 default:
13236 return false;
13237 }
13238 }
13239 return false;
13240}
13241
13242
13243void
13245 {
13246 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13247 for (size_t i = 0; i < gotos.size(); ++i)
13248 {
13249 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13250 SgLabelStatement* ls = gs->get_label();
13251 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13252 if (!lsParent) continue;
13253 SgStatementPtrList& bbStatements = lsParent->get_statements();
13254
13255 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13256
13257 ROSE_ASSERT (j != bbStatements.size());
13258
13259 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13260 {
13261 ++j;
13262 }
13263 gs->set_label(isSgLabelStatement(bbStatements[j]));
13264 }
13265 }
13266
13267bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13268{
13269 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13270}
13272
13276bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13277{
13278 bool rt= true;
13279 ROSE_ASSERT(decl != NULL);
13280 ROSE_ASSERT(assign_stmt != NULL);
13281
13282 // Sanity check of assign statement: must be a form of var = xxx;
13283 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13284 if (assign_op == NULL)
13285 return false;
13286 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13287 if (assign_op_var == NULL) return false;
13288
13289 // Sanity check of the variable declaration: it should not have an existing initializer
13291 if (decl_var->get_initptr()!= NULL ) return false;
13292
13293 // check if two variables match
13294 // In translation, it is possible the declaration has not yet been inserted into its scope.
13295 // finding its symbol can return NULL.
13296 // But we still want to do the merge.
13297 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13298 if (decl_var_symbol!=NULL)
13299 {
13300 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13301 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13302 }
13303 else
13304 { // fallback to comparing variable names instead
13305 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13306 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13307 }
13308
13309 // Everything looks fine now. Do the merge.
13311
13312 // Must preserve the proprecessing information of the original assign_stmt
13313 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13314 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13315
13316 // removeStatement() does not support removing a statement which is not inside a container.
13317 // But sometimes we do need to remove such a statement and replace it with a new one.
13318 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13319 // TODO: improve removeStatement() which uses low level rewritting.
13320 if (removeAssignStmt)
13321 SageInterface::removeStatement (assign_stmt);
13322// SageInterface::deepDelete (assign_stmt);
13324 decl_var->set_initptr(initor);
13325 initor->set_parent(decl_var);
13326
13327 return rt;
13328}
13329
13331{
13332 bool rt= true;
13333
13334 // Sanity check of assign statement: must be a form of var = xxx;
13335 ROSE_ASSERT(assign_stmt != NULL);
13336 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13337 if (assign_op == NULL)
13338 return false;
13339 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13340 if (assign_op_var == NULL)
13341 return false;
13342
13343 // Sanity check of the variable declaration: it should not have an existing initializer
13344 ROSE_ASSERT(decl != NULL);
13346 if (decl_var->get_initptr()!= NULL)
13347 return false;
13348
13349 // check if two variables match
13350 // In translation, it is possible the declaration has not yet been inserted into its scope.
13351 // finding its symbol can return NULL.
13352 // But we still want to do the merge.
13353 ROSE_ASSERT(decl_var != NULL);
13354 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13355 if (decl_var_symbol != NULL) {
13356 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13357 if (assign_op_var->get_symbol() != decl_var_symbol)
13358 return false;
13359 }
13360 else
13361 { // fallback to comparing variable names instead
13362 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13363 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13364 return false;
13365 }
13366
13367 // Everything looks fine now. Do the merge.
13368 // It is implemented by
13369 // 1. copy rhs to the decl's rhs,
13370 // 2. then move the decl to the place of the assignment,
13371 // 3. then remove the assignment
13372 //
13373 // Copy rhs to be initializer
13376 decl_var->set_initptr(initor);
13377 initor->set_parent(decl_var);
13378
13379 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13380 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13381 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13382
13383 // removeStatement() does not support removing a statement which is not inside a container.
13384 // But sometimes we do need to remove such a statement and replace it with a new one.
13385 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13386 // TODO: improve removeStatement() which uses low level rewritting.
13387
13388 // Now move the declaration to a new position, right before the assignment statement
13390 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13391
13392 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13393 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13394
13395 // Original assignment statement should be removed
13396 SageInterface::removeStatement (assign_stmt);
13397 // SageInterface::deepDelete (decl);
13398
13399 return rt;
13400}
13401// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13402// Return the generated assignment statement, if any
13404{
13405 SgExprStatement* rt = NULL;
13406 ROSE_ASSERT (decl != NULL);
13407
13409 SgInitializer* initor = decl_var ->get_initptr();
13410 if (initor == NULL)
13411 rt = NULL;
13412 else
13413 {
13414 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13415 SgExpression * rhs=NULL;
13416 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13417 rhs = ainitor->get_operand();
13418 else
13419 rhs = initor;
13420
13421 // we deep copy the rhs operand
13422 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13423 decl_var->set_initptr(NULL);
13424 //TODO clean up initor
13425 insertStatementAfter ( decl, rt );
13426 }
13427 return rt;
13428}
13430ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13431{
13432 int count = 0;
13433 if (!topLevelOnly)
13434 {
13435 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13436 ROSE_ASSERT (false);
13437 }
13438
13439 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13440 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13441 {
13442 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13443 if (topLevelOnly)
13444 {
13445 ROSE_ASSERT(decl != NULL);
13446 if (decl->get_scope() == scope)
13447 {
13449 count ++;
13450 }
13451 }
13452 }
13453 return count;
13454}
13455
13456void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13457{
13458 ROSE_ASSERT (root != NULL);
13459// std::vector<SgVarRefExp* > result;
13460
13461 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13462 // AST query won't find variables used in types
13464
13465 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13466 {
13467 SgVarRefExp *vRef = isSgVarRefExp(*i);
13468 ROSE_ASSERT (vRef != NULL);
13469 result.push_back(vRef);
13470 }
13471}
13472
13473int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13474{
13475 int rt = 0;
13476 ROSE_ASSERT (root != NULL);
13477 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13478 for (size_t i =0; i< constructorList.size(); i++)
13479 {
13480 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13481 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13482 {
13483 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13484 for (size_t j =0 ; j< varList.size(); j++)
13485 {
13486 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13487 currentVarRefList.push_back(var_exp);
13488//TODO: these variable references do have special scopes, how to communicate to users?
13489// specialVarRefScopeExp[var_exp] = c_init ;
13490 rt ++;
13491 }
13492 }
13493 }
13494 return rt;
13495}
13496
13497namespace SageInterface { // A few internal helper classes
13498
13500 {
13501 SgAndOp* op;
13502
13503 public:
13504 AndOpGenerator(SgAndOp* op): op(op) {}
13505
13506 virtual SgStatement* generate(SgExpression* lhs)
13507 {
13508 if (lhs==NULL)
13509 return NULL;
13510 SgTreeCopy treeCopy;
13511 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13512 ROSE_ASSERT (lhsCopy);
13513 SgIfStmt* tree =
13520 return tree;
13521 }
13522 };
13523
13525 {
13526 SgOrOp* op;
13527
13528 public:
13529 OrOpGenerator(SgOrOp* op): op(op) {}
13530
13531 virtual SgStatement* generate(SgExpression* lhs)
13532 {
13533 if (lhs==NULL)
13534 return NULL;
13535 SgTreeCopy treeCopy;
13536 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13537 ROSE_ASSERT (lhsCopy);
13538 SgIfStmt* tree =
13545 return tree;
13546 }
13547 };
13548
13550 {
13551 SgConditionalExp* op;
13552
13553 public:
13555
13556 virtual SgStatement* generate(SgExpression* lhs)
13557 {
13558 if (lhs==NULL)
13559 return NULL;
13560 SgTreeCopy treeCopy;
13561 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13562 ROSE_ASSERT (lhsCopy);
13563 SgIfStmt* tree =
13570 return tree;
13571 }
13572 };
13573
13574} // end of namespace for the helper classes
13575
13578{
13579 ROSE_ASSERT(from != NULL);
13580
13581#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13582#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13584 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13585 ROSE_ASSERT (false);
13586 }
13587
13588 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13589#endif
13590 SgStatement* stmt = getStatementOfExpression(from);
13591 assert (stmt);
13592 if (!isSgForInitStatement(stmt->get_parent())) {
13593 //SageInterface::ensureBasicBlockAsParent(stmt);
13594 // no return value is accepted. Only the optional transformation matters
13595 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13597 }
13598
13599 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13600 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13601 if (!parent && isSgForInitStatement(stmt->get_parent()))
13602 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13603 assert (parent);
13604 // cout << "parent is a " << parent->sage_class_name() << endl;
13605 // cout << "parent is " << parent->unparseToString() << endl;
13606 // cout << "stmt is " << stmt->unparseToString() << endl;
13607 SgName varname = "rose_temp__";
13608 if (newName == "") {
13609 varname << ++SageInterface::gensym_counter;
13610 } else {
13611 varname = newName;
13612 }
13613
13614 SgType* vartype = from->get_type();
13615 SgNode* fromparent = from->get_parent();
13616 vector<SgExpression*> ancestors;
13617 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13618 expr = anc, anc = isSgExpression(anc->get_parent()))
13619 {
13620 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13621 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13622 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13623 ancestors.push_back(anc); // Closest first
13624 }
13625 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13626 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13627 {
13628 StatementGenerator* gen;
13629 switch ((*ai)->variantT()) {
13630 case V_SgAndOp:
13631 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13632 case V_SgOrOp:
13633 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13634 case V_SgConditionalExp:
13635 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13636 default: assert (!"Should not happen"); abort();
13637 }
13639 delete gen;
13640 } // for
13641 if (ancestors.size() != 0) {
13642 return splitExpression(from);
13643 // Need to recompute everything if there were ancestors
13644 }
13645 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13647 ROSE_ASSERT (sym);
13648 SgInitializedName* initname = sym->get_declaration();
13649 ROSE_ASSERT (initname);
13651 replaceExpressionWithExpression(from, varref);
13652 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13653 // cout << "From is a " << from->sage_class_name() << endl;
13655 initname->set_initializer(ai);
13656 ai->set_parent(initname);
13657 myStatementInsert(stmt, vardecl, true);
13658 // vardecl->set_parent(stmt->get_parent());
13659 // FixSgTree(vardecl);
13660 // FixSgTree(parent);
13661 return ai;
13662
13663#else
13664 return NULL;
13665#endif
13666
13667} //splitExpression()
13668
13671 struct SplitStatementGenerator: public StatementGenerator {
13672 SgExpression* expr;
13673 virtual SgStatement* generate(SgExpression* answer) {
13674 using namespace SageBuilder;
13675 return buildBasicBlock(buildAssignStatement(answer, expr));
13676 }
13677 };
13678 SplitStatementGenerator gen;
13679 gen.expr = expr;
13681 }
13682
13684 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13685 V_SgGotoStatement);
13686 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13687 (size_t i = 0; i < gotos.size(); ++i) {
13688 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13689 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13690 if (!gsParent) continue;
13691 SgStatementPtrList& bbStatements = gsParent->get_statements();
13692 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13693 - bbStatements.begin();
13694 ROSE_ASSERT (j != bbStatements.size());
13695 if (j == 0) continue;
13696 if (isSgLabelStatement(bbStatements[j - 1])) {
13697 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13698 gs->get_label();
13699 }
13700 }
13701 for (size_t i = 0; i < gotos.size(); ++i) {
13702 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13703 SgLabelStatement* oldLabel = gs->get_label();
13704 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13705 oldLabel = labelsToReplace[oldLabel];
13706 }
13707 gs->set_label(oldLabel);
13708 }
13709 }
13710
13712 switch (e->variantT()) {
13713#ifdef _MSC_VER
13714 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13715 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13716#else
13717 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13718#endif
13719 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13720 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13721 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13722 case V_SgAddressOfOp: return true;
13723 default: return false;
13724 }
13725 }
13726
13728 switch (e->variantT()) {
13729 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13730 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13731 case V_SgCastExp: return
13732 isConstantFalse(isSgCastExp(e)->get_operand());
13733 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13734 default: return false;
13735 }
13736 }
13737
13739 SgExpression* e) {
13740 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13741 if (!fc) return false;
13742 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13743 if (fr == NULL) return false;
13744 return fr->get_symbol()->get_declaration() == decl;
13745 }
13746
13747 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13748 arity, SgExpression* e) {
13749 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13750 if (!fc) return false;
13751 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13752 if (fr == NULL) return false;
13753 string name =
13754 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13755 return (name == qualifiedName &&
13756 fc->get_args()->get_expressions().size() == arity);
13757 }
13758
13760 {
13761 ROSE_ASSERT( e != NULL);
13762 // We enforce that the source expression is fully attached to the AST
13763 // Too strict, the source expression can be just built and not attached.
13764 // Liao, 9/21/2009
13765// ROSE_ASSERT( e->get_parent() != NULL);
13766 return deepCopy(e);
13767 }
13768
13770 {
13771 return deepCopy(s);
13772 }
13773
13774 //----------------- add into AST tree --------------------
13776 {
13777 ROSE_ASSERT(expList);
13778 ROSE_ASSERT(exp);
13779 expList->append_expression(exp);
13780 exp->set_parent(expList);
13781 }
13782
13783 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13784 {
13785 for (size_t i = 0; i < exp.size(); ++i)
13786 appendExpression(expList, exp[i]);
13787 }
13788
13789# if 0
13790 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13791
13792 // TODO consider the difference between C++ and Fortran
13793 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13794template <class actualFunction>
13795void
13796// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13797SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13798 {
13799 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13800 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13801 // function derived classes).
13802
13803 ROSE_ASSERT(func);
13804 ROSE_ASSERT(paralist);
13805
13806 // Warn to users if a paralist is being shared
13807 if (paralist->get_parent() !=NULL)
13808 {
13809 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13810 << (func->get_name()).getString()<<endl
13811 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13812 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13813 // ROSE_ASSERT(false);
13814 }
13815
13816 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13817 if (func->get_parameterList() != NULL)
13818 if (func->get_parameterList() != paralist)
13819 delete func->get_parameterList();
13820
13821 func->set_parameterList(paralist);
13822 paralist->set_parent(func);
13823 }
13824#endif
13825
13826// static
13827SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
13828 {
13829 ROSE_ASSERT(paraList != NULL);
13830 ROSE_ASSERT(initName != NULL);
13831
13832 if (isPrepend == true)
13833 paraList->prepend_arg(initName);
13834 else
13835 paraList->append_arg(initName);
13836
13837 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
13838 // initName->set_parent(paraList);
13839 if (initName->get_parent() == NULL)
13840 initName->set_parent(paraList);
13841
13842 ROSE_ASSERT(initName->get_parent() == paraList);
13843
13844 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
13845
13846 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
13847 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
13848 // ROSE_ASSERT(paraList->get_parent() != NULL);
13849 // ROSE_ASSERT(func_decl != NULL);
13850
13851 SgScopeStatement* scope = NULL;
13852 if (func_decl != NULL)
13853 {
13854 if ((func_decl->get_definingDeclaration()) == func_decl )
13855 {
13856 // defining function declaration, set scope and symbol table
13857 SgFunctionDefinition* func_def = func_decl->get_definition();
13858 ROSE_ASSERT(func_def);
13859 scope = func_def;
13860 }
13861 else
13862 {
13863 // nondefining declaration, set scope only, currently set to decl's scope, TODO
13864 scope = func_decl->get_scope();
13865 }
13866
13867 // fix up declptr of the init name
13868 initName->set_declptr(func_decl);
13869 }
13870
13871 // 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
13872 // that initName already has a scope.
13873 //
13874 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
13875 // ROSE_ASSERT(initName->get_scope() != NULL);
13876 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
13877
13878 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
13879
13880 initName->set_scope(scope);
13881 if (scope != NULL)
13882 {
13883 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
13884 if (sym == NULL)
13885 {
13886 sym = new SgVariableSymbol(initName);
13887 scope->insert_symbol(initName->get_name(), sym);
13888 sym->set_parent(scope->get_symbol_table());
13889 }
13890 return sym;
13891 }
13892 else
13893 {
13894 return NULL;
13895 }
13896 }
13897
13899{
13900 return addArg(paraList,initName,false);
13901}
13902
13904{
13905 return addArg(paraList,initName,true);
13906}
13907
13909{
13910 ROSE_ASSERT(decl);
13911 ROSE_ASSERT(pragma);
13912 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
13913 decl->set_pragma(pragma);
13914 pragma->set_parent(decl);
13915}
13916
13917
13919//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
13920//It might be well legal to append the first and only statement in a scope!
13922 {
13923 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
13924 void testAstForUniqueNodes ( SgNode* node );
13925
13926#if 0
13927 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
13928#endif
13929
13930 // DQ (6/19/2012): Exit as a test...
13931 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
13932
13933 if (scope == NULL)
13934 {
13935#if 0
13936 printf (" --- scope was not specified as input! \n");
13937#endif
13939 }
13940
13941 ROSE_ASSERT(stmt != NULL);
13942 ROSE_ASSERT(scope != NULL);
13943
13944#if 0
13945 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
13946#endif
13947
13948#if 0
13949 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
13950 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
13951 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
13952 if (declarationStatement != NULL)
13953 {
13954 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
13955 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
13956 }
13957#endif
13958
13959#if 0
13960 // This fix breaks other transformations.
13961 // It is better to do this explicitly as needed before calling appendStatement();
13962 // Liao 10/19/2010
13963 // In rare cases, we are moving the statement from its original scope to another scope
13964 // We have to remove it from its original scope before append it to the new scope
13965 SgNode* old_parent= stmt->get_parent();
13966 if (old_parent)
13967 {
13968 removeStatement(stmt);
13969 }
13970#endif
13971
13972#if 0
13973 // catch-all for statement fixup
13974 // Must fix it before insert it into the scope,
13975 fixStatement(stmt,scope);
13976
13977 //-----------------------
13978 // append the statement finally
13979 // scope->append_statement (stmt);
13980 scope->insertStatementInScope(stmt,false);
13981 stmt->set_parent(scope); // needed?
13982#else
13983 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
13984 bool skipAddingStatement = false;
13985 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
13986 if (classDeclaration != NULL)
13987 {
13988 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
13989#if 0
13990 if (classDeclaration->get_parent() != NULL)
13991 {
13992 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());
13993 }
13994#endif
13995
13996#if 1
13997 // DQ (6/9/2013): This is the original code...
13998 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
13999#else
14000 // 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).
14001 // This fails to add enough statements to the AST.
14002 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
14003#endif
14004
14005 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
14006 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
14007 // twice as a result of a template argument being instantiated and we only want to add it into
14008 // the scope once. This happens for test2013_198.C and I can't find a better solution.
14009 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
14010 {
14011 // Check if this instnatiated template has already been added to the scope.
14012
14013 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
14014 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
14015 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
14016 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
14017 if (statementAlreadyExistsInScope == true)
14018 {
14019 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14020 {
14021// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14022// #if 1
14023#if PRINT_DEVELOPER_WARNINGS
14024 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",
14025 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14026#endif
14027 }
14028#if 1
14029 else
14030 {
14031#if 1
14032 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",
14033 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14034#endif
14035 }
14036#endif
14037 skipAddingStatement = true;
14038 }
14039 }
14040 }
14041 else
14042 {
14043 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14044 if (enumDeclaration != NULL)
14045 {
14046 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14047 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14048 }
14049 }
14050
14051#if 0
14052 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14053 // that would be inserted into the current scope. This is however a bit expensive so we are using
14054 // this as a way to also debug the new cases where this happens.
14055 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14056 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14057 {
14058#if 0
14059 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",
14060 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14061#endif
14062#if 0
14063 printf ("Exiting as a test! \n");
14064 ROSE_ABORT();
14065#endif
14066 skipAddingStatement = true;
14067 }
14068#endif
14069
14070#if 0
14071 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14072#endif
14073
14074 if (skipAddingStatement == false)
14075 {
14076 // catch-all for statement fixup
14077 // Must fix it before insert it into the scope,
14078 // printf ("In appendStatementList(): Calling fixStatement() \n");
14079 fixStatement(stmt,scope);
14080 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14081
14082 //-----------------------
14083 // append the statement finally
14084 // scope->append_statement (stmt);
14085#if 0
14086 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14087#endif
14088 scope->insertStatementInScope(stmt,false);
14089
14090 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14091 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14092 // other declarations (e.g. "typedef struct { int x; } y;").
14093 stmt->set_parent(scope); // needed?
14094 }
14095#endif
14096
14097 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14098 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14099 // this). Also since this is only operating within a single scope it is likely too specific to C
14100 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14101 // use name qualification).
14102 // update the links after insertion!
14104 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14105 {
14106 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14107 }
14108
14109#if 0
14110 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14111 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14112 // statement in a single scope.
14113 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14114 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14115 testAstForUniqueNodes(scope);
14116#else
14117 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14118#endif
14119 }
14120
14123{
14124 ROSE_ASSERT (stmt != NULL);
14125 ROSE_ASSERT (for_init_stmt != NULL);
14126
14127#if 0
14128 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());
14129#endif
14130
14131 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14132 // to record it being moved (and thus the macroExpansions that it might be associated with having
14133 // to force the macroExpansion's associated statements to be marked as a transformation.
14135
14136#if 0
14137 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());
14138#endif
14139
14140 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14141 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14142 // prepend, we only need to look at the scope.
14144
14145 for_init_stmt->append_init_stmt (stmt);
14146}
14147
14148void
14149SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14150 {
14151 for (size_t i = 0; i < stmts.size(); ++i)
14152 {
14153#if 0
14154#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14155 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14156 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14157#endif
14158#endif
14159 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14160#if 0
14161 if (stmts[i]->get_parent() != NULL)
14162 {
14163#if 0
14164#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14165 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());
14166#endif
14167#endif
14168 appendStatement(stmts[i], scope);
14169 }
14170 else
14171 {
14172 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14173 }
14174#endif
14175 }
14176 }
14177
14180 {
14181 ROSE_ASSERT (stmt != NULL);
14182
14183#if 0
14184 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14185#endif
14186
14187 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14188
14189 if (scope == NULL)
14190 {
14192 }
14193
14194 ROSE_ASSERT(scope != NULL);
14195 // TODO handle side effect like SageBuilder::appendStatement() does
14196
14197 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14198
14199 // Must fix it before insert it into the scope,
14200 // otherwise assertions in insertStatementInScope() would fail
14201 fixStatement(stmt,scope);
14202
14203#if 0
14204 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14205 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14206#endif
14207
14208 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14209
14210 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14211 // to record it being moved (and thus the macroExpansions that it might be associated with having
14212 // to force the macroExpansion's associated statements to be marked as a transformation.
14214
14215#if 0
14216 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14217 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14218#endif
14219
14220 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14221
14222 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14223 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14224 // prepend, we only need to look at the scope.
14226
14227#if 0
14228 printf ("Calling insertStatementInScope() \n");
14229#endif
14230
14231 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14232 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14233
14234 scope->insertStatementInScope(stmt,true);
14235 stmt->set_parent(scope); // needed?
14236
14237 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14238
14239 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14240 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14241 // this). Also since this is only operating within a single scope it is likely too specific to C
14242 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14243 // use name qualification).
14244 // update the links after insertion!
14246 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14247 {
14248 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14249 }
14250
14251 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14252
14253#if 0
14254 printf ("Leaving SageInterface::prependStatement() \n");
14255#endif
14256 } // prependStatement()
14257
14258
14261{
14262 ROSE_ASSERT (stmt != NULL);
14263 ROSE_ASSERT (for_init_stmt != NULL);
14264
14265#if 0
14266 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());
14267#endif
14268
14269 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14270 // to record it being moved (and thus the macroExpansions that it might be associated with having
14271 // to force the macroExpansion's associated statements to be marked as a transformation.
14273
14274#if 0
14275 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());
14276#endif
14277
14278 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14279 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14280 // prepend, we only need to look at the scope.
14282
14283 for_init_stmt->prepend_init_stmt (stmt);
14284}
14285
14286void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14287 {
14288 for (size_t i = stmts.size(); i > 0; --i)
14289 {
14290 prependStatement(stmts[i - 1], scope);
14291 }
14292 }
14293
14298{
14299 bool rt = false;
14300 ROSE_ASSERT (scope != NULL);
14301 switch (scope->variantT())
14302 {
14303 case V_SgBasicBlock:
14304 case V_SgClassDefinition:
14305 case V_SgFunctionDefinition:
14306 case V_SgGlobal:
14307 case V_SgNamespaceDefinitionStatement: //?
14308 rt = true;
14309 break;
14310
14311 case V_SgAssociateStatement :
14312 case V_SgBlockDataStatement :
14313 case V_SgCatchOptionStmt:
14314 case V_SgDoWhileStmt:
14315 case V_SgForAllStatement:
14316 case V_SgForStatement:
14317 case V_SgFortranDo:
14318 case V_SgIfStmt:
14319 case V_SgSwitchStatement:
14320 case V_SgUpcForAllStatement:
14321 case V_SgWhileStmt:
14322 rt = false;
14323 break;
14324
14325 default:
14326 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14327 break;
14328 }
14329 return rt;
14330}
14331
14332
14333// 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.
14335 {
14336 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14337 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14338
14339 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14340
14341 SgStatement* last_statement = NULL;
14342 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14343 // while (i != declarationList.end())
14344 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14345 {
14346#if 0
14347 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");
14348#endif
14349 last_statement = *i;
14350
14351 i++;
14352 }
14353
14354 ROSE_ASSERT(last_statement != NULL);
14355#if 1
14356 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14357#endif
14358#if 0
14359 printf ("Exiting as a test! \n");
14360 ROSE_ABORT();
14361#endif
14362
14363 return last_statement;
14364 }
14365
14366
14367 //TODO handle more side effect like SageBuilder::append_statement() does
14368 //Merge myStatementInsert()
14369 // insert SageInterface::insertStatement()
14370void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14371 {
14372 ROSE_ASSERT(targetStmt &&newStmt);
14373 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14374 SgNode* parent = targetStmt->get_parent();
14375 if (parent == NULL)
14376 {
14377 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14378 ROSE_ASSERT(parent);
14379 }
14380
14381 if (isSgLabelStatement(parent) != NULL)
14382 {
14383#if 0
14384 printf ("In SageInterface::insertStatement(): Detected case of label statement as parent, using parent of label statement \n");
14385#endif
14386 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14387 // parent = labelStatement->get_scope();
14388 parent = labelStatement->get_parent();
14389 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14390 }
14391
14392#if 0
14393 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());
14394#endif
14395
14396 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14397 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14398 // ROSE_ASSERT(functionDefinition != NULL);
14399
14400 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14401 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14402 // We now have single statement true/false body for IfStmt etc
14403 // However, IfStmt::insert_child() is ambiguous and not implemented
14404 // So we make SgBasicBlock out of the single statement and
14405 // essentially call SgBasicBlock::insert_child() instead.
14406 // TODO: add test cases for If, variable, variable/struct inside if, etc
14407 // parent = ensureBasicBlockAsParent(targetStmt);
14408
14409 // must get the new scope after ensureBasicBlockAsParent ()
14410 SgScopeStatement* scope = targetStmt->get_scope();
14411 ROSE_ASSERT(scope);
14412
14413#if 0
14414 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14415 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14416#endif
14417
14418 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14419 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14420 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14421 // 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
14422 // more sense in this special case of a SgLabelStatement.
14423 // newStmt->set_parent(targetStmt->get_parent());
14424 newStmt->set_parent(scope);
14425
14426 // 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.
14427 // The fix was the reuse the one that was found.
14428 fixStatement(newStmt,scope);
14429
14430 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14431 // However, if this is required to be true then what about statements in
14432 // SgStatementExpression IR nodes?
14433 ROSE_ASSERT(isSgStatement(parent) != NULL);
14434
14435 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14436 // appear before the statement to be attached to the inserted statement (and marked
14437 // to appear before that statement).
14438 ROSE_ASSERT(targetStmt != NULL);
14439 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14440
14441#if 0
14442 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14443 reportNodesMarkedAsModified(scope);
14444#endif
14445
14446 // TODO refactor this portion of code into a separate function
14447 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14448 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14449 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14450 {
14451 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14452 {
14453 vector<int> captureList;
14454#if 0
14455 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14456 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14457#endif
14458 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14459 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14460 {
14461 // If the inserted statment has attached comments or CPP directives then this is gets a little
14462 // bit more comple and we don't support that at present.
14463 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");
14464 }
14465 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14466 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14467
14468 int commentIndex = 0;
14469 AttachedPreprocessingInfoType::iterator i;
14470 for (i = comments->begin(); i != comments->end(); i++)
14471 {
14472 ROSE_ASSERT ( (*i) != NULL );
14473#if 0
14474 printf (" Attached Comment (relativePosition=%s): %s\n",
14475 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14476 (*i)->getString().c_str());
14477 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14478 (*i)->get_file_info()->display("comment/directive location");
14479#endif
14480 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14481 if ((*i)->getRelativePosition() == relativePosition)
14482 {
14483 // accumulate into list
14484 captureList.push_back(commentIndex);
14485 }
14486
14487 commentIndex++;
14488 }
14489
14490 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14491 if (captureList.empty() == false)
14492 {
14493 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14494 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14495 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14496 SgStatement* surroundingStatement = newStmt;
14497 ROSE_ASSERT(surroundingStatement != targetStmt);
14498 ROSE_ASSERT(surroundingStatement != NULL);
14499#if 0
14500 if (surroundingStatement == NULL)
14501 {
14502 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14503 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14504 }
14505#endif
14506 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14507 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14508 vector<int>::iterator j = captureList.begin();
14509 while (j != captureList.end())
14510 {
14511 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14512 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14513 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14514
14515 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14516 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14517 (*comments)[*j] = NULL;
14518
14519 j++;
14520 }
14521
14522 // Now remove each NULL entries in the comments vector.
14523 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14524 for (size_t n = 0; n < captureList.size(); n++)
14525 {
14526 AttachedPreprocessingInfoType::iterator k = comments->begin();
14527 while (k != comments->end())
14528 {
14529 // Only modify the list once per iteration over the captureList
14530 if (*k == NULL)
14531 {
14532 comments->erase(k);
14533 break;
14534 }
14535 k++;
14536 }
14537 }
14538 }
14539 }
14540 else
14541 {
14542 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14543 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14544 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14545 if (comments != NULL)
14546 {
14547 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");
14548 }
14549 }
14550 } // end if autoMovePreprocessingInfo
14551
14552
14553#if 0
14554 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14555 reportNodesMarkedAsModified(scope);
14556#endif
14557
14558 if (isSgIfStmt(parent))
14559 {
14560 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14561 {
14562 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14563 }
14564 else
14565 {
14566 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14567 {
14568 // Liao 3/2/2012
14569 // We have some choices:
14570 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14571 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14572 // Since the targetStmt will have new content inside of it, which is not the semantics of
14573 // inserting anything before/or after it.
14574 // 2) always insert a padding basic block between parent and targetStmt
14575 // and we can legally insert before/after the target statement within the
14576 // padding basic block.
14577 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14578 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14579 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14580 isSgIfStmt(parent)->set_true_body(newparent);
14581 newparent->set_parent(parent);
14582 insertStatement(targetStmt, newStmt,insertBefore);
14583 }
14584 else
14585 {
14586 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14587 {
14588 // ensureBasicBlockAsParent(targetStmt);
14589 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14590 isSgIfStmt(parent)->set_false_body(newparent);
14591 newparent->set_parent(parent);
14592 insertStatement(targetStmt, newStmt,insertBefore);
14593 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14594 }
14595 }
14596 }
14597 }
14598 else
14599 {
14600 if (isSgWhileStmt(parent))
14601 {
14602 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14603 {
14604 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14605 }
14606 else
14607 {
14608 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14609 {
14610 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14611 isSgWhileStmt(parent)->set_body(newparent);
14612 newparent->set_parent(parent);
14613 insertStatement(targetStmt, newStmt,insertBefore);
14614 // ensureBasicBlockAsParent(targetStmt);
14615 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14616 }
14617 }
14618 }
14619 else
14620 {
14621 if (isSgDoWhileStmt(parent))
14622 {
14623 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14624 {
14625 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14626 }
14627 else
14628 {
14629 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14630 {
14631 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14632 isSgDoWhileStmt(parent)->set_body(newparent);
14633 newparent->set_parent(parent);
14634 insertStatement(targetStmt, newStmt,insertBefore);
14635 // ensureBasicBlockAsParent(targetStmt);
14636 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14637 }
14638 }
14639 }
14640 else
14641 {
14642 if (isSgForStatement(parent))
14643 {
14644 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14645 {
14646 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14647 isSgForStatement(parent)->set_loop_body(newparent);
14648 newparent->set_parent(parent);
14649 insertStatement(targetStmt, newStmt,insertBefore);
14650 // ensureBasicBlockAsParent(targetStmt);
14651 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14652 }
14653 else
14654 {
14655 if (isSgForStatement(parent)->get_test()==targetStmt)
14656 {
14657 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14658 }
14659 }
14660 }
14661 else // \pp (2/24/2011) added support for UpcForAll
14662 {
14663 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14664 {
14665 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14666
14667 // \pp \todo what if !stmt_present
14668 // ROSE_ASSERT(stmt_present != NULL);
14669 insertStatement(p, newStmt, insertBefore);
14670 }
14671 else
14672 {
14673 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14674 {
14675 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14676 p->set_body(newparent);
14677 newparent->set_parent(parent);
14678 insertStatement(targetStmt, newStmt,insertBefore);
14679 }
14680 else
14681 {
14682 // It appears that all of the recursive calls are untimately calling this location.
14683 SgStatement* stmnt = isSgStatement(parent);
14684 ROSE_ASSERT(stmnt != NULL);
14685 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14686 }
14687 }
14688 }
14689 }
14690 }
14691 }
14692
14693 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14694 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14695 // this). Also since this is only operating within a single scope it is likely too specific to C
14696 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14697 // use name qualification).
14698 // update the links after insertion!
14700 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14701 {
14702 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14703 }
14704
14705#if 0
14706 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14707 reportNodesMarkedAsModified(scope);
14708#endif
14709 }
14710
14711
14712void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14713 {
14714 if (insertBefore)
14715 {
14716 for (size_t i = 0; i < newStmts.size(); ++i)
14717 {
14718 insertStatementBefore(targetStmt, newStmts[i]);
14719 }
14720 }
14721 else
14722 {
14723 for (size_t i = newStmts.size(); i > 0; --i)
14724 {
14725 insertStatementAfter(targetStmt, newStmts[i - 1]);
14726 }
14727 }
14728 }
14729
14730void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14731 {
14732 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14733 }
14734
14735void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14736 {
14737 insertStatementList(targetStmt,newStmts,false);
14738 }
14739
14742 {
14743 ROSE_ASSERT (stmt != NULL);
14744 ROSE_ASSERT (scope != NULL);
14745 // Insert to be the declaration after current declaration sequence, if any
14746 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14747 if (l_stmt)
14748 insertStatementAfter(l_stmt,stmt);
14749 else
14750 prependStatement(stmt, scope);
14751 }
14752
14754void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
14755 {
14756 ROSE_ASSERT (scope != NULL);
14757 vector <SgStatement* >::iterator iter;
14758 SgStatement* prev_stmt = NULL;
14759 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
14760 {
14761 if (iter == stmt_list.begin())
14762 {
14764 }
14765 else
14766 {
14767 ROSE_ASSERT (prev_stmt != NULL);
14768 insertStatementAfter (prev_stmt, *iter);
14769 }
14770 prev_stmt = *iter;
14771 }
14772 }
14773
14775{
14776 ROSE_ASSERT(newStmt!=NULL);
14777 ROSE_ASSERT(scope!=NULL);
14778 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14779 if (!isSgDeclarationStatement(targetStmt)) {
14780 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
14781 return;
14782 }
14783 }
14784 appendStatement(newStmt, scope);
14785}
14786
14787void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
14788{
14789 ROSE_ASSERT(scope!=NULL);
14790 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
14791 if (!isSgDeclarationStatement(targetStmt)) {
14792 insertStatementListBefore(targetStmt, newStmts);
14793 return;
14794 }
14795 }
14796 appendStatementList(newStmts, scope);
14797}
14798
14799void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
14800 {
14801 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
14802 }
14803
14804void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14805 {
14806 insertStatementList(targetStmt,newStmts,true);
14807 }
14808
14809 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
14810 // special concern for lvalue, parent,
14811 // todo: warning overwriting existing operands
14813 {
14814 ROSE_ASSERT(target);
14815 ROSE_ASSERT(operand);
14816 ROSE_ASSERT(target!=operand);
14817 switch (target->variantT())
14818 {
14819 case V_SgActualArgumentExpression:
14820 isSgActualArgumentExpression(target)->set_expression(operand);
14821 break;
14822 case V_SgAsmOp:
14823 isSgAsmOp(target)->set_expression(operand);
14824 break;
14825 case V_SgSizeOfOp:
14826 isSgSizeOfOp(target)->set_operand_expr(operand);
14827 break;
14828 case V_SgTypeIdOp:
14829 isSgTypeIdOp(target)->set_operand_expr(operand);
14830 break;
14831 case V_SgVarArgOp:
14832 isSgVarArgOp(target)->set_operand_expr(operand);
14833 break;
14834 case V_SgVarArgStartOneOperandOp:
14835 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
14836 break;
14837 case V_SgAssignInitializer:
14838 isSgAssignInitializer (target)->set_operand(operand);
14839 break;
14840 default:
14841 if (isSgUnaryOp(target)!=NULL)
14842 isSgUnaryOp(target)->set_operand_i(operand);
14843 else
14844 {
14845 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
14846 <<target->class_name()<<endl;
14847 ROSE_ABORT();
14848 }
14849 }// end switch
14850 operand->set_parent(target);
14851 markLhsValues(target);
14852 }
14853
14854 // binary and SgVarArgCopyOp, SgVarArgStartOp
14856 {
14857 ROSE_ASSERT(target);
14858 ROSE_ASSERT(lhs);
14859 ROSE_ASSERT(target!=lhs);
14860 bool hasrhs = false;
14861
14862 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14863 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14864 SgBinaryOp* binary = isSgBinaryOp(target);
14865
14866 if (varargcopy!=NULL)
14867 {
14868 varargcopy->set_lhs_operand(lhs);
14869 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
14870 }
14871 else if(varargstart!=NULL)
14872 {
14873 varargstart->set_lhs_operand(lhs);
14874 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
14875 }
14876 else if(binary!=NULL)
14877 {
14878 binary->set_lhs_operand(lhs);
14879 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
14880 }
14881 else
14882 {
14883 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
14884 <<target->class_name()<<endl;
14885 ROSE_ABORT();
14886 }
14887 lhs->set_parent(target);
14888// only when both lhs and rhs are available, can we set lvalue
14889// there is assertion(rhs!=NULL) in markLhsValues()
14890 if (hasrhs)
14891 markLhsValues(target);
14892 }
14893
14895 {
14896 ROSE_ASSERT(target);
14897 ROSE_ASSERT(rhs);
14898 ROSE_ASSERT(target!=rhs);
14899 bool haslhs = false;
14900
14901 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
14902 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
14903 SgBinaryOp* binary = isSgBinaryOp(target);
14904
14905 if (varargcopy!=NULL)
14906 {
14907 varargcopy->set_rhs_operand(rhs);
14908 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
14909 }
14910 else if(varargstart!=NULL)
14911 {
14912 varargstart->set_rhs_operand(rhs);
14913 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
14914 }
14915 else if(binary!=NULL)
14916 {
14917 binary->set_rhs_operand(rhs);
14918 if( binary->get_lhs_operand()!=NULL) haslhs= true;
14919 }
14920 else
14921 {
14922 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
14923 <<target->class_name()<<endl;
14924 ROSE_ABORT();
14925 }
14926 rhs->set_parent(target);
14927// only when both lhs and rhs are available, can we set lvalue
14928 if (haslhs)
14929 markLhsValues(target);
14930 }
14931
14932// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
14933void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
14934 {
14935 // This support makes use of the new SgDirectory IR node. It causes the unparser to
14936 // generate a subdirectory and unparse the file into the subdirectory. It works
14937 // by internally calling the system function "system()" to call "mkdir directoryName"
14938 // and then chdir()" to change the current directory. These steps are handled by the
14939 // unparser.
14940
14941 // This function just does the transformation to insert a SgDirectory IR node between
14942 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
14943
14944 // Add a directory and unparse the code (to the new directory)
14945 SgDirectory* directory = new SgDirectory(directoryName);
14946
14947 SgFileList* parentFileList = isSgFileList(file->get_parent());
14948 ROSE_ASSERT(parentFileList != NULL);
14949 directory->set_parent(file->get_parent());
14950
14951 SgProject* project = NULL;
14952 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
14953
14954 if (parentDirectory != NULL)
14955 {
14956 // Add a directory to the list in the SgDirectory node.
14957 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
14958
14959 // Erase the reference to the file in the project's file list.
14960 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
14961 }
14962 else
14963 {
14964 project = isSgProject(parentFileList->get_parent());
14965 ROSE_ASSERT(project != NULL);
14966
14967 // Add a directory to the list in the SgProject node.
14968 project->get_directoryList()->get_listOfDirectories().push_back(directory);
14969
14970 // Erase the reference to the file in the project's file list.
14971 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
14972 }
14973
14974 // Put the file into the new directory.
14975 directory->get_fileList()->get_listOfFiles().push_back(file);
14976
14977 // Erase the reference to the file in the project's file list.
14978 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
14979
14980 file->set_parent(directory);
14981}
14982
14983
14984//------------------------- AST repair----------------------------
14985//----------------------------------------------------------------
14987 {
14988 ROSE_ASSERT(structDecl != NULL);
14989 ROSE_ASSERT(scope != NULL);
14990 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
14991 ROSE_ASSERT(nondefdecl != NULL);
14992
14993 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
14994 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
14995 // ROSE_ASSERT(defdecl != NULL);
14996
14997 // Liao, 9/2/2009
14998 // fixup missing scope when bottomup AST building is used
14999 if (structDecl->get_scope() == NULL)
15000 structDecl->set_scope(scope);
15001 if (nondefdecl->get_scope() == NULL)
15002 nondefdecl->set_scope(scope);
15003
15004#if 0
15005 if (structDecl->get_parent() == NULL)
15006 structDecl->set_parent(scope);
15007 if (nondefdecl->get_parent() == NULL)
15008 nondefdecl->set_parent(scope);
15009#else
15010 // 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");
15011
15012 // DQ (7/21/2012): Can we assert this here? NO!
15013 // ROSE_ASSERT(structDecl->get_parent() == NULL);
15014 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
15015#endif
15016
15017 SgName name = structDecl->get_name();
15018
15019 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15020 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15021 // But symbols are associated with nondefining declarations whenever possible
15022 // and AST consistent check will check the nondefining declarations first
15023 // Liao, 9/2/2009
15024 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15025 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15026
15027 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15028 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15029 // ROSE_ASSERT(mysymbol != NULL);
15030
15031 if (mysymbol == NULL)
15032 {
15033 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15034
15035 // 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...
15036 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15037 ROSE_ASSERT(structDecl->get_scope() != NULL);
15038
15039 if (scope == structDecl->get_scope())
15040 {
15041 mysymbol = new SgClassSymbol(nondefdecl);
15042 ROSE_ASSERT(mysymbol);
15043
15044 // I need to check the rest of these functions.
15045 printf ("############## DANGER:DANGER:DANGER ################\n");
15046
15047 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15048 scope->insert_symbol(name, mysymbol);
15049
15050 // ROSE_ASSERT(defdecl != NULL);
15051 if (defdecl)
15052 defdecl->set_scope(scope);
15053 nondefdecl->set_scope(scope);
15054
15055 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15056#if 0
15057 if (defdecl)
15058 defdecl->set_parent(scope);
15059 nondefdecl->set_parent(scope);
15060#endif
15061 }
15062 else
15063 {
15064 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15065 }
15066 }
15067
15068 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15069 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15070
15071 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15072 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15073
15074 // DQ (9/4/2012): This should be a SgClassType IR node.
15075 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15076
15077 // fixup SgClassType, which is associated with the first non-defining declaration only
15078 // and the other declarations share it.
15079 if (nondefdecl->get_type() == NULL)
15080 {
15081 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15082 }
15083 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15084
15085 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15086 if (defdecl != NULL)
15087 {
15088 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15089 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15090
15091 // DQ (9/4/2012): This should be a SgClassType IR node.
15092 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15093 }
15094
15095 // ROSE_ASSERT(defdecl != NULL);
15096 if (defdecl != NULL)
15097 {
15098 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15099 ROSE_ASSERT(defdecl->get_type() != NULL);
15100 if (defdecl->get_type() != nondefdecl->get_type())
15101 {
15102 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15103 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15104 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15105 if (namedType_definingDecl != NULL)
15106 {
15107 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15108 }
15109 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15110 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15111 if (namedType_nondefiningDecl != NULL)
15112 {
15113 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15114 }
15115 }
15116 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15117 }
15118 }
15119
15120
15122 {
15123 fixStructDeclaration(classDecl,scope);
15124 }
15125
15126
15128 {
15129 ROSE_ASSERT(structDecl);
15130 ROSE_ASSERT(scope);
15131 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15132 ROSE_ASSERT(nondefdecl);
15133 // Liao, 9/2/2009
15134 // fixup missing scope when bottomup AST building is used
15135 if (structDecl->get_parent() == NULL)
15136 structDecl->set_parent(scope);
15137 if (nondefdecl->get_parent() == NULL)
15138 nondefdecl->set_parent(scope);
15139
15140 // tps : (09/03/2009) Namespace should not have a scope
15141 /*
15142 if (structDecl->get_scope() == NULL)
15143 structDecl->set_scope(scope);
15144 if (nondefdecl->get_scope() == NULL)
15145 nondefdecl->set_scope(scope);
15146 */
15147
15148 SgName name= structDecl->get_name();
15149 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15150 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15151 if (mysymbol==NULL)
15152 {
15153 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15154 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15155 if (scope == structDecl->get_scope())
15156 {
15157 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15158 ROSE_ASSERT(mysymbol);
15159
15160 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15161 scope->insert_symbol(name, mysymbol);
15162
15163 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15164 ROSE_ASSERT(defdecl);
15165 defdecl->set_scope(scope);
15166 nondefdecl->set_scope(scope);
15167
15168 defdecl->set_parent(scope);
15169 nondefdecl->set_parent(scope);
15170 }
15171 }
15172 }
15173
15175 {
15176 ROSE_ASSERT(varDecl != NULL);
15177 ROSE_ASSERT(scope != NULL);
15178
15179 SgInitializedNamePtrList namelist = varDecl->get_variables();
15180
15181 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15182
15183#if 0
15184 printf ("In SageInterface::fixVariableDeclaration(): varDecl = %p scope = %p = %s \n",varDecl,scope,scope->class_name().c_str());
15185#endif
15186
15187 ROSE_ASSERT(namelist.size() > 0);
15188
15189 SgInitializedNamePtrList::iterator i;
15190 for (i = namelist.begin(); i != namelist.end(); i++)
15191 {
15192 SgInitializedName *initName = *i;
15193 ROSE_ASSERT(initName != NULL);
15194
15195 SgName name = initName->get_name();
15196#if 0
15197 printf (" -- initName = %p : %s\n", initName, name.str());
15198 printf (" -- initName->get_scope() = %p (%s)\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15199#endif
15200
15201 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15202 // and be using name qualification, so might not be associated with the current scope.
15203 SgScopeStatement* requiredScope = scope;
15204 SgScopeStatement* preAssociatedScope = initName->get_scope();
15205 // printf ("In SageInterface::fixVariableDeclaration() preAssociatedScope = %p \n",preAssociatedScope);
15206
15207 if (preAssociatedScope != NULL)
15208 {
15209#if 0
15210 printf ("In SageInterface::fixVariableDeclaration(): Note that this variable already has an associated scope! preAssociatedScope = %p = %s (but will be reset below) \n",preAssociatedScope,preAssociatedScope->class_name().c_str());
15211#endif
15212 // ROSE_ASSERT(preAssociatedScope == scope);
15213 requiredScope = preAssociatedScope;
15214 }
15215
15216 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15217 // initName->set_scope(scope);
15218 initName->set_scope(requiredScope);
15219
15220 // optional?
15221 // DQ (7/9/2012): Don't set this since it will be set later (see test2012_107.C) (LATER) Putting this back (mark declarations to not be output as compiler generated -- and not to be output).
15222 // DQ (7/12/2012): This is not correct for C++, so don't set it here (unless we use the current scope instead of scope).
15223 // Yes, let's set it to the current top of the scope stack. This might be a problem if the scope stack is not being used...
15224 // varDecl->set_parent(scope);
15225 if (topScopeStack() != NULL)
15226 {
15227 varDecl->set_parent(topScopeStack());
15228 ROSE_ASSERT(varDecl->get_parent() != NULL);
15229 }
15230
15231 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15232 // symbol table
15233 // ROSE_ASSERT(scope != NULL);
15234 // SgVariableSymbol* varSymbol = scope->lookup_variable_symbol(name);
15235 ROSE_ASSERT(requiredScope != NULL);
15236 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15237#if 0
15238 printf (" -- varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15239#endif
15240
15241 if (varSymbol == NULL)
15242 {
15243 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15244 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15245 if (scope == initName->get_scope())
15246 {
15247 if (isSgTemplateVariableDeclaration(varDecl)) {
15248 varSymbol = new SgTemplateVariableSymbol(initName);
15249 } else {
15250 varSymbol = new SgVariableSymbol(initName);
15251 }
15252 ROSE_ASSERT(varSymbol);
15253
15254 // DQ (5/16/2013): We now want to use the SgScopeStatement::insert_symbol() functions since we put
15255 // the complexity of handling namespaces into the implementation of that function.
15256 scope->insert_symbol(name, varSymbol);
15257 }
15258 }
15259 else
15260 {
15261 // TODO consider prepend() and insert(), prev_decl_time is position dependent.
15262 // cout<<"sageInterface.C:5130 debug: found a previous var declaration!!...."<<endl;
15263 SgInitializedName* prev_decl = varSymbol->get_declaration();
15264 ROSE_ASSERT(prev_decl);
15265
15266 // DQ (11/19/2011): Don't let prev_decl_item point be a self reference.
15267 // initName->set_prev_decl_item(prev_decl);
15268 if (initName != prev_decl)
15269 initName->set_prev_decl_item(prev_decl);
15270
15271 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15272
15273 } //end if
15274 } //end for
15275
15276 // Liao 12/8/2010
15277 // For Fortran, a common statement may refer to a variable which is declared later.
15278 // In this case, a fake symbol is used for that variable reference.
15279 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15281 {
15282 fixVariableReferences(scope);
15283 }
15284 }
15285
15286int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15287{
15288 ROSE_ASSERT(root);
15289 int counter=0;
15290 Rose_STL_Container<SgNode*> varList;
15291
15292 SgVarRefExp* varRef=NULL;
15293 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15294 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15295 {
15296 varRef= isSgVarRefExp(*i);
15297 ROSE_ASSERT(varRef->get_symbol());
15298 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15299
15300 ROSE_ASSERT (initname != NULL);
15301 if (initname->get_type()==SgTypeUnknown::createType())
15302 {
15303 SgName varName=initname->get_name();
15304 SgSymbol* realSymbol = NULL;
15305
15306#if 1
15307 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15308 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15309 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15310 // operators, and static members using :: operators.
15311 //
15312 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15313 {
15314 if (varRef == arrowExp->get_rhs_operand_i())
15315 {
15316 // make sure the lhs operand has been fixed
15317 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15318 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15319 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15320 SgPointerType* ptrType = isSgPointerType(lhs_type);
15321 ROSE_ASSERT(ptrType);
15322 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));
15323 ROSE_ASSERT(clsType);
15324 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15325 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15326 ROSE_ASSERT(decl);
15327
15328 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15329 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15330 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15331 }
15332 else
15333 {
15334 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15335 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15336 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15337 }
15338 }
15339 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15340 {
15341 if (varRef == dotExp->get_rhs_operand_i())
15342 {
15343 // make sure the lhs operand has been fixed
15344 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15345
15346 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15347 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15348 SgClassType* clsType = isSgClassType(lhs_type);
15349 ROSE_ASSERT(clsType);
15350 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15351 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15352 ROSE_ASSERT(decl);
15353
15354 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15355 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15356 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15357 }
15358 else
15359 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15360 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15361 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15362 }
15363 else
15364#endif
15365 {
15366 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15367 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15368 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15369 }
15370
15371 // should find a real symbol at this final fixing stage!
15372 // This function can be called any time, not just final fixing stage
15373 if (realSymbol==NULL)
15374 {
15375 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15376 //ROSE_ASSERT(realSymbol);
15377 }
15378 else {
15379 // release placeholder initname and symbol
15380 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15381#if 0
15382 // CH (5/12/2010):
15383 // To delete a symbol node, first check if there is any node in memory
15384 // pool which points to this symbol node. Only if no such node exists,
15385 // this symbol together with its initialized name can be deleted.
15386 //
15387 bool toDelete = true;
15388
15389 SgSymbol* symbolToDelete = varRef->get_symbol();
15390 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15391 counter ++;
15392
15393 if (varList.empty())
15394 {
15395 VariantVector vv(V_SgVarRefExp);
15396 varList = NodeQuery::queryMemoryPool(vv);
15397 }
15398
15399 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15400 i != varList.end(); ++i)
15401 {
15402 if (SgVarRefExp* var = isSgVarRefExp(*i))
15403 {
15404 if (var->get_symbol() == symbolToDelete)
15405 {
15406 toDelete = false;
15407 break;
15408 }
15409 }
15410 }
15411 if (toDelete)
15412 {
15413 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15414 delete symbolToDelete;
15415 }
15416
15417#else
15418
15419 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15420 // which point to them. We will delay this clear just before AstTests.
15421#if 0
15422 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15423 delete (varRef->get_symbol());
15424#endif
15425
15426 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15427 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15428 counter ++;
15429#endif
15430 }
15431 }
15432 } // end for
15433 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15434 if (cleanUnusedSymbols)
15436 return counter;
15437}
15438
15440{
15441 Rose_STL_Container<SgNode*> symbolList;
15442 VariantVector sym_vv(V_SgVariableSymbol);
15443 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15444
15445 Rose_STL_Container<SgNode*> varList;
15446 VariantVector var_vv(V_SgVarRefExp);
15447 //varList = NodeQuery::queryMemoryPool(var_vv);
15448 if (root != NULL)
15449 {
15450 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15451 }
15452
15453 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15454 i != symbolList.end(); ++i)
15455 {
15456 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15457 ROSE_ASSERT(symbolToDelete);
15458 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15459 continue;
15460 // symbol with a declaration of SgTypeUnknown will be deleted
15461 bool toDelete = true;
15462
15463 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15464 {
15465 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15466 j != varList.end(); ++j)
15467 {
15468 SgVarRefExp* var = isSgVarRefExp(*j);
15469 ROSE_ASSERT(var);
15470
15471 if (var->get_symbol() == symbolToDelete)
15472 {
15473 toDelete = false;
15474 break;
15475 }
15476 }
15477 }
15478
15479 if (toDelete)
15480 {
15481#if 0
15482 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15483 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15484#endif
15485 delete symbolToDelete->get_declaration();
15486 delete symbolToDelete;
15487 }
15488 }
15489}
15490
15491
15493/*
15494 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15495 */
15497 {
15498 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15499 ROSE_ASSERT(label_stmt);
15500 SgName name = label_stmt->get_label();
15501
15502 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15503 const bool symbolAtFunctionLevel = !is_Ada_language();
15504 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15505 : scope;
15506
15507 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15508 if (isSgFunctionDefinition(scope) != nullptr)
15509 {
15510 ASSERT_not_null(label_scope);
15511 }
15512
15513 if (label_scope) //Should we assert this instead? No for bottom up AST building
15514 {
15515 label_stmt->set_scope(label_scope);
15516 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15517
15518 if (lsymbol == nullptr)
15519 {
15520 // SgLabelStatement should always be in the function scope
15521 // PP (07/18/23): in Ada symbols should be at the innermost scope
15522 lsymbol= new SgLabelSymbol(label_stmt);
15523 ASSERT_not_null(lsymbol);
15524 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15525 }
15526 }
15527 }
15528
15529
15531//efExp are created transparently as needed.
15533 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15534 {
15535 ROSE_ASSERT (stmt != NULL);
15536 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15537
15538 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15539 if (label_scope == NULL)
15540 {
15541 label_scope = getEnclosingFunctionDefinition(stmt);
15542 }
15543 ROSE_ASSERT (label_scope != NULL);
15544 SgName label_name(StringUtility::numberToString(label_value));
15545 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15546 if (symbol == NULL)
15547 {
15548 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15549 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15550 // symbol = new SgLabelSymbol(NULL);
15551 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15552 ROSE_ASSERT(symbol != NULL);
15553 symbol->set_fortran_statement(stmt);
15554 symbol->set_numeric_label_value(label_value);
15555 label_scope->insert_symbol(label_name,symbol);
15556 }
15557 else
15558 {
15559 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15560 ROSE_ASSERT (false);
15561 }
15562
15563 // SgLabelRefExp
15564 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15565 ref_exp->set_parent(stmt);
15566
15567 switch(label_type)
15568 {
15569 case SgLabelSymbol::e_start_label_type:
15570 {
15571 stmt->set_numeric_label(ref_exp);
15572 break;
15573 }
15574 case SgLabelSymbol::e_end_label_type:
15575 {
15576 stmt->set_end_numeric_label(ref_exp);
15577 break;
15578 }
15579 default:
15580 {
15581 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15582 ROSE_ABORT(); // NOT IMPLEMENTED
15583 }
15584 }
15585
15586 }
15587
15588
15591{
15592 int result =10;
15593 ROSE_ASSERT (func_def != NULL);
15594 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15595 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15596
15597 // find the max label value, +10 to be the suggested next label value
15598 std::set<SgNode*>::iterator iter ;
15599 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15600 {
15601 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15602 if (l_symbol)
15603 {
15604 int cur_val = l_symbol->get_numeric_label_value();
15605 if (result <=cur_val)
15606 result = cur_val +10;
15607 }
15608 }
15609
15610 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15611 return result;
15612}
15613
15615/*
15616 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15617 */
15619 {
15620 // DQ (3/5/2012): Added test.
15621 ROSE_ASSERT(scope != NULL);
15622
15623 // fix function type table's parent edge
15624 // Liao 5/4/2010
15626 ROSE_ASSERT(fTable != NULL);
15627
15628 if (fTable->get_parent() == NULL)
15629 {
15630 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15631 // fTable->set_parent(getGlobalScope(scope));
15632#if 0
15633 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15634#endif
15635 fTable->set_parent(getGlobalScope(scope));
15636 }
15637
15638#if 0
15639 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15640#endif
15641
15642 // Liao 4/23/2010, Fix function symbol
15643 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15644 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15645 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15646 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15647 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15648 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15649 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15650 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15651
15652 if (tmfunc != NULL)
15653 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15654 else if (mfunc != NULL)
15655 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15656 else if (tfunc != NULL)
15657 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15658 else if (procfunc != NULL)
15659 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15660 else if (progfunc != NULL)
15661 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15662 else if (func != NULL)
15663 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15664 else ROSE_ABORT();
15665
15666#if 0
15667 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15668 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15669#endif
15670
15671 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15672 // It is an error to put the symbol for a function into the current scope if the function's scope
15673 // is explicitly set to be different. So this should be allowed only if the function's scope is
15674 // not explicitly set, or if the scopes match. This is an example of something different for C++
15675 // than for C or other simpler languages.
15676 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15677 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15678 {
15679#if 0
15680 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());
15681#endif
15682 SgFunctionSymbol* func_symbol = NULL;
15683
15684 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15685 // In this case these are unavailable from this point.
15686 if (tmfunc != NULL)
15687 {
15688 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15689 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15690 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15691 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15692 }
15693 else if (mfunc != NULL)
15694 {
15695 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15696 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15697 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15698 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15699 }
15700 else if (tfunc != NULL)
15701 {
15702 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15703#if 0
15704 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15705#endif
15706 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15707 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15708 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15709 }
15710 else if (procfunc != NULL)
15711 {
15712#if 0
15713 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15714#endif
15715 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15716 assert(func_symbol != NULL);
15717 }
15718 else if (progfunc != NULL)
15719 {
15720 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15721 assert(func_symbol != NULL);
15722 }
15723 else if (func != NULL)
15724 {
15725#if 0
15726 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15727#endif
15728 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15729 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15730 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15731 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15732
15733 // 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
15734 // 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
15735 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15736 if (func_symbol == NULL)
15737 {
15738 // scope->print_symboltable("In SageInterface::fixStatement()");
15739 func_symbol = new SgFunctionSymbol(func);
15740 scope->insert_symbol(func->get_name(), func_symbol);
15741 }
15742 }
15743 else
15744 {
15745 ROSE_ABORT();
15746 }
15747#if 0
15748 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15749#endif
15750 assert(func_symbol != NULL);
15751 }
15752 }
15753
15755/*
15756 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15757 */
15759 {
15760 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15761 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15762 }
15763
15764
15767 {
15768 // fix symbol table
15769 if (isSgVariableDeclaration(stmt))
15770 {
15771 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
15772 }
15773 else if (isStructDeclaration(stmt))
15774 {
15775 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
15776 ROSE_ASSERT(classDeclaration != nullptr);
15777 fixStructDeclaration(classDeclaration,scope);
15778 }
15779 else if (isSgClassDeclaration(stmt))
15780 {
15781 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
15782 }
15783 else if (isSgLabelStatement(stmt))
15784 {
15785 fixLabelStatement(isSgLabelStatement(stmt),scope);
15786 }
15787 else if (isSgFunctionDeclaration(stmt))
15788 {
15789#if 1
15790 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
15791#else
15792 // fix function type table's parent edge
15793 // Liao 5/4/2010
15795 ROSE_ASSERT(fTable);
15796 if (fTable->get_parent() == NULL)
15797 fTable->set_parent(getGlobalScope(scope));
15798
15799 // Liao 4/23/2010, Fix function symbol
15800 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15801 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
15802 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
15803
15804 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15805 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15806
15807 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15808 // It is an error to put the symbol for a function into the current scope if the function's scope
15809 // is explicitly set to be different. So this should be allowed only if the function's scope is
15810 // not explicitly set, or if the scopes match. This is an example of something different for C++
15811 // than for C or other simpler languages.
15812 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15813 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15814 {
15815#if 0
15816 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());
15817#endif
15818 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
15819
15820 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15821 if (func_symbol == NULL)
15822 {
15823 // DQ (12/3/2011): Added support for C++ member functions.
15824 // func_symbol = new SgFunctionSymbol (func);
15825 if (mfunc != NULL)
15826 {
15827 func_symbol = new SgMemberFunctionSymbol (func);
15828 }
15829 else
15830 {
15831 func_symbol = new SgFunctionSymbol (func);
15832 }
15833 ROSE_ASSERT (func_symbol != NULL);
15834
15835 scope->insert_symbol(func->get_name(), func_symbol);
15836 }
15837 else
15838 {
15839 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
15840 }
15841 }
15842#if 0
15843 // Fix local symbol, a symbol directly refer to this function declaration
15844 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
15845 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
15846 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
15847 if (local_symbol == NULL) //
15848 {
15849 if (func->get_definingDeclaration() == NULL) // prototype function
15850 {
15851 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
15852 if (func != src_func )
15853 {
15854 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
15855 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
15856 }
15857 }
15858 }
15859#endif
15860#endif
15861 }
15862 else if (isSgTemplateDeclaration(stmt) != NULL)
15863 {
15864 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
15865 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
15866 }
15867
15868#if 0
15869 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
15870 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
15871 // This this code is very dangerous.
15872
15873 // fix scope pointer for statements explicitly storing scope pointer
15874 switch (stmt->variantT())
15875 {
15876 // The case of SgLabelStatement should maybe be included.
15877 case V_SgEnumDeclaration:
15878 case V_SgTemplateDeclaration:
15879 case V_SgTypedefDeclaration:
15880 case V_SgFunctionDeclaration:
15881 case V_SgMemberFunctionDeclaration:
15882 case V_SgTemplateInstantiationFunctionDecl:
15883 {
15884 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
15885 // already been set or we can let it default to the current scope where it si located structurally.
15886 // stmt->set_scope(scope);
15887 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15888 {
15889 stmt->set_scope(scope);
15890 }
15891 break;
15892 }
15893
15894 default:
15895 {
15896 // debugging support...
15897 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15898 ROSE_ASSERT(stmt->hasExplicitScope() == false);
15899#if 0
15900 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15901 ROSE_ABORT();
15902#endif
15903 break;
15904 }
15905 }
15906#else
15907 // If the scoep has to be set and it has not yet been set, then set it directly.
15908 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
15909 {
15910 stmt->set_scope(scope);
15911 }
15912#endif
15913 }
15914
15915
15928 {
15929 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
15930 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
15931
15932 ROSE_ASSERT(func != NULL && scope != NULL);
15933
15934 ROSE_ASSERT(func != NULL);
15935 ROSE_ASSERT(scope != NULL);
15936
15937 SgStatementPtrList stmtList, sameFuncList;
15938
15939 // SgFunctionDeclaration* first_nondef = NULL;
15940 // Some annoying part of scope
15941 if (scope->containsOnlyDeclarations())
15942 {
15943 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
15944 SgDeclarationStatementPtrList::iterator i;
15945 for (i=declList.begin();i!=declList.end();i++)
15946 stmtList.push_back(*i);
15947 }
15948 else
15949 {
15950 stmtList = scope->getStatementList();
15951 }
15952
15953 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
15954 if (firstNondefiningFunctionDeclaration != NULL)
15955 {
15956 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
15957 // then use it (unless we want to handle where it might be set wrong).
15958#if 0
15959 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
15960#endif
15961 }
15962
15963 // DQ (3/12/2012): Added assertion
15964 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
15965 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
15966
15967 // 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.
15968 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
15969 {
15970 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
15971 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
15973 }
15974 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
15975
15976#if 0
15977 // It would be better to find the first non-defining declaration via the symbol.
15978 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
15979 if (functionSymbol != NULL)
15980 {
15981 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
15982 }
15983 else
15984 {
15985 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
15986 }
15987#endif
15988
15989 // Find the same function declaration list, including func itself
15990 SgStatementPtrList::iterator j;
15991 for (j = stmtList.begin(); j != stmtList.end(); j++)
15992 {
15993 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
15994 if (func_decl != NULL)
15995 {
15996 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
15997 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
15998 if (isSameFunction(func_decl, func))
15999 {
16000 // Assume all defining functions have definingdeclaration links set properly already!!
16001 sameFuncList.push_back(func_decl);
16002 }
16003 }
16004 }
16005
16006#if 0
16007 printf ("func = %p \n",func);
16008 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
16009#endif
16010
16011 ROSE_ASSERT(func != NULL);
16012
16013 if (func->get_definingDeclaration() == func)
16014 {
16015 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16016 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
16017 }
16018 else
16019 {
16020 ROSE_ASSERT(func != NULL);
16021
16022 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16023 ROSE_ASSERT(sameFuncList.empty() == false);
16024
16025 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16026 {
16027 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16028 {
16029 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16030#if 0
16031 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16032#endif
16033 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16034 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16035 if (func_decl != func)
16036 {
16037 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16038 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16039 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16040 {
16041#if 0
16042 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16043#endif
16044 func_decl->set_firstNondefiningDeclaration(func);
16045 }
16046 }
16047 }
16048 }
16049 else // is a following nondefining declaration, grab any other's first nondefining link then
16050 {
16051#if 0
16052 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16053#endif
16054 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16055 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16056 if (func->get_firstNondefiningDeclaration() == NULL)
16057 {
16058#if 0
16059 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16060#endif
16061 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16062 }
16063 }
16064 }
16065 }
16066
16067PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16068 assert(source_file != NULL);
16069 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16070
16071 SgGlobal * global_scope = source_file->get_globalScope();
16072
16073 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16074 ROSE_ASSERT(result);
16075
16076 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16077 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16078 // when multiple files are used on the command line.
16079 result->get_file_info()->setTransformation();
16080
16081 global_scope->addToAttachedPreprocessingInfo(result, position);
16082
16083 return result;
16084}
16085
16086//---------------------------------------------------------------
16088 SgLocatedNode* target, const string& content,
16089 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16090 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16091 {
16092 ASSERT_not_null(target); //dangling comment is not allowed
16093
16094 PreprocessingInfo* result = NULL;
16095 PreprocessingInfo::DirectiveType mytype=dtype;
16096 string comment;
16097
16098 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16099 // DQ (5/5/2010): infer comment type from target's language
16100 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16101 {
16102 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16103 if (is_C_language() || is_C99_language())
16104 {
16105 // Comment = "/* "+ content + " */";
16106 mytype = PreprocessingInfo::C_StyleComment;
16107 }
16108 else if (is_Cxx_language() || is_Java_language())
16109 {
16110 // Comment = "// "+ content;
16111 mytype = PreprocessingInfo::CplusplusStyleComment;
16112 }
16113 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16114 {
16115 // Comment = "! "+ content;
16116 mytype = PreprocessingInfo::F90StyleComment;
16117 }
16118 else if (is_Ada_language())
16119 {
16120 // Comment = "-- " + content;
16121 mytype = PreprocessingInfo::AdaStyleComment;
16122 }
16123 else if (is_Jovial_language())
16124 {
16125 // Comment = "% " + content + " %";
16126 mytype = PreprocessingInfo::JovialStyleComment;
16127 }
16128 else
16129 {
16130 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16131 ROSE_ABORT();
16132 }
16133 }
16134
16135 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16136 bool resetPositionInfo = false;
16137 switch (mytype)
16138 {
16139 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16140 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16141 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16142 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16143 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16144 case PreprocessingInfo::JovialStyleComment:
16145 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16146 comment = content;
16147 break;
16148 case PreprocessingInfo::CpreprocessorLineDeclaration:
16149 comment = "#myline " + content;
16150 mytype = PreprocessingInfo::CplusplusStyleComment;
16151 resetPositionInfo = true;
16152 break;
16153 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16154 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16155 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16156 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16157
16158 default:
16159 {
16160 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16161 ROSE_ABORT();
16162 }
16163 }
16164
16165 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16166
16167 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16168 if (resetPositionInfo == true)
16169 {
16170 // Call the Sg_File_Info::operator=() member function.
16171 *(result->get_file_info()) = *(target->get_file_info());
16172 }
16173 else
16174 {
16175 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16176 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16177 // when multiple files are used on the command line.
16178 result->get_file_info()->setTransformation();
16179 }
16180
16181 ASSERT_not_null(result);
16182 target->addToAttachedPreprocessingInfo(result);
16183 return result;
16184 }
16185
16186void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16187 PreprocessingInfo * if_macro = new PreprocessingInfo(
16188 PreprocessingInfo::CpreprocessorIfDeclaration,
16189 "#if " + guard,
16190 "transformation-generated", 0, 0, 0,
16191 PreprocessingInfo::before
16192 );
16193 target->addToAttachedPreprocessingInfo(if_macro);
16194
16195 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16196 PreprocessingInfo::CpreprocessorEndifDeclaration,
16197 "#endif",
16198 "transformation-generated", 0, 0, 0,
16199 PreprocessingInfo::after
16200 );
16201 target->addToAttachedPreprocessingInfo(endif_macro);
16202
16203// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16204// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16205// when multiple files are used on the command line.
16206 if_macro->get_file_info()->setTransformation();
16207 endif_macro->get_file_info()->setTransformation();
16208}
16209
16210// internal hash table to cache the results: fileHeaderDict[file][header-key]
16211// header-key:
16212// system header : <header.h>
16213// non-system headers : "header.h"
16214static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16216PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16217{
16218 string header_key;
16219 if (isSystemHeader)
16220 header_key="<"+header_file_name+">";
16221 else
16222 header_key="\""+header_file_name+"\"";
16223
16224 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16225 return fileHeaderDict[source_file][header_key];
16226
16227 vector<SgLocatedNode*> candidates;
16228 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16229 // check SgGlobal
16230 SgGlobal* global= source_file -> get_globalScope();
16231
16232 candidates.push_back(global);
16233
16234 //check declarations within the global scope
16235 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16236 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16237 candidates.push_back(*iter);
16238
16239 bool found = false;
16240 for (size_t ci=0; ci<candidates.size(); ci++)
16241 {
16242 SgLocatedNode* locatedNode= candidates[ci];
16243 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16244
16245 if (comments == NULL) continue;
16246 AttachedPreprocessingInfoType::iterator i;
16247 for (i = comments->begin (); i != comments->end (); i++)
16248 {
16249 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16250 string content = (*i)->getString ();
16251 if (content.find(header_key) != string::npos)
16252 {
16253 fileHeaderDict[source_file][header_key] = *i;
16254 found =true;
16255 break;
16256 }
16257
16258 } // each comment
16259
16260 if (found) break;
16261 } // each node
16262
16263 if (found)
16264 return fileHeaderDict[source_file][header_key];
16265 return NULL;
16266}
16267
16269SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16270 {
16271 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16272 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16273 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16274 bool supportTokenUnparsing = false;
16275
16276 assert(source_file != NULL);
16277 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16278
16279 SgGlobal * global_scope = source_file->get_globalScope();
16280
16281 string content;
16282 if (isSystemHeader)
16283 content = "#include <" + header_file_name + "> \n";
16284 else
16285 content = "#include \"" + header_file_name + "\" \n";
16286
16287 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16288 ROSE_ASSERT(result);
16289
16290 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16291 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16292 // when multiple files are used on the command line.
16293 result->get_file_info()->setTransformation();
16294
16295 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16296 supportTokenUnparsing = source_file->get_unparse_tokens();
16297 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16298
16299#if 0
16300 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16301 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16302 printf ("source_file = %p \n",source_file);
16303 printf ("global_scope = %p \n",global_scope);
16304#endif
16305#if 0
16306 printf ("Exiting as a test! \n");
16307 ROSE_ABORT();
16308#endif
16309
16310 // global_scope->addToAttachedPreprocessingInfo(result, position);
16311 if (supportTokenUnparsing == false)
16312 {
16313 global_scope->addToAttachedPreprocessingInfo(result, position);
16314 }
16315 else
16316 {
16317 // global_scope->prepend_statement(null_statement);
16318 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16319
16320 if (supportUnparseHeaders == true)
16321 {
16322 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16323 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16324#if 0
16325 printf ("physical_file_id = %d \n",physical_file_id);
16326#endif
16327 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16328 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16329#if 0
16330 printf ("Exiting as a test! \n");
16331 ROSE_ABORT();
16332#endif
16333 }
16334
16335 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16336
16337 global_scope->prepend_statement(emptyDeclaration);
16338 }
16339
16340#if 0
16341 printf ("Exiting as a test! \n");
16342 ROSE_ASSERT(false);
16343#endif
16344
16345 return result;
16346 }
16347
16348PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16349 {
16350 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16351 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16352 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16353 bool supportTokenUnparsing = false;
16354
16355 // DQ (8/12/2020): This is a compiler warning.
16356 // bool successful = false;
16357
16358#if 0
16359 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16360 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16361#endif
16362
16363 if (scope == NULL)
16365
16366 ROSE_ASSERT(scope);
16367
16368 SgGlobal* globalScope = getGlobalScope(scope);
16369 ROSE_ASSERT(globalScope != NULL);
16370
16371 // 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
16372 // if the input scope is within a header file,
16373 // its global scope will jump to a .cpp file. Later looping will not find a match.
16374 SgScopeStatement* srcScope = globalScope;
16375 PreprocessingInfo* result=NULL;
16376 string content;
16377 if (isSystemHeader)
16378 content = "#include <" + filename + "> \n";
16379 else
16380 content = "#include \"" + filename + "\" \n";
16381
16382 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16383 // whitespace around the statement has been modified. This will trigger the unparser to output
16384 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16385 // file requires this support else the original token stream will not have the added header file.
16386
16387 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16388 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16389 ROSE_ASSERT(sourceFile != NULL);
16390
16391 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16392
16393 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16394 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16395 if (supportUnparseHeaders)
16396 {
16397 string filename= scope->get_file_info()->get_filename();
16398 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16399
16400 // vector.tcc: This is an internal header file, included by other library headers
16401 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16402 srcScope = scope;
16403 }
16404
16405#if 0
16406 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16407 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16408 printf ("sourceFile = %p \n",sourceFile);
16409 printf ("globalScope = %p \n",globalScope);
16410#endif
16411#if 0
16412 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16413#endif
16414#if 0
16415 printf ("Exiting as a test! \n");
16416 ROSE_ABORT();
16417#endif
16418
16419 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16420
16421#if 0
16422 printf ("stmtList.size() = %zu \n",stmtList.size());
16423#endif
16424
16425 if (stmtList.size() > 0) // the source file is not empty
16426 {
16427 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16428 {
16429 // must have this judgement, otherwise wrong file will be modified!
16430 // It could also be the transformation generated statements with #include attached
16431 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16432 {
16433 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16434 ROSE_ASSERT(result != NULL);
16435#if 0
16436 printf ("Building a PreprocessingInfo: result = %p \n",result);
16437#endif
16438 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16439 // add to the last position
16440 // TODO: support to add to the first,
16441 // TODO: support fine positioning with #include directives
16442 // (*j)->addToAttachedPreprocessingInfo(result,position);
16443
16444 if (supportTokenUnparsing == false)
16445 {
16446 (*j)->addToAttachedPreprocessingInfo(result,position);
16447 }
16448 else
16449 {
16450 (*j)->addToAttachedPreprocessingInfo(result,position);
16451#if 0
16452 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16453#endif
16454#if 1
16455 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16456 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16457#endif
16458#if 0
16459 SgDeclarationStatement* declarationStatement = *j;
16460
16461 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16462 // from the token stream and makrs some token stream elements as already unparsed.
16463 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16464 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16465 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16466 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16467 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16468#endif
16469#if 0
16470 // Liao, let's try the new way.
16471 // global_scope->prepend_statement(null_statement);
16472 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16473
16474 if (supportUnparseHeaders == true)
16475 {
16476 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16477 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16478#if 0
16479 printf ("physical_file_id = %d \n",physical_file_id);
16480#endif
16481 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16482 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16483#if 0
16484 printf ("Exiting as a test! \n");
16485 ROSE_ASSERT(false);
16486#endif
16487 }
16488
16489 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16490
16491 globalScope->insert_statement(*j,emptyDeclaration);
16492#endif
16493 }
16494#if 0
16495 printf ("break out of for loop: result = %p \n",result);
16496#endif
16497 // DQ (8/12/2020): This is a compiler warning.
16498 // successful = true;
16499 break;
16500 }
16501 }
16502 }
16503 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16504 {
16505 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16506 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16507 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16508 ROSE_ASSERT(false);
16509 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16510 ROSE_ASSERT(result);
16511 globalScope->addToAttachedPreprocessingInfo(result,position);
16512
16513 // DQ (8/12/2020): This is a compiler warning.
16514 // successful = true;
16515 }
16516
16517 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16518 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16519 // when multiple files are used on the command line.
16520 // DQ (3/12/2019): This can be NULL for the omp tests.
16521 if (result != NULL)
16522 {
16523 result->get_file_info()->setTransformation();
16524 }
16525
16526 // must be inserted once somehow
16527 // 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
16528 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16529 // ROSE_ASSERT(successful==true);
16530
16531#if 0
16532 printf ("Exiting as a test! \n");
16533 ROSE_ASSERT(false);
16534#endif
16535
16536#if 0
16537 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16538#endif
16539
16540#if 0
16541 printf ("Exiting as a test! \n");
16542 ROSE_ASSERT(false);
16543#endif
16544
16545 return result;
16546 }
16547
16548
16549// 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
16550void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16551{
16552 ROSE_ASSERT (stmt != NULL);
16553 ROSE_ASSERT (newheader != NULL);
16554
16555#if 0
16556 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16557#endif
16558
16560
16561 if (asLastHeader )
16562 position = PreprocessingInfo::after;
16563 else
16564 position = PreprocessingInfo::before;
16565
16566
16567 // Find existing first and last header.
16568 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16569
16570 if (comments != NULL)
16571 {
16572 PreprocessingInfo * firstExistingHeader = NULL;
16573 PreprocessingInfo * lastExistingHeader = NULL;
16574 PreprocessingInfo * firstExistingEndif = NULL;
16575
16576 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16577 // PreprocessingInfo * lastExistingEndif = NULL;
16578
16579 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16580 for (i = comments->begin (); i != comments->end (); i++)
16581 {
16582 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16583 // #ifdef #endif the added include directive might not be visible in the generated file.
16584 // This actually happened in the case of wget application: wget.c source file.
16585#if 0
16586 // Original version of code.
16587 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16588 {
16589 // Only set first header for the first time
16590 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16591 {
16592 if (firstExistingHeader == NULL)
16593 {
16594 firstExistingHeader = (*i);
16595 firsti = i;
16596 }
16597 // always updates last header
16598 lastExistingHeader = (*i);
16599 lasti = i;
16600 }
16601 }
16602#else
16603 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16604 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16605 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16606 {
16607 // Only set first header for the first time
16608 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16609 {
16610 if (firstExistingHeader == NULL)
16611 {
16612 firstExistingHeader = (*i);
16613 firsti = i;
16614 }
16615 // always updates last header
16616 lastExistingHeader = (*i);
16617 lasti = i;
16618 }
16619 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16620 {
16621 if (firstExistingEndif == NULL)
16622 {
16623 firstExistingEndif = (*i);
16624 firsti = i;
16625 }
16626 // always updates last header
16627 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16628 // lastExistingEndif = (*i);
16629 lasti = i;
16630 }
16631 }
16632#endif
16633 }
16634
16635 // based on existing header positions, insert the new header
16636 if (asLastHeader)
16637 {
16638 if (lastExistingHeader == NULL) // No last header at all, just append to after
16639 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16640 else
16641 {
16642 comments->insert (lasti+1, newheader);
16643 }
16644 }
16645 else // add as the first header
16646 {
16647 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16648 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16649 else
16650 {
16651 comments->insert (firsti, newheader);
16652 }
16653 }
16654 }
16655 else // No comments at all, first and last header mean the same, just attach to the located node
16656 stmt->addToAttachedPreprocessingInfo(newheader, position);
16657
16658#if 0
16659 printf ("Exiting as a test! \n");
16660 ROSE_ASSERT(false);
16661#endif
16662
16663}
16664
16665
16666// The recommended version
16667PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16668{
16669 ROSE_ASSERT (source_file != NULL);
16670 SgGlobal* globalScope = source_file->get_globalScope();
16671 ROSE_ASSERT (globalScope != NULL);
16672
16673 PreprocessingInfo* result=NULL;
16674 string content;
16675 if (isSystemHeader)
16676 content = "#include <" + filename + "> \n";
16677 else
16678 content = "#include \"" + filename + "\" \n";
16679
16680#if 0
16681 // 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.
16683
16684 if (asLastHeader )
16685 position = PreprocessingInfo::after;
16686 else
16687 position = PreprocessingInfo::before;
16688#endif
16689
16690 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16691 if (stmtList.size()>0) // the source file is not empty
16692 {
16693 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16694 {
16695 // Attach to the first eligible located statement
16696 //must have this judgement, otherwise wrong file will be modified!
16697 //It could also be the transformation generated statements with #include attached
16698 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16699 {
16700#if 0
16701 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16702 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16703#endif
16704 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16705 ROSE_ASSERT(result);
16706 insertHeader (*j, result, asLastHeader);
16707 //successful = true;
16708#if 0
16709 printf ("Exiting as a test! \n");
16710 ROSE_ABORT();
16711#endif
16712 break;
16713 }
16714 } // end for
16715 }
16716 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16717 {
16718 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16719 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16720 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16721 ROSE_ABORT();
16722#if 0 // [Robb Matzke 2021-03-24]: unreachable
16723 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16724 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16725 ROSE_ASSERT(result);
16726 globalScope->addToAttachedPreprocessingInfo(result,position);
16727#endif
16728 // successful = true;
16729 }
16730
16731#if 0
16732 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16733#endif
16734
16735 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16736 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16737 // when multiple files are used on the command line.
16738 if (result)
16739 result->get_file_info()->setTransformation();
16740
16741#if 0
16742 printf ("Exiting as a test! \n");
16743 ROSE_ASSERT(false);
16744#endif
16745
16746 // must be inserted once somehow
16747 // 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
16748 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16749 // ROSE_ASSERT(successful==true);
16750 return result;
16751
16752} // end insertHeader
16753
16754
16757SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16758 {
16759 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16760
16761 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16762 PreprocessingInfo* result = NULL;
16763
16764 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16765 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16766 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16767 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16768 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16769
16770 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
16771 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
16772
16773 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
16774 ROSE_ASSERT(result);
16775
16776 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16777 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16778 // when multiple files are used on the command line.
16779 result->get_file_info()->setTransformation();
16780
16781 target->addToAttachedPreprocessingInfo(result);
16782
16783 return result;
16784 }
16785
16786
16788// 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.
16790{
16791 // This is part of Wave support in ROSE.
16792// #if CAN_NOT_COMPILE_WITH_ROSE != true
16793// #if CAN_NOT_COMPILE_WITH_ROSE == 0
16794#ifndef USE_ROSE
16795 ROSE_ASSERT(target != NULL);
16796 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
16797 if (info == NULL) return;
16798 AttachedPreprocessingInfoType::iterator j;
16799 for (j = info->begin (); j != info->end (); j++)
16800 {
16801 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
16802 {
16803#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
16804 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
16805 std::ostringstream os;
16806 token_container tc = (*j)->get_macro_call()->expanded_macro;
16807 token_container::const_iterator iter;
16808 for (iter=tc.begin(); iter!=tc.end(); iter++)
16809 os<<(*iter).get_value();
16810 //cout<<"Found a macro call: "<<(*j)->getString()<<
16811 //"\nexpanding it to: "<<os.str()<<endl;
16812 string pragmaText = target->get_pragma()->get_pragma();
16813 string targetString = (*j)->getString();
16814 string replacement = os.str();
16815 // repeat until not found
16816 size_t pos1 = pragmaText.find(targetString);
16817 while (pos1 != string::npos)
16818 {
16819 pragmaText.replace(pos1, targetString.size(), replacement);
16820 pos1 = pragmaText.find(targetString);
16821 }
16822 delete target->get_pragma();
16823 target->set_pragma(buildPragma(pragmaText));
16824#endif
16825 } // end if
16826 } // end for
16827#endif
16828}
16829
16834 using namespace SageBuilder;
16835 SgStatement* body = NULL;
16836 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
16837 isSgForStatement(loopOrSwitch)) {
16838 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
16839 } else if (isSgSwitchStatement(loopOrSwitch)) {
16840 body = isSgSwitchStatement(loopOrSwitch)->get_body();
16841 }
16842 ROSE_ASSERT (body);
16843 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
16844 if (!breaks.empty()) {
16845 static int breakLabelCounter = 0;
16846 SgLabelStatement* breakLabel =
16847 buildLabelStatement("breakLabel" +
16848StringUtility::numberToString(++breakLabelCounter),
16850 isSgScopeStatement(loopOrSwitch->get_parent()));
16851 insertStatement(loopOrSwitch, breakLabel, false);
16852 for (size_t j = 0; j < breaks.size(); ++j) {
16853 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
16854
16855 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
16856 newGoto);
16857 newGoto->set_parent(breaks[j]->get_parent());
16858 }
16859 }
16860 }
16861
16863 {
16864 ROSE_ASSERT(node!=NULL);
16865 SgClassDeclaration *decl = isSgClassDeclaration(node);
16866 if (decl==NULL)
16867 return false;
16868 else
16869 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
16870 }
16871
16873 {
16874 ROSE_ASSERT(node!=NULL);
16875 SgClassDeclaration *decl = isSgClassDeclaration(node);
16876 if (decl==NULL)
16877 return false;
16878 else
16879 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
16880 }
16881
16882
16883void
16884SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
16885 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
16886 {
16887 ROSE_ASSERT(stmt_src != NULL);
16888 ROSE_ASSERT(stmt_dst != NULL);
16889 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
16890
16891 if (infoList == NULL)
16892 {
16893#if 0
16894 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
16895#endif
16896 return;
16897 }
16898
16899 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
16900
16901#if 0
16902 printf ("In SageInterface::movePreprocessingInfo(): \n");
16903 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
16904 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
16905 if (src_declarationStatement != NULL)
16906 {
16907 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
16908 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
16909 }
16910 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
16911 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
16912 if (dst_declarationStatement != NULL)
16913 {
16914 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
16915 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
16916 }
16917 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
16918 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
16919 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
16920
16921 printf (" --- infoList = %p \n",infoList);
16922 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
16923
16924 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
16925 printf (" --- dst_infoList = %p \n",dst_infoList);
16926#endif
16927#if 0
16928 printf ("****************************************************************** \n");
16929 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
16931 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
16933 printf ("****************************************************************** \n");
16934#endif
16935
16936 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
16937 // This is a bug in the support for building a new prototype from a defining function declaration
16938 // and caused this problem. This assertion will prevent this sort of error from happening again.
16939 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
16940
16941
16942#if 0
16943 printf (" --- infoList->size() = %zu \n",infoList->size());
16944 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
16945#endif
16946
16947#if 0
16948 int counter = 0;
16949
16950 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16951 {
16952 // DQ (11/19/2020): Added assertion.
16953 ROSE_ASSERT(*i != NULL);
16954
16955 // DQ (11/19/2020): Why do we have a dynamic cast here.
16956 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
16957 PreprocessingInfo * info = *i;
16958 ROSE_ASSERT(info != NULL);
16959
16960 // printf ("counter = %d \n",counter);
16961 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
16962 counter++;
16963 }
16964
16965 counter = 0;
16966#endif
16967
16968 PreprocessingInfo* prevItem = NULL;
16969
16970 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
16971 {
16972 ROSE_ASSERT(*i != NULL);
16973
16974 PreprocessingInfo * info = *i;
16975 ROSE_ASSERT(info != NULL);
16976
16977 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
16978 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
16979 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
16980 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
16981 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
16982 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
16983 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
16984 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
16985 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
16986 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
16987 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
16988 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
16989 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
16990 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
16991 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
16992 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
16993 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
16994 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
16995 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
16996 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
16997 // DQ (12/28/2020): Added support for C linkage specifications.
16998 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
16999 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
17000 )
17001 {
17002 // move all source preprocessing info if the desired source type is not specified or matching
17003 // a specified desired source type
17004 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
17005 {
17006 if (usePrepend == true)
17007 {
17008 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
17009 if (prevItem == NULL)
17010 {
17011 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
17012 // to indicate appending or prepending by reusing the type of relative position.
17013 // this is very confusing for users
17014 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
17015 }
17016 else // there is a previous item, insert after it
17017 {
17018 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
17019 }
17020 prevItem = info;
17021 }
17022 else
17023 {
17024 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17025 }
17026 // 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.
17027 info->setAsTransformation();
17028
17029 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17030 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17031 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17032 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17033 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17034 bool isMarkedAsModified = stmt_dst->get_isModified();
17035 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17036 if (isMarkedAsModified == false)
17037 {
17038 if (stmt_dst->get_isModified() == true)
17039 {
17040 stmt_dst->set_isModified(false);
17041 }
17042 }
17043 (*infoToRemoveList).push_back(*i);
17044 }
17045
17046 // adjust dst position if needed
17047 if (dst_position != PreprocessingInfo::undef)
17048 {
17049 info->setRelativePosition(dst_position);
17050 }
17051 } // end if
17052 } // end for
17053
17054 // Remove the element from the list of comments at the current astNode
17055 AttachedPreprocessingInfoType::iterator j;
17056 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17057 {
17058 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17059 }
17060 }
17061
17062
17063//----------------------------
17064// Sometimes, the preprocessing info attached to a declaration has to be
17065// moved 'up' if another declaration is inserted before it.
17066// This is a workaround for the broken LowLevelRewrite::insert() and the private
17067// LowLevelRewrite::reassociatePreprocessorDeclarations()
17068//
17069// input:
17070// *stmt_dst: the new inserted declaration
17071// *stmt_src: the existing declaration with preprocessing information
17072// tasks:
17073// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17074// add them into stmt_dst
17075// delete them from stmt_dst
17076// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17077// LoweLevel::remove(stmt_src)
17079 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17080 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17081 bool usePrepend /*= false */)
17082 {
17083 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17084 } // moveUpPreprocessingInfo()
17085
17086
17091static bool isNotRelPos (const PreprocessingInfo* info,
17093{
17094 return info && (info->getRelativePosition () != pos);
17095}
17096
17101static bool isRelPos (const PreprocessingInfo* info,
17103{
17104 return info && !isNotRelPos (info, pos);
17105}
17106
17107
17109void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17110{
17111 ASSERT_not_null(src_node);
17112
17113 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17114 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17115 if (info)
17116 {
17117 // copy elements to save_buf where isRelPos() is false
17118 remove_copy_if(info->begin(),
17119 info->end(),
17120 back_inserter(save_buf),
17121 [pos](auto x) { return !isRelPos(x, pos); }
17122 );
17123
17124 // delete copied elements from save_buf
17125 AttachedPreprocessingInfoType::iterator
17126 new_end = remove_if(info->begin(),
17127 info->end(),
17128 [pos](auto x) { return isRelPos(x, pos); }
17129 );
17130 info->erase(new_end, info->end());
17131 }
17132}
17133
17134static AttachedPreprocessingInfoType *
17135createInfoList (SgLocatedNode* s)
17136{
17137 ROSE_ASSERT (s);
17138 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17139 if (!info_list)
17140 {
17141 info_list = new AttachedPreprocessingInfoType;
17142 ROSE_ASSERT (info_list);
17143 s->set_attachedPreprocessingInfoPtr (info_list);
17144 }
17145
17146 // Guarantee a non-NULL pointer.
17147 ROSE_ASSERT (info_list);
17148 return info_list;
17149}
17150
17152void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17153{
17154 if (save_buf.size()==0) return;
17155 // if front
17156 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17157 ROSE_ASSERT (info);
17158
17159 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17160 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17161 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17162
17163 // Liao (10/3/2007), vectors can only be appended at the rear
17164 if (pos==PreprocessingInfo::before)
17165 {
17166 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17167 info->insert(info->begin(),*i);
17168 }
17169 // if back
17170 else if (pos==PreprocessingInfo::after)
17171 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17172 else if (pos==PreprocessingInfo::inside)
17173 {
17174 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17175 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17176 save_buf[0]->display("ttt");
17177 }
17178}
17179
17181{
17182 ROSE_ASSERT(locatedNode != NULL);
17183 AttachedPreprocessingInfoType *comments =
17184 locatedNode->getAttachedPreprocessingInfo ();
17185
17186 if (comments != NULL)
17187 {
17188 printf ("-----------------------------------------------\n");
17189 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17190 locatedNode, locatedNode->class_name ().c_str (),
17191 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17192 int counter = 0;
17193 AttachedPreprocessingInfoType::iterator i;
17194 for (i = comments->begin (); i != comments->end (); i++)
17195 {
17196 printf
17197 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17198 counter++,
17199 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17200 c_str (), (*i)->getString ().c_str ());
17201 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17202 printf ("relative position is: inside\n");
17203 else
17204 printf ("relative position is: %s\n", \
17205 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17206 }
17207 }
17208 else
17209 {
17210 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17211 locatedNode->sage_class_name ());
17212 }
17213}
17214
17226template <class ParentNode>
17227static
17228SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17229 SgStatement* (ParentNode::*getter) () const,
17230 void (ParentNode::*setter) (SgStatement*)
17231 )
17232{
17233 SgStatement* const body_stmt = (stmt.*getter)();
17234 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17235
17236 if (basicblock == NULL) {
17237 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17238 (stmt.*setter)(basicblock);
17239 basicblock->set_parent(&stmt);
17240 }
17241
17242 ROSE_ASSERT (basicblock != NULL);
17243 return basicblock;
17244}
17245
17247{
17248 SgStatement* b = fs->get_loop_body();
17249 if (!isSgBasicBlock(b)) {
17251 fs->set_loop_body(b);
17252 b->set_parent(fs);
17253
17254 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17256 }
17257 ROSE_ASSERT (isSgBasicBlock(b));
17258 return isSgBasicBlock(b);
17259}
17260
17262{
17263 SgStatement* b = cs->get_body();
17264 if (!isSgBasicBlock(b)) {
17266 cs->set_body(b);
17267 b->set_parent(cs);
17268
17269 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17271 }
17272 ROSE_ASSERT (isSgBasicBlock(b));
17273 return isSgBasicBlock(b);
17274}
17275
17277{
17278 SgStatement* b = cs->get_body();
17279 if (!isSgBasicBlock(b)) {
17281 cs->set_body(b);
17282 b->set_parent(cs);
17283
17284 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17286 }
17287 ROSE_ASSERT (isSgBasicBlock(b));
17288 return isSgBasicBlock(b);
17289}
17290
17292{
17293 ROSE_ASSERT (fs != NULL);
17294
17295 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17296}
17297
17299 SgStatement* b = fs->get_body();
17300 if (!isSgBasicBlock(b)) {
17302 fs->set_body(b);
17303 b->set_parent(fs);
17304
17305 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17307 }
17308 ROSE_ASSERT (isSgBasicBlock(b));
17309 return isSgBasicBlock(b);
17310 }
17311
17313 SgStatement* b = fs->get_body();
17314 if (!isSgBasicBlock(b)) {
17316 fs->set_body(b);
17317 b->set_parent(fs);
17318
17319 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17321 }
17322 ROSE_ASSERT (isSgBasicBlock(b));
17323 return isSgBasicBlock(b);
17324 }
17325
17327 SgStatement* b = fs->get_body();
17328 if (!isSgBasicBlock(b)) {
17330 fs->set_body(b);
17331 b->set_parent(fs);
17332
17333 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17335 }
17336 ROSE_ASSERT (isSgBasicBlock(b));
17337 return isSgBasicBlock(b);
17338 }
17339
17341 SgStatement* b = fs->get_true_body();
17342 if (!isSgBasicBlock(b)) {
17344 fs->set_true_body(b);
17345 b->set_parent(fs);
17346
17347 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17349#if 0
17350 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17351#endif
17352 }
17353 ROSE_ASSERT (isSgBasicBlock(b));
17354 return isSgBasicBlock(b);
17355 }
17356
17357// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17359 {
17360 // Record where normalization have been done so that we can preform denormalizations as required
17361 // for the token-based unparsing to generate minimal diffs.
17362
17363 SgBasicBlock* bb = isSgBasicBlock(s);
17364 ROSE_ASSERT(bb != NULL);
17365 addedBasicBlockNodes.push_back(bb);
17366#if 0
17367 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17368#endif
17369 }
17370
17371// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17373 {
17374 // Remove unused basic block IR nodes added as part of normalization.
17375 // This function should be called before the unparse step.
17376
17377#if 0
17378 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17379#endif
17380
17381 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17382 {
17383 SgBasicBlock* b = *i;
17384 ROSE_ASSERT(b != NULL);
17385 if (b->get_statements().size() == 1)
17386 {
17387#if 0
17388 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17389#endif
17390 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17391 ROSE_ASSERT(parentOfBlock != NULL);
17392
17393 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17394
17395 SgStatement* s = b->get_statements()[0];
17396 ROSE_ASSERT(s != NULL);
17397
17398 switch (parentOfBlock->variantT())
17399 {
17400 case V_SgIfStmt:
17401 {
17402 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17403 if (b == ifStatement->get_true_body())
17404 {
17405#if 0
17406 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17407#endif
17408 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17409 ifStatement->set_true_body(s);
17410#if 0
17411 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17412#endif
17413 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17414 s->set_parent(ifStatement);
17415#if 0
17416 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17417#endif
17418 *i = NULL;
17419 // delete b;
17420 }
17421 else
17422 {
17423 ROSE_ASSERT(b == ifStatement->get_false_body());
17424#if 0
17425 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17426#endif
17427 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17428 ifStatement->set_false_body(s);
17429#if 0
17430 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17431#endif
17432 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17433 s->set_parent(ifStatement);
17434#if 0
17435 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17436#endif
17437 *i = nullptr;
17438#if 0
17439 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17440#endif
17441#if 0
17442 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17443 ROSE_ABORT();
17444#endif
17445 }
17446 break;
17447 }
17448
17449 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17450 case V_SgWhileStmt:
17451 {
17452 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17453 if (b == whileStatement->get_body())
17454 {
17455 whileStatement->set_body(s);
17456 s->set_parent(whileStatement);
17457 }
17458 break;
17459 }
17460
17461 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17462 case V_SgSwitchStatement:
17463 {
17464 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17465 if (b == switchStatement->get_body())
17466 {
17467 switchStatement->set_body(s);
17468 s->set_parent(switchStatement);
17469 }
17470 break;
17471 }
17472
17473 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17474 case V_SgForStatement:
17475 {
17476 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17477 if (b == forStatement->get_loop_body())
17478 {
17479 forStatement->set_loop_body(s);
17480 s->set_parent(forStatement);
17481 }
17482 break;
17483 }
17484
17485 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17486 case V_SgCaseOptionStmt:
17487 {
17488 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17489 if (b == caseOptionStatement->get_body())
17490 {
17491 caseOptionStatement->set_body(s);
17492 s->set_parent(caseOptionStatement);
17493 }
17494 break;
17495 }
17496
17497 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17498 case V_SgDefaultOptionStmt:
17499 {
17500 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17501 if (b == defaultOptionStatement->get_body())
17502 {
17503 defaultOptionStatement->set_body(s);
17504 s->set_parent(defaultOptionStatement);
17505 }
17506 break;
17507 }
17508
17509 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17510 case V_SgDoWhileStmt:
17511 {
17512 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17513 if (b == doWhileStatement->get_body())
17514 {
17515 doWhileStatement->set_body(s);
17516 s->set_parent(doWhileStatement);
17517 }
17518 break;
17519 }
17520
17521 default:
17522 {
17523 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17524 ROSE_ABORT();
17525 }
17526 }
17527
17528 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17529 if (wasPreviouslyModified == false)
17530 {
17531 if (parentOfBlock->get_isModified() == true)
17532 {
17533#if 0
17534 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());
17535#endif
17536 parentOfBlock->set_isModified(false);
17537 }
17538
17539 }
17540#if 0
17541 printf ("Exiting as a test! \n");
17542 ROSE_ABORT();
17543#endif
17544 }
17545 }
17546
17547#if 0
17548 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17549#endif
17550 }
17551
17552
17554 SgStatement* b = fs->get_false_body();
17555 // if no false body at all AND no-create-empty-body
17556 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17557 return NULL;
17558 if (!isSgBasicBlock(b)) {
17559 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17560 fs->set_false_body(b);
17561 b->set_parent(fs);
17562
17563 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17565 }
17566 ROSE_ASSERT (isSgBasicBlock(b));
17567 return isSgBasicBlock(b);
17568 }
17569
17571 SgStatement* b = fs->get_body();
17572 if (!isSgBasicBlock(b)) {
17574 fs->set_body(b);
17575 b->set_parent(fs);
17576 }
17577 ROSE_ASSERT (isSgBasicBlock(b));
17578 return isSgBasicBlock(b);
17579 }
17580
17582{
17583 SgStatement* b = fs->get_body();
17584 if (!isSgBasicBlock(b)) {
17586 fs->set_body(b);
17587 b->set_parent(fs);
17588 }
17589 ROSE_ASSERT (isSgBasicBlock(b));
17590 return isSgBasicBlock(b);
17591}
17592
17594{
17595 bool rt = false;
17596 ROSE_ASSERT(s);
17597 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17598 ROSE_ASSERT(p);
17599
17600 switch (p->variantT())
17601 {
17602 case V_SgForStatement:
17603 {
17604 if (isSgForStatement(p)->get_loop_body() == s)
17605 rt = true;
17606 break;
17607 }
17608 case V_SgUpcForAllStatement: // PP
17609 {
17610 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17611 if (upcforall.get_loop_body() == s)
17612 rt = true;
17613 break;
17614 }
17615 case V_SgWhileStmt:
17616 {
17617 if (isSgWhileStmt(p)->get_body() == s)
17618 rt = true;
17619 break;
17620 }
17621 case V_SgDoWhileStmt:
17622 {
17623 if (isSgDoWhileStmt(p)->get_body() == s)
17624 rt = true;
17625 break;
17626 }
17627 case V_SgSwitchStatement:
17628 {
17629 if (isSgSwitchStatement(p)->get_body() == s)
17630 rt = true;
17631 break;
17632 }
17633 case V_SgCaseOptionStmt:
17634 {
17635 if (isSgCaseOptionStmt(p)->get_body() == s)
17636 rt = true;
17637 break;
17638 }
17639 case V_SgDefaultOptionStmt:
17640 {
17641 if (isSgDefaultOptionStmt(p)->get_body() == s)
17642 rt = true;
17643 break;
17644 }
17645 case V_SgCatchOptionStmt:
17646 {
17647 if (isSgCatchOptionStmt(p)->get_body() == s)
17648 rt = true;
17649 break;
17650 }
17651 case V_SgIfStmt:
17652 {
17653 if (isSgIfStmt(p)->get_true_body() == s)
17654 rt = true;
17655 else if (isSgIfStmt(p)->get_false_body() == s)
17656 rt = true;
17657 break;
17658 }
17659 default:
17660 {
17661 if (isSgOmpBodyStatement(p))
17662 rt = true;
17663 break;
17664 }
17665 }
17666 return rt;
17667}
17668
17670//etc.
17672{
17673 ROSE_ASSERT (singleStmt != NULL); // not NULL
17674 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17675 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17676
17677 SgBasicBlock* rt = NULL;
17678
17679
17680
17681 SgStatement* s = singleStmt;
17682 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17683 ROSE_ASSERT(p);
17684 switch (p->variantT())
17685 {
17686 case V_SgForStatement:
17687 {
17688 if (isSgForStatement(p)->get_loop_body() == s)
17689 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17690 break;
17691 }
17692 case V_SgUpcForAllStatement: // PP
17693 {
17694 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17695
17696 if (upcforall.get_loop_body() == s)
17697 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17698 break;
17699 }
17700 case V_SgWhileStmt:
17701 {
17702 if (isSgWhileStmt(p)->get_body() == s)
17703 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17704 break;
17705 }
17706 case V_SgDoWhileStmt:
17707 {
17708 if (isSgDoWhileStmt(p)->get_body() == s)
17709 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17710 break;
17711 }
17712 case V_SgSwitchStatement:
17713 {
17714 if (isSgSwitchStatement(p)->get_body() == s)
17715 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17716 break;
17717 }
17718 case V_SgCaseOptionStmt:
17719 {
17720 if (isSgCaseOptionStmt(p)->get_body() == s)
17721 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17722 break;
17723 }
17724 case V_SgDefaultOptionStmt:
17725 {
17726 if (isSgDefaultOptionStmt(p)->get_body() == s)
17727 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17728 break;
17729 }
17730 case V_SgCatchOptionStmt:
17731 {
17732 if (isSgCatchOptionStmt(p)->get_body() == s)
17733 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17734 break;
17735 }
17736 case V_SgIfStmt:
17737 {
17738 if (isSgIfStmt(p)->get_true_body() == s)
17739 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17740 else if (isSgIfStmt(p)->get_false_body() == s)
17741 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17742 break;
17743 }
17744 default:
17745 {
17746 if (isSgOmpBodyStatement(p))
17747 {
17748 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17749 }
17750 break;
17751 }
17752 }
17753 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.
17754 return rt;
17755}
17756
17757#if 0
17758SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17759{
17760 ROSE_ASSERT(s);
17761
17762 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17763 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17764 ROSE_ASSERT(p);
17765 switch (p->variantT())
17766 {
17767 case V_SgBasicBlock: return isSgBasicBlock(p);
17768 case V_SgForStatement:
17769 {
17770 if (isSgForStatement(p)->get_loop_body() == s)
17771 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17772 else if (isSgForStatement(p)->get_test() == s)
17773 {
17774 }
17775 else if (isSgForStatement(p)->get_for_init_stmt() == s)
17776 {
17777 }
17778 else ROSE_ABORT();
17779 break;
17780 }
17781 case V_SgUpcForAllStatement: // PP
17782 {
17783 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17784
17785 if (upcforall.get_loop_body() == s)
17786 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17787
17788 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
17789 || (s == upcforall.get_test())
17790 );
17791 break;
17792 }
17793 case V_SgWhileStmt:
17794 {
17795 if (isSgWhileStmt(p)->get_body() == s)
17796 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17797 else if (isSgWhileStmt(p)->get_condition() == s)
17798 {
17799 }
17800 else ROSE_ABORT();
17801 break;
17802 }
17803 case V_SgDoWhileStmt:
17804 {
17805 if (isSgDoWhileStmt(p)->get_body() == s)
17806 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17807 else if (isSgDoWhileStmt(p)->get_condition() == s)
17808 {
17809 }
17810 else ROSE_ABORT();
17811 break;
17812 }
17813 case V_SgSwitchStatement:
17814 {
17815 if (isSgSwitchStatement(p)->get_body() == s)
17816 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17817 else if (isSgSwitchStatement(p)->get_item_selector() == s)
17818 {
17819 }
17820 else ROSE_ABORT();
17821 break;
17822 }
17823 case V_SgCatchOptionStmt:
17824 {
17825 if (isSgCatchOptionStmt(p)->get_body() == s)
17826 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17827 else if (isSgCatchOptionStmt(p)->get_condition() == s)
17828 {
17829 }
17830 else ROSE_ABORT();
17831 break;
17832 }
17833 case V_SgIfStmt:
17834 {
17835 if (isSgIfStmt(p)->get_true_body() == s)
17836 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17837 else if (isSgIfStmt(p)->get_false_body() == s)
17838 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17839 else if (isSgIfStmt(p)->get_conditional() == s)
17840 {
17841 }
17842 else ROSE_ABORT();
17843 break;
17844 }
17845 default:
17846 {
17847 if (isSgOmpBodyStatement(p))
17848 {
17849 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17850 }
17851 else
17852 // Liao, 7/3/2008 We allow other conditions to fall through,
17853 // they are legal parents with list of statements as children.
17854 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
17855 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
17856 break;
17857 }
17858 }
17859 return p;
17860}
17861
17862 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
17863 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
17864 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
17866 }
17867
17868#endif
17869 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
17870 class Visitor: public AstSimpleProcessing {
17871 public:
17872 bool allowEmptyBody;
17873 Visitor (bool flag):allowEmptyBody(flag) {}
17874 virtual void visit(SgNode* n) {
17875
17876 bool wasPreviouslyModified = n->get_isModified();
17877
17878 switch (n->variantT()) {
17879 case V_SgForStatement: {
17880 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
17881 break;
17882 }
17883 case V_SgWhileStmt: {
17884 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
17885 break;
17886 }
17887 case V_SgDoWhileStmt: {
17888 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
17889 break;
17890 }
17891 case V_SgSwitchStatement: {
17892 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
17893 break;
17894 }
17895 case V_SgIfStmt: {
17896 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
17897 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
17898#if 0
17899 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
17900 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17901#endif
17902#if 0
17903 // Reset this to false as a test.
17904 if (n->get_isModified() == true)
17905 {
17906 n->set_isModified(false);
17907 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
17908 }
17909#endif
17910 break;
17911 }
17912 case V_SgCatchOptionStmt: {
17913 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
17914 break;
17915 }
17916 case V_SgUpcForAllStatement: {
17917 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
17918 break;
17919 }
17920
17921 default:
17922 {
17923 if (isSgOmpBodyStatement(n))
17924 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
17925 break;
17926 }
17927 }
17928
17929 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17930 if (wasPreviouslyModified == false)
17931 {
17932 if (n->get_isModified() == true)
17933 {
17934#if 0
17935 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());
17936#endif
17937 n->set_isModified(false);
17938 }
17939
17940 }
17941
17942 }
17943 };
17944 Visitor(createEmptyBody).traverse(top, postorder);
17945 }
17946
17947
17948// Replace a given expression with a list of statements produced by a
17949// generator. The generator, when given a variable as input, must produce
17950// some code which leaves its result in the given variable. The output
17951// from the generator is then inserted into the original program in such a
17952// way that whenever the expression had previously been evaluated, the
17953// statements produced by the generator are run instead and their result is
17954// used in place of the expression.
17955// Assumptions: not currently traversing from or the statement it is in
17956void
17958 {
17959 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
17960 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
17961 // the original assumptions upon which this function was based are not incorrect, hence the bug!
17962 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
17963 // for SgScopeStatement).
17964
17965#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
17966 SgStatement* enclosingStatement = getStatementOfExpression(from);
17967 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
17968
17969 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
17970 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
17971 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
17972
17973
17974 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
17975
17976 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
17977
17978 if (varDeclarationStatement)
17979 {
17981 }
17982 else
17983 {
17984 SgExpression* root = getRootOfExpression(from);
17985 ROSE_ASSERT (root);
17986 // printf ("root = %p \n",root);
17987 {
17988 if (forStatement && forStatement->get_increment() == root)
17989 {
17990 // printf ("Convert step of for statement \n");
17991 // Convert step of for statement
17992 // for (init; test; e) body; (where e contains from) becomes
17993 // for (init; test; ) {
17994 // body (with "continue" changed to "goto label");
17995 // label: e;
17996 // }
17997 // std::cout << "Converting for step" << std::endl;
17998 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
17999 forStatement->get_increment()->set_parent(incrStmt);
18000
18001 SageInterface::addStepToLoopBody(forStatement, incrStmt);
18003 forStatement->set_increment(ne);
18004 ne->set_parent(forStatement);
18006 }
18007 else
18008 {
18009 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
18010 assert (enclosingStmtParent);
18011 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
18012 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
18013 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
18014 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
18015 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
18016 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
18017 {
18018 // Convert test of for statement:
18019 // for (init; e; step) body; (where e contains from) becomes
18020 // for (init; true; step) {
18021 // bool temp;
18022 // temp = e;
18023 // if (!temp) break;
18024 // body;
18025 // }
18026 // in which "temp = e;" is rewritten further
18027 // std::cout << "Converting for test" << std::endl;
18028 pushTestIntoBody(enclosingForStatement);
18030 }
18031 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18032 {
18033 // printf ("Convert while statements \n");
18034 // Convert while statement:
18035 // while (e) body; (where e contains from) becomes
18036 // while (true) {
18037 // bool temp;
18038 // temp = e;
18039 // if (!temp) break;
18040 // body;
18041 // }
18042 // in which "temp = e;" is rewritten further
18043 // std::cout << "Converting while test" << std::endl;
18044 pushTestIntoBody(whileStatement);
18045 // FixSgTree(whileStatement);
18047 }
18048 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18049 {
18050 // printf ("Convert do-while statements \n");
18051 // Convert do-while statement:
18052 // do body; while (e); (where e contains from) becomes
18053 // {bool temp = true;
18054 // do {
18055 // body (with "continue" changed to "goto label";
18056 // label:
18057 // temp = e;} while (temp);}
18058 // in which "temp = e;" is rewritten further
18059 // std::cout << "Converting do-while test" << std::endl;
18060 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18061 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18062 assert (doWhileStatement->get_parent());
18063 new_statement->set_parent(doWhileStatement->get_parent());
18064 myStatementInsert(doWhileStatement, new_statement, false);
18065 SageInterface::myRemoveStatement(doWhileStatement);
18066 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18067 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18068 buildBoolValExp(true));
18069 //SageInterface::getBoolType(doWhileStatement));
18071 varname, buildBoolType(), assignInitializer, new_statement);
18072
18073 SgInitializedName* initname = new_decl->get_variables().back();
18074 initname->set_scope(new_statement);
18075
18076 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18077 assignInitializer->set_parent(initname);
18078
18079#if 1
18080 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18082#else
18083 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18084 new_statement->insert_symbol(varname, varsym);
18085 varsym->set_parent(new_statement->get_symbol_table());
18086#endif
18087
18088 SageInterface::appendStatement(new_decl, new_statement);
18089 SageInterface::appendStatement(doWhileStatement, new_statement);
18090 assert (varsym);
18091 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18092 SgVarRefExp* vr = buildVarRefExp(varsym);
18093 vr->set_lvalue(true);
18094
18095 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18096
18097 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18098 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18099
18101 varsymVr->set_parent(condStmt);
18102 doWhileStatement->set_condition(condStmt);
18103 condStmt->set_parent(doWhileStatement);
18105 }
18106 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18107 {
18108 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18109 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18110 assert (ifStatement->get_parent());
18111 new_statement->set_parent(ifStatement->get_parent());
18112 myStatementInsert(ifStatement, new_statement, false);
18114 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18115 SgBoolValExp* trueVal = buildBoolValExp(true);
18116
18118
18120 buildBoolType(), ai,new_statement);
18121 SgInitializedName* initname = new_decl->get_variables().back();
18122 ai->set_parent(initname);
18123 initname->set_scope(new_statement);
18124#if 1
18125 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18127#else
18128 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18129 new_statement->insert_symbol(varname, varsym);
18130 varsym->set_parent(new_statement->get_symbol_table());
18131#endif
18132 SageInterface::appendStatement(new_decl, new_statement);
18133 ifStatement->set_parent(new_statement);
18134 assert (varsym);
18135
18136 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18137 SgVarRefExp* vr = buildVarRefExp(varsym);
18138 vr->set_lvalue(true);
18139 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18140 SageInterface::appendStatement(temp_setup, new_statement);
18141 SageInterface::appendStatement(ifStatement, new_statement);
18144 ifStatement->set_conditional(es);
18145 es->set_parent(ifStatement);
18147 }
18148 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18149 {
18150 SgExpression* switchCond = exprStatement->get_expression();
18151 ROSE_ASSERT (switchCond);
18152 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18153 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18154 assert (switchStatement->get_parent());
18155 new_statement->set_parent(switchStatement->get_parent());
18156 myStatementInsert(switchStatement, new_statement, false);
18157 SageInterface::myRemoveStatement(switchStatement);
18158 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18159 switchCond->set_parent(NULL);
18160 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18162 SageInterface::appendStatement(new_decl, new_statement);
18163 switchStatement->set_parent(new_statement);
18164 assert (varsym);
18165
18166
18167 SageInterface::appendStatement(switchStatement, new_statement);
18170 switchStatement->set_item_selector(es);
18171 es->set_parent(switchStatement);
18173 }
18174 else
18175 {
18176 // printf ("Handles expression and return statements \n");
18177 // Handles expression and return statements
18178 // std::cout << "Converting other statement" << std::endl;
18180 }
18181 }
18182 }
18183 }
18184
18185#endif
18186
18187 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18188 }
18189
18198
18199// Similar to replaceExpressionWithStatement, but with more restrictions.
18200// Assumptions: from is not within the test of a loop or if
18201// not currently traversing from or the statement it is in
18203 {
18204
18205#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18206 SgStatement* stmt = getStatementOfExpression(from);
18207
18208 if (isSgExprStatement(stmt))
18209 {
18210 SgExpression* top = getRootOfExpression(from);
18211
18212
18213 if (top == from)
18214 {
18215 SgStatement* generated = to->generate(0);
18216 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18217 generated->set_parent(stmt->get_parent());
18218 return;
18219 }
18220 else
18221 {
18222 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18223 {
18224 SgAssignOp* t = isSgAssignOp(top);
18225 SgStatement* generated = to->generate(t->get_lhs_operand());
18226 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18227 generated->set_parent(stmt->get_parent());
18228 return;
18229 }
18230 else
18231 {
18232 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18233 }
18234 }
18235 }
18236
18237 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18239 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18240 convertInitializerIntoAssignment(init);
18241 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18242 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18243 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18244 assert (new_stmt != NULL); // Should now have this form because of conversion
18245 replaceAssignmentStmtWithStatement(new_stmt, to);
18246
18247 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18248 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18249
18250#endif
18251 }
18252
18253
18254 // Liao, 6/27/2008
18255 //Tasks
18256 // find all return statements
18257 // rewrite it to temp = expression; return temp; if expression is not a single value.
18258 // insert s right before 'return xxx;'
18260 {
18261 int result = 0;
18262 ROSE_ASSERT(func&&s);
18263 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18264 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18265 //vector<SgReturnStmt*>::iterator i;
18266 Rose_STL_Container<SgNode*>::iterator i;
18267 for (i=stmts.begin();i!=stmts.end();i++)
18268 {
18269 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18270 ROSE_ASSERT(cur_stmt);
18271 SgExpression * exp = cur_stmt->get_expression();
18272 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18273 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18274 if (needRewrite)
18275 {
18276 splitExpression(exp);
18277 }
18278 // avoid reusing the statement
18279 if (result>=1 )
18280 s = copyStatement(s);
18281 insertStatementBefore(cur_stmt,s);
18282 result ++;
18283 } // for
18284 if (stmts.size()==0 ) // a function without any return at all,
18285 {
18286 SgBasicBlock * body = func->get_definition()->get_body();
18287 if (body== NULL)
18288 {
18289 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18290 ROSE_ABORT();
18291 }
18292 appendStatement(s,body);
18293 result ++;
18294 }
18295 return result;
18296 } // instrumentEndOfFunction
18297
18299 {
18300 ROSE_ASSERT(stmt);
18301 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18302 } // isStatic()
18303
18306 {
18307 ROSE_ASSERT(stmt);
18308 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18309 }
18310
18312 {
18313 ROSE_ASSERT(stmt);
18314 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18315 } // isExtern()
18316
18317
18320 {
18321 ROSE_ASSERT(stmt);
18322 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18323 }
18324
18325 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18327 {
18328 ROSE_ASSERT(name);
18329 return name->get_storageModifier().isMutable();
18330 }
18331
18332 // True if a parameter name is a Jovial output parameter
18334 {
18335 return isMutable(name);
18336 }
18337
18338 // Get a vector of Jovial input parameters from the function parameter list
18339 // TODO: Look into making this work for Fortran
18340 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18341 {
18342 std::vector<SgInitializedName*> in_params;
18343 BOOST_FOREACH (SgInitializedName* name, params)
18344 {
18345 if (!isJovialOutParam(name)) in_params.push_back(name);
18346 }
18347 return in_params;
18348 }
18349
18350 // Get a list of Jovial output parameters from the function parameter list
18351 // TODO: Look into making this work for Fortran
18352 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18353 {
18354 std::vector<SgInitializedName*> out_params;
18355 BOOST_FOREACH (SgInitializedName* name, params)
18356 {
18357 if (isJovialOutParam(name)) out_params.push_back(name);
18358 }
18359 return out_params;
18360 }
18361
18363 switch (expr->variantT()) {
18364 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18365 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18366 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18367 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18368 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18369 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18370 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18371 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18372 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18373 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18374 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18375
18376 // DQ (2/18/2015): Make this a better error message.
18377 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18378 default:
18379 {
18380 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18381 ROSE_ASSERT (false);
18382 }
18383
18384 }
18385
18386 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18387 return 0;
18388 }
18389
18390
18391#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18392// tps : 28 Oct 2008 - support for finding the main interpretation
18393// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18397SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18398{
18399 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18400 ROSE_ASSERT(binary!=NULL);
18401
18402 /* Find the only header or the PE header of this file */
18403 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18404 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18405 if (1==headers.size()) {
18406 requisite_header = headers[0];
18407 } else {
18408 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18409 if (isSgAsmPEFileHeader(*hi)) {
18410 requisite_header = isSgAsmPEFileHeader(*hi);
18411 break;
18412 }
18413 }
18414 }
18415 ROSE_ASSERT(requisite_header!=NULL);
18416
18417 /* Find an interpretation that points to this header */
18418 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18419 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18420 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18421 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18422 if ((*hi)==requisite_header)
18423 return *ii;
18424 }
18425 }
18426
18427 ROSE_ASSERT(!"no appropriate interpretation");
18428 return NULL;
18429}
18430#endif
18431
18433 {
18434 public:
18435 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18436 // Note that the root of the does not have its file info set like its children.
18437 virtual SgNode *copyAst(const SgNode *n)
18438 {
18439 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18440 SgNode* copy = n->copy(*this);
18441
18442 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18443 Sg_File_Info* fileInfo = copy->get_file_info();
18444 if (fileInfo != NULL)
18445 {
18446 // Must make this for output (checked in unparser), marking as a transformation is not checked
18447 fileInfo->setOutputInCodeGeneration();
18448 fileInfo->setTransformation();
18449 }
18450
18451 return copy;
18452 }
18453 } collectDependentDeclarationsCopyType;
18454
18455
18457 {
18458 // This traversal collects the includes at the top of a file.
18459
18460 public:
18461 vector<PreprocessingInfo*> cppDirectiveList;
18462
18463 void visit(SgNode *astNode);
18464 };
18465
18466
18467void
18469 {
18470 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18471 if (locatedNode != NULL)
18472 {
18473 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18474
18475 if (comments != NULL)
18476 {
18477#if 0
18478 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18479#endif
18480 AttachedPreprocessingInfoType::iterator i;
18481 for (i = comments->begin(); i != comments->end(); i++)
18482 {
18483 ROSE_ASSERT ( (*i) != NULL );
18484#if 0
18485 printf (" Attached Comment (relativePosition=%s): %s\n",
18486 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18487 (*i)->getString().c_str());
18488 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18489 (*i)->get_file_info()->display("comment/directive location");
18490#endif
18491
18492 // We only save the #include directives, but likely we should be collecting ALL directives to
18493 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18494 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18495 {
18496 // This is an include directive.
18497 cppDirectiveList.push_back(*i);
18498#if 0
18499 printf (" Attached include directive (relativePosition=%s): %s\n",
18500 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18501 (*i)->getString().c_str());
18502#endif
18503 }
18504 }
18505 }
18506 else
18507 {
18508#if 0
18509 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18510#endif
18511 }
18512 }
18513 }
18514
18515
18516// This is part of a mechanism to collect directives from code that is to be outlined.
18517// However if we collect include directives we likely should really be collecting ALL
18518// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18519// This level of detail will be addressed later (in an iterative approach).
18520vector<PreprocessingInfo*>
18521collectCppDirectives ( SgSourceFile* file )
18522 {
18523 // This function is used to collect include directives from the whole file.
18525 t.traverse(file,preorder);
18526
18527 return t.cppDirectiveList;
18528 }
18529
18530
18531vector<PreprocessingInfo*>
18532collectCppDirectives ( SgLocatedNode* n )
18533 {
18534 // This function is used to collect include directives from specific dependent declarations.
18536 t.traverse(n,preorder);
18537
18538 return t.cppDirectiveList;
18539 }
18540
18541// Debugging support.
18542void
18543outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18544 {
18545 // This function support debugging the generated directive lists.
18546
18547 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18548 while ( i != l.end() )
18549 {
18550 printf (" Attached include directive (relativePosition=%s): %s\n",
18551 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18552 (*i)->getString().c_str());
18553 i++;
18554 }
18555 }
18556
18557
18558
18560getAssociatedDeclaration( SgScopeStatement* scope )
18561 {
18562 //TODO This should become a member of SgScopeStatement
18563
18564 SgDeclarationStatement* declaration = NULL;
18565 switch(scope->variantT())
18566 {
18567 case V_SgNamespaceDefinitionStatement:
18568 {
18569 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18570 declaration = namespaceDefinition->get_namespaceDeclaration();
18571 break;
18572 }
18573
18574 case V_SgClassDefinition:
18575 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18576 {
18577 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18578 declaration = classDefinition->get_declaration();
18579 break;
18580 }
18581
18582 default:
18583 {
18584 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18585 ROSE_ABORT();
18586 }
18587 }
18588
18589 // There may be some scopes that don't have an associated declaration.
18590 ROSE_ASSERT(declaration != NULL);
18591
18592 return declaration;
18593 }
18594
18595
18597 {
18598 public:
18599 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18600 // (usually of the outlined functions) to insert in the separate file to support outlining.
18601 vector<SgDeclarationStatement*> declarationList;
18602
18603 // Save the list of associated symbols of dependent declarations identified so that we can
18604 // support their replacement in the new AST.
18605 vector<SgSymbol*> symbolList;
18606
18607 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18608 set<SgDeclarationStatement*> alreadySavedDeclarations;
18609
18610 // Required visit function for the AST traversal
18611 void visit(SgNode *astNode);
18612 private:
18613 void addDeclaration(SgDeclarationStatement* decl);
18614 };
18615
18617getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18618 {
18619 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18620 // outline the reference to the class, we have to declare not the class but the outer scope
18621 // (which will have the class included).
18622
18623 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18624
18625 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18626 SgScopeStatement* scope = inputDeclaration->get_scope();
18627 ROSE_ASSERT(scope != NULL);
18628
18629 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18630
18631 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18632 SgGlobal* globalScope = isSgGlobal(scope);
18633 if (globalScope == NULL)
18634 {
18635 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18636 // printf ("Traverse back to the global scope to include outer declarations \n");
18637
18638 SgScopeStatement* parentScope = scope;
18639 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18640 ROSE_ASSERT(parentScope != NULL);
18641 while (globalScope == NULL)
18642 {
18643 associatedDeclaration = getAssociatedDeclaration(parentScope);
18644 ROSE_ASSERT(associatedDeclaration != NULL);
18645
18646 parentScope = parentScope->get_scope();
18647 globalScope = isSgGlobal(parentScope);
18648 }
18649
18650 returnDeclaration = associatedDeclaration;
18651 }
18652
18653 return returnDeclaration;
18654 }
18655
18656
18657// Debugging support.
18658void
18659outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18660 {
18661 // This function support debugging the generated declarations.
18662
18663 int counter = 0;
18664 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18665 while ( i != l.end() )
18666 {
18667 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18668 i++;
18669 }
18670 }
18671
18672void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18673{
18674 // If there was a declaration found then handle it.
18675 if (declaration != NULL)
18676 {
18677 // Reset the defining declaration in case there is an outer declaration that is more important
18678 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18679 // find the associated outer declaration in the global scope.
18680 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18681
18682 // This declaration is in global scope so we just copy the declaration
18683 // For namespace declarations: they may have the save name but they have to be saved separated.
18684 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18685 {
18686#if 0
18687 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18688 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18689#endif
18690 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18691 declarationList.push_back(dependentDeclaration);
18692
18693 // Record this as a copied declaration
18694 alreadySavedDeclarations.insert(dependentDeclaration);
18695#if 0
18696 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18697 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18698 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18699#endif
18700 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18701 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18702 }
18703 else
18704 {
18705#if 0
18706 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18707 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18708 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18709#endif
18710 }
18711 }
18712}
18713
18715static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18716{
18717 ROSE_ASSERT(type != NULL);
18718 std::vector<SgTypedefDeclaration*> result;
18719 SgType* currentType = type;
18720
18721 SgModifierType* modType = NULL;
18722 SgPointerType* pointType = NULL;
18723 SgReferenceType* refType = NULL;
18724 SgArrayType* arrayType = NULL;
18725 SgTypedefType* typedefType = NULL;
18726
18727 while (true)
18728 {
18729 modType = isSgModifierType(currentType);
18730 if(modType)
18731 {
18732 currentType = modType->get_base_type();
18733 }
18734 else
18735 {
18736 refType = isSgReferenceType(currentType);
18737 if(refType)
18738 {
18739 currentType = refType->get_base_type();
18740 }
18741 else
18742 {
18743 pointType = isSgPointerType(currentType);
18744 if ( pointType)
18745 {
18746 currentType = pointType->get_base_type();
18747 }
18748 else
18749 {
18750 arrayType = isSgArrayType(currentType);
18751 if (arrayType)
18752 {
18753 currentType = arrayType->get_base_type();
18754 }
18755 else
18756 {
18757 typedefType = isSgTypedefType(currentType);
18758 if (typedefType)
18759 {
18760 currentType = typedefType->get_base_type();
18761 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18762 // have to try to get the defining declaration for a defining typedef declaration
18763 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18764 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18765 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18766 if (decl ==NULL)
18767 decl = tdecl;
18768 result.push_back(decl);
18769 }
18770 else
18771 {
18772 // Exit the while(true){} loop!
18773 break;
18774 }
18775 }
18776 }
18777 }
18778 }
18779 }
18780#if 0
18781 // debug here
18782 if (result.size()>0)
18783 {
18784 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
18785 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
18786 iter!=result.end(); iter ++)
18787 cout<<(*iter)->unparseToString()<<endl;
18788 }
18789#endif
18790 return result;
18791}
18792
18794void
18796 {
18797 // Statements that can cause us to have declaration dependences:
18798 // 1) variable declarations (through their types)
18799 // 2) function calls
18800 // 3) typedefs (through their base types)
18801 // Not implemented:
18802 // 4) static member functions (through their class)
18803 // 5) static data members (through their class)
18804 // 6) namespaces
18805 // 7) #include<> CPP directives.
18806
18807 // DQ (2/22/2009): Changing the semantics for this function,
18808 // just save the original declaration, not a copy of it.
18809
18810#if 0
18811 // Debugging support.
18812 Sg_File_Info* fileInfo = astNode->get_file_info();
18813 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
18814 {
18815 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18816 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
18817 int counter = 0;
18818 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
18819 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
18820 {
18821 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
18822 }
18823 }
18824#endif
18825
18826 // The following conditionals set this variable
18827 SgDeclarationStatement* declaration = NULL;
18828
18829 // 1) ------------------------------------------------------------------
18830 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
18831 SgInitializedName* initializedname = isSgInitializedName(astNode);
18832 if (initializedname != NULL)
18833 {
18834 SgType* type = initializedname->get_type();
18835
18836 // handle all dependent typedef declarations, if any
18837 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
18838 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
18839 iter != typedefVec.end(); iter++)
18840 {
18841 SgTypedefDeclaration* typedef_decl = *iter;
18842 addDeclaration(typedef_decl);
18843 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
18844 }
18845
18846 // handle base type:
18847
18848 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
18849 // this also reach to the defining body of a defining typedef declaration
18850 // and treat it as an independent declarations,
18851 // the assumption here is that a defining typedef declaration will only has its
18852 // nondefining declaration copied to avoid redefining of the struct.
18853 // This is also a workaround for an AST copy bug: defining body gets lost after copying
18854 // a defining typedef declaration.
18855 // Liao, 5/8/2009
18856 //
18857 // e.g. typedef struct hypre_BoxArray_struct
18858 // {
18859 // int alloc_size;
18860 // } hypre_BoxArray;
18861 //
18862 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
18863 // will be inserted.
18864 //
18865 SgType* strippedType = type->stripType();
18866 SgNamedType* namedType = isSgNamedType(strippedType);
18867 if (namedType != NULL)
18868 {
18869 // Note that since this was obtained via the types and types are shared, this is the non-defining
18870 // declaration in original program (not the separate file is this is to support outlining into a
18871 // separate file.
18872 SgDeclarationStatement* named_decl = namedType->get_declaration();
18873 // the case of class declaration, including struct, union
18874 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
18875 if (classDeclaration != NULL)
18876 {
18877 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
18878 declaration = classDeclaration->get_definingDeclaration();
18879 // Liao, 12/09/2016.
18880 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
18881 // We should allow this.
18882 if (declaration != NULL)
18883 {
18884 // ROSE_ASSERT(declaration != NULL);
18885 addDeclaration(declaration);
18886 }
18887 else
18888 addDeclaration (classDeclaration); // we use the original forward declaration.
18889
18890 // Note that since types are shared in the AST, the declaration for a named type may be (is)
18891 // associated with the class declaration in the original file. However, we want to associated
18892 // class declaration in the current file, but since the AST copy mechanism work top-down, this
18893 // mapping form the declaration in the original file to the new declaration in the copied AST
18894 // is available in the SgCopyHelp map of copied IR nodes.
18895 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
18896 // these symbols will be mapped to their new symbols.
18897 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
18898 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
18899 ROSE_ASSERT(classSymbol != NULL);
18900
18901 // printf ("Saving classSymbol = %p \n",classSymbol);
18902 symbolList.push_back(classSymbol);
18903 }
18904
18905 // handle Enum types
18906 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
18907 if (enum_decl != NULL)
18908 {
18909 declaration = enum_decl->get_definingDeclaration();
18910 ROSE_ASSERT(declaration != NULL);
18911 addDeclaration(declaration);
18912 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
18913 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
18914 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
18915 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
18916 ROSE_ASSERT(esymbol!= NULL);
18917 symbolList.push_back(esymbol);
18918 }
18919 } // end if namedType
18920#if 0
18921 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
18922#endif
18923 }// end if (initializedname)
18924
18925 // 2) ------------------------------------------------------------------
18926 // Collect declarations associated with function calls.
18927 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
18928 if (functionCallExp != NULL)
18929 {
18930 declaration = functionCallExp->getAssociatedFunctionDeclaration();
18931 //ROSE_ASSERT(declaration != NULL);
18932 // We allow a function pointer to have no specific declaration associated.
18933 if (declaration != NULL)
18934 addDeclaration(declaration);
18935
18936 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
18937 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
18938 //ROSE_ASSERT(functionSymbol != NULL);
18939
18940 // printf ("Saving functionSymbol = %p \n",functionSymbol);
18941 if (functionSymbol)
18942 symbolList.push_back(functionSymbol);
18943 }
18944
18945 // 3) ------------------------------------------------------------------
18946 // Collect enumerate declarations associated with SgEnumVal
18947 SgEnumVal * eval = isSgEnumVal(astNode);
18948 if (eval != NULL)
18949 {
18950 declaration = eval->get_declaration();
18951 ROSE_ASSERT(declaration != NULL);
18952 addDeclaration(declaration);
18954 ROSE_ASSERT(symbol != NULL);
18955 symbolList.push_back(symbol);
18956 }
18957// addDeclaration(declaration); // do it in different cases individually
18958 }
18959
18960static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
18961
18962
18964// Used to separate a function to a new source file and add necessary type declarations into the new file.
18965// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
18966static void
18967getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
18968{
18969 // This function returns a list of the dependent declaration for any input statement.
18970 // Dependent declaration are functions called, types referenced in variable declarations, etc.
18971#if 0
18972 printf ("\n\n********************************************************** \n");
18973 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
18974 printf ("********************************************************** \n");
18975#endif
18976 visitedDeclMap[stmt]= true;
18978 t.traverse(stmt,preorder);
18979#if 0
18980 declarationList = t.declarationList;
18981 symbolList = t.symbolList;
18982#else
18983 // Merge to the parent level list
18984 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
18985 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
18986 // make their elements unique
18987 sort (declarationList.begin(), declarationList.end());
18988 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
18989 declarationList.erase(new_end, declarationList.end());
18990
18991 sort (symbolList.begin(), symbolList.end());
18992 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
18993 symbolList.erase(end2, symbolList.end());
18994
18995
18996 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
18997 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
18998 iter !=t.declarationList.end(); iter++)
18999 {
19000 SgDeclarationStatement* decl = *iter;
19001 SgType* base_type = NULL;
19002 SgStatement* body_stmt= NULL;
19003
19004 // grab base type for a declaration
19005 // For class declaration: grab their
19006 if (isSgClassDeclaration(decl))
19007 {
19008 base_type = isSgClassDeclaration(decl)->get_type();
19009 } else
19010 if (isSgTypedefDeclaration(decl))
19011 {
19012
19013 // we don't want to strip of nested typedef declarations
19014 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);
19015 }
19016
19017 //TODO variable declaration, function declaration: parameter list types,
19018 // multiple base_type then
19019
19020 // is the base type associated with a defining body?
19021 // TODO enum type
19022 if (isSgClassType(base_type))
19023 {
19024 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19025 if (class_decl!=NULL)
19026 {
19027 body_stmt = class_decl->get_definition();
19028 }
19029 }
19030 // recursively collect dependent declarations for the body stmt
19031 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19032 { // avoid infinite recursion
19033 getDependentDeclarations(body_stmt, declarationList, symbolList);
19034 }
19035 }
19036#endif
19037} // end void getDependentDeclarations()
19038
19039
19040// Reorder a list of declaration statements based on their appearance order in source files
19041// This is essential to insert their copies into a new file in a right order
19042// Liao, 5/7/2009
19043vector<SgDeclarationStatement*>
19044SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19045{
19046 vector<SgDeclarationStatement*> sortedNode;
19047
19048 if (nodevec.size()==0 )
19049 return sortedNode;
19050 // no need to sort if there is only 1 element
19051 if (nodevec.size() ==1)
19052 return nodevec;
19053
19055 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19056 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19057 iter!= queryResult.end(); iter++)
19058 {
19059 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19060 SgNode* cur_node = *iter;
19061 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19062 ROSE_ASSERT(cur_stmt!=NULL);
19063 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19064 // This is true even if the AST only has a defining function declaration.
19065 //
19066 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19067 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19068 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19069 if (func_decl)
19070 {
19071 if (func_decl->get_definingDeclaration() == func_decl )
19072 {
19073 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19074 ROSE_ASSERT (cur_stmt != func_decl);
19075 }
19076 }
19077 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19078 if (i!=nodevec.end())
19079 {
19080 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19081 // We have to make sure only one copy is inserted.
19082 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19083 if (j == sortedNode.end())
19084 sortedNode.push_back(*i);
19085 }
19086 }
19087
19088 if (nodevec.size() != sortedNode.size())
19089 {
19090 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19091 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19092 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19093 {
19094 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19095 }
19096 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19097 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19098 {
19099 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19100 }
19101
19102 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19103 }
19104 return sortedNode;
19105}
19106
19108// This function clears a history map transparently and return a sorted list of dependent declarations
19109std::vector<SgDeclarationStatement*>
19111 {
19112 // This function returns a list of the dependent declaration for any input statement.
19113 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19114#if 0
19115 printf ("\n\n********************************************************** \n");
19116 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19117 printf ("********************************************************** \n");
19118
19120 t.traverse(stmt,preorder);
19121
19122 return t.declarationList;
19123#else
19124 // share a single implementation for recursive lookup for dependent declaration
19125 visitedDeclMap.clear();
19126 vector<SgDeclarationStatement*> declarationList;
19127 vector<SgSymbol*> symbolList;
19128 getDependentDeclarations(stmt, declarationList, symbolList);
19129 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19130#if 0
19131 printf ("\n\n ********************************************************** \n");
19132 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19133 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19134 iter != declarationList.end(); iter++)
19135 {
19136 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19137 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19138 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19139 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19140 }
19141 printf ("\n ********************************************************** \n");
19142#endif
19143
19144 return declarationList;
19145
19146#endif
19147 }
19148
19149
19150bool
19152 {
19153 bool returnValue = false;
19154
19155#if 0
19156 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());
19157#endif
19158
19159 if (functionName.is_null() == false)
19160 {
19161 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19162 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19163 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19164 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19165 {
19166 returnValue = true;
19167 }
19168 }
19169
19170 return returnValue;
19171 }
19172
19173
19174// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19176bool
19178 {
19179 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19180 // Also we now support when they are defined as member functions and non-member functions.
19181
19182 bool returnValue = false;
19183
19184 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19185 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19186 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19187
19188 SgName functionName;
19189 size_t numberOfOperands = 0;
19190
19191 if (memberFunctionRefExp != NULL)
19192 {
19193 ROSE_ASSERT(functionRefExp == NULL);
19194 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19195 if (memberFunctionDeclaration != NULL)
19196 {
19197 functionName = memberFunctionDeclaration->get_name();
19198 numberOfOperands = memberFunctionDeclaration->get_args().size();
19199 }
19200 }
19201 else
19202 {
19203 // This could be "friend bool operator!(const X & x);"
19204 if (functionRefExp != NULL)
19205 {
19206 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19207 if (functionDeclaration != NULL)
19208 {
19209 functionName = functionDeclaration->get_name();
19210 numberOfOperands = functionDeclaration->get_args().size();
19211 }
19212 }
19213 else
19214 {
19215 // Note clear if this should be an error.
19216 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19217 }
19218 }
19219
19220#if 0
19221 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);
19222#endif
19223
19224 if (isPrefixOperatorName(functionName) == true)
19225 {
19226 if (memberFunctionRefExp != NULL)
19227 {
19228 // This case is for member functions.
19229 ROSE_ASSERT(functionRefExp == NULL);
19230 if (numberOfOperands == 0)
19231 {
19232 // This is the C++ signature for the operator++() prefix operator.
19233 returnValue = true;
19234 }
19235 else
19236 {
19237 // This is the C++ signature for the operator++() postfix operator.
19238 returnValue = false;
19239 }
19240 }
19241 else
19242 {
19243 // This case is for non-member functions.
19244 ROSE_ASSERT(functionRefExp != NULL);
19245 ROSE_ASSERT(memberFunctionRefExp == NULL);
19246 if (numberOfOperands == 1)
19247 {
19248 // This is the C++ signature for the operator++() prefix operator.
19249 returnValue = true;
19250 }
19251 else
19252 {
19253 // This is the C++ signature for the operator++() postfix operator.
19254 ROSE_ASSERT(numberOfOperands == 2);
19255 returnValue = false;
19256 }
19257 }
19258 }
19259
19260#if 0
19261 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19262#endif
19263
19264 return returnValue;
19265 }
19266
19267
19269bool
19271 {
19272 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19273 }
19274
19275
19277bool
19279 {
19280 bool returnValue = false;
19281 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19282 if (memberFunctionRefExp == NULL)
19283 return false;
19284
19285 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19286 if (memberFunctionDeclaration != NULL)
19287 {
19288 SgName functionName = memberFunctionDeclaration->get_name();
19289 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19290 {
19291 returnValue = true;
19292 }
19293 else
19294 {
19295 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19296 {
19297 returnValue = true;
19298 }
19299 else
19300 {
19301 returnValue = false;
19302 }
19303 }
19304 }
19305
19306 return returnValue;
19307 }
19308
19309
19310// DQ (1/10/2014): Adding more general support for token based unparsing.
19312SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19313 {
19314 // Return the last statement in the associated scope that has token information.
19315 SgStatement* lastStatement = NULL;
19316
19317 ROSE_ASSERT(scope != NULL);
19318
19319#if 0
19320 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19321#endif
19322
19323 SgIfStmt* ifStatement = isSgIfStmt(scope);
19324 if (ifStatement != NULL)
19325 {
19326 lastStatement = ifStatement->get_false_body();
19327 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19328 {
19329 lastStatement = ifStatement->get_true_body();
19330 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19331 {
19332 lastStatement = NULL;
19333 }
19334 }
19335
19336 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19337 if (lastStatement != NULL)
19338 {
19339 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19340 }
19341
19342 return lastStatement;
19343 }
19344
19345 SgStatementPtrList statementList = scope->generateStatementList();
19346 if (statementList.rbegin() != statementList.rend())
19347 {
19348 // Find the last statement with token stream information.
19349 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19350
19351 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19352 {
19353 i++;
19354 }
19355
19356 if (i == statementList.rend())
19357 {
19358 lastStatement = NULL;
19359 }
19360 else
19361 {
19362 lastStatement = *i;
19363 }
19364 }
19365
19366 return lastStatement;
19367 }
19368
19369
19370void
19372 {
19373 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19374
19375 class DeclarationTraversal : public AstSimpleProcessing
19376 {
19377 public:
19378 // DeclarationTraversal() {}
19379
19380 void visit (SgNode* node)
19381 {
19382 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19383 if (decl != NULL)
19384 {
19385 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19386 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19387 SgDeclarationStatement* otherDeclaration = NULL;
19388
19389 // Output access modifier information for each declaration.
19390 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19391 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19392 {
19393 otherDeclaration = decl;
19394 }
19395
19396 if (definingDeclaration != NULL)
19397 {
19398 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19399 }
19400
19401 if (firstNondefiningDeclaration != NULL)
19402 {
19403 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19404 }
19405
19406 if (otherDeclaration != NULL)
19407 {
19408 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19409 }
19410
19411 // Adding space for formatting.
19412 printf ("\n");
19413 }
19414 }
19415 };
19416
19417 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19418 DeclarationTraversal traversal;
19419 traversal.traverse(astNode, preorder);
19420 }
19421
19422
19423void
19425 {
19426 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19427
19428 class ScopeTraversal : public AstSimpleProcessing
19429 {
19430 public:
19431 void visit (SgNode* node)
19432 {
19433 SgScopeStatement* scope = isSgScopeStatement(node);
19434 if (scope != NULL)
19435 {
19436 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19437 if (functionDefinition != NULL)
19438 {
19439 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19440 ROSE_ASSERT(functionDeclaration != NULL);
19441
19442 string functionName = functionDeclaration->get_name();
19443
19444 printf ("functionName = %s \n",functionName.c_str());
19445
19446 if (functionName == "main")
19447 {
19448
19449 SgBasicBlock* functionBody = functionDefinition->get_body();
19450 ROSE_ASSERT(functionBody != NULL);
19451 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19452 ROSE_ASSERT(symbolTable != NULL);
19453
19454 // Print out the symbol table.
19455 symbolTable->print();
19456 }
19457 }
19458
19459 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19460 if (namespaceDefinition != NULL)
19461 {
19462 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19463 ROSE_ASSERT(namespaceDeclaration != NULL);
19464
19465 string namespaceName = namespaceDeclaration->get_name();
19466
19467 printf ("namespaceName = %s \n",namespaceName.c_str());
19468
19469 if (namespaceName == "B")
19470 {
19471 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19472 ROSE_ASSERT(symbolTable != NULL);
19473
19474 // Print out the symbol table.
19475 symbolTable->print();
19476 }
19477 }
19478 }
19479 }
19480 };
19481
19482 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19483 ScopeTraversal traversal;
19484 traversal.traverse(astNode, preorder);
19485 }
19486
19487//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19488void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19489 {
19490#if 0
19491 Sg_File_Info* fileInfo=node->get_file_info();
19492 if (fileInfo != NULL)
19493 {
19494 fileInfo->setTransformation();
19495 fileInfo->setOutputInCodeGeneration();
19496
19497 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19498 if (locatedNode != NULL)
19499 {
19500 // DQ (7/7/2015): Make the subtree as transformed.
19501 locatedNode->setTransformation();
19502 locatedNode->setOutputInCodeGeneration();
19503
19504 // DQ (7/8/2021): Added assertion.
19505 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19506#if 0
19507 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19508#endif
19509 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19510 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19511#if 1
19512 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19513#endif
19514 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19515 // to call setTransformation() and setOutputInCodeGeneration().
19516 markTransformationsForOutput(node);
19517 }
19518 else
19519 {
19520#if 0
19521 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19522#endif
19523 }
19524 }
19525 else
19526 {
19527#if 0
19528 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19529#endif
19530 }
19531#else
19532 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19533 if (locatedNode != NULL)
19534 {
19535 locatedNode->setTransformation();
19536 locatedNode->setOutputInCodeGeneration();
19537
19538 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19539 if (locatedNode->get_file_info() != NULL)
19540 {
19541#if 0
19542 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19543#endif
19544 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19545 }
19546 else
19547 {
19548#if 1
19549 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19550#endif
19551 }
19552
19553 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19554 // to call setTransformation() and setOutputInCodeGeneration().
19555 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19556 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19557 // markTransformationsForOutput(node);
19558 }
19559#endif
19560 }
19561
19562
19563
19564void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19565 {
19566 RoseAst ast(root);
19567 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19568 {
19569 markNodeToBeUnparsed(*i,physical_file_id);
19570 }
19571 }
19572
19573
19574
19576 {
19577 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19578 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19579 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19580 // This function has been implemented as part of debugging this issue.
19581
19582 class InheritedAttribute
19583 {
19584 public:
19585 int physical_file_id;
19586 bool isCastSubtree;
19587 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19588 InheritedAttribute(const InheritedAttribute & X)
19589 {
19590 isCastSubtree = X.isCastSubtree;
19591 physical_file_id = X.physical_file_id;
19592 }
19593 };
19594
19595// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19596// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19597#if (__GNUC__ > 4)
19598
19599 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19600 {
19601 public:
19602 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19603 {
19604 InheritedAttribute returnAttribute(inheritedAttribute);
19605
19606 SgCastExp* castExpression = isSgCastExp(node);
19607 if (castExpression != NULL)
19608 {
19609 returnAttribute.isCastSubtree = true;
19610 }
19611
19612 if (returnAttribute.isCastSubtree == true)
19613 {
19614 // Nothing to do, unless we want to fixup the physical node id.
19615#if 0
19616 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19617 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19618#endif
19619 }
19620 else
19621 {
19622#if 0
19623 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19624 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19625#endif
19626 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19627 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19628 }
19629
19630 return returnAttribute;
19631 }
19632 };
19633
19634 InheritedAttribute inheritedAttribute(physical_file_id);
19635
19636 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19637 SubtreeTraversal traversal;
19638
19639#if 0
19640 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19641#endif
19642
19643 traversal.traverse(root, inheritedAttribute);
19644#else
19645 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19646#endif
19647
19648 }
19649
19650
19651
19652
19654vector<SgDeclarationStatement*>
19655generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19656//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19657 {
19658 // Liao suggests adding the target scope to the parameter list so that the constructed function
19659 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19660 // correct scope as soon as possible.
19661
19662 // This function uses the getDependentDeclarations() function to get the dependent declarations
19663 // and then returns a list of copies of each of them.
19664
19665#if 0
19666 printf ("\n\n********************************************************** \n");
19667 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19668 printf ("********************************************************** \n");
19669#endif
19670
19671 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19672 // avoiding call getDependentDeclarations() twice
19673// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19674
19675#if 0
19676 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19677 outputDeclarationList(dependentDeclarations);
19678#endif
19679#if 0
19680 printf ("************************************************ \n");
19681 printf ("*** Make all copies of dependentDeclarations *** \n");
19682 printf ("************************************************ \n");
19683#endif
19684
19685 // Should have a valid scope, so that symbol tables can be expected to be setup.
19686 ROSE_ASSERT(targetScope != NULL);
19687
19688 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19689 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19690
19691 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19692 {
19693#if 0
19694 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19695#endif
19696 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19697
19698 SgNode* copy_node = NULL;
19699 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19700
19701 // For function declarations we don't want to do deep copies on defining declarations
19702 // since that would violate the One-time Definition Rule (ODR).
19703 if (functionDeclaration != NULL)
19704 {
19705 // the target scope may already have a declaration for this function.
19706 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19707 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19708 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19709 // Liao, 5/8/2009
19710
19711 if ( SgProject::get_verbose() >= 1 )
19712 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19713
19714 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19715 // TV (2/4/2014): can be found in the project wide global scope...
19716 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19717#endif
19718#if 0
19719 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19720
19721 printf ("functionDeclaration = %p \n",functionDeclaration);
19722 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19723 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19724 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19725 printf ("targetScope = %p \n",targetScope);
19726#endif
19727 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19728 assert(copy_functionDeclaration != NULL);
19729
19730 copy_functionDeclaration->set_parent(targetScope);
19731
19732 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19733
19734 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19735 // feature of clearing the symbol table used across multiple files.
19736 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19737
19738 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19739
19740 assert(copy_functionDeclaration->get_scope() != NULL);
19741 assert(copy_functionDeclaration->get_scope() == targetScope);
19742 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19743 copy_functionDeclaration->get_type()) != NULL);
19744 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19745 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19746
19747 copy_node = copy_functionDeclaration;
19748#if 0
19749 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19750 ROSE_ABORT();
19751#endif
19752 }
19753 else
19754 {
19755 // We only copy the non-defining declaration of a defining typedef declaration
19756 // since its defining body will be treated as a separate declaration and inserted to the new file.
19757 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19758 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19759 if (tdecl)
19760 {
19761#if 0
19762 if (tdecl->get_definingDeclaration() == tdecl)
19763 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19764 else
19765 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19766#endif
19768 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19769 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
19770 }
19771 else
19772 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19773
19774 // 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).
19775 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
19776 ROSE_ASSERT(copy_declaration != NULL);
19777
19778 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
19779 if (copy_declaration->hasExplicitScope() == true)
19780 copy_declaration->set_scope(targetScope);
19781 }
19782
19783 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19784 // Build a function prototype, but what scope should be used?
19785 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
19786 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
19787
19788#if 0
19789 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());
19790#endif
19791
19792 ROSE_ASSERT(copy_node != NULL);
19793 ROSE_ASSERT(copy_node->get_file_info() != NULL);
19794
19795 // Note that the root of the does not have its file info set like its children.
19796 copy_node->get_file_info()->setTransformation();
19798 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
19799
19800 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
19801 ROSE_ASSERT(copy_definingDeclaration != NULL);
19802
19803 ROSE_ASSERT( *i != NULL );
19804 ROSE_ASSERT(copy_definingDeclaration != NULL);
19805
19806 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
19807 if (copy_definingDeclaration->get_parent() == NULL)
19808 {
19809 copy_definingDeclaration->set_parent(targetScope);
19810 }
19811 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19812
19813#if 0
19814 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
19815#endif
19816
19817 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
19818 copy_definingDeclaration->set_parent(NULL);
19819
19820 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
19821 // copy_definingDeclaration->set_scope(NULL);
19822
19823 // DQ (2/20/2009): Added assertion.
19824 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
19825
19826#if 0
19827 // DQ (2/20/2009): Added assertion.
19828 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
19829 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
19830 {
19831 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
19832 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
19833 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
19834 }
19835#endif
19836
19837 // DQ (2/21/2009): Commented out as a test.
19838 if ((*i)->get_firstNondefiningDeclaration() != NULL)
19839 {
19840 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
19841 }
19842
19843 // DQ (2/20/2009): Added asertion.
19844 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
19845
19846 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
19847 }
19848
19849#if 0
19850 printf ("****************************************************** \n");
19851 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
19852 printf ("****************************************************** \n");
19853 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
19854#endif
19855
19856 // The mapping of copies to original declarations should be 1-to-1.
19857 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
19858 // 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
19859 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
19860
19861 return copiesOfDependentDeclarations;
19862 }
19863
19864
19865bool
19866declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
19867 {
19868 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
19869 bool returnValue = false;
19870
19871#if 0
19872 printf ("\n\n********************************************************** \n");
19873 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
19874 printf ("********************************************************** \n");
19875#endif
19876
19877 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
19878
19879 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
19880 // outputPreprocessingInfoList(locallyDependentDeclarationList);
19881
19882 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
19883 {
19884 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
19885#if 0
19886 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
19887#endif
19888 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
19889 if (j != dependentDeclarationList.end())
19890 {
19891 // These identified declaration must be output as members of the class when it is output in the separate header file.
19892 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
19893#if 0
19894 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());
19895#endif
19896 returnValue = true;
19897 }
19898 }
19899
19900#if 0
19901 printf ("**************************************************************************** \n");
19902 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
19903 printf ("**************************************************************************** \n");
19904#endif
19905
19906 return returnValue;
19907 }
19910{
19911 ROSE_ASSERT (new_exp != NULL);
19912 ROSE_ASSERT (anchor_exp != NULL);
19913 ROSE_ASSERT (new_exp != anchor_exp);
19914
19915 SgNode* parent = anchor_exp->get_parent();
19916 ROSE_ASSERT (parent != NULL);
19917
19918 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
19919 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
19920 ROSE_ASSERT (result != NULL);
19921 replaceExpression (anchor_exp, result, true);
19922
19923 result->set_rhs_operand(anchor_exp);
19924 anchor_exp->set_parent(result);
19925 return result ;
19926}
19927
19928
19930SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
19931{
19932 ROSE_ASSERT (new_exp != NULL);
19933 ROSE_ASSERT (anchor_exp != NULL);
19934 ROSE_ASSERT (new_exp != anchor_exp);
19935
19936 SgNode* parent = anchor_exp->get_parent();
19937 ROSE_ASSERT (parent != NULL);
19938
19939 // insert TYPE T1; right before the enclosing statement of anchor_exp
19940 SgType * t = anchor_exp ->get_type();
19941 ROSE_ASSERT (t != NULL);
19942 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
19943 ROSE_ASSERT (enclosing_stmt != NULL);
19944
19945 gensym_counter ++;
19946 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
19947 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
19948 insertStatementBefore (enclosing_stmt, t_decl);
19949 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
19950 ROSE_ASSERT (temp_sym != NULL);
19951 if (temp_decl)
19952 *temp_decl = t_decl;
19953
19954 // build ((T1 = anchor_exp, new_exp),T1) )
19955 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
19956 if (temp_ref)
19957 * temp_ref = first_ref;
19958 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
19959 replaceExpression (anchor_exp, result, false);
19960
19961 return result;
19962}
19963
19964void
19966 {
19967 // Put out a message in the separate file to lable the dependent CPP directives.
19968 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
19969 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
19970 string fileName = "separate-outlined-file";
19971 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
19972 // requiredDirectivesList.push_back(messageToUser);
19973 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
19974
19975 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
19976 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
19977 // when multiple files are used on the command line.
19978 messageToUser->get_file_info()->setTransformation();
19979 }
19980
19981
19982// DQ (2/6/2009): Added function to support outlining into separate file.
19983// 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)
19984void
19986 {
19987 // New function to support outlining of functions into separate files (with their required declarations).
19988
19989#if 0
19990 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
19991 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
19992 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
19993 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
19994 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
19995 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
19996 if (decl->get_firstNondefiningDeclaration() != NULL)
19997 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
19998 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
19999 if (decl->get_definingDeclaration() != NULL)
20000 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
20001#endif
20002
20003#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20004 // Make sure that the input declaration (decl" is consistent in it's representation across more
20005 // than one file (only a significant test when outlining to a separate file; which is what this
20006 // function supports).
20007 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20008 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20009 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20010
20011 // DQ (2/6/2009): I need to write this function to support the
20012 // insertion of the function into the specified scope. If the
20013 // file associated with the scope is marked as compiler generated
20014 // (or as a transformation) then the declarations referenced in the
20015 // function must be copied as well (those not in include files)
20016 // and the include files must be copies also. If the SgFile
20017 // is not compiler generated (or a transformation) then we just
20018 // append the function to the scope (trivial case).
20019
20020 // This code will be based on the work in:
20021 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20022
20023 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20024 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20025
20026 // ***** Also move different loop IR nodes into a common base class *****
20027
20028 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20029
20030 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20031 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20032 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20033 // symbols generated in the copied AST.
20034 // Collect the declaration that the input declaration depends upon.
20035 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20036
20037 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20038
20039 // Generate the copies of all the dependent statements
20040// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20041// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20042 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20043 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20044
20045 // Make sure that the input declaration (decl" is consistent in it's representation across more
20046 // than one file (only a significant test when outlining to a separate file; which is what this
20047 // function supports).
20048 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20049 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20050 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20051
20052 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20053 std::map<SgNode*, SgNode*> replacementMap;
20054
20055 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20056 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20057 // copy mechanism).
20058 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20059 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20060 while (copyNodeMapItrator != copyNodeMap.end())
20061 {
20062 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20063 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20064 // SgNode* first = copyNodeMapItrator->first;
20065 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20066 SgNode* second = copyNodeMapItrator->second;
20067#if 0
20068 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20069#endif
20070 // Add the SgGlobal referenece to the replacementMap
20071 if (isSgSymbol(first) != NULL)
20072 {
20073#if 0
20074 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20075#endif
20076 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20077 }
20078
20079 copyNodeMapItrator++;
20080 }
20081
20082#if 0
20083 printf ("Exiting after test of new functionality \n");
20084 ROSE_ABORT();
20085#endif
20086
20087 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20088 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20089 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20090 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20091
20092 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20093 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20094 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20095 ROSE_ASSERT(originalFileGlobalScope != NULL);
20096 if ( SgProject::get_verbose() >= 1 )
20097 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20098
20099 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20100 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20101 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20102
20103 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20104 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20105 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20106#if 0
20107 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20108
20109 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20110 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20111 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20112#endif
20113
20114 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20115 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20116
20117 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20118 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20119
20120 // Add the SgGlobal referenece to the replacementMap
20121 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20122
20123 // Add the non-defining declarations of the outlined function to the replacementMap
20124 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20125 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20126 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20127 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20128 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20129
20130
20131 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20132 // while (i != declarationList.end())
20133 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20134
20135// cout<<"\n*******************************************\n"<<endl;
20136// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20137 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20138 {
20139 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20140#if 0
20141 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20142 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20143 printf ("originalDeclaration = %p \n",originalDeclaration);
20144
20145 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20146#endif
20147
20148 // DQ (2/20/2009): Added assertion.
20149 ROSE_ASSERT(d->get_parent() == NULL);
20150
20151 // scope->append_declaration(d);
20152 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20153 ROSE_ASSERT(decl->get_scope() == scope);
20154 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20155 scope->insert_statement (decl, d, /* bool inFront= */ true);
20156 d->set_parent (scope);
20157
20158#if 0
20159 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20160#endif
20161
20162 // For whatever type of declaration we add to the global scope in the new separate
20163 // file we have to add the required symbol information to the symbol table.
20164 switch(d->variantT())
20165 {
20166 case V_SgClassDeclaration:
20167 {
20168 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20169 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20170 break;
20171 }
20172
20173 case V_SgMemberFunctionDeclaration:
20174 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20175 ROSE_ABORT();
20176
20177 case V_SgTemplateInstantiationDecl:
20178 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20179 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20180
20181 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20182 ROSE_ABORT();
20183
20184 case V_SgNamespaceDeclarationStatement:
20185 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20186 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20187 break;
20188
20189 case V_SgFunctionDeclaration:
20190 case V_SgTypedefDeclaration:
20191 case V_SgEnumDeclaration:
20192 break;
20193
20194 default:
20195 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20196 ROSE_ABORT();
20197 }
20198
20199
20200 // Collect include directives that are already attached to this dependent declaration.
20201 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20202
20203#if 0
20204 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20205 outputPreprocessingInfoList(requiredDirectivesList);
20206
20207 printf ("directives already attached to dependent declarations \n");
20208 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20209#endif
20210
20211 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20212 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20213 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20214 {
20215 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20216 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20217 ROSE_ASSERT(entry != requiredDirectivesList.end());
20218
20219 requiredDirectivesList.erase(entry);
20220
20221 j++;
20222 }
20223
20224#if 0
20225 printf ("directives AFTER excluding those already present in dependent declarations \n");
20226 outputPreprocessingInfoList(requiredDirectivesList);
20227#endif
20228 }
20229
20230 // Add a message to the top of the outlined function that has been added
20231 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20232
20233 // Insert the dependent declarations ahead of the input "decl".
20234 SgStatement* firstStatmentInFile = NULL;
20235 if (dependentDeclarationList.empty() == true)
20236 {
20237 firstStatmentInFile = decl;
20238 }
20239 else
20240 {
20241 firstStatmentInFile = dependentDeclarationList[0];
20242 }
20243
20244 ROSE_ASSERT(firstStatmentInFile != NULL);
20245
20246 // Add a message to the top of the dependent declarations that have been added
20247 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20248
20249 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20250 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20251 // declarations (which must be in the header file) so we can automate this step.
20252 if (excludeHeaderFiles == false)
20253 {
20254 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20255 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20256 while ( j != requiredDirectivesList.rend() )
20257 {
20258 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20259 j++;
20260 }
20261 }
20262
20263 // Add a message to the top of the CPP directives that have been added
20264 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20265
20266 // ****************************************************************************
20267 // **************** Fixup AST to Reset References To IR nodes ***************
20268 // ****************************************************************************
20269 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20270 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20271 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20272 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20273 // list for update are added to the intermediateDeleteSet.
20274
20275 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20276 ROSE_ASSERT(outlinedFile != NULL);
20277
20278 // This replacement will be done over the entire file (parts of it are redundant with what has already
20279 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20280 // on the outlined function, I think).
20281#if 0
20282 printf ("\n\n************************************************************\n");
20283 printf ("Calling Utils::edgePointerReplacement() \n");
20284#endif
20285
20286 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20287
20288#if 0
20289 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20290 printf ("************************************************************\n\n");
20291
20292 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20293 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20294#endif
20295
20296 // Repeated test from above
20297 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20298
20299// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20300#endif
20301
20302#if 0
20303 // The replacementMap should include the symbols associated with the dependentDeclarationList
20304 // and the outlined function (so dependentDeclarationList.size() + 1).
20305 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20306 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20307#endif
20308 }
20309
20310void
20312 {
20313//Tan, August/25/2010: //Re-implement DeleteAST function
20314
20315 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20316 //This class defines the visitors for the MemoryPoolTraversal
20317
20318 class ClassicVisitor : public ROSE_VisitorPattern
20319 {
20320 private:
20321 int SgVariableSymbol_count;
20322 int SgFunctionSymbol_count;
20323 int SgClassDeclaration_count;
20324 int SgTypedefSymbol_count;
20325 int SgMemFuncSymbol_count;
20326 int SgTemplateSymbol_count;
20327 int SgEnumFieldSymbol_count;
20328
20329 SgVariableSymbol* SgVariableSymbolPtr;
20330 SgFunctionSymbol* SgFunctionSymbolPtr;
20331 SgClassSymbol * SgClassSymbolPtr;
20332 SgTypedefSymbol * SgTypedefPtr;
20333 SgEnumFieldSymbol * SgEnumFieldSymbolPtr;
20334 SgMemberFunctionSymbol * SgMemFuncSymbolPtr;
20335 SgTemplateSymbol * SgTemplateSymbolPtr;
20336 SgClassDeclaration * class_defining;
20337 SgTemplateDeclaration * template_defining;
20339 SgTypedefDeclaration * typedef_defining;
20340 SgFunctionDeclaration * function_decl;
20341 SgTemplateInstantiationDecl * templateInstantiate_defining;
20342
20343 public:
20344 ClassicVisitor(SgVariableSymbol* symbol){
20345 SgVariableSymbol_count = 0;
20346 SgVariableSymbolPtr = symbol;
20347 SgFunctionSymbolPtr =NULL;
20348 SgClassSymbolPtr =NULL;
20349 SgTypedefPtr = NULL;
20350 SgMemFuncSymbolPtr =NULL;
20351 class_defining = NULL;
20352 memFunc =NULL;
20353 typedef_defining =NULL;
20354 function_decl = NULL;
20355 SgTemplateSymbolPtr = NULL;
20356 template_defining = NULL;
20357 SgEnumFieldSymbolPtr = NULL;
20358 templateInstantiate_defining =NULL;
20359 }
20360
20361 ClassicVisitor(SgFunctionSymbol* symbol){
20362 SgFunctionSymbol_count = 0;
20363 SgFunctionSymbolPtr = symbol;
20364
20365 // DQ (5/2/2013): Added to fix test2013_141.C.
20366 SgMemFuncSymbol_count =0;
20367
20368 SgVariableSymbolPtr = NULL;
20369 SgClassSymbolPtr =NULL;
20370 SgTypedefPtr = NULL;
20371 SgMemFuncSymbolPtr =NULL;
20372 class_defining = NULL;
20373 memFunc =NULL;
20374 typedef_defining =NULL;
20375 function_decl = NULL;
20376 SgTemplateSymbolPtr = NULL;
20377 template_defining = NULL;
20378 SgEnumFieldSymbolPtr = NULL;
20379 templateInstantiate_defining =NULL;
20380 }
20381
20382 ClassicVisitor(SgClassSymbol* symbol){
20383 SgClassDeclaration_count = 0;
20384 SgClassSymbolPtr = symbol;
20385 SgFunctionSymbolPtr = NULL;
20386 SgVariableSymbolPtr = NULL;
20387 SgTypedefPtr = NULL;
20388 SgMemFuncSymbolPtr =NULL;
20389 class_defining = NULL;
20390 memFunc =NULL;
20391 typedef_defining =NULL;
20392 function_decl = NULL;
20393 SgTemplateSymbolPtr = NULL;
20394 template_defining = NULL;
20395 SgEnumFieldSymbolPtr = NULL;
20396 templateInstantiate_defining =NULL;
20397 }
20398
20399 ClassicVisitor(SgTypedefSymbol* symbol){
20400 SgTypedefSymbol_count =0;
20401 SgTypedefPtr = symbol;
20402 SgClassSymbolPtr = NULL;
20403 SgFunctionSymbolPtr = NULL;
20404 SgVariableSymbolPtr = NULL;
20405 SgMemFuncSymbolPtr =NULL;
20406 class_defining = NULL;
20407 memFunc =NULL;
20408 typedef_defining =NULL;
20409 function_decl = NULL;
20410 SgTemplateSymbolPtr = NULL;
20411 template_defining = NULL;
20412 SgEnumFieldSymbolPtr = NULL;
20413 templateInstantiate_defining =NULL;
20414 }
20415
20416 ClassicVisitor(SgMemberFunctionSymbol* symbol){
20417 SgMemFuncSymbolPtr = symbol;
20418 SgMemFuncSymbol_count =0;
20419 SgTypedefPtr = NULL;
20420 SgClassSymbolPtr = NULL;
20421 SgFunctionSymbolPtr = NULL;
20422 SgVariableSymbolPtr = NULL;
20423 class_defining = NULL;
20424 memFunc =NULL;
20425 typedef_defining =NULL;
20426 function_decl = NULL;
20427 SgTemplateSymbolPtr = NULL;
20428 template_defining = NULL;
20429 SgEnumFieldSymbolPtr = NULL;
20430 templateInstantiate_defining =NULL;
20431 }
20432
20433 ClassicVisitor(SgTemplateSymbol* symbol){
20434 SgTemplateSymbolPtr = symbol;
20435 SgTemplateSymbol_count =0;
20436 SgMemFuncSymbolPtr = NULL;
20437 SgTypedefPtr = NULL;
20438 SgClassSymbolPtr = NULL;
20439 SgFunctionSymbolPtr = NULL;
20440 SgVariableSymbolPtr = NULL;
20441 class_defining = NULL;
20442 memFunc =NULL;
20443 typedef_defining =NULL;
20444 function_decl = NULL;
20445 template_defining = NULL;
20446 SgEnumFieldSymbolPtr = NULL;
20447 templateInstantiate_defining =NULL;
20448 }
20449
20450 ClassicVisitor(SgEnumFieldSymbol* symbol){
20451 SgEnumFieldSymbolPtr = symbol;
20452 SgEnumFieldSymbol_count =0;
20453 SgTemplateSymbolPtr = NULL;
20454 SgMemFuncSymbolPtr = NULL;
20455 SgTypedefPtr = NULL;
20456 SgClassSymbolPtr = NULL;
20457 SgFunctionSymbolPtr = NULL;
20458 SgVariableSymbolPtr = NULL;
20459 class_defining = NULL;
20460 memFunc =NULL;
20461 typedef_defining =NULL;
20462 function_decl = NULL;
20463 template_defining = NULL;
20464 templateInstantiate_defining =NULL;
20465 }
20466
20467
20468 ClassicVisitor(SgClassDeclaration* node){
20469 class_defining = node;
20470 SgMemFuncSymbolPtr = NULL;
20471 SgTypedefPtr = NULL;
20472 SgClassSymbolPtr = NULL;
20473 SgFunctionSymbolPtr = NULL;
20474 SgVariableSymbolPtr = NULL;
20475 memFunc =NULL;
20476 typedef_defining =NULL;
20477 function_decl = NULL;
20478 SgTemplateSymbolPtr = NULL;
20479 template_defining = NULL;
20480 SgEnumFieldSymbolPtr = NULL;
20481 templateInstantiate_defining =NULL;
20482 }
20483
20484 ClassicVisitor(SgTemplateDeclaration* node){
20485 template_defining = node;
20486 class_defining = NULL;
20487 SgMemFuncSymbolPtr = NULL;
20488 SgTypedefPtr = NULL;
20489 SgClassSymbolPtr = NULL;
20490 SgFunctionSymbolPtr = NULL;
20491 SgVariableSymbolPtr = NULL;
20492 memFunc =NULL;
20493 typedef_defining =NULL;
20494 function_decl = NULL;
20495 SgTemplateSymbolPtr = NULL;
20496 SgEnumFieldSymbolPtr = NULL;
20497 templateInstantiate_defining =NULL;
20498 }
20499 ClassicVisitor(SgFunctionDeclaration* node){
20500 function_decl =node;
20501 class_defining = NULL;
20502 SgMemFuncSymbolPtr = NULL;
20503 SgTypedefPtr = NULL;
20504 SgClassSymbolPtr = NULL;
20505 SgFunctionSymbolPtr = NULL;
20506 SgVariableSymbolPtr = NULL;
20507 memFunc =NULL;
20508 typedef_defining =NULL;
20509 SgTemplateSymbolPtr = NULL;
20510 template_defining = NULL;
20511 SgEnumFieldSymbolPtr = NULL;
20512 templateInstantiate_defining =NULL;
20513 }
20514
20515 ClassicVisitor(SgMemberFunctionDeclaration* node){
20516 memFunc = node;
20517 function_decl =NULL;
20518 class_defining = NULL;
20519 SgMemFuncSymbolPtr = NULL;
20520 SgTypedefPtr = NULL;
20521 SgClassSymbolPtr = NULL;
20522 SgFunctionSymbolPtr = NULL;
20523 SgVariableSymbolPtr = NULL;
20524 typedef_defining =NULL;
20525 SgTemplateSymbolPtr = NULL;
20526 template_defining = NULL;
20527 SgEnumFieldSymbolPtr = NULL;
20528 templateInstantiate_defining =NULL;
20529 }
20530
20531 ClassicVisitor(SgTypedefDeclaration* node){
20532 typedef_defining = node;
20533 memFunc = NULL;
20534 function_decl =NULL;
20535 class_defining = NULL;
20536 SgMemFuncSymbolPtr = NULL;
20537 SgTypedefPtr = NULL;
20538 SgClassSymbolPtr = NULL;
20539 SgFunctionSymbolPtr = NULL;
20540 SgVariableSymbolPtr = NULL;
20541 SgTemplateSymbolPtr = NULL;
20542 template_defining = NULL;
20543 SgEnumFieldSymbolPtr = NULL;
20544 templateInstantiate_defining =NULL;
20545 }
20546
20547 ClassicVisitor(SgTemplateInstantiationDecl* node){
20548 templateInstantiate_defining =node;
20549 typedef_defining = NULL;
20550 memFunc = NULL;
20551 function_decl =NULL;
20552 class_defining = NULL;
20553 SgMemFuncSymbolPtr = NULL;
20554 SgTypedefPtr = NULL;
20555 SgClassSymbolPtr = NULL;
20556 SgFunctionSymbolPtr = NULL;
20557 SgVariableSymbolPtr = NULL;
20558 SgTemplateSymbolPtr = NULL;
20559 template_defining = NULL;
20560 SgEnumFieldSymbolPtr = NULL;
20561 }
20562
20563
20564 // SgVariableSymbol and SgEnumFieldSymbol
20565 void visit(SgInitializedName* node)
20566 {
20567 if(SgVariableSymbolPtr !=NULL)
20568 {
20569 if(node->get_scope()!=NULL)
20570 {
20571 // DQ (5/21/2013): We want to restrict access to the symbol table.
20572 if(node->get_scope()->get_symbol_table()!=NULL)
20573 {
20575 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20576 }
20577 }
20578 }
20579
20580 if(SgEnumFieldSymbolPtr !=NULL)
20581 {
20582 if(node->get_scope()!=NULL)
20583 {
20584 // DQ (5/21/2013): We want to restrict access to the symbol table.
20585 if(node->get_scope()->get_symbol_table()!=NULL)
20586 {
20588 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20589 }
20590 }
20591 }
20592 }
20593
20594 void visit(SgVarRefExp* node)
20595 {
20596 if(SgVariableSymbolPtr !=NULL){
20597 SgVariableSymbol* s = node->get_symbol();
20598 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20599 }
20600 }
20601
20602 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20603
20604 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20605
20606
20607 // SgFunctionSymbol
20608 void visit(SgFunctionDeclaration* node) {
20609 if(SgFunctionSymbolPtr !=NULL){
20610 if(node->get_scope()!=NULL){
20611 // DQ (5/21/2013): We want to restrict access to the symbol table.
20612 if(node->get_scope()->get_symbol_table()!=NULL)
20613 {
20615 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20616 }
20617 }
20618 }
20619#if 0
20620 if(function_decl!=NULL){
20621 if(node->get_symbol_from_symbol_table() == NULL){
20624 if(node!=function_decl && (define==function_decl || first_nondefine==function_decl)) delete node;
20625 }
20626 }
20627#endif
20628 }
20629
20630 void visit(SgFunctionRefExp* node)
20631 {
20632#if 0
20633 printf ("In visit(SgFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20634#endif
20635 if (SgFunctionSymbolPtr !=NULL)
20636 {
20637 SgFunctionSymbol* s = node->get_symbol_i();
20638 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20639 {
20640 SgFunctionSymbol_count++;
20641#if 0
20642 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20643#endif
20644 }
20645 }
20646 }
20647
20648 // DQ (5/2/2013): Added support for SgMemberFunctionRefExp which is not derived from SgFunctionRefExp.
20649 void visit(SgMemberFunctionRefExp* node)
20650 {
20651#if 0
20652 printf ("In visit(SgMemberFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20653#endif
20654 if (SgFunctionSymbolPtr !=NULL)
20655 {
20656 SgFunctionSymbol* s = node->get_symbol_i();
20657 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20658 {
20659 SgFunctionSymbol_count++;
20660#if 0
20661 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20662#endif
20663 }
20664 }
20665 }
20666
20667 void visit(SgUserDefinedBinaryOp* node)
20668 {
20669 if (SgFunctionSymbolPtr !=NULL){
20670 SgFunctionSymbol* s = node->get_symbol();
20671 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20672 }
20673 }
20674
20675 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20676
20677 // SgClassSymbol
20678 void visit(SgClassDeclaration* node)
20679 {
20680 if(SgClassSymbolPtr !=NULL){
20681 if(node->get_scope()!=NULL){
20682 if(node->get_scope()->get_symbol_table()!=NULL)
20683 {
20685 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20686 }
20687 }
20688 }
20689
20690 if(class_defining!=NULL) {
20691 if(node->get_symbol_from_symbol_table() == NULL){
20694 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20695 delete node;
20696 }
20697 }
20698 }
20699
20700 void visit(SgTemplateInstantiationDecl* node)
20701 {
20702 if(SgClassSymbolPtr !=NULL){
20703 if(node->get_scope()!=NULL){
20704 if(node->get_scope()->get_symbol_table()!=NULL)
20705 {
20707 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20708 }
20709 }
20710 }
20711
20712 if(templateInstantiate_defining!=NULL) {
20713 if(node->get_scope()!=NULL){
20714 if(node->get_scope()->get_symbol_table()!=NULL)
20715 {
20716 if(node->get_symbol_from_symbol_table() == NULL){
20719 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20720 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20721 foreach (SgTemplateArgument* element, tempargs){
20722 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20723 if(temparg){
20724 delete temparg;
20725 }
20726 printf("SgTemplateArg in Memory Pool traversal\n");
20727 }*/
20728 delete node;
20729 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20730 }
20731 }
20732 }
20733 }
20734 }
20735 }
20736
20737 void visit(SgThisExp* node)
20738 {
20739 if (SgClassSymbolPtr !=NULL){
20740 SgSymbol* s = node->get_class_symbol();
20741 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20742 }
20743 }
20744
20745 void visit(SgClassNameRefExp* node)
20746 {
20747 if (SgClassSymbolPtr !=NULL){
20748 SgSymbol* s = node->get_symbol();
20749 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20750 }
20751 }
20752
20753
20754 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20755
20756
20757 // SgMemberFunctionSymbol
20758 void visit(SgCtorInitializerList* node)
20759 {
20760 if(memFunc !=NULL){
20762 if(func == memFunc){
20763 delete node;
20764 }
20765 }
20766 }
20767
20768
20769 void visit(SgMemberFunctionDeclaration* node)
20770 {
20771 if (SgMemFuncSymbolPtr !=NULL){
20772 if(node->get_scope()!=NULL){
20773 if(node->get_scope()->get_symbol_table()!=NULL)
20774 {
20775 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20776 if(symbol == SgMemFuncSymbolPtr){
20777 SgMemFuncSymbol_count++;
20778 }
20779 }
20780 }
20781 }
20782 }
20783
20785 {
20786 if (SgMemFuncSymbolPtr !=NULL){
20787 if(node->get_scope()!=NULL){
20788 if(node->get_scope()->get_symbol_table()!=NULL)
20789 {
20790 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
20791 if(symbol == SgMemFuncSymbolPtr){
20792 SgMemFuncSymbol_count++;
20793 }
20794 }
20795 }
20796 }
20797 }
20798
20799
20800
20801 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
20802
20803
20804 // SgTypedefSymbol
20805 void visit(SgTypedefDeclaration* node)
20806 {
20807 if(SgTypedefPtr!=NULL){
20808 if(node->get_scope()!=NULL){
20809 if(node->get_scope()->get_symbol_table()!=NULL)
20810 {
20812 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
20813 }
20814 }
20815 }
20816 if(typedef_defining!=NULL){
20818 if(typedef_define == typedef_defining && node != typedef_defining ) {
20819 delete node;
20820 }
20821 }
20822 }
20823
20824 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
20825
20826
20827
20828 void visit(SgTemplateDeclaration* node)
20829 {
20830 if (SgTemplateSymbolPtr !=NULL){
20831 if(node->get_scope()!=NULL){
20832 if(node->get_scope()->get_symbol_table()!=NULL)
20833 {
20834 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
20835 if(symbol == SgTemplateSymbolPtr){
20836 SgTemplateSymbol_count++;
20837 }
20838 }
20839 }
20840 }
20841
20842 if(template_defining !=NULL) {
20843 if(node->get_scope()!=NULL){
20844 if(node->get_scope()->get_symbol_table()!=NULL)
20845 {
20846 if(node->get_symbol_from_symbol_table() == NULL){
20849 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
20850 delete node;
20851
20852 }
20853 }
20854 }
20855 }
20856 }
20857 }
20858
20859 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
20860
20861 };
20862
20863
20864 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
20865 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
20866 {
20867 public:
20868
20869 void visit (SgNode* node)
20870 {
20871 //These nodes are manually deleted because they cannot be visited by the traversal
20873 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
20875#if 0
20876 printf ("In DeleteAST::visit(): node = %p = %s \n",node,node->class_name().c_str());
20877#endif
20878#if 0
20879 // DQ (3/2/2014): I think this might be a problem...
20880 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20881 if (isSgScopeStatement(node) !=NULL)
20882 {
20883 SgScopeStatement* scope = isSgScopeStatement(node);
20884#if 1
20885 printf ("Deleting the scopes type table: scope->get_type_table() = %p \n",scope->get_type_table());
20886#endif
20887 delete scope->get_type_table();
20888 }
20889#endif
20890#if 0
20891 // DQ (3/2/2014): I think this might be a problem...
20892 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
20893 if (isSgTypeTable(node) !=NULL)
20894 {
20895 SgTypeTable* typeTable = isSgTypeTable(node);
20896#if 1
20897 printf ("Deleting the type table (SgSymbolTable): typeTable->get_type_table() = %p \n",typeTable->get_type_table());
20898#endif
20899 delete typeTable->get_type_table();
20900 }
20901#endif
20902 if(isSgInitializedName(node) !=NULL){
20903 //remove SgVariableDefinition
20904 SgDeclarationStatement* var_def;
20905 var_def = ((SgInitializedName *)node)->get_definition();
20906 if(isSgVariableDefinition(var_def) !=NULL){
20907 delete var_def;
20908 //printf("A SgVariableDefinition was deleted\n");
20909 }
20910
20911
20912 //remove SgVariableSymbol
20913 if(isSgInitializedName(node)->get_scope()!=NULL){
20914 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
20915 {
20916 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
20917 if(isSgVariableSymbol(symbol) !=NULL){
20918 ClassicVisitor visitor((SgVariableSymbol*)symbol);
20919 traverseMemoryPoolVisitorPattern(visitor);
20920 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20921 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20922 delete symbol;
20923 //printf("A SgVariableSymbol was deleted\n");
20924 }
20925 }
20926
20927 if(isSgEnumFieldSymbol(symbol) !=NULL){
20928 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol);
20929 traverseMemoryPoolVisitorPattern(visitor);
20930 if(visitor.get_num_EnumField_pointers()==1){
20931 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
20932 delete symbol;
20933 //printf("A SgEnumFieldSymbol was deleted\n");
20934 }
20935 }
20936
20937 }
20938 }
20939 }
20940
20941 if(isSgVarRefExp(node) !=NULL){
20942 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
20943 ClassicVisitor visitor(symbol);
20944 traverseMemoryPoolVisitorPattern(visitor);
20945 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
20946 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20947 delete symbol;
20948 //printf("A SgVariableSymbol was deleted\n");
20949 }
20950 }
20951
20952 /*////////////////////////////////////////////////
20953 /remove SgFunctionSymbol
20955
20956 {
20957 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
20958 if (funcDecl != NULL){
20959 if (isSgMemberFunctionDeclaration(node) == NULL) {
20960 if (funcDecl->get_scope() != NULL) {
20961 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
20962 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
20963 ClassicVisitor visitor((SgFunctionSymbol *)symbol);
20964 traverseMemoryPoolVisitorPattern(visitor);
20965 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
20966 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
20967 delete symbol;
20968 //printf("A SgFunctionSymbol was deleted\n");
20969 }
20970 ClassicVisitor visitor1((SgFunctionDeclaration *)node);
20971 traverseMemoryPoolVisitorPattern(visitor1);
20972 }
20973 }
20974 }
20975 }
20976 }
20977
20978 if(isSgFunctionRefExp(node) !=NULL)
20979 {
20980#if 0
20981 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(node);
20982 ROSE_ASSERT(functionRefExp->get_symbol_i() != NULL);
20983 printf ("In DeleteAST::visit(): functionRefExp->get_symbol_i() = %p = %s \n",functionRefExp->get_symbol_i(),functionRefExp->get_symbol_i()->class_name().c_str());
20984#endif
20985 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
20986 ClassicVisitor visitor(symbol);
20987 traverseMemoryPoolVisitorPattern(visitor);
20988 if(visitor.get_num_Function_pointers()==1)
20989 {
20990 // only one reference to this FunctionSymbol => safe to delete
20991 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
20992 delete symbol;
20993 //printf("A SgFunctionSymbol was deleted\n");
20994 }
20995
20996 }
20997
20998 if(isSgUserDefinedBinaryOp(node) !=NULL){
20999 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
21000 ClassicVisitor visitor(symbol);
21001 traverseMemoryPoolVisitorPattern(visitor);
21002 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
21003 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21004 delete symbol;
21005 //printf("A SgFunctionSymbol was deleted\n");
21006 }
21007 }
21008
21009 /*/
21010 /remove SgTypedefSymbol
21012
21013 if(isSgTypedefDeclaration(node) !=NULL){
21014 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
21015 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21016 {
21017 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
21018 if(isSgTypedefSymbol(symbol)){
21019 ClassicVisitor visitor((SgTypedefSymbol*) symbol);
21020 traverseMemoryPoolVisitorPattern(visitor);
21021 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
21022 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21023 delete symbol;
21024 //printf("A SgTypedefSymbol was deleted\n");
21025 }
21026 }
21027 }
21028 }
21029
21030 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
21031 ClassicVisitor visitor1((SgTypedefDeclaration*) node);
21032 traverseMemoryPoolVisitorPattern(visitor1);
21033 }
21034 }
21035
21036 /*////////////////////////////////////////////////
21037 /remove SgNamespaceDeclarationSymbol
21039
21040 if(isSgNamespaceDeclarationStatement(node) !=NULL){
21041 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
21042 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21043 {
21044 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
21045 if(isSgNamespaceSymbol(symbol)){
21046 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21047 delete symbol;
21048 //printf("A SgNamespaceSymbol was deleted\n");
21049 }
21050 }
21051 }
21052 }
21053
21054
21055 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
21056 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
21057 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21058 {
21059 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
21060 if(isSgNamespaceSymbol(symbol)){
21061 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21062 delete symbol;
21063 //printf("A SgNamespaceSymbol was deleted\n");
21064 }
21065 }
21066 }
21067 }
21068
21069
21070 /*/
21071 /remove SgLabelSymbol
21073
21074 if(isSgLabelStatement(node) !=NULL){
21075 if(((SgLabelStatement*)node)->get_scope()!=NULL){
21076 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21077 {
21078 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
21079 if(isSgLabelSymbol(symbol)){
21080 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21081 delete symbol;
21082 //printf("A SgLabelSymbol was deleted\n");
21083 }
21084 }
21085 }
21086 }
21087
21088 if(isSgLabelRefExp(node) !=NULL){
21089 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
21090 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21091 delete symbol;
21092 //printf("A SgLabelSymbol was deleted\n");
21093 }
21094
21095
21096 /*////////////////////////////////////////////////
21097 /remove SgEnumSymbol
21099
21100 if(isSgEnumDeclaration(node) !=NULL){
21101 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
21102 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21103 {
21104 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
21105 if(isSgEnumSymbol(symbol) !=NULL){
21106 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21107 delete symbol;
21108 //printf("A SgEnumSymbol was deleted\n");
21109 }
21110 }
21111 }
21112 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21113 if(type !=NULL){
21114 delete type;
21115 //printf("A SgEnumType was deleted\n");
21116 }
21117 }
21118
21119
21120 /*/
21121 /remove SgClassSymbol
21123
21124 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21125 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21126 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21127 {
21128 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21129 if(isSgClassSymbol(symbol) !=NULL){
21130 ClassicVisitor visitor((SgClassSymbol*)symbol);
21131 traverseMemoryPoolVisitorPattern(visitor);
21132 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21133 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21134 delete symbol;
21135 //printf("A SgClassSymbol was deleted\n");
21136 }
21137 }
21138 }
21139 }
21140
21141 ClassicVisitor visitor((SgClassDeclaration*) node );
21142 traverseMemoryPoolVisitorPattern(visitor);
21143
21144 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21145 if(type !=NULL){
21146 delete type;
21147 //printf("A SgClassType was deleted\n");
21148 }
21149 }
21150
21151 if(isSgThisExp(node) !=NULL){
21152 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21153 ClassicVisitor visitor((SgClassSymbol*)symbol);
21154 traverseMemoryPoolVisitorPattern(visitor);
21155 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21156 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21157 delete symbol;
21158 //printf("A SgClassSymbol was deleted\n");
21159 }
21160
21161 }
21162
21163 if(isSgClassNameRefExp(node) !=NULL){
21164 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21165 if(isSgClassSymbol(symbol) !=NULL)
21166 {
21167 ClassicVisitor visitor((SgClassSymbol*)symbol);
21168 traverseMemoryPoolVisitorPattern(visitor);
21169 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21170 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21171 delete symbol;
21172 //printf("A SgClassSymbol was deleted\n");
21173 }
21174 }
21175 }
21176
21177 /*////////////////////////////////////////////////
21178 /remove SgMemberFunctionSymbol
21180
21181
21182 if(isSgMemberFunctionDeclaration(node) !=NULL){
21183 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21184 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21185 {
21186 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21187 if(isSgMemberFunctionSymbol(symbol)){
21188 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21189 traverseMemoryPoolVisitorPattern(visitor);
21190 if(visitor.get_num_memFunc_pointers()==1){
21191 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21192 delete symbol;
21193 //printf("A SgMemberFunctionSymbol was deleted\n");
21194 }
21195 }
21196 }
21197 }
21198 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21199 traverseMemoryPoolVisitorPattern(visitor);
21200
21201 }
21202//Tan: I have no idea why the codes below cannot work. Perhaps it conflicts with some prior works
21203#if 0
21204 if(isSgMemberFunctionRefExp(node) !=NULL){
21205 SgMemberFunctionSymbol* symbol = ((SgMemberFunctionRefExp*)node)->get_symbol_i();
21206 ClassicVisitor visitor(symbol);
21207 traverseMemoryPoolVisitorPattern(visitor);
21208 if(visitor.get_num_memFunc_pointers()==1){ //only one reference to this symbol => safe to delete
21209 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21210 delete symbol;
21211 //printf("A SgClassSymbol was deleted\n");
21212 }
21213
21214 }
21215
21216 if(isSgFunctionType(node) !=NULL){
21217 SgSymbol* symbol = ((SgFunctionType*)node)->get_symbol_from_symbol_table();
21218 if(isSgFunctionTypeSymbol(symbol)){
21219 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21220 delete symbol;
21221 //printf("A SgFunctionTypeSymbol was deleted\n");
21222 }
21223 }
21224#endif
21225
21226 /*/
21229
21230 if(isSgInterfaceStatement(node) !=NULL){
21231 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21232 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21233 {
21234 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21235 if(isSgInterfaceSymbol(symbol)){
21236 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21237 delete symbol;
21238 //printf("A SgInterfaceSymbol was deleted\n");
21239 }
21240 }
21241 }
21242
21243 }
21244
21245
21246 if(isSgModuleStatement(node) !=NULL){
21247 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21248 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21249 {
21250 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21251 if(isSgModuleSymbol(symbol)){
21252 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21253 delete symbol;
21254 //printf("A SgModuleSymbol was deleted\n");
21255 }
21256 }
21257 }
21258
21259 }
21260
21261
21262//Tan: I got stuck in deleting the SgTemplateArgument
21263#if 0
21264 if(isSgTemplateInstantiationMemberFunctionDecl(node) !=NULL){
21265 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()!=NULL){
21266 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21267 {
21268 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21269 if(isSgMemberFunctionSymbol(symbol)){
21270 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21271 traverseMemoryPoolVisitorPattern(visitor);
21272 if(visitor.get_num_memFunc_pointers()==1){
21273 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21274 delete symbol;
21275 //printf("A SgMemberFunctionSymbol was deleted\n");
21276 }
21277 }
21278 }
21279 }
21280 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21281 traverseMemoryPoolVisitorPattern(visitor);
21282 }
21283
21284 if(isSgTemplateDeclaration(node) !=NULL){
21285 if(((SgTemplateDeclaration*)node)->get_scope()!=NULL){
21286 if(((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21287 {
21288 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21289 ClassicVisitor visitor((SgTemplateSymbol*)symbol);
21290 traverseMemoryPoolVisitorPattern(visitor);
21291 if(visitor.get_num_Template_pointers()==1){
21292 ((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21293 delete symbol;
21294 printf("A SgTemplateSymbol was deleted\n");
21295 }
21296 }
21297 }
21298 //if(isSgTemplateDeclaration(node) == ((SgTemplateDeclaration*)node)->get_firstNondefiningDeclaration()){
21299 ClassicVisitor visitor1((SgTemplateDeclaration*) node );
21300 traverseMemoryPoolVisitorPattern(visitor1);
21301 //}
21302
21303 }
21304
21305 if(isSgInterfaceStatement(node) !=NULL){
21306 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21307 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21308 {
21309 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21310 if(isSgInterfaceSymbol(symbol)){
21311 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21312 delete symbol;
21313 //printf("A SgInterfaceSymbol was deleted\n");
21314 }
21315 }
21316 }
21317
21318 }
21319
21320
21321 if(isSgModuleStatement(node) !=NULL){
21322 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21323 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21324 {
21325 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21326 if(isSgModuleSymbol(symbol)){
21327 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21328 delete symbol;
21329 //printf("A SgModuleSymbol was deleted\n");
21330 }
21331 }
21332 }
21333
21334 }
21335
21336 if(isSgTemplateInstantiationDecl(node) !=NULL){
21337 if(((SgTemplateInstantiationDecl*)node)->get_scope()!=NULL){
21338 if(((SgTemplateInstantiationDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21339 {
21340 SgSymbol* symbol = ((SgTemplateInstantiationDecl*)node)->get_symbol_from_symbol_table();
21341 if(isSgClassSymbol(symbol)){
21342 ClassicVisitor visitor((SgClassSymbol*)symbol);
21343 traverseMemoryPoolVisitorPattern(visitor);
21344 if(visitor.get_num_Class_pointers()==1){
21345 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21346 delete symbol;
21347 }
21348 }
21349 }
21350 }
21351 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21352 if(type !=NULL){
21353 delete type;
21354 //printf("A SgClassType was deleted\n");
21355 }
21356
21357 vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
21358 foreach (SgTemplateArgument* element, tempargs){
21359 SgTemplateArgument* temparg = isSgTemplateArgument(element);
21360 if(temparg){
21361 delete temparg;
21362 }
21363 printf("SgTemplateArg in normal traversal\n");
21364 }
21365 printf("SgTemplateInstantiationDecl in normal traversal\n");
21366
21367 ClassicVisitor visitor((SgTemplateInstantiationDecl*) node);
21368 traverseMemoryPoolVisitorPattern(visitor);
21369 }
21370
21371#endif
21372#if 0
21373 printf ("Deleting node = %p = %s = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
21374#endif
21375 // Normal nodes will be removed in a post-order way
21376 delete node;
21377#if 0
21378 printf ("After delete node: node = %p = %s \n",node,node->class_name().c_str());
21379#endif
21380 }
21381 };
21382
21383
21384 DeleteAST deleteTree;
21385
21386 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21387 deleteTree.traverse(n,postorder);
21388
21389#if 0
21390 printf ("Leaving SageInterface::deleteAST(): n = %p = %s \n",n,n->class_name().c_str());
21391#endif
21392 }
21393
21394
21395
21396
21397#ifndef USE_ROSE
21398// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21399// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21400// In the post-processing either:
21401// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21402// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21403// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21404// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21405// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21406// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21407// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21408// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21409// that are not use post-processed. This is the special purpose function that we need.
21410//
21411// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21412//
21414 {
21415 struct Visitor: public AstSimpleProcessing
21416 {
21417 virtual void visit(SgNode* n)
21418 {
21419 SgExpression* expression = isSgExpression(n);
21420 if (expression != NULL)
21421 {
21422 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21423 }
21424
21425 delete (n);
21426 }
21427 };
21428
21429 Visitor().traverse(root, postorder);
21430 }
21431#endif
21432 // move symbol table from one scope to another
21433static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21434{
21435 // Move the symbol table
21436 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21437 ASSERT_not_null(sourceBlock->get_symbol_table());
21438 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21439 for (SgInitializedName* iname : initname_vec)
21440 {
21441 SgSymbol* symbol = s_table->find(iname);
21442 ASSERT_not_null(symbol);
21443 }
21444 // entirely move source block's symbol table to target block
21445 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21446
21447 ASSERT_not_null(sourceBlock);
21448 ASSERT_not_null(targetBlock);
21449 ASSERT_not_null(targetBlock->get_symbol_table());
21450 ASSERT_not_null(sourceBlock->get_symbol_table());
21451 targetBlock->get_symbol_table()->set_parent(targetBlock);
21452
21453 ASSERT_not_null(sourceBlock->get_symbol_table());
21454 sourceBlock->set_symbol_table(nullptr);
21455
21456 // Reset with a valid symbol table
21457 sourceBlock->set_symbol_table(new SgSymbolTable());
21458 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21459
21460 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21461 for (SgInitializedName* iname : initname_vec)
21462 {
21463 SgSymbol* symbol = s_table->find(iname);
21464 ASSERT_not_null(symbol);
21465 }
21466
21467 // Liao, 11/26/2019 make sure init names have symbols after the move.
21468 for (SgInitializedName* iname : initname_vec)
21469 {
21470 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21471 ASSERT_not_null(symbol);
21472 }
21473}
21474
21475// helper function to move a single statement or declaration from a block to another
21476static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21477{
21478 // append statement to the target block
21479 targetBlock->append_statement(stmt);
21480
21481 // Make sure that the parents are set.
21482 ASSERT_require(stmt->get_parent() == targetBlock);
21483 if (stmt->hasExplicitScope())
21484 {
21485 if (stmt->get_scope() != targetBlock)
21486 {
21487 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21488 {
21489 // why only move if it is a first nondefining declaration?
21490 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21491 // comment out the if condition for now. 1/20/2021
21492 //
21493 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21494 // The func declaration should be moved along with the call site.
21495 // The scope should be set to the new block also
21496 // Liao 1/14/2011
21497 func->set_scope(targetBlock);
21498 // This is needed to move functions in Ada package body into C++ namespace
21499 // We may have compiler generated first nondefining declaration. We need to move its scope also
21500 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21501 if (func != nondef_decl)
21502 {
21503 ASSERT_not_null(nondef_decl);
21504 ASSERT_not_null(nondef_decl->get_file_info());
21505 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21506 nondef_decl->set_scope(targetBlock);
21507 }
21508 }
21509 }
21510 else if (auto labelStmt = isSgLabelStatement(stmt))
21511 {
21512 if (labelStmt->get_scope() == sourceBlock) {
21513 labelStmt->set_scope(targetBlock);
21514 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21515 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21516 }
21517 }
21518 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21519 {
21520 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21521 // The issues are fixed in the switch statement below but this test is needed
21522 // so that the warning message immediately below is not triggered.
21523 }
21524 else
21525 {
21526 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21527 << stmt->class_name() << "\n";
21528 }
21529 }
21530 }
21531
21532 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21533 if (declaration != nullptr)
21534 {
21535 // Need to reset the scope from sourceBlock to targetBlock.
21536 switch(declaration->variantT())
21537 {
21538 // There will be other cases to handle, but likely not all declaration will be possible to support.
21539
21540 case V_SgVariableDeclaration:
21541 {
21542 // Reset the scopes on any SgInitializedName objects.
21543 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21544 SgInitializedNamePtrList & l = varDecl->get_variables();
21545 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21546 {
21547 // reset the scope, but make sure it was set to sourceBlock to make sure.
21548 // This might be an issue for extern variable declaration that have a scope
21549 // in a separate namespace of a static class member defined external to
21550 // its class, etc. I don't want to worry about those cases right now.
21551
21552 SgInitializedName * init_name = (*ii);
21553
21554 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21555 SgType* var_type = init_name->get_type();
21556 if (SgModifierType* mod_type = isSgModifierType(var_type))
21557 {
21558 var_type = mod_type->get_base_type();
21559 }
21560
21561 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21562 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21563 // be that class types are not moved correctly either.
21564 //
21565 if (isSgEnumType(var_type))
21566 {
21567 SgEnumType* enum_type = isSgEnumType(var_type);
21568 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21569 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21570 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21571
21572 if (decl->get_scope() == sourceBlock)
21573 {
21574 // Needs to be moved
21575 def_decl->set_scope(targetBlock);
21576 nondef_decl->set_scope(targetBlock);
21577 nondef_decl->set_parent(targetBlock);
21578
21579 // Move the scope of the enumerators to the new block as well
21580 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21581 {
21582 enumerator->set_scope(targetBlock);
21583 }
21584 }
21585 }
21586 else if (isSgJovialTableType(var_type))
21587 {
21588 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21589 SgDeclarationStatement* decl = table_type->get_declaration();
21590 if (decl->get_scope() == sourceBlock)
21591 {
21592 // Needs to be moved
21595 def_decl->set_scope(targetBlock);
21596 nondef_decl->set_scope(targetBlock);
21597 nondef_decl->set_parent(targetBlock);
21598 }
21599 }
21600
21601 // Must also move the symbol into the source block, Liao 2019/8/14
21602 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21603 ASSERT_not_null(var_sym);
21604 SgScopeStatement * old_scope = var_sym -> get_scope();
21605#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21606 if (old_scope != sourceBlock)
21607 {
21608 old_scope->remove_symbol (var_sym);
21609 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21610 }
21611#endif
21612 init_name->set_scope(targetBlock);
21613 initname_vec.push_back(init_name);
21614 }
21615 break;
21616 }
21617 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21618 {
21619 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21620 ASSERT_not_null(funcDecl);
21621#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21622 // move function symbols also: search_for_symbol_from_symbol_table()
21624 if (func_sym)
21625 {
21626 SgScopeStatement * old_scope = func_sym -> get_scope();
21627 if (old_scope != sourceBlock)
21628 {
21629 old_scope->remove_symbol (func_sym);
21630 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21631 }
21632 }
21633#endif
21634 break;
21635 }
21636 // needed to move Ada record into definition of C++ namespace
21637 case V_SgProgramHeaderStatement:
21638 case V_SgProcedureHeaderStatement:
21639 case V_SgClassDeclaration:
21640 case V_SgEnumDeclaration:
21641 {
21642 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21643 ASSERT_not_null(nondef_decl);
21644
21645 nondef_decl->set_parent(targetBlock);
21646 nondef_decl->set_scope(targetBlock);
21647
21648 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21649 if (def_decl)
21650 {
21651 def_decl->set_parent(targetBlock);
21652 def_decl->set_scope(targetBlock);
21653 }
21654 else
21655 {
21656 // Set the scope of the function arguments
21657 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21658 for (auto arg : proc->get_parameterList()->get_args()) {
21659 if (arg->get_scope() != proc->get_scope()) {
21660 // Note: arg (is an SgInitializedName) from the parameter list does not have
21661 // a symbol in the scope of the procedure declaration (proc). Should add
21662 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21663 arg->set_scope(proc->get_scope());
21664 }
21665 }
21666 }
21667 }
21668
21669 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21670 if (enum_decl)
21671 {
21672 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21673 for (SgInitializedName* name : enum_decl->get_enumerators())
21674 {
21675 name->set_scope(targetBlock);
21676 }
21677 }
21678 break;
21679 }
21680 case V_SgJovialTableStatement:
21681 {
21682 // [RC-135, Rasmussen 9/21/2020]
21683 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21684 ROSE_ASSERT (table);
21685
21688 nondef_decl->set_parent(targetBlock);
21689 nondef_decl->set_scope(targetBlock);
21690 def_decl->set_scope(targetBlock);
21691 break;
21692 }
21693 case V_SgTypedefDeclaration:
21694 {
21695 // [RC-227, Rasmussen 10/19/2020]
21696 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21697 ASSERT_not_null(typedef_decl);
21698 typedef_decl->set_parent(targetBlock);
21699 typedef_decl->set_scope(targetBlock);
21700 break;
21701 }
21702 case V_SgAttributeSpecificationStatement:
21703 case V_SgEmptyDeclaration:
21704 case V_SgFortranIncludeLine:
21705 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21706 case V_SgJovialDefineDeclaration:
21707 case V_SgJovialDirectiveStatement:
21708 case V_SgJovialLabelDeclaration:
21709 case V_SgJovialOverlayDeclaration:
21710 case V_SgPragmaDeclaration:
21711 case V_SgAdaAttributeClause:
21712 break;
21713 default:
21714 {
21715 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());
21716 declaration->get_file_info()->display("file info");
21717 ROSE_ABORT();
21718 }
21719 }
21720 } // end if
21721}
21722
21723// different handling for scopes with declarations only
21724template <class T1, class T2>
21725void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21726{
21727 // This function moves statements from one block to another (used by the outliner).
21728 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21729 ROSE_ASSERT (sourceBlock && targetBlock);
21730 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21731 if ((void*)sourceBlock == (void*)targetBlock)
21732 {
21733 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21734 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21735 return;
21736 }
21737
21738 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21739 std::vector <SgInitializedName*> initname_vec;
21740
21741 for (auto stmt : srcStmts)
21742 {
21743 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21744 }
21745
21746 // Remove the statements in the sourceBlock
21747 srcStmts.clear();
21748 ROSE_ASSERT(srcStmts.empty() == true);
21749 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21750
21751 // move symbol table from one scope to another
21752 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21753
21754 // Liao 2/4/2009
21755 // Finally , move preprocessing information attached inside the source block to the target block
21756 // Outliner uses this function to move a code block to the outlined function.
21757 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21758 // to the target block to match #if (which is attached
21759 // before some statement moved to the target block)
21760 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21761}
21762
21763
21764// source and destination class, both are derived classes of scope statement but with support of get_statements()
21765template <class T1, class T2>
21766void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21767{
21768 // This function moves statements from one block to another (used by the outliner).
21769 ROSE_ASSERT (sourceBlock && targetBlock);
21770 if ((void*)sourceBlock == (void*)targetBlock)
21771 {
21772 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21773 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21774 return;
21775 }
21776
21777 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
21778 std::vector <SgInitializedName*> initname_vec;
21779
21780 for (SgStatement* stmt : srcStmts)
21781 {
21782 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21783 }
21784
21785 // Remove the statements in the sourceBlock
21786 srcStmts.clear();
21787 ROSE_ASSERT(srcStmts.empty() == true);
21788 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
21789
21790 // move symbol table from one scope to another
21791 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21792
21793 // Liao 2/4/2009
21794 // Finally , move preprocessing information attached inside the source block to the target block
21795 // Outliner uses this function to move a code block to the outlined function.
21796 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21797 // to the target block to match #if (which is attached
21798 // before some statement moved to the target block)
21799 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21800
21801}
21802
21803static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
21804{
21805 ASSERT_not_null(decl);
21807 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
21808
21809 ASSERT_require(local_def && global_def && (local_def!=global_def));
21810
21811 for (auto symbol : local_def->get_symbol_table()->get_symbols())
21812 {
21813 SgSymbol *orig_sym = isSgSymbol(symbol);
21814 ASSERT_not_null(orig_sym);
21815 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
21816 global_def->get_symbol_table()->insert (asym->get_name(), asym);
21817 }
21818}
21819
21820//TODO: now with more types, we need to use template functions
21822{
21823 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21824 //create alias symbols in its global definition
21825 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21826}
21827
21829{
21830 moveStatementsBetweenScopes(sourceBlock, targetBlock);
21831 //create alias symbols in its global definition
21832 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
21833}
21834
21836{
21837 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
21838}
21839
21840void
21842{
21843 moveStatementsBetweenScopes (sourceBlock, targetBlock);
21844}
21845
21847// TODO, expose to SageInterface namespace
21849{
21850 bool rt = false;
21851 ROSE_ASSERT (func != NULL);
21852 SgNode* p = func->get_parent();
21853 ROSE_ASSERT (p != NULL);
21854 SgLambdaExp* le = isSgLambdaExp (p);
21855 if (le && le->get_lambda_function() == func)
21856 rt = true;
21857 return rt;
21858}
21859
21860// check if a variable reference is this->a[i] inside of a lambda function
21861// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
21862// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
21863// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
21865{
21866 bool rt = false;
21867#ifdef _MSC_VER
21868 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
21869#else
21870 ROSE_ASSERT (varRef!= NULL);
21871 SgNode* parent = varRef->get_parent();
21872 if (SgArrowExp *p = isSgArrowExp(parent))
21873 {
21874 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
21875 if (te != NULL)
21876 {
21877 SgClassSymbol* csym = te->get_class_symbol();
21878 ROSE_ASSERT (csym!= NULL);
21879 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
21880 // each this exp should have a class decl
21881 ROSE_ASSERT (xdecl != NULL);
21882 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
21883 if (le != NULL)
21884 {
21885 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
21886 rt = true;
21887 }
21888 }
21889 }
21890#endif
21891 return rt;
21892}
21893
21896//TODO consult AstInterface::IsVarRef() for more cases
21898{
21899 SgInitializedName* name = NULL;
21900 SgExpression* nameExp = NULL;
21901 ROSE_ASSERT(current != NULL);
21902
21903 if (isSgInitializedName(current))
21904 {
21905 name = isSgInitializedName(current);
21906 }
21907 else if (isSgPntrArrRefExp(current) != NULL)
21908 {
21909 bool suc=false;
21910 SgExpression* exp = isSgExpression(current);
21911 ROSE_ASSERT(exp != NULL);
21912 suc = SageInterface::isArrayReference(exp,&nameExp);
21913 ROSE_ASSERT(suc == true);
21914 // has to resolve this recursively
21915 return convertRefToInitializedName(nameExp, coarseGrain);
21916 }
21917 else if (isSgVarRefExp(current) != NULL)
21918 {
21919 if (coarseGrain)
21920 {
21921 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
21922 SgNode* parent = current->get_parent();
21923 if (isSgDotExp(parent))
21924 {
21925 if (isSgDotExp(parent)->get_rhs_operand() == current)
21926 return convertRefToInitializedName(parent, coarseGrain);
21927 }
21928 // avoid backtracking to parent if this is part of lambda function
21929 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
21930 {
21931 if (isSgArrowExp(parent)->get_rhs_operand() == current)
21932 return convertRefToInitializedName(parent, coarseGrain);
21933 }
21934 }
21935 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
21936 }
21937 else if (isSgFunctionRefExp(current) != NULL ||
21938 isSgTemplateFunctionRefExp(current) != NULL ||
21939 isSgMemberFunctionRefExp(current) != NULL ||
21940 isSgTemplateMemberFunctionRefExp(current) != NULL)
21941 {
21942 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
21943 return NULL;
21944 }
21945 else if (isSgNonrealRefExp(current) != NULL)
21946 {
21947 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
21948 return NULL;
21949 }
21950 else if (isSgDotExp(current))
21951 {
21952 SgExpression* child = NULL;
21953 if (coarseGrain)
21954 child= isSgDotExp(current)->get_lhs_operand();
21955 else
21956 child= isSgDotExp(current)->get_rhs_operand();
21957 ROSE_ASSERT(child);
21958 // has to resolve this recursively
21959 return convertRefToInitializedName(child, coarseGrain);
21960 }
21961 else if (isSgArrowExp(current))
21962 {
21963 SgExpression* child = NULL;
21964 if (coarseGrain)
21965 {
21966 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
21967 ROSE_ASSERT(lhs);
21968 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
21969 // They capture variables outside of the lambda function.
21970 // They are represented as a class variable of an anonymous class, this->a[i]
21971 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
21972 // has to resolve this recursively
21974
21975 if (isLambdaFunction (efunc) )
21976 child= isSgArrowExp(current)->get_rhs_operand();
21977 else
21978 child = lhs;
21979 }
21980 else
21981 child = isSgArrowExp(current)->get_rhs_operand();
21982 ROSE_ASSERT(child);
21983 // has to resolve this recursively
21984
21985 return convertRefToInitializedName(child, coarseGrain);
21986 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
21987 else if (isSgThisExp(current))
21988 {
21989 //SgThisExp* texp = isSgThisExp(current);
21990 name = NULL; // inside a class, there is no initialized name at all!! what to do??
21991 }
21992 else if (isSgPointerDerefExp(current))
21993 {
21994 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
21995 }
21996 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
21997 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
21998 }
21999 else if (isSgCastExp(current))
22000 {
22001 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
22002 }
22003 // Scientific applications often use *(address + offset) to access array elements
22004 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
22005 else if (isSgAddOp(current))
22006 {
22007 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
22008 return convertRefToInitializedName(lhs, coarseGrain);
22009 }
22010 else if (isSgSubtractOp(current))
22011 {
22012 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
22013 return convertRefToInitializedName(lhs, coarseGrain);
22014 }
22015 // operator->() may be called upon a class object.
22016 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
22017 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
22018 {
22019 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
22020 }
22021 else if (isSgIntVal(current))
22022 {
22023 //It is very rare, but sometimes a constant is treated as a
22024 //variable. In which case we don't need an SgInitializdName
22025 return NULL;
22026 }
22027
22028 else
22029 {
22030 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
22031 if (!isSgConstructorInitializer(current))
22032 {
22033 mlog[Sawyer::Message::Common::WARN] <<
22034 "convertRefToInitializedName: " <<
22035 current->get_file_info()->get_filename() << ":" <<
22036 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
22037 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
22038 ROSE_ABORT();
22039 }
22040 }
22041 //ROSE_ASSERT(name != NULL);
22042 return name;
22043}
22044
22047{
22048#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22049 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
22050 ROSE_ABORT();
22051#else
22053
22054 // trim off the possible leading handle for project: "Project<numbering,1>::"
22055 size_t pos = input_string.find("SourceFile<");
22056 ROSE_ASSERT (pos != string::npos);
22057 string trimed_string = input_string.substr(pos);
22058 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
22059 if (handle)
22060 {
22061 if (handle->getNode()!=NULL)
22062 {
22063#ifdef _MSC_VER
22064 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
22065 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
22066#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
22067 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
22068 ROSE_ABORT();
22069#else
22070 SgNode* result = (SgNode*)(handle->getNode()->getNode());
22071#endif
22072 // deallocate memory, should not do this!!
22073 // May corrupt the internal std maps used in abstract handle namespace
22074 //delete handle->getNode();
22075 //delete handle;
22076 return result;
22077 }
22078 }
22079#endif
22080
22081 return NULL;
22082}
22083
22084
22086// unparseToString() is too strict for debugging purpose
22087// we provide this instead.
22088void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
22089{
22090 ROSE_ASSERT(node != NULL);
22091 cout<<desc<<endl;
22092 // base information for all SgNode:
22093 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
22094 cout<<"--------------base info. for SgNode---------------"<<endl;
22095 cout<<node<<" "<<node->class_name()<<endl;
22096 SgLocatedNode* snode = isSgLocatedNode(node);
22097 if (snode)
22098 {
22099 // source file info. dump
22100 cout<<"--------------source location info. for SgNode---------------"<<endl;
22101 cout<<snode->get_file_info()->get_filename()
22102 << ":"<<snode->get_file_info()->get_line()<<"-"
22103 << snode->get_file_info()->get_col()<<endl;
22104 // preprocessing info dump
22105 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
22106 if (comments)
22107 {
22108 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
22109 AttachedPreprocessingInfoType::iterator i;
22110 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
22111 for (i = comments->begin (); i != comments->end (); i++)
22112 {
22113 PreprocessingInfo * pinfo = *i;
22114 pinfo->display("");
22115 }
22116 }
22117 cout<<"--------------name info. for SgNode---------------"<<endl;
22118 // print out namea for named nodes
22119 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
22120 if (decl)
22121 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
22122 SgVarRefExp * varRef = isSgVarRefExp(snode);
22123 if (varRef)
22124 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
22125 }
22126 SgInitializedName * iname = isSgInitializedName(snode);
22127 if (iname)
22128 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
22129
22130 cout<<endl;
22131 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
22132}
22133
22139bool
22140SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
22141{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
22142 bool retVal = true;
22143
22144 ROSE_ASSERT(stmt !=NULL);
22145
22146#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22147 // We should allow accumulate the effects for multiple statements
22148 // ROSE_ASSERT(readRefs.size() == 0);
22149 // ROSE_ASSERT(writeRefs.size() == 0);
22150
22151 // convert a request for a defining function declaration to its function body
22152 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
22153 if (funcDecl != NULL)
22154 {
22155 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
22156 if (funcDecl == NULL)
22157 {
22158 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
22159 }
22160 else
22161 stmt = funcDecl->get_definition()->get_body();
22162 }
22163
22164 // get function level information
22165 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
22166 if (!funcDef)
22168
22169 ROSE_ASSERT(funcDef != NULL);
22170 SgBasicBlock* funcBody = funcDef->get_body();
22171 ROSE_ASSERT(funcBody!= NULL);
22172
22173 // prepare Loop transformation environment
22174 AstInterfaceImpl faImpl(funcBody);
22175 AstInterface fa(&faImpl);
22176 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
22177 if( useCachedDefUse ){
22178 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
22179 LoopTransformInterface::set_arrayInfo(array_interface);
22180 } else {
22181 ArrayInterface array_interface(*annot);
22182 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
22183// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
22184 array_interface.observe(fa);
22185 LoopTransformInterface::set_arrayInfo(&array_interface);
22186 }
22187 LoopTransformInterface::set_astInterface(fa);
22188 // Liao, 3/27/2015. connect to annotations for function side effect
22189 LoopTransformInterface::set_sideEffectInfo(annot);
22190
22191 // variables to store results
22192 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
22193 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
22194 AstNodePtr s1 = AstNodePtrImpl(stmt);
22195
22196 // Actual side effect analysis
22197 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
22198 {
22199 //False returned here just means that the function called a
22200 //function that was not annotated with Qing's RWset annotation
22201 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
22202 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
22203 retVal = false;
22204 }
22205
22206 // transfer results into STL containers.
22207 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
22208 {
22209 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22210 p = rRef1.Next(p);
22211 AstNodePtr cur = p1->GetEntry();
22212 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22213 ROSE_ASSERT(sgRef != NULL);
22214 readRefs.push_back(sgRef);
22215 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22216 // " sage type:"<< sgRef->class_name()<< endl;
22217 }
22218
22219 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22220 {
22221 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22222 p = wRef1.Next(p);
22223 AstNodePtr cur = p1->GetEntry();
22224 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22225 ROSE_ASSERT(sgRef != NULL);
22226 writeRefs.push_back(sgRef);
22227 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22228 // " sage type:"<< sgRef->class_name()<< endl;
22229 }
22230
22231#endif
22232
22233 return retVal;
22234}
22235#if 0
22236// The side effect analysis will report three references for a statement like this->x = ...
22237// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22238// We only need to keep SgVarRefExp and skip the other two.
22239static bool skipSomeRefs(SgNode* n)
22240{
22241 ROSE_ASSERT (n);
22242 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22243}
22244#endif
22246bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22247{
22248 ROSE_ASSERT(stmt != NULL);
22249 vector <SgNode* > readRefs, writeRefs;
22250
22251 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22252 // process read references
22253 vector<SgNode*>::iterator iter = readRefs.begin();
22254 for (; iter!=readRefs.end();iter++)
22255 {
22256 SgNode* current = *iter;
22257 //if (skipSomeRefs(current)) continue;
22258
22259 ROSE_ASSERT (current != NULL);
22260 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22261 //ROSE_ASSERT (name); // this pointer will return NULL
22262 if (!name) continue;
22263 // Only insert unique ones
22264 // We use std::set to ensure uniqueness now
22265 readVars.insert(name);
22266 }
22267 // process write references
22268 vector<SgNode*>::iterator iterw = writeRefs.begin();
22269 for (; iterw!=writeRefs.end();iterw++)
22270 {
22271 SgNode* current = *iterw;
22272 ROSE_ASSERT (current != NULL);
22273 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22274 if (!name) continue;
22275 //ROSE_ASSERT (name); // this pointer will return NULL
22276 // Only insert unique ones
22277 // We use std::set to ensure uniqueness now
22278 writeVars.insert(name);
22279 }
22280 return retVal;
22281}
22282
22284void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22285{
22286 ROSE_ASSERT(stmt != NULL);
22287 set<SgInitializedName*> readVars, writeVars;
22288 // Only collect read only variables if collectReadWriteVariables() succeeded.
22289 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22290 {
22291 // read only = read - write
22292 set_difference(readVars.begin(), readVars.end(),
22293 writeVars.begin(), writeVars.end(),
22294 std::inserter(readOnlyVars, readOnlyVars.begin()));
22295 }
22296 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
22297 {
22298 RoseAst ast(stmt);
22299
22300 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22301 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22302 {
22303 if (isConstType(v_ref->get_type()))
22304 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22305 }
22306 } // end for
22307 } // end else
22308}
22309
22310
22312void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22313{
22314 set<SgInitializedName*> temp;
22315 collectReadOnlyVariables(stmt, temp, coarseGrain);
22316
22317 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22318 iter!=temp.end(); iter++)
22319 {
22320 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22321 ROSE_ASSERT(symbol != NULL );
22322 ROSE_ASSERT(isSgVariableSymbol(symbol));
22323 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22324 }
22325
22326}
22327
22330{
22331 bool result = false;
22332 ROSE_ASSERT(ref != NULL);
22333 ROSE_ASSERT(ref->get_parent() != NULL);
22334 // case 1: ref is used as an operator for & (SgAddressofOp)
22335 // TODO tolerate possible type casting operations in between ?
22336 if (isSgAddressOfOp(ref->get_parent()))
22337 {
22338 result = true;
22339 }
22340 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22341 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22342 {
22343 SgNode* grandparent = ref->get_parent()->get_parent();
22344 ROSE_ASSERT(grandparent);
22345 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22346 {
22347 // find which parameter ref is in SgExpressionPtrList
22348
22349 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22350 // int param_index = 0;
22351 size_t param_index = 0;
22352
22353 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22354 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22355 for (; iter!=expList.end(); iter++)
22356 {
22357 if (*iter == ref)
22358 break;
22359 else
22360 param_index++;
22361 }
22362 // find the parameter type of the corresponding function declaration
22363 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22364 ROSE_ASSERT (func_exp);
22365 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22366 if (funcRef) // regular functions
22367 {
22368 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22369 SgInitializedNamePtrList nameList = funcDecl->get_args();
22370 //TODO tolerate typedef chains
22371 // printf() has only two arguments to express variable arguments.
22372 // The third argument index ==2 will be out of bounds for nameList[index]
22373 // So we must check the bound first.
22374 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22375 {
22376 if (isSgReferenceType(ref))
22377 result = true;
22378 }
22379 else // now within the bound: two situations,
22380 if (isSgReferenceType(nameList[param_index]->get_type()))
22381 {
22382 result = true;
22383 }
22384 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22385 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22386 {
22387 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22388 ROSE_ASSERT (binOp);
22389 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22390 ROSE_ASSERT (mfuncRef);
22391 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22392 ROSE_ASSERT (mfuncDecl);
22393 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22394 //TODO tolerate typedef chains
22395 if (isSgReferenceType(nameList[param_index]->get_type()))
22396 {
22397 result = true;
22398 }
22399 }
22400
22401 }
22402 }
22403 return result;
22404}
22405
22406
22408void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22409{
22410 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22411
22412 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22413 for (; iter!=var_refs.end(); iter++)
22414 {
22415 SgVarRefExp* ref = isSgVarRefExp(*iter);
22416 ROSE_ASSERT(ref != NULL);
22417 ROSE_ASSERT(ref->get_parent() != NULL);
22418#if 0
22419 // case 1: ref is used as an operator for & (SgAddressofOp)
22420 // TODO tolerate possible type casting operations in between ?
22421 if (isSgAddressOfOp(ref->get_parent()))
22422 {
22423 varSetB.insert(ref);
22424 }
22425 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22426 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22427 {
22428 SgNode* grandparent = ref->get_parent()->get_parent();
22429 ROSE_ASSERT(grandparent);
22430 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22431 {
22432 // find which parameter ref is in SgExpressionPtrList
22433 int param_index =0;
22434 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22435 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22436 for (; iter!=expList.end(); iter++)
22437 {
22438 if (*iter == ref)
22439 break;
22440 else
22441 param_index++;
22442 }
22443 // find the parameter type of the corresponding function declaration
22444 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22445 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22446 SgInitializedNamePtrList nameList = funcDecl->get_args();
22447 //TODO tolerate typedef chains
22448 if (isSgReferenceType(nameList[param_index]->get_type()))
22449 {
22450 varSetB.insert(ref);
22451 }
22452 }
22453 }
22454#endif
22456 varSetB.insert(ref);
22457 }
22458}
22459
22460#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22462LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22463{
22464 // We expect this function to be called multiple times but always return the result generated from the first execution.
22465 static LivenessAnalysis* liv = NULL; // one instance
22466 if (liv!=NULL)
22467 return liv;
22468
22469 static DFAnalysis * defuse = NULL; // only one instance
22470 // Prepare def-use analysis
22471 if (defuse==NULL)
22472 {
22473 ROSE_ASSERT(project != NULL);
22474 defuse = new DefUseAnalysis(project);
22475 }
22476
22477 ROSE_ASSERT(defuse != NULL);
22478 defuse->run(debug);
22479
22480 if (debug)
22481 defuse->dfaToDOT();
22482
22483 //Prepare variable liveness analysis
22484 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22485 ROSE_ASSERT(liv != NULL);
22486
22487 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22488 NodeQuerySynthesizedAttributeType vars =
22489 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22490 NodeQuerySynthesizedAttributeType::const_iterator i;
22491 bool abortme=false;
22492 // run liveness analysis on each function body
22493 for (i= vars.begin(); i!=vars.end();++i)
22494 {
22495 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22496 ROSE_ASSERT(func != NULL);
22497 if (debug)
22498 {
22499 std::string name = func->class_name();
22500 string funcName = func->get_declaration()->get_qualified_name().str();
22501 cout<< " .. running liveness analysis for function: " << funcName << endl;
22502 }
22503 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22504 // propagate results to statement level
22505 liv->fixupStatementsINOUT(func);
22506 if (rem_source.getNode()!=NULL)
22507 dfaFunctions.push_back(rem_source);
22508 if (abortme)
22509 break;
22510 } // end for ()
22511 if(debug)
22512 {
22513 cout << "Writing out liveness analysis results into var.dot... " << endl;
22514 std::ofstream f2("var.dot");
22515 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22516 f2.close();
22517 }
22518 if (abortme) {
22519 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22520 ROSE_ABORT();
22521 }
22522 return liv;
22523 //return !abortme;
22524}
22525#endif
22526
22527#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22529void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22530{
22531 ROSE_ASSERT(liv != NULL);
22532 ROSE_ASSERT(loop != NULL);
22533 SgForStatement *forstmt = loop;
22534 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22535
22536 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22537 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22538 // We have to check the full control flow graph to find all SgForStatement's nodes,
22539 // check the index numbers from 0 , find the one with two out edges (true, false)
22540 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22541 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22542 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22543 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22544 CFGNode cfgnode(forstmt,2);
22545 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22546 // This one does not return the one we want even its getNode returns the
22547 // right for statement
22548 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22549 ROSE_ASSERT(filternode.getNode()==forstmt);
22550
22551 // Check out edges
22552 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22553 ROSE_ASSERT(out_edges.size()==2);
22554 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22555
22556 for (; iter!=out_edges.end();iter++)
22557 {
22558 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22559 //SgForStatement should have two outgoing edges based on the loop condition
22560 // one true(going into the loop body) and one false (going out the loop)
22561 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22562 if (edge.condition()==eckTrue)
22563 {
22564 SgNode* firstnode= edge.target().getNode();
22565 liveIns0 = liv->getIn(firstnode);
22566 // cout<<"Live-in variables for loop:"<<endl;
22567 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22568 iter!=liveIns0.end(); iter++)
22569 {
22570 // SgInitializedName* name = *iter;
22571 liveIns.insert(*iter);
22572 // cout<< name->get_qualified_name().getString()<<endl;
22573 }
22574 }
22575 //x. live-out(loop) = live-in (first-stmt-after-loop)
22576 else if (edge.condition()==eckFalse)
22577 {
22578 SgNode* firstnode= edge.target().getNode();
22579 liveOuts0 = liv->getIn(firstnode);
22580 // cout<<"Live-out variables for loop:"<<endl;
22581 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22582 iter!=liveOuts0.end(); iter++)
22583 {
22584 // SgInitializedName* name = *iter;
22585 // cout<< name->get_qualified_name().getString()<<endl;
22586 liveOuts.insert(*iter);
22587 }
22588 }
22589 else
22590 {
22591 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22592 ROSE_ABORT();
22593 }
22594 } // end for (edges)
22595
22596}
22597#endif
22598
22599//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22600static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22601{
22602 bool isReduction = false;
22603 // Sanity check
22604 ROSE_ASSERT (ref_exp1!= NULL);
22605 ROSE_ASSERT (ref_exp2!= NULL);
22606 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22607 // must be scalar type
22608 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22609
22612 if (stmt != stmt2) return false; // early return false;
22613
22614 // must be assignment statement using
22615 // x= x op expr, x = expr op x (except for subtraction)
22616 // one reference on left hand, the other on the right hand of assignment expression
22617 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22618 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22619 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22620 {
22621 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22622 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22623 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22624 ROSE_ASSERT(assign_lhs && assign_rhs);
22625 // x must show up in both lhs and rhs in any order:
22626 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22627 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22628 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22629 {
22630 // assignment's rhs must match the associative binary operations
22631 // +, *, -, &, ^ ,|, &&, ||
22632 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22633 if (binop!=NULL){
22634 SgExpression* op_lhs = binop->get_lhs_operand();
22635 SgExpression* op_rhs = binop->get_rhs_operand();
22636
22637 // double check that the binary expression has either ref1 or ref2 as one operand
22638 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22639 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22640 return false; // early return false;
22641
22642 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22643 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22644 (op_lhs==ref_exp2))
22645 isOnLeft = true;
22646 switch (binop->variantT())
22647 {
22648 case V_SgAddOp:
22649 {
22650 optype = OmpSupport::e_reduction_plus;
22651 isReduction = true;
22652 break;
22653 }
22654 case V_SgMultiplyOp:
22655 {
22656 optype = OmpSupport::e_reduction_mul;
22657 isReduction = true;
22658 break;
22659 }
22660 case V_SgSubtractOp: // special handle here!!
22661 {
22662 optype = OmpSupport::e_reduction_minus;
22663 if (isOnLeft) // cannot allow (exp - x)a
22664 {
22665 isReduction = true;
22666 }
22667 break;
22668 }
22669 case V_SgBitAndOp:
22670 {
22671 optype = OmpSupport::e_reduction_bitand ;
22672 isReduction = true;
22673 break;
22674 }
22675 case V_SgBitXorOp:
22676 {
22677 optype = OmpSupport::e_reduction_bitxor;
22678 isReduction = true;
22679 break;
22680 }
22681 case V_SgBitOrOp:
22682 {
22683 optype = OmpSupport::e_reduction_bitor;
22684 isReduction = true;
22685 break;
22686 }
22687 case V_SgAndOp:
22688 {
22689 optype = OmpSupport::e_reduction_logand;
22690 isReduction = true;
22691 break;
22692 }
22693 case V_SgOrOp:
22694 {
22695 optype = OmpSupport::e_reduction_logor;
22696 isReduction = true;
22697 break;
22698 }
22699 default:
22700 break;
22701 }
22702 } // end matching associative operations
22703 }
22704 } // end if assignop
22705 return isReduction;
22706}
22707// A helper function for reduction recognition
22708// check if two references to the same variable form a reduction idiom using if-statement
22709// example 1: if (array[i]> maxV) maxV = array[i]
22710// example 2: if (array[i]< minV) minV = array[i]
22711// If it matches, return true and the reduction operator type
22712static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22713{
22714 bool matchStmt1 = false;
22715 bool matchStmt2 = false;
22716
22717 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22718 // SgExpression* reduction_var_ref = NULL;
22719 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22720
22721 // Sanity check
22722 ROSE_ASSERT (ref1 != NULL);
22723 ROSE_ASSERT (ref2 != NULL);
22724 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22725 // must be scalar type
22726 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22727
22730
22731 //early return if the same stmt
22732 if (stmt1 == stmt2) return false;
22733
22734 // check stmt2 first. It is easier.
22735 // stmt2 should be an assignment stmt like:
22736 // reduction_variable = else;
22737 // minV = array[i];
22738 SgExpression* lhs2 = NULL;
22739 SgExpression* rhs2 = NULL;
22740 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22741 {
22742 // lhs2 must be ref2
22743 if (lhs2 == ref2 )
22744 {
22745 matchStmt2 = true;
22746 // reduction_var_ref = lhs2;
22747 // source_var_ref= rhs2;
22748 }
22749 } // end assignment stmt
22750
22751 // stmt1 should be a if-stmt's conditional expression stmt
22752 // and its body should be stmt2
22753 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22754 {
22755 bool matchBody = false;
22756 bool matchCondition= false;
22757 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22758 {
22759 if (SgStatement* body = if_stmt->get_true_body())
22760 {
22761 if (SgBasicBlock* block = isSgBasicBlock (body))
22762 {
22763 // stmt2 must be the only child of the if true body
22764 ROSE_ASSERT(stmt2 != NULL);
22765 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22766 matchBody = true;
22767 }
22768 else
22769 {
22770 if (body == stmt2)
22771 matchBody = true;
22772 }
22773 } // body match test
22774
22775 // match condition SgExprStatement ref1 SgLessThanOp source_var
22776 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
22777 {
22778 SgExpression* cond_exp = cond_exp_stmt->get_expression();
22779 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
22780 {
22781 if (ref1 == binop->get_lhs_operand_i())
22782 {
22783 // minV > array[i] ;
22784 if (isSgLessThanOp (binop))
22785 {
22786 optype = OmpSupport::e_reduction_max;
22787 matchCondition= true;
22788 }
22789 else if (isSgGreaterThanOp(binop))
22790 {
22791 optype = OmpSupport::e_reduction_min;
22792 matchCondition= true;
22793 }
22794 }
22795 else if ( ref1 == binop->get_rhs_operand_i() )
22796 {
22797 // array[i] < minV
22798 if (isSgLessThanOp (binop))
22799 {
22800 optype = OmpSupport::e_reduction_min;
22801 matchCondition= true;
22802 }
22803 else if (isSgGreaterThanOp(binop))
22804 {
22805 optype = OmpSupport::e_reduction_max;
22806 matchCondition= true;
22807 }
22808 }
22809 } // end if binary op
22810 // TODO the source_var should match the source_var from stmt2
22811 }
22812 }
22813 matchStmt1 = matchBody && matchCondition;
22814 } // end if-stmt
22815
22816
22817 return (matchStmt2 && matchStmt1);
22818}
22819
22820// check if a var ref is a form of
22821// --x, x--, ++x, x++
22822// x+= .., x-= ..., etc.
22823// The reduction variable appears only once in the reduction idiom.
22824static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
22825{
22826 bool isReduction = false;
22827
22828 ROSE_ASSERT (ref1 != NULL);
22829 // must be scalar type
22830 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22831
22833
22834 if (isSgExprStatement(stmt))
22835 {
22836 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
22837 SgExpression* binop = isSgBinaryOp(exp);
22838 if (isSgPlusPlusOp(exp)) // x++ or ++x
22839 { // Could have multiple reduction clause with different operators!!
22840 // So the variable list is associated with each kind of operator
22841 optype = OmpSupport::e_reduction_plus;
22842 isReduction = true;
22843 }
22844 else if (isSgMinusMinusOp(exp)) // x-- or --x
22845 {
22846 optype = OmpSupport::e_reduction_minus;
22847 isReduction = true;
22848 }
22849 else
22850 // x binop= expr where binop is one of + * - & ^ |
22851 // x must be on the left hand side
22852 if (binop!=NULL) {
22853 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
22854 if (lhs==ref1)
22855 {
22856 switch (exp->variantT())
22857 {
22858 case V_SgPlusAssignOp:
22859 {
22860 optype = OmpSupport::e_reduction_plus;
22861 isReduction = true;
22862 break;
22863 }
22864 case V_SgMultAssignOp:
22865 {
22866 optype = OmpSupport::e_reduction_mul;
22867 isReduction = true;
22868 break;
22869 }
22870 case V_SgMinusAssignOp:
22871 {
22872 optype = OmpSupport::e_reduction_minus;
22873 isReduction = true;
22874 break;
22875 }
22876 case V_SgAndAssignOp:
22877 {
22878 optype = OmpSupport::e_reduction_bitand;
22879 isReduction = true;
22880 break;
22881 }
22882 case V_SgXorAssignOp:
22883 {
22884 optype = OmpSupport::e_reduction_bitxor;
22885 isReduction = true;
22886 break;
22887 }
22888 case V_SgIorAssignOp:
22889 {
22890 optype = OmpSupport::e_reduction_bitor;
22891 isReduction = true;
22892 break;
22893 }
22894 default:
22895 break;
22896 } // end
22897 }// end if on left side
22898 }
22899 }
22900 return isReduction;
22901}
22902
22904/* This code is refactored from project/autoParallelization/autoParSupport.C
22905 std::vector<SgInitializedName*>
22906 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
22907 * Algorithms:
22908 * for each scalar candidate which are both live-in and live-out for the loop body
22909 * (We don't use liveness analysis here for simplicity)
22910 * and which is not the loop invariant variable (loop index).
22911 * Consider those with only 1 or 2 references
22912 * 1 reference
22913 * the operation is one of x++, ++x, x--, --x, x binop= expr
22914 * 2 references belonging to the same operation
22915 * operations: one of x= x op expr, x = expr op x (except for subtraction)
22916 * The reduction description from the OpenMP 3.0 specification.
22917 * x is not referenced in exp
22918 * expr has scalar type (no array, objects etc)
22919 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
22920 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
22921 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
22922 */
22923void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
22924{
22925 //x. Collect variable references of scalar types as candidates, excluding loop index
22926 SgInitializedName* loopindex;
22927 if (!(isCanonicalForLoop(loop, &loopindex)))
22928 {
22929// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
22930 return;
22931 }
22932 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
22933 //Store the references for each scalar variable
22934 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
22935
22936 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
22937 SgStatement* lbody= loop->get_loop_body();
22938 ROSE_ASSERT(lbody != NULL);
22939 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
22940 for (; iter!=reflist.end(); iter++)
22941 {
22942 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
22943 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
22944 // candidates are of scalar types and are not the loop index variable
22945 // And also should be live-in:
22946 // not declared locally (var_scope equal or lower than loop body )
22947 // or redefined (captured by ref count)
22948 SgScopeStatement* var_scope = initname->get_scope();
22949 ROSE_ASSERT(var_scope != NULL);
22950 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
22951 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
22952 {
22953 candidateVars.insert(initname);
22954 var_references[initname].push_back(ref_exp);
22955 }
22956 }
22957
22958 //Consider variables referenced at most twice
22959 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
22960 for (; niter!=candidateVars.end(); niter++)
22961 {
22962 SgInitializedName* initname = *niter;
22963 bool isReduction = false;
22964 OmpSupport::omp_construct_enum optype;
22965 // referenced once only
22966 if (var_references[initname].size()==1)
22967 {
22968 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
22969 SgVarRefExp* ref_exp = *(var_references[initname].begin());
22970 if (isSingleAppearanceReduction (ref_exp, optype))
22971 isReduction = true;
22972 }
22973 // referenced twice within a same statement
22974 else if (var_references[initname].size()==2)
22975 {
22976 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
22977 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
22978 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
22979 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
22980 // TODO: recognize maxV = max (maxV, array[i])
22981 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
22982 {
22983 isReduction = true;
22984 }
22985
22986 }// end referenced twice
22987
22988 if (isReduction)
22989 results.insert(make_pair(initname,optype));
22990 }// end for ()
22991}
22992
22995{
22996 ROSE_ASSERT(r!=NULL);
22997#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22998 ConstantFolding::constantFoldingOptimization(r,false);
22999#endif
23000}
23001
23004{
23006 {
23007 public:
23008 virtual void visit (SgNode * n)
23009 {
23010 SgExpression* exp = isSgExpression(n);
23011 if (exp)
23012 {
23013 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
23014 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
23015 ROSE_ASSERT (name_attribute != NULL);
23016 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
23017 }
23018 }
23019 };
23020 visitorTraversal exampleTraversal;
23021 //Sriram FIX: should traverse using the traverse function
23022 // exampleTraversal.traverseInputFiles(project,preorder);
23023 exampleTraversal.traverse(project, preorder);
23024}
23025
23026
23027 //
23028 // wrap free-standing function body in another function
23029
23031 {
23032 ROSE_ASSERT(vardecl.get_variables().size());
23033
23034 return *vardecl.get_variables().front();
23035 }
23036
23037#if 0
23038 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23039 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23040
23048 static
23050 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
23051 {
23052 namespace SB = SageBuilder;
23053
23054 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
23055 const SgInitializedNamePtrList& orig_decls = params.get_args();
23056
23057 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
23058
23059 return copy;
23060 }
23061#endif
23062
23063#if 0
23064 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
23065
23067 static
23068 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
23069 {
23070 // swap definitions
23071 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
23072 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
23073
23074 // \todo do we need to swap also exception spec, decorator_list, etc. ?
23075 }
23076#endif
23077
23078#if 0
23079 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23080 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23081
23082 std::pair<SgStatement*, SgInitializedName*>
23083 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
23084 {
23085 namespace SB = SageBuilder;
23086
23087 // handles freestanding functions only
23088 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
23089 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
23090
23091 // clone function parameter list
23092 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
23093
23094 // create new function definition/declaration in the same scope
23095 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
23096 SgType* result_type = definingDeclaration.get_type()->get_return_type();
23097 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
23098
23099 // DQ (4/9/2015): Suggested fix for this function.
23100 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
23101 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
23102
23103 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
23104 ROSE_ASSERT(wrapperdef);
23105
23106 // copy the exception specification
23107 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
23108
23109 // swap the original's function definition w/ the clone's function def
23110 // and the original's func parameter list w/ the clone's parameters
23111 swapDefiningElements(definingDeclaration, *wrapperfn);
23112
23113 // call original function from within the defining decl's body
23114 SgBasicBlock* body = wrapperdef->get_body();
23115 SgExprListExp* args = SB::buildExprListExp();
23116 SgInitializedNamePtrList& param_decls = param_list.get_args();
23117
23118 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
23119
23120 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
23121 SgInitializedName* resultName = NULL;
23122 SgStatement* callStatement = NULL;
23123
23124 // \todo skip legal qualifiers that could be on top of void
23125 if (!isSgTypeVoid(result_type))
23126 {
23127 // add call to original function and assign result to variable
23128 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
23129 SgVarRefExp* resref = SB::buildVarRefExp( res );
23130
23131 appendStatement(res, body);
23132
23133 // add return statement, returning result
23134 resultName = &getFirstVariable(*res);
23135 callStatement = res;
23136
23137 appendStatement(SB::buildReturnStmt(resref), body);
23138 }
23139 else
23140 {
23141 // add function call statement to original function
23142 callStatement = SB::buildExprStatement(callWrapped);
23143 appendStatement(callStatement, body);
23144 }
23145
23146 ROSE_ASSERT(callStatement);
23147
23148 // create non defining declaration
23149 SgExprListExp* decorator_proto = deepCopy( decorators );
23150 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
23151
23152 // add the new functions at the proper location of the surrounding scope
23153 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
23154 insertStatementAfter (&definingDeclaration, wrapperfn);
23155
23156 return std::make_pair(callStatement, resultName);
23157 }
23158#endif
23159
23160 //
23161 // flatten C/C++ array dimensions
23162 namespace
23163 {
23164 struct VarrefBuilder
23165 {
23166 virtual SgVarRefExp* get() const = 0;
23167
23168 static
23169 SgVarRefExp* build(const SgVarRefExp& n)
23170 {
23171 return SageInterface::deepCopy(&n);
23172 }
23173
23174 static
23176 {
23177 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
23178
23179 return SageBuilder::buildVarRefExp(&n, scope);
23180 }
23181 };
23182
23183 template <class AstNode>
23184 struct VarrefCreator : VarrefBuilder
23185 {
23186 AstNode& origin;
23187
23188 explicit
23189 VarrefCreator(AstNode& orig)
23190 : origin(orig)
23191 {}
23192
23193 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
23194 };
23195
23196 template <class AstNode>
23197 VarrefCreator<AstNode>
23198 varrefCreator(AstNode& n)
23199 {
23200 return VarrefCreator<AstNode>(n);
23201 }
23202
23203 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
23204 {
23205 namespace SB = SageBuilder;
23206 namespace SI = SageInterface;
23207
23208 // we own the lhs (intermediate result),
23209 // but we do not own the rhs (another top-level expression)
23210 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
23211 }
23212
23213 std::pair<std::vector<SgExpression*>, SgType*>
23214 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23215 {
23216 namespace SB = SageBuilder;
23217 namespace SI = SageInterface;
23218
23219 const SgArrayType* arrtype = &arr_type;
23220 std::vector<SgExpression*> indices;
23221 SgType* undertype = NULL;
23222
23223 // \todo when get_index() does not return a nullptr anymore
23224 // the condition can be removed
23225 if (arrtype->get_index() == NULL)
23226 {
23227 indices.push_back(SB::buildNullExpression());
23228 undertype = arrtype->get_base_type();
23229 arrtype = isSgArrayType(undertype);
23230 }
23231
23232 while (arrtype)
23233 {
23234 SgExpression* indexexpr = arrtype->get_index();
23235 ROSE_ASSERT(indexexpr);
23236
23237 indices.push_back(SI::deepCopy(indexexpr));
23238 undertype = arrtype->get_base_type();
23239 arrtype = isSgArrayType(undertype);
23240 }
23241
23242 ROSE_ASSERT((!indices.empty()) && undertype);
23243 return std::make_pair(indices, undertype);
23244 }
23245
23247 std::vector<SgExpression*>
23248 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23249 {
23250 namespace SB = SageBuilder;
23251
23252 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23253 const std::vector<SgExpression*>::iterator first = res.first.begin();
23254
23255 // if the first dimension was open, create the expression for it
23256 if (isSgNullExpression(*first))
23257 {
23258 // handle implicit first dimension for array initializers
23259 // for something like
23260 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23261 // we can calculate the first dimension as
23262 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23263
23264 const std::vector<SgExpression*>::iterator aa = first+1;
23265 const std::vector<SgExpression*>::iterator zz = res.first.end();
23266
23267 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23268 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23269 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23270 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23271
23272 std::swap(*first, sz);
23273 delete sz;
23274 }
23275
23276 return res.first;
23277 }
23278 }
23279
23280 std::vector<SgExpression*>
23282 {
23283 return get_C_array_dimensions_aux(arrtype).first;
23284 }
23285
23286 std::vector<SgExpression*>
23288 {
23289 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23290 }
23291
23292 std::vector<SgExpression*>
23294 {
23295 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23296 }
23297
23298// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23300 {
23301 public:
23302 set<unsigned int> sourceSequenceSet;
23303
23304 void visit ( SgNode* astNode );
23305 };
23306
23307// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23308void
23310 {
23311 Sg_File_Info* fileInfo = astNode->get_file_info();
23312 if (fileInfo != NULL)
23313 {
23314 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23315#if 0
23316 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23317#endif
23318 sourceSequenceSet.insert(source_sequence_number);
23319 }
23320 }
23321
23322// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23323set<unsigned int>
23325 {
23327
23328 traversal.traverse(astNode,preorder);
23329
23330 return traversal.sourceSequenceSet;
23331
23332 }
23333
23334/*Winnie, loop collapse, collapse nested for loops into one large for loop
23335 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23336 * loop scope, and used inside the loop scope.
23337 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23338 * transOmpCollpase(..) function in omp_lowering.cpp.
23339 *
23340 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23341 *
23342 *
23343 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23344 *
23345 * to collapse two level of loops:
23346 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23347 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23348 * total_iteration_count = iteration_count_one * iteration_count_two
23349 *
23350 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23351 *
23352 * Example 1:
23353 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23354 * {
23355 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23356 * {
23357 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23358 * {
23359 * a[i][j][l]=i+j+l;
23360 * }
23361 * }
23362 * }
23363 *
23364 *==> translated output code ==>
23365 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23366 * 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;
23367 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23368 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23369 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23370 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23371 * int l_nom_3_interval = 1;
23372 *
23373 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23374 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23375 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23376 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23377 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23378 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23379 * }
23380 *
23381 * Example 2 with concrete numbers:
23382 *
23383 * // collapse the following two level of for loops:
23384 * for (i=1; i<=9; i+=1) //incremental for loop
23385 * {
23386 * for(j=10; j>=1; j+=-2) //decremental for loop
23387 * {
23388 * a[i][j]=i+j;
23389 * }
23390 * }
23391 * // it becomes
23392 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23393 * // ub = 45
23394 * // lb = 0
23395 *
23396 * int i_nom_1_total_iters = 9;
23397 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23398 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23399 *
23400 * int i_nom_1_interval = 5;
23401 *
23402 * for (z=0; z<=44; z+=1)
23403 * {
23404 * i_nom_1 = z / 5 + 1;
23405 * j_nom_2 = -(z % 5 * 2) + 10;
23406 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23407 * }
23408 * // for the generated loop, a few compiler generated variables are introduced
23409 * final_total_iters for the collapsed loop
23410 * i_interval for each of the n-1 loops
23411 **
23412*/
23413
23414#ifndef USE_ROSE
23416{
23417#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23418 //Handle 0 and 1, which means no collapsing at all
23419 if (collapsing_factor <= 1)
23420 return NULL;
23421
23422 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23423
23424 /*
23425 *step 1: grab the target loops' header information
23426 */
23427 SgForStatement *& target_loop = loop;
23428
23429 // we use global scope to help generate unique variable name later
23430 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23431 SgGlobal* global_scope = getGlobalScope (loop);
23432 ROSE_ASSERT (global_scope != NULL);
23433 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23434 SgExpression** lb = new SgExpression*[collapsing_factor];
23435 SgExpression** ub = new SgExpression*[collapsing_factor];
23436 SgExpression** step = new SgExpression*[collapsing_factor];
23437 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23438
23439 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23440 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23441 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23442
23443
23444 //Winnie, get loops info first
23445 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23446 ROSE_ASSERT(loops.size()>=collapsing_factor);
23447
23448 SgForStatement* temp_target_loop = NULL;
23449 SgExpression* temp_range_exp = NULL; //Raw iteration range
23450 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23451 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23452 SgExpression* temp_total_iter = NULL;
23453 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23454
23455 /*
23456 * get lb, ub, step information for each level of the loops
23457 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23458 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23459 */
23460
23461 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23462 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23463
23464 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23465
23466 while(scope == NULL)
23467 {
23468 parent = isSgStatement(parent->get_parent());
23469 scope = isSgScopeStatement(parent);
23470 }
23471
23472 SgStatement* insert_target = findLastDeclarationStatement(scope);
23473 if (insert_target != NULL)
23474 insert_target = getNextStatement(insert_target);
23475 else
23476 insert_target = getFirstStatement(scope);
23477
23478 ROSE_ASSERT(scope != NULL);
23479
23480
23481 for(size_t i = 0; i < collapsing_factor; i ++)
23482 {
23483 temp_target_loop = loops[i];
23484
23485 // normalize the target loop first // adjust to numbering starting from 0
23486 forLoopNormalization(temp_target_loop);
23487
23488 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23489 {
23490 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23491 dumpInfo(target_loop);
23492
23493 // release memory
23494 delete[] ivar;
23495 delete[] lb;
23496 delete[] ub;
23497 delete[] step;
23498 delete[] orig_body;
23499 delete[] total_iters;
23500 delete[] interval;
23501 delete[] isPlus;
23502
23503 return NULL;
23504 }
23505
23506 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23507
23508
23509//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]
23510 if(isPlus[i] == true)
23511 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23512 else{
23513 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23514 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23515 }
23516 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23517
23518 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23519
23520 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23521
23522 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23523 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23524 string iter_var_name= "_total_iters";
23525 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23526 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23527 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23528 insertStatementBefore(insert_target, total_iter);
23529 constantFolding (total_iter);
23530 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23531 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23532 }
23533
23534
23535 /*
23536 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23537 */
23538
23539 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23540 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23541 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23542 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23543 insertStatementBefore(insert_target, final_total_iter);
23544 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23545 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23546
23547 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23548 for(unsigned int i = 0; i < collapsing_factor; i++)
23549 {
23550 interval[i] = buildIntVal(1);
23551 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23552 {
23553 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23554 }
23555 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23556 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23557 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23558 insertStatementBefore(insert_target, temp_interval);
23559 interval[i] = buildVarRefExp(interval_name, scope);
23560 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23561 }
23562
23563
23564 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23565 scope = getScope(target_loop);
23566
23567 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23568 //Winnie, declare a brand new var as the new index
23569 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23570 ROSE_ASSERT(insert_target != NULL);
23571 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23572 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23573 insertStatementBefore(insert_target, new_index_decl);
23574 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23575 new_var_list->append_expression(clps_index_ref);
23576
23577// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23578
23579
23580 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23581 ROSE_ASSERT(body != NULL);
23582 SgExpression* new_exp = NULL;
23583 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23584 std::vector<SgStatement*> new_stmt_list;
23585
23586 SgExprStatement* assign_stmt = NULL;
23587
23588 /* Winnie
23589 * express old iterator variables (i_norm, j_norm ...) with new_index,
23590 * new_exp, create new expression for each of the iterators
23591 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23592 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23593 * create a new var to store total_iters[i]
23594 */
23595 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23596 {
23597 if(isPlus[i] == true)
23598 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]
23599 else
23600 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
23601
23602 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23603 new_stmt_list.push_back(assign_stmt);
23604 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23605
23606 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
23607 string remain_var_name= "_remainder";
23608 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23609 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23610 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23611 new_stmt_list.push_back(loop_index_decl);
23612 }
23613 new_exp = NULL;
23614 }
23615
23616//Winnie, the inner most loop, iter
23617 if(isPlus[collapsing_factor - 1] == true)
23618 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23619 else
23620 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23621 new_stmt_list.push_back(assign_stmt);
23622 prependStatementList(new_stmt_list, body);
23623
23624 /*
23625 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23626 */
23627 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23628
23629 //Winnie, build the new conditional expression/ub
23630 SgExprStatement* cond_stmt = NULL;
23631 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23632 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23633 ROSE_ASSERT(cond_stmt != NULL);
23634
23635 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23636 new_loop->set_parent(scope); //TODO: what's the correct parent?
23637
23638 replaceStatement(target_loop, new_loop);
23639
23640 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23641 // constant folding for the transformed AST
23642 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
23643
23644 delete [] ivar;
23645 delete [] lb;
23646 delete [] ub;
23647 delete [] step;
23648 delete [] orig_body;
23649 delete [] total_iters;
23650 delete [] interval;
23651 delete [] isPlus;
23652
23653 #endif
23654
23655 return new_var_list;
23656}
23657
23658
23659
23660bool
23662 {
23663 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23664
23665#ifndef USE_CMAKEx
23666 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23667
23668 // This is AST container for the ROSE AST that will provide an iterator.
23669 // We want two iterators (one for the copy of the snippet and one for the
23670 // original snippet so that we can query the original snippet's AST
23671 // as we process each IR node of the AST for the copy of the snippet.
23672 // Only the copy of the snippet is inserted into the target AST.
23673 RoseAst ast_of_copy(tree1);
23674 RoseAst ast_of_original(tree2);
23675
23676 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23677
23678 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23679 RoseAst::iterator i_copy = ast_of_copy.begin();
23680 RoseAst::iterator i_original = ast_of_original.begin();
23681
23682 // Iterate of the copy of the snippet's AST.
23683 while (i_copy != ast_of_copy.end())
23684 {
23685#if 0
23686 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23687 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23688#endif
23689 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23690 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23691 if ((*i_copy)->variantT() != (*i_original)->variantT())
23692 {
23693#if 0
23694 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23695#endif
23696#if 0
23697 printf ("Making this an error! \n");
23698 ROSE_ABORT();
23699#endif
23700 return false;
23701 }
23702
23703 i_copy++;
23704
23705 // Verify that we have not reached the end of the ast for the original (both the
23706 // copy and the original are the same structurally, and thus the same size).
23707 ROSE_ASSERT(i_original != ast_of_original.end());
23708 i_original++;
23709 }
23710
23711 // We have reached the end of both ASTs.
23712 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23713#endif
23714
23715 return true;
23716 }
23717
23718
23719#endif
23720
23722 SgForStatement * for_loop,
23723 SgVariableSymbol * & iterator,
23724 SgExpression * & lower_bound,
23725 SgExpression * & upper_bound,
23726 SgExpression * & stride
23727) {
23730
23731 iterator = NULL;
23732 lower_bound = NULL;
23733 upper_bound = NULL;
23734 stride = NULL;
23735
23736 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23737 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23738 assert(init_stmts.size() == 1);
23739 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23740 assert(init_stmt != NULL);
23741 SgExpression * init = init_stmt->get_expression();
23742
23743 SgAssignOp * assign_init = isSgAssignOp(init);
23744 assert(assign_init != NULL);
23745 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23746 assert(iterator_init_ref != NULL);
23747 iterator = iterator_init_ref->get_symbol();
23748 assert(iterator != NULL);
23749 lower_bound = assign_init->get_rhs_operand_i();
23750
23751 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23752 assert(test_stmt != NULL);
23753 SgExpression * test = test_stmt->get_expression();
23754 SgBinaryOp * bin_test = isSgBinaryOp(test);
23755 assert(bin_test);
23756
23757 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23758 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23759 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23760 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23761
23762 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23763 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23764 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23765#ifndef NDEBUG
23766 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23767
23768// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23769// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
23770// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
23771// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
23772// value. Since these are boolean typed values we can use "a != b", directly.
23773// assert(lhs_it xor rhs_it);
23774 assert(lhs_it != rhs_it);
23775#endif
23776
23777 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
23778
23779 bool inclusive;
23780 bool reversed;
23781
23782 switch (test->variantT()) {
23783 case V_SgGreaterOrEqualOp:
23784 inclusive = lhs_it;
23785 reversed = lhs_it;
23786 break;
23787 case V_SgGreaterThanOp:
23788 inclusive = !lhs_it;
23789 reversed = lhs_it;
23790 break;
23791 case V_SgLessOrEqualOp:
23792 inclusive = lhs_it;
23793 reversed = !lhs_it;
23794 break;
23795 case V_SgLessThanOp:
23796 inclusive = !lhs_it;
23797 reversed = !lhs_it;
23798 break;
23799 case V_SgEqualityOp:
23800 case V_SgNotEqualOp:
23801 default:
23802 ROSE_ABORT();
23803 }
23804
23805 SgExpression * increment = for_loop->get_increment();
23806 switch (increment->variantT()) {
23807 case V_SgPlusPlusOp:
23808 assert(!reversed);
23809 stride = SageBuilder::buildIntVal(1);
23810 break;
23811 case V_SgMinusMinusOp:
23812 assert(reversed);
23813 stride = SageBuilder::buildIntVal(-1);
23814 break;
23815 case V_SgPlusAssignOp:
23816 {
23817 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23818#ifndef NDEBUG
23819 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23820 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23821#endif
23822 stride = bin_op->get_rhs_operand_i();
23823 break;
23824 }
23825 case V_SgMinusAssignOp:
23826 {
23827 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
23828#ifndef NDEBUG
23829 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
23830 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
23831#endif
23832 stride = bin_op->get_rhs_operand_i();
23833 break;
23834 }
23835 case V_SgAssignOp:
23836 {
23837 SgAssignOp * assign_op = (SgAssignOp *)increment;
23838#ifndef NDEBUG
23839 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
23840 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
23841#endif
23842 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
23843 assert(inc_assign_rhs != NULL);
23844 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
23845 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
23846 stride = inc_assign_rhs->get_rhs_operand_i();
23847 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
23848 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
23849 stride = inc_assign_rhs->get_lhs_operand_i();
23850 break;
23851 }
23852 default:
23853 ROSE_ABORT();
23854 }
23855
23856 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
23857 if (!inclusive)
23858 {
23859 if (reversed)
23860 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
23861 else
23862 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
23863 }
23864
23865 return true;
23866}
23867
23868//------------------------------------------------------------------------------
23869#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
23870//------------------------------------------------------------------------------
23871
23876 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
23877
23878 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
23879 ROSE_ASSERT(utf8);
23880 string directory_name = utf8;
23881 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
23882
23883 list<string> sourcepath = project -> get_Java_sourcepath();
23884 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
23885 project -> set_Java_sourcepath(sourcepath);
23886
23887 return directory_name;
23888}
23889
23890
23894void SageInterface::destroyTempDirectory(string directory_name) {
23895 string command = string("rm -fr ") + directory_name;
23896 int status = system(command.c_str());
23897 ROSE_ASSERT(status == 0);
23898}
23899
23900
23904SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
23905 //
23906 // Set up the new source file for processing "a la Rose".
23907 //
23908 project -> get_sourceFileNameList().push_back(filename);
23909 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
23910 arg_list.push_back(filename);
23911 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
23912 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
23913 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
23914 SgFile *file = determineFileType(arg_list, error_code, project);
23915 SgSourceFile *sourcefile = isSgSourceFile(file);
23916 ROSE_ASSERT(sourcefile);
23917 sourcefile -> set_parent(project);
23918
23919 //
23920 // Insert the file into the list of files in the project.
23921 //
23922 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
23923 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
23924
23925 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
23926
23927 if (! unparse) { // if we are not supposed to unparse this file,
23928 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
23929 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
23930 }
23931
23932 // DQ (7/2/2020): Added assertion (fails for snippet tests).
23933 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
23934
23935 return file;
23936}
23937
23938
23943string SageInterface::preprocessPackage(SgProject *project, string package_name) {
23944 string command = "package " + package_name + ";";
23945
23946 //
23947 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
23948 //
23949 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23950 Rose::Frontend::Java::Ecj::createTempFileMethod,
23951 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23952
23953 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23954 ROSE_ASSERT(utf8);
23955 string filename = (string) utf8;
23956 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23957
23958 processFile(project, filename); // translate the file
23959
23960 return package_name;
23961}
23962
23963
23968string SageInterface::preprocessImport(SgProject *project, string import_string) {
23969 string command = "import " + import_string + ";";
23970
23971 //
23972 // Call the Java side to create an input file with the relevant import statement.
23973 //
23974 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23975 Rose::Frontend::Java::Ecj::createTempFileMethod,
23976 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
23977
23978 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
23979 ROSE_ASSERT(utf8);
23980 string filename = (string) utf8;
23981 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
23982
23983 processFile(project, filename); // translate the file
23984
23985 return import_string;
23986}
23987
23988
23993SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
23994 //
23995 // Call the Java side to create an input file with the relevant import statement.
23996 //
23997 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
23998 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
23999 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
24000 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
24001
24002 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24003 ROSE_ASSERT(utf8);
24004 string filename = (string) utf8;
24005 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24006
24007 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
24008}
24009
24010
24015 ROSE_ASSERT(scope);
24016 SgClassDefinition *package_definition = NULL;
24017 for (int index = 0, length = package_name.size(); index < length; index++) {
24018 int n;
24019 for (n = index; n < length; n++) {
24020 if (package_name[n] == '.') {
24021 break;
24022 }
24023 }
24024 string name = package_name.substr(index, n - index);
24025
24026 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
24027 if (package_symbol == NULL) { // package not found?
24028 return NULL;
24029 }
24030
24031 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
24032 ROSE_ASSERT(package_declaration);
24033 package_definition = package_declaration -> get_definition();
24034 ROSE_ASSERT(package_definition);
24035 scope = package_definition;
24036
24037 index = n;
24038 }
24039
24040 return package_definition;
24041}
24042
24043
24047SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
24048 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
24049 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
24050 if (package_definition == NULL) { // try again after loading the package
24051 preprocessPackage(project, package_name);
24052
24053 //
24054 // If requested, Create the directory associated with this package_name.
24055 //
24056 if (create_directory) {
24057 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24058 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
24059 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
24060 }
24061
24062 package_definition = findJavaPackage(global_scope, package_name);
24063 }
24064
24065 return package_definition;
24066}
24067
24072 ROSE_ASSERT(package_definition);
24073 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
24074 SgClassDeclaration *class_declaration = (class_symbol == NULL
24075 ? NULL
24076 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24077 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
24078 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
24079 preprocessImport(project, qualified_name);
24080 class_symbol = package_definition -> lookup_class_symbol(class_name);
24081 }
24082
24083 class_declaration = (class_symbol == NULL
24084 ? NULL
24085 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24086
24087 return class_declaration;
24088}
24089
24090
24094SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
24095 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
24096}
24097
24098
24103 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24104 ROSE_ASSERT(class_declaration);
24105 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
24106 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
24107 class_declaration = isSgClassDeclaration(scope -> get_parent());
24108 ROSE_ASSERT(class_declaration);
24109 scope = isSgClassDefinition(class_declaration -> get_scope());
24110 }
24111
24112 if (! scope) { // a local type !!!
24113 return NULL;
24114 }
24115
24116 string class_name = class_declaration -> get_name().getString();
24117 return findOrImportJavaClass(project, scope, class_name);
24118}
24119
24120
24125 ROSE_ASSERT(class_definition);
24127 ROSE_ASSERT(type_list);
24128 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
24129 ROSE_ASSERT(string_array_type);
24130 type_list -> append_argument(string_array_type);
24131
24132 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
24133 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
24134 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
24135
24136 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
24137 delete type_list;
24138 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
24139}
24140
24141
24146 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24147 ROSE_ASSERT(class_declaration);
24148 SgClassDefinition *class_definition = class_declaration -> get_definition();
24149 return findJavaMain(class_definition);
24150}
24151
24152//------------------------------------------------------------------------------
24153#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24154//------------------------------------------------------------------------------
24155
24157// Essentially replace variable a with b.
24159{
24160 ROSE_ASSERT (old_sym != NULL);
24161 ROSE_ASSERT (new_sym != NULL);
24162 ROSE_ASSERT (old_sym != new_sym);
24163 ROSE_ASSERT (scope != NULL);
24164
24165 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
24166 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
24167 {
24168 SgVarRefExp *vRef = isSgVarRefExp(*i);
24169 if (vRef->get_symbol() == old_sym)
24170 vRef->set_symbol(new_sym);
24171 }
24172}
24173
24174
24175// 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.
24180bool
24182 {
24183 bool result = true;
24184
24185 bool includingSelf = false;
24186 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
24187
24188 if (sourceFile == NULL)
24189 {
24190 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
24191 }
24192
24193 // I think we can assert this!
24194 ROSE_ASSERT(sourceFile != NULL);
24195
24196 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
24197 {
24198 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
24199 // 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.
24200 string source_filename = stmt->getFilenameString();
24201#if 0
24202 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
24203 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
24204#endif
24205
24206 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
24207 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
24208 {
24209 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
24210 ROSE_ASSERT(include_file != NULL);
24211#if 0
24212 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");
24213#endif
24214 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24215 {
24216#if 0
24217 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24218#endif
24219 result = false;
24220 }
24221 }
24222 else
24223 {
24224 // DQ (5/13/2021): I think that the default (returing true) will work well.
24225 // This is likely just the original input source file (not a header file).
24226#if 0
24227 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24228#endif
24229#if 0
24230 printf ("Exiting as a test! \n");
24231 ROSE_ABORT();
24232#endif
24233 }
24234
24235#if 0
24236 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24237 ROSE_ABORT();
24238#endif
24239 }
24240
24241 return result;
24242 }
24243
24244
24245//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24248{
24249 ROSE_ASSERT (decl!= NULL);
24250 ROSE_ASSERT (target_scope != NULL);
24251 ROSE_ASSERT (target_scope != decl->get_scope());
24252
24253#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24254 // Special handling for If-Stmt, may need to climb up one level of scope when:
24255 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24256 // If-stmt will be the innermost common scope for the variable.
24257 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24258 if (isSgIfStmt (target_scope))
24259 {
24260 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24261 if (target_scope == )
24262 }
24263# endif
24264
24265 // Move the declaration
24266 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24268
24269 switch (target_scope->variantT())
24270 {
24271 case V_SgBasicBlock:
24272 {
24273 SageInterface::prependStatement (decl, target_scope);
24274 break;
24275 }
24276#if 0 // this check should be done earlier before any side effects can happen
24277 case V_SgIfStmt:
24278 {
24279 // adjust to parent scope of if-stmt
24280 break;
24281 }
24282#endif
24283 case V_SgForStatement:
24284 {
24285 // we move int i; to be for (int i=0; ...);
24286 SgForStatement* stmt = isSgForStatement (target_scope);
24287 ROSE_ASSERT(stmt != NULL);
24288 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24289 // Try to match a pattern like for (i=0; ...) here
24290 // assuming there is only one assignment like i=0
24291 // We don't yet handle more complex cases
24292 if (stmt_list.size() !=1)
24293 {
24294 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24295 ROSE_ASSERT (stmt_list.size() ==1);
24296 }
24297 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24298 ROSE_ASSERT (exp_stmt != NULL);
24299 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24300 ROSE_ASSERT (assign_op != NULL);
24301
24302 // remove the existing i=0; preserve its right hand operand
24304 stmt_list.clear();
24305 SageInterface::deepDelete (exp_stmt);
24306
24307 // modify the decl's rhs to be the new one
24310 if (init_name->get_initptr() != NULL)
24311 SageInterface::deepDelete (init_name->get_initptr());
24312 init_name->set_initptr(initor);
24313 initor->set_parent(init_name);
24314
24315 stmt_list.insert (stmt_list.begin(), decl );
24316 break;
24317 }
24318
24319 default:
24320 {
24321 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24322 ROSE_ASSERT (false);
24323 }
24324 }
24325
24326 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24328 ROSE_ASSERT(sym != NULL);
24329 SgScopeStatement* orig_scope = sym->get_scope();
24330 if (orig_scope != target_scope)
24331 {
24332 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24333 // it somehow always reuses previously associated scope.
24335 init_name->set_scope(target_scope);
24336 SgName sname = sym->get_name();
24337 orig_scope->remove_symbol(sym);
24338 target_scope->insert_symbol(sname, sym);
24339 }
24340 // This is difficult since C++ variables have namespaces
24341 // Details are in SageInterface::fixVariableDeclaration()
24342 ROSE_ASSERT (target_scope->symbol_exists(sym));
24343}
24344
24345class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24346 public:
24348 }
24349
24350 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24351 struct SageInterface::const_int_expr_t subtreeVal;
24352 subtreeVal.hasValue_ = true;
24353
24354 if (isSgIntVal(valExp)) {
24355 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24356 } else if (isSgLongIntVal(valExp)) {
24357 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24358 } else if (isSgLongLongIntVal(valExp)) {
24359 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24360 } else if (isSgShortVal(valExp)) {
24361 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24362 } else if (isSgUnsignedIntVal(valExp)) {
24363 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24364 } else if (isSgUnsignedLongVal(valExp)) {
24365 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24366 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24367 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24368 } else if (isSgUnsignedShortVal(valExp)) {
24369 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24370 }
24371 return subtreeVal;
24372 }
24373
24374 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24375 if (isSgModifierType(vRef->get_type()) == NULL) {
24377 val.value_ = -1;
24378 val.hasValue_ = false;
24379 return val;
24380 }
24381 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24382 // We know that the var value is const, so get the initialized name and evaluate it
24383 SgVariableSymbol *sym = vRef->get_symbol();
24384 SgInitializedName *iName = sym->get_declaration();
24385 SgInitializer *ini = iName->get_initializer();
24386
24387 if (isSgAssignInitializer(ini)) {
24388 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24389 SgExpression *rhs = initializer->get_operand();
24390 SimpleExpressionEvaluator variableEval;
24391
24392 return variableEval.traverse(rhs);
24393 }
24394 }
24396 val.hasValue_ = false;
24397 val.value_ = -1;
24398 return val;
24399 }
24400
24401 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24402 if (isSgExpression(node) != NULL) {
24403 SgValueExp* valueExp = isSgValueExp(node);
24404 if (valueExp != NULL) {
24405 return this->getValueExpressionValue(valueExp);
24406 }
24407
24408 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24409 if (varRefExp != NULL) {
24410 // std::cout << "Hit variable reference expression!" << std::endl;
24411 return evaluateVariableReference(varRefExp);
24412 }
24413 // Early break out for assign initializer // other possibility?
24414 if (isSgAssignInitializer(node)) {
24415 if(synList.at(0).hasValue_){
24416 return synList.at(0);
24417 } else {
24419 val.value_ = -1;
24420 val.hasValue_ = false;
24421 return val;
24422 }
24423 }
24424 struct SageInterface::const_int_expr_t evaluatedValue;
24425 evaluatedValue.hasValue_ = false;
24426 evaluatedValue.value_ = -1;
24427#if 0
24428 if(synList.size() != 2){
24429 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24430 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24431 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24432 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24433 }
24434 }
24435#endif
24436 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24437 if((*it).hasValue_){
24438 if (isSgAddOp(node)) {
24439 assert(synList.size() == 2);
24440 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24441 evaluatedValue.hasValue_ = true;
24442 } else if (isSgSubtractOp(node)) {
24443 assert(synList.size() == 2);
24444 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24445 evaluatedValue.hasValue_ = true;
24446 } else if (isSgMultiplyOp(node)) {
24447 assert(synList.size() == 2);
24448 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24449 evaluatedValue.hasValue_ = true;
24450 } else if (isSgDivideOp(node)) {
24451 assert(synList.size() == 2);
24452 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24453 evaluatedValue.hasValue_ = true;
24454 } else if (isSgModOp(node)) {
24455 assert(synList.size() == 2);
24456 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24457 evaluatedValue.hasValue_ = true;
24458 }
24459 } else {
24460 std::cerr << "Expression is not evaluatable" << std::endl;
24461 evaluatedValue.hasValue_ = false;
24462 evaluatedValue.value_ = -1;
24463 return evaluatedValue;
24464 }
24465 }
24466 evaluatedValue.hasValue_ = true;
24467 return evaluatedValue;
24468 }
24469 struct SageInterface::const_int_expr_t evaluatedValue;
24470 evaluatedValue.hasValue_ = false;
24471 evaluatedValue.value_ = -1;
24472 return evaluatedValue;
24473 }
24474};
24475
24479 return eval.traverse(expr);
24480}
24481
24482bool
24484
24485 class TypeEquivalenceChecker {
24486 public:
24487 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24488 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24489 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24490 {
24491 }
24492
24493 SgNode * getBasetypeIfApplicable(SgNode *t){
24494 SgNode * node = t;
24495 if (isSgTypedefType(t)) {
24496// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24497 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24498 }
24499 if(useSemanticEquivalence_){
24500 if(isSgModifierType(t)){
24501 SgModifierType *modType = isSgModifierType(t);
24502 ROSE_ASSERT(modType != NULL);
24503 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24504 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24505 // like classes
24506 // restrict seems to have no impact on the type itself.
24507 if(SageInterface::isVolatileType(modType)){
24508 // handle volatile case
24509 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24510 node = modType->get_base_type();
24511 }
24512 if(SageInterface::isRestrictType(modType)){
24513 // handle restrict case
24514 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24515 node = modType->get_base_type();
24516 }
24517 }
24518 }
24519 ROSE_ASSERT(node != NULL);
24520 return node;
24521}
24522
24523bool typesAreEqual(SgType *t1, SgType *t2) {
24524 bool equal = false;
24525 if(t1 == NULL || t2 == NULL){
24526 std::string wasNull;
24527 if(t1 == NULL){
24528 wasNull = "t1";
24529 } else {
24530 wasNull = "t2";
24531 }
24532 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24533 return equal;
24534 }
24535 // if both pointers point to same location the types MUST be equal!
24536 if(t1 == t2){
24537// std::cout << "Pointers are equal, returning true" << std::endl;
24538 return true;
24539 }
24540#ifndef USE_CMAKEx
24541 RoseAst subT1(t1);
24542 RoseAst subT2(t2);
24543
24544 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24545 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24546 SgNode *nodeT1 = *i;
24547 SgNode *nodeT2 = *j;
24548
24549// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24550 nodeT1 = getBasetypeIfApplicable(nodeT1);
24551 nodeT2 = getBasetypeIfApplicable(nodeT2);
24552
24553 if (nodeT1->variantT() == nodeT2->variantT()) {
24554// std::cout << "variantT is the same" << std::endl;
24555 if(isSgModifierType(nodeT1)){
24556 // we need to check whether the modifier is the same or not
24557 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24558 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24559 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24560 return false;
24561 }
24562 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24563 return false;
24564 }
24565 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24566 if (profile_) {
24567 namedType_++;
24568 }
24569 i.skipChildrenOnForward();
24570 j.skipChildrenOnForward();
24571 SgNamedType *c1 = isSgNamedType(nodeT1);
24572 SgNamedType *c2 = isSgNamedType(nodeT2);
24573
24574 // XXX A function to check whether a named type is anonymous or not would speed
24575 // up this check, since we could get rid of this string compare.
24576 if(!c1->get_autonomous_declaration()){
24577 return false;
24578 }
24579 if (!c2->get_autonomous_declaration()){
24580 return false;
24581 }
24582 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24583 return true;
24584 } else {
24585 return false;
24586 }
24587
24588 } else if (isSgPointerType(nodeT1)) {
24589 if (profile_) {
24590 pointerType_++;
24591 }
24592 SgPointerType *t1 = isSgPointerType(nodeT1);
24593 SgPointerType *t2 = isSgPointerType(nodeT2);
24594
24595 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24596
24597 } else if(isSgReferenceType(nodeT1)){
24598 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24599 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24600
24601 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24602 } else if (isSgArrayType(nodeT1)) {
24603 if (profile_) {
24604 arrayType_++;
24605 }
24606 SgArrayType *a1 = isSgArrayType(nodeT1);
24607 SgArrayType *a2 = isSgArrayType(nodeT2);
24608
24609 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24610
24613 bool arrayIndexExpressionIsEquivalent = false;
24614 if(t1Index.hasValue_ && t2Index.hasValue_){
24615 if(t1Index.value_ == t2Index.value_){
24616 arrayIndexExpressionIsEquivalent = true;
24617 }
24618 }
24619 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24620 return arraysAreEqual;
24621 } else if (isSgFunctionType(nodeT1)) {
24622 if(profile_) {
24623 functionType_++;
24624 }
24625 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24626 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24627// std::cout << "Inside SgFunctionType" << std::endl;
24628// assert(funcTypeA != funcTypeB);
24629 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24630 // If functions don't have the same number of arguments, they are not type-equal
24631 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24632 return false;
24633 }
24634 // This should always be the same as the if before...
24635 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24636 return false;
24637 }
24638
24639 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24640 jj = funcTypeB->get_arguments().begin();
24641 ii != funcTypeA->get_arguments().end() &&
24642 jj != funcTypeB->get_arguments().end();
24643 ++ii, ++jj) {
24644// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24645 // For all argument types check whether they are equal
24646 if(!typesAreEqual((*ii), (*jj))) {
24647 return false;
24648 }
24649 }
24650 return true;
24651 }
24652 return false;
24653 } else {
24654 // We don't have a named type, pointer type or array type, so they are equal
24655 // This is for the primitive type - case
24656 return true;
24657 }
24658 } else {
24659 // In this case the types are not equal, since its variantT is not equal.
24660 return false;
24661 }
24662 }
24663 // this should be unreachable code...
24664 return equal;
24665#else
24666 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24667 ROSE_ABORT();
24668#endif
24669}
24670
24671int getNamedTypeCount() {
24672 return namedType_;
24673}
24674
24675int getPointerTypeCount() {
24676 return pointerType_;
24677}
24678
24679int getArrayTypeCount() {
24680 return arrayType_;
24681}
24682
24683int getFunctionTypeCount() {
24684 return functionType_;
24685}
24686 private:
24687// SgNode * getBasetypeIfApplicable(SgNode *t);
24688 bool profile_, useSemanticEquivalence_;
24689 int namedType_, pointerType_, arrayType_, functionType_;
24690};
24691
24692TypeEquivalenceChecker tec(false, false);
24693return tec.typesAreEqual(typeA, typeB);
24694}
24695
24696
24697std::set<SgStatement*>
24699 {
24700 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24701 // It is useful for debugging the token-based unparsing.
24702
24703 class StatementTraversal : public AstSimpleProcessing
24704 {
24705 public:
24706 StatementTraversal() : count (0) {}
24707 void visit (SgNode* node)
24708 {
24709 SgStatement* statement = isSgStatement(node);
24710 if (statement != nullptr && statement->isTransformation() == true)
24711 {
24712 returnset.insert(statement);
24713 count++;
24714 }
24715 }
24716
24717 int count; // running total of statements found marked as transformations in the input AST
24718 std::set<SgStatement*> returnset;
24719 };
24720
24721 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24722 StatementTraversal traversal;
24723 traversal.traverse(node, preorder);
24724
24725 return traversal.returnset;
24726 }
24727
24728std::set<SgStatement*>
24730 {
24731 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24732 // It is useful for debugging the token-based unparsing.
24733
24734#if 1
24735 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24736#endif
24737
24738 class StatementTraversal : public AstSimpleProcessing
24739 {
24740 public:
24741 StatementTraversal() : count (0) {}
24742 void visit (SgNode* node)
24743 {
24744 SgStatement* statement = isSgStatement(node);
24745 if (statement != NULL && statement->get_isModified() == true)
24746 {
24747 returnset.insert(statement);
24748 count++;
24749 }
24750 }
24751
24752 int count; // running total of statements found marked as transformations in the input AST
24753 std::set<SgStatement*> returnset;
24754 };
24755
24756 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24757 StatementTraversal traversal;
24758 traversal.traverse(node, preorder);
24759
24760 return traversal.returnset;
24761 }
24762
24763
24764void
24766 {
24767 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24768
24769#if 0
24770 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
24771#endif
24772
24773 class LocatedNodeTraversal : public AstSimpleProcessing
24774 {
24775 public:
24776 LocatedNodeTraversal() {}
24777 void visit (SgNode* node)
24778 {
24779 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24780 if (locatedNode != NULL)
24781 {
24782#if 0
24783 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
24784 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
24785#endif
24786 }
24787 else
24788 {
24789 SgInitializedName* initializedName = isSgInitializedName(node);
24790 if (initializedName != NULL)
24791 {
24792 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
24793 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
24794 }
24795 }
24796 }
24797 };
24798
24799 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24800 LocatedNodeTraversal traversal;
24801 traversal.traverse(node, preorder);
24802
24803#if 0
24804 printf ("Exiting as a test! \n");
24805 ROSE_ABORT();
24806#endif
24807 }
24808
24809
24810std::set<SgLocatedNode*>
24812 {
24813 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24814 // It is useful for debugging the token-based unparsing.
24815
24816#if 0
24817 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
24818#endif
24819
24820 class LocatedNodeTraversal : public AstSimpleProcessing
24821 {
24822 public:
24823 LocatedNodeTraversal() : count (0) {}
24824 void visit (SgNode* node)
24825 {
24826 SgLocatedNode* locatedNode = isSgLocatedNode(node);
24827 if (locatedNode != NULL && locatedNode->get_isModified() == true)
24828 {
24829#if 0
24830 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
24831#endif
24832 returnset.insert(locatedNode);
24833 count++;
24834 }
24835 }
24836
24837 int count; // running total of statements found marked as transformations in the input AST
24838 std::set<SgLocatedNode*> returnset;
24839 };
24840
24841 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24842 LocatedNodeTraversal traversal;
24843 traversal.traverse(node, preorder);
24844
24845 return traversal.returnset;
24846 }
24847
24848
24850void
24851SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
24852 {
24853 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
24854
24855#if 0
24856 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
24857#endif
24858
24859 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
24860 while (i != modifiedNodeSet.end())
24861 {
24862 SgLocatedNode* node = *i;
24863#if 0
24864 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
24865#endif
24866 node->set_isModified(true);
24867
24868 i++;
24869 }
24870 }
24871
24872
24873void
24875 {
24876 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
24877 // It is useful for debugging the token-based unparsing.
24878
24879 printf ("\n\n##################################################### \n");
24880 printf ("Report on modified statements: label = %s \n",label.c_str());
24881
24882 SgSourceFile* sourceFile = isSgSourceFile(node);
24883 if (sourceFile != NULL)
24884 {
24885 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24886 }
24887 else
24888 {
24889 SgGlobal* globalScope = isSgGlobal(node);
24890 if (globalScope != NULL)
24891 {
24892 sourceFile = isSgSourceFile(globalScope->get_parent());
24893 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24894 }
24895 }
24896
24897 ROSE_ASSERT(node != NULL);
24898 std::set<SgStatement*> collection = collectModifiedStatements(node);
24899
24900#if 0
24901 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
24902#endif
24903
24904 std::set<SgStatement*>::iterator i = collection.begin();
24905 while (i != collection.end())
24906 {
24907 // DQ (10/9/2019): Adding filename to debug output.
24908 string filename = (*i)->get_file_info()->get_filename();
24909
24910 // DQ (10/14/2019): Get the best name possible.
24911 if (filename == "transformation")
24912 {
24913#if 0
24914 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24915#endif
24916 // filename = (*i)->get_file_info()->get_physical_filename();
24917 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24918 if (sourceFile != NULL)
24919 {
24920 filename = sourceFile->getFileName();
24921 }
24922 }
24923
24924 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24925
24926 i++;
24927 }
24928
24929#if 1
24930 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
24931 // output spew else the message output at the top of this function will scroll off the screen.
24932 printf ("########################################################## \n");
24933 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
24934#endif
24935 printf ("########################################################## \n\n\n");
24936
24937#if 0
24938 printf ("Exiting as a test! \n");
24939 ROSE_ASSERT(false);
24940#endif
24941 }
24942
24943
24944
24945void
24947 {
24948 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
24949 // It is useful for debugging the token-based unparsing.
24950
24951 printf ("\n\n##################################################### \n");
24952 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
24953
24954 SgSourceFile* sourceFile = isSgSourceFile(node);
24955 if (sourceFile != NULL)
24956 {
24957 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
24958 }
24959 else
24960 {
24961 SgGlobal* globalScope = isSgGlobal(node);
24962 if (globalScope != NULL)
24963 {
24964 sourceFile = isSgSourceFile(globalScope->get_parent());
24965 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
24966 }
24967 }
24968
24969 ROSE_ASSERT(node != NULL);
24970 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
24971
24972#if 0
24973 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
24974#endif
24975
24976 std::set<SgLocatedNode*>::iterator i = collection.begin();
24977 while (i != collection.end())
24978 {
24979 // DQ (10/9/2019): Adding filename to debug output.
24980 string filename = (*i)->get_file_info()->get_filename();
24981
24982 // DQ (10/14/2019): Get the best name possible.
24983 if (filename == "transformation")
24984 {
24985#if 0
24986 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
24987#endif
24988 // filename = (*i)->get_file_info()->get_physical_filename();
24989 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
24990 if (sourceFile != NULL)
24991 {
24992 filename = sourceFile->getFileName();
24993 }
24994 }
24995
24996 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
24997
24998 i++;
24999 }
25000
25001#if 1
25002 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
25003 // output spew else the message output at the top of this function will scroll off the screen.
25004 printf ("########################################################## \n");
25005 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
25006#endif
25007 printf ("########################################################## \n\n\n");
25008
25009#if 0
25010 printf ("Exiting as a test! \n");
25011 ROSE_ASSERT(false);
25012#endif
25013 }
25014
25015
25016
25017
25018// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
25019
25020void
25022 {
25023 // Debugging function to print out comments in the statements (added by DQ)
25024
25025 ROSE_ASSERT(locatedNode != NULL);
25026 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
25027
25028#if 0
25029 curprint ("/* Inside of printOutComments() */");
25030#endif
25031
25032 if (comments != NULL)
25033 {
25034#if 0
25035 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25036 curprint ("/* Inside of printOutComments(): comments != NULL */");
25037#endif
25038
25039 AttachedPreprocessingInfoType::iterator i;
25040 for (i = comments->begin(); i != comments->end(); i++)
25041 {
25042 ROSE_ASSERT ( (*i) != NULL );
25043 printf (" Attached Comment (relativePosition=%s): %s \n",
25044 // DQ (2/11/2021): Fixed to report correct relative locations.
25045 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25046 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
25047 (*i)->getString().c_str());
25048 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
25049 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
25050
25051#if 0
25052 (*i)->get_file_info()->display("comment/directive location");
25053#endif
25054 }
25055 }
25056 else
25057 {
25058#if 0
25059 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25060#endif
25061 }
25062 }
25063
25064
25065
25066bool
25068 {
25069 bool returnValue = false;
25070
25071 ROSE_ASSERT(currentPreprocessingInfo != NULL);
25072
25073 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
25074
25075 if (directive == PreprocessingInfo::C_StyleComment ||
25076 directive == PreprocessingInfo::CplusplusStyleComment ||
25077 directive == PreprocessingInfo::FortranStyleComment ||
25078 directive == PreprocessingInfo::CpreprocessorBlankLine ||
25079 directive == PreprocessingInfo::ClinkageSpecificationStart ||
25080 directive == PreprocessingInfo::ClinkageSpecificationEnd)
25081 {
25082 returnValue = true;
25083 }
25084
25085 return returnValue;
25086 }
25087
25088std::vector<SgC_PreprocessorDirectiveStatement*>
25090 {
25091 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
25092
25093 // Find existing first and last header.
25094 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
25095
25096 if (comments != nullptr)
25097 {
25098 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
25099 for (i = comments->begin (); i != comments->end(); i++)
25100 {
25101 if (skipTranslateToUseCppDeclaration(*i) == true)
25102 {
25103 // 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).
25104 }
25105 else
25106 {
25107 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
25108 ROSE_ASSERT(directive != NULL);
25109 directiveList.push_back(directive);
25110 }
25111
25112 printf ("directiveList.size() = %zu \n",directiveList.size());
25113 }
25114 }
25115
25116 return directiveList;
25117 }
25118
25119
25120void
25122 {
25123 bool declarationsOnly = scope->containsOnlyDeclarations();
25124
25125 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
25126
25127 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
25128
25129 if (declarationsOnly == true)
25130 {
25131 // These are scopes such as global scope, namespace definitions, class definitions, etc.
25132 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
25133 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
25134 while (i != declarationList.end())
25135 {
25136 SgDeclarationStatement* declaration = *i;
25137 ROSE_ASSERT(declaration != NULL);
25138
25139 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
25140
25141 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25142
25143 if (attachDirectives.empty() == false)
25144 {
25145 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
25146 }
25147
25148 i++;
25149 }
25150
25151 // Need to save the list of things that will be added so we can avoid iterator invalidation.
25152 }
25153 else
25154 {
25155 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
25156 SgStatementPtrList & statementList = scope->getStatementList();
25157 SgStatementPtrList::iterator i = statementList.begin();
25158 while (i != statementList.end())
25159 {
25160 SgStatement* statement = *i;
25161 ROSE_ASSERT(statement != NULL);
25162
25163 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
25164
25165 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25166
25167 if (attachDirectives.empty() == false)
25168 {
25169 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
25170 }
25171
25172 i++;
25173 }
25174 }
25175
25176 printf ("directiveMap.size() = %zu \n",directiveMap.size());
25177
25178 printf ("Processing the directiveMap: \n");
25179 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
25180 while (i != directiveMap.end())
25181 {
25182 SgStatement* statement = i->first;
25183 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
25184
25185 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
25186 printf ("directives.size() = %zu \n",directives.size());
25187 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
25188 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
25189 while (j != directives.end())
25190 {
25191 scope->insert_statement(statement,*j);
25192
25193 j++;
25194 }
25195
25196 // Remove the directives there were attached to the statement.
25197 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
25198 ROSE_ASSERT(comments != NULL);
25199
25200 AttachedPreprocessingInfoType deleteList;
25201 // std::vector<PreprocessingInfo*> deleteList;
25202
25203 // comments->erase();
25204 // statement->setAttachedPreprocessingInfo(NULL);
25205 AttachedPreprocessingInfoType::iterator k;
25206 for (k = comments->begin(); k != comments->end(); k++)
25207 {
25208#if 1
25209 ROSE_ASSERT ( (*k) != NULL );
25210 printf (" Attached Comment (relativePosition=%s): %s\n",
25211 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25212 (*k)->getString().c_str());
25213 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
25214#endif
25215
25216 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25217 if (skipTranslateToUseCppDeclaration(*k) == true)
25218 {
25219 // 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).
25220 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25221 }
25222 else
25223 {
25224 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25225
25226 deleteList.push_back(*k);
25227 // delete *k;
25228 // *k = NULL;
25229 }
25230 }
25231
25232 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25233 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25234 while (m != deleteList.end())
25235 {
25236 // comments->erase(m);
25237 // std::remove(comments->begin(), comments->end(), *m);
25238 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25239
25240 printf (" --- comments->size() = %zu \n",comments->size());
25241
25242 m++;
25243 }
25244
25245 // comments->clear();
25246 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25247 // statement->set_attachedPreprocessingInfoPtr(NULL);
25248
25249 i++;
25250 }
25251
25252 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25253 }
25254
25255
25256void
25258 {
25259 class CppTranslationTraversal : public AstSimpleProcessing
25260 {
25261 public:
25262 CppTranslationTraversal() {}
25263 void visit (SgNode* node)
25264 {
25265 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25266
25267 SgScopeStatement* scope = isSgScopeStatement(node);
25268 SgGlobal* globalScope = isSgGlobal(scope);
25269 if (globalScope != NULL)
25270 {
25271 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25273 }
25274 else
25275 {
25276 if (scope != NULL)
25277 {
25278 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25279 }
25280 }
25281 }
25282 };
25283
25284 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25285 CppTranslationTraversal traversal;
25286
25287 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25288
25289 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25290 // traversal.traverse(n, preorder);
25291 traversal.traverse(n, postorder);
25292
25293 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25294 }
25295
25297{
25298 // print current level's info
25299 if (!n) return;
25300 cout<<"--------------"<<endl;
25301 cout<<n<<":"<<n->class_name()<< endl;
25302 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25303 {
25304 cout<<"file info:\t ";
25305 lnode->get_file_info()->display();
25306 cout<<"\n unparseToString:\t ";
25307 lnode->unparseToString();
25308 }
25309
25310 // track back to its parent
25312}
25313// forward declaration is needed here,
25314//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25315
25316#if 0 // made it into a template function to handle various ptr lists in AST
25317// A special node in the AST text dump
25318static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25319{
25320 out<<prefix;
25321 out<< (hasRemaining?"|---": "|___");
25322
25323// out<<"+"<<edgeLabel<<"+>";
25324 out<<" "<<edgeLabel<<" ->";
25325 // print address
25326 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25327
25328 out<<endl;
25329
25330 int last_non_null_child_idx =-1;
25331 for (int i = (int) (plist.size())-1; i>=0; i--)
25332 {
25333 if (plist[i])
25334 {
25335 last_non_null_child_idx = i;
25336 break;
25337 }
25338 }
25339
25340 for (size_t i=0; i< plist.size(); i++ )
25341 {
25342 bool n_hasRemaining=false;
25343#if 0
25344 if (i+1 < plist.size())
25345 n_hasRemaining=true;
25346#else
25347 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25348#endif
25349 string suffix= hasRemaining? "| " : " ";
25350 string n_prefix = prefix+suffix;
25351 string n_edge_label="";
25352 if (plist[i])
25353 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25354 }
25355}
25356#endif
25357
25358// print essential information from any AST node
25359// hasRemaining if this node has a sibling node to be visited next.
25360void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25361{
25362 // there may be NULL children!!
25363 //if (!node) return;
25364
25365 out<<prefix;
25366 out<< (hasRemaining?"|---": "|___");
25367
25368 out<<" "<<edgeLabel<<" ->";
25369 if (!node)
25370 {
25371 out<<" NULL "<<endl;
25372 return;
25373 }
25374
25375 // print address
25376 out<<"@"<<node<<" "<< node->class_name()<<" ";
25377
25378 //optionally file info
25379 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25380 {
25381 //Rose::StringUtility::stripPathFromFileName()
25382 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25383 // also preprocessing info. attached.
25384 AttachedPreprocessingInfoType *comments =
25385 lnode->getAttachedPreprocessingInfo ();
25386
25387 if (comments != NULL)
25388 {
25389// printf ("Found an IR node with preprocessing Info attached:\n");
25390 out<<" AttachedPreprocessingInfoType@"<<comments;
25391 int counter = 0;
25392 AttachedPreprocessingInfoType::iterator i;
25393 out <<"{";
25394 for (i = comments->begin (); i != comments->end (); i++)
25395 {
25396 if (i!=comments->begin ())
25397 out<<endl;
25398 out<<"<id=";
25399 out<<counter++<<" ";
25400 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25401 // printf("classification = %s:\n String format = %s\n",
25402 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25403 // (*i)->getString ().c_str ());
25404 if (*i==NULL)
25405 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25406 else
25407 {
25408 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25409 out<<" string="<<(*i)->getString ().c_str ();
25410 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25411#if 1
25412 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25413 out<<"inside";
25414 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25415 out<<"before";
25416 else
25417 out<<"after";
25418#endif
25419 }
25420 out<<">";
25421 }
25422 out <<"}";
25423 }
25424 }
25425
25426 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25427 {
25428 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25429 out<<" defining decl@"<< v->get_definingDeclaration();
25430 }
25431
25432 if (SgEnumVal* f = isSgEnumVal(node) )
25433 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25434 // optionally qualified name
25435
25436 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25437 out<<" "<< f->get_qualified_name();
25438
25439 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25440 out<<" renamed_function "<< f->get_renamed_function();
25441
25442 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25443 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25444
25445 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25446 out<<" "<< f->get_qualified_name();
25447
25448 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25449 out<<" "<< f->get_qualified_name();
25450
25451 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25452 out<<" "<< f->get_qualified_name();
25453
25454 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25455 out<<" enumType="<< f->get_enumType();
25456
25457 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25458 {
25459 // out<<" "<< v->get_qualified_name();
25460 //out<<" "<< v->get_name();
25461 // PP (2/18/22) updated to reflect properties in AdaAccessType
25462 //~ out<<" is_object_type"<< v->get_is_object_type();
25463 out<<" is_general_access"<< v->get_is_general_access();
25464 //~ out<<" is_constant:"<< v->get_is_constant();
25465 //~ out<<" is_protected:"<< v->get_is_protected ();
25466 out<<" is_anonymous:"<< v->get_is_anonymous ();
25467 }
25468
25469 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25470 {
25471 out<<" is_protected"<< v->get_is_protected();
25472 }
25473
25474 if (SgInitializedName * v = isSgInitializedName(node) )
25475 {
25476 out<<" "<< v->get_qualified_name();
25477 out<<" type@"<< v->get_type();
25478 out<<" initializer@"<< v->get_initializer();
25479 out<<" scope@"<< v->get_scope();
25480// type_set.insert (v->get_type());
25481 }
25482
25483 // associated class, function and variable declarations
25484 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25485 out<<" template class decl@"<< f->get_templateDeclaration();
25486
25487 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25488 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25489
25490 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25491 {
25492 out<<" member function decl@"<< ctor->get_declaration();
25493 }
25494
25495 if (SgIntVal* v= isSgIntVal(node))
25496 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25497
25498 if (SgShortVal* v= isSgShortVal(node))
25499 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25500
25501 if (SgLongIntVal* v= isSgLongIntVal(node))
25502 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25503
25504 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25505 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25506
25507 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25508 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25509
25510 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25511 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25512
25513 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25514 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25515
25516 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25517 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25518
25519 if (SgFloatVal* v= isSgFloatVal(node))
25520 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25521
25522 if (SgDoubleVal* v= isSgDoubleVal(node))
25523 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25524
25525 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25526 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25527
25528 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25529 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25530
25531 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25532 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25533
25534 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25535 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25536
25537 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25538 {
25539 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25540 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25541 }
25542
25543 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25544 {
25545 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25546 out<<" ada renaming decl@"<< renaming_decl;
25547 }
25548
25549 // base type of several types of nodes:
25550 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25551 {
25552 out<<" base_type@"<< v->get_base_type();
25553// type_set.insert (v->get_base_type());
25554 }
25555
25556 if (SgArrayType* v= isSgArrayType(node))
25557 out<<" base_type@"<< v->get_base_type();
25558
25559 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25560 out<<" base_type@"<< v->get_base_type();
25561
25562 if (SgTypeExpression* v= isSgTypeExpression(node))
25563 out<<" type@"<< v->get_type();
25564
25565 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25566 out<<" attribute@"<< v->get_attribute();
25567
25568 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25569 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25570
25571 out<<endl;
25572
25573 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25574#if 0
25575 int total_count = children.size();
25576 int current_index=0;
25577#endif
25578
25579 int last_non_null_child_idx =-1;
25580 for (int i = (int) (children.size())-1; i>=0; i--)
25581 {
25582 if (children[i])
25583 {
25584 last_non_null_child_idx = i;
25585 break;
25586 }
25587 }
25588
25589#if 0
25590 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25591 // we sum all children into single total_count to tell if there is remaining children.
25592 if (isSgTemplateInstantiationDecl (node))
25593 total_count += 1; // sn->get_templateArguments().size();
25594#endif
25595
25596 // handling SgTemplateArgumentPtrList first
25597 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25598 {
25599 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25600 bool n_hasRemaining=false;
25601 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25602 string suffix= hasRemaining? "| " : " ";
25603 string n_prefix = prefix+suffix;
25604 string n_edge_label= "";
25605 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25606 }
25607 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25608 {
25609 SgExpressionPtrList& plist = import_stmt->get_import_list();
25610 bool n_hasRemaining=false;
25611 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25612 string suffix= hasRemaining? "| " : " ";
25613 string n_prefix = prefix+suffix;
25614 string n_edge_label= "";
25615 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25616 }
25617
25618 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25619
25620 // finish sucessors
25621 for (size_t i =0; i< children.size(); i++)
25622 {
25623 bool n_hasRemaining=false;
25624#if 0
25625 if (current_index+1<total_count)
25626 n_hasRemaining=true;
25627 current_index++;
25628#else
25629 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25630#endif
25631 string suffix= hasRemaining? "| " : " ";
25632 string n_prefix = prefix+suffix;
25633 if (children[i])
25634 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25635 }
25636}
25637
25639{
25640 ostringstream oss;
25641 string prefix;
25642 string label="";
25643 serialize(node, prefix, false, oss, label);
25644 cout<<oss.str();
25645}
25646
25647void SageInterface::printAST(SgNode* node, const char* filename)
25648{
25649 printAST2TextFile(node, filename, true);
25650}
25651
25652void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25653{
25654 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25655// ROSE_ABORT();
25656 printAST2TextFile (node, filename.c_str(), printType);
25657}
25658
25659void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25660{
25661 ostringstream oss;
25662 string prefix;
25663 string label="";
25664 serialize(node, prefix, false, oss, label);
25665 ofstream textfile;
25666 textfile.open(filename, ios::out);
25667 textfile<<oss.str();
25668
25669 if (printType)
25670 {
25671 // append type information also
25672 textfile<<"Types encountered ...."<<endl;
25673 ostringstream oss2;
25674 VariantVector vv(V_SgType);
25675 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25676 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25677 {
25678 serialize (*i, prefix, false, oss2, label);
25679 }
25680 textfile<<oss2.str();
25681 }
25682
25683 textfile.close();
25684}
25685
25687{
25688 saveToPDF(node, string("temp.pdf.json") );
25689}
25691// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25692void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25693{
25694 ROSE_ASSERT(node != NULL);
25695 AstJSONGeneration json;
25696 json.generateWithinFile(filename, getEnclosingFileNode(node));
25697}
25698
25700{
25701 bool rtval = false;
25702 ROSE_ASSERT (node != NULL);
25703 Sg_File_Info* finfo = node->get_file_info();
25704 if (finfo!=NULL)
25705 {
25706 string fname = finfo->get_filenameString();
25707 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25708 string buildtree_str2 = string("include-staging/g++_HEADERS");
25709 string installtree_str1 = string("include/edg/gcc_HEADERS");
25710 string installtree_str2 = string("include/edg/g++_HEADERS");
25711 string system_headers = string("/usr/include");
25712 // if the file name has a sys header path of either source or build tree
25713 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25714 (fname.find (buildtree_str2, 0) != string::npos) ||
25715 (fname.find (installtree_str1, 0) != string::npos) ||
25716 (fname.find (installtree_str2, 0) != string::npos) ||
25717 (fname.find (system_headers, 0) != string::npos)
25718 )
25719 rtval = true;
25720 }
25721 return rtval;
25722}
25723
25724
25725// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25727 {
25728 // Check if a node is from a header file
25729
25730 bool returnValue = false;
25731
25732 Sg_File_Info* fileInfo = node->get_file_info();
25733 ROSE_ASSERT(fileInfo != NULL);
25734 string filename = fileInfo->get_filenameString();
25735
25736#if 0
25737 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());
25738#endif
25739
25740 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25741 // so the test is only if the filename is in the list.
25742 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25743 {
25744#if 0
25745 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25746#endif
25747 }
25748 else
25749 {
25750#if 0
25751 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25752#endif
25753 returnValue = true;
25754 }
25755
25756 return returnValue;
25757 }
25758
25759
25762{
25763 ROSE_ASSERT(return_type != NULL);
25764 ROSE_ASSERT(typeList != NULL);
25766 ROSE_ASSERT(fTable);
25767
25768 // This function make clever use of a static member function which can't be built
25769 // for the case of a SgMemberFunctionType (or at least not without more work).
25770 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
25771 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
25772
25773 return funcType;
25774}
25775
25780{
25781 ROSE_ASSERT (lhs != NULL);
25782 ROSE_ASSERT (rhs != NULL);
25783 if (lhs == rhs)
25784 return true;
25785
25786 bool rt = false;
25787 SgType* rt1 = lhs->get_return_type();
25788 SgType* rt2 = rhs->get_return_type();
25789
25790 if (isEquivalentType (rt1, rt2))
25791 {
25792 SgTypePtrList f1_arg_types = lhs->get_arguments();
25793 SgTypePtrList f2_arg_types = rhs->get_arguments();
25794 // Must have same number of argument types
25795 if (f1_arg_types.size() == f2_arg_types.size())
25796 {
25797 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
25798 // int counter = 0;
25799 size_t counter = 0;
25800 // iterate through all argument types
25801 // for (int i=0; i< f1_arg_types.size(); i++)
25802 for (size_t i=0; i< f1_arg_types.size(); i++)
25803 {
25804 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
25805 counter ++; // count the number of equal arguments
25806 else
25807 break; // found different type? jump out the loop
25808 }
25809 // all arguments are equivalent, set to true
25810 if (counter == f1_arg_types.size())
25811 rt = true;
25812 }
25813 } // end if equivalent return types
25814
25815 return rt;
25816}
25817
25818bool
25820 {
25821 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
25822
25823 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
25824
25825 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
25826 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
25827 // Note that this is only required within the change to use this isEquivalentType() function in the
25828 // support to replace:
25829 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
25830 // in ROSETTA/Grammar/Support.code
25831
25832 ROSE_ASSERT(lhs != NULL);
25833 ROSE_ASSERT(rhs != NULL);
25834
25835 bool isSame = false;
25836
25837 // 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).
25838 static int counter = 0;
25839
25840 const SgType & X = *lhs;
25841 const SgType & Y = *rhs;
25842
25843 // DQ (11/28/2015): We don't want to strip off everything.
25844 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
25845
25846 // I think we need to compute the type chain to evaluate equalence.
25847 // Rose_STL_Container< SgType*> getInternalTypes () const
25848
25849#define DEBUG_TYPE_EQUIVALENCE 0
25850
25851#if DEBUG_TYPE_EQUIVALENCE
25852 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25853 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
25854 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
25855#endif
25856
25857#if DEBUG_TYPE_EQUIVALENCE || 0
25858 if (counter == 0)
25859 {
25860 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
25861 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
25862 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
25863 }
25864#endif
25865
25866#if DEBUG_TYPE_EQUIVALENCE || 0
25867 // Debugging output.
25868 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
25869 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
25870
25871 // Debugging output.
25872 printf ("Output of type chain for lhs: \n");
25873 for (size_t i = 0; i < X_typeChain.size(); i++)
25874 {
25875 SgType* element_type = X_typeChain[i];
25876 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25877 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25878 SgModifierType* modifierType = isSgModifierType(element_type);
25879 if (modifierType != NULL)
25880 {
25881 // modifierType->get_typeModifier().display("X type chain");
25882 string s = modifierType->get_typeModifier().displayString();
25883 printf (" --- type chain modifier: %s \n",s.c_str());
25884 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25885 }
25886 }
25887
25888 printf ("Output of type chain for rhs: \n");
25889 for (size_t i = 0; i < Y_typeChain.size(); i++)
25890 {
25891 SgType* element_type = Y_typeChain[i];
25892 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
25893 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
25894 SgModifierType* modifierType = isSgModifierType(element_type);
25895 if (modifierType != NULL)
25896 {
25897 // modifierType->get_typeModifier().display("Y type chain");
25898 string s = modifierType->get_typeModifier().displayString();
25899 printf (" --- type chain modifier: %s \n",s.c_str());
25900 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
25901 }
25902 }
25903#endif
25904
25905 // Increment the static variable to control the recursive depth while we debug this.
25906 counter++;
25907
25908 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
25909 // if (counter >= 280)
25910 // if (counter >= 500)
25911 if (counter >= 280)
25912 {
25913 // 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());
25914 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);
25915 }
25916
25917 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
25918 // DQ (11/28/2015): exit in stead of infinte recursion.
25919 // if (counter > 300)
25920 // if (counter > 600)
25921 // if (counter > 5000)
25922 // if (counter > 300)
25923 if (counter > 350)
25924 {
25925 // DQ (11/28/2015): I think this is a reasonable limit.
25926 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
25927 ROSE_ABORT();
25928 }
25929
25930 // bool exit = false;
25931
25932 // Strip off any typedefs since they are equivalent by definition.
25933 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
25934 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
25935
25936 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
25937 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
25938 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
25939
25940 if (X_referenceType != NULL && Y_referenceType != NULL)
25941 {
25942 X_element_type = X_referenceType->get_base_type();
25943 Y_element_type = Y_referenceType->get_base_type();
25944
25945 counter--;
25946
25947 // Recursive call.
25948 // return (*X_element_type) == (*Y_element_type);
25949 return isEquivalentType(X_element_type,Y_element_type);
25950 }
25951 else
25952 {
25953 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25954 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
25955 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
25956
25957 if (X_pointerType != NULL && Y_pointerType != NULL)
25958 {
25959 X_element_type = X_pointerType->get_base_type();
25960 Y_element_type = Y_pointerType->get_base_type();
25961
25962 counter--;
25963
25964 // Recursive call.
25965 // return (*X_element_type) == (*Y_element_type);
25966 return isEquivalentType(X_element_type,Y_element_type);
25967 }
25968 else
25969 {
25970 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
25971 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
25972 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
25973
25974 // DQ (12/8/2015): We need to check that the array size is the same.
25975 if (X_arrayType != NULL && Y_arrayType != NULL)
25976 {
25977 X_element_type = X_arrayType->get_base_type();
25978 Y_element_type = Y_arrayType->get_base_type();
25979
25980 SgExpression* X_array_index_expression = X_arrayType->get_index();
25981 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
25982
25983 if (X_array_index_expression == Y_array_index_expression)
25984 {
25985#if DEBUG_TYPE_EQUIVALENCE || 0
25986 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
25987#endif
25988 counter--;
25989
25990 // Recursive call.
25991 // return (*X_element_type) == (*Y_element_type);
25992 return isEquivalentType(X_element_type,Y_element_type);
25993 }
25994 else
25995 {
25996 // Need more complex test for expression equivalence.
25997#if DEBUG_TYPE_EQUIVALENCE || 0
25998 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
25999 string str1 = X_array_index_expression->unparseToString();
26000 string str2 = Y_array_index_expression->unparseToString();
26001 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
26002#endif
26003 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
26004 counter--;
26005
26006 // Recursive call.
26007 return isEquivalentType(X_element_type,Y_element_type);
26008 }
26009 }
26010 else
26011 {
26012 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26013 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
26014 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
26015
26016 // DQ (12/15/2015): We need to check that the array size is the same.
26017 if (X_templateType != NULL && Y_templateType != NULL)
26018 {
26019 string X_name = X_templateType->get_name();
26020 string Y_name = Y_templateType->get_name();
26021
26022 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
26023 ROSE_ASSERT(X_templateDecl != NULL);
26024 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
26025 ROSE_ASSERT(Y_templateDecl != NULL);
26026
26027 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
26028 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
26029
26030 SgNode * X_parent = X_templateDecl->get_parent();
26031 SgNode * Y_parent = Y_templateDecl->get_parent();
26032
26033#if DEBUG_TYPE_EQUIVALENCE
26034 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
26035 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
26036 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
26037 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
26038 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
26039 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() : "");
26040 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() : "");
26041 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
26042 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
26043#endif
26044 bool value = (X_parent == Y_parent);
26045
26046 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
26047 value = (X_template_parameter_position == Y_template_parameter_position);
26048 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
26049 value = (X_name == Y_name);
26050 }
26051
26052 counter--;
26053
26054 return value;
26055 }
26056 else
26057 {
26058 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
26059 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
26060#if 0
26061 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
26062 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
26063 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
26064 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26065 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26066#endif
26067#if DEBUG_TYPE_EQUIVALENCE
26068 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");
26069#endif
26070 }
26071 }
26072 }
26073 } // end if reference type, pointer type, array type, and template type
26074
26075 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
26076 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
26077
26078#if DEBUG_TYPE_EQUIVALENCE
26079 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
26080 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26081#endif
26082
26083 if (X_modifierType != NULL && Y_modifierType != NULL)
26084 {
26085 // Handle the case of both modifiers.
26086#if DEBUG_TYPE_EQUIVALENCE
26087 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
26088#endif
26089 if (X_modifierType == Y_modifierType)
26090 {
26091 isSame = true;
26092#if DEBUG_TYPE_EQUIVALENCE
26093 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
26094#endif
26095 }
26096 else
26097 {
26098 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
26099 {
26100#if DEBUG_TYPE_EQUIVALENCE
26101 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
26102#endif
26103 // Recursive call.
26104 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
26105 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
26106 }
26107 else
26108 {
26109#if DEBUG_TYPE_EQUIVALENCE
26110 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
26111#endif
26112 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
26113 bool skippingOverIdentityModifier = false;
26114
26115 if (X_modifierType->get_typeModifier().isIdentity() == true)
26116 {
26117#if DEBUG_TYPE_EQUIVALENCE
26118 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26119#endif
26120 X_element_type = X_modifierType->get_base_type();
26121
26122 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26123 skippingOverIdentityModifier = true;
26124 }
26125
26126 if (Y_modifierType->get_typeModifier().isIdentity() == true)
26127 {
26128#if DEBUG_TYPE_EQUIVALENCE
26129 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26130#endif
26131 Y_element_type = Y_modifierType->get_base_type();
26132
26133 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26134 skippingOverIdentityModifier = true;
26135 }
26136
26137 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26138#if DEBUG_TYPE_EQUIVALENCE
26139 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
26140#endif
26141 // Recursive call on non-default modifier base types.
26142 // isSame = (*X_element_type) == (*Y_element_type);
26143 // isSame = isEquivalentType(X_element_type,Y_element_type);
26144 if (skippingOverIdentityModifier == true)
26145 {
26146#if DEBUG_TYPE_EQUIVALENCE
26147 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");
26148#endif
26149 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
26150 isSame = isEquivalentType(X_element_type,Y_element_type);
26151 }
26152 else
26153 {
26154 // 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).
26155 isSame = false;
26156#if DEBUG_TYPE_EQUIVALENCE
26157 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");
26158#endif
26159 }
26160
26161#if DEBUG_TYPE_EQUIVALENCE
26162 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
26163#endif
26164 }
26165 }
26166 }
26167 else
26168 {
26169 // At least one of these is not a SgModifierType.
26170
26171 if (X_modifierType != NULL || Y_modifierType != NULL)
26172 {
26173 bool isReduceable = false;
26174
26175 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
26176 {
26177#if DEBUG_TYPE_EQUIVALENCE
26178 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26179#endif
26180 X_element_type = X_modifierType->get_base_type();
26181 isReduceable = true;
26182 }
26183
26184 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
26185 {
26186#if DEBUG_TYPE_EQUIVALENCE
26187 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26188#endif
26189 Y_element_type = Y_modifierType->get_base_type();
26190 isReduceable = true;
26191 }
26192
26193 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26194#if DEBUG_TYPE_EQUIVALENCE
26195 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
26196#endif
26197 if (isReduceable == true)
26198 {
26199 // Recursive call on non-default modifier base types.
26200 // isSame = (*X_element_type) == (*Y_element_type);
26201 isSame = isEquivalentType(X_element_type,Y_element_type);
26202 }
26203 else
26204 {
26205 // Neither of these types were reducable.
26206 isSame = false;
26207 }
26208
26209#if DEBUG_TYPE_EQUIVALENCE
26210 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
26211 isReduceable ? "true" : "false",isSame ? "true" : "false");
26212#endif
26213 }
26214 else
26215 {
26216 // Neither of these are SgModifierType nodes.
26217 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26218 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26219
26220 if (X_element_type == Y_element_type)
26221 {
26222 isSame = true;
26223#if DEBUG_TYPE_EQUIVALENCE || 0
26224 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26225 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26226 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26227#endif
26228#if DEBUG_TYPE_EQUIVALENCE || 0
26229 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26230 // still might not be interchangable if one is defined in a restrcited scope.
26231 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26232 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26233
26234 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26235 {
26236#if 0
26237 if (lhs_typedefType != NULL)
26238 {
26239 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26240 }
26241 if (rhs_typedefType != NULL)
26242 {
26243 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26244 }
26245#else
26246 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26247 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26248#endif
26249 }
26250#endif
26251 }
26252 else
26253 {
26254 // DQ (3/20/2016): This is reported by GNU as set but not used.
26255 // bool isReduceable = false;
26256
26257 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26258 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26259 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26260
26261 if (X_referenceType != NULL || Y_referenceType != NULL)
26262 {
26263#if 0
26264 if (X_referenceType != NULL)
26265 {
26266 X_element_type = X_referenceType->get_base_type();
26267
26268 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26269 // isReduceable = true;
26270 isReduceable = false;
26271 }
26272
26273 if (Y_referenceType != NULL)
26274 {
26275 Y_element_type = Y_referenceType->get_base_type();
26276
26277 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26278 // isReduceable = true;
26279 isReduceable = false;
26280 }
26281
26282 if (isReduceable == true)
26283 {
26284 // Recursive call on non-default modifier base types.
26285 // isSame = (*X_element_type) == (*Y_element_type);
26286 isSame = isEquivalentType(X_element_type,Y_element_type);
26287 }
26288 else
26289 {
26290 // Neither of these types were reducable.
26291 isSame = false;
26292 }
26293#else
26294 isSame = false;
26295#endif
26296 }
26297 else
26298 {
26299 // Recursive call on non-typedef base types.
26300 // isSame = (*X_element_type) == (*Y_element_type);
26301 // isSame = isEquivalentType(X_element_type,Y_element_type);
26302
26303#if DEBUG_TYPE_EQUIVALENCE
26304 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26305#endif
26306
26307 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26308 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26309 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26310
26311 if (X_pointerType != NULL || Y_pointerType != NULL)
26312 {
26313#if 0
26314 if (X_pointerType != NULL)
26315 {
26316 X_element_type = X_pointerType->get_base_type();
26317
26318 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26319 // isReduceable = true;
26320 isReduceable = false;
26321 }
26322
26323 if (Y_pointerType != NULL)
26324 {
26325 Y_element_type = Y_pointerType->get_base_type();
26326
26327 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26328 // isReduceable = true;
26329 isReduceable = false;
26330 }
26331
26332 if (isReduceable == true)
26333 {
26334 // Recursive call on non-default modifier base types.
26335 // isSame = (*X_element_type) == (*Y_element_type);
26336 isSame = isEquivalentType(X_element_type,Y_element_type);
26337 }
26338 else
26339 {
26340 // Neither of these types were reducable.
26341 isSame = false;
26342 }
26343#else
26344 isSame = false;
26345#endif
26346 }
26347 else
26348 {
26349 // Recursive call on non-typedef base types.
26350 // isSame = (*X_element_type) == (*Y_element_type);
26351 // isSame = isEquivalentType(X_element_type,Y_element_type);
26352
26353#if DEBUG_TYPE_EQUIVALENCE
26354 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26355#endif
26356
26357 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26358 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26359 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26360
26361 if (X_arrayType != NULL || Y_arrayType != NULL)
26362 {
26363#if 0
26364 if (X_arrayType != NULL)
26365 {
26366 X_element_type = X_arrayType->get_base_type();
26367
26368 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26369 // isReduceable = true;
26370 isReduceable = false;
26371 }
26372
26373 if (Y_arrayType != NULL)
26374 {
26375 Y_element_type = Y_arrayType->get_base_type();
26376
26377 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26378 // isReduceable = true;
26379 isReduceable = false;
26380 }
26381
26382 if (isReduceable == true)
26383 {
26384 // Recursive call on non-default modifier base types.
26385 // isSame = (*X_element_type) == (*Y_element_type);
26386 isSame = isEquivalentType(X_element_type,Y_element_type);
26387 }
26388 else
26389 {
26390 // Neither of these types were reducable.
26391 isSame = false;
26392 }
26393#else
26394 isSame = false;
26395#endif
26396 }
26397 else
26398 {
26399 // Recursive call on non-typedef base types.
26400 // isSame = (*X_element_type) == (*Y_element_type);
26401 // isSame = isEquivalentType(X_element_type,Y_element_type);
26402
26403#if DEBUG_TYPE_EQUIVALENCE
26404 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26405#endif
26406
26407 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26408 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26409 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26410
26411 if (X_functionType != NULL || Y_functionType != NULL)
26412 {
26413 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26414 //TODO: Liao, 9/15/2016, better comparison of function types
26415 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26416#if DEBUG_TYPE_EQUIVALENCE || 0
26417 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26418#endif
26419 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26420 // isSame == value;
26421 isSame = value;
26422
26423 // DQ (3/20/2016): This is reported by GNU as set but not used.
26424 // isReduceable = false;
26425 }
26426 else
26427 {
26428 // Recursive call on non-typedef base types.
26429 // isSame = isEquivalentType(X_element_type,Y_element_type);
26430
26431 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26432 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26433 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26434
26435 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26436 {
26437 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26438 printf ("This should be unreachable code \n");
26439 ROSE_ABORT();
26440
26441#if 0 // [Robb Matzke 2021-03-24]: unreachable
26442 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26443#if DEBUG_TYPE_EQUIVALENCE || 0
26444 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26445#endif
26446 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26447 // isSame == value;
26448 isSame = value;
26449#endif
26450 }
26451 else
26452 {
26453 // Recursive call on non-typedef base types.
26454 // isSame = isEquivalentType(X_element_type,Y_element_type);
26455#if 0
26456 // Check for irreducable types.
26457 bool X_isReduceable = true;
26458 if (isSgTypeSignedLong(X_element_type) != NULL ||
26459 isSgTypeUnsignedInt(X_element_type) != NULL ||
26460 isSgTypeBool(X_element_type) != NULL ||
26461 isSgTypeInt(X_element_type) != NULL)
26462 {
26463 X_isReduceable = false;
26464 }
26465
26466 bool Y_isReduceable = true;
26467 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26468 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26469 isSgTypeBool(Y_element_type) != NULL ||
26470 isSgTypeInt(Y_element_type) != NULL)
26471 {
26472 Y_isReduceable = false;
26473 }
26474#if DEBUG_TYPE_EQUIVALENCE || 0
26475 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26476 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26477#endif
26478 if (X_isReduceable == true || Y_isReduceable == true)
26479 {
26480 // Recursive call on non-default modifier base types.
26481 isSame = isEquivalentType(X_element_type,Y_element_type);
26482 }
26483 else
26484 {
26485 // Neither of these types were reducable.
26486 isSame = false;
26487 }
26488#else
26489 // DQ (12/20/2015): This is the default case for irreducable types.
26490 if (X_element_type->variantT() == Y_element_type->variantT())
26491 {
26492#if DEBUG_TYPE_EQUIVALENCE || 0
26493 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26494 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26495#endif
26496 // DQ (5/26/2016): It is not good enough that the variants match.
26497 // isSame = true;
26498 // isSame = isEquivalentType(X_element_type,Y_element_type);
26499 isSame = (X_element_type == Y_element_type);
26500 }
26501 else
26502 {
26503 // Neither of these types were reducable or equal.
26504 isSame = false;
26505 }
26506#endif
26507 }
26508 }
26509 }
26510 }
26511 }
26512 }
26513 }
26514 }
26515
26516 // Decrement the static variable to control the recursive depth while we debug this.
26517 counter--;
26518
26519#if DEBUG_TYPE_EQUIVALENCE || 0
26520 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26521#endif
26522
26523#if DEBUG_TYPE_EQUIVALENCE || 0
26524 if (counter == 1 && isSame == true)
26525 {
26526 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());
26527
26528 // Debugging output.
26529 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26530 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26531
26532 // Debugging output.
26533 printf (" --- Output of type chain for lhs: \n");
26534 for (size_t i = 0; i < X_typeChain.size(); i++)
26535 {
26536 SgType* element_type = X_typeChain[i];
26537 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26538 SgModifierType* modifierType = isSgModifierType(element_type);
26539 if (modifierType != NULL)
26540 {
26541 // modifierType->get_typeModifier().display("X type chain");
26542 string s = modifierType->get_typeModifier().displayString();
26543 printf (" --- type chain modifier: %s \n",s.c_str());
26544 }
26545 }
26546
26547 printf (" --- Output of type chain for rhs: \n");
26548 for (size_t i = 0; i < Y_typeChain.size(); i++)
26549 {
26550 SgType* element_type = Y_typeChain[i];
26551 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26552 SgModifierType* modifierType = isSgModifierType(element_type);
26553 if (modifierType != NULL)
26554 {
26555 // modifierType->get_typeModifier().display("Y type chain");
26556 string s = modifierType->get_typeModifier().displayString();
26557 printf (" --- --- type chain modifier: %s \n",s.c_str());
26558 }
26559 }
26560 }
26561#endif
26562
26563#if 0
26564 if (counter == 0)
26565 {
26566 if (isSame == true)
26567 {
26568 // 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());
26569 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26570 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26571 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26572 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26573 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26574 }
26575 else
26576 {
26577 // 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());
26578 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26579 }
26580 }
26581 else
26582 {
26583 printf (" --- counter = %d \n",counter);
26584 }
26585#endif
26586
26587 return isSame;
26588 }
26589
26590
26591#if 0
26592// This is modified to be a template function and so must be moved to the header file.
26593// DQ (8/30/2016): Added function to detect EDG AST normalization.
26594bool
26595SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26596 {
26597 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26598 // function template instnatiations (which come from normalized template functions and member functions).
26599
26600 bool retval = false;
26601
26602#if 1
26603 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26604 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26605 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26606 // But we still need to look at if the location of the parent template is something that we wnat to output.
26607 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26608 // it is not compiler generated.
26609 retval = function->get_marked_as_edg_normalization();
26610#else
26611 // Test for this to be a template instantation (in which case it was marked as
26612 // compiler generated but we may want to allow it to be used in the call graph,
26613 // if it's template was a part was defined in the current directory).
26614 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26615 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26616
26617 if (templateInstantiationFunction != NULL)
26618 {
26619 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26620 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26621 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26622 if (templateFunctionDeclaration != NULL)
26623 {
26624 // retval = operator()(templateFunctionDeclaration);
26625 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26626 }
26627 else
26628 {
26629 // Assume false.
26630 }
26631
26632#if DEBUG_SELECTOR
26633 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26634#endif
26635 }
26636 else
26637 {
26638 if (templateInstantiationMemberFunction != NULL)
26639 {
26640 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26641 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26642 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26643 if (templateMemberFunctionDeclaration != NULL)
26644 {
26645 // retval = operator()(templateMemberFunctionDeclaration);
26646 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26647 }
26648 else
26649 {
26650 // Assume false.
26651 }
26652
26653#if DEBUG_SELECTOR
26654 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26655#endif
26656 }
26657 }
26658#endif
26659
26660 return retval;
26661 }
26662#endif
26663
26664void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26665#if 0
26666 printf("In detectCycleInType():\n");
26667 printf(" -- from = %s\n", from.c_str());
26668 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26669#endif
26670 std::vector<SgType *> seen_types;
26671
26672 while (type != NULL) {
26673
26674 // DQ (4/15/2019): Added assertion.
26675 ROSE_ASSERT(type != NULL);
26676
26677 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26678 if (it != seen_types.end()) {
26679 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26680 size_t i = 0;
26681 for (; it != seen_types.end(); it++) {
26682 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26683 i++;
26684 }
26685 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26686 ROSE_ABORT();
26687 }
26688 seen_types.push_back(type);
26689
26690 SgModifierType * modType = isSgModifierType(type);
26691 SgPointerType * pointType = isSgPointerType(type);
26692 SgReferenceType * refType = isSgReferenceType(type);
26693 SgArrayType * arrayType = isSgArrayType(type);
26694 SgTypedefType * typedefType = isSgTypedefType(type);
26695
26696#if 0
26697 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26698 if (isSgPointerMemberType(type) != NULL)
26699 {
26700 pointType = NULL;
26701 }
26702#endif
26703
26704 if ( modType ) {
26705 type = modType->get_base_type();
26706 } else if ( refType ) {
26707 type = refType->get_base_type();
26708 } else if ( pointType ) {
26709 type = pointType->get_base_type();
26710 // } else if ( pointerMemberType ) {
26711 // type = pointerMemberType->get_base_type();
26712 } else if ( arrayType ) {
26713 type = arrayType->get_base_type();
26714 } else if ( typedefType ) {
26715 type = typedefType->get_base_type();
26716 } else {
26717 break;
26718 }
26719 ROSE_ASSERT(type != NULL);
26720 }
26721}
26722
26723
26724#if 0
26725// DQ (11/10/2019): Older original version of the function.
26726
26727// DQ (6/6/2019): Move this to the SageInteface namespace.
26728void
26730 {
26731 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26732 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26733 // declarations in the outlined code we can support the outpiled code with those references. This
26734 // approach has the added advantage of also supporting the same include file tree as the original
26735 // file where the outlined code is being taken from.
26736
26737 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26738 {
26739 public:
26740 std::vector<SgFunctionDeclaration*> functionList;
26741 SgSourceFile* sourceFile;
26742 int sourceFileId;
26743 string filenameWithPath;
26744
26745 public:
26746 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26747
26748 void visit (SgNode* node)
26749 {
26750#if 0
26751 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26752#endif
26753 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26754 if (temp_sourceFile != NULL)
26755 {
26756 sourceFile = temp_sourceFile;
26757 sourceFileId = sourceFile->get_file_info()->get_file_id();
26758
26759 // The file_id is not sufficnet, not clear why, but the filenames match.
26760 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26761
26762 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26763
26764 }
26765
26766 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26767 if (functionDeclaration != NULL)
26768 {
26769 // This should have been set already.
26770 ROSE_ASSERT(sourceFile != NULL);
26771
26772 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
26773 if (functionDeclaration == definingFunctionDeclaration)
26774 {
26775#if 1
26776 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
26777 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26778
26779 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26780 printf (" --- source file: file_info: id = %d name = %s \n",
26781 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
26782#endif
26783 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
26784 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
26785 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
26786#if 1
26787 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
26788#endif
26789 // Remove the defining declaration as a test.
26790 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
26791 if (isInSourceFile == true && functionDeclarationScope != NULL)
26792 {
26793#if 1
26794 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
26795 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
26796#endif
26797 // functionDeclarationScope->removeStatement(functionDeclaration);
26798 // removeStatement(functionDeclaration);
26799 functionList.push_back(functionDeclaration);
26800 }
26801 }
26802 }
26803 }
26804 };
26805
26806 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
26807 TransformFunctionDefinitionsTraversal traversal;
26808 traversal.traverse(node, preorder);
26809
26810 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
26811
26812#if 1
26813 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
26814#endif
26815
26816 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
26817 while (i != functionList.end())
26818 {
26819 SgFunctionDeclaration* functionDeclaration = *i;
26820 ROSE_ASSERT(functionDeclaration != NULL);
26821
26822 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
26823 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
26824
26825#if 1
26826 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
26827 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26828#endif
26829 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
26830 // removeStatement(functionDeclaration);
26831 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
26832
26833 i++;
26834 }
26835
26836#if 0
26837 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
26838 ROSE_ABORT();
26839#endif
26840 }
26841#endif
26842
26843
26844void
26846 {
26847 // DQ (10/31/2020): Display function for scopes (useful for debugging).
26848 ROSE_ASSERT(scope != NULL);
26849
26850 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
26851
26852 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
26853 SgStatementPtrList statementList = scope->generateStatementList();
26854 for (size_t i = 0; i < statementList.size(); i++)
26855 {
26856 SgStatement* statement = statementList[i];
26857 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
26858 }
26859
26860#if 0
26861 printf ("Exiting as a test at the end of evaluation of global scope! \n");
26862 ROSE_ABORT();
26863#endif
26864 }
26865
26866
26869 {
26870 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
26871 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
26872
26873#if 0
26874 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
26875 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
26876#endif
26877
26878 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
26879 bool isConstructor = false;
26880 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
26881 if (tmp_memberFunctionDeclaration != NULL)
26882 {
26883 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
26884
26885#if 0
26886 if (isConstructor == true)
26887 {
26888 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
26889 return;
26890 }
26891#endif
26892 }
26893
26894 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
26895 // bool replaceWithEmptyDeclaration = false;
26896 // SgDeclarationStatement* emptyDeclaration = NULL;
26897
26898 SgName name = functionDeclaration->get_name();
26899 SgType* return_type = functionDeclaration->get_type()->get_return_type();
26900
26901#if 0
26902 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
26903 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
26904 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
26905 // this function that builds the function prototype from the defining function.
26906
26907 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
26908 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
26909 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
26910
26911 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
26912 // are specified in the function declarations, and make sure the prototype reproduces them.
26913 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
26914 {
26915 SgInitializedName* arg = functionDeclaration->get_args()[i];
26916#if 1
26917 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
26918 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
26919 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
26920#endif
26921 if (arg->get_file_info()->isDefaultArgument() == true)
26922 {
26923 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
26924 }
26925 }
26926#endif
26927
26928#if 1
26929 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26930#else
26931 // 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).
26932 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
26933 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
26934 SgFunctionParameterList* param_list = NULL;
26935
26936 if (templateInstantiationFunctionDecl == NULL)
26937 {
26938 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26939 }
26940 else
26941 {
26942 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
26943 if (templateInstantiationMemberFunctionDecl == NULL)
26944 {
26945 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
26946 }
26947 }
26948#endif
26949
26950
26951 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
26952 bool isTemplateInstantiationMemberFunctionDecl = false;
26953
26954 SgScopeStatement* scope = functionDeclaration->get_scope();
26955 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
26956 SgExprListExp* python_decoratorList = NULL;
26957 bool buildTemplateInstantiation = false;
26958 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
26959
26960 // DQ (9/26/2019): Tracing down a null parent pointer.
26961 // ROSE_ASSERT(param_list->get_parent() != NULL);
26962 // ROSE_ASSERT(param_list->get_parent() == NULL);
26963 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
26964
26965 switch (functionDeclaration->variantT())
26966 {
26967 case V_SgTemplateMemberFunctionDeclaration:
26968 {
26969#if 0
26970 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
26971#endif
26972 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
26973 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
26974
26975 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
26976
26977 unsigned int functionConstVolatileFlags = 0;
26978
26979 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
26980
26981 // Need to call:
26982 // unsigned int get_mfunc_specifier();
26983
26984 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
26985 ROSE_ASSERT(memberFunctionType != NULL);
26986
26987 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
26988
26989 // SgTemplateMemberFunctionDeclaration*
26990 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
26991 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
26992
26993 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
26994 // ROSE_ASSERT(templateParameterList != NULL);
26995
26996 templateMemberFunctionDeclaration =
26997 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
26998#if 0
26999 printf ("ERROR: Template functions are not yet supported! \n");
27000 ROSE_ABORT();
27001#endif
27002 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
27003
27004 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27005
27006 // DQ (11/21/2019): Handle constructors.
27007 if (isConstructor == true)
27008 {
27009 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27010 }
27011
27012 break;
27013 }
27014
27015 case V_SgTemplateFunctionDeclaration:
27016 {
27017#if 0
27018 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
27019#endif
27020 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
27021 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
27022
27023 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
27024
27025 // SgTemplateFunctionDeclaration*
27026 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27027 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
27028
27029 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
27030
27031 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
27032#if 0
27033 printf ("ERROR: Template functions are not yet supported! \n");
27034 ROSE_ABORT();
27035#endif
27036 nondefiningFunctionDeclaration = templateFunctionDeclaration;
27037
27038 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27039
27040 break;
27041 }
27042
27043 // DQ (10/29/2020): Added new case.
27044 case V_SgTemplateInstantiationMemberFunctionDecl:
27045 {
27046 buildTemplateInstantiation = true;
27047
27048 isTemplateInstantiationMemberFunctionDecl = true;
27049
27050 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27051 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
27052 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
27053#if 0
27054 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27055 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
27056 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
27057 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
27058 if (templateDeclaration != NULL)
27059 {
27060 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27061 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27062 }
27063#endif
27064 // name = functionDeclaration->get_name();
27065 // name = templateInstantiationMemberFunctionDecl->get_template_name();
27066 name = templateInstantiationMemberFunctionDecl->get_templateName();
27067#if 0
27068 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
27069#endif
27070 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
27071 }
27072 // fall through
27073 case V_SgMemberFunctionDeclaration:
27074 {
27075#if 0
27076 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
27077#endif
27078 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27079 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
27080
27081 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
27082
27083 // SgMemberFunctionDeclaration*
27084 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27085 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
27086
27087 unsigned int functionConstVolatileFlags = 0;
27088
27089 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
27090
27091 // Need to call:
27092 // unsigned int get_mfunc_specifier();
27093
27094 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
27095 // since they is not allowed to be declared outside of the class they are a member of.
27096
27097 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
27098 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
27099#if 0
27100 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
27101#endif
27102 if (buildPrototype == true)
27103 {
27104 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
27105 ROSE_ASSERT(memberFunctionType != NULL);
27106#if 0
27107 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
27108#endif
27109 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27110
27111 memberFunctionDeclaration =
27113 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
27114 buildTemplateInstantiation,templateArgumentsList );
27115#if 0
27116 printf ("ERROR: Member functions are not yet supported! \n");
27117 ROSE_ABORT();
27118#endif
27119 // DQ (11/21/2019): Handle constructors.
27120 if (isConstructor == true)
27121 {
27122 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27123 }
27124
27125 nondefiningFunctionDeclaration = memberFunctionDeclaration;
27126
27127 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27128 }
27129 else
27130 {
27131 // Case of member function defined outside of it's class.
27132#if 0
27133 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
27134#endif
27135 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
27136 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
27137 nondefiningFunctionDeclaration = NULL;
27138#if 0
27139 nondefiningFunctionDeclaration = NULL;
27140
27141 replaceWithEmptyDeclaration = true;
27142 emptyDeclaration = buildEmptyDeclaration();
27143 ROSE_ASSERT(emptyDeclaration != NULL);
27144#endif
27145 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27146 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27147
27148 // Since we din't build a member function we don't need the parameter list.
27149 delete param_list;
27150 param_list = NULL;
27151#if 0
27152 printf ("Exiting as a test! \n");
27153 ROSE_ABORT();
27154#endif
27155 }
27156
27157 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27158 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27159 break;
27160 }
27161
27162 case V_SgFunctionDeclaration:
27163 {
27164 // This is for a non-member non-template function declaration.
27165 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27166 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27167 break;
27168 }
27169
27170 // DQ (10/29/2020): Added new case.
27171 case V_SgTemplateInstantiationFunctionDecl:
27172 {
27173 // This is for a non-member non-template function declaration.
27174 buildTemplateInstantiation = true;
27175 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27176 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
27177 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
27178#if 0
27179 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27180 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
27181 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
27182 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
27183 if (templateDeclaration != NULL)
27184 {
27185 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27186 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27187 }
27188#endif
27189 name = templateInstantiationFunctionDecl->get_templateName();
27190#if 0
27191 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
27192#endif
27193 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27194 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27195 break;
27196 }
27197
27198 default:
27199 {
27200 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
27201 // These cases would be only template instantiations.
27202
27203 // Nothing to do, except delete the parameter list we built, and return.
27204 delete param_list;
27205 param_list = NULL;
27206
27207 return NULL;
27208 }
27209 }
27210
27211 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
27212 // DQ (9/26/2019): Tracing down a null parent pointer.
27213 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
27214 // ROSE_ASSERT(param_list != NULL);
27215 // ROSE_ASSERT(param_list->get_parent() != NULL);
27216
27217 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27218
27219 if (nondefiningFunctionDeclaration != NULL)
27220 {
27221 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27222 {
27223#if 0
27224 printf ("Setting the firstNondefiningDeclaration \n");
27225#endif
27226 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27227 }
27228
27229 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27230 {
27231#if 0
27232 printf ("Setting the definingDeclaration \n");
27233#endif
27234 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27235 }
27236
27237 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27238 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27239
27240 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27241 if (nondefiningFunctionDeclaration != NULL)
27242 {
27243 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27244 // This is a bug in the support for building a new prototype from a defining function declaration
27245 // and caused this problem. This assertion will prevent this sort of error from happening again.
27246 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27247 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27248 }
27249 }
27250
27251 return nondefiningFunctionDeclaration;
27252 }
27253
27254
27255// 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).
27258 {
27259 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27260 ROSE_ASSERT(functionDeclaration != NULL);
27261
27262#if 0
27263 printf ("****************************************************************** \n");
27264 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27265 SageInterface::printOutComments (functionDeclaration);
27266 printf ("****************************************************************** \n");
27267#endif
27268
27269 // 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.
27270
27271 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27272
27273 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27274 if (nondefiningFunctionDeclaration != NULL)
27275 {
27276 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27277 // This is a bug in the support for building a new prototype from a defining function declaration
27278 // and caused this problem. This assertion will prevent this sort of error from happening again.
27279 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27280 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27281 }
27282
27283 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27284
27285 if (templateInstantiationFunctionDecl == NULL)
27286 {
27287 if (nondefiningFunctionDeclaration != NULL)
27288 {
27289 // DQ (10/29/2020): Match the associated declaration modifiers.
27290 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27291
27292 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27293 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27294 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27295
27296 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27297 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27298
27299 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27300
27301 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27302 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27303 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27304
27305 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27306 // removeStatement(functionDeclaration);
27307 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27308 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27309 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27310 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27311 // DQ (11/15/2020): Note that the default is false, and we need true.
27312 bool movePreprocessingInfo = true;
27313 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27314
27315 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27316 // 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.
27317 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27318 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27319 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27320 }
27321 }
27322 else
27323 {
27324 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27325 nondefiningFunctionDeclaration = NULL;
27326 }
27327
27328 // Check that static declaration is preserved.
27329 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27330 {
27331 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27332 }
27333
27334 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27335 return nondefiningFunctionDeclaration;
27336 }
27337
27338
27339std::vector<SgFunctionDeclaration*>
27341 {
27342 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27343 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27344 // declarations in the outlined code we can support the outpiled code with those references. This
27345 // approach has the added advantage of also supporting the same include file tree as the original
27346 // file where the outlined code is being taken from.
27347
27348 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27349 {
27350 public:
27351 std::vector<SgFunctionDeclaration*> functionList;
27352 FunctionDefinitionsTraversal() {}
27353
27354 void visit (SgNode* node)
27355 {
27356 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27357 if (functionDeclaration != NULL)
27358 {
27359 // This should have been set already.
27360 // ROSE_ASSERT(sourceFile != NULL);
27361
27362 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27363 if (functionDeclaration == definingFunctionDeclaration)
27364 {
27365 // Remove the defining declaration as a test.
27366 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27367 if (functionDeclarationScope != NULL)
27368 {
27369 functionList.push_back(functionDeclaration);
27370 }
27371 }
27372 }
27373 }
27374 };
27375
27376 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27377 FunctionDefinitionsTraversal traversal;
27378
27379 traversal.traverseWithinFile(node, preorder);
27380
27381 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27382
27383 return functionList;
27384 }
27385
27386
27387void
27389 {
27390 ROSE_ASSERT(node != NULL);
27391
27392 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27393 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27394
27395 while (i != functionList.end())
27396 {
27397 SgFunctionDeclaration* functionDeclaration = *i;
27398 ROSE_ASSERT(functionDeclaration != NULL);
27399 // Transform into prototype.
27401 i++;
27402 }
27403 }
27404
27405
27406
27407// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27408void
27410 {
27411 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27412 // support for variable declarations initialized using lambda functions is that the initalizer
27413 // is discarded at some point in the processing of the AST. This function reports on all
27414 // variable declarations and if they contain initializers and if so what kind of initializer.
27415
27416 ROSE_ASSERT(node != nullptr);
27417
27418 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27419 class CheckInitializerTraversal : public AstSimpleProcessing
27420 {
27421 public:
27422 void visit (SgNode* node)
27423 {
27424 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27425 if (variableDeclaration != NULL)
27426 {
27427 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27428 SgExpression* initializer = initializedName->get_initializer();
27429
27430 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27431 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27432
27433 if (initializer != NULL)
27434 {
27435 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27436 }
27437 }
27438 }
27439 };
27440
27441 // Now buid the traveral object and call the traversal (preorder) on the project.
27442 CheckInitializerTraversal traversal;
27443 traversal.traverse(node, preorder);
27444 }
27445
27446namespace
27447{
27448 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27449 {
27450 void setResult(SgNamedType* ty) { res = ty; }
27451 void setResult(SgType*) { /* not a named type */ }
27452
27453 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27454
27455 template <class SageDeclarationStatement>
27456 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27457 {
27458 // SgDeclarationStatement::get_type is not a virtual function
27459 // => find overloaders returning SgNamedType in subclasses
27460 // by using the full type (SageDeclarationStatement).
27461 setResult(n.get_type());
27462 }
27463
27464 template <class SageNode>
27465 void handle(SageNode& n)
27466 {
27467 handle(n, n);
27468 }
27469 };
27470}
27471
27473{
27474 return sg::dispatch(DeclaredType{}, declaration);
27475}
27476
27478 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27479 ROSE_ASSERT(gsaf != nullptr);
27480 SgSymbolTable * st = gsaf->get_symbol_table();
27481 ROSE_ASSERT(st != nullptr);
27482 rose_hash_multimap * hmm = st->get_table();
27483 ROSE_ASSERT(hmm != nullptr);
27484 hmm->clear();
27485
27486 st = SgNode::get_globalTypeTable()->get_type_table();
27487 ROSE_ASSERT(st != nullptr);
27488 hmm = st->get_table();
27489 ROSE_ASSERT(hmm != nullptr);
27490 hmm->clear();
27491
27493 ROSE_ASSERT(st != nullptr);
27494 hmm = st->get_table();
27495 ROSE_ASSERT(hmm != nullptr);
27496 hmm->clear();
27497}
27498
27500/*
27501
27502By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27503
27504--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27505 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27506 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27507 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27508
27509
27510TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27511
27512 * */
27513int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27514{
27515 int match_count = 0;
27516 ROSE_ASSERT (root);
27517
27518 // find all SgArrowExp, then try to match the expected pattern
27519 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27520 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27521
27522 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27523 // So we need to make sure the same subtree is only processed once
27524 boost::unordered::unordered_map <SgNode*, bool> visited;
27525
27526 // reverse iterator is safer to use than forward iterator to support translation
27527 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27528 {
27529 // skip a node if it is previously processed.
27530 if (visited.count(*i)==1)
27531 continue;
27532
27533 visited[*i]=true;
27534
27535 SgArrowExp* a_exp = isSgArrowExp(*i);
27536
27537 if (!a_exp)
27538 {
27539 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27540 ROSE_ASSERT (a_exp);
27541 }
27542
27543 if (transformationGeneratedOnly)
27544 {
27545 if (!(a_exp->get_file_info()->isTransformation()))
27546 continue;
27547 }
27548
27549 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27550 {
27551 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27552 {
27553 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27554 {
27555 // do the transformation: copy two operands, making a dot exp instead
27556 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27557 replaceExpression (a_exp, dot_exp);
27558 match_count++;
27559 }
27560 }
27561 }
27562 } // end for
27563
27564 return match_count;
27565}
27566
27567bool
27569 {
27570 class Traversal : public AstSimpleProcessing
27571 {
27572 public:
27573 bool found;
27574 Traversal() : found(false) {}
27575 void visit (SgNode* node)
27576 {
27577 SgCastExp* castExpression = isSgCastExp(node);
27578 if (castExpression != NULL)
27579 {
27580 // SgNode* parent = castExpression->get_parent();
27581 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27582 if (initializer == NULL)
27583 {
27584 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27585 if (castExpression->get_file_info()->isTransformation() == true)
27586 {
27587 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27588 found = true;
27589#if 0
27590 printf ("Exiting as a test! \n");
27591 ROSE_ASSERT(false);
27592#endif
27593 }
27594 else
27595 {
27596#if 0
27597 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27598#endif
27599 }
27600 }
27601 else
27602 {
27603 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27604#if 1
27605 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27606#endif
27607 }
27608 }
27609 else
27610 {
27611#if 0
27612 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27613#endif
27614 }
27615 }
27616 };
27617
27618#if 1
27619 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27620#endif
27621
27622 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27623 Traversal traversal;
27624 traversal.traverse(n, preorder);
27625
27626#if 1
27627 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27628#endif
27629#if 0
27630 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27631 if (traversal.found == true)
27632 {
27633 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27634 }
27635
27636 return false;
27637#else
27638 return traversal.found;
27639#endif
27640 }
27641
27642// A helper function to check
27643// begin: return 1
27644// middle (#else, #elif): return 2
27645// end directive: return -1
27646// othewise return 0;
27647static int isBeginDirective (PreprocessingInfo* info)
27648{
27649 ROSE_ASSERT (info != NULL);
27650 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27651 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27652 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27653 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27654 {
27655 return 1;
27656 }
27657 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27658 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27659 {
27660 return 2;
27661 }
27662 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27663 {
27664 return -1;
27665 }
27666
27667 return 0;
27668}
27669
27670// a helper function to move things, the associated directive in the middle
27671static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27672{
27673// AttachedPreprocessingInfoType* infoList = (*ki).first;
27674// int cidx= (*ki).second;
27675
27676 relatedInfoList.insert (infoList);
27677
27678 PreprocessingInfo* info = (*infoList)[cidx];
27679 // rewrite relative position
27680 info->setRelativePosition(PreprocessingInfo::after);
27681
27682 // insert after lnode
27683 lnode->addToAttachedPreprocessingInfo (info);
27684 retVal++;
27685
27686 // zero out from original list
27687 (*infoList)[cidx]= NULL;
27688}
27689
27690// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27692{
27693 int retVal=0;
27694 ROSE_ASSERT(lnode);
27695
27696 // collecting NULL entries
27697 RoseAst ast(lnode);
27698 RoseAst::iterator ast_i=ast.begin();
27699
27700 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27701 for(;ast_i!=ast.end();++ast_i) {
27702 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27703 if (current ==NULL ) // skip non located nodes
27704 continue;
27705
27706 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27707 if (infoList == NULL) continue;
27708
27709 int commentIndex=0;
27710 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27711 {
27712 // fundamentally, we want to move individual PreprocessingInfo objects
27713 // Or just duplicate them (easier)
27714 PreprocessingInfo * info = *ci;
27715 if (info==NULL)
27716 empty_entries.push_back( make_pair (infoList, commentIndex) );
27717 commentIndex++;
27718 }
27719 }
27720
27721 // using reverse iterator to remove from backwards
27722 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27723 {
27724 AttachedPreprocessingInfoType* infoList = (*ki).first;
27725 int cidx= (*ki).second;
27726
27727 PreprocessingInfo* info = (*infoList)[cidx];
27728 ROSE_ASSERT (info==NULL);
27729
27730 // erase start+offset
27731 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27732 infoList->erase(k+cidx);
27733// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27734 retVal ++;
27735 }
27736 return retVal;
27737}
27738
27739//TODO: expose this to header file?
27740// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27741// Should this be maintained by librose or user space code?
27742static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27743
27744void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27745{
27746 // stop condition
27747 if (current == NULL)
27748 return;
27749
27750 // Three possible locations: before, inside, and after
27751 // immediately add prepression info that is before and inside of current node
27752 // delayed additions of these that are located after the current node
27753 vector<PreprocessingInfo*> afterList;
27754 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27755 {
27756 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27757
27758 if (comments != nullptr)
27759 {
27760 AttachedPreprocessingInfoType::iterator i;
27761 int idx=0;
27762 for (i = comments->begin (); i != comments->end (); i++)
27763 {
27764 PreprocessingInfo* info= *i;
27765
27766 // prepare the data just in case
27768 data.container=comments;
27769 data.index = idx;
27770 data.depth = depth;
27771
27772 // put directives with before or inside location into the infoList
27773 if (info->getRelativePosition () == PreprocessingInfo::before||
27774 info->getRelativePosition () == PreprocessingInfo::inside)
27775 {
27776 infoList.push_back (info);
27777 infoMap[info] = data;
27778 }
27779 else if (info->getRelativePosition () == PreprocessingInfo::after)
27780 {
27781 afterList.push_back (info); // if attached to be after, save to afterList
27782 infoMap[info] = data;
27783 }
27784 else
27785 {
27786 cerr<<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
27787 // ROSE_ASSERT (false); // Jovial has end_of
27788 }
27789
27790 idx++;
27791 } // end for
27792 }
27793 } // end if
27794
27795 // handling children nodes
27796 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
27797 for (auto c: children)
27798 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
27799
27800 // append after locations after recursively handling children nodes.
27801 for (auto fi : afterList)
27802 infoList.push_back(fi);
27803}
27804
27805// This may be expensive to run since it is called anytime replace() is called.
27807// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
27808// This should be done before removing or replace the statement: lnode
27809// TODO: this may need to be a recursive function for multiple levels of nested directives.
27810//
27811// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
27812//
27814{
27815 int retVal=0;
27816 ROSE_ASSERT(lnode);
27817
27818// algorithm: using a queue (vector to simulate it)
27819// queue <PreProcessingInfo* > q;
27820// start from 2nd node: ignore the first root node
27821// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
27822// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
27823//
27824// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
27825// They cannot neutralize each other.
27826// They should be attached to be after lnode !
27827 RoseAst ast(lnode);
27828 RoseAst::iterator ast_i=ast.begin();
27829 ++ast_i; // skip the root node itself
27830
27831 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
27832 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
27833 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
27834 // it is not always an independent decision.
27835 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
27836 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
27837
27838 // store the associated middle directives what should be erased in the end
27839 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
27840 // associated_directives[BeginInfo] will not retrieve them!
27841 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
27842
27843 // Two steps here
27844 // Step 1: We build the list first, then go through them to neutralize them
27845 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
27846 //
27847 // The list must provide the following information
27848 // infoList (container), index of the directive, PreprocessingInfo* itself
27849 vector<PreprocessingInfo*> candidateInfoList;
27850 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
27851 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
27852 // now we have both candidateInfoList and infoMap.
27853
27854 for (auto candidate: candidateInfoList)
27855 {
27856 // fundamentally, we want to move individual PreprocessingInfo objects
27857 // Or just duplicate them (easier)
27858 PreprocessingInfo * info = candidate;
27859
27860 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
27861 if (infoMap[info].depth ==0)
27862 continue;
27863
27864 int commentIndex = infoMap[info].index;
27865 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
27866
27867 // begin directives
27868 if ( isBeginDirective(info) == 1)
27869 {
27870 keepers.push_back(make_pair (infoList,commentIndex));
27871 }
27872 // the middle #else, #elif,
27873 else if (isBeginDirective(info) == 2)
27874 {
27875 // two situtations for immediate decision of unbalanced status
27876 //1. empty stack, or
27877 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27878 if (keepers.size()==0)
27879 keepers.push_back(make_pair (infoList, commentIndex));
27880 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27881 {
27882 keepers.push_back(make_pair (infoList,commentIndex));
27883 }
27884 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27885 {
27886 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27887 // we associated this middle directive with the beginning directive
27888 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27889 }
27890 }
27891 // end directive
27892 else if ( isBeginDirective(info) == -1)
27893 {
27894 bool neutralized = false;
27895 // neutralize an internall matched pair, if any
27896 if (keepers.size()>0)
27897 {
27898 AttachedPreprocessingInfoType* comments = keepers.back().first;
27899 int idx = keepers.back().second;
27900
27901 if(isBeginDirective( (*comments)[idx] )==1)
27902 {
27903 keepers.pop_back();
27904 neutralized = true;
27905 }
27906 }
27907
27908 if (!neutralized)
27909 keepers.push_back(make_pair (infoList,commentIndex));
27910 }
27911
27912 }
27913
27914#if 0 // old and wrong linear search of directives
27915
27916 // Then we go through the list, extract keepers, neutralize anything else.
27917 for(;ast_i!=ast.end();++ast_i) {
27918 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27919 if (current ==NULL ) // skip non located nodes
27920 continue;
27921
27922 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27923 if (infoList == NULL) continue;
27924
27925 int commentIndex=0;
27926 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27927 {
27928 ROSE_ASSERT(*ci != NULL);
27929 // fundamentally, we want to move individual PreprocessingInfo objects
27930 // Or just duplicate them (easier)
27931 PreprocessingInfo * info = *ci;
27932
27933 // begin directives
27934 if ( isBeginDirective(info) == 1)
27935 {
27936 keepers.push_back(make_pair (infoList,commentIndex));
27937 }
27938 // the middle #else, #elif,
27939 else if (isBeginDirective(info) == 2)
27940 {
27941 // two situtations for immediate decision of unbalanced status
27942 //1. empty stack, or
27943 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
27944 if (keepers.size()==0)
27945 keepers.push_back(make_pair (infoList,commentIndex));
27946 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
27947 {
27948 keepers.push_back(make_pair (infoList,commentIndex));
27949 }
27950 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
27951 {
27952 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
27953 // we associated this middle directive with the beginning directive
27954 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
27955 }
27956 }
27957 // end directive
27958 else if ( isBeginDirective(info) == -1)
27959 {
27960 bool neutralized = false;
27961 // neutralize an internall matched pair, if any
27962 if (keepers.size()>0)
27963 {
27964 AttachedPreprocessingInfoType* comments = keepers.back().first;
27965 int idx = keepers.back().second;
27966
27967 if(isBeginDirective( (*comments)[idx] )==1)
27968 {
27969 keepers.pop_back();
27970 neutralized = true;
27971 }
27972 }
27973
27974 if (!neutralized)
27975 keepers.push_back(make_pair (infoList,commentIndex));
27976 }
27977 commentIndex++;
27978 }
27979 }
27980#endif
27981// TODO this variable is not used in the end.
27982 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
27983 // 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!
27984 // move from old containers, and add into lnode's after position
27985 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
27986 {
27987 AttachedPreprocessingInfoType* infoList = (*ki).first;
27988 int cidx= (*ki).second;
27989 // TODO replace the code block below with moveInofListToNewPlace()
27990 relatedInfoList.insert (infoList);
27991
27992 PreprocessingInfo* info = (*infoList)[cidx];
27993 // rewrite relative position
27994 info->setRelativePosition(PreprocessingInfo::after);
27995
27996 // insert after lnode
27997 lnode->addToAttachedPreprocessingInfo (info);
27998 retVal++;
27999
28000 // we additionally process the associated directives, if any, TODO: reverse processing also??
28001 if (associated_directives.count (info)!=0)
28002 {
28003 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
28004 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
28005 {
28006 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
28007 int aidx= (*vec_i).second;
28008 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
28009 associated_erase.push_back(make_pair (a_infoList, aidx));
28010 }
28011 } // each begin directive may associate multiple other middle directives
28012
28013 // Doing this after the associated directives are processed.
28014 // zero out from original list, Note this element slot is NULL now!
28015 (*infoList)[cidx]= NULL;
28016
28017 }
28019 return retVal;
28020}
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 &x)
Insert data into the digest.
uint64_t make64Bits()
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(void)
Computes the number of nodes in the defined subtree of the AST.
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()
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 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::vector< SgNode * > get_traversalSuccessorContainer()
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
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 std::vector< SgNode * > get_traversalSuccessorContainer() override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
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.
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 num)
Converts a 64 bit in to base 62 (All letters and numbers).
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C:58
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.
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 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 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