ROSE 0.11.145.339
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// We need this so that USE_CMAKE and ROSE_USE_CLANG_FRONTEND will be seen (set via configure).
85#include "rose_config.h"
86
87// DQ (11/5/2019): Added to support SageInterface::statementCanBeTransformed().
88namespace EDG_ROSE_Translation
89 {
90 // DQ (9/18/2018): Declare this map so that we can use it for the unparse header files option.
91#if defined(ROSE_BUILD_CXX_LANGUAGE_SUPPORT) && !defined(ROSE_USE_CLANG_FRONTEND)
92 // DQ (12/11/2018): Use the definition in the EDG edgRose.C file if C/C++ support IS defined.
93 extern std::map<std::string, SgIncludeFile*> edg_include_file_map;
94#else
95 // DQ (12/11/2018): Allow this to be the definition if C/C++ support is NOT defined.
96 std::map<std::string, SgIncludeFile*> edg_include_file_map;
97#endif
98 }
99
100
101
102// DQ (12/1/2015): Added to support macro handling.
103#include "detectMacroOrIncludeFileExpansions.h"
104
105namespace SageInterface {
106 template<class T> void setSourcePositionToDefault( T* node );
107}
108
109
110#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
111 #include "transformationSupport.h"
112#endif
113
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 case V_SgTemplateVariableInstantiation:
1696
1697 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1698 case V_SgVariableDeclaration:
1699 {
1700 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1701 // because we use this mechanism to generate names for unnamed structs and enums).
1702 name = "_variable_declaration_";
1703 const SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(declaration);
1704 ROSE_ASSERT(variableDeclaration != NULL);
1705 SgInitializedNamePtrList::const_iterator i = variableDeclaration->get_variables().begin();
1706
1707 // Make sure that we have at least one variable in the list
1708 ROSE_ASSERT(i != variableDeclaration->get_variables().end());
1709 do {
1710 // name += string(" ") + string((*i)->get_name().str());
1711 name += string((*i)->get_name().str());
1712 i++;
1713 }
1714 while (i != variableDeclaration->get_variables().end());
1715 break;
1716 }
1717
1718
1719 // DQ (3/8/2006): Implemented case for variable declaration (forgot this case)
1720 case V_SgVariableDefinition:
1721 {
1722 // DQ (2/11/2007): Modified to return names that can be used as variables (required
1723 // because we use this mechanism to generate names for unnamed structs and enums).
1724 name = "_variable_definition_";
1725 const SgVariableDefinition* variableDefinition = isSgVariableDefinition(declaration);
1726 ROSE_ASSERT(variableDefinition != NULL);
1727
1728 // define this in terms of the associated SgInitializedName
1729 ROSE_ASSERT(variableDefinition->get_vardefn() != NULL);
1730 name += get_name(variableDefinition->get_vardefn());
1731 break;
1732 }
1733
1734 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
1735 case V_SgPragmaDeclaration:
1736 {
1737 name = "_pragma_declaration_";
1738 const SgPragmaDeclaration* pragmaDeclaration = isSgPragmaDeclaration(declaration);
1739 ROSE_ASSERT(pragmaDeclaration != NULL);
1740 ROSE_ASSERT(pragmaDeclaration->get_pragma() != NULL);
1741 name += get_name(pragmaDeclaration->get_pragma());
1742 break;
1743 }
1744
1745 // DQ (4/15/2007): Implemented case for using directive statement (forgot this case)
1746 case V_SgUsingDirectiveStatement:
1747 {
1748 name = "_using_directive_statement_";
1749 const SgUsingDirectiveStatement* usingDeclaration = isSgUsingDirectiveStatement(declaration);
1750 ROSE_ASSERT(usingDeclaration != NULL);
1751 ROSE_ASSERT(usingDeclaration->get_namespaceDeclaration() != NULL);
1752 name += get_name(usingDeclaration->get_namespaceDeclaration());
1753 break;
1754 }
1755
1756 // DQ (6/20/2007): Added new case!
1757 case V_SgNamespaceAliasDeclarationStatement:
1758 {
1759 name = "_namespace_alias_directive_statement_";
1760 const SgNamespaceAliasDeclarationStatement* namespaceAliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
1761 ROSE_ASSERT(namespaceAliasDeclaration != NULL);
1762 ROSE_ASSERT(namespaceAliasDeclaration->get_name().is_null() == false);
1763 name += namespaceAliasDeclaration->get_name();
1764 break;
1765 }
1766
1767 // DQ (6/20/2007): Added new case!
1768 case V_SgUsingDeclarationStatement:
1769 {
1770 name = "_using_declaration_statement_";
1771 const SgUsingDeclarationStatement* usingDeclaration = isSgUsingDeclarationStatement(declaration);
1772 ROSE_ASSERT(usingDeclaration != NULL);
1773 if (usingDeclaration->get_declaration() != NULL)
1774 {
1775 name += get_name(usingDeclaration->get_declaration());
1776 }
1777 else
1778 {
1779 ROSE_ASSERT(usingDeclaration->get_initializedName() != NULL);
1780 name += get_name(usingDeclaration->get_initializedName());
1781 }
1782 break;
1783 }
1784
1785 // DQ (6/20/2007): Added new case!
1786 case V_SgTemplateInstantiationDirectiveStatement:
1787 {
1788 name = "_template_instantiation_directive_statement_";
1789 ROSE_ASSERT(declaration != NULL);
1790 const SgTemplateInstantiationDirectiveStatement* templateInstantiationDirective = isSgTemplateInstantiationDirectiveStatement(declaration);
1791 ROSE_ASSERT(templateInstantiationDirective != NULL);
1792 ROSE_ASSERT(templateInstantiationDirective->get_declaration() != NULL);
1793#if 0
1794 printf ("declaration->get_declaration() = %p = %s \n",templateInstantiationDirective->get_declaration(),templateInstantiationDirective->get_declaration()->class_name().c_str());
1795#endif
1796 name += get_name(templateInstantiationDirective->get_declaration());
1797 break;
1798 }
1799
1800 case V_SgCtorInitializerList:
1801 {
1802 name = "_ctor_list_";
1803 const SgCtorInitializerList* ctorDeclaration = isSgCtorInitializerList(declaration);
1804 ROSE_ASSERT(ctorDeclaration != NULL);
1805 ROSE_ASSERT(ctorDeclaration->get_parent() != NULL);
1806 name += get_name(ctorDeclaration->get_parent());
1807 break;
1808 }
1809
1810 // DQ (8/9/2007): Added case for SgAsmStmt
1811 case V_SgAsmStmt:
1812 {
1813 name = "_asm_stmt_";
1814 const SgAsmStmt* asmStatement = isSgAsmStmt(declaration);
1815 ROSE_ASSERT(asmStatement != NULL);
1816 ROSE_ASSERT(asmStatement->get_parent() != NULL);
1817 name += StringUtility::numberToString(const_cast<SgAsmStmt*>(asmStatement));
1818 break;
1819 }
1820
1821 // DQ (8/22/2007): Added case for SgImplicitStatement
1822 case V_SgImplicitStatement:
1823 {
1824 name = "_fortran_implicit_";
1825 const SgImplicitStatement* implicitStatement = isSgImplicitStatement(declaration);
1826 ROSE_ASSERT(implicitStatement != NULL);
1827 ROSE_ASSERT(implicitStatement->get_parent() != NULL);
1828 name += StringUtility::numberToString(const_cast<SgImplicitStatement*>(implicitStatement));
1829 break;
1830 }
1831
1832 // DQ (8/22/2007): Added case for SgNamelistStatement
1833 case V_SgNamelistStatement:
1834 {
1835 name = "_fortran_namelist_";
1836 const SgNamelistStatement* namelistStatement = isSgNamelistStatement(declaration);
1837 ROSE_ASSERT(namelistStatement != NULL);
1838 ROSE_ASSERT(namelistStatement->get_parent() != NULL);
1839 name += StringUtility::numberToString(const_cast<SgNamelistStatement*>(namelistStatement));
1840 break;
1841 }
1842
1843 // DQ (11/21/2007): Added case for SgEquivalenceStatement
1844 case V_SgEquivalenceStatement:
1845 {
1846 name = "_fortran_equivalence_";
1847 const SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(declaration);
1848 ROSE_ASSERT(equivalenceStatement != NULL);
1849 ROSE_ASSERT(equivalenceStatement->get_parent() != NULL);
1850 name += StringUtility::numberToString(const_cast<SgEquivalenceStatement*>(equivalenceStatement));
1851 break;
1852 }
1853
1854
1855 // DQ (11/21/2007): Added case for SgCommonBlock
1856 case V_SgCommonBlock:
1857 {
1858 name = "_fortran_common_block_";
1859 const SgCommonBlock* commonBlockStatement = isSgCommonBlock(declaration);
1860 ROSE_ASSERT(commonBlockStatement != NULL);
1861 ROSE_ASSERT(commonBlockStatement->get_parent() != NULL);
1862 name += StringUtility::numberToString(const_cast<SgCommonBlock*>(commonBlockStatement));
1863 break;
1864 }
1865
1866 // DQ (11/21/2007): Added case for SgImportStatement
1867 case V_SgImportStatement:
1868 {
1869 name = "_fortran_import_stmt_";
1870 const SgImportStatement* importStatement = isSgImportStatement(declaration);
1871 ROSE_ASSERT(importStatement != NULL);
1872 ROSE_ASSERT(importStatement->get_parent() != NULL);
1873 name += StringUtility::numberToString(const_cast<SgImportStatement*>(importStatement));
1874 break;
1875 }
1876
1877 // DQ (11/21/2007): Added case for SgFormatStatement
1878 case V_SgFormatStatement:
1879 {
1880 name = "_fortran_format_stmt_";
1881 const SgFormatStatement* formatStatement = isSgFormatStatement(declaration);
1882 ROSE_ASSERT(formatStatement != NULL);
1883 ROSE_ASSERT(formatStatement->get_parent() != NULL);
1884 name += StringUtility::numberToString(const_cast<SgFormatStatement*>(formatStatement));
1885 break;
1886 }
1887
1888 // DQ (12/27/2007): Added case for SgModuleStatement
1889 case V_SgModuleStatement:
1890 {
1891 name = "_fortran_module_stmt_";
1892 const SgModuleStatement* moduleStatement = isSgModuleStatement(declaration);
1893 ROSE_ASSERT(moduleStatement != NULL);
1894 ROSE_ASSERT(moduleStatement->get_parent() != NULL);
1895 name += StringUtility::numberToString(const_cast<SgModuleStatement*>(moduleStatement));
1896 break;
1897 }
1898
1899 // DQ (12/27/2007): Added case for SgUseStatement
1900 case V_SgUseStatement:
1901 {
1902 name = "_fortran_use_stmt_";
1903 const SgUseStatement* useStatement = isSgUseStatement(declaration);
1904 ROSE_ASSERT(useStatement != NULL);
1905 ROSE_ASSERT(useStatement->get_parent() != NULL);
1906 name += StringUtility::numberToString(const_cast<SgUseStatement*>(useStatement));
1907 break;
1908 }
1909
1910 // DQ (12/28/2007): Added case for SgContainsStatement
1911 case V_SgContainsStatement:
1912 {
1913 name = "_fortran_contains_stmt_";
1914 const SgContainsStatement* containsStatement = isSgContainsStatement(declaration);
1915 ROSE_ASSERT(containsStatement != NULL);
1916 ROSE_ASSERT(containsStatement->get_parent() != NULL);
1917 name += StringUtility::numberToString(const_cast<SgContainsStatement*>(containsStatement));
1918 break;
1919 }
1920
1921 // DQ (1/20/2008): Added case for SgEntryStatement
1922 case V_SgEntryStatement:
1923 {
1924 name = "_fortran_entry_stmt_";
1925 const SgEntryStatement* entryStatement = isSgEntryStatement(declaration);
1926 ROSE_ASSERT(entryStatement != NULL);
1927 ROSE_ASSERT(entryStatement->get_parent() != NULL);
1928 name += StringUtility::numberToString(const_cast<SgEntryStatement*>(entryStatement));
1929 break;
1930 }
1931
1932 // DQ (1/23/2008): Added case for SgAttributeSpecificationStatement
1933 case V_SgAttributeSpecificationStatement:
1934 {
1935 name = "_fortran_attribute_specification_stmt_";
1936 const SgAttributeSpecificationStatement* statement = isSgAttributeSpecificationStatement(declaration);
1937 ROSE_ASSERT(statement != NULL);
1938 ROSE_ASSERT(statement->get_parent() != NULL);
1940 break;
1941 }
1942
1943 case V_SgInterfaceStatement:
1944 {
1945 name = "_fortran_interface_stmt_";
1946 const SgInterfaceStatement* statement = isSgInterfaceStatement(declaration);
1947 ROSE_ASSERT(statement != NULL);
1948 ROSE_ASSERT(statement->get_parent() != NULL);
1949 name += StringUtility::numberToString(const_cast<SgInterfaceStatement*>(statement));
1950 break;
1951 }
1952
1953 case V_SgFortranIncludeLine:
1954 {
1955 name = "_fortran_include_line_stmt_";
1956 const SgFortranIncludeLine* statement = isSgFortranIncludeLine(declaration);
1957 ROSE_ASSERT(statement != NULL);
1958 ROSE_ASSERT(statement->get_parent() != NULL);
1959 name += StringUtility::numberToString(const_cast<SgFortranIncludeLine*>(statement));
1960 break;
1961 }
1962
1963 // DQ (4/16/2011): Added Java import statment support.
1964 case V_SgJavaImportStatement:
1965 {
1966 name = "_java_import_stmt_";
1967 const SgJavaImportStatement* statement = isSgJavaImportStatement(declaration);
1968 ROSE_ASSERT(statement != NULL);
1969 ROSE_ASSERT(statement->get_parent() != NULL);
1970 name += StringUtility::numberToString(const_cast<SgJavaImportStatement*>(statement));
1971 break;
1972 }
1973
1974 case V_SgJavaPackageDeclaration:
1975 {
1976 name = "_java_package_declaration_";
1977 const SgJavaPackageDeclaration* package_declaration = isSgJavaPackageDeclaration(declaration);
1978 ROSE_ASSERT(package_declaration != NULL);
1979 ROSE_ASSERT(package_declaration->get_parent() != NULL);
1980 name += StringUtility::numberToString(const_cast<SgJavaPackageDeclaration*>(package_declaration));
1981 break;
1982 }
1983
1984 case V_SgJavaPackageStatement:
1985 {
1986 name = "_java_package_stmt_";
1987 const SgJavaPackageStatement* statement = isSgJavaPackageStatement(declaration);
1988 ROSE_ASSERT(statement != NULL);
1989 ROSE_ASSERT(statement->get_parent() != NULL);
1990 name += StringUtility::numberToString(const_cast<SgJavaPackageStatement*>(statement));
1991 break;
1992 }
1993
1994 // DQ (1/21/2018): Added case for C++11 SgStaticAssertionDeclaration
1995 case V_SgStaticAssertionDeclaration:
1996 {
1997 name = "_static_assertion_declaration_stmt_";
1998 const SgStaticAssertionDeclaration* statement = isSgStaticAssertionDeclaration(declaration);
1999 ROSE_ASSERT(statement != NULL);
2000 ROSE_ASSERT(statement->get_parent() != NULL);
2001 name += StringUtility::numberToString(const_cast<SgStaticAssertionDeclaration*>(statement));
2002 break;
2003 }
2004
2005 case V_SgNonrealDecl:
2006 {
2007 const SgNonrealDecl * nrdecl = isSgNonrealDecl(declaration);
2008 ROSE_ASSERT(nrdecl != NULL);
2009 name = nrdecl->get_name();
2010 break;
2011 }
2012
2013 // DQ (3/26/2019): Adding support for new declaration.
2014 case V_SgEmptyDeclaration:
2015 {
2016 const SgEmptyDeclaration * emptyDeclaration = isSgEmptyDeclaration(declaration);
2017 ROSE_ASSERT(emptyDeclaration != NULL);
2018 name = string("emptyDeclaration") + StringUtility::numberToString(const_cast<SgDeclarationStatement*>(declaration));
2019 break;
2020 }
2021
2022 case V_SgAdaPackageSpecDecl:
2023 {
2024 name = genericGetName(isSgAdaPackageSpecDecl(declaration));
2025 break;
2026 }
2027
2028 case V_SgAdaPackageBodyDecl:
2029 {
2030 name = genericGetName(isSgAdaPackageBodyDecl(declaration));
2031 break;
2032 }
2033
2034 case V_SgAdaFormalTypeDecl:
2035 {
2036 name = genericGetName(isSgAdaFormalTypeDecl(declaration));
2037 break;
2038 }
2039
2040 case V_SgAdaGenericDecl:
2041 {
2042 // need to look inside the declaration wrapped by the generic.
2043 const SgAdaGenericDecl* gendcl = isSgAdaGenericDecl(declaration);
2044 name = get_name(gendcl->get_declaration());
2045 break;
2046#if OBSOLETE_CODE
2047 if (isSgFunctionDeclaration(dcl->get_declaration())) {
2048 name = "_ada_generic_decl_" + genericGetName(isSgFunctionDeclaration(dcl->get_declaration()));
2049 break;
2050 }
2051 if (isSgAdaPackageSpecDecl(dcl->get_declaration())) {
2052 name = "_ada_generic_decl_" + genericGetName(isSgAdaPackageSpecDecl(dcl->get_declaration()));
2053 break;
2054 }
2055
2056 // something malformed in the tree if we get here
2057 ROSE_ABORT();
2058 break;
2059#endif /* OBSOLETE_CODE */
2060 }
2061
2062 case V_SgAdaDiscriminatedTypeDecl:
2063 {
2064 const SgAdaDiscriminatedTypeDecl* dcl = isSgAdaDiscriminatedTypeDecl(declaration);
2065 ROSE_ASSERT(dcl);
2066
2067 if (const SgDeclarationStatement* discrDcl = dcl->get_discriminatedDecl())
2068 {
2069 name = get_name(discrDcl);
2070 }
2071 else
2072 {
2073 name = "_incomplete_Ada_discriminated_type_";
2074 }
2075
2076 break;
2077 }
2078
2079 case V_SgAdaVariantDecl:
2080 {
2081 name = "_ada_variant_decl_";
2082 break;
2083 }
2084
2085 case V_SgAdaAttributeClause:
2086 {
2087 name = "_ada_attribute_clause_";
2088 break;
2089 }
2090
2091 case V_SgAdaRepresentationClause:
2092 {
2093 name = "_ada_representation_clause_";
2094 break;
2095 }
2096
2097 case V_SgAdaEnumRepresentationClause:
2098 {
2099 name = "_ada_enum_representation_clause_";
2100 break;
2101 }
2102
2103 case V_SgAdaComponentClause:
2104 {
2105 name = "_ada_component_clause_";
2106 break;
2107 }
2108
2109 case V_SgAdaTaskTypeDecl:
2110 {
2111 name = genericGetName(isSgAdaTaskTypeDecl(declaration));
2112 break;
2113 }
2114
2115 case V_SgAdaProtectedTypeDecl:
2116 {
2117 name = genericGetName(isSgAdaProtectedTypeDecl(declaration));
2118 break;
2119 }
2120
2121 case V_SgAdaTaskBodyDecl:
2122 {
2123 name = genericGetName(isSgAdaTaskBodyDecl(declaration));
2124 break;
2125 }
2126
2127 case V_SgAdaProtectedBodyDecl:
2128 {
2129 name = genericGetName(isSgAdaProtectedBodyDecl(declaration));
2130 break;
2131 }
2132
2133 case V_SgAdaRenamingDecl:
2134 {
2135 name = genericGetName(isSgAdaRenamingDecl(declaration));
2136 break;
2137 }
2138
2139 case V_SgAdaTaskSpecDecl:
2140 {
2141 name = genericGetName(isSgAdaTaskSpecDecl(declaration));
2142 break;
2143 }
2144
2145 case V_SgAdaProtectedSpecDecl:
2146 {
2147 name = genericGetName(isSgAdaProtectedSpecDecl(declaration));
2148 break;
2149 }
2150
2151 case V_SgAdaGenericInstanceDecl:
2152 {
2153 name = genericGetName(isSgAdaGenericInstanceDecl(declaration));
2154 break;
2155 }
2156
2157 case V_SgAdaFormalPackageDecl:
2158 {
2159 name = genericGetName(isSgAdaFormalPackageDecl(declaration));
2160 break;
2161 }
2162
2163 case V_SgAdaParameterList:
2164 {
2165 const SgAdaParameterList* plst = isSgAdaParameterList(declaration);
2166 ROSE_ASSERT(plst);
2167
2168 name = std::accumulate( plst->get_parameters().begin(), plst->get_parameters().end(),
2169 std::string{"_ada_parameter_list_"},
2170 [](std::string n, SgDeclarationStatement* rhs) -> std::string
2171 {
2172 n += SageInterface::get_name(rhs);
2173 return n;
2174 }
2175 );
2176 break;
2177 }
2178
2179 // Note that the case for SgVariableDeclaration is not implemented
2180 default:
2181 printf ("Warning: default case reached in SageInterface::get_name ( const SgDeclarationStatement* declaration ), declaration = %p = %s \n",
2182 declaration,declaration->class_name().c_str());
2183 ROSE_ABORT();
2184 }
2185
2186 return name;
2187 }
2188
2189string
2191 {
2192 string name = "undefined_name";
2193
2194 ROSE_ASSERT(scope != NULL);
2195
2196 switch (scope->variantT())
2197 {
2198 // DQ (6/11/2011): Added support for new template IR nodes.
2199 case V_SgTemplateClassDefinition:
2200 name = get_name(isSgTemplateClassDefinition(scope)->get_declaration());
2201 break;
2202
2203 case V_SgClassDefinition:
2204 case V_SgTemplateInstantiationDefn:
2205 name = get_name(isSgClassDefinition(scope)->get_declaration());
2206 break;
2207
2208 // DQ (9/8/2012): Added missing case for SgTemplateFunctionDefinition.
2209 case V_SgTemplateFunctionDefinition:
2210 case V_SgFunctionDefinition:
2211 name = get_name(isSgFunctionDefinition(scope)->get_declaration());
2212 break;
2213
2214 case V_SgNamespaceDefinitionStatement:
2215 name = get_name(isSgNamespaceDefinitionStatement(scope)->get_namespaceDeclaration());
2216 break;
2217 case V_SgJavaLabelStatement:
2218 name = (isSgJavaLabelStatement(scope)->get_label()).getString();
2219 break;
2220
2221 // DQ (7/18/2017): Added support for the new declaration scope.
2222 case V_SgDeclarationScope:
2223
2224 // DQ (11/30/2007): Added more fortran support.
2225 case V_SgAssociateStatement:
2226 case V_SgJavaForEachStatement:
2227
2228 case V_SgFunctionParameterScope:
2229 case V_SgAdaPackageSpec:
2230 case V_SgAdaPackageBody:
2231 case V_SgAdaTaskSpec:
2232 case V_SgAdaTaskBody:
2233 case V_SgAdaProtectedSpec:
2234 case V_SgAdaProtectedBody:
2235 case V_SgAdaGenericDefn:
2236 case V_SgAdaAcceptStmt:
2237 case V_SgJovialForThenStatement: //Rasmussen: Jovial for statement
2238 case V_SgMatlabForStatement: //SK: Matlab for statement
2239 case V_SgBasicBlock:
2240 case V_SgCatchOptionStmt:
2241 case V_SgDoWhileStmt:
2242 case V_SgForStatement:
2243 case V_SgGlobal:
2244 case V_SgIfStmt:
2245 case V_SgSwitchStatement:
2246 case V_SgWhileStmt:
2247 case V_SgFortranDo:
2248 case V_SgForAllStatement:
2249 case V_SgRangeBasedForStatement:
2250 name = StringUtility::numberToString(const_cast<SgScopeStatement*>(scope));
2251 break;
2252
2253 default:
2254 printf ("Error: undefined case (SgScopeStatement) in SageInterface::get_name(): node = %s \n",scope->class_name().c_str());
2255 ROSE_ABORT();
2256 }
2257
2258 return name;
2259 }
2260
2261string
2263 {
2264 string name = "undefined_name";
2265
2266 ROSE_ASSERT(stmt != NULL);
2267
2268 const SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
2269 if (declaration != NULL)
2270 {
2271 name = get_name(declaration);
2272 }
2273 else
2274 {
2275 const SgScopeStatement* scope = isSgScopeStatement(stmt);
2276 if (scope != NULL)
2277 {
2278 name = get_name(scope);
2279 }
2280 else
2281 {
2282 // DQ (10/25/2007): This is better since it names the SgLabelStatement case
2283 switch (stmt->variantT())
2284 {
2285#if 0
2286 case V_SgBreakStmt:
2287 case V_SgCaseOptionStmt:
2288 case V_SgCatchStatementSeq:
2289 case V_SgClinkageStartStatement:
2290 case V_SgContinueStmt:
2291 case V_SgDefaultOptionStmt:
2292 case V_SgExprStmt:
2293 case V_SgForInitStmt:
2294 case V_SgFunctionTypeTable:
2295 case V_SgGotoStatement:
2296 case V_SgReturnStmt:
2297 case V_SgSpawnStmt:
2298 case V_SgTryStmt:
2299 name = stmt->class_name();
2300 break;
2301#endif
2302 case V_SgLabelStatement:
2303 {
2304 const SgLabelStatement* labelStatement = isSgLabelStatement(stmt);
2305 name = labelStatement->get_label().str();
2306 break;
2307 }
2308
2309 default:
2310 {
2311 // printf ("Default reached in switch \n");
2312 // name = "default name";
2313 name = stmt->class_name();
2314 break;
2315 }
2316 }
2317 }
2318 }
2319
2320 return name;
2321 }
2322
2323string
2325 {
2326 // This function is useful for debugging
2327 // This is the most general case of a function to return a name for an IR node.
2328 ROSE_ASSERT(node != NULL);
2329
2330 string name = "undefined_name";
2331
2332 ROSE_ASSERT(node != NULL);
2333
2334 switch (node->variantT())
2335 {
2336 case V_SgInitializedName:
2337 {
2338 const SgInitializedName* initializedName = isSgInitializedName(node);
2339 if (initializedName != NULL)
2340 {
2341 name = initializedName->get_name().str();
2342 }
2343 break;
2344 }
2345#if 1
2346 // DQ (3/17/2006): Implemented case for pragma declaration (forgot this case)
2347 case V_SgPragma:
2348 {
2349 name = "_pragma_string_";
2350 const SgPragma* pragma = isSgPragma(node);
2351 ROSE_ASSERT(pragma != NULL);
2352 name += pragma->get_pragma();
2353 break;
2354 }
2355#endif
2356
2357 // DQ (5/31/2007): Implemented case for SgProject
2358 case V_SgProject:
2359 {
2360 name = "_project_";
2361 break;
2362 }
2363
2364 // DQ (5/31/2007): Implemented case for SgFile
2365 // case V_SgFile:
2366 case V_SgSourceFile:
2367#ifdef ROSE_ENABLE_BINARY_ANALYSIS
2368 case V_SgBinaryComposite:
2369#endif
2370 {
2371 name = "_file_";
2372
2373 // DQ (3/1/2009): Added support to include the file name.
2374 const SgFile* file = isSgFile(node);
2375 ROSE_ASSERT(file != NULL);
2376
2377 name += file->getFileName();
2378 break;
2379 }
2380
2381 // DQ (5/31/2007): Implemented case for SgSymbolTable
2382 case V_SgSymbolTable:
2383 {
2384 name = "_symbol_table_";
2385 break;
2386 }
2387
2388 // DQ (5/31/2007): Implemented case for SgStorageModifier
2389 case V_SgStorageModifier:
2390 {
2391 name = "_storage_modifier_";
2392 break;
2393 }
2394
2395
2396 // DQ (5/31/2007): Implemented case for Sg_File_Info
2397 case V_Sg_File_Info:
2398 {
2399 name = "_file_info_";
2400 break;
2401 }
2402
2403 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2404 case V_SgTemplateArgument:
2405 {
2406 name = "_template_argument_";
2407 const SgTemplateArgument* templateArgument = isSgTemplateArgument(node);
2408 ROSE_ASSERT(templateArgument != NULL);
2409 switch(templateArgument->get_argumentType())
2410 {
2412 {
2413 SgType* t = templateArgument->get_type();
2414 ROSE_ASSERT(t != NULL);
2415 name += get_name(t);
2416 break;
2417 }
2418
2420 {
2421 SgExpression* t = templateArgument->get_expression();
2422
2423 // DQ (8/11/2013): Adding support for including an initializedName instead of an expression (for template parameters used as expressions).
2424 // ROSE_ASSERT(t != NULL);
2425 // name += get_name(t);
2426 if (t != NULL)
2427 {
2428 ROSE_ASSERT(templateArgument->get_initializedName() == NULL);
2429 name += get_name(t);
2430 }
2431 else
2432 {
2433 ROSE_ASSERT(t == NULL);
2434 SgInitializedName* initializedName = templateArgument->get_initializedName();
2435 ROSE_ASSERT(initializedName != NULL);
2436
2437 name += get_name(initializedName);
2438 }
2439 break;
2440 }
2441
2443 {
2444 // SgTemplateDeclaration* t = templateArgument->get_templateDeclaration();
2445 SgDeclarationStatement* t = templateArgument->get_templateDeclaration();
2446 ROSE_ASSERT(t != NULL);
2447 name += get_name(t);
2448 break;
2449 }
2450
2451 default:
2452 {
2453 printf ("Error: default case reached in switch on templateArgument->get_argumentType() \n");
2454 ROSE_ABORT();
2455 }
2456 }
2457 break;
2458 }
2459
2460
2461 // DQ (8/7/2007): Implemented case for SgTemplateArgument
2462 case V_SgTypeModifier:
2463 {
2464 const SgTypeModifier* typeModifier = isSgTypeModifier(node);
2465 ROSE_ASSERT(typeModifier != NULL);
2466 name = "_type_modifier_" + typeModifier->displayString();
2467 break;
2468 }
2469
2470 // DQ (11/19/2007): Implemented case for SgNameGroup
2471 case V_SgNameGroup:
2472 {
2473 const SgNameGroup* nameGroup = isSgNameGroup(node);
2474 ROSE_ASSERT(nameGroup != NULL);
2475 name = "_name_group_" + nameGroup->get_group_name();
2476 break;
2477 }
2478
2479 // DQ (11/20/2007): Implemented case for Fortran data statement support
2480 case V_SgDataStatementGroup:
2481 {
2482 const SgDataStatementGroup* dataGroup = isSgDataStatementGroup(node);
2483 ROSE_ASSERT(dataGroup != NULL);
2484 name = "_data_statement_group_";
2485 break;
2486 }
2487
2488 // DQ (11/20/2007): Implemented case for Fortran data statement support
2489 case V_SgDataStatementObject:
2490 {
2491 const SgDataStatementObject* dataObject = isSgDataStatementObject(node);
2492 ROSE_ASSERT(dataObject != NULL);
2493 name = "_data_statement_object_";
2494 break;
2495 }
2496
2497 // DQ (11/20/2007): Implemented case for Fortran data statement support
2498 case V_SgDataStatementValue:
2499 {
2500 const SgDataStatementValue* dataValue = isSgDataStatementValue(node);
2501 ROSE_ASSERT(dataValue != NULL);
2502 name = "_data_statement_value_";
2503 break;
2504 }
2505
2506 // DQ (11/19/2007): Implemented case for SgCommonBlock
2507 case V_SgCommonBlockObject:
2508 {
2509 const SgCommonBlockObject* commonBlockObject = isSgCommonBlockObject(node);
2510 ROSE_ASSERT(commonBlockObject != NULL);
2511 name = "_common_block_object_" + commonBlockObject->get_block_name();
2512 break;
2513 }
2514
2515 // DQ (12/23/2007): Added support for repeat_specification
2516 case V_SgFormatItem:
2517 {
2518 const SgFormatItem* formatItem = isSgFormatItem(node);
2519 ROSE_ASSERT(formatItem != NULL);
2520 name = "_format_item_";
2521 break;
2522 }
2523
2524 // DQ (12/23/2007): Added support for repeat_specification
2525 case V_SgFormatItemList:
2526 {
2527 const SgFormatItemList* formatItemList = isSgFormatItemList(node);
2528 ROSE_ASSERT(formatItemList != NULL);
2529 name = "_format_item_list_";
2530 break;
2531 }
2532
2533 // DQ (12/23/2007): Added support for repeat_specification
2534 case V_SgRenamePair:
2535 {
2536 const SgRenamePair* renamePair = isSgRenamePair(node);
2537 ROSE_ASSERT(renamePair != NULL);
2538 name = renamePair->get_local_name() + "__" + renamePair->get_use_name() + "_rename_pair_";
2539 break;
2540 }
2541
2542 // DQ (12/2/2010): Implemented case for SgName
2543 case V_SgName:
2544 {
2545 const SgName* name_node = isSgName(node);
2546 ROSE_ASSERT(name_node != NULL);
2547 name = "_name_" + name_node->getString();
2548 break;
2549 }
2550
2551 // DQ (8/8/2013): Implemented case for SgTemplateParameter
2552 case V_SgTemplateParameter:
2553 {
2554 const SgTemplateParameter* template_parameter_node = isSgTemplateParameter(node);
2555 ROSE_ASSERT(template_parameter_node != NULL);
2556 name = "_template_parameter_";
2557
2558 switch(template_parameter_node->get_parameterType())
2559 {
2561 {
2562 name += "type_parameter_";
2563 break;
2564 }
2565
2567 {
2568 name += "nontype_parameter_";
2569#if 1
2570 name += template_parameter_node->unparseToString();
2571#else
2572 if (template_parameter_node->get_expression() != NULL)
2573 {
2574 name += template_parameter_node->get_expression()->unparseToString();
2575 }
2576 else
2577 {
2578 ROSE_ASSERT(template_parameter_node->get_initializedName() != NULL);
2579
2580 // DQ (8/8/2013): This does not handle the case of "template <void (foo::*M)()> void test() {}"
2581 // since what is unparsed is: "_template_parameter_nontype_parameter_M"
2582 // instead of a string to represent what is in "void (foo::*M)()"
2583 // and differentiate it from: "int foo::*M" in: "template <void (foo::*M)()> void test() {}"
2584 name += template_parameter_node->get_initializedName()->unparseToString();
2585 }
2586#endif
2587 break;
2588 }
2589
2591 {
2592 name += "template_parameter_";
2593 break;
2594 }
2595
2596 default:
2597 {
2598 printf ("Error: default reached \n");
2599 ROSE_ABORT();
2600 }
2601 }
2602 break;
2603 }
2604
2605 // DQ (1/21/2019): Implemented case for SgBaseClass
2606 case V_SgBaseClass:
2607 {
2608 const SgBaseClass* base_class_node = isSgBaseClass(node);
2609 ROSE_ASSERT(base_class_node != NULL);
2610 ROSE_ASSERT(base_class_node->get_base_class() != NULL);
2611
2612 // Add the access modifier to the output.
2613 string access = "";
2614 const SgBaseClassModifier* baseClassModifier = base_class_node->get_baseClassModifier();
2615 ROSE_ASSERT(baseClassModifier != NULL);
2616 access = baseClassModifier->displayString();
2617
2618 name = "_base_class_" + access + "_" + get_name(base_class_node->get_base_class());
2619 break;
2620 }
2621
2622 default:
2623 {
2624 printf ("Default reached in switch for SgSupport IR node = %s \n",node->class_name().c_str());
2625 name = "default name";
2626 // ROSE_ASSERT(false);
2627 break;
2628 }
2629 }
2630
2631 return name;
2632 }
2633
2634
2635string
2637 {
2638 // This function is useful for debugging
2639 // This is the most general case of a function to return a name for an IR node.
2640 ROSE_ASSERT(symbol != NULL);
2641
2642 string aliasSymbolPrefix = "";
2643 if (isSgAliasSymbol(symbol) != NULL)
2644 {
2645 aliasSymbolPrefix = "_ALIAS";
2646 }
2647
2648 // printf ("In SageInterface::get_name(): symbol->get_symbol_basis() = %p = %s \n",symbol->get_symbol_basis(),symbol->get_symbol_basis()->class_name().c_str());
2649 // printf ("In SageInterface::get_name(): symbol->get_declaration() = %p = %s \n",symbol->get_declaration(),symbol->get_declaration()->class_name().c_str());
2650
2651 // This is a call to the "get_name()" virtual function
2652 return symbol->get_name() + aliasSymbolPrefix + "_symbol_";
2653 }
2654
2655string
2657 {
2658 // This function is useful for debugging
2659 // This is the most general case of a function to return a name for an IR node.
2660 ROSE_ASSERT(type != NULL);
2661
2662 string returnName;
2663
2664 const SgNamedType* namedType = isSgNamedType(type);
2665 if (namedType != NULL)
2666 {
2667 returnName = "named_type_";
2668 returnName = namedType->get_name().getString();
2669 }
2670 else
2671 {
2672 switch(type->variantT())
2673 {
2674 case V_SgPointerType:
2675 {
2676 const SgPointerType* pointerType = isSgPointerType(type);
2677 returnName = "pointer_to_";
2678 returnName += get_name(pointerType->get_base_type());
2679 break;
2680 }
2681
2682 case V_SgReferenceType:
2683 {
2684 const SgReferenceType* referenceType = isSgReferenceType(type);
2685 returnName = "reference_to_";
2686 returnName += get_name(referenceType->get_base_type());
2687 break;
2688 }
2689
2690 case V_SgArrayType:
2691 {
2692 const SgArrayType* arrayType = isSgArrayType(type);
2693 returnName = "array_of_";
2694 returnName += get_name(arrayType->get_base_type());
2695 break;
2696 }
2697
2698 case V_SgModifierType:
2699 {
2700 const SgModifierType* modifierType = isSgModifierType(type);
2701 returnName = get_name(&(modifierType->get_typeModifier()));
2702 returnName += get_name(modifierType->get_base_type());
2703 break;
2704 }
2705
2706 // DQ (8/26/2012): Added case to support template declaration work.
2707 case V_SgTemplateType:
2708 {
2709 const SgTemplateType* templateType = isSgTemplateType(type);
2710 returnName = "templateType_";
2711 returnName += templateType->get_name();
2712 break;
2713 }
2714
2715 default:
2716 {
2717 returnName = type->class_name();
2718 }
2719 }
2720 }
2721
2722 return returnName;
2723 }
2724
2725string
2727 {
2728 string name = "undefined_name";
2729
2730 // ROSE_ASSERT(expr != NULL);
2731 switch(expr->variantT())
2732 {
2733 case V_SgVarRefExp:
2734 {
2735 const SgVarRefExp* varRef = isSgVarRefExp(expr);
2736 name = "var_ref_of_";
2737 ROSE_ASSERT(varRef != NULL);
2738 ROSE_ASSERT(varRef->get_symbol() != NULL);
2739 name += varRef->get_symbol()->get_name();
2740 break;
2741 }
2742
2743 // DQ (2/2/2011): Added case to support fortran use of label references in alternate return parameters.
2744 case V_SgLabelRefExp:
2745 {
2746 const SgLabelRefExp* labelRef = isSgLabelRefExp(expr);
2747 name = "label_ref_of_";
2748 ROSE_ASSERT(labelRef != NULL);
2749 ROSE_ASSERT(labelRef->get_symbol() != NULL);
2750 name += labelRef->get_symbol()->get_name();
2751 break;
2752 }
2753
2754 case V_SgPntrArrRefExp:
2755 {
2756 const SgPntrArrRefExp* arrayRef = isSgPntrArrRefExp(expr);
2757 name = "array_ref_of_";
2758 name += get_name(arrayRef->get_lhs_operand());
2759 name += "_at_";
2760 name += get_name(arrayRef->get_rhs_operand());
2761 break;
2762 }
2763
2764 case V_SgFunctionCallExp:
2765 {
2766 const SgFunctionCallExp* functionCall = isSgFunctionCallExp(expr);
2767 name = "function_call_";
2768 name += get_name(functionCall->get_function());
2769 break;
2770 }
2771
2772 case V_SgFunctionRefExp:
2773 {
2774 const SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(expr);
2775 name = "function_ref_";
2776 name += functionRefExp->get_symbol()->get_name();
2777 break;
2778 }
2779
2780 // DQ (4/19/2013): Added support for SgMemberFunctionRefExp.
2781 case V_SgMemberFunctionRefExp:
2782 {
2783 const SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(expr);
2784 name = "member_function_ref_";
2785 name += memberFunctionRefExp->get_symbol()->get_name();
2786 break;
2787 }
2788
2789 case V_SgIntVal:
2790 {
2791 const SgIntVal* valueExp = isSgIntVal(expr);
2792 name = "integer_value_exp_";
2793 name += StringUtility::numberToString(valueExp->get_value());
2794 break;
2795 }
2796
2797 case V_SgStringVal:
2798 {
2799 const SgStringVal* valueExp = isSgStringVal(expr);
2800 name = "string_value_exp_";
2801 name += valueExp->get_value();
2802 break;
2803 }
2804
2805 case V_SgSubscriptExpression:
2806 {
2807 const SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(expr);
2808 name = "subscript_exp_";
2809 // name += StringUtility::numberToString(subscriptExpression->get_lowerBound());
2810 name += get_name(subscriptExpression->get_lowerBound());
2811 name += "_";
2812 // name += StringUtility::numberToString(subscriptExpression->get_upperBound());
2813 name += get_name(subscriptExpression->get_upperBound());
2814 name += "_";
2815 // name += StringUtility::numberToString(subscriptExpression->get_stride());
2816 name += get_name(subscriptExpression->get_stride());
2817 break;
2818 }
2819
2820 case V_SgNullExpression:
2821 {
2822 name = "null_expression";
2823 break;
2824 }
2825
2826 // DQ (1/17/2011): Added support for SgExprListExp (to support debugging).
2827 case V_SgExprListExp:
2828 {
2829 const SgExprListExp* exprListExp = isSgExprListExp(expr);
2830 name = "expr_list_exp_";
2831 for (size_t i = 0; i < exprListExp->get_expressions().size(); i++)
2832 {
2833 name += get_name(exprListExp->get_expressions()[i]);
2834 }
2835 break;
2836 }
2837
2838 // DQ (1/31/2011): Added to support Fortran debugging.
2839 case V_SgActualArgumentExpression:
2840 {
2841 const SgActualArgumentExpression* actualArgExp = isSgActualArgumentExpression(expr);
2842 name = "actual_arg_exp_name_";
2843 name += actualArgExp->get_argument_name();
2844 name = "_exp_";
2845 name += get_name(actualArgExp->get_expression());
2846 break;
2847 }
2848
2849 // DQ (7/25/2012): Added support for new template IR nodes.
2850 case V_SgTemplateParameterVal:
2851 {
2852 const SgTemplateParameterVal* valueExp = isSgTemplateParameterVal(expr);
2853 name = "template_parameter_value_expression_number_";
2854 // name += valueExp->get_value();
2855 // name += get_name(valueExp);
2856 name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2857 break;
2858 }
2859
2860 // DQ (4/19/2013): Added support for SgDotExp.
2861 case V_SgDotExp:
2862 {
2863 const SgDotExp* dotExp = isSgDotExp(expr);
2864 ROSE_ASSERT(dotExp != NULL);
2865
2866 name = "_dot_exp_lhs_";
2867 name += get_name(dotExp->get_lhs_operand());
2868 name += "_dot_exp_rhs_";
2869 name += get_name(dotExp->get_rhs_operand());
2870 // name += StringUtility::numberToString(valueExp->get_template_parameter_position());
2871 break;
2872 }
2873
2874 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2875 case V_SgLambdaExp:
2876 {
2877 const SgLambdaExp* lambdaExp = isSgLambdaExp(expr);
2878 ROSE_ASSERT (lambdaExp != NULL);
2879 name = "lambda_expression_";
2880 break;
2881 }
2882
2883 // DQ (1/3/2020): Added support for SgThisExp.
2884 case V_SgThisExp:
2885 {
2886 const SgThisExp* thisExp = isSgThisExp(expr);
2887 ROSE_ASSERT(thisExp != NULL);
2888
2889 name = "_this_exp_for_";
2890
2891 SgClassSymbol* classSymbol = thisExp->get_class_symbol();
2892 ROSE_ASSERT(classSymbol != NULL);
2893 // name += get_name(classSymbol->get_name());
2894 // string class_name = classSymbol->get_name();
2895 // name += class_name;
2896 name += classSymbol->get_name();
2897 break;
2898 }
2899
2900 default:
2901 {
2902 // Nothing to do for other IR nodes
2903#if 0
2904 // DQ (7/25/2012): Make this an error.
2905 printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2906 ROSE_ABORT();
2907#endif
2908 // DQ (4/8/2010): define something specific to this function to make debugging more clear.
2909 // printf ("Note: default reached in get_name() expr = %p = %s \n",expr,expr->class_name().c_str());
2910 // name = "undefined_expression_name";
2911 name = expr->class_name() + "_undef_name";
2912 break;
2913 }
2914 }
2915
2916 return name;
2917 }
2918
2919string
2921 {
2922 // This function is useful for debugging
2923 // This is the most general case of a function to return a name for an IR node.
2924 ROSE_ASSERT(node != NULL);
2925
2926 string returnName;
2927
2928 switch(node->variantT())
2929 {
2930 case V_SgRenamePair:
2931 {
2932 const SgRenamePair* n = isSgRenamePair(node);
2933 returnName = "rename_pair_";
2934 returnName += n->get_local_name().str();
2935 returnName += "_from_";
2936 returnName += n->get_use_name().str();
2937 break;
2938 }
2939
2940 case V_SgInitializedName:
2941 {
2942 const SgInitializedName* n = isSgInitializedName(node);
2943 ROSE_ASSERT (n != NULL);
2944 returnName = "initialized_name_";
2945 returnName += n->get_name().str();
2946 break;
2947 }
2948
2949 // DQ (9/3/2014): Added support for C++11 lambda expressions.
2950 case V_SgLambdaCapture:
2951 {
2952 const SgLambdaCapture* n = isSgLambdaCapture(node);
2953 ROSE_ASSERT (n != NULL);
2954 returnName = "lambda_capture_";
2955 // returnName += n->get_name().str();
2956 break;
2957 }
2958
2959#if 0
2960 case V_SgInterfaceBody:
2961 {
2962 const SgInterfaceBody* n = isSgInterfaceBody(node);
2963 returnName = "interface_body";
2964 break;
2965 }
2966#endif
2967 default:
2968 {
2969 returnName = node->class_name();
2970 }
2971 }
2972
2973 return returnName;
2974 }
2975
2976string
2978 {
2979 // This function is useful for debugging
2980 // This is the most general case of a function to return a name for an IR node.
2981 // Later this function will handle expressions, etc.
2982
2983 string name = "undefined_name";
2984
2985 ROSE_ASSERT(node != NULL);
2986
2987 const SgLocatedNode* locatedNode = isSgLocatedNode(node);
2988 if (locatedNode != NULL)
2989 {
2990 const SgStatement* statement = isSgStatement(node);
2991 if (statement != NULL)
2992 {
2993 name = get_name(statement);
2994 }
2995 else
2996 {
2997 const SgExpression* expression = isSgExpression(node);
2998 if (expression != NULL)
2999 {
3000 name = get_name(expression);
3001 }
3002 else
3003 {
3004 const SgLocatedNodeSupport* locatedNodeSupport = isSgLocatedNodeSupport(node);
3005 if (locatedNodeSupport != NULL)
3006 {
3007 name = get_name(locatedNodeSupport);
3008 }
3009 else
3010 {
3011 const SgToken* token = isSgToken(node);
3012 if (token != NULL)
3013 {
3014 name = get_name(token);
3015 }
3016 else
3017 {
3018 printf ("Unknown SgLocatedNode = %p = %s \n",node,node->class_name().c_str());
3019 ROSE_ABORT();
3020 }
3021 }
3022 }
3023 }
3024 }
3025 else
3026 {
3027 const SgSupport* supportNode = isSgSupport(node);
3028 if (supportNode != NULL)
3029 {
3030 name = get_name(supportNode);
3031 }
3032 else
3033 {
3034 // DQ (9/21/2005): I think this is good enough for the more general case (for now)
3035 const SgSymbol* symbol = isSgSymbol(node);
3036 if (symbol != NULL)
3037 {
3038 name = get_name(symbol);
3039 }
3040 else
3041 {
3042 // DQ (8/7/2007): Added support to get names of types (usefult for SgNamedType objects).
3043 const SgType* type = isSgType(node);
3044 if (type != NULL)
3045 {
3046 name = get_name(type);
3047 }
3048 else
3049 {
3050 name = node->class_name();
3051 }
3052 }
3053 }
3054 }
3055
3056 return name;
3057 }
3058
3059
3060string
3062 {
3063 // This function is useful for debugging
3064 string name = "undefined_name";
3065
3066 ROSE_ASSERT(token != NULL);
3067 name = token->get_lexeme_string();
3068
3069 // Handle special cases
3070 if (name == " ")
3071 name = "<space>";
3072 else if (name == "\n")
3073 name = "<eol>";
3074 else if (name == "\t")
3075 name = "<tab>";
3076
3077 return name;
3078 }
3079
3080
3081void
3088
3089
3090string
3092 {
3093 // DQ (3/20/2016): Adding support for generating a unique name from a declaration that
3094 // can be used as an identifier. This functionality is used in the DSL infrastructure
3095 // support (refactored to this location in ROSE). The point of this mechanism is that
3096 // unlike mangled names that are compressed in a way that allows them to only be used
3097 // within a single translation unit, names generated by this function can be used across
3098 // multiple translation units. These names are also easier to interprete in debugging
3099 // (since they explicitly contain the scope, function name, and coding to interprete
3100 // function overloading.
3101
3102 // At present it only supports class declarations, and function declarations (all others
3103 // are trapped as errors).
3104
3105 // Name collision testing, it might be that this should be external to this function.
3106 // static std::map<std::string,int> dsl_attribute_name_collision_map;
3107 // static std::map<std::string,int> local_name_collision_map;
3108
3109 string s;
3110
3111 // string scope = SageInterface::get_name(classDeclaration->get_scope());
3112 string scope = isSgGlobal(declaration->get_scope()) == NULL ? SageInterface::get_name(declaration->get_scope()) : "global";
3113
3114 switch (declaration->variantT())
3115 {
3116 case V_SgClassDeclaration:
3117 case V_SgTemplateClassDeclaration:
3118 // case V_SgTemplateInstantiationDecl:
3119 {
3120 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declaration);
3121 ROSE_ASSERT(classDeclaration != NULL);
3122
3123 string type_name = classDeclaration->get_name();
3124#if 0
3125 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case class or template type: type_name = %s \n",type_name.c_str());
3126#endif
3127 string className = string("scope_") + scope + "_type_name_" + type_name;
3128#if 0
3129 printf ("classDeclaration->get_scope() = %p = %s scope = %s \n",classDeclaration->get_scope(),classDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3130#endif
3131 s = className;
3132 break;
3133 }
3134
3135 // DQ (3/29/2016): Seperate out the case of the SgTemplateInstantiationDecl.
3136 case V_SgTemplateInstantiationDecl:
3137 {
3138 SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(declaration);
3139 ROSE_ASSERT(templateInstantiationDeclaration != NULL);
3140
3141 // Note that we can't use the mangled name because they might not be unique across multiple translation units if seperately compiled).
3142 // string type_name = templateInstantiationDeclaration->get_name();
3143 // string type_name = templateInstantiationDeclaration->get_mangled_name();
3144 // string type_name = templateInstantiationDeclaration->get_templateName();
3145 string type_name = templateInstantiationDeclaration->get_name();
3146#if 0
3147 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgTemplateInstantiationDecl: type_name = %s \n",type_name.c_str());
3148#endif
3149 string className = string("scope_") + scope + "_type_name_" + type_name;
3150
3151 // Note that trimSpaces is defined in the name mangling support.
3152 // string compressedClassName = trimSpaces(className);
3153 // string compressedClassName = SageInterface::get_name(templateInstantiationDeclaration);
3154 // ROSE_UTIL_API std::string copyEdit(const std::string& inputString, const std::string & oldToken, const std::string & newToken);
3155
3156 // We need to turn this template instatiation name into a name that can be used as a C++ identifier.
3157 string compressedClassName = StringUtility::copyEdit(className," ","");
3158 compressedClassName = StringUtility::copyEdit(compressedClassName,"<","_abs_");
3159 compressedClassName = StringUtility::copyEdit(compressedClassName,">","_abe_");
3160 compressedClassName = StringUtility::copyEdit(compressedClassName,",","_comma_");
3161 compressedClassName = StringUtility::copyEdit(compressedClassName,"*","_star_");
3162 compressedClassName = StringUtility::copyEdit(compressedClassName,"&","_ref_");
3163#if 0
3164 printf ("className = %s compressedClassName = %s \n",className.c_str(),compressedClassName.c_str());
3165#endif
3166#if 0
3167 printf ("templateInstantiationDeclaration->get_scope() = %p = %s scope = %s \n",
3168 templateInstantiationDeclaration->get_scope(),templateInstantiationDeclaration->get_scope()->class_name().c_str(),scope.c_str());
3169#endif
3170 // s = className;
3171 s = compressedClassName;
3172#if 0
3173 printf ("Exiting as a test! \n");
3174 ROSE_ABORT();
3175#endif
3176 break;
3177 }
3178
3179 case V_SgFunctionDeclaration:
3180 case V_SgTemplateFunctionDeclaration:
3181 case V_SgTemplateInstantiationFunctionDecl:
3182 {
3183 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declaration);
3184 ROSE_ASSERT(functionDeclaration != NULL);
3185#if 0
3186 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgFunctionDeclaration: not implemented \n");
3187#endif
3188 // We might at some point want the qualified name.
3189 string original_name = functionDeclaration->get_name();
3190
3191 string function_name_part = mangleFunctionName(original_name,"return_type");
3192 string function_name = string("scope_") + scope + "_function_name_" + function_name_part;
3193
3194 // DQ (3/16/2016): Detect name collisions so that we can
3195 // std::map<std::string,int> dsl_attribute_name_collision_map;
3196 if (local_name_collision_map.find(function_name) == local_name_collision_map.end())
3197 {
3198 local_name_collision_map.insert(pair<string,int>(function_name,0));
3199 }
3200 else
3201 {
3202 local_name_collision_map[function_name]++;
3203
3204 int count = local_name_collision_map[function_name];
3205#if 0
3206 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3207#endif
3208 function_name += StringUtility::numberToString(count);
3209 }
3210
3211 s = function_name;
3212#if 0
3213 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgFunctionDeclaration: Exiting as a test! \n");
3214 ROSE_ABORT();
3215#endif
3216 break;
3217 }
3218
3219 case V_SgMemberFunctionDeclaration:
3220 case V_SgTemplateMemberFunctionDeclaration:
3221 case V_SgTemplateInstantiationMemberFunctionDecl:
3222 {
3223 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(declaration);
3224 ROSE_ASSERT(memberFunctionDeclaration != NULL);
3225#if 0
3226 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier_support(): case SgMemberFunctionDeclaration: not implemented \n");
3227#endif
3228 // We might at some point want the qualified name.
3229 string original_name = memberFunctionDeclaration->get_name();
3230
3231 // string member_function_name = memberFunctionDeclaration->get_mangled_name();
3232 // string member_function_name = memberFunctionDeclaration->get_qualified_name();
3233 // string member_function_name = SageInterface::get_name(memberFunctionDeclaration);
3234 // string member_function_scope = SageInterface::get_name(memberFunctionDeclaration->get_scope());
3235 string member_function_name_part = mangleFunctionName(original_name,"return_type");
3236 // string member_function_name = string("scope_") + member_function_scope + "_function_name_" + member_function_name_part;
3237 string member_function_name = string("scope_") + scope + "_member_function_name_" + member_function_name_part;
3238
3239 // DQ (3/16/2016): Detect name collisions so that we can
3240 // std::map<std::string,int> dsl_attribute_name_collision_map;
3241 if (local_name_collision_map.find(member_function_name) == local_name_collision_map.end())
3242 {
3243 local_name_collision_map.insert(pair<string,int>(member_function_name,0));
3244 }
3245 else
3246 {
3247 local_name_collision_map[member_function_name]++;
3248
3249 int count = local_name_collision_map[member_function_name];
3250#if 0
3251 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Collision count = %d \n",count);
3252#endif
3253 member_function_name += StringUtility::numberToString(count);
3254 }
3255
3256 s = member_function_name;
3257#if 0
3258 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): case SgMemberFunctionDeclaration: Exiting as a test! \n");
3259 ROSE_ABORT();
3260#endif
3261 break;
3262 }
3263
3264 default:
3265 {
3266 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): Unsupported declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3267// ROSE_ASSERT(false);
3268 }
3269 }
3270
3271#if 0
3272 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3273#endif
3274#if 0
3275 if (s != "")
3276 {
3277 printf ("In SageInterface::generateUniqueNameForUseAsIdentifier(): s = %s \n",s.c_str());
3278 }
3279#endif
3280
3281#if 0
3282 printf ("Exiting as a test! \n");
3283 ROSE_ABORT();
3284#endif
3285
3286 return s;
3287 }
3288
3289// Generate unique name for use as a class name for the generated attribute classes.
3290// std::string AttributeGeneratorTraversal::generateUniqueNameForUseAsIdentifier ( SgDeclarationStatement* declaration )
3291// std::string AttributeGeneratorTraversal::generateUniqueName ( SgDeclarationStatement* declaration )
3292std::string
3294 {
3295 // DQ (3/21/2016): The support for unique name generation for use across translation
3296 // units is not refactored into the SageInterface.
3297 // string s = SageInterface::generateUniqueNameForUseAsIdentifier(declaration);
3298 string s;
3299
3300#if 0
3301 printf ("In generateUniqueNameForUseAsIdentifier(): evaluating declaration = %p = %s \n",declaration,declaration->class_name().c_str());
3302#endif
3303
3304 ROSE_ASSERT(local_node_to_name_map.empty() == false);
3305 ROSE_ASSERT(local_name_to_node_map.empty() == false);
3306
3308 {
3310 }
3311 else
3312 {
3313 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3314 if (definingDeclaration != NULL)
3315 {
3316#if 0
3317 printf ("In generateUniqueName(): Using the defining declaration = %p since %p was not in the map \n",definingDeclaration,declaration);
3318#endif
3319 // s = generateUniqueName(definingDeclaration);
3320 s = generateUniqueNameForUseAsIdentifier_support(definingDeclaration);
3321 }
3322 else
3323 {
3324 // Note that builtin functions will not have a defining declaration.
3325 printf ("Warning: defining declaration not in SageInterface::local_node_to_name_map: declaration = %p = %s using name = %s \n",
3326 declaration,declaration->class_name().c_str(),SageInterface::get_name(declaration).c_str());
3327 // ROSE_ASSERT(false);
3328
3329 // If there is no defining declaration then go ahead and use the non-defining one.
3330 // s = SageInterface::get_name(declaration);
3331 SgDeclarationStatement* nondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3332 ROSE_ASSERT(nondefiningDeclaration != NULL);
3333 s = generateUniqueNameForUseAsIdentifier_support(nondefiningDeclaration);
3334 }
3335 }
3336
3337#if 0
3338 printf ("Exiting as a test! \n");
3339 ROSE_ABORT();
3340#endif
3341
3342 return s;
3343 }
3344
3345
3346void
3348 {
3349 ROSE_ASSERT(astNode != NULL);
3350
3351 ROSE_ASSERT(local_name_collision_map.empty() == true);
3352 ROSE_ASSERT(local_name_to_node_map.empty() == true);
3353 ROSE_ASSERT(local_node_to_name_map.empty() == true);
3354
3355 // Preorder traversal to uniquely name specific declarations (SgClassDeclaration and SgFunctionDeclaration IR nodes).
3356 class UniqueNameTraversal : public AstSimpleProcessing
3357 {
3358 public:
3359 void visit (SgNode* node)
3360 {
3361 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
3362 if (decl != NULL)
3363 {
3364 SgClassDeclaration* classDeclaration = isSgClassDeclaration(decl);
3365 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(decl);
3366 if (classDeclaration != NULL || functionDeclaration != NULL)
3367 {
3369 local_name_to_node_map.insert(pair<string,SgNode*>(s,decl));
3370 local_node_to_name_map.insert(pair<SgNode*,string>(decl,s));
3371 }
3372 }
3373 }
3374 };
3375
3376 // Now buid the traveral object and call the traversal (preorder) on the function definition.
3377 UniqueNameTraversal traversal;
3378 traversal.traverse(astNode, preorder);
3379 }
3380
3381
3382
3385 {
3386 SgMemberFunctionDeclaration* defaultConstructor = NULL;
3387
3388 ROSE_ASSERT(classDeclaration != NULL);
3389 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3390 ROSE_ASSERT(definingDeclaration != NULL);
3391 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3392
3393 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3394 // would be associated with a class declaration but no definition would exist).
3395 if (definingClassDeclaration != NULL)
3396 {
3397 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3398 ROSE_ASSERT(classDefinition != NULL);
3399
3400 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3401 while ( i != classDefinition->get_members().end() )
3402 {
3403 // Check the parent pointer to make sure it is properly set
3404 ROSE_ASSERT( (*i)->get_parent() != NULL);
3405 ROSE_ASSERT( (*i)->get_parent() == classDefinition);
3406
3407 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3408 if (memberFunction != NULL)
3409 {
3410 // printf ("memberFunction = %p = %s \n",memberFunction,memberFunction->get_name().str());
3411 if ( memberFunction->get_specialFunctionModifier().isConstructor() == true )
3412 defaultConstructor = memberFunction;
3413 }
3414
3415 // iterate through the class members
3416 i++;
3417 }
3418 }
3419
3420 // This should be true for the specific case that we are currently debugging!
3421 // ROSE_ASSERT(defaultConstructor != NULL);
3422
3423 return defaultConstructor;
3424 }
3425
3428 {
3429 SgMemberFunctionDeclaration* defaultDestructor = NULL;
3430
3431 ROSE_ASSERT(classDeclaration != NULL);
3432 SgDeclarationStatement* definingDeclaration = classDeclaration->get_definingDeclaration();
3433 if (definingDeclaration != NULL)
3434 {
3435 ROSE_ASSERT(definingDeclaration != NULL);
3436 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(definingDeclaration);
3437
3438 // Note that not all class declarations have to have a defining declaration (e.g. "~int()"
3439 // would be associated with a class declaration but no definition would exist).
3440 if (definingClassDeclaration != NULL)
3441 {
3442 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3443 ROSE_ASSERT(classDefinition != NULL);
3444
3445 SgDeclarationStatementPtrList::iterator i = classDefinition->get_members().begin();
3446 while ( i != classDefinition->get_members().end() )
3447 {
3448 // Check the parent pointer to make sure it is properly set
3449 SgNode* i_parent = (*i)->get_parent();
3450 ROSE_ASSERT(i_parent != NULL);
3451
3452 // DQ (11/1/2005): Note that a template instantiation can have a parent which is the
3453 // variable which forced it's instantiation. Since it does not really exist in the
3454 // source code explicitly (it is compiler generated) this is as reasonable as anything else.
3455 if ( i_parent != classDefinition )
3456 {
3457 printf ("Error: (*i)->get_parent() = %p = %s \n",i_parent,i_parent->class_name().c_str());
3458 printf ("(*i) = %p = %s = %s \n",*i,(*i)->class_name().c_str(),(*i)->unparseToString().c_str());
3459 (*i)->get_file_info()->display("Called from SageInterface::getDefaultDestructor: debug");
3460 }
3461 ROSE_ASSERT( i_parent == classDefinition);
3462
3463 SgMemberFunctionDeclaration* memberFunction = isSgMemberFunctionDeclaration(*i);
3464 if (memberFunction != NULL)
3465 {
3466 if ( memberFunction->get_specialFunctionModifier().isDestructor() == true )
3467 defaultDestructor = memberFunction;
3468 }
3469
3470 // iterate through the class members
3471 i++;
3472 }
3473 }
3474 }
3475
3476 return defaultDestructor;
3477 }
3478
3479
3480
3481bool
3482SageInterface::addDefaultConstructorIfRequired ( SgClassType* classType, int physical_file_id /* = Sg_File_Info::TRANSFORMATION_FILE_ID */ )
3483 {
3484 // DQ (11/9/2020): Added function to support adding a default constructor definition to a class
3485 // if it does not have a default constructor, but has any other constructor that would prevent
3486 // a compiler generated default constructor from being generated by the compiler.
3487
3488#define DEBUG_ADD_DEFAULT_CONSTRUCTOR 0
3489
3490 // Note the physical_file_id is so that it can be marked to be unparsed when header file unparsing is active.
3491
3492 ASSERT_not_null(classType);
3493
3494 bool returnValue = false;
3495
3496 // To setup this transformation we need to see if there is a default constructor in the associated class.
3497 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
3498 ROSE_ASSERT(classDeclaration != NULL);
3499 SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(classDeclaration->get_definingDeclaration());
3500 ROSE_ASSERT(definingClassDeclaration != NULL);
3501 SgClassDefinition* classDefinition = definingClassDeclaration->get_definition();
3502 ROSE_ASSERT(classDefinition != NULL);
3503
3504 SgDeclarationStatementPtrList & declarationList = classDefinition->get_members();
3505
3506 bool foundConstructor = false;
3507 bool foundDefaultConstructor = false;
3508
3509#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3510 printf ("In addDefaultConstructorIfRequired(): class name = %s \n",classDeclaration->get_name().str());
3511#endif
3512
3513 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
3514 while (i != declarationList.end())
3515 {
3516 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(*i);
3517 if (memberFunctionDeclaration != NULL)
3518 {
3519 bool isConstructor = memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
3520 if (isConstructor == true)
3521 {
3522 foundConstructor = true;
3523
3524#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3525 printf ("Found a constructor! \n");
3526#endif
3527 SgFunctionParameterList* functionParameterList = memberFunctionDeclaration->get_parameterList();
3528 ROSE_ASSERT(functionParameterList != NULL);
3529
3530 // DQ (7/19/2021): Fixed to allow for previously found default constructor to be registered as found.
3531 // foundDefaultConstructor = (functionParameterList->get_args().size() == 0);
3532 foundDefaultConstructor = ((foundDefaultConstructor == true) || (functionParameterList->get_args().size() == 0));
3533
3534#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3535 if (foundDefaultConstructor == true)
3536 {
3537 printf ("Found a default constructor! \n");
3538 }
3539 else
3540 {
3541 printf ("This is not a default constructor: functionParameterList->get_args().size() = %zu \n",functionParameterList->get_args().size());
3542 }
3543#endif
3544 }
3545 else
3546 {
3547#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3548 printf ("This is not a constructor \n");
3549#endif
3550 }
3551 }
3552
3553 i++;
3554 }
3555
3556#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3557 printf ("foundConstructor = %s \n",foundConstructor ? "true" : "false");
3558 printf ("foundDefaultConstructor = %s \n",foundDefaultConstructor ? "true" : "false");
3559#endif
3560
3561 if (foundConstructor == true)
3562 {
3563 // Since there is at least one constructor, we can't rely on compiler generated constructors.
3564#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3565 printf ("Since there is at least one constructor, we can't rely on compiler generated constructors \n");
3566#endif
3567 if (foundDefaultConstructor == true)
3568 {
3569 // We can use the existing default constructor.
3570#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3571 printf ("We can use the existing default constructor (no need to build one) \n");
3572#endif
3573 }
3574 else
3575 {
3576 // We don't have a default constructor, so we need to build one explicitly, and insert it into the class definition.
3577
3578#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3579 printf ("########################################################### \n");
3580 printf ("Need to build a default constructor in the associated class \n");
3581#endif
3582 SgMemberFunctionDeclaration* constructorDeclaration = SageBuilder::buildDefaultConstructor(classType);
3583 ROSE_ASSERT(constructorDeclaration != NULL);
3584
3585#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3586 printf (" --- constructorDeclaration = %p = %s name = %s \n",constructorDeclaration,constructorDeclaration->class_name().c_str(),constructorDeclaration->get_name().str());
3587#endif
3588 ROSE_ASSERT (constructorDeclaration->get_declarationModifier().get_accessModifier().isPublic() == true);
3589
3590 classDefinition->prepend_statement(constructorDeclaration);
3591
3592 // constructorDeclaration->set_parent(classDefinition);
3593 ROSE_ASSERT(constructorDeclaration->get_parent() != NULL);
3594
3595 // int physical_file_id = variableDeclaration->get_startOfConstruct()->get_physical_file_id();
3596 markSubtreeToBeUnparsed(constructorDeclaration,physical_file_id);
3597
3598 returnValue = true;
3599#if 0
3600 constructorDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3601 constructorDeclaration->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3602
3603 // We also need to set the source position of the function definition, else the
3604 // function declaration will not be output.
3605 ROSE_ASSERT(constructorDeclaration->get_definition() != NULL);
3606 ROSE_ASSERT(constructorDeclaration->get_definition()->get_startOfConstruct() != NULL);
3607 ROSE_ASSERT(constructorDeclaration->get_definition()->get_endOfConstruct() != NULL);
3608 constructorDeclaration->get_definition()->get_startOfConstruct()->set_physical_file_id(physical_file_id);
3609 constructorDeclaration->get_definition()->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
3610#endif
3611
3612#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3613 printf ("DONE: Need to build a default constructor in the associated class \n");
3614 printf ("################################################################# \n");
3615#endif
3616#if 0
3617 printf ("Exiting as a test! \n");
3618 ROSE_ABORT();
3619#endif
3620 }
3621 }
3622 else
3623 {
3624 // No constructors found, so we don't need to add an explicit default constructor.
3625
3626#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3627 printf ("No constructors found, so we don't need to add an explicit default constructor \n");
3628#endif
3629 }
3630
3631#if DEBUG_ADD_DEFAULT_CONSTRUCTOR
3632 printf ("Leaving addDefaultConstructorIfRequired(): returnValue = %s \n",returnValue ? "true" : "false");
3633#endif
3634
3635 return returnValue;
3636 }
3637
3638
3639
3640
3641void
3643 {
3644 // DQ (6/27/2005): This function outputs the global table of function type symbols
3645 // it is built during the EDG/Sage translation phase, and it built initially with
3646 // the EDG names of all instantiated templates. At a later phase (incomplete at
3647 // the moment) the AST fixup rebuilds the table to use the modified template names
3648 // (that is mangled names built from the modified template names used in Sage III).
3649
3650 // DQ (1/31/2006): Modified to build all types in the memory pools
3651 // extern SgFunctionTypeTable Sgfunc_type_table;
3652 // Sgfunc_type_table.print_functypetable();
3653 ROSE_ASSERT(SgNode::get_globalFunctionTypeTable() != NULL);
3654 SgNode::get_globalFunctionTypeTable()->print_functypetable();
3655 }
3656
3657void
3659 {
3660 // This simplifies how the traversal is called!
3661 OutputLocalSymbolTables astTraversal;
3662
3663 // I think the default should be preorder so that the interfaces would be more uniform
3664 astTraversal.traverse(node,preorder);
3665 }
3666
3667void
3669 {
3670 // DQ (6/27/2005): Output the local symbol table from each scope.
3671 // printf ("node = %s \n",node->sage_class_name());
3672
3673#if 0
3674 printf ("Exiting as a test! \n");
3675 ROSE_ABORT();
3676#endif
3677
3678 SgScopeStatement* scope = isSgScopeStatement(node);
3679 if (scope != NULL)
3680 {
3681 // SgSymbolTable* symbolTable = scope->get_symbol_table();
3682 // ROSE_ASSERT(symbolTable != NULL);
3683
3684 printf ("Symbol Table from %p = %s at: \n",scope,scope->sage_class_name());
3685 scope->get_file_info()->display("Symbol Table Location (Called from SageInterface::OutputLocalSymbolTables::visit())");
3686 // symbolTable->print("Called from SageInterface::OutputLocalSymbolTables::visit()");
3687 scope->print_symboltable("Called from SageInterface::OutputLocalSymbolTables::visit()");
3688 }
3689 }
3690
3691#if 0
3692// DQ (8/28/2005): This is already a member function of the SgFunctionDeclaration
3693// (so that it can handle template functions and member functions)
3694
3695// DQ (8/27/2005):
3696bool
3697SageInterface::isTemplateMemberFunction( SgTemplateInstantiationMemberFunctionDecl* memberFunctionDeclaration )
3698 {
3699 // This function determines if the member function is associated with a template
3700 // or just a template class (where it is a normal non-template member function).
3701
3702 bool result = false;
3703
3704 result = memberFunctionDeclaration->isTemplateFunction();
3705
3706 return result;
3707 }
3708#endif
3709
3710// DQ (8/27/2005):
3711bool
3713 {
3714 // This function determines if the template declaration associated withthis member function instantiation is
3715 // defined in the class or outside of the class.
3716
3717 bool result = false;
3718
3719#if 0
3720 // Check if this is a template or non-template member function
3721 if (isTemplateMemberFunction(memberFunctionDeclaration) == true)
3722 {
3723 SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3724 printf ("templateDeclaration = %p parent of templateDeclaration = %p \n",templateDeclaration,templateDeclaration->get_parent());
3725
3726 // SgTemplateInstantiationDecl* classTemplateInstantiation = memberFunctionDeclaration->get_class_scope()->get_declaration();
3727 SgClassDeclaration* classDeclaration = memberFunctionDeclaration->get_class_scope()->get_declaration();
3728 ROSE_ASSERT(classDeclaration != NULL);
3729 SgTemplateInstantiationDecl* classTemplateInstantiation = isSgTemplateInstantiationDecl(classDeclaration);
3730
3731 if (classTemplateInstantiation != NULL)
3732 {
3733 SgTemplateDeclaration* classTemplateDeclaration = classTemplateInstantiation->get_templateDeclaration();
3734 if (classTemplateDeclaration != NULL && classTemplateDeclaration != templateDeclaration)
3735 {
3736 result = true;
3737 }
3738 }
3739 }
3740#endif
3741
3742 // Alternative approach
3743 // SgTemplateDeclaration* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3744 SgDeclarationStatement* templateDeclaration = memberFunctionDeclaration->get_templateDeclaration();
3745// printf ("In templateDefinitionIsInClass(): templateDeclaration = %p parent of templateDeclaration = %p = %s \n",templateDeclaration,
3746// templateDeclaration->get_parent(),templateDeclaration->get_parent()->class_name().c_str());
3747
3748 if (templateDeclaration != NULL && templateDeclaration->get_parent() != NULL)
3749 {
3750 SgScopeStatement* parentScope = isSgScopeStatement(templateDeclaration->get_parent());
3751 if (isSgClassDefinition(parentScope) != NULL)
3752 {
3753 result = true;
3754 }
3755 }
3756
3757 return result;
3758 }
3759#if 0
3761generateUniqueDeclaration ( SgDeclarationStatement* declaration )
3762 {
3763 // DQ (10/11/2007): This is no longer used.
3764 printf ("Error: This is no longer used. \n");
3765 ROSE_ABORT();
3766
3767 // Get the defining or first non-defining declaration so that we can use it as a key to know
3768 // when we have found the same function. So we don't count a redundant forward declaration
3769 // found outside of the class as matching the first non-defining declaration or the defining
3770 // declaration in the class by mistake. All declarations share the same firstNondefining
3771 // declaration and defining declaration so either could be a key declaration, but there are
3772 // times when either one of then (but not both) can be NULL (function defined withouth forward
3773 // declaration or not defined at all).
3774 SgDeclarationStatement* firstNondefiningDeclaration = declaration->get_firstNondefiningDeclaration();
3775 SgDeclarationStatement* definingDeclaration = declaration->get_definingDeclaration();
3776 SgDeclarationStatement* keyDeclaration = NULL;
3777 if (firstNondefiningDeclaration != NULL)
3778 keyDeclaration = firstNondefiningDeclaration;
3779 else
3780 keyDeclaration = definingDeclaration;
3781 ROSE_ASSERT(keyDeclaration != NULL);
3782
3783 return keyDeclaration;
3784 }
3785#endif
3788{
3789 string pragmaString = pragmaDeclaration->get_pragma()->get_pragma();
3790 istringstream istr(pragmaString);
3791 std::string key;
3792 istr >> key;
3793 return key;
3794}
3795
3797// TODO: move all Omp*statement under a parent SgOmpStatement
3799{
3800 ROSE_ASSERT (n != NULL);
3801 bool result = false;
3802 if (isSgOmpBarrierStatement(n)||
3803 isSgOmpBodyStatement(n)||
3804 isSgOmpDeclareSimdStatement(n) ||
3805 isSgOmpFlushStatement(n)||
3806 isSgOmpThreadprivateStatement(n)||
3807 isSgOmpTaskwaitStatement(n) )
3808 result = true;
3809
3810 return result;
3811
3812}
3813// DQ (8/28/2005):
3814bool
3816 {
3817 // This function looks for any other function that might overload the input function.
3818 // for member functions we only look in the scope where the member function is defined.
3819 // for non-member functions we look only in the scope where the function is declared.
3820
3821 // Note that there are scenarios where this approach of searching only these locations
3822 // might not catch an overloaded function.
3823 // * member functions:
3824 // - overloaded functions might be declared in base classes
3825 // * non-member functions:
3826 // - function declarations might be friend functions in classes
3827 // - functions might be declared in differen namespace definitions
3828 // (SgNamespaceDefinitionStatement), since a namespace in re-entrant
3829 // and can have many namespace declarations and definitions.
3830
3831 // bool result = false;
3832 int counter = 0;
3833
3834 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
3835 if (memberFunctionDeclaration != NULL)
3836 {
3837 // This is a member function declaration
3838
3839 // DQ (10/11/2007): Fix this to NOT use the generateUniqueDeclaration() function.
3840 // Generate a key to use for comparision (avoids false positives)
3841 // SgMemberFunctionDeclaration* keyDeclaration = isSgMemberFunctionDeclaration(generateUniqueDeclaration(functionDeclaration));
3842 // ROSE_ASSERT(keyDeclaration != NULL);
3843
3844 SgScopeStatement * scope = memberFunctionDeclaration->get_scope();
3845 ROSE_ASSERT(scope != NULL);
3846
3847 // TV (09/17/2018): ROSE-1378
3848 if (isSgDeclarationScope(scope)) {
3849 printf("TODO SageInterface::isOverloaded case when scope is SgDeclarationScope. See ROSE-1378.\n");
3850 return false;
3851 }
3852
3853 // Get the class definition
3854 SgClassDefinition* classDefinition =
3855 isSgClassDefinition(memberFunctionDeclaration->get_scope());
3856 ROSE_ASSERT(classDefinition != NULL);
3857
3858 // Get the class declaration associated with the class definition
3859 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classDefinition->get_declaration());
3860 ROSE_ASSERT(classDeclaration != NULL);
3861
3862 // Get the list of member declarations in the class
3863 SgDeclarationStatementPtrList & memberList = classDefinition->get_members();
3864#if 0
3865 // DQ (10/11/2007): Fix this function better by checking for more than one member function declaration in the class definition.
3866 printf (" memberList.size() = %" PRIuPTR " \n",memberList.size());
3867#endif
3868 for (SgDeclarationStatementPtrList::iterator i = memberList.begin(); i != memberList.end(); i++)
3869 {
3870#if 0
3871 printf (" counter = %d declaration = %p = %s \n",counter,*i,(*i)->class_name().c_str());
3872#endif
3873 SgMemberFunctionDeclaration* tempMemberFunction = isSgMemberFunctionDeclaration(*i);
3874 SgTemplateDeclaration* tempTemplateDeclaration = isSgTemplateDeclaration(*i);
3875
3876 // Member functions could be overloaded
3877 if (tempMemberFunction != NULL)
3878 {
3879#if 0
3880 // 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.
3881 // Check using the key declaration
3882 if ( keyDeclaration == generateUniqueDeclaration(tempMemberFunction) )
3883 {
3884#if 0
3885 printf ("Skipping the case of keyDeclaration == generateUniqueDeclaration(tempMemberFunction) = %p \n",keyDeclaration);
3886#endif
3887 continue;
3888 }
3889#endif
3890 ROSE_ASSERT(tempMemberFunction->get_name() != "");
3891#if 0
3892 printf (" tempMemberFunction = (name) %s = (qualified) %s \n",
3893 tempMemberFunction->get_name().str(),
3894 tempMemberFunction->get_qualified_name().str());
3895#endif
3896 if (tempMemberFunction->get_name() == memberFunctionDeclaration->get_name())
3897 {
3898#if 0
3899 printf (" Found a matching overloaded member function! \n");
3900#endif
3901 // result = true;
3902 counter++;
3903 }
3904 }
3905 else
3906 {
3907 // Or templates could be overloaded, but nothing else.
3908 if (tempTemplateDeclaration != NULL)
3909 {
3910 // If this is a template declaration, it could be a template
3911 // declaration for an overloaded member function of the same name.
3912#if 0
3913 // printf ("keyDeclaration->get_name() = %s \n",keyDeclaration->get_name().str());
3914 printf ("tempTemplateDeclaration->get_name() = %s \n",tempTemplateDeclaration->get_name().str());
3915#endif
3916 if (memberFunctionDeclaration->get_name() == tempTemplateDeclaration->get_name())
3917 {
3918#if 0
3919 printf (" Found a matching overloaded member function! \n");
3920#endif
3921 // result = true;
3922 counter++;
3923 }
3924 }
3925 else
3926 {
3927 // DQ (10/12/2007): Could friend functions defined in a class be overloaded? Need to check this!
3928 if (functionDeclaration->variantT() == V_SgFunctionDeclaration)
3929 {
3930 printf ("In SageInterface::isOverloaded(): could friend functions be overloaded in a class? \n");
3931 }
3932 }
3933 }
3934
3935 // If we have detected two, so we have an overloaded function.
3936 if (counter > 1)
3937 break;
3938 }
3939 }
3940 else
3941 {
3942 // This is a non-member function declaration
3943 printf ("In SageInterface::isOverloaded(): case of non-member function not yet implemented! \n");
3944 ROSE_ABORT();
3945 }
3946
3947 // DQ (10/11/2007): Fixup to use the counter and consider more than 1 function with the same name an overloaded member function.
3948 // This might be a problem for friend functions, so test this separately.
3949 // return result;
3950 return (counter > 1);
3951 }
3952
3953
3954
3955
3958 {
3959 // DQ (9/6/2005): This function builds a copy of the input function for the
3960 // construction of a forward declaration of the function. Required in the
3961 // instantiated functions definition is to be output as a specialization by ROSE.
3962 // Since the shallow copy mechanism will cause IR nodes to be shared, we have
3963 // to fix it up with deep copies of the parameter list and the CtorInitializerList.
3964
3965 ROSE_ASSERT(memberFunctionInstantiation != NULL);
3966
3967#if 0
3968 printf ("buildForwardFunctionDeclaration: Member function = %p = %s = definition = %p \n",
3969 memberFunctionInstantiation,
3970 memberFunctionInstantiation->get_name().str(),
3971 memberFunctionInstantiation->get_definition());
3972 memberFunctionInstantiation->get_file_info()->display("memberFunctionInstantiation: debug");
3973#endif
3974
3975 // This is a better implementation using a derived class from SgCopyHelp to control the
3976 // copying process (skipping the copy of any function definition). This is a variable
3977 // declaration with an explicitly declared class type.
3978 class NondefiningFunctionDeclarationCopyType : public SgCopyHelp
3979 {
3980 // DQ (9/26/2005): This class demonstrates the use of the copy mechanism
3981 // within Sage III (originally designed and implemented by Qing Yi).
3982 // One problem with it is that there is no context information permitted.
3983
3984 public:
3985 virtual SgNode *copyAst(const SgNode *n)
3986 {
3987 // If still NULL after switch then make the copy
3988 SgNode* returnValue = NULL;
3989
3990 switch(n->variantT())
3991 {
3992 // DQ (10/21/2007): Now that s bug is fixed in the SgDeclarationStatement::fixupCopy()
3993 // member function, I think we might not need this case.
3994
3995 // Don't copy the associated non-defining declaration when building a function prototype!
3996 case V_SgFunctionDeclaration:
3997 case V_SgMemberFunctionDeclaration:
3998 case V_SgTemplateInstantiationFunctionDecl:
3999 case V_SgTemplateInstantiationMemberFunctionDecl:
4000 {
4001 // printf ("Skip copying an associated non-defining declaration if it is present \n");
4002 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(n);
4003 ROSE_ASSERT(functionDeclaration != NULL);
4004 if (functionDeclaration == functionDeclaration->get_definingDeclaration())
4005 {
4006 // This is the defining declaration (make a shallow copy)
4007 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the DEFINING declaration! \n");
4008 // return const_cast<SgNode *>(n);
4009 returnValue = const_cast<SgNode *>(n);
4010 }
4011 else
4012 {
4013 // This is the non-defining declaration where we want to make a deep copy.
4014 // printf ("In NondefiningFunctionDeclarationCopyType::copyAst(): This is the NONDEFINING declaration! \n");
4015 }
4016
4017 break;
4018 }
4019
4020 // Don't copy the function definitions (roughly the body of the function)
4021 case V_SgFunctionDefinition:
4022 {
4023 printf ("Skip copying the function definition if it is present \n");
4024 // return const_cast<SgNode *>(n);
4025 returnValue = const_cast<SgNode *>(n);
4026 break;
4027 }
4028
4029 default:
4030 {
4031 // Nothing to do here
4032 break;
4033 }
4034 }
4035
4036 // return n->copy(*this);
4037
4038 // If not set at this point then make the copy!
4039 if (returnValue == NULL)
4040 returnValue = n->copy(*this);
4041
4042 ROSE_ASSERT(returnValue != NULL);
4043 return returnValue;
4044 }
4045 } nondefiningFunctionDeclarationCopy;
4046
4047 // DQ (10/20/2007): The more accurate copy mechanism now builds us a defining declaration to go with the non-defining declaration!
4048 // 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!
4049 // delete copyOfMemberFunction->get_definingDeclaration();
4050 if (memberFunctionInstantiation->get_definition() != NULL)
4051 {
4052 printf ("\n\nNEED TO REMOVE POINTERS IN THE NON-DEFINING DECLARATION TO THE SgClassDefinition objects. \n");
4053 ROSE_ABORT();
4054
4055 // If we see the assertion above fail then we might want to use this code:
4056 ROSE_ASSERT( memberFunctionInstantiation != memberFunctionInstantiation->get_definingDeclaration() );
4057 memberFunctionInstantiation->set_definition(NULL);
4058 }
4059 SgNode* copyOfMemberFunctionNode = memberFunctionInstantiation->copy(nondefiningFunctionDeclarationCopy);
4060 SgTemplateInstantiationMemberFunctionDecl* copyOfMemberFunction = static_cast<SgTemplateInstantiationMemberFunctionDecl*>(copyOfMemberFunctionNode);
4061
4062 // printf ("\n\nHOW DO WE KNOW WHEN TO NOT COPY THE DEFINING DECLARATION SO THAT WE CAN JUST BUILD A FUNCTION PROTOTYPE! \n");
4063 // ROSE_ASSERT(false);
4064
4065#if 0
4066 printf ("copyOfMemberFunction->get_firstNondefiningDeclaration() = %p \n",copyOfMemberFunction->get_firstNondefiningDeclaration());
4067#endif
4068 // DQ (10/11/2007): The copy function sets the firstNondefiningDeclaration to itself if in the original declaration it had the
4069 // firstNondefiningDeclaration set to itself, this is incorrect in the case where we only make a copy of function declaration,
4070 // and causes the symbol table tests for get_declaration_associated_with_symbol() to fail because it uses the
4071 // firstNondefiningDeclaration which is not the one associated with the symbol in the parent scope. So reset the
4072 // firstNondefiningDeclaration in the copy of the member function.
4073 copyOfMemberFunction->set_firstNondefiningDeclaration(memberFunctionInstantiation->get_firstNondefiningDeclaration());
4074
4075#if 0
4076 printf ("memberFunctionInstantiation->get_firstNondefiningDeclaration() = %p \n",memberFunctionInstantiation->get_firstNondefiningDeclaration());
4077
4078 printf ("copyOfMemberFunction->isForward() = %s \n",copyOfMemberFunction->isForward() ? "true" : "false");
4079 printf ("memberFunctionInstantiation->isForward() = %s \n",memberFunctionInstantiation->isForward() ? "true" : "false");
4080#endif
4081#if 0
4082 printf ("memberFunctionInstantiation->isSpecialization() = %s \n",memberFunctionInstantiation->isSpecialization() ? "true" : "false");
4083 printf ("copyOfMemberFunctionNode = %p = %s = %s memberFunctionInstantiation->isSpecialization() = %s \n",
4084 copyOfMemberFunction,copyOfMemberFunction->class_name().c_str(),SageInterface::get_name(copyOfMemberFunction).c_str(),copyOfMemberFunction->isSpecialization() ? "true" : "false");
4085 copyOfMemberFunction->get_file_info()->display("copyOfMemberFunction: debug");
4086#endif
4087
4088 // Make sure that we have the same number of arguments on the copy that we build
4089 ROSE_ASSERT(memberFunctionInstantiation->get_args().size() == copyOfMemberFunction->get_args().size());
4090
4091 // DQ (11/5/2007): Additional tests
4092 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isOutputInCodeGeneration() == copyOfMemberFunction->get_startOfConstruct()->isOutputInCodeGeneration());
4093 ROSE_ASSERT(memberFunctionInstantiation->get_startOfConstruct()->isCompilerGenerated() == copyOfMemberFunction->get_startOfConstruct()->isCompilerGenerated());
4094
4095 ROSE_ASSERT(copyOfMemberFunction != NULL);
4096 return copyOfMemberFunction;
4097 }
4098
4099
4100void
4101supportForBaseTypeDefiningDeclaration ( SgSymbolTable* symbolTable, SgDeclarationStatement* declarationForType )
4102 {
4103 // DQ (10/14/2007): Supporting function for
4104
4105 ROSE_ASSERT(declarationForType != NULL);
4106
4107 // DQ (11/7/2007): Added more cases...
4108 switch(declarationForType->variantT())
4109 {
4110 // DQ (12/26/2012): Added support for templates.
4111 case V_SgTemplateInstantiationDecl:
4112 case V_SgTemplateClassDeclaration:
4113
4114 case V_SgClassDeclaration:
4115 {
4116 SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationForType);
4117 // SgSymbol* symbol = new SgClassSymbol(classDeclaration);
4118 SgSymbol* symbol = NULL;
4119 if (isSgTemplateClassDeclaration(declarationForType) != NULL)
4120 {
4121 symbol = new SgTemplateClassSymbol(classDeclaration);
4122 }
4123 else
4124 {
4125 symbol = new SgClassSymbol(classDeclaration);
4126 }
4127
4128 ROSE_ASSERT(symbol != NULL);
4129 SgName name = classDeclaration->get_name();
4130 symbolTable->insert(name,symbol);
4131 break;
4132 }
4133
4134 case V_SgEnumDeclaration:
4135 {
4136 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(declarationForType);
4137 SgSymbol* symbol = new SgEnumSymbol(enumDeclaration);
4138 ROSE_ASSERT(symbol != NULL);
4139 SgName name = enumDeclaration->get_name();
4140 symbolTable->insert(name,symbol);
4141 break;
4142 }
4143
4144 case V_SgFunctionDeclaration:
4145 {
4146 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(declarationForType);
4147 SgSymbol* symbol = new SgFunctionSymbol(functionDeclaration);
4148 ROSE_ASSERT(symbol != NULL);
4149 SgName name = functionDeclaration->get_name();
4150 symbolTable->insert(name,symbol);
4151 break;
4152 }
4153
4154 case V_SgMemberFunctionDeclaration:
4155 {
4156 SgMemberFunctionDeclaration* functionDeclaration = isSgMemberFunctionDeclaration(declarationForType);
4157 SgSymbol* symbol = new SgMemberFunctionSymbol(functionDeclaration);
4158 ROSE_ASSERT(symbol != NULL);
4159
4160 // printf ("In supportForBaseTypeDefiningDeclaration(): symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4161
4162 SgName name = functionDeclaration->get_name();
4163 symbolTable->insert(name,symbol);
4164 break;
4165 }
4166
4167 default:
4168 {
4169 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());
4170 ROSE_ABORT();
4171 }
4172 }
4173 }
4174
4175
4176void
4177supportForVariableLists ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgInitializedNamePtrList & variableList )
4178 {
4179 // DQ (11/1/2007): Added supporting function to refactor code.
4180 SgInitializedNamePtrList::iterator i = variableList.begin();
4181 while (i != variableList.end())
4182 {
4184 ROSE_ASSERT(variable != NULL);
4185 if (variable->get_scope() == scope)
4186 {
4187 // printf ("Scopes match, OK! \n");
4188 }
4189 else
4190 {
4191 if (SgProject::get_verbose() > 0)
4192 {
4193 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());
4194 }
4195 }
4196
4197 SgSymbol* symbol = new SgVariableSymbol(variable);
4198 ROSE_ASSERT(symbol != NULL);
4199 SgName name = variable->get_name();
4200 symbolTable->insert(name,symbol);
4201
4202 i++;
4203 }
4204 }
4205#if 0
4206// DQ (3/2/2014): Added a new interface function (used in the snippet insertion support).
4207void
4208SageInterface::supportForInitializedNameLists ( SgScopeStatement* scope, SgInitializedNamePtrList & variableList )
4209 {
4210 SgSymbolTable* symbolTable = scope->get_symbol_table();
4211 ROSE_ASSERT(symbolTable != NULL);
4212
4213 supportForVariableLists(scope,symbolTable,variableList);
4214 }
4215#endif
4216
4217void
4218supportForVariableDeclarations ( SgScopeStatement* scope, SgSymbolTable* symbolTable, SgVariableDeclaration* variableDeclaration )
4219 {
4220 // DQ (10/24/2007): Added supporting function to refactor code.
4221 SgInitializedNamePtrList & variableList = variableDeclaration->get_variables();
4222 supportForVariableLists(scope,symbolTable,variableList);
4223
4224 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4225 // that also force symbols to be built in the current scope!
4226 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4227 if (variableDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4228 {
4229 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4230 ROSE_ASSERT(symbolTable != NULL);
4231 ROSE_ASSERT(variableDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4232 supportForBaseTypeDefiningDeclaration ( symbolTable, variableDeclaration->get_baseTypeDefiningDeclaration() );
4233 }
4234 }
4235
4236void
4237supportForLabelStatements ( SgScopeStatement* scope, SgSymbolTable* symbolTable )
4238 {
4239 // Update the symbol table in SgFunctionDefinition with all the labels in the function.
4240
4241 std::vector<SgNode*> labelList = NodeQuery::querySubTree (scope,V_SgLabelStatement);
4242
4243 int numberOfLabels = labelList.size();
4244 for (int i=0; i < numberOfLabels; i++)
4245 {
4246 SgLabelStatement* labelStatement = isSgLabelStatement(labelList[i]);
4247
4248 ROSE_ASSERT(labelStatement != NULL);
4249 ROSE_ASSERT(labelStatement->get_scope() == scope);
4250
4251 SgSymbol* symbol = new SgLabelSymbol(labelStatement);
4252 ROSE_ASSERT(symbol != NULL);
4253
4254 // printf ("In SageInterface::rebuildSymbolTable() labelStatement = %p building a new SgLabelSymbol = %p \n",labelStatement,symbol);
4255
4256 SgName name = labelStatement->get_name();
4257 symbolTable->insert(name,symbol);
4258 }
4259 }
4260
4261
4262void
4264 {
4265 // This function is called from the implementation of the copy member functions.
4266
4267 ROSE_ASSERT(scope != NULL);
4268#if 0
4269 printf ("In SageInterface::rebuildSymbolTable(): Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4270#endif
4271#if 0
4272 printf ("Exiting as a test \n");
4273 ROSE_ABORT();
4274#endif
4275
4276 SgSymbolTable* symbolTable = scope->get_symbol_table();
4277
4278 if (symbolTable != NULL)
4279 {
4280 // This must be an empty symbol table!
4281 if (symbolTable->size() != 0)
4282 {
4283 printf ("symbolTable->size() = %d \n",symbolTable->size());
4284 }
4285 ROSE_ASSERT(symbolTable->size() == 0);
4286#if 0
4287 printf ("Symbol Table from %p = %s of size = %" PRIuPTR " \n",scope,scope->class_name().c_str(),symbolTable->size());
4288 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
4289#endif
4290 }
4291 else
4292 {
4293#if 0
4294 printf ("In SageInterface::rebuildSymbolTable(): No symbol table found \n");
4295#endif
4296 ROSE_ASSERT(symbolTable == NULL);
4297
4298 // DQ (10/8/2007): Build a new symbol table if there was not already one built.
4299 symbolTable = new SgSymbolTable();
4300
4301 ROSE_ASSERT(symbolTable != NULL);
4302 ROSE_ASSERT(symbolTable->get_table() != NULL);
4303
4304 // DQ (2/16/2006): Set this parent directly (now tested)
4305 symbolTable->set_parent(scope);
4306 ROSE_ASSERT(symbolTable->get_parent() != NULL);
4307
4308 scope->set_symbol_table(symbolTable);
4309 }
4310
4311 // 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.
4312 ROSE_ASSERT(scope->get_symbol_table() != NULL);
4313 ROSE_ASSERT(scope->get_symbol_table()->get_table() != NULL);
4314
4315 // This implements SgScopeStatement specific details (e.g function declarations have parameters and their declaration causes variable
4316 // symbols to be placed into the SgFunctionDefinition scope (but only for defining declarations).
4317 switch(scope->variantT())
4318 {
4319 case V_SgForStatement:
4320 {
4321 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4322 // printf ("Symbol tables could contain symbols outside of the inclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4323
4324 SgForStatement* forStatement = isSgForStatement(scope);
4325
4326 SgStatementPtrList::iterator i = forStatement->get_init_stmt().begin();
4327
4328 // printf ("i != forStatement->get_init_stmt().end() = %s \n",i != forStatement->get_init_stmt().end() ? "true" : "false");
4329
4330 while (i != forStatement->get_init_stmt().end())
4331 {
4332 // printf ("For statement initialization list: *i = %p = %s \n",*i,(*i)->class_name().c_str());
4333 SgVariableDeclaration* variableDeclarationInitializer = isSgVariableDeclaration(*i);
4334 if (variableDeclarationInitializer != NULL)
4335 {
4336 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4337 // 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());
4338 // ROSE_ASSERT(false);
4339 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationInitializer );
4340 }
4341
4342 i++;
4343 }
4344
4345 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(forStatement->get_test());
4346 if (variableDeclarationCondition != NULL)
4347 {
4348 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4349 // 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());
4350 // ROSE_ASSERT(false);
4351 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4352 }
4353
4354 return;
4355 break;
4356 }
4357
4358 case V_SgJovialForThenStatement:
4359 case V_SgMatlabForStatement:
4360 {
4361 return;
4362 break;
4363 }
4364
4365
4366 // DQ (12/23/2012): Added support for templates.
4367 case V_SgTemplateFunctionDefinition:
4368
4369 case V_SgFunctionDefinition:
4370 {
4371 // These scopes have their symbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4372 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4373
4374 // DQ (10/8/2007): If this is a SgFunctionDefinition, then include the parameters in the SgFunctionDeclaration.
4375 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
4376 if (functionDefinition != NULL)
4377 {
4378 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
4379 // printf ("In SageInterface::rebuildSymbolTable(): functionDefinition = %p functionDeclaration = %p \n",functionDefinition,functionDeclaration);
4380
4381 // 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!
4382 if (functionDeclaration != NULL)
4383 {
4384 // 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.
4385 if (functionDeclaration->isForward() == true)
4386 {
4387 printf ("ERROR: functionDeclaration = %p = %s = %s \n",functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
4388 printf (" --- functionDeclaration (get_name()) = %s \n",get_name(functionDeclaration).c_str());
4389 printf (" --- functionDeclaration (mangled name) = %s \n",functionDeclaration->get_mangled_name().str());
4390 SgMemberFunctionDeclaration* memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
4391 if (memberFunctionDeclaration != NULL)
4392 {
4393 printf ("memberFunctionDeclaration != NULL \n");
4394 }
4395 }
4396 ROSE_ASSERT(functionDeclaration->isForward() == false);
4397 SgInitializedNamePtrList & argumentList = functionDeclaration->get_args();
4398 supportForVariableLists(scope,symbolTable,argumentList);
4399 }
4400 else
4401 {
4402 // This happens in the copy function because the function definition is copied from the SgFunctionDeclaration
4403 // and only after the copy is made is the parent of the definition set to be the function declaration. Thus
4404 // the get_declaration() member function returns NULL.
4405 // printf ("There is no function declaration associated with this function definition! \n");
4406 // ROSE_ASSERT(functionDeclaration->isForward() == true);
4407 }
4408 }
4409
4410 // DQ (10/25/2007): Label symbols are now places into the SgFunctionDefinition (they have to be collected from the function).
4411 supportForLabelStatements(scope,symbolTable);
4412
4413 return;
4414 break;
4415 }
4416
4417 case V_SgIfStmt:
4418 {
4419 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4420 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4421
4422 SgIfStmt* ifStatement = isSgIfStmt(scope);
4423 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(ifStatement->get_conditional());
4424 if (variableDeclarationCondition != NULL)
4425 {
4426 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4427 // printf ("There is a variable declaration in the conditional, it needs to be added to the symbol table \n");
4428 // ROSE_ASSERT(false);
4429 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4430 }
4431 return;
4432 break;
4433 }
4434
4435 case V_SgSwitchStatement:
4436 {
4437 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4438 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4439
4440 SgSwitchStatement* switchStatement = isSgSwitchStatement(scope);
4441 SgVariableDeclaration* variableDeclarationSelector = isSgVariableDeclaration(switchStatement->get_item_selector());
4442 if (variableDeclarationSelector != NULL)
4443 {
4444 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4445 // printf ("There is a variable declaration in the item selector of the switch statement, it needs to be added to the symbol table \n");
4446
4447 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationSelector );
4448 }
4449 return;
4450 break;
4451 }
4452
4453 case V_SgWhileStmt:
4454 {
4455 // These scopes have their sysmbols split between the attached symbol table and the symbol tables in the SgBasicBlock data member(s).
4456 // commented out like for others, otherwise show up each time a While is being copied. Liao, 1/31/2008
4457 // printf ("Symbol tables could contain symbols outside of the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4458
4459 SgWhileStmt* whileStatement = isSgWhileStmt(scope);
4460 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(whileStatement->get_condition());
4461 if (variableDeclarationCondition != NULL)
4462 {
4463 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4464 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4465 // ROSE_ASSERT(false);
4466
4467 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4468 }
4469 return;
4470 break;
4471 }
4472
4473 case V_SgCatchOptionStmt:
4474 case V_SgDoWhileStmt:
4475 {
4476 // These scopes contain a SgBasicBlock as a data member and the scope is held there.
4477 // printf ("Symbol tables can must be computed by the enclosed body scope = %p = %s \n",scope,scope->class_name().c_str());
4478 return;
4479 break;
4480 }
4481
4482 // DQ (12/24/2012): Added support for templates.
4483 case V_SgTemplateClassDefinition:
4484
4485 case V_SgBasicBlock:
4486 case V_SgClassDefinition:
4487 case V_SgTemplateInstantiationDefn:
4488 case V_SgGlobal:
4489 case V_SgNamespaceDefinitionStatement:
4490 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
4491 {
4492 // printf ("Used the list of statements/declarations that are held deirectly by this scope \n");
4493 break;
4494 }
4495
4496 // DQ (3/29/2014): Added support for SgJavaForEachStatement.
4497 case V_SgJavaForEachStatement:
4498 {
4499 SgJavaForEachStatement* javaForEachStatement = isSgJavaForEachStatement(scope);
4500 SgVariableDeclaration* variableDeclarationCondition = isSgVariableDeclaration(javaForEachStatement->get_element());
4501 if (variableDeclarationCondition != NULL)
4502 {
4503 // There is a variable declaration in the conditional, it needs to be added to the symbol table.
4504 // printf ("There is a variable declaration in the while statement condition, it needs to be added to the symbol table \n");
4505 // ROSE_ASSERT(false);
4506
4507 supportForVariableDeclarations ( scope, symbolTable, variableDeclarationCondition );
4508 }
4509 return;
4510 break;
4511 }
4512
4513 default:
4514 {
4515 printf ("Default reached in SageInterface::rebuildSymbolTable() scope = %p = %s \n",scope,scope->class_name().c_str());
4516 ROSE_ABORT();
4517 }
4518 }
4519
4520#if 0
4521 printf ("In SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
4522#endif
4523
4524 // Generate a copy of the statement list (this is simpler than handling the cases of a
4525 // declaration list and a statement list separately for the scopes that contain one or the other.
4526 SgStatementPtrList statementList = scope->generateStatementList();
4527
4528 // Loop through the statements and for each declaration build a symbol and add it to the symbol table
4529 for (SgStatementPtrList::iterator i = statementList.begin(); i != statementList.end(); i++)
4530 {
4531 // At some point we should move this mechanism in to a factory patterns for SgSymbol
4532
4533 // printf ("Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4534
4535 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
4536 if (declaration != NULL)
4537 {
4538 // DQ (11/7/2007): Where there can be multiple declaration (e.g. function declarations with prototypes) only use one of them.
4539 bool useThisDeclaration = (declaration->get_firstNondefiningDeclaration() == declaration) ||
4540 ( (declaration->get_firstNondefiningDeclaration() == NULL) && (declaration->get_definingDeclaration() == declaration) );
4541
4542 list<SgSymbol*> symbolList;
4543 switch(declaration->variantT())
4544 {
4545 case V_SgTemplateInstantiationMemberFunctionDecl:
4546 {
4547 SgTemplateInstantiationMemberFunctionDecl* derivedDeclaration = isSgTemplateInstantiationMemberFunctionDecl(declaration);
4548 // 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
4549 if (scope == derivedDeclaration->get_scope())
4550 {
4551 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4552 ROSE_ASSERT(symbol != NULL);
4553
4554 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4555
4556 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s inserting a symbol = %p \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str(),symbol);
4557
4558 SgName name = derivedDeclaration->get_name();
4559 symbolTable->insert(name,symbol);
4560 }
4561 else
4562 {
4563 // printf ("SgTemplateInstantiationMemberFunctionDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4564
4565 // These IR nodes might only exist as a template declaration and thus not be structureally present in their scope.
4566 // So we would never traverse them in the correct scope and so never build sysmbols for them and add the symbols
4567 // to the correct symbol table. This is a fundamental problem. So we have to try to add these sorts of symbols
4568 // to the scope were they belong.
4569 SgScopeStatement* derivedDeclarationScope = derivedDeclaration->get_scope();
4570 ROSE_ASSERT(derivedDeclarationScope != NULL);
4571
4572 // If this is a copy then it would be nice to make sure that the scope has been properly set.
4573 // Check this by looking for the associated template declaration in the scope.
4574 // SgTemplateDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4575 // SgDeclarationStatement* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4576 SgTemplateMemberFunctionDeclaration* templateDeclaration = derivedDeclaration->get_templateDeclaration();
4577 ROSE_ASSERT(templateDeclaration != NULL);
4578 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_name());
4579
4580 // DQ (8/13/2013): Fixed the interface to avoid use of lookup_template_symbol() (removed).
4581 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
4582 // In this case these are unavailable from this point.
4583 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name());
4584 // SgTemplateSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4585 SgType* functionType = templateDeclaration->get_type();
4586 SgTemplateParameterPtrList & templateParameterList = templateDeclaration->get_templateParameters();
4587 // SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_symbol(templateDeclaration->get_template_name(),NULL,NULL);
4588 SgTemplateMemberFunctionSymbol* templateSymbol = derivedDeclarationScope->lookup_template_member_function_symbol(templateDeclaration->get_template_name(),functionType,&templateParameterList);
4589 if (templateSymbol != NULL)
4590 {
4591 // The symbol is not present, so we have to build one and add it.
4592#if 0
4593 printf ("Building a symbol for derivedDeclaration = %p = %s to an alternative symbol table in derivedDeclarationScope = %p \n",
4594 derivedDeclaration,get_name(derivedDeclaration).c_str(),derivedDeclarationScope);
4595#endif
4596 SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4597 ROSE_ASSERT(symbol != NULL);
4598 SgName name = derivedDeclaration->get_name();
4599 derivedDeclarationScope->insert_symbol(name,symbol);
4600 }
4601 else
4602 {
4603 // printf ("The symbol was already present in the derivedDeclarationScope = %p \n",derivedDeclarationScope);
4604 }
4605 }
4606 break;
4607 }
4608
4609 // DQ (12/26/2012): Added support for templates.
4610 case V_SgTemplateMemberFunctionDeclaration:
4611
4612 case V_SgMemberFunctionDeclaration:
4613 {
4614 SgMemberFunctionDeclaration* derivedDeclaration = isSgMemberFunctionDeclaration(declaration);
4615
4616 // 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
4617 if (scope == derivedDeclaration->get_scope())
4618 {
4619 // SgSymbol* symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4620 SgSymbol* symbol = NULL;
4621 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4622 symbol = new SgTemplateMemberFunctionSymbol(derivedDeclaration);
4623 else
4624 symbol = new SgMemberFunctionSymbol(derivedDeclaration);
4625
4626 ROSE_ASSERT(symbol != NULL);
4627
4628 // printf ("In rebuildSymbolTable: symbol = %p = %s = %s \n",symbol,symbol->class_name().c_str(),SageInterface::get_name(symbol).c_str());
4629
4630 SgName name = derivedDeclaration->get_name();
4631 symbolTable->insert(name,symbol);
4632 }
4633 else
4634 {
4635 // This happens when a defining declaration is located outside of the class where it is associated.
4636 // printf ("SgMemberFunctionDeclaration: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4637 }
4638 break;
4639 }
4640
4641 // DQ (2/26/2009): These have to be reformatted from where someone removed the formatting previously.
4642 case V_SgTemplateInstantiationFunctionDecl:
4643 {
4644 SgTemplateInstantiationFunctionDecl* derivedDeclaration = isSgTemplateInstantiationFunctionDecl(declaration);
4645 // 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)
4646 if (scope == derivedDeclaration->get_scope())
4647 {
4648 SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4649 ROSE_ASSERT(symbol != NULL);
4650 SgName name = derivedDeclaration->get_name();
4651 symbolTable->insert(name,symbol);
4652 }
4653 else
4654 {
4655 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4656 {
4657#if PRINT_DEVELOPER_WARNINGS
4658 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4659#endif
4660 }
4661 }
4662
4663 break;
4664 }
4665
4666 // DQ (12/24/2012): Added support for templates.
4667 case V_SgTemplateFunctionDeclaration:
4668
4669 case V_SgFunctionDeclaration:
4670 {
4671 SgFunctionDeclaration* derivedDeclaration = isSgFunctionDeclaration(declaration);
4672
4673 // 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)
4674
4675 if (useThisDeclaration == true)
4676 {
4677 if (scope == derivedDeclaration->get_scope())
4678 {
4679 // DQ (12/24/2012): Added support for templates.
4680 // SgSymbol* symbol = new SgFunctionSymbol(derivedDeclaration);
4681 SgSymbol* symbol = NULL;
4682 if (isSgTemplateFunctionDeclaration(declaration) != NULL)
4683 symbol = new SgTemplateFunctionSymbol(derivedDeclaration);
4684 else
4685 symbol = new SgFunctionSymbol(derivedDeclaration);
4686
4687 ROSE_ASSERT(symbol != NULL);
4688 SgName name = derivedDeclaration->get_name();
4689 symbolTable->insert(name,symbol);
4690 }
4691 else
4692 {
4693 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4694 {
4695#if PRINT_DEVELOPER_WARNINGS
4696 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4697#endif
4698 }
4699 }
4700 }
4701 break;
4702 }
4703
4704 // DQ (12/28/2012): Adding support for templates.
4705 case V_SgTemplateVariableDeclaration:
4706
4707 case V_SgVariableDeclaration:
4708 {
4709 SgVariableDeclaration* derivedDeclaration = isSgVariableDeclaration(declaration);
4710 SgInitializedNamePtrList & variableList = derivedDeclaration->get_variables();
4711 SgInitializedNamePtrList::iterator i = variableList.begin();
4712 while ( i != variableList.end() )
4713 {
4715 ROSE_ASSERT(variable != NULL);
4716
4717 // DQ (10/20/2007): static data members declared outside the class scope don't generate symbols.
4718 if (variable->get_scope() == scope)
4719 {
4720 SgSymbol* symbol = new SgVariableSymbol(variable);
4721 ROSE_ASSERT(symbol != NULL);
4722
4723 // printf ("In SageInterface::rebuildSymbolTable() variable = %p building a new SgVariableSymbol = %p \n",variable,symbol);
4724
4725 SgName name = variable->get_name();
4726 symbolTable->insert(name,symbol);
4727 }
4728 else
4729 {
4730 // I think there is nothing to do in this case
4731 // 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);
4732 }
4733
4734 i++;
4735 }
4736
4737 // DQ (10/13/2007): Need to look into variable declarations to see if there are defining declaration
4738 // that also force symbols to be built in the current scope!
4739 // ROSE_ASSERT(derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == false);
4740 if (derivedDeclaration->get_variableDeclarationContainsBaseTypeDefiningDeclaration() == true)
4741 {
4742 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4743 ROSE_ASSERT(symbolTable != NULL);
4744 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4745 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4746 }
4747
4748 // ROSE_ASSERT(symbolList.empty() == false);
4749 break;
4750 }
4751
4752 case V_SgTemplateInstantiationDecl:
4753 {
4754 SgTemplateInstantiationDecl* derivedDeclaration = isSgTemplateInstantiationDecl(declaration);
4755#if 1
4756 // printf ("case SgTemplateInstantiationDecl: derivedDeclaration name = %s derivedDeclaration->get_declarationModifier().isFriend() = %s \n",
4757 // derivedDeclaration->get_name().str(),derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4758
4759 if (scope == derivedDeclaration->get_scope())
4760 {
4761 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4762 // printf ("Inserting SgClassSymbol = %p into scope = %p = %s \n",symbol,scope,scope->class_name().c_str());
4763 ROSE_ASSERT(symbol != NULL);
4764 SgName name = derivedDeclaration->get_name();
4765#if 0
4766 // DQ (10/21/2007): The scopes should match
4767 if (scope != derivedDeclaration->get_scope())
4768 {
4769 printf ("Error: scopes don't match for derivedDeclaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4770 }
4771 ROSE_ASSERT(scope == derivedDeclaration->get_scope());
4772#endif
4773 symbolTable->insert(name,symbol);
4774 }
4775 else
4776 {
4777 // printf ("SgTemplateInstantiationDecl: scope = %p derivedDeclaration = %p = %s didn't match the scope \n",scope,derivedDeclaration,get_name(derivedDeclaration).c_str());
4778
4779 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4780 {
4781#if PRINT_DEVELOPER_WARNINGS
4782 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4783#endif
4784 }
4785 }
4786#else
4787 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4788 ROSE_ASSERT(symbol != NULL);
4789 SgName name = derivedDeclaration->get_name();
4790 symbolTable->insert(name,symbol);
4791#endif
4792 break;
4793 }
4794
4795
4796 // DQ (12/24/2012): Added support for templates.
4797 case V_SgTemplateClassDeclaration:
4798
4799 case V_SgClassDeclaration:
4800 {
4801 SgClassDeclaration* derivedDeclaration = isSgClassDeclaration(declaration);
4802#if 1
4803 if (scope == derivedDeclaration->get_scope())
4804 {
4805 SgSymbol* symbol = NULL;
4806 if (isSgTemplateClassDeclaration(declaration) != NULL)
4807 symbol = new SgTemplateClassSymbol(derivedDeclaration);
4808 else
4809 symbol = new SgClassSymbol(derivedDeclaration);
4810
4811 ROSE_ASSERT(symbol != NULL);
4812 SgName name = derivedDeclaration->get_name();
4813 symbolTable->insert(name,symbol);
4814 }
4815 else
4816 {
4817 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4818 {
4819#if PRINT_DEVELOPER_WARNINGS
4820 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4821#endif
4822 }
4823 }
4824#else
4825 SgSymbol* symbol = new SgClassSymbol(derivedDeclaration);
4826 ROSE_ASSERT(symbol != NULL);
4827 SgName name = derivedDeclaration->get_name();
4828 symbolTable->insert(name,symbol);
4829#endif
4830 break;
4831 }
4832
4833 case V_SgEnumDeclaration:
4834 {
4835 SgEnumDeclaration* derivedDeclaration = isSgEnumDeclaration(declaration);
4836 ROSE_ASSERT(derivedDeclaration != NULL);
4837 SgSymbol* symbol = new SgEnumSymbol(derivedDeclaration);
4838 ROSE_ASSERT(symbol != NULL);
4839 SgName name = derivedDeclaration->get_name();
4840 symbolTable->insert(name,symbol);
4841
4842 // DQ (10/18/2007): Fixed construction of symbol tabel to include enum fields.
4843 SgInitializedNamePtrList & enumFieldList = derivedDeclaration->get_enumerators();
4844 SgInitializedNamePtrList::iterator i = enumFieldList.begin();
4845
4846 // Iterate over enum fields and add each one to the symbol table.
4847 while (i != enumFieldList.end())
4848 {
4849 SgSymbol* enum_field_symbol = new SgEnumFieldSymbol(*i);
4850 ROSE_ASSERT(enum_field_symbol != NULL);
4851 SgName enum_field_name = (*i)->get_name();
4852 symbolTable->insert(enum_field_name,enum_field_symbol);
4853
4854 i++;
4855 }
4856
4857 break;
4858 }
4859
4860
4861 // DQ (2/18/2017): Added support for C++11 SgTemplateTypedefDeclaration.
4862 case V_SgTemplateTypedefDeclaration:
4863
4864 case V_SgTypedefDeclaration:
4865 {
4866 SgTypedefDeclaration* derivedDeclaration = isSgTypedefDeclaration(declaration);
4867 SgSymbol* symbol = new SgTypedefSymbol(derivedDeclaration);
4868 ROSE_ASSERT(symbol != NULL);
4869 SgName name = derivedDeclaration->get_name();
4870 symbolTable->insert(name,symbol);
4871#if 0
4872 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration \n");
4873#endif
4874 // DQ (10/13/2007): Need to look into typedefs to see if there are defining declaration
4875 // that also force symbols to be built in the current scope!
4876 // ROSE_ASSERT(derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == false);
4877 if (derivedDeclaration->get_typedefBaseTypeContainsDefiningDeclaration() == true)
4878 {
4879 // Build a SgClassDeclaration, SgEnumDeclaration associated symbol and add it to the symbol table.
4880 ROSE_ASSERT(symbolTable != NULL);
4881 ROSE_ASSERT(derivedDeclaration->get_baseTypeDefiningDeclaration() != NULL);
4882#if 0
4883 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == true calling supportForBaseTypeDefiningDeclaration() \n");
4884#endif
4885 supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_baseTypeDefiningDeclaration() );
4886 }
4887 else
4888 {
4889 // DQ (11/7/2007): If the typedef has a definition (e.g. function pointer) then build a symbol.
4890 SgDeclarationStatement* declaration = derivedDeclaration->get_declaration();
4891 if (declaration != NULL)
4892 {
4893#if 0
4894 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false calling supportForBaseTypeDefiningDeclaration() \n");
4895#endif
4896 // 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).
4897 // supportForBaseTypeDefiningDeclaration ( symbolTable, derivedDeclaration->get_declaration() );
4898
4899 printf ("In SageInterface::rebuildSymbolTable(): case of SgTypedefDeclaration: typedefBaseTypeContainsDefiningDeclaration == false: skipping call to supportForBaseTypeDefiningDeclaration() \n");
4900 }
4901 }
4902#if 0
4903 printf ("In SageInterface::rebuildSymbolTable(): Leaving case of SgTypedefDeclaration \n");
4904#endif
4905 break;
4906 }
4907
4908 case V_SgTemplateDeclaration:
4909 {
4910 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4911#if 1
4912 // 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)
4913#if 0
4914 printf ("case V_SgTemplateDeclaration: derivedDeclaration = %p \n",derivedDeclaration);
4915 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_declarationModifier().isFriend() = %s \n",derivedDeclaration->get_declarationModifier().isFriend() ? "true" : "false");
4916 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_name() = %s \n",derivedDeclaration->get_name().str());
4917 printf ("case V_SgTemplateDeclaration: derivedDeclaration->get_string() = %s \n",derivedDeclaration->get_string().str());
4918#endif
4919 if (scope == derivedDeclaration->get_scope())
4920 {
4921 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4922 ROSE_ASSERT(symbol != NULL);
4923 SgName name = derivedDeclaration->get_name();
4924 symbolTable->insert(name,symbol);
4925 }
4926 else
4927 {
4928 if (derivedDeclaration->get_declarationModifier().isFriend() == false)
4929 {
4930#if PRINT_DEVELOPER_WARNINGS
4931 printf ("Shouldn't this be a friend declaration = %p = %s \n",derivedDeclaration,derivedDeclaration->class_name().c_str());
4932#endif
4933 }
4934 }
4935#else
4936 SgTemplateDeclaration* derivedDeclaration = isSgTemplateDeclaration(declaration);
4937 SgSymbol* symbol = new SgTemplateSymbol(derivedDeclaration);
4938 ROSE_ASSERT(symbol != NULL);
4939 SgName name = derivedDeclaration->get_name();
4940 symbolTable->insert(name,symbol);
4941#endif
4942 break;
4943 }
4944
4945 // Does this cause a symbol to be built? Seems that it should,
4946 // unless we always reference the non-aliased symbol (reuse it)!
4947 case V_SgNamespaceAliasDeclarationStatement:
4948 {
4949 SgNamespaceAliasDeclarationStatement* aliasDeclaration = isSgNamespaceAliasDeclarationStatement(declaration);
4950 ROSE_ASSERT(aliasDeclaration != NULL);
4951 ROSE_ASSERT(aliasDeclaration->get_namespaceDeclaration() != NULL);
4952
4953 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(aliasDeclaration->get_namespaceDeclaration());
4954 ROSE_ASSERT(derivedDeclaration != NULL);
4955
4956 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4957 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4958 ROSE_ASSERT(symbol != NULL);
4959 SgName name = derivedDeclaration->get_name();
4960 symbolTable->insert(name,symbol);
4961 // symbolList.push_back(symbol);
4962 // ROSE_ASSERT(symbolList.empty() == false);
4963 break;
4964 }
4965
4966 // Does this cause a symbol to be built? Seems that it should,
4967 // unless we always reference the non-aliased symbol (reuse it)!
4968 case V_SgNamespaceDeclarationStatement:
4969 {
4970 SgNamespaceDeclarationStatement* derivedDeclaration = isSgNamespaceDeclarationStatement(declaration);
4971 ROSE_ASSERT(derivedDeclaration != NULL);
4972
4973 // The constructor for the SgNamespaceSymbol is disturbingly different from the rest of the constructors.
4974 SgSymbol* symbol = new SgNamespaceSymbol(derivedDeclaration->get_name(),derivedDeclaration);
4975 ROSE_ASSERT(symbol != NULL);
4976 SgName name = derivedDeclaration->get_name();
4977 symbolTable->insert(name,symbol);
4978 // symbolList.push_back(symbol);
4979 // ROSE_ASSERT(symbolList.empty() == false);
4980 break;
4981 }
4982
4983 case V_SgUsingDirectiveStatement:
4984 case V_SgPragmaDeclaration:
4985 case V_SgTemplateInstantiationDirectiveStatement:
4986 case V_SgUsingDeclarationStatement:
4987 {
4988 // DQ (10/22/2005): Not sure if we have to worry about this declaration's appearance in the symbol table!
4989#if 0
4990 printf ("This declaration is ignored in rebuilding symbol table %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
4991#endif
4992 break;
4993 }
4994
4995 case V_SgAsmStmt:
4996 {
4997 // DQ (8/13/2006): This is not really a declaration (I think). This will be fixed later.
4998#if 0
4999 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());
5000#endif
5001 break;
5002 }
5003
5004 // Cases where declations are not used or referenced and so symbols are not required!
5005 case V_SgVariableDefinition:
5006 case V_SgFunctionParameterList:
5007 case V_SgCtorInitializerList:
5008 // These are not referenced so they don't need a symbol!
5009 {
5010 printf ("Special cases not handled %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5011 ROSE_ABORT();
5012 }
5013
5014 case V_SgStaticAssertionDeclaration:
5015 {
5016 // DQ (2/18/2017): This is not really a declaration (I think). This will be fixed later.
5017#if 0
5018 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());
5019#endif
5020 break;
5021 }
5022
5023 default:
5024 {
5025 printf ("Error: Default reached in rebuildSymbolTable declaration = %p = %s \n",declaration,declaration->class_name().c_str());
5026 ROSE_ABORT();
5027 }
5028 }
5029
5030 ROSE_ASSERT(symbolTable != NULL);
5031 ROSE_ASSERT(symbolTable->get_table() != NULL);
5032 }
5033 // printf ("DONE: Iterating through the declaration in this scope ... %p = %s = %s \n",*i,(*i)->class_name().c_str(),get_name(*i).c_str());
5034
5035 }
5036
5037 ROSE_ASSERT(symbolTable != NULL);
5038 ROSE_ASSERT(symbolTable->get_table() != NULL);
5039
5040#if 0
5041 printf ("Leaving SageInterface::rebuildSymbolTable(): fixup declarations in Symbol Table from %p = %s \n",scope,scope->class_name().c_str());
5042#endif
5043
5044#if 0
5045 printf ("Symbol Table from %p = %s at: \n",scope,scope->class_name().c_str());
5046 scope->get_file_info()->display("Symbol Table Location");
5047 symbolTable->print("Called from SageInterface::rebuildSymbolTable()");
5048#endif
5049 }
5050
5051
5052// #ifndef USE_ROSE
5053
5054void
5056 {
5057 // This function is called by the SageInterface::rebuildSymbolTable().
5058 // It resets references to old symbols to the new symbols (just built).
5059 // All pairs of old/new symbols are also saved in the object:
5060 // SgCopyHelp::copiedNodeMapType copiedNodeMap
5061
5062#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
5063 ROSE_ASSERT(this_scope != NULL);
5064 ROSE_ASSERT(copy_scope != NULL);
5065
5066#if 0
5067 printf ("In fixupReferencesToSymbols(this_scope = %p = %s = %s, copy_scope = %p = %s = %s) \n",
5068 this_scope,this_scope->class_name().c_str(),get_name(this_scope).c_str(),
5069 copy_scope,copy_scope->class_name().c_str(),get_name(copy_scope).c_str());
5070#endif
5071
5072 SgSymbolTable* this_symbolTable = this_scope->get_symbol_table();
5073 SgSymbolTable* copy_symbolTable = copy_scope->get_symbol_table();
5074#if 0
5075 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());
5076 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());
5077#endif
5078
5079 // DQ (3/4/2009): For now just output a warning, but this might be a more serious problem.
5080 // Since the symbol table size of the copy is larger than that of the original it might
5081 // be that a symbol is enterted twice by the copy mechanism. If so I want to fix this.
5082 if (this_symbolTable->get_table()->size() != copy_symbolTable->get_table()->size())
5083 {
5084 if (SgProject::get_verbose() > 0)
5085 {
5086 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());
5087 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());
5088 printf ("Warning the symbols tables in these different scopes are different sizes \n");
5089 }
5090 }
5091 // ROSE_ASSERT(this_symbolTable->get_table()->size() <= copy_symbolTable->get_table()->size());
5092
5093 SgSymbolTable::hash_iterator i = this_symbolTable->get_table()->begin();
5094
5095 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
5096 std::map<SgNode*, SgNode*> replacementMap;
5097 int counter = 0;
5098 while (i != this_symbolTable->get_table()->end())
5099 {
5100 ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL );
5101
5102 SgName name = (*i).first;
5103 // SgSymbol* symbol = isSgSymbol((*i).second);
5104 SgSymbol* symbol = (*i).second;
5105 ROSE_ASSERT ( symbol != NULL );
5106
5107 SgSymbol* associated_symbol = NULL;
5108#if 0
5109 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());
5110#endif
5111 // Look for the associated symbol in the copy_scope's symbol table.
5112 SgSymbolTable::hash_iterator associated_symbol_iterator = copy_symbolTable->get_table()->find(name);
5113
5114 // Note that this is a multi-map and for C++ a number of symbols can have the same name
5115 // (though not the same type of symbol) so we have to iterator over the symbols of the
5116 // same name so that we can identify the associated symbol.
5117 while (associated_symbol_iterator != copy_symbolTable->get_table()->end() && associated_symbol_iterator->first == name)
5118 {
5119 if ( associated_symbol_iterator->second->variantT() == symbol->variantT() )
5120 {
5121 associated_symbol = associated_symbol_iterator->second;
5122 }
5123
5124 associated_symbol_iterator++;
5125 }
5126
5127 if (associated_symbol != NULL)
5128 {
5129 ROSE_ASSERT ( associated_symbol != NULL );
5130
5131 // Check to make sure that this is correct
5132 ROSE_ASSERT(copy_scope->symbol_exists(associated_symbol) == true);
5133
5134 // Add the SgGlobal referenece to the replacementMap
5135 // replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
5136 // DQ (23/1/2009): Find the reference to symbol and replace it with associated_symbol.
5137 replacementMap.insert(pair<SgNode*,SgNode*>(symbol,associated_symbol));
5138
5139 // DQ (3/1/2009): This is backwards
5140 // replacementMap.insert(pair<SgNode*,SgNode*>(associated_symbol,symbol));
5141
5142 // DQ (3/2/2009): accumulate the symbol pair into the SgCopyHelp object (to support the outliner).
5143 // Actually this should also improve the robustness of the outliner.
5144 help.get_copiedNodeMap().insert(pair<const SgNode*,SgNode*>(symbol,associated_symbol));
5145 }
5146 else
5147 {
5148 // DQ (3/4/2009): This case was broken out because copytest2007_14.C fails here.
5149 if (SgProject::get_verbose() > 0)
5150 {
5151 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());
5152 printf ("Warning: associated_symbol == NULL, need to investigate this (ignoring for now) \n");
5153 }
5154 }
5155
5156 counter++;
5157
5158 i++;
5159 }
5160
5161#if 0
5162 printf ("\n\n************************************************************\n");
5163 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());
5164#endif
5165
5166 Rose::AST::Utility::edgePointerReplacement(copy_scope,replacementMap);
5167
5168#if 0
5169 printf ("fixupReferencesToSymbols(): calling Utils::edgePointerReplacement(): DONE \n");
5170 printf ("************************************************************\n\n");
5171
5172 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
5173 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
5174
5175 printf ("After fixup: this_symbolTable->get_table()->size() = %" PRIuPTR " \n",this_symbolTable->get_table()->size());
5176 printf ("After fixup: copy_symbolTable->get_table()->size() = %" PRIuPTR " \n",copy_symbolTable->get_table()->size());
5177#endif
5178
5179 // DQ (3/1/2009): find a case where this code is tested.
5180 // ROSE_ASSERT(this_symbolTable->get_table()->size() == 0);
5181 // ROSE_ASSERT(isSgClassDefinition(copy_scope) == NULL);
5182#endif
5183
5184#if 0
5185 printf ("Exiting as a test in fixupReferencesToSymbols() \n");
5186 ROSE_ABORT();
5187#endif
5188 }
5189
5190// #endif
5191
5192#ifndef USE_ROSE
5193
5194std::vector<SgFile*>
5196 {
5197 // This function uses a memory pool traversal specific to the SgFile IR nodes
5198 class FileTraversal : public ROSE_VisitTraversal
5199 {
5200 public:
5201 vector<SgFile*> fileList;
5202 void visit ( SgNode* node)
5203 {
5204 SgFile* file = isSgFile(node);
5205 ROSE_ASSERT(file != NULL);
5206 if (file != NULL)
5207 {
5208 fileList.push_back(file);
5209 }
5210 };
5211
5212 virtual ~FileTraversal() {}
5213 };
5214
5215 FileTraversal fileTraversal;
5216
5217 // traverse just the SgFile nodes (both the SgSourceFile and SgBinaryComposite IR nodes)!
5218 // SgFile::visitRepresentativeNode(fileTraversal);
5220#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5222#endif
5223
5224 // This would alternatively traverse all IR nodes in thememory pool!
5225 // fileTraversal.traverseMemoryPool();
5226
5227 // TV (06/24/2013): This fail when calling SageBuilder::buildVariableDeclaration(...) without any file created.
5228 // DQ (10/11/2014): This is allowed to be empty (required for new aterm support).
5229 // ROSE_ASSERT(fileTraversal.fileList.empty() == false);
5230
5231 return fileTraversal.fileList;
5232 }
5233
5234#endif
5235
5236// #ifndef USE_ROSE
5237
5238// DQ (4/17/2015): I think this function should be removed since it interferes
5239// with the concept of having more than one SgProject node.
5240// This function uses a memory pool traversal specific to the SgProject IR nodes
5241SgProject*
5243{
5244#if 0
5245 class ProjectTraversal : public ROSE_VisitTraversal
5246 {
5247 public:
5248 SgProject * project;
5249 void visit ( SgNode* node)
5250 {
5251 project = isSgProject(node);
5252 ROSE_ASSERT(project!= NULL);
5253 };
5254 virtual ~ProjectTraversal() {}
5255 };
5256
5257 ProjectTraversal projectTraversal;
5258 SgProject::visitRepresentativeNode(projectTraversal);
5259 return projectTraversal.project;
5260#endif
5261 std::vector<SgProject* > resultlist = getSgNodeListFromMemoryPool<SgProject>();
5262 if (resultlist.empty())
5263 return NULL;
5264 ROSE_ASSERT(resultlist.size()==1);
5265 return resultlist[0];
5266}
5267
5268SgProject*
5270 return getEnclosingNode<SgProject>(node, true /*includingSelf*/);
5271}
5272
5274 SgFunctionDeclaration * ret = NULL;
5275 if (isSgFunctionRefExp(func))
5276 {
5277 return isSgFunctionRefExp(func)->get_symbol()->get_declaration();
5278 }
5279 else if (isSgDotExp(func) || isSgArrowExp(func))
5280 {
5281 SgExpression* func2 = isSgBinaryOp(func)->get_rhs_operand();
5282 if (isSgMemberFunctionRefExp(func2))
5283 return isSgMemberFunctionRefExp(func2)->get_symbol()->get_declaration();
5284 else
5285 {
5286 cerr<<"Warning in SageInterface::getDeclarationOfNamedFunction(): rhs operand of dot or arrow operations is not a member function, but a "<<func2->class_name()<<endl;
5287 }
5288 }
5289
5290 return ret;
5291}
5292
5294 SgExprListExp* el = stmt->get_forall_header();
5295 const SgExpressionPtrList& ls = el->get_expressions();
5296 if (ls.empty()) return 0;
5297 if (isSgAssignOp(ls.back())) return 0;
5298 return ls.back();
5299}
5300
5301//Find all SgPntrArrRefExp under astNode, add the referenced dim_info SgVarRefExp (if any) into NodeList_t
5302void SageInterface::addVarRefExpFromArrayDimInfo(SgNode * astNode, Rose_STL_Container<SgNode *>& NodeList_t)
5303{
5304 ASSERT_not_null(astNode);
5305 Rose_STL_Container<SgNode*> arr_exp_list = NodeQuery::querySubTree(astNode,V_SgPntrArrRefExp);
5306 for (SgNode* expr : arr_exp_list)
5307 {
5308 SgPntrArrRefExp* arr_exp = isSgPntrArrRefExp(expr);
5309 ASSERT_not_null(arr_exp);
5310 Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp);
5311 for (SgNode* ref : refList)
5312 {
5313 SgVarRefExp* cur_ref = isSgVarRefExp(ref);
5314 ASSERT_not_null(cur_ref);
5315 SgVariableSymbol * sym = cur_ref->get_symbol();
5316 ASSERT_not_null(sym);
5317 SgInitializedName * iname = sym->get_declaration();
5318 ASSERT_not_null(iname);
5319 SgArrayType * a_type = isSgArrayType(iname->get_typeptr());
5320 if (a_type && a_type->get_dim_info())
5321 {
5322 Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp);
5323 for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++)
5324 {
5325 SgVarRefExp* dim_ref = isSgVarRefExp(*iter2);
5326 NodeList_t.push_back(dim_ref);
5327 }
5328 }
5329 }
5330 } // end for
5331}
5332
5333
5334// DQ (11/25/2020): This disables these non-inlined functions in favor of
5335// inlined versions of the functions in the sageInterface.h (header file).
5336#if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5337bool
5339 {
5340#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5341 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5342 return Rose::is_Ada_language;
5343#else
5344 bool returnValue = false;
5345
5346 vector<SgFile*> fileList = generateFileList();
5347
5348 int size = (int)fileList.size();
5349 for (int i = 0; i < size; i++)
5350 {
5351 if (fileList[i]->get_Ada_only() == true)
5352 returnValue = true;
5353 }
5354
5355 return returnValue;
5356#endif
5357 }
5358
5359bool
5361 {
5362#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5363 // 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).
5364 return Rose::is_C_language;
5365#else
5366 bool returnValue = false;
5367
5368 vector<SgFile*> fileList = generateFileList();
5369
5370 int size = (int)fileList.size();
5371 for (int i = 0; i < size; i++)
5372 {
5373 if (fileList[i]->get_C_only() == true)
5374 returnValue = true;
5375 }
5376
5377 return returnValue;
5378#endif
5379 }
5380
5381bool
5383 {
5384#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5385 // 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).
5386 return Rose::is_OpenMP_language;
5387#else
5388 bool returnValue = false;
5389
5390 vector<SgFile*> fileList = generateFileList();
5391
5392 int size = (int)fileList.size();
5393 for (int i = 0; i < size; i++)
5394 {
5395 if (fileList[i]->get_openmp() == true)
5396 returnValue = true;
5397 }
5398
5399 return returnValue;
5400#endif
5401 }
5402
5403bool
5405 {
5406#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5407 // 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).
5408 return Rose::is_UPC_language;
5409#else
5410 bool returnValue = false;
5411
5412 vector<SgFile*> fileList = generateFileList();
5413
5414 int size = (int)fileList.size();
5415 for (int i = 0; i < size; i++)
5416 {
5417 if (fileList[i]->get_UPC_only() == true)
5418 returnValue = true;
5419 }
5420
5421 return returnValue;
5422#endif
5423 }
5424
5425//FMZ
5426bool
5428 {
5429#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5430 // 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).
5431 return Rose::is_CAF_language;
5432#else
5433 bool returnValue = false;
5434
5435 vector<SgFile*> fileList = generateFileList();
5436
5437 int size = (int)fileList.size();
5438 for (int i = 0; i < size; i++)
5439 {
5440 if (fileList[i]->get_CoArrayFortran_only()==true)
5441 returnValue = true;
5442 }
5443
5444 return returnValue;
5445#endif
5446 }
5447
5448
5449// true if any of upc_threads is set to >0 via command line: -rose:upc_threads n
5450bool
5452 {
5453#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5454 // 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).
5455 return Rose::is_UPC_dynamic_threads;
5456#else
5457 bool returnValue = false;
5458
5459 vector<SgFile*> fileList = generateFileList();
5460
5461 int size = (int)fileList.size();
5462 for (int i = 0; i < size; i++)
5463 {
5464 if (fileList[i]->get_upc_threads() > 0)
5465 returnValue = true;
5466 }
5467
5468 return returnValue;
5469#endif
5470 }
5471
5472
5473
5474bool
5476 {
5477#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5478 // 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).
5479 return Rose::is_C99_language;
5480#else
5481 bool returnValue = false;
5482
5483 vector<SgFile*> fileList = generateFileList();
5484
5485 int size = (int)fileList.size();
5486 for (int i = 0; i < size; i++)
5487 {
5488 if (fileList[i]->get_C99_only() == true)
5489 returnValue = true;
5490 }
5491
5492 return returnValue;
5493#endif
5494 }
5495
5496bool
5498 {
5499#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5500 // 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).
5501 return Rose::is_Cxx_language;
5502#else
5503 bool returnValue = false;
5504
5505 vector<SgFile*> fileList = generateFileList();
5506
5507 int size = (int)fileList.size();
5508 for (int i = 0; i < size; i++)
5509 {
5510 // DQ (8/19/2007): Make sure this is not a Fortran code!
5511 if (fileList[i]->get_Cxx_only() == true)
5512 {
5513 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);
5514
5515 returnValue = true;
5516 }
5517 }
5518
5519 return returnValue;
5520#endif
5521 }
5522
5523bool
5525 {
5526#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5527 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5528 return Rose::is_Java_language;
5529#else
5530 bool returnValue = false;
5531
5532 vector<SgFile*> fileList = generateFileList();
5533
5534 int size = (int)fileList.size();
5535 for (int i = 0; i < size; i++)
5536 {
5537 if (fileList[i]->get_Java_only() == true)
5538 returnValue = true;
5539 }
5540
5541 return returnValue;
5542#endif
5543 }
5544
5545bool
5547 {
5548#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5549 // DQ (11/25/2020): Add support to set this as a specific language kind file (there is at least one language kind file processed by ROSE).
5550 return Rose::is_Jvm_language;
5551#else
5552 bool returnValue = false;
5553
5554 vector<SgFile*> fileList = generateFileList();
5555
5556 int size = (int)fileList.size();
5557 for (int i = 0; i < size; i++)
5558 {
5559 if (fileList[i]->get_Jvm_only() == true)
5560 returnValue = true;
5561 }
5562
5563 return returnValue;
5564#endif
5565 }
5566
5567// Rasmussen (4/4/2018): Added Jovial
5568bool
5570 {
5571#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5572 // 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).
5573 return Rose::is_Jovial_language;
5574#else
5575 bool returnValue = false;
5576
5577 vector<SgFile*> fileList = generateFileList();
5578
5579 int size = (int)fileList.size();
5580 for (int i = 0; i < size; i++)
5581 {
5582 if (fileList[i]->get_Jovial_only() == true)
5583 returnValue = true;
5584 }
5585
5586 return returnValue;
5587#endif
5588 }
5589
5590
5591bool
5593 {
5594#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5595 // 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).
5596 return Rose::is_Fortran_language;
5597#else
5598 bool returnValue = false;
5599
5600 vector<SgFile*> fileList = generateFileList();
5601
5602 int size = (int)fileList.size();
5603 for (int i = 0; i < size; i++)
5604 {
5605 if (fileList[i]->get_Fortran_only() == true)
5606 returnValue = true;
5607 }
5608
5609 return returnValue;
5610#endif
5611 }
5612
5613
5614bool
5616 {
5617#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5618 // 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).
5619 return Rose::is_binary_executable;
5620#else
5621 bool returnValue = false;
5622
5623 vector<SgFile*> fileList = generateFileList();
5624
5625 int size = (int)fileList.size();
5626 for (int i = 0; i < size; i++)
5627 {
5628 if (fileList[i]->get_binary_only() == true)
5629 returnValue = true;
5630 }
5631
5632 return returnValue;
5633#endif
5634 }
5635
5636bool
5638 {
5639#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5640 // 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).
5641 return Rose::is_PHP_language;
5642#else
5643 bool returnValue = false;
5644
5645 vector<SgFile*> fileList = generateFileList();
5646
5647 int size = (int)fileList.size();
5648 for (int i = 0; i < size; i++)
5649 {
5650 if (fileList[i]->get_PHP_only() == true)
5651 returnValue = true;
5652 }
5653
5654 return returnValue;
5655#endif
5656 }
5657
5658bool
5660 {
5661#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5662 // 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).
5663 return Rose::is_Python_language;
5664#else
5665 bool returnValue = false;
5666
5667 vector<SgFile*> fileList = generateFileList();
5668
5669 int size = (int)fileList.size();
5670 for (int i = 0; i < size; i++)
5671 {
5672 if (fileList[i]->get_Python_only() == true)
5673 returnValue = true;
5674 }
5675
5676 return returnValue;
5677#endif
5678 }
5679
5680bool
5682 {
5683#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5684 // 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).
5685 return Rose::is_Cuda_language;
5686#else
5687 bool returnValue = false;
5688
5689 vector<SgFile*> fileList = generateFileList();
5690
5691 int size = (int)fileList.size();
5692 for (int i = 0; i < size; i++)
5693 {
5694 if (fileList[i]->get_Cuda_only() == true)
5695 returnValue = true;
5696 }
5697
5698 return returnValue;
5699#endif
5700 }
5701
5702bool
5704 {
5705#if OPTIMIZE_IS_LANGUAGE_KIND_FUNCTIONS
5706 // 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).
5707 return Rose::is_OpenCL_language;
5708#else
5709 bool returnValue = false;
5710
5711 vector<SgFile*> fileList = generateFileList();
5712
5713 int size = (int)fileList.size();
5714 for (int i = 0; i < size; i++)
5715 {
5716 if (fileList[i]->get_OpenCL_only() == true)
5717 returnValue = true;
5718 }
5719
5720 return returnValue;
5721#endif
5722 }
5723
5724// for if (INLINE_OPTIMIZED_IS_LANGUAGE_KIND_FUNCTIONS == 0)
5725#endif
5726
5731
5736
5741
5746
5751
5752// Languages that may have scopes that contain statements that are not only declarations.
5753// For Fortran and Jovial (at least), function definitions may be declared at the end of procedures.
5758
5759// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5760// labels for scopes in a function (as required for name mangling).
5761void
5763 {
5764 ASSERT_not_null(functionDefinition);
5765 std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5766
5767 // Clear the cache of stored (scope,integer) pairs
5768 scopeMap.erase(scopeMap.begin(),scopeMap.end());
5769
5770 ASSERT_require(scopeMap.empty() == true);
5771 ASSERT_require(functionDefinition->get_scope_number_list().empty() == true);
5772 }
5773
5774#ifndef USE_ROSE
5775
5776// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5777// labels for scopes in a function (as required for name mangling).
5778void
5780 {
5781 ROSE_ASSERT(functionDefinition != NULL);
5782 // std::map<SgNode*,int> & scopeMap = functionDefinition->get_scope_number_list();
5783 // ROSE_ASSERT(scopeMap.empty() == true);
5784 ROSE_ASSERT(functionDefinition->get_scope_number_list().empty() == true);
5785
5786 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5787 class ScopeNumberingTraversal : public AstSimpleProcessing
5788 {
5789 public:
5790 ScopeNumberingTraversal() : count (0), storedFunctionDefinition(NULL) {}
5791 void visit (SgNode* node)
5792 {
5793 SgScopeStatement* scope = isSgScopeStatement (node);
5794 if (scope != NULL)
5795 {
5796 // Set the function definition
5797 SgFunctionDefinition* testFunctionDefinition = isSgFunctionDefinition(scope);
5798 if (testFunctionDefinition != NULL && storedFunctionDefinition == NULL)
5799 {
5800 ROSE_ASSERT(storedFunctionDefinition == NULL);
5801 storedFunctionDefinition = testFunctionDefinition;
5802 }
5803
5804 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5805 ROSE_ASSERT(storedFunctionDefinition != NULL);
5806
5807 count++;
5808
5809 std::map<SgNode*,int> & scopeMap = storedFunctionDefinition->get_scope_number_list();
5810 scopeMap.insert(pair<SgNode*,int>(scope,count));
5811#if 0
5812 string functionName = storedFunctionDefinition->get_declaration()->get_name().str();
5813 printf ("In function = %s insert scope = %p = %s with count = %d into local map (size = %d) \n",
5814 functionName.c_str(),scope,scope->class_name().c_str(),count,scopeMap.size());
5815#endif
5816 }
5817 }
5818
5819 private:
5820 int count; // running total of scopes found in the input function
5821 SgFunctionDefinition* storedFunctionDefinition;
5822 };
5823
5824 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5825 ScopeNumberingTraversal traversal;
5826 traversal.traverse(functionDefinition, preorder);
5827 }
5828
5829#endif
5830
5831#ifndef USE_ROSE
5832
5833#if 0
5834// DQ (6/26/2007): These are removed and the support is added to SgNode to support a single mangled name cache.
5835// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5836// labels for scopes in a function (as required for name mangling).
5837void
5839 {
5840 ROSE_ASSERT(globalScope != NULL);
5841 std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5842
5843 // Clear the cache of stored (scope,integer) pairs
5844 mangledNameCache.erase(mangledNameCache.begin(),mangledNameCache.end());
5845
5846 ROSE_ASSERT(mangledNameCache.empty() == true);
5847 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5848 }
5849
5850// DQ (10/5/2006): Added support for faster (non-quadratic) computation of unique
5851// labels for scopes in a function (as required for name mangling).
5852void
5854 {
5855 ROSE_ASSERT(globalScope != NULL);
5856 ROSE_ASSERT(globalScope->get_mangledNameCache().empty() == true);
5857
5858 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
5859 class MangledNameTraversal : public AstSimpleProcessing
5860 {
5861 public:
5862 MangledNameTraversal() : storedGlobalScope(NULL) {}
5863 void visit (SgNode* node)
5864 {
5865 SgFunctionDeclaration* mangleableNode = isSgFunctionDeclaration(node);
5866 if ( (mangleableNode != NULL) || (isSgGlobal(node) != NULL) )
5867 {
5868 // Set the global scope
5869 SgGlobal* testGlobalScope = isSgGlobal(mangleableNode);
5870 if (testGlobalScope != NULL && storedGlobalScope == NULL)
5871 {
5872 ROSE_ASSERT(storedGlobalScope == NULL);
5873 storedGlobalScope = testGlobalScope;
5874 }
5875
5876 // This should now be set (since the root of each traversal is a SgFunctionDefinition).
5877 ROSE_ASSERT(storedGlobalScope != NULL);
5878
5879 string mangledName = mangleableNode->get_mangled_name();
5880 // printf ("mangledName = %s \n",mangledName.c_str());
5881
5882 std::map<SgNode*,std::string> & mangledNameCache = storedGlobalScope->get_mangledNameCache();
5883 mangledNameCache.insert(pair<SgNode*,std::string>(mangleableNode,mangledName));
5884#if 0
5885 string nodeName = get_name(mangleableNode);
5886 printf ("At node = %p = %s = %s in local map (size = %d) \n",
5887 mangleableNode,mangleableNode->class_name().c_str(),nodeName.c_str(),mangledNameCache.size());
5888#endif
5889 }
5890 }
5891
5892 private:
5893 SgGlobal* storedGlobalScope;
5894 };
5895
5896 // Now buid the traveral object and call the traversal (preorder) on the function definition.
5897 MangledNameTraversal traversal;
5898 traversal.traverse(globalScope, preorder);
5899 }
5900#endif
5901
5902
5903string
5905 {
5906 // The TransformationSupport is not defined yet (I forget the
5907 // details but I recall that there is a reason why this is this way).
5908 // SgGlobal* globalScope = TransformationSupport::getGlobalScope(astNode);
5909#if 0
5910 SgGlobal* globalScope = isSgGlobal(astNode);
5911
5912 if (globalScope == NULL && isSgFile(astNode) != NULL)
5913 {
5914 globalScope = isSgFile(astNode)->get_globalScope();
5915 ROSE_ASSERT(globalScope != NULL);
5916 }
5917
5918 if (globalScope == NULL && isSgProject(astNode) != NULL)
5919 {
5920 // Check to make sure that the SgFile can be uniquely determined
5921 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5922 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5923 ROSE_ASSERT(globalScope != NULL);
5924 }
5925
5926 SgNode* temp = astNode;
5927 while (temp->get_parent() != NULL && globalScope == NULL)
5928 {
5929 temp = temp->get_parent();
5930 globalScope = isSgGlobal(temp);
5931 }
5932 ROSE_ASSERT(globalScope != NULL);
5933#endif
5934
5935 // std::map<SgNode*,std::string> & mangledNameCache = globalScope->get_mangledNameCache();
5936 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
5937
5938 // Build an iterator
5939 std::map<SgNode*,std::string>::iterator i = mangledNameCache.find(astNode);
5940
5941 string mangledName;
5942 if (i != mangledNameCache.end())
5943 {
5944 // get the precomputed mangled name!
5945 //~ printf ("Mangled name IS found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5946 mangledName = i->second;
5947 }
5948 else
5949 {
5950 // mangled name not found in cache!
5951 //~ printf ("Mangled name NOT found in cache (node = %p = %s) \n",astNode,astNode->class_name().c_str());
5952 }
5953
5954 return mangledName;
5955 }
5956
5957#define DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE 0
5958#define DEBUG_MANGLED_SHORTNAME 1
5959
5960//#ifdef DEBUG_MANGLED_SHORTNAME
5961//std::unordered_map<uint64_t, std::string> SageInterface::mangledNameHashCollisionCheckMap;
5962//#endif
5963
5964std::string
5965SageInterface::addMangledNameToCache( SgNode* astNode, const std::string & oldMangledName)
5966 {
5967#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
5968 printf ("In SageInterface::addMangledNameToCache(): TOP: astNode = %p = %s oldMangledName = %s \n",astNode,astNode->class_name().c_str(),oldMangledName.c_str());
5969#endif
5970
5971//#define DEBUG_MANGLED_SHORTNAME 1
5972#ifdef DEBUG_MANGLED_SHORTNAME
5973 static std::unordered_map<uint64_t, std::string> mangledNameHashCollisionCheckMap;
5974#endif
5975
5976
5977#if 0
5978 SgGlobal* globalScope = isSgGlobal(astNode);
5979
5980 if (globalScope == NULL && isSgFile(astNode) != NULL)
5981 {
5982 globalScope = isSgFile(astNode)->get_globalScope();
5983 ROSE_ASSERT(globalScope != NULL);
5984 }
5985
5986 if (globalScope == NULL && isSgProject(astNode) != NULL)
5987 {
5988 // Check to make sure that the SgFile can be uniquely determined
5989 ROSE_ASSERT( isSgProject(astNode)->get_fileList()->size() == 1 );
5990 globalScope = isSgProject(astNode)->get_fileList()->operator[](0)->get_globalScope();
5991 ROSE_ASSERT(globalScope != NULL);
5992 }
5993
5994 SgNode* temp = astNode;
5995 while (temp->get_parent() != NULL && globalScope == NULL)
5996 {
5997 temp = temp->get_parent();
5998 globalScope = isSgGlobal(temp);
5999 }
6000 ROSE_ASSERT(globalScope != NULL);
6001#endif
6002
6003 std::map<SgNode*,std::string> & mangledNameCache = SgNode::get_globalMangledNameMap();
6004
6005 std::string mangledName;
6006
6007 if (SgProject::get_mangled_noshortname() == false) {
6008 std::map<std::string, uint64_t> & shortMangledNameCache = SgNode::get_shortMangledNameCache();
6009
6010 if (oldMangledName.size() > 40) {
6011 std::map<std::string, uint64_t>::const_iterator shortMNIter = shortMangledNameCache.find(oldMangledName);
6012 uint64_t idNumber = 0;
6013 if (shortMNIter != shortMangledNameCache.end())
6014 {
6015 idNumber = shortMNIter->second;
6016
6017#ifdef DEBUG_MANGLED_SHORTNAME
6018 //Check for hash colisions, if we found an idNumber, but the long mangled name is different, we have a problem
6019 auto collisionIt = mangledNameHashCollisionCheckMap.find(idNumber);
6020 if(collisionIt != mangledNameHashCollisionCheckMap.end() &&
6021 oldMangledName != shortMNIter->first)
6022 {
6023 mlog[Sawyer::Message::Common::ERROR] <<" Got a short mangled name collision. \n "<<
6024 oldMangledName << " and \n " << shortMNIter->first << " \n" <<
6025 "have the same idNumber of: " << Combinatorics::toBase62String(idNumber) << " " << shortMNIter->second << endl;
6026 exit(12);
6027 } else {
6028 mangledNameHashCollisionCheckMap[idNumber] = oldMangledName;
6029 }
6030#endif //DEBUG_MANGLED_SHORTNAME
6031
6032 }
6033 else
6034 {
6036 hasher.insert(oldMangledName);
6037 hasher.digest();
6038 idNumber = hasher.toU64();
6039 shortMangledNameCache.insert(std::pair<std::string, uint64_t>(oldMangledName, idNumber));
6040 }
6041
6042 std::ostringstream mn;
6043 mn << 'L' << Combinatorics::toBase62String(idNumber) << 'R';
6044 mangledName = mn.str();
6045 } else {
6046 mangledName = oldMangledName;
6047 }
6048 } else {
6049
6050 // DQ (7/24/2012): Note that using this option can cause some test codes using operators that have
6051 // difficult names (conversion operators to user-defined types) to fail. See test2004_141.C for example.
6052 // The conversion operator "operator T&() const;" will fail because the character "&" will remain in
6053 // mangled name. The substring coding changes the strings for the mangled names and this effectively
6054 // removes the special characters, but there could be cases where they might remain.
6055
6056 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6057 static unsigned long counter = 0;
6058
6059 // DQ (3/27/2012): Use this as a mechanism to limit the I/O but still output a warning infrequently.
6060 // This supports debugging the new EDG 4.x interface...
6061 if (counter++ % 500 == 0)
6062 {
6063 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");
6064 }
6065 mangledName = oldMangledName;
6066}
6067
6068 // DQ (6/26/2007): Output information useful for understanding Jeremiah's shortended name merge caching.
6069 // std::cerr << "Changed MN " << oldMangledName << " to " << mangledName << std::endl;
6070
6071#if 0
6072 printf ("Updating mangled name cache for node = %p = %s with mangledName = %s \n",astNode,astNode->class_name().c_str(),mangledName.c_str());
6073#endif
6074
6075#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
6076 SgStatement* statement = isSgStatement(astNode);
6077 if (statement != NULL && statement->hasExplicitScope() == true)
6078 {
6079 if (statement->get_scope() == NULL)
6080 {
6081 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",
6082 statement,statement->class_name().c_str(),oldMangledName.c_str());
6083 }
6084 }
6085#endif
6086
6087 mangledNameCache.insert(pair<SgNode*,string>(astNode,mangledName));
6088
6089#if DEBUG_SAGE_INTERFACE_ADD_MANGLED_TO_CACHE
6090 printf ("In SageInterface::addMangledNameToCache(): returning mangledName = %s \n",mangledName.c_str());
6091#endif
6092
6093 return mangledName;
6094 }
6095
6096
6097// #endif
6098
6099#ifndef USE_ROSE
6100
6101bool
6103 {
6104 // This function is used in the unparser, but might be more generally useful. Since it is
6105 // related to general AST tests, I have put it here. It might be alternatively put in the
6106 // src/backend/unparser or related utility directory.
6107
6108 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6109 // declarations in the preorder traversal of the AST.
6110 class DeclarationOrderTraversal : public AstSimpleProcessing
6111 {
6112 public:
6113 DeclarationOrderTraversal( SgDeclarationStatement* nonDefiningDeclaration, SgDeclarationStatement* definingDeclaration )
6114 : storedNondefiningDeclaration(nonDefiningDeclaration),
6115 storedDefiningDeclaration(definingDeclaration)
6116 {
6117 storedDeclarationFound = false;
6118 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6119 }
6120
6121 void visit (SgNode* node)
6122 {
6123 ROSE_ASSERT(storedNondefiningDeclaration != NULL);
6124 ROSE_ASSERT(storedDefiningDeclaration != NULL);
6125 ROSE_ASSERT(storedNondefiningDeclaration != storedDefiningDeclaration);
6126 // ROSE_ASSERT(storedNondefiningDeclaration->get_definingDeclaration() == storedDefiningDeclaration);
6127
6128 // Even though we only care about the SgClassDeclaration IR nodes we have to traverse them
6129 // in the AST in the order defined by the traversal (order of apprearance in the AST). We
6130 // also can't just search the declarations of a single scope (since the nondefining declaration
6131 // can appear in a different scope than the defining declaration).
6132 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6133 if ( declaration != NULL )
6134 {
6135 if (storedDeclarationFound == false)
6136 {
6137 if (declaration == storedDefiningDeclaration)
6138 {
6139 storedDeclarationFound = true;
6140 nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6141 }
6142 if (declaration == storedNondefiningDeclaration)
6143 {
6144 storedDeclarationFound = true;
6145 nonDefiningDeclarationPreceedsDefiningDeclaration = true;
6146 }
6147 }
6148 }
6149 }
6150
6151 public:
6152 bool storedDeclarationFound;
6153 bool nonDefiningDeclarationPreceedsDefiningDeclaration;
6154
6155 private:
6156 SgDeclarationStatement* storedNondefiningDeclaration;
6157 SgDeclarationStatement* storedDefiningDeclaration;
6158 };
6159
6160 ROSE_ASSERT(nonDefiningDeclaration != NULL);
6161#if 0
6162 printf ("In SageInterface::declarationPreceedsDefinition(): \n");
6163 printf (" nondefiningDeclaration = %p = %s \n",nonDefiningDeclaration,nonDefiningDeclaration->class_name().c_str());
6164 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6165 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6166 printf (" definingDeclaration = %p = %s \n",definingDeclaration,definingDeclaration->class_name().c_str());
6167 definingDeclaration->get_file_info()->display("definingDeclaration");
6168 printf ("************************************************************* \n");
6169#endif
6170
6171#if 0
6172 // The nonDefiningDeclaration can be a different type of declaration than the definingDeclaration
6173 if (nonDefiningDeclaration->get_definingDeclaration() != definingDeclaration)
6174 {
6175 printf ("In SageInterface::declarationPreceedsDefinition() (warning): \n");
6176 printf (" nondefiningDeclaration = %p \n",nonDefiningDeclaration);
6177 printf (" nondefiningDeclaration->get_definingDeclaration() = %p \n",nonDefiningDeclaration->get_definingDeclaration());
6178 printf (" definingDeclaration = %p \n",definingDeclaration);
6179 }
6180#endif
6181
6182 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6183 bool returnResult = false;
6184 if (nonDefiningDeclaration != definingDeclaration)
6185 {
6186 // Get the global scope from a traversal back (up) through the AST.
6187 SgGlobal* globalScope = TransformationSupport::getGlobalScope(definingDeclaration);
6188 ROSE_ASSERT(globalScope != NULL);
6189
6190 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6191 DeclarationOrderTraversal traversal (nonDefiningDeclaration,definingDeclaration);
6192
6193#if 0
6194 traversal.traverse(globalScope, preorder);
6195#else
6196 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6197 printf ("Skipping traversal within SageInterface::declarationPreceedsDefinition() \n");
6198 traversal.storedDeclarationFound = true;
6199 traversal.nonDefiningDeclarationPreceedsDefiningDeclaration = false;
6200#endif
6201
6202 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6203 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6204 // nondefining declarations that are not in the traversal).
6205
6206 if (traversal.storedDeclarationFound == false)
6207 {
6208#if 0
6209 printf ("In SageInterface::declarationPreceedsDefinition(): warning, nonDefiningDeclaration not found in the AST \n");
6210 nonDefiningDeclaration->get_file_info()->display("nonDefiningDeclaration");
6211 definingDeclaration->get_file_info()->display("definingDeclaration");
6212 printf ("---------------------------------------------------- \n\n");
6213#endif
6214 // Set this error case to return true so that we will not assume incorrectly
6215 // that the classNonDefiningDeclaration apears after the classDefiningDeclaration.
6216 returnResult = true;
6217 }
6218 else
6219 {
6220 returnResult = traversal.nonDefiningDeclarationPreceedsDefiningDeclaration;
6221 }
6222
6223 // ROSE_ASSERT(traversal.storedDeclarationFound == true);
6224 }
6225#if 0
6226 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6227 printf ("************************************************************* \n\n");
6228#endif
6229 return returnResult;
6230 }
6231
6232
6233bool
6235 {
6236 // This function is used in the unparser, but might be more generally useful. Since it is
6237 // related to general AST tests, I have put it here. It might be alternatively put in the
6238 // src/backend/unparser or related utility directory.
6239
6240 // Preorder traversal to test the order of declaration of non-defining vs. defining class
6241 // declarations in the preorder traversal of the AST.
6242 class DeclarationOrderTraversal : public AstSimpleProcessing
6243 {
6244 public:
6245 DeclarationOrderTraversal( SgFunctionCallExp* functionCall )
6246 : storedFunctionCall(functionCall)
6247 {
6248 ROSE_ASSERT(functionCall != NULL);
6249 ROSE_ASSERT(functionCall->get_function() != NULL);
6250 SgExpression* functionExpression = functionCall->get_function();
6251
6252 switch (functionExpression->variantT())
6253 {
6254 // these are the acceptable cases
6255 case V_SgDotExp:
6256 case V_SgDotStarOp:
6257 case V_SgArrowExp:
6258 case V_SgArrowStarOp:
6259 case V_SgPointerDerefExp:
6260 {
6261 // These are the acceptable cases, but not handled yet.
6262 printf ("These are the acceptable cases, but not handled yet... \n");
6263 ROSE_ABORT();
6264 }
6265
6266 case V_SgFunctionRefExp:
6267 {
6268 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression);
6269 ROSE_ASSERT(functionRefExp != NULL);
6270 SgFunctionSymbol* functionSymbol = functionRefExp->get_symbol();
6271 ROSE_ASSERT(functionSymbol != NULL);
6272
6273 // Make sure that the function has a valid declaration
6274 ROSE_ASSERT(functionSymbol->get_declaration() != NULL);
6275 storedFunctionDeclaration = functionSymbol->get_declaration();
6276 break;
6277 }
6278
6279 case V_SgMemberFunctionRefExp:
6280 {
6281 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression);
6282 ROSE_ASSERT(memberFunctionRefExp != NULL);
6283 SgMemberFunctionSymbol* memberFunctionSymbol = memberFunctionRefExp->get_symbol();
6284 ROSE_ASSERT(memberFunctionSymbol != NULL);
6285
6286 storedFunctionDeclaration = memberFunctionSymbol->get_declaration();
6287
6288 printf ("V_SgMemberFunctionRefExp case not handled yet... \n");
6289 ROSE_ABORT();
6290 }
6291
6292 default:
6293 {
6294 printf ("default reached in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() functionExpression = %s \n",
6295 functionExpression->class_name().c_str());
6296 ROSE_ABORT();
6297 }
6298 }
6299 // ROSE_ASSERT(functionCall->get_declaration() != NULL);
6300 // ROSE_ASSERT(functionCall->get_function()->get_firstNondefiningDeclaration() != NULL);
6301 // storedFunctionDeclaration = functionCall->get_declaration()->get_firstNondefiningDeclaration();
6302 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6303
6304 storedFunctionCallFound = false;
6306 }
6307
6308 void visit (SgNode* node)
6309 {
6310 ROSE_ASSERT(storedFunctionCall != NULL);
6311 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6312 // ROSE_ASSERT(storedFunctionCall != storedFunctionDeclaration);
6313
6314 if (storedFunctionCallFound == false)
6315 {
6316 SgFunctionCallExp* functionCall = isSgFunctionCallExp(node);
6317 if ( functionCall != NULL )
6318 {
6319 if (functionCall == storedFunctionCall)
6320 {
6321 storedFunctionCallFound = true;
6322
6323 // A declaration for the function in a scope where the function could be defined
6324 // (and a scope associated with it) has not been found so the function call
6325 // preceeds such a declaration (if it even exists).
6327 }
6328 }
6329
6330 SgDeclarationStatement* declaration = isSgDeclarationStatement(node);
6331 ROSE_ASSERT(storedFunctionDeclaration != NULL);
6332
6333 // Note that all firstNondefiningDeclaration are set to the same declaration (for all associated declarations).
6334 // Need to check the result of get_firstNondefiningDeclaration() since this will be the same for all declarations
6335 // of the same function and thus can be used to match that we have an associated declaration for the same function.
6336 if ( declaration != NULL && declaration->get_firstNondefiningDeclaration() == storedFunctionDeclaration->get_firstNondefiningDeclaration())
6337 {
6338 // Test if this is a declaration is a scope where the existance of the forward
6339 // declaration will define the scope fo the function declaration.
6340 SgScopeStatement* parentScopeOfDeclaration = isSgScopeStatement(declaration->get_parent());
6341 if (parentScopeOfDeclaration != NULL && parentScopeOfDeclaration->supportsDefiningFunctionDeclaration() == true)
6342 {
6343 // We are done so we can skip further testing
6344 storedFunctionCallFound = true;
6345
6346 // We have found a declaration which will associated the scope of a function declaration
6347 // (so all function calls after this point can be qualified (and might have to be).
6349#if 0
6350 printf ("Found a declaration which preceeds the function \n");
6351 declaration->get_file_info()->display("Found a declaration which preceeds the function: declaration");
6352 storedFunctionCall->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionCall");
6353 storedFunctionDeclaration->get_file_info()->display("Found a declaration which preceeds the function: storedFunctionDeclaration");
6354#endif
6355 }
6356 else
6357 {
6358 // Error checking!
6359 if (parentScopeOfDeclaration == NULL)
6360 {
6361 // This might be a function declaration (non-defining) used in a type or buried deeply in some sort of declaration!
6362 printf ("Strange case of parentScopeOfDeclaration == NULL in SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6363 SgNode* parent = declaration->get_parent();
6364 if (parent != NULL) {
6365 printf ("declaration->get_parent() = %s \n",parent->class_name().c_str());
6366 }
6367 else {
6368 printf ("declaration->get_parent() = NULL \n");
6369 }
6370 declaration->get_file_info()->display("case of parentScopeOfDeclaration == NULL");
6371 ROSE_ABORT();
6372 }
6373 }
6374 }
6375 }
6376 }
6377
6378 public:
6379 bool storedFunctionCallFound;
6381
6382 private:
6383 SgFunctionCallExp* storedFunctionCall;
6384 SgDeclarationStatement* storedFunctionDeclaration;
6385 };
6386
6387 ROSE_ASSERT(functionCall != NULL);
6388#if 0
6389 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): \n");
6390 printf (" storedFunctionCall = %p = %s \n",functionCall,functionCall->class_name().c_str());
6391 functionCall->get_file_info()->display("storedFunctionCall");
6392 printf (" storedFunctionCall->get_function() = %p = %s \n",functionCall->get_function(),functionCall->get_function()->class_name().c_str());
6393 printf ("************************************************************* \n");
6394#endif
6395
6396 // define trival case of classNonDefiningDeclaration == classDefiningDeclaration to be false.
6397 bool returnResult = false;
6398
6399 // Get the global scope from a traversal back (up) through the AST.
6400 SgGlobal* globalScope = TransformationSupport::getGlobalScope(functionCall);
6401 ROSE_ASSERT(globalScope != NULL);
6402
6403 // Now buid the traveral object and call the traversal (preorder) on the function definition.
6404 DeclarationOrderTraversal traversal (functionCall);
6405
6406#if 0
6407 traversal.traverse(globalScope, preorder);
6408#else
6409 // DQ (5/29/2007): To avoid order n^2 complexity in unparsing we turn off the name qualification for now.
6410 printf ("Skipping traversal within SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope() \n");
6411 traversal.storedFunctionCallFound = true;
6412 traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope = false;
6413#endif
6414
6415 // I hope that we have found the input nondefining or defining declaration, if not let it be an error
6416 // for now. There may however be good reasons why we might miss them (hidden island problem, or
6417 // nondefining declarations that are not in the traversal).
6418
6419 if (traversal.storedFunctionCallFound == false)
6420 {
6421#if 0
6422 printf ("In SageInterface::functionCallExpressionPreceedsDeclarationWhichAssociatesScope(): warning, storedFunctionCall not found in the AST \n");
6423 functionCall->get_file_info()->display("functionCall");
6424 printf ("---------------------------------------------------- \n\n");
6425#endif
6426 // Set this error case to return true so that we will not assume incorrectly
6427 // that the function call is used after a declaration that associated the scope
6428 // with the function. This still causes the global name qualifier to be omitted.
6429 returnResult = true;
6430 }
6431 else
6432 {
6433 returnResult = traversal.functionCallExpressionPreceedsDeclarationWhichAssociatesScope;
6434 }
6435
6436 // I hope that this is nearly always be true!
6437 ROSE_ASSERT(traversal.storedFunctionCallFound == true);
6438#if 0
6439 printf ("returnResult = %s \n",returnResult ? "true" : "false");
6440 printf ("************************************************************* \n\n");
6441#endif
6442 return returnResult;
6443 }
6444
6445#endif
6446
6447// #ifndef USE_ROSE
6448
6449string
6450SageInterface::generateProjectName( const SgProject* project, bool supressSuffix )
6451 {
6452 // This function generates a string to use as a unique project name for
6453 // a collection of files. The last file will include it's suffix so that
6454 // we generate proper names that communicate the source language.
6455 // Also also allows the single file case to be consistant with the previous
6456 // version of names generated for "DOT" files in the tutorial.
6457
6458 // DQ (9/6/2008): Introduced optional parameter to supresse the suffix in the
6459 // generation of the project name so that we can support more complex name
6460 // construction as required for the generation of names for the whole AST
6461 // graphs which append an additional suffix to avoid filename collision.
6462
6463 ROSE_ASSERT(project != NULL);
6464 string projectName;
6465
6466 // DQ (9/2/2008): Removed the redundant function getFileNames().
6467 // Rose_STL_Container<string> fileList = project->get_sourceFileNameList();
6468 Rose_STL_Container<string> fileList = project->getAbsolutePathFileNames();
6469
6470 Rose_STL_Container<string>::iterator i = fileList.begin();
6471
6472 // Handle the case of an empty list (e.g. for link lines).
6473 if ( fileList.empty() == true )
6474 {
6475 return "empty_file_list";
6476 }
6477
6478 do {
6479 string filename = *i;
6480
6481 // printf ("In SageInterface::generateProjectName(): absolute filename = %s \n",filename.c_str());
6482
6483 // string filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6484
6485 if (i != fileList.begin())
6486 projectName += "--";
6487
6488 i++;
6489
6490 string filenameWithoutSuffix;
6491 if ( i != fileList.end() || supressSuffix == true )
6492 filenameWithoutSuffix = StringUtility::stripFileSuffixFromFileName(filename);
6493 else
6494 filenameWithoutSuffix = filename;
6495
6496 string filenameWithoutPathOrSuffix = StringUtility::stripPathFromFileName(filenameWithoutSuffix);
6497
6498 // printf ("filenameWithoutSuffix = %s \n",filenameWithoutSuffix.c_str());
6499 // printf ("filenameWithoutPathOrSuffix = %s \n",filenameWithoutPathOrSuffix.c_str());
6500
6501 filename = filenameWithoutPathOrSuffix;
6502
6503 unsigned long int n = 0;
6504 while (n < filename.size())
6505 {
6506 if (filename[n] == '/')
6507 filename[n] = '_';
6508 n++;
6509 }
6510
6511 // printf ("In SageInterface:generateProjectName(): modified absolute filename = %s \n",filename.c_str());
6512
6513 projectName += filename;
6514
6515 // printf ("In SageInterface:generateProjectName(): evolving projectName = %s \n",projectName.c_str());
6516 }
6517 while (i != fileList.end());
6518
6519 // printf ("In SageInterface:generateProjectName(): projectName = %s \n",projectName.c_str());
6520
6521 return projectName;
6522 }
6523
6524// #endif
6525
6526// #ifndef USE_ROSE
6527
6530 {
6531 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6532 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6533
6534 // enable default search from top of StackScope, Liao, 1/24/2008
6535 SgFunctionSymbol* functionSymbol = NULL;
6536 if (currentScope == NULL)
6537 currentScope = SageBuilder::topScopeStack();
6538 ROSE_ASSERT(currentScope != NULL);
6539
6540 SgScopeStatement* tempScope = currentScope;
6541 while ((functionSymbol == NULL) && (tempScope != NULL))
6542 {
6543 functionSymbol = tempScope->lookup_function_symbol(functionName);
6544#if 0
6545 printf ("In lookupFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6546#endif
6547 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6548 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6549 else
6550 tempScope = NULL;
6551 }
6552 return functionSymbol;
6553 }
6554
6556SageInterface::lookupTemplateFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6557 {
6558 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6559 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6560
6561 // enable default search from top of StackScope, Liao, 1/24/2008
6562 SgFunctionSymbol* functionSymbol = NULL;
6563 if (currentScope == NULL)
6564 currentScope = SageBuilder::topScopeStack();
6565 ROSE_ASSERT(currentScope != NULL);
6566
6567 SgScopeStatement* tempScope = currentScope;
6568 while ((functionSymbol == NULL) && (tempScope != NULL))
6569 {
6570 functionSymbol = tempScope->lookup_template_function_symbol(functionName, ftype, tplparams);
6571#if 0
6572 printf ("In lookupTemplateFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6573#endif
6574 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6575 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6576 else
6577 tempScope = NULL;
6578 }
6579 return functionSymbol;
6580 }
6581
6583SageInterface::lookupTemplateMemberFunctionSymbolInParentScopes(const SgName & functionName, SgFunctionType * ftype, SgTemplateParameterPtrList * tplparams, SgScopeStatement* currentScope )
6584 {
6585 // DQ (11/24/2007): This function can return NULL. It returns NULL when the function symbol is not found.
6586 // This can happen when a function is referenced before it it defined (no prototype mechanism in Fortran is required).
6587
6588 // enable default search from top of StackScope, Liao, 1/24/2008
6589 SgFunctionSymbol* functionSymbol = NULL;
6590 if (currentScope == NULL)
6591 currentScope = SageBuilder::topScopeStack();
6592 ROSE_ASSERT(currentScope != NULL);
6593
6594 SgScopeStatement* tempScope = currentScope;
6595 while ((functionSymbol == NULL) && (tempScope != NULL))
6596 {
6597 functionSymbol = tempScope->lookup_template_member_function_symbol(functionName, ftype, tplparams);
6598#if 0
6599 printf ("In lookupTemplateMemberFunctionSymbolInParentScopes(): Searching scope = %p = %s functionName = %s functionSymbol = %p \n",tempScope,tempScope->class_name().c_str(),functionName.str(),functionSymbol);
6600#endif
6601 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set in middle of translation
6602 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6603 else
6604 tempScope = NULL;
6605 }
6606 return functionSymbol;
6607 }
6608
6609void
6610SageInterface::addTextForUnparser ( SgNode* astNode, string s, AstUnparseAttribute::RelativePositionType inputlocation )
6611 {
6612 // printf ("addText(): using new attribute interface (s = %s) \n",s.c_str());
6613
6614 if (isSgType(astNode) != NULL)
6615 {
6616 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");
6617 ROSE_ABORT();
6618 }
6619
6620 if (astNode->attributeExists(AstUnparseAttribute::markerName) == true)
6621 {
6622 AstUnparseAttribute* code = dynamic_cast<AstUnparseAttribute*>(astNode->getAttribute(AstUnparseAttribute::markerName));
6623 ROSE_ASSERT(code != NULL);
6624
6625 // DQ (2/23/2009): commented added.
6626 // Since there is at least one other string (there is an existing attribute) the relative order of the strings is significant.
6627 code->addString(s,inputlocation);
6628 }
6629 else
6630 {
6631 // DQ (2/25/2016): I think it is significant, because inputlocation refers to the order relative to
6632 // the statement, not relative to other AstUnparseAttribute objects. Fixed to use the inputlocation.
6633 // DQ (2/23/2009): commented added.
6634 // Note that this will be the only string in the attribute, so inputlocation is not significant (and e_before is the default used).
6635 // AstUnparseAttribute* code = new AstUnparseAttribute(s,AstUnparseAttribute::e_before);
6636 AstUnparseAttribute* code = new AstUnparseAttribute(s,inputlocation);
6637 ROSE_ASSERT(code != NULL);
6638
6639 astNode->addNewAttribute(AstUnparseAttribute::markerName,code);
6640 }
6641 }
6642
6643
6644#if 0
6645// DQ (7/20/2011): Resolving conflict, this was added in previous work in dq-cxx-rc branch.
6646// DQ (7/17/2011): Added function from cxx branch that I need here for the Java support.
6649 {
6650 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6651 SgClassSymbol* symbol = NULL;
6652 if (cscope == NULL)
6653 cscope = SageBuilder::topScopeStack();
6654 ROSE_ASSERT(cscope != NULL);
6655
6656 while ((cscope != NULL) && (symbol == NULL))
6657 {
6658 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6659 symbol = cscope->lookup_class_symbol(name,NULL);
6660
6661 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6662 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6663 else
6664 cscope = NULL;
6665 }
6666
6667 return symbol;
6668 }
6669#endif
6670
6671
6672
6673SgType* SageInterface::lookupNamedTypeInParentScopes(const std::string& type_name, SgScopeStatement* scope/*=NULL*/)
6674 {
6675 if (scope == NULL)
6677
6678 // DQ (8/16/2013): Added NULL pointers to at least handle the API change.
6679 SgSymbol* symbol = lookupSymbolInParentScopes (type_name,scope,NULL,NULL);
6680
6681 if (symbol == NULL)
6682 return NULL;
6683 else
6684 return symbol->get_type();
6685 }
6686
6688 const SgType* t,
6689 SgScopeStatement *currentScope)
6690 //SgScopeStatement *currentScope=NULL)
6691{
6692 SgFunctionSymbol* functionSymbol = NULL;
6693 if (currentScope == NULL)
6694 currentScope = SageBuilder::topScopeStack();
6695 ROSE_ASSERT(currentScope != NULL);
6696 SgScopeStatement* tempScope = currentScope;
6697 while (functionSymbol == NULL && tempScope != NULL)
6698 {
6699 functionSymbol = tempScope->lookup_function_symbol(functionName,t);
6700 if (tempScope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6701 tempScope = isSgGlobal(tempScope) ? NULL : tempScope->get_scope();
6702 else tempScope = NULL;
6703 }
6704 return functionSymbol;
6705}
6706
6707SgSymbol*
6708SageInterface::lookupSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6709 {
6710 SgSymbol* symbol = nullptr;
6711 if (cscope == nullptr) {
6712 cscope = SageBuilder::topScopeStack();
6713 }
6714 ASSERT_not_null(cscope);
6715
6716 while ((cscope != nullptr) && (symbol == nullptr))
6717 {
6718 symbol = cscope->lookup_symbol(name,templateParameterList,templateArgumentList);
6719 if (cscope->get_parent() != nullptr) // avoid calling get_scope when parent is not set
6720 cscope = isSgGlobal(cscope) ? nullptr : cscope->get_scope();
6721 else
6722 cscope = nullptr;
6723 }
6724
6725 return symbol;
6726 }
6727
6728
6729
6730SgSymbol*
6731SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols (const SgName & name, SgScopeStatement *currentScope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6732 {
6733 // DQ (8/5/2020): the "using namespace" directive will not hide existing visability of symbols in resolving visability.
6734 // So we need to test if a symbol is visible exclusing matching alises due to using direectives before we can decide to
6735 // persue name space qualification. This is best demonstrated by Cxx_tests/test2020_18.C, test2020_19.C, test2020_20.C,
6736 // and test2020_21.C.
6737
6738// DQ (7/14/2025): Adding timers to support Matt's tool.
6739#define USING_PERFORMANCE_TRACING 0
6740
6741 SgSymbol* symbol = NULL;
6742
6743#if USING_PERFORMANCE_TRACING
6744 // DQ (7/14/2025): Adding timers to support Matt's tool.
6745 TimingPerformance timer1 ("SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols: whole function:");
6746#endif
6747
6748 if (currentScope == NULL)
6749 {
6750 currentScope = SageBuilder::topScopeStack();
6751 }
6752
6753 ROSE_ASSERT(currentScope != NULL);
6754
6755#define DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS 0
6756
6757#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6758 printf ("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): currentScope = %p = %s (templateParameterList = %p templateArgumentList = %p) \n",
6759 currentScope,currentScope->class_name().c_str(),templateParameterList,templateArgumentList);
6760#endif
6761
6762 while ((currentScope != NULL) && (symbol == NULL))
6763 {
6764#if USING_PERFORMANCE_TRACING
6765 // DQ (7/14/2025): Adding timers to support Matt's tool.
6766 TimingPerformance timer1 ("SageInterface::lookupSymbolInParentScopesIgnoringAliasSymbols: in loop:");
6767#endif
6768
6769#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6770 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): name = %s currentScope = %p = %s \n",
6771 name.str(),currentScope,currentScope->class_name().c_str());
6772#endif
6773
6774 // DQ (8/16/2013): Changed API to support template parameters and template arguments.
6775 // symbol = cscope->lookup_symbol(name);
6776 symbol = currentScope->lookup_symbol(name,templateParameterList,templateArgumentList);
6777
6778 if (isSgAliasSymbol(symbol) != NULL)
6779 {
6780#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6781 printf ("Found a SgAliasSymbol: reset to NULL: symbol = %p = %s \n",symbol,symbol->class_name().c_str());
6782#endif
6783 symbol = NULL;
6784 }
6785
6786#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS && 1
6787 // debug
6788 printf(" --- In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): symbol = %p \n",symbol);
6789 currentScope->print_symboltable("In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): debug");
6790#endif
6791 if (currentScope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6792 currentScope = isSgGlobal(currentScope) ? NULL : currentScope->get_scope();
6793 else
6794 currentScope = NULL;
6795
6796#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6797 printf (" --- In SageInterface:: (base of loop) lookupSymbolInParentScopesIgnoringAliasSymbols(): cscope = %p symbol = %p \n\n",currentScope,symbol);
6798#endif
6799 }
6800
6801 if (symbol == NULL)
6802 {
6803#if DEBUG_SYMBOL_LOOKUP_IN_PARENT_SCOPES_IGNORING_ALIAS_SYMBOLS
6804 printf ("Warning: In SageInterface:: lookupSymbolInParentScopesIgnoringAliasSymbols(): could not locate the specified name %s in any outer symbol table (templateParameterList = %p templateArgumentList = %p) \n",
6805 name.str(),templateParameterList,templateArgumentList);
6806#endif
6807 // ROSE_ASSERT(false);
6808 }
6809
6810#if 0
6811 printf ("Support for lookupSymbolInParentScopesIgnoringAliasSymbols() is not yet implemented \n");
6812 ROSE_ABORT();
6813#endif
6814
6815 return symbol;
6816 }
6817
6818
6819
6820
6821
6822
6823
6824
6825#if 0
6826// DQ (7/13/2011): This was part of a merge conflict with the above modified function.
6827// It appeas they are the same so this one is commented out.
6829{
6830 SgSymbol* symbol = NULL;
6831 if (cscope == NULL)
6832 cscope = SageBuilder::topScopeStack();
6833 ROSE_ASSERT(cscope);
6834
6835 while ((cscope!=NULL)&&(symbol==NULL))
6836 {
6837 symbol = cscope->lookup_symbol(name);
6838 //debug
6839 // cscope->print_symboltable("debug sageInterface.C L3749...");
6840 if (cscope->get_parent()!=NULL) // avoid calling get_scope when parent is not set
6841 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6842 else
6843 cscope = NULL;
6844 }
6845
6846 if (symbol==NULL)
6847 {
6848 // printf ("Warning: could not locate the specified name %s in any outer symbol table \n"e,
6849 // name.str());
6850 // ROSE_ASSERT(false);
6851 }
6852 return symbol;
6853}
6854#endif
6855
6858 {
6859 // DQ (1/24/2011): This function is inconsistant with an implementation that would correctly handle SgAliasSymbols.
6860 // Also this function might get a SgClassSymbol instead of a SgVariableSymbol when both names are used.
6861 // This function needs to be fixed to handle the multi-map semantics of the symbol tables.
6862
6863#if 0
6864 // DQ (5/7/2011): I think this implementation is not correct (does not resolve past hidden types) and so should
6865 // be fixed to be consistant with the implementation of SageInterface::lookupClassSymbolInParentScopes().
6866 // Since I don't know where this function is used, I don't want to change it just yet.
6867 printf ("WARNING: SageInterface::lookupVariableSymbolInParentScopes() should be implemented similar to SageInterface::lookupClassSymbolInParentScopes() \n");
6868
6869 SgVariableSymbol* result = NULL;
6870 SgSymbol* symbol=lookupSymbolInParentScopes(name,cscope);
6871 if (symbol != NULL)
6872 {
6873 if (isSgAliasSymbol(symbol) != NULL)
6874 {
6875 printf ("Error: This SageInterface::lookupVariableSymbolInParentScopes() function does not handle SgAliasSymbols \n");
6876 ROSE_ABORT();
6877 }
6878 result = isSgVariableSymbol(symbol);
6879 }
6880 return result;
6881#else
6882 // I think this is the better implementation.
6883 SgVariableSymbol* symbol = NULL;
6884 if (cscope == NULL)
6885 cscope = SageBuilder::topScopeStack();
6886 ROSE_ASSERT(cscope != NULL);
6887
6888 while ((cscope != NULL) && (symbol == NULL))
6889 {
6890 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6891 symbol = cscope->lookup_variable_symbol(name);
6892
6893 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6894 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6895 else
6896 cscope = NULL;
6897 }
6898
6899 return symbol;
6900#endif
6901 }
6902
6903#define DEBUG_LOOKUP_TEMPLATE_VARIABLE 0
6904
6906SageInterface::lookupTemplateVariableSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList * tplparams, SgTemplateArgumentPtrList* tplargs, SgScopeStatement *cscope)
6907 {
6908#if DEBUG_LOOKUP_TEMPLATE_VARIABLE
6909 printf ("In SageInterface::lookupTemplateVariableSymbolInParentScopes():\n");
6910 printf (" -- name = %s\n", name.str());
6911 printf (" -- tplparams = %p [%zd]\n", tplparams, tplparams ? tplparams->size() : 0);
6912 printf (" -- tplargs = %p [%zd]\n", tplargs, tplargs ? tplargs->size() : 0);
6913 printf (" -- cscope = %p (%s)\n", cscope, cscope ? cscope->class_name().c_str() : "");
6914#endif
6915
6916 SgTemplateVariableSymbol* symbol = NULL;
6917 if (cscope == NULL)
6918 cscope = SageBuilder::topScopeStack();
6919 ROSE_ASSERT(cscope != NULL);
6920
6921 while ((cscope != NULL) && (symbol == NULL))
6922 {
6923 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6924 symbol = cscope->lookup_template_variable_symbol(name, tplparams, tplargs);
6925
6926 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6927 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6928 else
6929 cscope = NULL;
6930 }
6931
6932 return symbol;
6933 }
6934
6935// SgClassSymbol* SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
6937SageInterface::lookupClassSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateArgumentPtrList* templateArgumentList)
6938 {
6939 // DQ (5/7/2011): I think this is the better implementation that lookupVariableSymbolInParentScopes() should have.
6940 SgClassSymbol* symbol = NULL;
6941 if (cscope == NULL)
6942 cscope = SageBuilder::topScopeStack();
6943 ROSE_ASSERT(cscope != NULL);
6944
6945 while ((cscope != NULL) && (symbol == NULL))
6946 {
6947 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6948 // symbol = cscope->lookup_class_symbol(name,NULL);
6949 symbol = cscope->lookup_class_symbol(name,templateArgumentList);
6950
6951 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6952 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6953 else
6954 cscope = NULL;
6955 }
6956
6957 return symbol;
6958 }
6959
6961SageInterface::lookupNonrealSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList)
6962 {
6963 SgNonrealSymbol* symbol = NULL;
6964 if (cscope == NULL)
6965 cscope = SageBuilder::topScopeStack();
6966 ROSE_ASSERT(cscope != NULL);
6967
6968 while ((cscope != NULL) && (symbol == NULL))
6969 {
6970 symbol = cscope->lookup_nonreal_symbol(name,templateParameterList,templateArgumentList);
6971
6972 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
6973 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
6974 else
6975 cscope = NULL;
6976 }
6977
6978 return symbol;
6979 }
6980
6983 {
6984 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
6985 SgTypedefSymbol* symbol = NULL;
6986 if (cscope == NULL)
6987 cscope = SageBuilder::topScopeStack();
6988 ROSE_ASSERT(cscope != NULL);
6989
6990#if 0
6991 printf ("In lookupTypedefSymbolInParentScopes(): name = %s starting with cscope = %p = %s \n",name.str(),cscope,cscope->class_name().c_str());
6992 printf ("--- parent scope = %p = %s \n",cscope->get_scope(),(cscope->get_scope() != NULL) ? cscope->get_scope()->class_name().c_str() : "null");
6993#endif
6994
6995 while ((cscope != NULL) && (symbol == NULL))
6996 {
6997 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
6998 symbol = cscope->lookup_typedef_symbol(name);
6999
7000 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7001 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7002 else
7003 cscope = NULL;
7004
7005#if 0
7006 printf ("In lookupTypedefSymbolInParentScopes(): symbol = %p next cscope = %p = %s \n",symbol,cscope,(cscope != NULL) ? cscope->class_name().c_str() : "null");
7007#endif
7008 }
7009
7010#if 0
7011 printf ("Leaving lookupTypedefSymbolInParentScopes(): symbol = %p \n",symbol);
7012#endif
7013
7014 return symbol;
7015 }
7016
7017#if 0
7018// DQ (8/13/2013): This function does not make since any more, now that we have make the symbol
7019// table handling more precise and we have to provide template parameters for any template lookup.
7020// We also have to know if we want to lookup template classes, template functions, or template
7021// member functions (since each have specific requirements).
7023SageInterface::lookupTemplateSymbolInParentScopes (const SgName & name, SgScopeStatement *cscope)
7024 {
7025 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7026 SgTemplateSymbol* symbol = NULL;
7027 if (cscope == NULL)
7028 cscope = SageBuilder::topScopeStack();
7029 ROSE_ASSERT(cscope != NULL);
7030
7031 while ((cscope != NULL) && (symbol == NULL))
7032 {
7033 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7034 // In this case these are unavailable from this point.
7035 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7036 // symbol = cscope->lookup_template_symbol(name);
7037 symbol = cscope->lookup_template_symbol(name,NULL,NULL);
7038#if 0
7039 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7040#endif
7041 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7042 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7043 else
7044 cscope = NULL;
7045 }
7046
7047 return symbol;
7048 }
7049#endif
7050
7051
7053SageInterface::lookupTemplateClassSymbolInParentScopes (const SgName & name, SgTemplateParameterPtrList* templateParameterList, SgTemplateArgumentPtrList* templateArgumentList, SgScopeStatement *cscope)
7054 {
7055 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7056 SgTemplateClassSymbol* symbol = NULL;
7057 if (cscope == NULL)
7058 cscope = SageBuilder::topScopeStack();
7059 ROSE_ASSERT(cscope != NULL);
7060
7061 while ((cscope != NULL) && (symbol == NULL))
7062 {
7063 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
7064 // In this case these are unavailable from this point.
7065 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7066 // symbol = cscope->lookup_template_symbol(name);
7067 symbol = cscope->lookup_template_class_symbol(name,templateParameterList,templateArgumentList);
7068#if 0
7069 printf ("In lookupTemplateSymbolInParentScopes(): Searching scope = %p = %s name = %s symbol = %p \n",cscope,cscope->class_name().c_str(),name.str(),symbol);
7070#endif
7071 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7072 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7073 else
7074 cscope = NULL;
7075 }
7076
7077 return symbol;
7078 }
7079
7080
7083 {
7084 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7085 // A templated solution might make for a better implementation.
7086 SgEnumSymbol* symbol = NULL;
7087 if (cscope == NULL)
7088 cscope = SageBuilder::topScopeStack();
7089 ROSE_ASSERT(cscope != NULL);
7090
7091 while ((cscope != NULL) && (symbol == NULL))
7092 {
7093 // I think this will resolve SgAliasSymbols to be a SgClassSymbol where the alias is of a SgClassSymbol.
7094 symbol = cscope->lookup_enum_symbol(name);
7095
7096 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7097 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7098 else
7099 cscope = NULL;
7100 }
7101
7102 return symbol;
7103 }
7104
7107 {
7108 // DQ (5/7/2011): This is similar to lookupClassSymbolInParentScopes().
7109 SgNamespaceSymbol* symbol = NULL;
7110 if (cscope == NULL)
7111 cscope = SageBuilder::topScopeStack();
7112 ROSE_ASSERT(cscope != NULL);
7113
7114 while ((cscope != NULL) && (symbol == NULL))
7115 {
7116 // I think this will resolve SgAliasSymbols to be a SgNamespaceSymbol where the alias is of a SgNamespaceSymbol.
7117 symbol = cscope->lookup_namespace_symbol(name);
7118
7119 if (cscope->get_parent() != NULL) // avoid calling get_scope when parent is not set
7120 cscope = isSgGlobal(cscope) ? NULL : cscope->get_scope();
7121 else
7122 cscope = NULL;
7123 }
7124
7125 return symbol;
7126 }
7127
7128template<class T>
7129void
7130SageInterface::setSourcePositionToDefault( T* node )
7131 {
7132 // This is a templated function because SgPragma is not yet derived from SgLocatedNode.
7133
7134 // DQ (2/17/2013): This function is called a lot, so it might be a performance issue.
7135 // All IR nodes built by the Build Interface are assighed source position information
7136 // using this function and then reset afterward as we use information within EDG to
7137 // reset the source position information. Ideally, the EDG/ROSE connection would
7138 // use NULL pointers as the behavior for the front-end mode. We can move to that
7139 // later to maek the source position handling more efficient.
7140
7141 // DQ (1/24/2009): It might be that this function is only called from the Fortran support.
7142
7143 // This function sets the source position to be marked as not
7144 // available (since we often don't have token information)
7145 // These nodes WILL be unparsed in the conde generation phase.
7146
7147 // The SgLocatedNode has both a startOfConstruct and endOfConstruct source position.
7148 ROSE_ASSERT(node != NULL);
7149
7150 // We have to support this being called where the Sg_File_Info have previously been set.
7151 if (node->get_endOfConstruct() == NULL && node->get_startOfConstruct() == NULL)
7152 {
7153#if 0
7154 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());
7155#endif
7156 // Check the endOfConstruct first since it is most likely NULL (helpful in debugging)
7157 ROSE_ASSERT(node->get_endOfConstruct() == NULL);
7158 ROSE_ASSERT(node->get_startOfConstruct() == NULL);
7159
7162
7163 // DQ (5/2/2012): I think we don't want to do this.
7164#if 0
7165 printf ("In SageInterface::setSourcePositionToDefault(): Calling setSourcePositionUnavailableInFrontend() \n");
7166#endif
7167 start_fileInfo->setSourcePositionUnavailableInFrontend();
7168 end_fileInfo->setSourcePositionUnavailableInFrontend();
7169
7170 // DQ (5/2/2012): I think we don't want to do this.
7171#if 0
7172 printf ("In SageInterface::setSourcePositionToDefault(): Calling setOutputInCodeGeneration() \n");
7173#endif
7174 // This is required for the unparser to output the code from the AST.
7175 start_fileInfo->setOutputInCodeGeneration();
7176 end_fileInfo->setOutputInCodeGeneration();
7177
7178 node->set_startOfConstruct(start_fileInfo);
7179 node->set_endOfConstruct (end_fileInfo);
7180
7181 node->get_startOfConstruct()->set_parent(node);
7182 node->get_endOfConstruct ()->set_parent(node);
7183 }
7184 else
7185 {
7186 // If both the starting and ending Sg_File_Info pointers are not NULL then both must be valid.
7187 // We don't want to support partially completed source code position information.
7188#if 0
7189 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());
7190#endif
7191 if (node->get_startOfConstruct() == NULL)
7192 {
7193 printf ("ERROR: startOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7194 }
7195 if (node->get_endOfConstruct() == NULL)
7196 {
7197 printf ("ERROR: endOfConstruct not set for locatedNode = %p = %s \n",node,node->class_name().c_str());
7198 }
7199
7200 ROSE_ASSERT(node->get_startOfConstruct() != NULL);
7201 ROSE_ASSERT(node->get_endOfConstruct() != NULL);
7202 ROSE_ASSERT(node->get_endOfConstruct() != NULL && node->get_startOfConstruct() != NULL);
7203 }
7204
7205 // DQ (11/2/2012): This is an important fix to support the new EDG 4.x branch.
7206 // Note that because the unparser will use the function isFromAnotherFile() in the unparsing
7207 // of expressions, specifically: SgAggregateInitializer, SgCompoundInitializer, and anything
7208 // in their expression lists (which could be any expression). The isFromAnotherFile() will
7209 // use the get_file_info() function on the SgExpression IR nodes and the data from that
7210 // Sg_File_Info object to determine if that expression subtree should be unparsed. This
7211 // expression level granularity of unparsing capability is extremely useful in handling
7212 // now #includes and other CPP directives are woven back into the AST. But since the
7213 // get_file_info() function is used, and it returns the value of get_operatorPosition(),
7214 // it is critically important to have correct data in the SgExpression::p_operatorPosition
7215 // Sg_File_Info object (it counts more that the startOfConstruct and endOfConstruct
7216 // Sg_File_Info objects in controlling what expressions are unparsed. So we have to set these
7217 // up for all expressions (since any SgExpression could appear in the list contained in
7218 // a SgAggregateInitializer or SgCompoundInitializer.
7219
7220 // DQ (11/2/2012): Set the operator source position information to default values.
7221 // This will trigger it to be reset to valid source position information in the front-end.
7222 SgExpression* expression = isSgExpression(node);
7223 if (expression != NULL)
7224 {
7225#if 0
7226 SgBinaryOp* binaryOp = isSgBinaryOp(expression);
7227 if (binaryOp != NULL)
7228 {
7229 if (binaryOp->get_operatorPosition() == NULL)
7230 {
7232 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7233 operator_fileInfo->setOutputInCodeGeneration();
7234 binaryOp->set_operatorPosition(operator_fileInfo);
7235
7236 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7237 binaryOp->get_operatorPosition()->set_parent(binaryOp);
7238 }
7239 }
7240#else
7241 // Setup all of the SgExpression operatorPosition pointers to default objects.
7242 if (expression->get_operatorPosition() == NULL)
7243 {
7245 operator_fileInfo->setSourcePositionUnavailableInFrontend();
7246 operator_fileInfo->setOutputInCodeGeneration();
7247 expression->set_operatorPosition(operator_fileInfo);
7248
7249 // This is equivalent to: "operator_fileInfo->set_parent(binaryOp);"
7250 // expression->get_operatorPosition()->set_parent(expression);
7251 operator_fileInfo->set_parent(expression);
7252 ROSE_ASSERT(expression->get_operatorPosition()->get_parent() == expression);
7253 }
7254#endif
7255 }
7256 }
7257
7258
7259void
7261 {
7262 // DQ (5/1/2012): Older depricated function.
7263#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
7264 printf ("+++++ Depricated function (use setSourcePositionAsTransformation() instead) (no using internal source position mode) \n");
7265#endif
7266
7267 // setSourcePositionAsTransformation(node);
7268 setSourcePosition(node);
7269 }
7270
7271
7272void
7274 {
7275 // DQ (5/1/2012): Newer function to support specification of IR nodes being a part of a transformation.
7276
7277 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionAsTransformation(SgNode *node)"
7278 // The logic should be make more independent of if (locatedNode->get_startOfConstruct() == NULL)
7279 // Since that make understanding where the function is applied too complex.
7280 // If (locatedNode->get_startOfConstruct() != NULL), then we should just make that Sg_File_Info as
7281 // a transforamtion directly, this function misses that step.
7282
7283 ROSE_ASSERT(node != NULL);
7284
7285 // DQ (10/12/2012): Commented out since we are past AST regression tests passing and now trying to get this work checked in.
7286// printf ("In SageInterface::setSourcePositionAsTransformation() for node = %p = %s (make this an error while debugging AST construction) \n",node,node->class_name().c_str());
7287 // ROSE_ASSERT(false);
7288
7289 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7290 SgExpression* expression = isSgExpression(node);
7291 // SgInitializedName* initName = isSgInitializedName(node);
7292 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7293 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7294
7295#if 0
7296 SgVariableDefinition * v_d = isSgVariableDefinition(node);
7297 if (v_d )
7298 printf ("Debug, Found a variable definition: %p\n", v_d);
7299#endif
7300
7301 if (locatedNode != NULL)
7302 {
7304 locatedNode->get_startOfConstruct()->set_parent(locatedNode);
7305
7306 if (global==NULL)
7307 {
7309 locatedNode->get_endOfConstruct ()->set_parent(locatedNode);
7310 }
7311
7312 // Only SgExpression IR nodes have a 3rd source position data structure.
7313 if (expression!=NULL)
7314 {
7315 expression->set_operatorPosition(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7316 expression->get_operatorPosition()->set_parent(expression);
7317 }
7318 }
7319 else // special non-located node with file info
7320 {
7321 if ( (pragma != NULL) && (pragma->get_startOfConstruct() == NULL) )
7322 {
7323 pragma->set_startOfConstruct(Sg_File_Info::generateDefaultFileInfoForTransformationNode());
7324 pragma->get_startOfConstruct()->set_parent(pragma);
7325 }
7326 }
7327 }
7328
7329
7330void
7332 {
7333 // DQ (5/1/2012): Older depricated function (use setSourcePositionPointersToNull() instead).
7334#if 0
7335 printf ("+++++ Depricated name setOneSourcePositionNull() (use setSourcePositionPointersToNull() instead) (no using internal source position mode) \n");
7336#endif
7337
7338 setSourcePosition(node);
7339 }
7340
7341// DQ (5/1/2012): Newly renamed function (previous name preserved for backward compatability).
7342void
7344 {
7345 // DQ (1/24/2009): I think this should be renamed to be "setSourcePositionToNULL(SgNode *node)"
7346 // However, if this is doen then the logic should be that it asserts that: (locatedNode->get_startOfConstruct() == NULL)
7347 // so that we know when we are leaking memory. Similarly, we should assert that:
7348 // (locatedNode->get_endOfConstruct() == NULL).
7349 // But then this function just asserts that everything is already NULL and is less about setting them to NULL.
7350 // If (locatedNode->get_startOfConstruct() != NULL), should we delete the existing Sg_File_Info object?
7351 // This function misses that step.
7352
7353 ROSE_ASSERT(node != NULL);
7354
7355 SgLocatedNode * locatedNode = isSgLocatedNode(node);
7356 SgExpression* expression = isSgExpression(node);
7357 SgPragma* pragma = isSgPragma(node); // missed this one!! Liao, 1/30/2008
7358 SgGlobal* global = isSgGlobal(node); // SgGlobal should have NULL endOfConstruct()
7359
7360 // DQ (1/24/2009): If the point is to set the source position to NULL pointers,
7361 // why do we only handle the case when (get_startOfConstruct() == NULL)
7362 // (i.e. when the start source postion is already NULL).
7363
7364 if (locatedNode != NULL)
7365 {
7366 if (locatedNode->get_startOfConstruct() != NULL)
7367 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of startOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7368
7369 locatedNode->set_startOfConstruct(NULL);
7370
7371 // Note that SgGlobal should have NULL endOfConstruct()
7372 if (global == NULL)
7373 {
7374 if (locatedNode->get_endOfConstruct() != NULL)
7375 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of endOfConstruct Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7376
7377 locatedNode->set_endOfConstruct(NULL);
7378 }
7379
7380 // Only SgExpression IR nodes have a 3rd source position data structure.
7381 if (expression != NULL)
7382 {
7383 if (expression->get_operatorPosition() != NULL)
7384 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of operatorPosition Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7385
7386 expression->set_operatorPosition(NULL);
7387 }
7388 }
7389 else
7390 {
7391 if ( (pragma != NULL) && (pragma->get_startOfConstruct() != NULL) )
7392 {
7393 printf ("WARNING: In SageInterface::setSourcePositionPointersToNull(): Memory leak of Sg_File_Info object (setting Sg_File_Info pointers to NULL) \n");
7394
7395 pragma->set_startOfConstruct(NULL);
7396 }
7397 }
7398 }
7399
7400// DQ (1/24/2009): Could we change the name to be "setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)"
7401void
7403 {
7404#if 1
7405#if 0
7406 printf ("+++++ Depricated name setSourcePositionForTransformation() (use setSourcePositionAtRootAndAllChildrenAsTransformation() instead) \n");
7407#endif
7408
7409 // This is the semantically correct function to call.
7410 // setSourcePositionAtRootAndAllChildrenAsTransformation(root);
7411
7412 // 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.
7413 // setSourcePosition(root);
7414 // Liao 11/21/2012. This function should only be called when the mode is transformation
7415 // Liao 8/2/2013. It can actually be called inside frontend by OmpSupport::lower_omp().
7416 //ROSE_ASSERT(SageBuilder::SourcePositionClassificationMode == SageBuilder::e_sourcePositionTransformation);
7418#else
7419 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7420 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7421 {
7423 }
7424#endif
7425 }
7426
7427
7428#if 0
7429// DQ (5/1/2012): New function with improved name (still preserving the previous interface).
7430void
7431SageInterface::setSourcePositionAtRootAndAllChildrenAsTransformation(SgNode *root)
7432 {
7433 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7434 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7435 {
7437 }
7438 }
7439#endif
7440
7441#if 0
7442void
7443SageInterface::setSourcePositionAtRootAndAllChildrenAsDefault(SgNode *root)
7444 {
7445 Rose_STL_Container <SgNode*> nodeList= NodeQuery::querySubTree(root,V_SgNode);
7446 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i!=nodeList.end(); i++ )
7447 {
7448 setSourcePositionAsDefault(*i);
7449 }
7450 }
7451#endif
7452
7453void
7455 {
7456 // DQ (2/17/2013): This is a relatively expensive operation so we might look into this.
7457
7458 Rose_STL_Container <SgNode*> nodeList = NodeQuery::querySubTree(root,V_SgNode);
7459
7460#if 0
7461 printf ("In setSourcePositionAtRootAndAllChildren(): nodeList.size() = %" PRIuPTR " \n",nodeList.size());
7462#endif
7463
7464 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
7465 {
7466#if 0
7467 printf ("In setSourcePositionAtRootAndAllChildren(): *i = %p = %s \n",*i,(*i)->class_name().c_str());
7468#endif
7470 }
7471 }
7472
7473// DQ (5/1/2012): This function queries the SageBuilder::SourcePositionClassification mode (stored in the SageBuilder
7474// interface) and used the specified mode to initialize the source position data (Sg_File_Info objects). This
7475// function is the only function that should be called directly (though in a namespace we can't define permissions).
7476void
7478 {
7479 // Check the mode and build the correct type of source code position.
7481
7482 // DQ (2/17/2013): Note that the SourcePositionClassification will be e_sourcePositionFrontendConstruction
7483 // during construction of the AST from the EDG frontend.
7484
7485#if 0
7486 printf ("In SageInterface::setSourcePosition(): SourcePositionClassification scp = %s \n",display(scp).c_str());
7487#endif
7488
7489 switch(scp)
7490 {
7491 case e_sourcePositionError: // Error value for enum.
7492 {
7493 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7494 ROSE_ABORT();
7495 }
7496
7497 case e_sourcePositionDefault: // Default source position.
7498 {
7499#if 0
7500 printf ("e_sourcePositionDefault in SageInterface::setSourcePosition() \n");
7501#endif
7502 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7503 if (locatedNode != NULL)
7504 {
7505 setSourcePositionToDefault(locatedNode);
7506 }
7507 else
7508 {
7509 // This is not supported (not clear if it need be).
7510 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionDefault with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7511 ROSE_ABORT();
7512 }
7513 break;
7514 }
7515
7516 case e_sourcePositionTransformation: // Classify as a transformation.
7517 {
7518#if 0
7519 printf ("e_sourcePositionTransformation in SageInterface::setSourcePosition() \n");
7520#endif
7521 // setSourcePositionAtRootAndAllChildrenAsTransformation(node);
7523 break;
7524 }
7525
7526 case e_sourcePositionCompilerGenerated: // Classify as compiler generated code (e.g. template instantiation).
7527 {
7528 printf ("e_sourcePositionCompilerGenerated in SageInterface::setSourcePosition() \n");
7529
7530 printf ("Sorry, not implemented \n");
7531 ROSE_ABORT();
7532 }
7533
7534 case e_sourcePositionNullPointers: // Set pointers to Sg_File_Info objects to NULL.
7535 {
7536 // DQ (2/17/2013): We want to move to this mode as the one used for EDG/ROSE connection so that we can
7537 // avoid building and rebuilding source position information.
7538#if 0
7539 printf ("e_sourcePositionNullPointers in SageInterface::setSourcePosition() \n");
7540#endif
7542 break;
7543 }
7544
7545 case e_sourcePositionFrontendConstruction: // Specify as source position to be filled in as part of AST construction in the front-end.
7546 {
7547 // DQ (2/17/2013): The setSourcePositionToDefault() function is called a lot, so it might be a performance issue.
7548 // All IR nodes built by the Build Interface are assighed source position information
7549 // using this function and then reset afterward as we use information within EDG to
7550 // reset the source position information. Ideally, the EDG/ROSE connection would
7551 // use NULL pointers as the behavior for the front-end mode. We can move to that
7552 // later to make the source position handling more efficient.
7553
7554 // This function builds an empty Sg_File_Info entry (valid object but filled with default values; must be reset in front-end processing).
7555#if 0
7556 printf ("e_sourcePositionFrontendConstruction in SageInterface::setSourcePosition() \n");
7557#endif
7558 SgLocatedNode* locatedNode = isSgLocatedNode(node);
7559 if (locatedNode != NULL)
7560 {
7561 // setSourcePositionAtRootAndAllChildrenAsDefault(locatedNode);
7562 setSourcePositionToDefault(locatedNode);
7563 }
7564 else
7565 {
7566 // This is not supported (not clear if it need be).
7567 SgPragma* pragma = isSgPragma(node);
7568 if (pragma != NULL)
7569 {
7570 setSourcePositionToDefault(pragma);
7571 }
7572 else
7573 {
7574 // printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7575 // ROSE_ASSERT(false);
7576 SgType* type = isSgType(node);
7577 if (type != NULL)
7578 {
7579 // Ignore this case, OK.
7580 }
7581 else
7582 {
7583 SgFunctionParameterTypeList* functionParameterTypeList = isSgFunctionParameterTypeList(node);
7584 if (functionParameterTypeList != NULL)
7585 {
7586 // Ignore this case, OK.
7587 }
7588 else
7589 {
7590 printf ("Error: can't call setSourcePosition() in mode e_sourcePositionFrontendConstruction with non SgLocatedNode (node = %p = %s) \n",node,node->class_name().c_str());
7591 ROSE_ABORT();
7592 }
7593 }
7594 }
7595 }
7596
7597 break;
7598 }
7599
7600
7602 {
7603 printf ("Error: error value e_sourcePositionError in SageInterface::setSourcePosition() \n");
7604 ROSE_ABORT();
7605 }
7606
7607 default:
7608 {
7609 printf ("Error: default reached in SageInterface::setSourcePosition() \n");
7610 break;
7611 }
7612 }
7613
7614#if 0
7615 if (node->get_file_info() != NULL)
7616 {
7617 node->get_file_info()->display("Leaving SageInterface::setSourcePosition()");
7618 }
7619#endif
7620 }
7621
7622#if 0
7623void
7624SageInterface::setSourcePositionForTransformation_memoryPool()
7625 {
7626 // DQ (1/24/2009): This seems like a very dangerous function to have, is it required!
7627
7628 // DQ (5/1/2012): Make it an error to call this function.
7629 printf ("ERROR: In setSourcePositionForTransformation_memoryPool(): This seems like a very dangerous function to have, is it required? \n");
7630 ROSE_ABORT();
7631
7632 VariantVector vv(V_SgNode);
7633 Rose_STL_Container<SgNode*> nodeList = NodeQuery::queryMemoryPool(vv);
7634 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++ )
7635 {
7637 }
7638 }
7639#endif
7640
7642 {
7643 // Liao, 1/9/2008, get the first global scope from current project
7644 // mostly used to prepare for AST construction under the global scope
7645 ROSE_ASSERT(project != NULL);
7646
7647 // DQ (1/24/2009): Added a check to make sure STL list is non-empty.
7648 ROSE_ASSERT(project->get_fileList().empty() == false);
7649
7650 // SgGlobal* global = project->get_file(0).get_root();
7651 SgSourceFile* file = isSgSourceFile(project->get_fileList()[0]);
7652 SgGlobal* global = file->get_globalScope();
7653
7654#if 0
7655 SgFilePtrListPtr fileList = project->get_fileList();
7656 SgFilePtrList::const_iterator i= fileList->begin();
7657
7658 SgGlobal* global = (*i)->get_globalScope();
7659#endif
7660 ROSE_ASSERT(global != NULL);
7661
7662 return global;
7663 }
7664
7665// Liao, 1/10/2008, get the last stmt from the scope
7666// two cases
7667// SgScopeStatement::getDeclarationList
7668// SgScopeStatement::getStatementList()
7670 {
7671 ROSE_ASSERT(scope);
7672 SgStatement* stmt = NULL;
7673
7674 if (scope->containsOnlyDeclarations())
7675 {
7676 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7677 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7678 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7679
7680 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7681 if (declList.empty() == false)
7682 {
7683 stmt = isSgStatement(declList.back());
7684 }
7685 }
7686 else
7687 {
7688 // DQ (2/17/2013): Fixed stmtList to be a reference instead of a copy.
7689 SgStatementPtrList & stmtList = scope->getStatementList();
7690
7691 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7692 if (stmtList.empty() == false)
7693 {
7694 stmt = stmtList.back();
7695 }
7696 }
7697
7698 return stmt;
7699 }
7700
7701
7702SgStatement* SageInterface::getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated/*=false*/)
7703 {
7704 // DQ (2/17/2013): This function appears to be a performance problem (so a pass was made to
7705 // use lower complexity operations that are equivalent in funcionality for this context).
7706
7707 ROSE_ASSERT(scope);
7708 SgStatement* stmt = NULL;
7709
7710 if (scope->containsOnlyDeclarations())
7711 {
7712 // DQ (2/17/2013): Fixed declList to be a reference instead of a copy.
7713 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7714 // SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7715 SgDeclarationStatementPtrList & declList = scope->getDeclarationList();
7716 if (includingCompilerGenerated)
7717 {
7718 // DQ (2/17/2013): Fixed evaluation of empty list use SgDeclarationStatementPtrList::empty() member function for faster performance.
7719 // DQ Note: (declList.empty() == false) is a much faster test O(1) than (declList.size() > 0), which is O(n).
7720 if (declList.empty() == false)
7721 {
7722 stmt = isSgStatement(declList.front());
7723 }
7724 }
7725 else
7726 {
7727 // skip compiler-generated declarations
7728 SgDeclarationStatementPtrList::iterator i=declList.begin();
7729 while (i != declList.end())
7730 {
7731 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7732 // some content from headers included are not marked as compiler-generated
7733 //
7734 // cout<<(*i)->unparseToString()<<endl;
7735 // ((*i)->get_file_info())->display("debug.......");
7736 Sg_File_Info * fileInfo = (*i)->get_file_info();
7737 // include transformation-generated statements, but not the hidden ones
7738 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7739 if ((fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation() && fileInfo->isOutputInCodeGeneration()))
7740 {
7741 stmt = *i;
7742 break;
7743 }
7744 else
7745 {
7746 i++;
7747 continue;
7748 }
7749 }
7750 }
7751 }
7752 else
7753 {
7754 // DQ Note: Do we really need to make a copy of the list just to return a pointer to the first entry?
7755 SgStatementPtrList & stmtList = scope->getStatementList();
7756 if (includingCompilerGenerated)
7757 {
7758 // DQ (2/17/2013): Fixed evaluation of empty list use SgStatementPtrList::empty() member function for faster performance.
7759 // DQ Note: (stmtList.empty() == false) is a much faster test O(1) than (stmtList.size() > 0), which is O(n).
7760 if (stmtList.empty() == false)
7761 {
7762 stmt = stmtList.front();
7763 }
7764 }
7765 else
7766 {
7767 // skip compiler-generated declarations
7768 SgStatementPtrList::iterator i = stmtList.begin();
7769 while (i!=stmtList.end())
7770 {
7771 // isCompilerGenerated(),isOutputInCodeGeneration(),etc. are not good enough,
7772 // some content from headers included are not marked as compiler-generated
7773 //
7774 // cout<<(*i)->unparseToString()<<endl;
7775 // ((*i)->get_file_info())->display("debug.......");
7776 Sg_File_Info * fileInfo = (*i)->get_file_info();
7777 // include transformation-generated statements, but not the hidden ones
7778 // Note: isOutputInCodeGeneration is not default to true for original statements from user code
7779 if ( (fileInfo->isSameFile(scope->get_file_info())) || (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration()))
7780 {
7781 stmt=*i;
7782 break;
7783 }
7784 else
7785 {
7786 i++;
7787 continue;
7788 }
7789 }
7790 }
7791 }
7792
7793 return stmt;
7794 }
7795
7796
7798 {
7799 ROSE_ASSERT(scope);
7800 SgFunctionDeclaration* result = NULL;
7801 if (scope->containsOnlyDeclarations())
7802 {
7803 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
7804 SgDeclarationStatementPtrList::iterator i=declList.begin();
7805 while (i!=declList.end())
7806 {
7807 Sg_File_Info * fileInfo = (*i)->get_file_info();
7808
7809 if ((fileInfo->isSameFile(scope->get_file_info()))||
7810 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7811 )
7812 {
7813 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7814 if (func)
7815 {
7816 if (func->get_definingDeclaration ()==func)
7817 {
7818 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7819 result=func;
7820 break;
7821 }
7822 }
7823 }
7824 i++;
7825 }//end while
7826 } else
7827 {
7828 SgStatementPtrList stmtList = scope->getStatementList();
7829 SgStatementPtrList::iterator i=stmtList.begin();
7830 while (i!=stmtList.end())
7831 {
7832 Sg_File_Info * fileInfo = (*i)->get_file_info();
7833 if ( (fileInfo->isSameFile(scope->get_file_info()))||
7834 (fileInfo->isTransformation()&& fileInfo->isOutputInCodeGeneration())
7835 )
7836 {
7837 SgFunctionDeclaration* func = isSgFunctionDeclaration(*i);
7838 if (func)
7839 {
7840 if (func->get_definingDeclaration ()==func)
7841 {
7842 //cout<<"debug, first defining func decl is:"<<(*i)->unparseToString()<<endl;
7843 result=func;
7844 break;
7845 }// if defining
7846 } // if func
7847 }// if fileInof
7848 i++;
7849 }//while
7850 } // end if
7851 return result;
7852 }
7853
7854
7856{
7857 bool result = false;
7858 // Liao 1/5/2010, handle Fortran main entry: SgProgramHeaderStatement
7860 if (isSgProgramHeaderStatement(n)) {
7861 result = true;
7862 }
7863 }
7864 else {
7865 if (isSgFunctionDeclaration(n) != nullptr) {
7866 bool either = false;
7868 either = true;
7869 }
7870 else {
7871 const SgStatement* stmnt = isSgStatement(n);
7872 ROSE_ASSERT(stmnt != nullptr);
7873 if (isSgGlobal(stmnt->get_scope())) {
7874 either = true;
7875 }
7876 }
7877 if (either) {
7878 const SgFunctionDeclaration* funcDefn = isSgFunctionDeclaration(n);
7879 ROSE_ASSERT(funcDefn != nullptr);
7880 if (funcDefn->get_name() == "main") {
7881 result = true;
7882 }
7883 }
7884 }
7885 }
7886 return result;
7887}
7888
7889// Originally from ompTranslator.C
7890// DQ (1/6/2007): The correct qualified name for "main" is "::main", at least in C++.
7891// however for C is should be "main". Our name qualification is not language specific,
7892// however, for C is makes no sense to as for the qualified name, so the name we
7893// want to search for could be language specific. The test code test2007_07.C
7894// demonstrates that the function "main" can exist in both classes (as member functions)
7895// and in namespaces (as more meaningfully qualified names). Because of this C++
7896// would have to qualify the global main function as "::main", I think.
7897
7898// Revised by Jeremiah,
7899// Added check to see if the scope is global: Liao
7901 if (!n) return 0;
7902 if (isMain(n))
7903 {
7904 return isSgFunctionDeclaration(n);
7905 }
7906 vector<SgNode*> children = n->get_traversalSuccessorContainer();
7907 for (vector<SgNode*>::const_iterator i = children.begin();
7908 i != children.end(); ++i) {
7909
7910 SgFunctionDeclaration* mainDecl = findMain(*i);
7911 if (mainDecl)
7912 if (mainDecl->get_definingDeclaration() == mainDecl) // skip non-defining main() declaration, Liao 8/27/2010
7913 return mainDecl;
7914 }
7915 return 0;
7916}
7917
7919// another declaration statement can be inserted.
7920// This is useful to find a safe place to insert a declaration statement with special requirements about where it can be inserted.
7921// e.g. a variable declaration statement should not be inserted before IMPLICIT none in Fortran
7922// If it returns NULL, a declaration statement should be able to be prepended to the scope
7924{
7925 SgStatement* rt = NULL;
7926 ROSE_ASSERT (scope != NULL);
7927
7928 SgStatementPtrList stmt_list = scope->generateStatementList ();
7929
7930 for (size_t i = 0; i<stmt_list.size(); i++)
7931 {
7932 SgStatement* cur_stmt = stmt_list[i];
7933 // We should exclude pragma decl. We don't want to insert things after pragmas.
7934 if (isSgDeclarationStatement(cur_stmt))
7935 {
7936 if (isSgPragmaDeclaration (cur_stmt))
7937 {
7938 if (includePragma)
7939 rt = cur_stmt;
7940 }
7941 else
7942 rt = cur_stmt;
7943 }
7944 //if (isSgImplicitStatement(cur_stmt)) || isSgFortranIncludeLine(cur_stmt) || isSgDeclarationStatement
7945 }
7946
7947 return rt;
7948}
7949
7951{
7952 SgNode* rt = NULL;
7953 SgTreeCopy g_treeCopy; // should use a copy object each time of usage!
7954 if (n!= NULL)
7955 {
7956 rt = n->copy (g_treeCopy);
7958 }
7959 // return n ? n->copy (g_treeCopy) : 0;
7960 return rt;
7961}
7962
7963// by Jeremiah
7964// Return bool for C++ code, and int for C code
7966 bool isC = TransformationSupport::getSourceFile(n)->get_outputLanguage() == SgFile::e_C_language;
7967 if (isC) {
7968 return SgTypeInt::createType();
7969 } else {
7970 return SgTypeBool::createType();
7971 }
7972}
7973
7974#if 1
7975// Change continue statements in a given block of code to gotos to a label
7977 {
7978#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
7979 std::vector<SgContinueStmt*> continues = SageInterface::findContinueStmts(stmt);
7980 for (std::vector<SgContinueStmt*>::iterator i = continues.begin(); i != continues.end(); ++i)
7981 {
7982 SgGotoStatement* gotoStatement = SageBuilder::buildGotoStatement(label);
7983 // printf ("Building gotoStatement #1 = %p \n",gotoStatement);
7984#ifndef _MSC_VER
7985 LowLevelRewrite::replace(*i, make_unit_list( gotoStatement ) );
7986#else
7987 ROSE_ABORT();
7988#endif
7989 }
7990#else
7991 printf ("Not supported in mode: ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT (LowLevelRewrite::replace() is unavailable)");
7992 ROSE_ABORT();
7993#endif
7994 }
7995
7996#define DEBUG_TEMPLATE_ARG_EQUIVALENCE 0
7997
7999 {
8000 if (arg1 == arg2)
8001 {
8002#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8003 printf ("In templateArgumentEquivalence(): same pointer to template argument: returning true \n");
8004#endif
8005 return true;
8006 }
8007
8008 if (arg1->get_argumentType() != arg2->get_argumentType())
8009 {
8010#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8011 printf ("In templateArgumentEquivalence(): different argumentType(): returning false \n");
8012#endif
8013 return false;
8014 }
8015
8016 switch (arg1->get_argumentType())
8017 {
8019 {
8020 ROSE_ASSERT(arg1->get_type() != NULL);
8021 ROSE_ASSERT(arg2->get_type() != NULL);
8022
8023#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8024 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: arg1->get_type() = %p = %s arg2->get_type() = %p = %s \n",
8025 arg1->get_type(),arg1->get_type()->class_name().c_str(),
8026 arg2->get_type(),arg2->get_type()->class_name().c_str());
8027#endif
8028 // DQ (5/19/2016): Rewrote to support debugging.
8029 // return arg1->get_type() == arg2->get_type();
8030 if (arg1->get_type() == arg2->get_type())
8031 {
8032#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8033 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: returning true \n");
8034#endif
8035 return true;
8036 }
8037 else
8038 {
8039 // ROSE_ASSERT(!"NIY: non-type template argument comparaison."); /// \todo
8040
8041 // DQ (5/19/2016): Use type equivalence mechanism to handle the case where
8042 // these are different pointers to what might still be the same type.
8043 // return false;
8044 bool typesAreEqual = isEquivalentType(arg1->get_type(),arg2->get_type());
8045
8046#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8047 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::type_argument: checking for the same type: pointers are different: returning typesAreEqual = %s \n",typesAreEqual ? "true" : "false");
8048#endif
8049 return typesAreEqual;
8050 }
8051 }
8052
8054 {
8055 SgExpression * expr1 = arg1->get_expression();
8056 SgExpression * expr2 = arg2->get_expression();
8057 if (expr1 == expr2) {
8058#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8059 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: checking for the same expression: returning true \n");
8060#endif
8061 return true;
8062 } else if (expr1->variantT() == expr2->variantT() ) {
8063#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8064 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: same variant of expression: %s\n", expr1->class_name().c_str());
8065#endif
8066 switch (expr1->variantT()) {
8067 case V_SgLongIntVal: {
8068 return ((SgLongIntVal *)expr1)->get_value() == ((SgLongIntVal *)expr2)->get_value();
8069 }
8070 // DQ (7/21/2024): Adding support for another type (from processing nlohmann/json.hpp with ROSE)
8071 case V_SgUnsignedLongVal:
8072 {
8073 return ((SgUnsignedLongVal*) expr1)->get_value() == ((SgUnsignedLongVal*) expr2)->get_value();
8074 }
8075 // PP (4/10/2025): Adding support for another type (from processing ROSE with ROSE)
8076 case V_SgBoolValExp:
8077 {
8078 return static_cast<SgBoolValExp*>(expr1)->get_value() == static_cast<SgBoolValExp*>(expr2)->get_value();
8079 }
8080 default: {
8081 mlog[Sawyer::Message::Common::FATAL]
8082 << "FATAL: In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: expression have the same variant "
8083 << expr1->class_name()
8084 << " but comparison is not NIY!"
8085 << std::endl;
8086 ROSE_ABORT();
8087 }
8088 }
8089 } else {
8090#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8091 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::nontype_argument: different variant of expression: returning false \n");
8092#endif
8093 return false;
8094 }
8095 }
8096
8098 {
8099 if (arg1->get_templateDeclaration() == arg2->get_templateDeclaration())
8100 {
8101#if DEBUG_TEMPLATE_ARG_EQUIVALENCE
8102 printf ("In templateArgumentEquivalence(): case SgTemplateArgument::template_template_argument: checking for the same templateDeclaration: returning true \n");
8103#endif
8104 return true;
8105 }
8106 else
8107 {
8108 ROSE_ASSERT(!"NIY: template template argument comparaison.");
8109 }
8110 }
8111
8113 {
8114 ROSE_ASSERT(!"Try to compare template arguments of unknown type...");
8115 }
8116
8117 // DQ (7/19/2015): Added missing case:
8119 {
8120 // Liao 6/24/2016. Handle the simplest case: both arguments are parameter pack.
8122 return true;
8123 ROSE_ASSERT(!"Try to compare template arguments of unknown type start_of_pack_expansion_argument");
8124 }
8125
8126 // DQ (7/19/2015): Added missing default case: we always want to ahve a default case to catch errors and missing cases.
8127 default:
8128 {
8129 printf ("Error: default case not handled! \n");
8130 ROSE_ABORT();
8131 }
8132 }
8133
8134 ROSE_ABORT(); // unreachable code
8135 }
8136
8137#define DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE 0
8138
8139bool SageInterface::templateArgumentListEquivalence(const SgTemplateArgumentPtrList & list1, const SgTemplateArgumentPtrList & list2)
8140 {
8141 if (list1.size() != list2.size())
8142 {
8143#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8144 printf ("In templateArgumentListEquivalence(): different list sizes: returning false \n");
8145 printf (" --- list1.size() = %zu \n",list1.size());
8146 printf (" --- list2.size() = %zu \n",list2.size());
8147#endif
8148 return false;
8149 }
8150
8151 if (list1 == list2)
8152 {
8153#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8154 printf ("In templateArgumentListEquivalence(): same list using STL equality operator: returning true \n");
8155#endif
8156 return true;
8157 }
8158
8159 // for (unsigned i = 0; i < list1.size(); i++)
8160 for (size_t i = 0; i < list1.size(); i++)
8161 {
8162#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8163 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu \n",i);
8164#endif
8165 // if (!templateArgumentEquivalence(list1[i], list2[i]))
8166 if (templateArgumentEquivalence(list1[i], list2[i]) == false)
8167 {
8168#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8169 printf ("In templateArgumentListEquivalence(): calling templateArgumentEquivalence() for i = %zu --- returned false: returning false \n",i);
8170#endif
8171 return false;
8172 }
8173 }
8174
8175#if DEBUG_TEMPLATE_ARG_LIST_EQUIVALENCE
8176 printf ("In templateArgumentListEquivalence(): reached base of function: returning true \n");
8177#endif
8178
8179 return true;
8180 }
8181
8182// Add a step statement to the end of a loop body
8183// Add a new label to the end of the loop, with the step statement after
8184// it; then change all continue statements in the old loop body into
8185// jumps to the label
8186//
8187// For example:
8188// while (a < 5) {if (a < -3) continue;} (adding "a++" to end) becomes
8189// while (a < 5) {if (a < -3) goto label; label: a++;}
8191 using namespace SageBuilder;
8193 SgStatement* old_body = SageInterface::getLoopBody(loopStmt);
8194 SgBasicBlock* new_body = buildBasicBlock();
8195// printf ("Building IR node #13: new SgBasicBlock = %p \n",new_body);
8196 SgName labelname = "rose_label__";
8197 labelname << ++gensym_counter;
8198 SgLabelStatement* labelstmt = buildLabelStatement(labelname,
8199buildBasicBlock(), proc);
8200 changeContinuesToGotos(old_body, labelstmt);
8201 appendStatement(old_body, new_body);
8202 appendStatement(labelstmt, new_body);
8203 appendStatement(step, new_body);
8204 SageInterface::setLoopBody(loopStmt, new_body);
8205}
8206
8207
8209 if (isSgNullExpression(f->get_increment())) return;
8210 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(f->get_increment());
8211 f->get_increment()->set_parent(incrStmt);
8214 f->set_increment(ne);
8215 ne->set_parent(f);
8216}
8217
8218static
8219bool hasEmptyCondition(SgForStatement* f)
8220{
8221 ROSE_ASSERT(f);
8222
8223 SgStatement* condstmt = f->get_test();
8224 ROSE_ASSERT(condstmt);
8225
8226 if (isSgNullStatement(condstmt)) return true;
8227
8228 SgExprStatement* exprStmt = isSgExprStatement(condstmt);
8229
8230 return isSgNullExpression(exprStmt->get_expression());
8231}
8232
8237 SgStatementPtrList& bbStmts = bb->get_statements();
8238 SgStatementPtrList& initStmts = inits->get_init_stmt();
8239 bbStmts = initStmts;
8240 for (size_t i = 0; i < bbStmts.size(); ++i) {
8241 bbStmts[i]->set_parent(bb);
8242 }
8243
8244 const bool testIsNull = hasEmptyCondition(f);
8246 : f->get_test();
8248
8249 appendStatement(ws, bb);
8250 isSgStatement(f->get_parent())->replace_statement(f, bb);
8251}
8252
8254 Rose_STL_Container<SgNode*> fors = NodeQuery::querySubTree(top,
8255V_SgForStatement);
8256 for (size_t i = 0; i < fors.size(); ++i) {
8257 convertForToWhile(isSgForStatement(fors[i]));
8258 }
8259}
8260
8261 vector<SgGotoStatement*> SageInterface::findGotoStmts(SgStatement* scope, SgLabelStatement* l) {
8262 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8263 // But we still need the copy since the return type is IR node specific.
8264 Rose_STL_Container<SgNode*> allGotos = NodeQuery::querySubTree(scope, V_SgGotoStatement);
8265
8266 vector<SgGotoStatement*> result;
8267 for (Rose_STL_Container<SgNode*>::const_iterator i = allGotos.begin(); i != allGotos.end(); ++i) {
8268 if (isSgGotoStatement(*i)->get_label() == l) {
8269 result.push_back(isSgGotoStatement(*i));
8270 }
8271 }
8272 return result;
8273 }
8274
8275#if 0 // Liao 5/21/2010. This is a bad function in terms of performance
8276 // vectors are created/destroyed multiple times
8277 vector<SgReturnStmt*> SageInterface::findReturnStmts(SgStatement* scope) {
8278 // DQ (9/25/2007): Moved from std::list to std::vector uniformally in ROSE.
8279 // But we still need the copy since the return type is IR node specific.
8280 Rose_STL_Container<SgNode*> returns = NodeQuery::querySubTree(scope, V_SgReturnStmt);
8281
8282 vector<SgReturnStmt*> result;
8283 for (Rose_STL_Container<SgNode*>::const_iterator i = returns.begin(); i != returns.end(); ++i) {
8284 result.push_back(isSgReturnStmt(*i));
8285 }
8286 return result;
8287 }
8288
8289#endif
8290static void getSwitchCasesHelper(SgStatement* top, vector<SgStatement*>& result) {
8291 ROSE_ASSERT (top);
8292 if (isSgSwitchStatement(top)) return; // Don't descend into nested switches
8293 if (isSgCaseOptionStmt(top) || isSgDefaultOptionStmt(top)) {
8294 result.push_back(top);
8295 }
8296 vector<SgNode*> children = top->get_traversalSuccessorContainer();
8297 for (unsigned int i = 0; i < children.size(); ++i) {
8298 if (isSgStatement(children[i])) {
8299 getSwitchCasesHelper(isSgStatement(children[i]), result);
8300 }
8301 }
8302 }
8303
8305 vector<SgStatement*> result;
8306 getSwitchCasesHelper(sw->get_body(), result);
8307 return result;
8308 }
8309
8310
8311#endif
8312
8319SgScopeStatement* SageInterface::getEnclosingScope(SgNode* n, const bool includingSelf/* =false*/)
8320{
8321 SgScopeStatement* result = getScope (n);
8322 if (result == n)
8323 {
8324 if (!includingSelf)
8325 result = getScope(n->get_parent());
8326 }
8327 return result;
8328}
8329
8330// from transformationSupport.C
8333 {
8334
8335 // Case 1: directly call get_scope() for some types of nodes
8336 if (const SgSymbol* symbol = isSgSymbol(astNode))
8337 return symbol->get_scope();
8338 else if (const SgInitializedName* initName = isSgInitializedName(astNode))
8339 return initName->get_scope();
8340 else if (const SgTemplateArgument* tempArg = isSgTemplateArgument(astNode))
8341 return tempArg->get_scope();
8342 else if (const SgQualifiedName* qualifiedName = isSgQualifiedName(astNode))
8343 return qualifiedName->get_scope();
8344
8345 // DQ (6/9/2007): This function traverses through the parents to the first scope (used for name qualification support of template arguments)
8346 const SgNode* parentNode = astNode;
8347 while (!isSgScopeStatement(parentNode))
8348 {
8349 //George Vulov (11/29/2010)
8350 //Function parameter lists are siblings of SgFunctionDefinition, so just going up to parents
8351 //produces SgGlobal.
8352 if (isSgFunctionParameterList(parentNode) || isSgCtorInitializerList(parentNode))
8353 {
8354 const SgFunctionDeclaration* funcDeclaration = isSgFunctionDeclaration(parentNode->get_parent());
8355 ROSE_ASSERT(funcDeclaration != NULL);
8356 funcDeclaration = isSgFunctionDeclaration(funcDeclaration->get_definingDeclaration());
8357 if (funcDeclaration != NULL)
8358 {
8359 return funcDeclaration->get_definition();
8360 }
8361 }
8362
8363 parentNode = parentNode->get_parent();
8364 if (parentNode == NULL)
8365 {
8366 break;
8367 }
8368 }
8369
8370 // Check to see if we made it back to the root (current root is SgProject).
8371 // It is also OK to stop at a node for which get_parent() returns NULL (SgType and SgSymbol nodes).
8372 if ( isSgScopeStatement(parentNode) == NULL &&
8373 dynamic_cast<const SgType*>(parentNode) == NULL &&
8374 dynamic_cast<const SgSymbol*>(parentNode) == NULL )
8375 {
8376 printf ("Error: In SageInterface::getScope(): could not trace back to SgScopeStatement node \n");
8377 ROSE_ABORT();
8378 }
8379 else
8380 {
8381 if ( dynamic_cast<const SgType*>(parentNode) != NULL || dynamic_cast<const SgSymbol*>(parentNode) != NULL )
8382 {
8383 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());
8384 return NULL;
8385 }
8386 }
8387
8388 // Make sure we have a SgStatement node
8389 const SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8390 //SgScopeStatement* scopeStatement = isSgScopeStatement(parentNode);
8391 ROSE_ASSERT (scopeStatement != NULL);
8392
8393 // ensure the search is inclusive
8394 if (isSgScopeStatement(astNode))
8395 if (isSgScopeStatement(parentNode))
8396 {
8397 ROSE_ASSERT (astNode == parentNode);
8398 }
8399
8400 // return scopeStatement;
8401 return const_cast<SgScopeStatement*>(scopeStatement);
8402 }
8403
8404
8405// from outliner, ASTtools
8406// ------------------------------------------------
8407
8415static
8416const SgVariableSymbol *
8417getVarSymFromName_const (const SgInitializedName* name)
8418 {
8419 SgVariableSymbol* v_sym = NULL;
8420
8421 if (name != NULL)
8422 {
8423#if 0
8424 printf ("In getVarSymFromName(): name->get_name() = %s \n",name->get_name().str());
8425#endif
8426 SgScopeStatement* scope = name->get_scope();
8427 ROSE_ASSERT (scope != NULL);
8428#if 0
8429 printf ("In getVarSymFromName(): name->get_name() = %s scope = %p = %s \n",name->get_name().str(),scope,scope->class_name().c_str());
8430#endif
8431 v_sym = scope->lookup_var_symbol (name->get_name());
8432
8433 if (!v_sym) // E.g., might be part of an 'extern' declaration.
8434 {
8435 // Try the declaration's scope.
8436 SgDeclarationStatement* decl = name->get_declaration ();
8437 ROSE_ASSERT (decl);
8438
8439 SgScopeStatement* decl_scope = decl->get_scope ();
8440 if (decl_scope != NULL)
8441 v_sym = decl_scope->lookup_var_symbol (name->get_name());
8442
8443 if (!v_sym)
8444 cerr << "\t\t*** WARNING: Can't seem to find a symbol for '"
8445 << name->get_name ().str ()
8446 << "' ***" << endl;
8447 }
8448 }
8449
8450 return v_sym;
8451 }
8452
8453#if 0
8461static
8463getVarSymFromName (SgInitializedName* name)
8464{
8465 const SgVariableSymbol* v_sym = getVarSymFromName_const (name);
8466 return const_cast<SgVariableSymbol *> (v_sym);
8467}
8468#endif
8473static
8474const SgVariableSymbol *
8475getVarSym_const (const SgNode* n)
8476{
8477 const SgVariableSymbol* v_sym = 0;
8478 switch (n->variantT ())
8479 {
8480 case V_SgVarRefExp:
8481 v_sym = isSgVarRefExp (n)->get_symbol ();
8482 break;
8483 case V_SgInitializedName:
8484 v_sym = getVarSymFromName_const (isSgInitializedName (n));
8485 break;
8486 default:
8487 break;
8488 }
8489 return v_sym;
8490}
8491
8492#if 0
8497static
8499getVarSym (SgNode* n)
8500{
8501 const SgVariableSymbol* v_sym = getVarSym_const (n);
8502 return const_cast<SgVariableSymbol *> (v_sym);
8503}
8504#endif
8505
8506static
8507const SgVariableSymbol *
8508getFirstVarSym_const (const SgVariableDeclaration* decl)
8509{
8510 if (!decl) return 0;
8511 const SgInitializedNamePtrList& names = decl->get_variables ();
8512 if (names.begin () != names.end ())
8513 {
8514 const SgInitializedName* name = *(names.begin ());
8515 return getVarSym_const (name);
8516 }
8517 else
8518 return 0;
8519}
8520
8523{
8524 const SgVariableSymbol* sym = getFirstVarSym_const (decl);
8525 return const_cast<SgVariableSymbol *> (sym);
8526}
8527
8528
8531{
8532 ROSE_ASSERT(decl);
8533 SgInitializedNamePtrList& names = decl->get_variables ();
8534 if (names.begin () != names.end ())
8535 return *(names.begin ());
8536 else
8537 return NULL;
8538}
8539
8540
8541static void findBreakStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgBreakStmt*>& breakStmts) {
8542 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code) || isSgSwitchStatement(code)) {
8543 if (fortranLabel == "") {
8544 // Outermost loop only
8545 return;
8546 } else {
8547 // Set this for query on children
8548 inOutermostBody = false;
8549 }
8550 }
8551 if (isSgBreakStmt(code)) {
8552 SgBreakStmt* bs = isSgBreakStmt(code);
8553 bool breakMatchesThisConstruct = false;
8554 if (bs->get_do_string_label() == "") {
8555 // Break matches closest construct
8556 breakMatchesThisConstruct = inOutermostBody;
8557 } else {
8558 breakMatchesThisConstruct = (fortranLabel == bs->get_do_string_label());
8559 }
8560 if (breakMatchesThisConstruct) {
8561 breakStmts.push_back(bs);
8562 }
8563 return;
8564 }
8565 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8566 for (unsigned int i = 0; i < children.size(); ++i) {
8567 if (isSgStatement(children[i])) {
8568 findBreakStmtsHelper(isSgStatement(children[i]), fortranLabel, inOutermostBody, breakStmts);
8569 }
8570 }
8571}
8572
8573vector<SgBreakStmt*> SageInterface::findBreakStmts(SgStatement* code, const std::string& fortranLabel) {
8574 // Run this on the body of a loop or switch, because it stops at any
8575 // construct which defines a new scope for break statements
8576 vector<SgBreakStmt*> result;
8577 findBreakStmtsHelper(code, fortranLabel, true, result);
8578 return result;
8579}
8580
8581
8582static void findContinueStmtsHelper(SgStatement* code, const std::string& fortranLabel, bool inOutermostBody, vector<SgContinueStmt*>& continueStmts) {
8583 if (isSgWhileStmt(code) || isSgDoWhileStmt(code) || isSgForStatement(code)) {
8584 if (fortranLabel == "") {
8585 // Outermost loop only
8586 return;
8587 } else {
8588 // Set this for query on children
8589 inOutermostBody = false;
8590 }
8591 }
8592 if (isSgContinueStmt(code)) {
8593 SgContinueStmt* cs = isSgContinueStmt(code);
8594 bool continueMatchesThisConstruct = false;
8595 if (cs->get_do_string_label() == "") {
8596 // Continue matches closest construct
8597 continueMatchesThisConstruct = inOutermostBody;
8598 } else {
8599 continueMatchesThisConstruct = (fortranLabel == cs->get_do_string_label());
8600 }
8601 if (continueMatchesThisConstruct) {
8602 continueStmts.push_back(cs);
8603 }
8604 return;
8605 }
8606 vector<SgNode*> children = code->get_traversalSuccessorContainer();
8607 for (unsigned int i = 0; i < children.size(); ++i) {
8608 SgStatement* stmnt = isSgStatement(children[i]);
8609 if (stmnt != NULL) {
8610 findContinueStmtsHelper(stmnt, fortranLabel, inOutermostBody, continueStmts);
8611 }
8612 }
8613}
8614
8615vector<SgContinueStmt*> SageInterface::findContinueStmts(SgStatement* code, const std::string& fortranLabel) {
8616 // Run this on the body of a loop, because it stops at any construct which
8617 // defines a new scope for continue statements
8618 vector<SgContinueStmt*> result;
8619 findContinueStmtsHelper(code, fortranLabel, true, result);
8620 return result;
8621}
8622
8623
8624// Get the initializer containing an expression if it is within an
8625// initializer.
8626// from replaceExpressionWithStatement.C
8628 assert(n);
8629#if 0
8630 std::cout << "Starting getInitializerOfExpression on 0x" << std::hex << (int)n << ", which has type " << n->sage_class_name() << std::endl;
8631#endif
8632 while (!isSgInitializer(n)) {
8633 n = isSgExpression(n->get_parent());
8634#if 0
8635 std::cout << "Continuing getInitializerOfExpression on 0x" << std::hex << (int)n;
8636 if (n) std::cout << ", which has type " << n->sage_class_name();
8637 std::cout << std::endl;
8638#endif
8639 assert(n);
8640 }
8641 return isSgInitializer(n);
8642}
8643
8644#ifndef USE_ROSE
8645// Get all symbols used in a given expression
8647 class GetSymbolsUsedInExpressionVisitor: public AstSimpleProcessing {
8648 public:
8649 std::vector<SgVariableSymbol*> symbols;
8650
8651 virtual void visit(SgNode* n) {
8652 if (isSgVarRefExp(n))
8653 symbols.push_back(isSgVarRefExp(n)->get_symbol());
8654 }
8655 };
8656
8657 GetSymbolsUsedInExpressionVisitor vis;
8658 vis.traverse(expr, preorder);
8659 return vis.symbols;
8660}
8661#endif
8662
8665 return getEnclosingNode<SgSourceFile>(n, includingSelf);
8666}
8667
8668
8670{
8671 return findDeclarationStatement<SgFunctionDeclaration> (root, name, scope, isDefining);
8672}
8673
8674
8676{
8677 return getEnclosingFunctionDefinition(n,includingSelf);
8678}
8679
8682 return getEnclosingNode<SgFunctionDefinition>(n, includingSelf);
8683}
8684
8685
8688 return getEnclosingNode<SgFunctionDeclaration>(astNode, includingSelf);
8689}
8690
8691// #endif
8692
8693// #ifndef USE_ROSE
8694
8695SgGlobal*
8697 // should including itself in this case
8698 return getEnclosingNode<SgGlobal>(astNode, true /*includingSelf*/);
8699}
8700
8702SageInterface::getEnclosingClassDefinition(SgNode* astNode, const bool includingSelf/* =false*/) {
8703 return getEnclosingNode<SgClassDefinition>(astNode, includingSelf);
8704}
8705
8706
8709 // DQ (1/24/2019): This might have to get the SgClassDefinition and then the SgClassDeclaration from that.
8710 // I'm having trouble making this work for a member function declared outside of the class definition.
8711 return getEnclosingNode<SgClassDeclaration>(astNode, true);
8712}
8713
8715SageInterface::getEnclosingExprListExp(SgNode* astNode, const bool includingSelf/* =false*/) {
8716 return getEnclosingNode<SgExprListExp>(astNode, includingSelf);
8717}
8718
8719bool
8721 {
8722 bool returnValue = false;
8723
8724 struct Visitor: public AstSimpleProcessing
8725 {
8726 SgExpression* expression_target;
8727 bool in_subtree;
8728 virtual void visit(SgNode* n)
8729 {
8730 if (n == expression_target)
8731 {
8732 in_subtree = true;
8733 }
8734 }
8735
8736 Visitor(SgExpression* expr) : expression_target(expr), in_subtree(false) {}
8737 };
8738
8739 Visitor traversal(exp);
8740
8741 traversal.traverse(subtree, preorder);
8742
8743 returnValue = traversal.in_subtree;
8744
8745 return returnValue;
8746 }
8747
8748
8751 {
8752 // DQ (2/7/2019): Added more general function to support extraction of the associated function declaration.
8753 // The lower level functions are more robust on the SgFunctionRefExp and SgMemberFunctionRefExp than
8754 // when called on the SgFunctionCallExp for example.
8755
8756 // SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
8757 ROSE_ASSERT (functionCallExp != NULL);
8758
8759 SgExpression* expression = functionCallExp->get_function();
8760 ROSE_ASSERT (expression != NULL);
8761
8762 SgFunctionDeclaration* returnDeclaration = NULL;
8763
8764 SgDotExp* dotExp = isSgDotExp(expression);
8765 if (dotExp != NULL)
8766 {
8767 ROSE_ASSERT (dotExp != NULL);
8768
8769 SgExpression* rhsOperand = dotExp->get_rhs_operand();
8770 ROSE_ASSERT (rhsOperand != NULL);
8771
8772 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8773
8774 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8775 if (memberFunctionRefExp != NULL)
8776 {
8777 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8778 }
8779 }
8780
8781 SgFunctionRefExp* functionReferenceExp = isSgFunctionRefExp(expression);
8782 if (functionReferenceExp != NULL)
8783 {
8784 returnDeclaration = functionReferenceExp->getAssociatedFunctionDeclaration();
8785 }
8786
8787 SgArrowExp* arrowExp = isSgArrowExp(expression);
8788 if ( arrowExp != NULL)
8789 {
8790 ROSE_ASSERT (arrowExp != NULL);
8791
8792 SgExpression* rhsOperand = arrowExp->get_rhs_operand();
8793 ROSE_ASSERT (rhsOperand != NULL);
8794
8795 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(rhsOperand);
8796
8797 // ROSE_ASSERT (memberFunctionRefExp != NULL);
8798 if (memberFunctionRefExp != NULL)
8799 {
8800 returnDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
8801 }
8802 }
8803
8804 return returnDeclaration;
8805 }
8806
8807
8808
8809std::list<SgClassType*>
8811 {
8812 // DQ (2/16/2019): This version support for data member name qualification return type chains.
8813
8814#define DEBUG_DATA_MEMBER_TYPE_CHAIN 0
8815
8816 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
8817 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
8818 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
8819
8820 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
8821
8822 std::list<SgClassType*> returnTypeChain;
8823
8824 // Internal list used to filter the class chain generated from chained SgCastExp objects to identify the subset containing an ambiguity.
8825 std::list<SgClassType*> classChain;
8826
8827 // Make sure this is at least a reference to a data or member function member.
8828 // The requirements for these functions are different, however, if they were
8829 // virtual functions it might be a more attractive design.
8830 if (varRefExp != NULL)
8831 {
8832 ROSE_ASSERT(isDataMemberReference(varRefExp) == true);
8833 }
8834 else
8835 {
8836 ROSE_ASSERT(memberFunctionRefExp != NULL);
8837 ROSE_ASSERT(isMemberFunctionMemberReference(memberFunctionRefExp) == true);
8838 }
8839
8840 SgNode* parent = refExp->get_parent();
8841 ROSE_ASSERT(parent != NULL);
8842
8843#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8844 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): parent = %p = %s \n",parent,parent->class_name().c_str());
8845#endif
8846
8847 SgArrowExp* arrowExp = isSgArrowExp(parent);
8848 SgDotExp* dotExp = isSgDotExp(parent);
8849
8850 SgBinaryOp* binaryOperator = NULL;
8851
8852 if (arrowExp != NULL)
8853 {
8854#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8855 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an arrow expression \n");
8856#endif
8857 binaryOperator = arrowExp;
8858 }
8859
8860 if (dotExp != NULL)
8861 {
8862#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8863 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): Found an dot expression \n");
8864#endif
8865 binaryOperator = dotExp;
8866 }
8867
8868 // ROSE_ASSERT(binaryOperator != NULL);
8869 if (binaryOperator != NULL)
8870 {
8871 SgExpression* lhs = binaryOperator->get_lhs_operand();
8872 ROSE_ASSERT(lhs != NULL);
8873
8874#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8875 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs = %p = %s \n",lhs,lhs->class_name().c_str());
8876#endif
8877
8878 // Looking for a chain of SgCastExp expressions.
8879 SgExpression* temp_lhs = lhs;
8880 SgCastExp* cast = NULL;
8881 while (isSgCastExp(temp_lhs) != NULL)
8882 {
8883 cast = isSgCastExp(temp_lhs);
8884 ROSE_ASSERT(cast != NULL);
8885 temp_lhs = cast->get_operand();
8886
8887#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8888 printf ("Top of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
8889#endif
8890 ROSE_ASSERT(cast->get_type() != NULL);
8891 SgClassType* classType = isSgClassType(cast->get_type());
8892 if (classType == NULL)
8893 {
8894#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8895 printf (" --- looking for base type: In SageInterface::getClassTypeChainForDataMemberReference(): classType == NULL: cast->get_type() = %p = %s \n",
8896 cast->get_type(),cast->get_type()->class_name().c_str());
8897#endif
8898 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);
8899 ROSE_ASSERT(baseType != NULL);
8900
8901#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8902 printf (" --- baseType = %p = %s name = %s \n",baseType,baseType->class_name().c_str(),get_name(baseType).c_str());
8903#endif
8904 classType = isSgClassType(baseType);
8905 }
8906 // ROSE_ASSERT(classType != NULL);
8907
8908 ROSE_ASSERT(temp_lhs != NULL);
8909
8910#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8911 printf (" --- temp_lhs = %p = %s name = %s \n",temp_lhs,temp_lhs->class_name().c_str(),get_name(temp_lhs).c_str());
8912#endif
8913
8914#if 1
8915 // DQ (1/20/2020): This (original) code works fine.
8916 // returnTypeChain.push_front(classType);
8917 if (classType != NULL)
8918 {
8919 classChain.push_front(classType);
8920 }
8921#else
8922 // DQ (1/20/2020): This (new) code works for Cxx11_tests/test2020_61.C.
8923 if (classType != NULL)
8924 {
8925 // DQ (1/20/2020): We might want to fully resolve the class types associated with this cast here directly
8926 // (see Cxx11_tests/test2020_61.C). The point is that we need a qualified name that will reflect all of
8927 // the class declarations from the temp_lhs to the declarations associated with the classType.
8928 // The steps are:
8929 // 1) Get the target class definition for the type represented by the temp_lhs.
8930 // 2) Get the source class definition for the classType.
8931 // 3) Iterate from the source class definition to the target class definition, and save the associated
8932 // types associated with the class declarations associated with the scopes visited.
8933 SgType* target_type = temp_lhs->get_type();
8934 ROSE_ASSERT(target_type != NULL);
8935 SgClassType* target_classType = isSgClassType(target_type);
8936 // ROSE_ASSERT(target_classType != NULL);
8937 if (target_classType != NULL)
8938 {
8939 SgDeclarationStatement* target_declaration = target_classType->get_declaration();
8940 ROSE_ASSERT(target_declaration != NULL);
8941 SgClassDeclaration* target_classDeclaration = isSgClassDeclaration(target_declaration);
8942 ROSE_ASSERT(target_classDeclaration != NULL);
8943 SgClassDeclaration* target_definingClassDeclaration = isSgClassDeclaration(target_classDeclaration->get_definingDeclaration());
8944 ROSE_ASSERT(target_definingClassDeclaration != NULL);
8945 SgScopeStatement* target_scope = target_definingClassDeclaration->get_definition();
8946 ROSE_ASSERT(target_scope != NULL);
8947
8948#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8949 printf ("target_classDeclaration = %p = %s name = %s target_scope = %p = %s \n",
8950 target_classDeclaration,target_classDeclaration->class_name().c_str(),target_classDeclaration->get_name().str(),target_scope,target_scope->class_name().c_str());
8951#endif
8952 SgClassType* source_classType = classType;
8953 ROSE_ASSERT(source_classType != NULL);
8954 SgDeclarationStatement* source_declaration = source_classType->get_declaration();
8955 ROSE_ASSERT(source_declaration != NULL);
8956 SgClassDeclaration* source_classDeclaration = isSgClassDeclaration(source_declaration);
8957 ROSE_ASSERT(source_classDeclaration != NULL);
8958 SgClassDeclaration* source_definingClassDeclaration = isSgClassDeclaration(source_classDeclaration->get_definingDeclaration());
8959 ROSE_ASSERT(source_definingClassDeclaration != NULL);
8960 SgScopeStatement* source_scope = source_definingClassDeclaration->get_definition();
8961 ROSE_ASSERT(source_scope != NULL);
8962
8963#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8964 printf ("source_classDeclaration = %p = %s name = %s source_scope = %p = %s \n",
8965 source_classDeclaration,source_classDeclaration->class_name().c_str(),source_classDeclaration->get_name().str(),source_scope,source_scope->class_name().c_str());
8966#endif
8967 SgScopeStatement* tmp_scope = source_scope;
8968 while (tmp_scope != NULL && tmp_scope != target_scope)
8969 {
8970#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8971 printf ("tmp_scope = %p = %s \n",tmp_scope,tmp_scope->class_name().c_str());
8972#endif
8973 SgClassDefinition* tmp_classDefinition = isSgClassDefinition(tmp_scope);
8974 ROSE_ASSERT(tmp_classDefinition != NULL);
8975 SgClassDeclaration* tmp_classDeclaration = tmp_classDefinition->get_declaration();
8976 ROSE_ASSERT(tmp_classDeclaration != NULL);
8977
8978#if DEBUG_DATA_MEMBER_TYPE_CHAIN
8979 SgName scope_name = tmp_classDeclaration->get_name();
8980 printf ("scope_name = %s \n",scope_name.str());
8981#endif
8982 SgClassType* tmp_classType = tmp_classDeclaration->get_type();
8983 ROSE_ASSERT(tmp_classType != NULL);
8984
8985 // classChain.push_front(tmp_classDefinition);
8986 classChain.push_front(tmp_classType);
8987
8988 tmp_scope = tmp_scope->get_scope();
8989
8990 if (isSgGlobal(tmp_scope) != NULL)
8991 {
8992 tmp_scope = NULL;
8993 }
8994 }
8995 }
8996 else
8997 {
8998#if 1
8999 printf ("In loop processing cast: target_type = %p = %s \n",target_type,target_type->class_name().c_str());
9000#endif
9001 }
9002 }
9003#endif
9004
9005#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9006 printf ("Bottom of loop: processing cast = %p temp_lhs = %p = %s \n",cast,temp_lhs,temp_lhs->class_name().c_str());
9007#endif
9008 }
9009
9010 // 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.
9011
9012 ROSE_ASSERT(temp_lhs != NULL);
9013
9014#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9015 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9016#endif
9017
9018 SgVarRefExp* derivedClassVarRefExp = isSgVarRefExp(temp_lhs);
9019 if (derivedClassVarRefExp != NULL)
9020 {
9021 SgVariableSymbol* derivedClassVariableSymbol = derivedClassVarRefExp->get_symbol();
9022 ROSE_ASSERT(derivedClassVariableSymbol != NULL);
9023
9024 SgName derivedClassVariableName = derivedClassVariableSymbol->get_name();
9025
9026#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9027 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): derivedClassVariableName = %s \n",derivedClassVariableName.str());
9028#endif
9029 // SgType* type = cast->get_type();
9030 SgType* type = temp_lhs->get_type();
9031 ROSE_ASSERT(type != NULL);
9032
9033#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9034 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s \n",type,type->class_name().c_str());
9035#endif
9036
9037 // 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);
9038 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);
9039
9040#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9041 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type = %p = %s \n",stripped_type,stripped_type->class_name().c_str());
9042#endif
9043
9044 // SgClassType* classType = isSgClassType(type);
9045 SgClassType* classType = isSgClassType(stripped_type);
9046
9047 // ROSE_ASSERT(classType != NULL);
9048 if (classType != NULL)
9049 {
9050#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9051 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classType = %p = %s \n",classType,classType->class_name().c_str());
9052 SgClassDeclaration* classDeclaration = isSgClassDeclaration(classType->get_declaration());
9053 ROSE_ASSERT(classDeclaration != NULL);
9054 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs classDeclaration = %p = %s name = %s \n",
9055 classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9056#endif
9057 // This is where we want the SgVarRefExp data member qualification to start.
9058 // returnType = classType;
9059 // returnTypeChain.push_front(classType);
9060 classChain.push_front(classType);
9061 }
9062 else
9063 {
9064#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9065 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs stripped_type is not a SgClassType \n");
9066#endif
9067 }
9068 }
9069 else
9070 {
9071#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9072 printf ("Need to support alternative to SgVarRefExp: temp_lhs = %p = %s \n",temp_lhs,temp_lhs->class_name().c_str());
9073#endif
9074 SgType* type = temp_lhs->get_type();
9075 ROSE_ASSERT(type != NULL);
9076
9077#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9078 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): lhs type = %p = %s name = %s \n",type,type->class_name().c_str(),get_name(type).c_str());
9079#endif
9080
9081 // DQ (1/3/2019): Need to strip the type to get to a possible SgClassType.
9082 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);
9083
9084#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9085 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());
9086#endif
9087 // SgClassType* classType = isSgClassType(type);
9088 SgClassType* classType = isSgClassType(stripped_type);
9089 // returnTypeChain.push_front(classType);
9090 if (classType != NULL)
9091 {
9092 classChain.push_front(classType);
9093 }
9094 }
9095
9096#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9097 printf ("classChain.size() = %zu \n",classChain.size());
9098 std::list<SgClassType*>::iterator iter = classChain.begin();
9099 while(iter != classChain.end())
9100 {
9101 printf (" --- *iter = %p = %s name = %s \n",*iter,(*iter)->class_name().c_str(),(*iter)->get_name().str());
9102
9103 iter++;
9104 }
9105#endif
9106
9107 // Test the first element in the list to see if there is an ambiguity in the associated classDefinition
9108 // for the input variable referenced SgVarRefExp).
9109
9110 // SgVariableSymbol* variableSymbol = varRefExp->get_symbol();
9111 // ROSE_ASSERT(variableSymbol != NULL);
9112 // SgName variableName = variableSymbol->get_name();
9113 SgSymbol* referenceSymbol = NULL;
9114 if (varRefExp != NULL)
9115 {
9116 ROSE_ASSERT(varRefExp != NULL);
9117 ROSE_ASSERT(memberFunctionRefExp == NULL);
9118
9119 referenceSymbol = varRefExp->get_symbol();
9120 }
9121 else
9122 {
9123 ROSE_ASSERT(varRefExp == NULL);
9124 ROSE_ASSERT(memberFunctionRefExp != NULL);
9125
9126 referenceSymbol = memberFunctionRefExp->get_symbol();
9127 }
9128 ROSE_ASSERT(referenceSymbol != NULL);
9129 SgName symbolName = referenceSymbol->get_name();
9130
9131#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9132 printf ("referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9133 printf ("symbolName = %s \n",symbolName.str());
9134#endif
9135
9136 // Generate the name without the template arguments.
9137 SgFunctionSymbol* functionSymbol = isSgFunctionSymbol(referenceSymbol);
9138 if (functionSymbol != NULL)
9139 {
9140 // 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.
9141 // SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(referenceSymbol->get_declaration());
9142 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(functionSymbol->get_declaration());
9143 if (templateInstantiationMemberFunctionDeclaration != NULL)
9144 {
9145#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9146 printf ("This is a template name, we want the name without template arguments \n");
9147 printf ("templateInstantiationMemberFunctionDeclaration = %p \n",templateInstantiationMemberFunctionDeclaration);
9148 printf ("templateInstantiationMemberFunctionDeclaration->get_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_name().str());
9149#endif
9150
9151 // DQ (2/24/2019): This is an error (calls base class function).
9152 // printf ("templateInstantiationMemberFunctionDeclaration->get_template_name() = %s \n",templateInstantiationMemberFunctionDeclaration->get_template_name().str());
9153
9154 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration =
9155 isSgTemplateMemberFunctionDeclaration(templateInstantiationMemberFunctionDeclaration->get_templateDeclaration());
9156 if (templateMemberFunctionDeclaration != NULL)
9157 {
9158#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9159 printf ("templateMemberFunctionDeclaration = %p \n",templateMemberFunctionDeclaration);
9160 printf ("templateMemberFunctionDeclaration->get_name() = %s \n",templateMemberFunctionDeclaration->get_name().str());
9161#endif
9162 // We need the template name without template arguments.
9163 symbolName = templateMemberFunctionDeclaration->get_name();
9164 }
9165 else
9166 {
9167#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9168 printf ("templateMemberFunctionDeclaration == NULL: template declaration not available from template instantiation (rare, I think) \n");
9169#endif
9170 }
9171#if 0
9172 printf ("Exiting as a test! \n");
9173 ROSE_ABORT();
9174#endif
9175 }
9176 else
9177 {
9178 // DQ (2/24/2019): This might indicate another case to handle: finding SgMemberFunctionDeclaration (but this is not a template).
9179 SgDeclarationStatement* declarationStatement = functionSymbol->get_declaration();
9180 ROSE_ASSERT(declarationStatement != NULL);
9181#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9182 printf ("functionSymbol != NULL: but declaration is not a member function: declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
9183#endif
9184 }
9185 }
9186 else
9187 {
9188 SgVariableSymbol* variableSymbol = isSgVariableSymbol(referenceSymbol);
9189 if (variableSymbol != NULL)
9190 {
9191 // Nothing to do in this case of a SgVariableSymbol.
9192 }
9193 else
9194 {
9195#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9196 printf ("In SageInterface::getClassTypeChainForDataMemberReference(): NOTE: referenceSymbol is not a SgFunctionSymbol or SgVariableSymbol \n");
9197#endif
9198#if 1
9199 printf ("Exiting as a test! \n");
9200 ROSE_ABORT();
9201#endif
9202 }
9203
9204 }
9205
9206#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9207 printf ("symbolName = %s \n",symbolName.str());
9208#endif
9209
9210 // SgClassType* firstDetectedAmbiguity = NULL;
9211 // SgClassType* lastDetectedAmbiguity = NULL;
9212
9213 // bool nameQualificationRequired = false;
9214
9215 // std::list<SgClassType*> deleteList;
9216 std::list<SgClassType*> saveList;
9217
9218#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9219 printf ("classChain.size() = %zu \n",classChain.size());
9220#endif
9221
9222 std::list<SgClassType*>::iterator i = classChain.begin();
9223 std::list<SgClassType*>::iterator save_iter = i;
9224
9225 // 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.
9226 save_iter++;
9227
9228 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9229 bool ambiguityDetectedSoSaveWholeChain = false;
9230
9231 while(i != classChain.end())
9232 {
9233#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9234 printf ("******** TOP OF WHILE LOOP ******** \n");
9235 printf (" --- *i = %p = %s name = %s \n",*i,(*i)->class_name().c_str(),(*i)->get_name().str());
9236 printf (" --- --- referenceSymbol = %p = %s \n",referenceSymbol,referenceSymbol->class_name().c_str());
9237#endif
9238 bool ambiguityDetected = false;
9239
9240 SgDeclarationStatement* declarationStatement = (*i)->get_declaration();
9241 ROSE_ASSERT(declarationStatement != NULL);
9242 SgDeclarationStatement* definingDeclarationStatement = declarationStatement->get_definingDeclaration();
9243 if (definingDeclarationStatement != NULL)
9244 {
9245 SgClassDeclaration* classDeclaration = isSgClassDeclaration(definingDeclarationStatement);
9246 ROSE_ASSERT(classDeclaration != NULL);
9247 SgClassDefinition* classDefinition = classDeclaration->get_definition();
9248
9249#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9250 printf (" --- classDeclaration = %p = %s name = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9251 printf (" --- classDefinition = %p = %s \n",classDefinition,classDefinition->class_name().c_str());
9252#endif
9253 // This works for any SgName and SgSymbol, so it need not be specific to variables.
9254 ambiguityDetected = classDefinition->hasAmbiguity(symbolName,referenceSymbol);
9255
9256#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9257 printf (" --- ambiguityDetected = %s \n",ambiguityDetected ? "true" : "false");
9258#endif
9259 }
9260
9261 // DQ (1/19/2020): Add support for more complex nested base classes, see Cxx11_tests/test2020_61.C.
9262 if (ambiguityDetected == true || ambiguityDetectedSoSaveWholeChain == true)
9263 {
9264 ambiguityDetectedSoSaveWholeChain = true;
9265
9266 if (save_iter != classChain.end())
9267 {
9268#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9269 printf (" --- add to saveList: *save_iter = %p \n",*save_iter);
9270#endif
9271 saveList.push_back(*save_iter);
9272 }
9273 else
9274 {
9275#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9276 printf (" --- save_iter == classChain.end() \n");
9277#endif
9278 }
9279 }
9280
9281#if DEBUG_DATA_MEMBER_TYPE_CHAIN || 0
9282 printf ("******** BOTTOM OF WHILE LOOP ******** \n");
9283#endif
9284 i++;
9285
9286 // Also increment the save_iter.
9287 save_iter++;
9288 }
9289
9290 // Now build a list of class types to use in the name qualification from firstDetectedAmbiguity to lastDetectedAmbiguity (inclusive).
9291
9292#if DEBUG_DATA_MEMBER_TYPE_CHAIN
9293 printf ("saveList.size() = %zu \n",saveList.size());
9294 std::list<SgClassType*>::iterator saveList_iterator = saveList.begin();
9295 while (saveList_iterator != saveList.end())
9296 {
9297 printf (" --- *saveList_iterator = %p = %s name = %s \n",*saveList_iterator,(*saveList_iterator)->class_name().c_str(),(*saveList_iterator)->get_name().str());
9298
9299 saveList_iterator++;
9300 }
9301#endif
9302
9303 returnTypeChain = saveList;
9304
9305 // End of branch for binaryOperator != NULL.
9306 }
9307
9308 return returnTypeChain;
9309 }
9310
9311
9312
9313bool
9315 {
9316 // DQ (2/17/2019): This may share a design in common with isDataMemberReference() below.
9317
9318#define DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE 0
9319
9320 ROSE_ASSERT(memberFunctionRefExp != NULL);
9321
9322 bool returnValue = false;
9323
9324 // 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;")
9325 SgNode* parent = memberFunctionRefExp->get_parent();
9326
9327 SgArrowExp* arrowExp = isSgArrowExp(parent);
9328 SgDotExp* dotExp = isSgDotExp(parent);
9329
9330 // I don't know that the SgAddressOfOp is as relevant for the case of SgMemberFunctionRefExp, but I think
9331 // it is because we would have to support membr pointeds to functions the same a member pointers to data.
9332 // I need some examples test codes to verify that name qualification is important in this case.
9333 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9334
9335 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9336 {
9337 // Use a SgFunctionSymbol instead of a SgMemberFunctionSymbol for generality (I hope this works).
9338 SgFunctionSymbol* symbol = memberFunctionRefExp->get_symbol();
9339 ROSE_ASSERT(symbol != NULL);
9340
9341 SgFunctionDeclaration* functionDeclaration = symbol->get_declaration();
9342 ROSE_ASSERT(functionDeclaration != NULL);
9343
9344 // Check if this is a statically declared variable.
9345 if (functionDeclaration != NULL)
9346 {
9347 bool isStatic = functionDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9348#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9349 printf ("isStatic = %s \n",isStatic ? "true" : "false");
9350#endif
9351 if (isStatic == false)
9352 {
9353 SgScopeStatement* scope = functionDeclaration->get_scope();
9354 ROSE_ASSERT(scope != NULL);
9355
9356 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9357 if (classDefinition != NULL)
9358 {
9359 returnValue = true;
9360 }
9361 }
9362 }
9363 else
9364 {
9365#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9366 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9367#endif
9368 }
9369 }
9370 else
9371 {
9372#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9373 printf ("In SageInterface::isMemberFunctionMemberReference(): memberFunctionRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9374#endif
9375 }
9376
9377#if DEBUG_IS_MEMBER_FUNCTION_MEMBER_REFERENCE
9378 printf ("Leaving SageInterface::isMemberFunctionMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9379#endif
9380
9381 return returnValue;
9382 }
9383
9384
9385
9386bool
9388 {
9389 // This function is used to support the name qualification of data member references seperate from name qualification
9390 // of variables that might be members (e.g. "X x; x.A::y;" instead of "A::y" (which is just simple name qualification)).
9391
9392 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9393
9394 // DQ (2/17/2019): I think we need to make sure this is not a static data member reference (since those are qualified
9395 // differently (not member data name qualification). Consider changing the name of this function to indicate non-static.
9396
9397#define DEBUG_IS_DATA_MEMBER_REFERENCE 0
9398
9399 ROSE_ASSERT(varRefExp != NULL);
9400
9401 bool returnValue = false;
9402
9403 // 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;")
9404 SgNode* parent = varRefExp->get_parent();
9405
9406 SgArrowExp* arrowExp = isSgArrowExp(parent);
9407 SgDotExp* dotExp = isSgDotExp(parent);
9408
9409 SgAddressOfOp* addressOfOp = isSgAddressOfOp(parent);
9410
9411 if (arrowExp != NULL || dotExp != NULL || addressOfOp != NULL)
9412 {
9413 if (arrowExp != NULL)
9414 {
9415 // DQ (2/17/2019): Check if this is part of a sizeof operand for which is is_objectless_nonstatic_data_member_reference == true.
9416 SgNode* parentOfArrowExp = arrowExp->get_parent();
9417 ROSE_ASSERT(parentOfArrowExp != NULL);
9418 SgSizeOfOp* sizeOfOp = isSgSizeOfOp(parentOfArrowExp);
9419 if (sizeOfOp != NULL && sizeOfOp->get_is_objectless_nonstatic_data_member_reference() == true)
9420 {
9421 // This is not to be qualified using data member name qualification (it should use standard name qualification).
9422#if DEBUG_IS_DATA_MEMBER_REFERENCE
9423 printf ("In SageInterface::isDataMemberReference(): Found case of expression used in sizeof with objectless_nonstatic_data_member_reference \n");
9424#endif
9425 return false;
9426 }
9427 }
9428
9429 SgVariableSymbol* symbol = varRefExp->get_symbol();
9430 ROSE_ASSERT(symbol != NULL);
9431
9432 SgInitializedName* initializedName = symbol->get_declaration();
9433 ROSE_ASSERT(initializedName != NULL);
9434
9435 // Check if this is a statically declared variable.
9436 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(initializedName->get_parent());
9437 if (variableDeclaration != NULL)
9438 {
9439 bool isStatic = variableDeclaration->get_declarationModifier().get_storageModifier().isStatic();
9440 if (isStatic == false)
9441 {
9442 SgScopeStatement* scope = initializedName->get_scope();
9443 ROSE_ASSERT(scope != NULL);
9444
9445 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
9446 if (classDefinition != NULL)
9447 {
9448 returnValue = true;
9449 }
9450 }
9451 }
9452 else
9453 {
9454#if DEBUG_IS_DATA_MEMBER_REFERENCE
9455 printf ("In SageInterface::isDataMemberReference(): varRefExp is not associated with variableDeclaration (could not compute if it is static data member) \n");
9456#endif
9457 }
9458 }
9459 else
9460 {
9461#if DEBUG_IS_DATA_MEMBER_REFERENCE
9462 printf ("In SageInterface::isDataMemberReference(): varRefExp parent is not a is not SgArrowExp or SgDotExp expression \n");
9463#endif
9464 }
9465
9466#if DEBUG_IS_DATA_MEMBER_REFERENCE
9467 printf ("Leaving SageInterface::isDataMemberReference(): returnValue = %s \n",returnValue ? "true" : "false");
9468#endif
9469
9470 return returnValue;
9471 }
9472
9473
9474#if 0
9475bool
9477 {
9478 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9479 ROSE_ASSERT(varRefExp != NULL);
9480
9481 bool returnValue = false;
9482
9483 SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9484
9485 if (addressOfOp != NULL)
9486 {
9487 returnValue = true;
9488 }
9489
9490 return returnValue;
9491 }
9492#endif
9493
9494bool
9496 {
9497 // DQ (2/17/2019): Need to generalize this function to apply to member functions references as well.
9498
9499 // The input must be one of these two, then this function is suficiently general to support name qualification requirements for both.
9500 SgVarRefExp* varRefExp = isSgVarRefExp(refExp);
9501 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(refExp);
9502
9503 ROSE_ASSERT(varRefExp != NULL || memberFunctionRefExp != NULL);
9504
9505 // DQ (2/8/2019): Adding support for detecting when to use added name qualification for pointer-to-member expressions.
9506 // ROSE_ASSERT(varRefExp != NULL);
9507 ROSE_ASSERT(refExp != NULL);
9508
9509 bool returnValue = false;
9510
9511 // SgAddressOfOp* addressOfOp = isSgAddressOfOp(varRefExp->get_parent());
9512 SgAddressOfOp* addressOfOp = isSgAddressOfOp(refExp->get_parent());
9513
9514 if (addressOfOp != NULL)
9515 {
9516 returnValue = true;
9517 }
9518
9519 return returnValue;
9520 }
9521
9523 {
9524 // DQ (3/4/2014): This new version of this function supports both C/C++ and also Java.
9525 // If the SgJavaPackageDeclaration is noticed then the previous parent is a
9526 // SgClassDefinition and the previous previous parent is a SgClassDeclaration whose
9527 // name can be used to match the filename in the SgProject's list of files.
9528 // A better implementation usign an attribute (not in place until tomorrow) and
9529 // from the attribute the pointer to the associated file is directly available.
9530 // The later implementation is as fast as possible.
9531
9532 ROSE_ASSERT (astNode != NULL);
9533
9534 // Make sure this is not a project node (since the SgFile exists below
9535 // the project and could not be found by a traversal of the parent list)
9536 ROSE_ASSERT (isSgProject(astNode) == NULL);
9537
9538 SgNode* previous_parent = NULL;
9539 SgNode* previous_previous_parent = NULL;
9540
9541 SgNode* parent = astNode;
9542 // while ( (parent != NULL) && (isSgFile(parent) == NULL) )
9543 while ( (parent != NULL) && (isSgFile(parent) == NULL) && isSgJavaPackageDeclaration(parent) == NULL)
9544 {
9545#if 0
9546 printf ("In getEnclosingFileNode(): parent = %p = %s \n",parent,parent->class_name().c_str());
9547#endif
9548 previous_previous_parent = previous_parent;
9549 previous_parent = parent;
9550
9551 parent = parent->get_parent();
9552 }
9553
9554 if (previous_previous_parent != NULL && previous_parent != NULL && isSgJavaPackageDeclaration(parent) != NULL)
9555 {
9556 // This is for a Java program and is contained within a SgJavaPackageDeclaration
9557#if 0
9558 printf ("parent = %p = %s \n",parent,parent->class_name().c_str());
9559 printf ("previous_parent = %p = %s \n",previous_parent,previous_parent->class_name().c_str());
9560 printf ("previous_previous_parent = %p = %s \n",previous_previous_parent,previous_previous_parent->class_name().c_str());
9561#endif
9562 SgClassDeclaration* classDeclaration = isSgClassDeclaration(previous_previous_parent);
9563 if (classDeclaration != NULL)
9564 {
9565#if 0
9566 printf ("Class name = %p = %s = %s \n",classDeclaration,classDeclaration->class_name().c_str(),classDeclaration->get_name().str());
9567#endif
9568 // Find the associated Java class file.
9569#if 0
9570 // DQ (3/4/2014): This is the code we want to use until we get Philippe's branch in place with the attribute.
9571 SgProject* project = TransformationSupport::getProject(parent);
9572 ROSE_ASSERT(project != NULL);
9573 SgFileList* fileList = project->get_fileList_ptr();
9574 ROSE_ASSERT(fileList != NULL);
9575 SgFilePtrList & vectorFile = fileList->get_listOfFiles();
9576#if 0
9577 printf ("Output list of files: \n");
9578#endif
9579 SgFilePtrList::iterator i = vectorFile.begin();
9580 while (i != vectorFile.end())
9581 {
9582 SgFile* file = *i;
9583 ROSE_ASSERT(file != NULL);
9584#if 0
9585 printf (" --- filename = %s \n",file->getFileName().c_str());
9586#endif
9587 string filename = file->getFileName();
9588 string filenameWithoutPath = file->get_sourceFileNameWithoutPath();
9589 string classname = classDeclaration->get_name();
9590 string matchingfilename = classname + ".java";
9591#if 0
9592 printf (" --- --- filename = %s \n",filename.c_str());
9593 printf (" --- --- filenameWithoutPath = %s \n",filenameWithoutPath.c_str());
9594 printf (" --- --- classname = %s \n",classname.c_str());
9595 printf (" --- --- matchingfilename = %s \n",matchingfilename.c_str());
9596#endif
9597 if (filenameWithoutPath == matchingfilename)
9598 {
9599#if 0
9600 printf (" return file = %p \n",file);
9601#endif
9602 return file;
9603 }
9604
9605 i++;
9606 }
9607#else
9608 // DQ (3/4/2014): This is the code we want to use when the attribute is in place (philippe's branch).
9609 AstSgNodeAttribute *attribute = (AstSgNodeAttribute *) classDeclaration->getAttribute("sourcefile");
9610
9611 // "This simpler and more efficent code requires the latest work in Java support (3/6/2014)"
9612
9613 if (attribute)
9614 {
9615 // true for all user-specified classes and false for all classes fom libraries
9616 SgSourceFile *sourcefile = isSgSourceFile(attribute->getNode());
9617 ROSE_ASSERT(sourcefile != NULL);
9618 return sourcefile;
9619 }
9620#endif
9621 }
9622 }
9623 else
9624 {
9625 // previous_parent was uninitialized to a non-null value or astNode is a SgJavaPackageDeclaration or SgFile.
9626 if (previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9627 {
9628 // The input was a SgJavaPackageDeclaration (so there is no associated SgFile).
9629 ROSE_ASSERT(isSgJavaPackageDeclaration(astNode) != NULL);
9630 return NULL;
9631 }
9632 else
9633 {
9634 if (previous_previous_parent == NULL && isSgJavaPackageDeclaration(parent) != NULL)
9635 {
9636 // The input was a SgClassDefinition (so there is no associated SgFile).
9637 ROSE_ASSERT(isSgClassDefinition(astNode) != NULL);
9638 return NULL;
9639 }
9640 else
9641 {
9642 // This could be a C/C++ file (handled below).
9643 }
9644 }
9645 }
9646
9647 // This is where we handle the C/C++ files.
9648 if (parent == nullptr)
9649 {
9650 return nullptr;
9651 }
9652 else
9653 {
9654 return isSgFile(parent);
9655 }
9656 }
9657
9659 struct FrontendSpecificTraversal : public ROSE_VisitTraversal {
9660 std::set<SgNode*> specific;
9661 std::set<SgNode*> non_specific;
9662
9663 static void recursive_collect( SgNode* node , std::set<SgNode *> & collection ) {
9664 // Stop on sinks and loops
9665 if (node == NULL || !collection.insert(node).second) return;
9666
9667 std::vector<std::pair<SgNode*, std::string> > data_members = node->returnDataMemberPointers();
9668 for (std::vector<std::pair<SgNode*, std::string> >::iterator i = data_members.begin(); i != data_members.end(); ++i) {
9669 recursive_collect(i->first, collection);
9670 }
9671 }
9672
9673 void visit (SgNode* n) {
9674 Sg_File_Info * fileInfo = n->get_file_info();
9675
9676 if (fileInfo != NULL) {
9677 if (fileInfo->isFrontendSpecific()) {
9678 specific.insert(n);
9679 recursive_collect(n, specific);
9680 } else {
9681 non_specific.insert(n);
9682 recursive_collect(n, non_specific);
9683 }
9684 } else {
9685 fileInfo = isSg_File_Info(n);
9686 if (fileInfo != NULL) {
9687 if (fileInfo->isFrontendSpecific()) {
9688 specific.insert(n);
9689 } else {
9690 non_specific.insert(n);
9691 }
9692 }
9693 }
9694 }
9695
9696 std::set<SgNode*> apply() {
9697 traverseMemoryPool();
9698
9699 std::set<SgNode*> result;
9700
9701 std::set_difference(
9702 specific.begin(), specific.end(),
9703 non_specific.begin(), non_specific.end(),
9704 std::insert_iterator<set<SgNode*> >(result, result.begin())
9705 );
9706
9707 return result;
9708 }
9709 };
9710
9711 FrontendSpecificTraversal fst;
9712 return fst.apply();
9713}
9714
9715void
9717 {
9718 // DQ (2/17/2019): Display the shared nodes in the AST for debugging.
9719
9720 class OutputSharedNodesTraversal : public SgSimpleProcessing
9721 {
9722 // This traversal collects the includes at the top of a file.
9723 public:
9724 void visit(SgNode *astNode)
9725 {
9726 ROSE_ASSERT(astNode != NULL);
9727 Sg_File_Info* file_info = astNode->get_file_info();
9728 if (file_info != NULL)
9729 {
9730 if (file_info->isShared() == true)
9731 {
9732 printf ("Found shared node: astNode = %p = %s \n",astNode,astNode->class_name().c_str());
9733 }
9734 }
9735 }
9736 };
9737
9738 OutputSharedNodesTraversal tt;
9739 tt.traverse(node,preorder);
9740 }
9741
9742
9743
9744
9745
9747 while (n && !isSgStatement(n)) n = n->get_parent();
9748 return isSgStatement(n);
9749}
9750
9751
9752
9753#if 1
9754// DQ (11/19/2020): We need to expand the use of this to cover deffered transformations of common SageInterface transformations (e.g. replaceStatement).
9755// So I need to move this out of being specific to the outliner and make it more generally data structure in the SageInterface.
9756
9757SageInterface::DeferredTransformation::DeferredTransformation()
9758 : deferredTransformationKind(e_default),
9759 statementToRemove(NULL),
9760 statementToAdd(NULL),
9761 class_definition(NULL),
9762 target_class_member(NULL),
9763 new_function_prototype(NULL),
9764 // DQ (2/28/2021): Added new data member to support deferred transformations.
9765 locationToOverwriteWithTransformation(NULL),
9766 transformationToOverwriteFirstStatementInInterval(NULL),
9767 blockOfStatementsToOutline(NULL)
9768 {
9769 // Default constructor (not particularly useful).
9770#if 0
9771 printf ("In SageInterface::DeferredTransformation default constructor called \n");
9772#endif
9773 }
9774
9775// DQ (2/28/2021): Added new data member to support deferred transformations.
9776// IntervalType statementInterval;
9777// SgStatement* locationToOverwriteWithTransformation;
9778
9779SageInterface::DeferredTransformation::DeferredTransformation(
9780 SgClassDefinition* input_class_definition,
9781 SgDeclarationStatement* input_target_class_member,
9782 SgDeclarationStatement* input_new_function_prototype)
9783 : deferredTransformationKind(e_outliner),
9784 statementToRemove(NULL),
9785 statementToAdd(NULL),
9786 class_definition(input_class_definition),
9787 target_class_member(input_target_class_member),
9788 new_function_prototype(input_new_function_prototype),
9789 // DQ (2/28/2021): Added new data member to support deferred transformations.
9790 locationToOverwriteWithTransformation(NULL),
9791 transformationToOverwriteFirstStatementInInterval(NULL),
9792 blockOfStatementsToOutline(NULL)
9793 {
9794 // This constructor is used by the outliner.
9795#if 0
9796 printf ("In SageInterface::DeferredTransformation constructor for outliner called \n");
9797#endif
9798 }
9799
9802 {
9803#if 0
9804 printf ("In SageInterface::DeferredTransformation constructor for replaceDefiningFunctionDeclarationWithFunctionPrototype called \n");
9805#endif
9806 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9807 // This constructor is used by tool_G and supports the use of the transformation represented
9808 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9810 X.deferredTransformationKind = e_replaceDefiningFunctionDeclarationWithFunctionPrototype;
9811 X.statementToRemove = functionDeclaration;
9812 X.statementToAdd = NULL;
9813 X.class_definition = NULL;
9814 X.target_class_member = NULL;
9815 X.new_function_prototype = NULL;
9816
9817 // DQ (2/28/2021): Added new data member to support deferred transformations.
9818 X.locationToOverwriteWithTransformation = NULL;
9819 X.transformationToOverwriteFirstStatementInInterval = NULL;
9820 X.blockOfStatementsToOutline = NULL;
9821
9822 return X;
9823 }
9824
9826SageInterface::DeferredTransformation::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool /*movePreprocessingInfo = false*/)
9827 {
9828#if 0
9829 printf ("In SageInterface::DeferredTransformation constructor for replaceStatement called \n");
9830#endif
9831 // DQ (11/20/20): Added new static function to support genertation of deferred transformation.
9832 // This constructor is used by tool_G and supports the use of the transformation represented
9833 // by SageInterface::replaceDefiningFunctionDeclarationWithFunctionPrototype().
9835 X.deferredTransformationKind = e_replaceStatement;
9836 X.statementToRemove = oldStmt;
9837 X.statementToAdd = newStmt;
9838 X.class_definition = NULL;
9839 X.target_class_member = NULL;
9840 X.new_function_prototype = NULL;
9841
9842 // DQ (2/28/2021): Added new data member to support deferred transformations.
9843 X.locationToOverwriteWithTransformation = NULL;
9844 X.transformationToOverwriteFirstStatementInInterval = NULL;
9845 X.blockOfStatementsToOutline = NULL;
9846
9847 return X;
9848 }
9849
9850SageInterface::DeferredTransformation::DeferredTransformation (const DeferredTransformation& X)
9851#if 0
9852 : deferredTransformationKind(X.deferredTransformationKind),
9853 statementToRemove(X.statementToRemove),
9854 statementToAdd(X.StatementToAdd),
9855 class_definition(X.class_definition),
9856 target_class_member(X.target_class_member),
9857 new_function_prototype(X.new_function_prototype),
9858 targetClasses(X.targetClasses),
9859 targetFriends(X.targetFriends)
9860 {
9861 }
9862#else
9863 {
9864#if 0
9865 printf ("In SageInterface::DeferredTransformation copy constructor called \n");
9866#endif
9867 // DQ (11/19/2020): Leverage the operator=() implementation to reduce complexity (one place to update).
9868 *this = X;
9869 }
9870#endif
9871
9873 {
9874#if 0
9875 printf ("Inside of SageInterface::DeferredTransformation::operator= (const DeferredTransformation& X) \n");
9876#endif
9877
9878#if 0
9879 // Original code.
9880 targetFriends = X.targetFriends;
9881 targetClasses = X.targetClasses;
9882#else
9883
9884 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9885 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9886 // definitions in the dynamic library file with function prototypes.
9887 transformationLabel = X.transformationLabel;
9888
9889 // New code added to support more general usage.
9890 deferredTransformationKind = X.deferredTransformationKind;
9891 statementToRemove = X.statementToRemove;
9892 statementToAdd = X.statementToAdd;
9893
9894 class_definition = X.class_definition;
9895 target_class_member = X.target_class_member;
9896 new_function_prototype = X.new_function_prototype;
9897 targetClasses = X.targetClasses;
9898 targetFriends = X.targetFriends;
9899
9900 // DQ (2/28/2021): Added new data member to support deferred transformations.
9901 statementInterval = X.statementInterval;
9902 locationToOverwriteWithTransformation = X.locationToOverwriteWithTransformation;
9903 transformationToOverwriteFirstStatementInInterval = X.transformationToOverwriteFirstStatementInInterval;
9904
9905 // DQ (3/1/2021): Added new data member to support deferred transformations.
9906 blockOfStatementsToOutline = X.blockOfStatementsToOutline;
9907#endif
9908
9909 return *this;
9910 }
9911
9916
9917std::string SageInterface::DeferredTransformation::outputDeferredTransformationKind(const TransformationKind & kind)
9918 {
9919 string returnValue = "uninitialized";
9920 switch (kind)
9921 {
9922 case e_error: returnValue = "e_error"; break;
9923 case e_default: returnValue = "e_default"; break;
9924 case e_outliner: returnValue = "e_outliner"; break;
9925 case e_replaceStatement: returnValue = "e_replaceStatement"; break;
9926 case e_removeStatement: returnValue = "e_removeStatement"; break;
9927 case e_replaceDefiningFunctionDeclarationWithFunctionPrototype: returnValue = "e_replaceDefiningFunctionDeclarationWithFunctionPrototype"; break;
9928 case e_last: returnValue = "e_last"; break;
9929 default:
9930 {
9931 printf ("Error: SageInterface::DeferredTransformation::get_deferredTransformationKind_string(): default reached \n");
9932 ROSE_ABORT();
9933 }
9934 }
9935
9936 return returnValue;
9937 }
9938
9939void SageInterface::DeferredTransformation::display ( std::string label ) const
9940 {
9941 printf ("SageInterface::DeferredTransformation::display(): label = %s \n",label.c_str());
9942
9943 // DQ (12/12/2020): Adding a string label so that we can name the different kinds of transformations.
9944 // E.g. moving pattern matched function from header file to dynamic library, vs. replacing function
9945 // definitions in the dynamic library file with function prototypes.
9946 printf (" --- transformationLabel = %s \n",transformationLabel.c_str());
9947
9948 printf (" --- deferredTransformationKind = %s \n",outputDeferredTransformationKind(deferredTransformationKind).c_str());
9949 if (statementToRemove != NULL)
9950 {
9951 printf (" --- statementToRemove = %p = %s name = %s \n",statementToRemove,statementToRemove->class_name().c_str(),get_name(statementToRemove).c_str());
9952 }
9953 else
9954 {
9955 printf (" --- statementToRemove == NULL \n");
9956 }
9957
9958 if (statementToAdd != NULL)
9959 {
9960 printf (" --- statementToAdd = %p = %s name = %s \n",statementToAdd,statementToAdd->class_name().c_str(),get_name(statementToAdd).c_str());
9961 }
9962 else
9963 {
9964 printf (" --- statementToAdd == NULL \n");
9965 }
9966
9967 if (class_definition != NULL)
9968 {
9969 // printf (" --- class_definition = %p = %s name = %s \n",class_definition,class_definition->class_name().c_str(),get_name(class_definition).c_str());
9970 printf (" --- class_definition = %p \n",class_definition);
9971 }
9972
9973 if (target_class_member != NULL)
9974 {
9975 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());
9976 }
9977
9978 if (new_function_prototype != NULL)
9979 {
9980 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());
9981 }
9982
9983 // DQ (2/28/2021): Added new data member to support deferred transformations.
9984 if (locationToOverwriteWithTransformation != NULL)
9985 {
9986 // printf (" --- locationToOverwriteWithTransformation = %p = %s name = %s \n",locationToOverwriteWithTransformation,
9987 // locationToOverwriteWithTransformation->class_name().c_str(),get_name(locationToOverwriteWithTransformation).c_str());
9988 printf (" --- locationToOverwriteWithTransformation = %p \n",locationToOverwriteWithTransformation);
9989 }
9990
9991 // DQ (2/28/2021): Added new data member to support deferred transformations.
9992 if (transformationToOverwriteFirstStatementInInterval != NULL)
9993 {
9994 // printf (" --- transformationToOverwriteFirstStatementInInterval = %p = %s name = %s \n",transformationToOverwriteFirstStatementInInterval,
9995 // transformationToOverwriteFirstStatementInInterval->class_name().c_str(),get_name(transformationToOverwriteFirstStatementInInterval).c_str());
9996 printf (" --- transformationToOverwriteFirstStatementInInterval = %p \n",transformationToOverwriteFirstStatementInInterval);
9997 }
9998
9999 // DQ (3/1/2021): Added new data member to support deferred transformations.
10000 if (blockOfStatementsToOutline != NULL)
10001 {
10002 printf (" --- blockOfStatementsToOutline = %p \n",blockOfStatementsToOutline);
10003 }
10004
10005 printf ("targetClasses.size() = %zu \n",targetClasses.size());
10006 printf ("targetFriends.size() = %zu \n",targetFriends.size());
10007
10008 // DQ (2/28/2021): Added new data member to support deferred transformations.
10009 printf ("statementInterval.size() = %zu \n",statementInterval.size());
10010
10011 }
10012#endif
10013
10014
10015
10016
10017
10018// DQ (/20/2010): Control debugging output for SageInterface::removeStatement() function.
10019#define REMOVE_STATEMENT_DEBUG 0
10020
10022void SageInterface::removeStatement(SgStatement* targetStmt, bool autoRelocatePreprocessingInfo /*= true*/)
10023 {
10024#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
10025 // This function removes the input statement.
10026 // If there are comments and/or CPP directives then those comments and/or CPP directives will
10027 // be moved to a new SgStatement. The new SgStatement is selected using the findSurroundingStatementFromSameFile()
10028 // function and if there is not statement found then the SgGlobal IR node will be selected.
10029 // this work is tested by the tests/nonsmoke/functional/roseTests/astInterfaceTests/removeStatementCommentRelocation.C
10030 // translator and a number of input codes that represent a range of contexts which exercise different
10031 // cases in the code below.
10032
10033#ifndef _MSC_VER
10034 // This function only supports the removal of a whole statement (not an expression within a statement)
10035 ASSERT_not_null(targetStmt);
10036
10037 SgStatement * parentStatement = isSgStatement(targetStmt->get_parent());
10038
10039 // Can't assert this since SgFile is the parent of SgGlobal, and SgFile is not a statement.
10040 // Even so SgGlobal can't be removed from SgFile, but isRemovableStatement() takes a SgStatement.
10041 // ROSE_ASSERT (parentStatement != NULL);
10042
10043 bool isRemovable = (parentStatement != NULL) ? LowLevelRewrite::isRemovableStatement(targetStmt) : false;
10044
10045#if REMOVE_STATEMENT_DEBUG || 0
10046 printf ("In SageInterface::removeStatement(): parentStatement = %p = %s remove targetStatement = %p = %s (isRemovable = %s) \n",
10047 parentStatement,parentStatement->class_name().c_str(),targetStmt,targetStmt->class_name().c_str(),isRemovable ? "true" : "false");
10048#endif
10049
10050 if (isRemovable == true)
10051 {
10052 // DQ (9/19/2010): Disable this new (not completely working feature) so that I can checkin the latest UPC/UPC++ work.
10053#if 1
10054 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
10055 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
10056 // Liao 10/28/2010. Sometimes we want remove the statement with all its preprocessing information
10057 if (autoRelocatePreprocessingInfo == true)
10058 {
10059 // WE need to move up inner danglinge #endif or #if directives first.
10061 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
10062 // appear before the statment to be attached to the inserted statement (and marked
10063 // to appear before that statement).
10064 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
10065
10066
10067 if (comments != nullptr && isSgBasicBlock(targetStmt) == nullptr )
10068 {
10069 vector<int> captureList;
10070#if REMOVE_STATEMENT_DEBUG
10071 printf ("Found attached comments (removing %p = %s): comments->size() = %" PRIuPTR " \n",targetStmt,targetStmt->class_name().c_str(),comments->size());
10072#endif
10073
10074 // Liao 10/28/2010. relinking AST statements may be achieved by remove it and attach it to somewhere else.
10075 // In this case, preprocessing information sometimes should go with the statements and not be relocated to the original places.
10076 // Dan: Since this statement will be removed we have to relocate all the associated comments and CPP directives.
10077 int commentIndex = 0;
10078 AttachedPreprocessingInfoType::iterator i;
10079 for (i = comments->begin(); i != comments->end(); i++)
10080 {
10081 ROSE_ASSERT ( (*i) != NULL );
10082#if REMOVE_STATEMENT_DEBUG
10083 printf (" Attached Comment (relativePosition=%s): %s\n",
10084 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
10085 (*i)->getString().c_str());
10086 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
10087 (*i)->get_file_info()->display("comment/directive location debug");
10088#endif
10089 captureList.push_back(commentIndex);
10090 commentIndex++;
10091 }
10092
10093#if REMOVE_STATEMENT_DEBUG
10094 printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
10095#endif
10096
10097 if (captureList.empty() == false)
10098 {
10099 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
10100 // Find the surrounding statement by first looking up in the sequence of statements in this block, then down, we need another
10101 // statement from the same file. SgGlobal may be returned if nothing else is found.
10102 bool surroundingStatementPreceedsTargetStatement = false;
10103 SgStatement* surroundingStatement = findSurroundingStatementFromSameFile(targetStmt,surroundingStatementPreceedsTargetStatement);
10104
10105 if (surroundingStatement != nullptr)
10106 {
10107 // If we have identified a valid surrounding statemen, then move the comments and CPP directives to that statement.
10108#if REMOVE_STATEMENT_DEBUG
10109 printf ("In removeStatement(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10110 printf (" --- moving comments from targetStmt = %p = %s name = %s \n",targetStmt,targetStmt->class_name().c_str(),get_name(targetStmt).c_str());
10111 printf (" --- moving comments to surroundingStatement = %p = %s name = %s \n",surroundingStatement,surroundingStatement->class_name().c_str(),get_name(surroundingStatement).c_str());
10112#endif
10113 moveCommentsToNewStatement(targetStmt,captureList,surroundingStatement,surroundingStatementPreceedsTargetStatement);
10114 }
10115 }
10116 } // end if (comments)
10117 }// end if (autoRelocatePreprocessingInfo)
10118#endif // end #if 1
10119
10120 // DQ (12/1/2015): Adding support for fixup internal data struuctures that have references to statements (e.g. macro expansions).
10122
10123 parentStatement->remove_statement(targetStmt);
10124 }
10125#else
10126 printf ("Error: This is not supported within Microsoft Windows (I forget why). \n");
10127 ROSE_ABORT();
10128#endif
10129
10130#endif
10131 }
10132
10133
10134
10136void
10138 {
10139 // This function allows the modification of the input statement to trigger operations on internal
10140 // data structures that hold references to such statements. An example is the macroExpansion
10141 // data structures that have a reference to the statements that are associated with and macro expansion.
10142 // if a statement assocated with a macro expansion is removed, then the macroExpansion needs to be
10143 // updated to force all of the statements to be marked as transformed (so that the AST will be unparsed
10144 // instead of the tokens representing the macro or some partial representation of the transformed
10145 // statements and the macro call (worse).
10146
10147#if 0
10148 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10149#endif
10150
10151 SgSourceFile* sourceFile = getEnclosingSourceFile(sourceStatement);
10152
10153 // NOTE: if the statment has not yet been added to the AST then it will not return a valid pointer.
10154 // ROSE_ASSERT(sourceFile != NULL);
10155
10156#if 0
10157 printf ("In SageInterface::resetInternalMapsForTargetStatement(SgStatement*): sourceFile = %p \n",sourceFile);
10158#endif
10159
10160 if (sourceFile != NULL)
10161 {
10162 std::map<SgStatement*,MacroExpansion*> & macroExpansionMap = sourceFile->get_macroExpansionMap();
10163
10164 if (macroExpansionMap.find(sourceStatement) != macroExpansionMap.end())
10165 {
10166 MacroExpansion* macroExpansion = macroExpansionMap[sourceStatement];
10167 ROSE_ASSERT(macroExpansion != NULL);
10168#if 0
10169 printf ("In resetInternalMapsForTargetStatement(): macroExpansion = %p = %s \n",macroExpansion,macroExpansion->macro_name.c_str());
10170#endif
10171 if (macroExpansion->isTransformed == false)
10172 {
10173 // Mark all of the statements in the macro expansion to be transformed.
10174 std::vector<SgStatement*> & associatedStatementVector = macroExpansion->associatedStatementVector;
10175
10176 for (size_t i = 0; i < associatedStatementVector.size(); i++)
10177 {
10178 // I am concerned that some of these statements might have been deleted.
10179 SgStatement* statement = associatedStatementVector[i];
10180#if 0
10181 printf ("Mark as transformation to be output: statement = %p = %s \n",statement,statement->class_name().c_str());
10182#endif
10183 // Note that any new statement might not yet have valid Sg_File_Info objects setup at this point.
10184 // Then again, now did it make it into the associatedStatementVector unless it was via memory
10185 // recycling through the mmory pool.
10186 if (statement->get_file_info() != NULL)
10187 {
10188 // Mark each of the statements as a transformation.
10189 statement->setTransformation();
10190
10191 // This is required, else the statement will not be output in the generated code.
10192 // To understand this, consider that statements in header files could be transformed,
10193 // but we would not want that to cause them to be unparse in the source file.
10194 statement->setOutputInCodeGeneration();
10195
10196 // Not clear if we should also remove the statement from the associatedStatementVector.
10197 // This would be important to do to avoid having the same location in the memory pool
10198 // be reused for another statement. Since we makr the macro expansion as transformed
10199 // we likely don't have to worry about this.
10200 }
10201 }
10202 }
10203
10204 // Mark this macro expansion as having been processed.
10205 macroExpansion->isTransformed = true;
10206 }
10207
10208 // Other data strucutes that may have to be updated include:
10209 // representativeWhitespaceStatementMap (should be required, but only effects whitespace details)
10210 // redundantlyMappedTokensToStatementMultimap (might not be required)
10211
10212 }
10213 }
10214
10215
10217void
10218SageInterface::moveCommentsToNewStatement(SgStatement* sourceStatement, const vector<int> & indexList, SgStatement* destinationStatement , bool destinationStatementProceedsSourceStatement)
10219 {
10220 AttachedPreprocessingInfoType* comments = sourceStatement->getAttachedPreprocessingInfo();
10221
10222#if REMOVE_STATEMENT_DEBUG || 0
10223 printf ("In moveCommentsToNewStatement(): destinationStatementProceedsSourceStatement = %s \n",destinationStatementProceedsSourceStatement ? "true" : "false");
10224 printf (" --- sourceStatement = %p = %s name = %s \n",sourceStatement,sourceStatement->class_name().c_str(),get_name(sourceStatement).c_str());
10225 printf (" --- destinationStatement = %p = %s name = %s \n",destinationStatement,destinationStatement->class_name().c_str(),get_name(destinationStatement).c_str());
10226#endif
10227 // Liao 2024/1/24
10228 // 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.
10229 // A solution : pcounter++ whenever a leading #if #ifdef #ifndef is encountered.
10230 // pcounter -- if #endif is countered
10231 // Normally the final pcounter ==0, if pcounter>=1, a #endif is missing somewhere. We should patch it up.
10232
10233#if REMOVE_STATEMENT_DEBUG
10234 printf ("Output the comments attached to sourceStatement: \n");
10235 printOutComments(sourceStatement);
10236 printf ("Output the comments attached to destinationStatement: \n");
10237 printOutComments(destinationStatement);
10238#endif
10239
10240 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
10241 vector<int>::const_iterator j = indexList.begin();
10242 PreprocessingInfo* prevTargetAnchorComment = NULL;
10243 while (j != indexList.end())
10244 {
10245 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
10246 ROSE_ASSERT(destinationStatement->get_file_info() != NULL);
10247#if REMOVE_STATEMENT_DEBUG || 0
10248 printf ("Attaching comments to destinationStatement = %p = %s on file = %s line %d \n",
10249 destinationStatement,destinationStatement->class_name().c_str(),
10250 destinationStatement->get_file_info()->get_filenameString().c_str(),
10251 destinationStatement->get_file_info()->get_line());
10252
10253 printf ("(*comments)[*j]->getRelativePosition() = %s \n",PreprocessingInfo::relativePositionName((*comments)[*j]->getRelativePosition()).c_str());
10254#endif
10255
10256 // Liao 2024/3/27: special handling when surrounding statement is SgGlobal
10257 // It should not be treated as either before or after the source statement we want to move comments from
10258 // SgGlobal should be treated as the enclosing scope of the source statement
10259 // The comments of the source statements should be attached to inside position of SgGlobal.
10260 // This is a variant of the before position (SgGlobal vs. source statement).
10261 // We do not treate SgGlobal as the same as if sgGlobal is preceeding source
10262 // because the comments of source statement would be attached to ::after of SgGlobal and
10263 // all comments will show up in the end of the file.
10264 // The ::inside location relies on the unparser to properly handle them later.
10265 if (destinationStatementProceedsSourceStatement == true || isSgGlobal(destinationStatement) != NULL )
10266 {
10267 // dest
10268 // src // comments to be moved up: all before positions become after position
10269 // // then append to dest's commments
10270 // adjust relative position one by one
10271 auto commentPosition = (*comments)[*j]->getRelativePosition();
10272 if (commentPosition == PreprocessingInfo::before)
10273 {
10274 // Mark comments that were before the preceeding statement to be after the preceeding statement
10275 (*comments)[*j]->setRelativePosition(PreprocessingInfo::after);
10276 }
10277 else if (commentPosition == PreprocessingInfo::after ||
10278 commentPosition == PreprocessingInfo::end_of)
10279 {
10280 // Leave position alone [Rasmussen 2023.01.09]
10281 }
10282 else
10283 {
10284 ROSE_ASSERT(false && "Comment relative position neither, before, after, nor end_of");
10285 }
10286
10287 // special handling of inside position
10288 // The surrounding statement will accept the comments. It also preceeds the source statement providing the comments.
10289 // If it is an enclosing scope statement, the comments should be attached to inside position, not before nor after.
10290 // if ( isSgGlobal(destinationStatement) || isSgBasicBlock(destinationStatement) )
10291 // Handle all SgScopeStatement variants.
10292 // We do this only for C/C++ language. Otherwise the code may break Jovial and other languages.
10294 {
10295 if (SageInterface::isAncestor(destinationStatement, sourceStatement))
10296 (*comments)[*j]->setRelativePosition(PreprocessingInfo::inside);
10297 }
10298 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10299
10300 }
10301 else // the target statement is after the source statment: we want to move comments from src to target
10302 {
10303 // src : comments : before or after (when moved to dest, it should become before)
10304 // all should be prepend to dest's first comment
10305 // dest: comments
10306 // adjust relative position one by one
10307 if ((*comments)[*j]->getRelativePosition() == PreprocessingInfo::before)
10308 {
10309 // Leave the comments marked as being before the removed statement
10310 // as before the following statement
10311 }
10312 else
10313 {
10314 // If is is not before, I hope it can only be after. Sometimes it is end_of, e.g. gitlab-issue-186.jov
10315 ASSERT_require((*comments)[*j]->getRelativePosition() == PreprocessingInfo::after||
10316 (*comments)[*j]->getRelativePosition() == PreprocessingInfo::end_of);
10317 (*comments)[*j]->setRelativePosition(PreprocessingInfo::before);
10318 }
10319 AttachedPreprocessingInfoType* targetInfoList = destinationStatement->getAttachedPreprocessingInfo();
10320 // source stmt has a list of comments c1, c2, c3
10321 // we want to keep their order and prepend to target stmt's existing comments
10322 // The solution is to define an anchor comment in target stmt
10323 // first time anchor is NULL, we prepend c1 to before the target stmt's first comment
10324 // after that, we insert after the anchor comment (previous anchor)
10325 // all anchor comments must come from source statement
10326 if (targetInfoList==NULL)
10327 {
10328 // we can just use append to the end. the same effect.
10329 destinationStatement->addToAttachedPreprocessingInfo((*comments)[*j]);
10330 }
10331 else
10332 {
10333 // target stmt has comments
10334 // first time to grab thing
10335 if( prevTargetAnchorComment==NULL)
10336 {
10337 PreprocessingInfo * origFirstTargetComment = *(targetInfoList->begin());
10338 // insert before this original first one
10339 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],origFirstTargetComment,false);
10340 }
10341 else
10342 {
10343 // now we have non null prev comment from target statement. insert after it!
10344 destinationStatement->insertToAttachedPreprocessingInfo((*comments)[*j],prevTargetAnchorComment ,true);
10345 }
10346 }
10347
10348 prevTargetAnchorComment = (*comments)[*j];
10349 }
10350
10351
10352 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
10353#if REMOVE_STATEMENT_DEBUG
10354 printf ("Marking entry from comments list as NULL on sourceStatement = %p = %s \n",sourceStatement,sourceStatement->class_name().c_str());
10355#endif
10356 (*comments)[*j] = nullptr;// Why do we need to make it NULL??
10357
10358 j++;
10359 }
10360
10361 // Now remove each NULL entries in the comments vector.
10362 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
10363 for (size_t n = 0; n < indexList.size(); n++)
10364 {
10365#if REMOVE_STATEMENT_DEBUG || 0
10366 printf ("Erase entry from comments list on comments->size() %" PRIuPTR " \n",comments->size());
10367#endif
10368 bool modifiedList = false;
10369 AttachedPreprocessingInfoType::iterator k = comments->begin();
10370 while (k != comments->end() && modifiedList == false)
10371 {
10372 // Only modify the list once per iteration over the captureList
10373 if (*k == nullptr)
10374 {
10375 k = comments->erase(k);
10376 modifiedList = true;
10377 continue;
10378 }
10379 else
10380 {
10381 k++;
10382 }
10383 }
10384 }
10385 }
10386
10387
10389// This function is a helper function for SageInterface::removeStatement() to handle preprocessing info.
10390// It should find a suitable destination statement to which we can move the current stmt's preprocessing info to.
10391// targetStmt of this function is the source statement to move preprocessing info first, before removing it.
10393SageInterface::findSurroundingStatementFromSameFile(SgStatement* targetStmt, bool & surroundingStatementPreceedsTargetStatement)
10394 {
10395 // Note that if the return value is SgGlobal (global scope), then surroundingStatementPreceedsTargetStatement is false, but meaningless.
10396 // This function can not return a NULL pointer.
10397
10398 ROSE_ASSERT(targetStmt != NULL);
10399
10400 SgStatement* surroundingStatement = targetStmt;
10401 int surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID; // No file id can have this value.
10402
10403#if REMOVE_STATEMENT_DEBUG || 0
10404 printf ("TOP of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s \n",surroundingStatementPreceedsTargetStatement ? "true" : "false");
10405#endif
10406
10407 std::set<SgStatement*> previousVisitedStatementSet;
10408
10409 // Only handle relocation for statements that exist in the file (at least for now while debugging).
10410 if (targetStmt->get_file_info()->get_file_id() >= 0)
10411 {
10412 surroundingStatementPreceedsTargetStatement = true;
10413
10414#if REMOVE_STATEMENT_DEBUG
10415 printf (" targetStmt->get_file_info()->get_file_id() = %d \n",targetStmt->get_file_info()->get_file_id());
10416#endif
10417#if REMOVE_STATEMENT_DEBUG
10418 printf ("Before loop: surroundingStatement = %p = %s name = %s surroundingStatement_fileId = %d \n",surroundingStatement,
10419 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str(),surroundingStatement_fileId);
10420#endif
10421 bool returningNullSurroundingStatement = false;
10422 // while (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id())
10423 while ((returningNullSurroundingStatement == false) && (surroundingStatement != NULL) && surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id() && surroundingStatement_fileId !=Sg_File_Info::TRANSFORMATION_FILE_ID)
10424 {
10425 // Start by going up in the source sequence.
10426 // This is a declaration from the wrong file so go to the next statement.
10427 // surroundingStatement = (insertBefore == true) ? getNextStatement(surroundingStatement) : getPreviousStatement(surroundingStatement);
10428 // surroundingStatement = (insertBefore == true) ? getPreviousStatement(surroundingStatement) : getNextStatement(surroundingStatement);
10429 // Liao, 12/26/2024. We should not climb out the current scope when finding the previous statement
10430 // Otherwise, preprocessingInfo may be moved from a child stmt to its parent stmt, causing errors in AST.
10431 surroundingStatement = getPreviousStatement(surroundingStatement, false);
10432
10433#if REMOVE_STATEMENT_DEBUG
10434 printf ("In loop: after getPreviousStatement(): surroundingStatement = %p = %s name = %s \n",surroundingStatement,
10435 surroundingStatement->class_name().c_str(),SageInterface::get_name(surroundingStatement).c_str());
10436#endif
10437
10438 if (surroundingStatement == NULL)
10439 {
10440 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10441#if REMOVE_STATEMENT_DEBUG
10442 printf (" surroundingStatement_fileId set to Sg_File_Info::BAD_FILE_ID \n");
10443#endif
10444 }
10445 else
10446 {
10447 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10448#if REMOVE_STATEMENT_DEBUG
10449 printf (" surroundingStatement = %p = %s surroundingStatement->get_file_info()->get_file_id() = %d \n",
10450 surroundingStatement,surroundingStatement->class_name().c_str(),surroundingStatement->get_file_info()->get_file_id());
10451#endif
10452 }
10453
10454#if REMOVE_STATEMENT_DEBUG
10455 if (surroundingStatement != NULL)
10456 {
10457 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",
10458 surroundingStatement,surroundingStatement->class_name().c_str(),
10459 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10460 surroundingStatement->get_file_info()->get_file_id(),
10461 surroundingStatement->get_file_info()->get_line());
10462 }
10463 else
10464 {
10465 printf ("surroundingStatement == NULL \n");
10466 }
10467#endif
10468
10469 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10470 if (previousVisitedStatementSet.find(surroundingStatement) != previousVisitedStatementSet.end())
10471 {
10472 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10473
10474 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10475
10476 surroundingStatement = NULL;
10477 // break;
10478 // return NULL;
10479 }
10480 else
10481 {
10482 previousVisitedStatementSet.insert(surroundingStatement);
10483 }
10484
10485 // As a last resort restart and go down in the statement sequence.
10486 if (surroundingStatement == NULL || isSgGlobal(surroundingStatement) != NULL)
10487 {
10488 // This is triggered by rose_inputloopUnrolling.C
10489#if REMOVE_STATEMENT_DEBUG
10490 printf ("We just ran off the start (top) of the file... targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
10491#endif
10492#if 0
10493 ROSE_ABORT();
10494#endif
10495 // A statement in the same file could not be identified, so this is false.
10496 surroundingStatementPreceedsTargetStatement = false;
10497
10498 // Restart by going the other direction (down in the source sequence)
10499 surroundingStatement = targetStmt;
10500 SgStatement* previousStatement = surroundingStatement;
10501 // surroundingStatement = getNextStatement(surroundingStatement);
10502 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10503
10504 std::set<SgStatement*> forwardVisitedStatementSet;
10505
10506 // while ( (surroundingStatement != NULL) && (surroundingStatement->get_file_info()->get_file_id() != targetStmt->get_file_info()->get_file_id()) )
10507 while ( (surroundingStatement != NULL) && (surroundingStatement_fileId != targetStmt->get_file_info()->get_file_id()) )
10508 {
10509 // DQ (11/15/2020): Eliminate the infinite loop that is possible when we iterate over a loop of statements.
10510 if (forwardVisitedStatementSet.find(surroundingStatement) != forwardVisitedStatementSet.end())
10511 {
10512 printf ("This statement has been previously visited: surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10513
10514 printf ("ERROR: SageInterface::findSurroundingStatementFromSameFile(): cannot located surrounding statement from same file (return NULL) \n");
10515
10516 surroundingStatement = NULL;
10517 break;
10518 // return NULL;
10519 }
10520 else
10521 {
10522 forwardVisitedStatementSet.insert(surroundingStatement);
10523 }
10524
10525 previousStatement = surroundingStatement;
10526 surroundingStatement = getNextStatement(surroundingStatement);
10527
10528 if (surroundingStatement == NULL)
10529 {
10530 surroundingStatement_fileId = Sg_File_Info::BAD_FILE_ID;
10531#if REMOVE_STATEMENT_DEBUG
10532 printf ("We just ran off the end (bottom) of the file... \n");
10533#endif
10534#if 0
10535 ROSE_ABORT();
10536#endif
10537 returningNullSurroundingStatement = true;
10538 }
10539 else
10540 {
10541 surroundingStatement_fileId = surroundingStatement->get_file_info()->get_file_id();
10542#if REMOVE_STATEMENT_DEBUG
10543 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",
10544 surroundingStatement,surroundingStatement->class_name().c_str(),
10545 surroundingStatement->get_file_info()->get_filenameString().c_str(),
10546 surroundingStatement->get_file_info()->get_file_id(),
10547 surroundingStatement->get_file_info()->get_line());
10548#endif
10549 }
10550 }
10551
10552 if (surroundingStatement == NULL)
10553 {
10554#if REMOVE_STATEMENT_DEBUG
10555 printf ("Resetting the surroundingStatement to the previousStatement = %p = %s \n",previousStatement,previousStatement->class_name().c_str());
10556#endif
10557 surroundingStatement = previousStatement;
10558
10559 // Check if this is the input statement we are removing (since the we have to attach comments to the global scope IR node.
10560 if (surroundingStatement == targetStmt)
10561 {
10562 // This can happen if there was only a single statement in a file and it was removed.
10563 // All associated comments would have to be relocated to the SgGlobal IR node.
10564#if REMOVE_STATEMENT_DEBUG
10565 printf ("Setting the surroundingStatement to be global scope \n");
10566#endif
10567 surroundingStatement = TransformationSupport::getGlobalScope(targetStmt);
10568 }
10569 }
10570 }
10571 }
10572
10573 ROSE_ASSERT(surroundingStatement != NULL);
10574 }
10575 else
10576 {
10577 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());
10578 surroundingStatement = NULL;
10579 }
10580
10581#if REMOVE_STATEMENT_DEBUG
10582 printf ("BOTTOM of findSurroundingStatementFromSameFile(): surroundingStatementPreceedsTargetStatement = %s surroundingStatement = %p \n",surroundingStatementPreceedsTargetStatement ? "true" : "false",surroundingStatement);
10583 if (surroundingStatement != NULL)
10584 {
10585 printf ("surroundingStatement = %p = %s \n",surroundingStatement,surroundingStatement->class_name().c_str());
10586 }
10587#endif
10588
10589 // ROSE_ASSERT(surroundingStatement != NULL);
10590
10591 return surroundingStatement;
10592 }
10593
10594
10595#ifndef USE_ROSE
10598{
10599#if 0
10600 struct Visitor: public AstSimpleProcessing {
10601 virtual void visit(SgNode* n) {
10602 delete (n);
10603 }
10604 };
10605 Visitor().traverse(root, postorder);
10606#else
10607 deleteAST(root);
10608#endif
10609}
10610#endif
10611
10613void SageInterface::replaceStatement(SgStatement* oldStmt, SgStatement* newStmt, bool movePreprocessingInfoValue/* = false*/)
10614 {
10615 ROSE_ASSERT(oldStmt);
10616 ROSE_ASSERT(newStmt);
10617
10618 if (oldStmt == newStmt) return;
10619
10620 SgStatement * p = isSgStatement(oldStmt->get_parent());
10621 ROSE_ASSERT(p);
10622
10623#if 0
10624 // TODO handle replace the body of a C/Fortran function definition with a single statement?
10625 // Liao 2/1/2010, in some case, we want to replace the entire body (SgBasicBlock) for some parent nodes.
10626 // the built-in replace_statement() (insert_child() underneath) may not defined for them.
10627 if (SgFortranDo * f_do = isSgFortranDo (p))
10628 {
10629 ROSE_ASSERT (f_do->get_body() == oldStmt);
10630 if (!isSgBasicBlock(newStmt))
10631 newStmt = buildBasicBlock (newStmt);
10632 f_do->set_body(isSgBasicBlock(newStmt));
10633 newStmt->set_parent(f_do);
10634 }
10635 else
10636 {
10637 p->replace_statement(oldStmt,newStmt);
10638 }
10639#endif
10640 p->replace_statement(oldStmt,newStmt);
10641
10642#if 1
10643 // DQ (7/20/2021): Need to make the physical_file_ids match and the parents.
10644 // Acutally this may be too late in the case of a deferred transformation since
10645 // we run the AST consistancy tests as an intermediate step.
10646 int physical_file_id = oldStmt->get_startOfConstruct()->get_physical_file_id();
10647
10648#if 0
10649 printf ("In SageInterface::replaceStatement(): physical_file_id = %d \n",physical_file_id);
10650#endif
10651
10652 newStmt->get_startOfConstruct()->set_physical_file_id(physical_file_id);
10653 newStmt->get_endOfConstruct ()->set_physical_file_id(physical_file_id);
10654
10655 // DQ (7/20/2021): Do we need this when we set the physical_file_id?
10656 newStmt->set_parent(oldStmt->get_parent());
10657#endif
10658
10659 // Some translators have their own handling for this (e.g. the outliner)
10660 if (movePreprocessingInfoValue)
10661 {
10662 // move inner dangling #endif, #if etc to newStmt's after position, otherwise they got lost
10663//A-B test here
10664 // I think we should move up old statement's inner dangling directives
10665 // later , we move directives from old statement to new statement
10667#if 0
10668 printf ("In SageInterface::replaceStatement(): calling moveUpPreprocessingInfo() changed to movePreprocessingInfo() \n");
10669#endif
10670
10671 // DQ (12/28/2020): I think this should be movePreprocessingInfo instead of moveUpPreprocessingInfo
10672 // (which has a collection of defaults that are not appropriate).
10673 // moveUpPreprocessingInfo(newStmt, oldStmt);
10674#if 1
10675 // 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).
10676 moveUpPreprocessingInfo(newStmt, oldStmt);
10677#else
10678 // void SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
10679 // PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
10680 bool usePrepend = true;
10681 // movePreprocessingInfo ( newStmt, oldStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10682 movePreprocessingInfo ( oldStmt, newStmt, PreprocessingInfo::undef, PreprocessingInfo::undef, usePrepend );
10683#endif
10684 }
10685 }
10686
10687void
10689 {
10690 // Relocate the declaration to be explicitly represented in its associated namespace (required for some backend compilers to process template instantiations).
10691
10692 // DQ (7/19/2015): This is required to support general unparsing of template instantations for the GNU g++
10693 // compiler which does not permit name qualification to be used to support the expression of the namespace
10694 // where a template instantiatoon would be places. Such name qualification would also sometimes require
10695 // global qualification which is also not allowed by the GNU g++ compiler. These issues appear to be
10696 // specific to the GNU compiler versions, at least versions 4.4 through 4.8.
10697
10698 // Find the previous statement in this scope so that we can close off the namepsace and start a new one.
10699 SgStatement* previousDeclarationStatement = getPreviousStatement(declarationStatement);
10700 SgStatement* nextDeclarationStatement = getNextStatement(declarationStatement);
10701
10702#if 0
10703 printf ("In SageInterface::moveDeclarationToAssociatedNamespace(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
10704 printf (" --- previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement != NULL ? previousDeclarationStatement->class_name().c_str() : "null");
10705 printf (" --- nextDeclarationStatement = %p \n",nextDeclarationStatement);
10706 printf (" --- nextDeclarationStatement = %p = %s \n",nextDeclarationStatement, nextDeclarationStatement != NULL ? nextDeclarationStatement->class_name().c_str() : "null");
10707#endif
10708
10709 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10710 if (previousDeclarationStatement != NULL)
10711 {
10712 // printf ("previousDeclarationStatement = %p = %s \n",previousDeclarationStatement,previousDeclarationStatement->class_name().c_str());
10713 }
10714 else
10715 {
10716 printf ("There is no previous statement so there is no namespace to close off! \n");
10717
10718 // Handle this corner case after we have the most general case working!
10719 printf ("Exiting as a test! \n");
10720 ROSE_ABORT();
10721 }
10722
10723 // DQ (7/19/2015): Initial error handling to allow us to focuse on the most common case.
10724 if (nextDeclarationStatement != NULL)
10725 {
10726 // printf ("nextDeclarationStatement = %p = %s \n",nextDeclarationStatement,nextDeclarationStatement->class_name().c_str());
10727 }
10728 else
10729 {
10730#if 0
10731 printf ("There is no next statement so there is no namespace to reopen! \n");
10732#endif
10733#if 0
10734 // Handle this corner case after we have the most general case working!
10735 printf ("Exiting as a test! \n");
10736 ROSE_ABORT();
10737#endif
10738 }
10739
10740 if (previousDeclarationStatement != NULL && nextDeclarationStatement != NULL)
10741 {
10742 // DQ (7/19/2015): This is the most common case!
10743#if 0
10744 printf ("Identified the most common case... \n");
10745#endif
10746 // Identify the associated namespace
10747 //SgScopeStatement* declarationScope = declarationStatement->get_scope();
10748#if 0
10749 printf ("declarationScope = %p = %s \n",declarationScope,declarationScope->class_name().c_str());
10750#endif
10751#if 0
10752 // Handle this corner case after we have the most general case working!
10753 printf ("Exiting as a test! \n");
10754 ROSE_ABORT();
10755#endif
10756 }
10757 else
10758 {
10759 if (previousDeclarationStatement != NULL && nextDeclarationStatement == NULL)
10760 {
10761 // This is the case for the last template instantiaton in global scope (so it too is a common case)!
10762#if 0
10763 printf ("Found 2nd most common case: previousDeclarationStatement != NULL && nextDeclarationStatement == NULL \n");
10764#endif
10765#if 0
10766 // Handle this corner case after we have the most general case working!
10767 printf ("Exiting as a test! \n");
10768 ROSE_ABORT();
10769#endif
10770 }
10771 else
10772 {
10773 if (previousDeclarationStatement == NULL && nextDeclarationStatement == NULL)
10774 {
10775 printf ("This case should require no special handling, unless we are still in the wrong namespace \n");
10776
10777 // Handle this corner case after we have the most general case working!
10778 printf ("Exiting as a test! \n");
10779 ROSE_ABORT();
10780 }
10781 else
10782 {
10783 printf ("This case should have been caught above! \n");
10784
10785 // Handle this corner case after we have the most general case working!
10786 printf ("Exiting as a test! \n");
10787 ROSE_ABORT();
10788 }
10789 }
10790 }
10791
10792 SgScopeStatement* declarationParent = isSgScopeStatement(declarationStatement->get_parent());
10793 if (declarationParent == NULL)
10794 {
10795#if 0
10796 printf ("declarationStatement->get_parent() = %p = %s \n",declarationStatement->get_parent(), (declarationStatement->get_parent() != NULL) ? declarationStatement->get_parent()->class_name().c_str() : "null");
10797#endif
10798 }
10799 // This can be a SgTemplateInstantiationDirectiveStatement (bug we want to skip over this case for now).
10800 // ROSE_ASSERT(declarationParent != NULL);
10801
10802 if (declarationParent != NULL)
10803 {
10804 SgScopeStatement* declarationScope = declarationStatement->get_scope();
10805 ROSE_ASSERT(declarationScope != NULL);
10806
10807 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(declarationScope);
10808 if (namespaceDefinition != NULL)
10809 {
10810 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
10811 ROSE_ASSERT(namespaceDeclaration != NULL);
10812#if 0
10813 printf ("The declaration has been identified to be associuated with a valid namespace = %p = %s \n",namespaceDeclaration,namespaceDeclaration->get_name().str());
10814 printf (" --- declarationParent = %p = %s \n",declarationParent,declarationParent->class_name().c_str());
10815 printf (" --- Move declaration from scope = %p = %s to namespace = %p = %s \n",declarationParent,declarationParent->class_name().c_str(),namespaceDeclaration,namespaceDeclaration->get_name().str());
10816#endif
10817#if 0
10818 printf ("Exiting as a test! \n");
10819 ROSE_ABORT();
10820#endif
10821 }
10822 else
10823 {
10824#if 0
10825 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());
10826#endif
10827 }
10828 }
10829 else
10830 {
10831#if 0
10832 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");
10833#endif
10834 // ROSE_ASSERT(declarationParent != NULL);
10835 }
10836
10837 }
10838
10839
10840bool
10842 {
10843 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10844 if (isSgTemplateInstantiationDefn(node) != NULL)
10845 {
10846#if 0
10847 printf ("Note: In SageInterface::isTemplateInstantiationNode(): skipping SgTemplateInstantiationDefn \n");
10848#endif
10849 }
10850
10851 return isSgTemplateInstantiationDecl(node)
10852 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10853// || isSgTemplateInstantiationDefn(node)
10854 || isSgTemplateInstantiationDefn(node)
10855 || isSgTemplateInstantiationFunctionDecl(node)
10856 || isSgTemplateInstantiationMemberFunctionDecl(node)
10857 || isSgTemplateInstantiationTypedefDeclaration(node)
10858 || isSgTemplateInstantiationDirectiveStatement(node)
10859 ;
10860 }
10861
10862#if 0
10863// DQ (5/23/2021): Added (uncommented, and added to the header file) function to support test for template declaration.
10864// Commented back out, since this is not required for what I am debugging currently.
10865// DQ (6/27/2018): This will be the template declaration test version of the template instantiation test function above.
10866bool
10867SageInterface::isTemplateDeclarationNode(SgNode* node)
10868 {
10869 // DQ (7/19/2015): I think we want to focus exclusively on declarations.
10870 if (isSgTemplateDefinition(node) != NULL)
10871 {
10872#if 0
10873 printf ("Note: In SageInterface::isTemplateDeclarationNode(): skipping SgTemplateDefinition \n");
10874#endif
10875 }
10876
10877 return isSgTemplateInstantiationDecl(node)
10878 // DQ (1/3/2016): Allow SgTemplateInstantiationDefn IR nodes.
10879 // || isSgTemplateInstantiationDefn(node)
10880 || isSgTemplateInstantiationDefn(node)
10881 || isSgTemplateInstantiationFunctionDecl(node)
10882 || isSgTemplateInstantiationMemberFunctionDecl(node)
10883 || isSgTemplateInstantiationTypedefDeclaration(node)
10884 || isSgTemplateInstantiationDirectiveStatement(node)
10885 ;
10886 }
10887#endif
10888
10889void
10891 {
10892 // DQ (8/18/2015): This function is called from the tests/nonsmoke/functional/testTemplates translator.
10893
10894 // DQ (7/19/2015): This function can't use an iterator since it will be
10895 // doing transformations on the AST and will cause iterator invalidation errors.
10896
10897 std::vector<SgDeclarationStatement*> templateInstantiationVector;
10898
10899 // DQ (9/24/2015): This feature is not available yet in CMake (Markus is adding the library support for this feature).
10900#ifndef USE_CMAKEx
10901 RoseAst ast(root);
10902
10903 for (RoseAst::iterator i= ast.begin(); i!= ast.end(); ++i)
10904 {
10906 {
10907 // markNodeToBeUnparsed(*i);
10908 SgDeclarationStatement* declaration = isSgDeclarationStatement(*i);
10909 if (declaration != NULL)
10910 {
10911 templateInstantiationVector.push_back(declaration);
10912 }
10913 else
10914 {
10915 // I think it is OK that not all are a SgDeclarationStatement.
10916 }
10917 }
10918 }
10919#else
10920 std::cerr << "This feature for now is available with autotools only!" << std::endl;
10921 ROSE_ABORT();
10922#endif
10923
10924 std::vector<SgDeclarationStatement*>::iterator j = templateInstantiationVector.begin();
10925 while (j != templateInstantiationVector.end())
10926 {
10928 j++;
10929 }
10930 }
10931
10932
10933
10935// All SgVariantExpression in the pattern will be replaced with copies of the anchor node.
10937{
10938 SgExpression * anchor_exp = isSgExpression(anchor);
10939 SgExpression * pattern_exp = isSgExpression(new_pattern);
10940 ROSE_ASSERT (anchor_exp != NULL);
10941 ROSE_ASSERT (pattern_exp != NULL);
10942
10943 // we replace all SgExpression within the pattern with copies of anchor
10944 Rose_STL_Container<SgNode*> opaque_exp_list = NodeQuery::querySubTree(pattern_exp,V_SgExpression);
10945 for (size_t i = 0; i<opaque_exp_list.size(); i++)
10946 {
10947 SgExpression* opaque_exp = isSgExpression(opaque_exp_list[i]);
10948 ROSE_ASSERT (opaque_exp != NULL);
10949 if (opaque_exp->variantT() == V_SgVariantExpression)
10950 {
10951 SgExpression * anchor_exp_copy = deepCopy(anchor_exp);
10952 replaceExpression(opaque_exp, anchor_exp_copy);
10953 }
10954 }
10955
10956 // finally we replace anchor_exp with the pattern_exp
10957 replaceExpression(anchor_exp, pattern_exp, false);
10958 return new_pattern;
10959}
10963{
10964 //This implementation tends to generate numbers that are unnecessarily high.
10965 static int counter = 0;
10966
10967 string name;
10968 bool collision = false;
10969 do
10970 {
10971 name = "__" + baseName + boost::lexical_cast<string > (counter++) + "__";
10972
10973 // DQ (8/16/2013): Modified to reflect new API.
10974 // Look up the name in the parent scopes
10975 // SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope);
10976 SgSymbol* nameSymbol = SageInterface::lookupSymbolInParentScopes(SgName(name), scope,NULL,NULL);
10977 collision = (nameSymbol != NULL);
10978
10979 //Look up the name in the children scopes
10980 Rose_STL_Container<SgNode*> childScopes = NodeQuery::querySubTree(scope, V_SgScopeStatement);
10981
10982 BOOST_FOREACH(SgNode* childScope, childScopes)
10983 {
10984 SgScopeStatement* childScopeStatement = isSgScopeStatement(childScope);
10985
10986 // DQ (8/16/2013): Modified to reflect new API.
10987 // nameSymbol = childScopeStatement->lookup_symbol(SgName(name));
10988 nameSymbol = childScopeStatement->lookup_symbol(SgName(name),NULL,NULL);
10989
10990 collision = collision || (nameSymbol != NULL);
10991 }
10992 } while (collision);
10993
10994 return name;
10995}
10996
10997
10998std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableForExpression
10999(SgExpression* expression, SgScopeStatement* scope, bool initializeInDeclaration, SgAssignOp** reEvaluate)
11000{
11001 SgType* expressionType = expression->get_type();
11002 SgType* variableType = expressionType;
11003
11004 //If the expression has a reference type, we need to use a pointer type for the temporary variable.
11005 //Else, re-assigning the variable is not possible
11006 bool isReferenceType = SageInterface::isReferenceType(expressionType);
11007 if (isReferenceType)
11008 {
11009 SgType* expressionBaseType = expressionType->stripType(SgType::STRIP_TYPEDEF_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE);
11010 variableType = SageBuilder::buildPointerType(expressionBaseType);
11011 }
11012
11013 //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.
11014 if (SgArrayType* arrayType=isSgArrayType(expressionType)) {
11015 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11016 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11017 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11018 }
11019 }
11020
11021 // If the expression is a dereferenced pointer, use a reference to hold it.
11022 if (isSgPointerDerefExp(expression))
11023 variableType = SageBuilder::buildReferenceType(variableType);
11024
11025 //Generate a unique variable name
11026 string name = generateUniqueVariableName(scope);
11027
11028 //Initialize the temporary variable to an evaluation of the expression
11029 SgExpression* tempVarInitExpression = SageInterface::copyExpression(expression);
11030 ROSE_ASSERT(tempVarInitExpression != NULL);
11031 if (isReferenceType)
11032 {
11033 //FIXME: the next line is hiding a bug in ROSE. Remove this line and talk to Dan about the resulting assert
11034 tempVarInitExpression->set_lvalue(false);
11035
11036 tempVarInitExpression = SageBuilder::buildAddressOfOp(tempVarInitExpression);
11037 }
11038
11039 //Optionally initialize the variable in its declaration
11040 SgAssignInitializer* initializer = NULL;
11041 if (initializeInDeclaration)
11042 {
11043 SgExpression* initExpressionCopy = SageInterface::copyExpression(tempVarInitExpression);
11044 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11045 }
11046
11047 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11048 ROSE_ASSERT(tempVarDeclaration != NULL);
11049
11050 //Now create the assignment op for reevaluating the expression
11051 if (reEvaluate != NULL)
11052 {
11053 SgVarRefExp* tempVarReference = SageBuilder::buildVarRefExp(tempVarDeclaration);
11054 *reEvaluate = SageBuilder::buildAssignOp(tempVarReference, tempVarInitExpression);
11055 }
11056
11057 //Build the variable reference expression that can be used in place of the original expression
11058 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11059 if (isReferenceType)
11060 {
11061 //The temp variable is a pointer type, so dereference it before using it
11062 varRefExpression = SageBuilder::buildPointerDerefExp(varRefExpression);
11063 }
11064
11065 return std::make_pair(tempVarDeclaration, varRefExpression);
11066}
11067
11068// This function creates a temporary variable for a given expression in the given scope
11069// This is different from SageInterface::createTempVariableForExpression in that it does not
11070// try to be smart to create pointers to reference types and so on. The tempt is initialized to expression.
11071// The caller is responsible for setting the parent of SgVariableDeclaration since buildVariableDeclaration
11072// may not set_parent() when the scope stack is empty. See programTransformation/extractFunctionArgumentsNormalization/ExtractFunctionArguments.C for sample usage.
11073
11074std::pair<SgVariableDeclaration*, SgExpression*> SageInterface::createTempVariableAndReferenceForExpression
11075(SgExpression* expression, SgScopeStatement* scope)
11076{
11077 SgType* expressionType = expression->get_type();
11078 SgType* variableType = expressionType;
11079
11080 //MS 10/24/2018: If the expression has array type, we need to use a pointer type for the temporary variable.
11081 if (SgArrayType* arrayType=isSgArrayType(expressionType))
11082 {
11083 if(SgArrayType* strippedArrayType = isSgArrayType(arrayType->stripType(SgType::STRIP_TYPEDEF_TYPE))) {
11084 SgType* strippedArrayBaseType = strippedArrayType->get_base_type();
11085 variableType = SageBuilder::buildPointerType(strippedArrayBaseType);
11086 }
11087 }
11088
11089 //Generate a unique variable name
11090 string name = generateUniqueVariableName(scope);
11091
11092 //initialize the variable in its declaration
11093 SgAssignInitializer* initializer = NULL;
11094 SgExpression* initExpressionCopy = SageInterface::copyExpression(expression);
11095 initializer = SageBuilder::buildAssignInitializer(initExpressionCopy);
11096
11097 SgVariableDeclaration* tempVarDeclaration = SageBuilder::buildVariableDeclaration(name, variableType, initializer, scope);
11098 ROSE_ASSERT(tempVarDeclaration != NULL);
11099
11100 //Build the variable reference expression that can be used in place of the original expression
11101 SgExpression* varRefExpression = SageBuilder::buildVarRefExp(tempVarDeclaration);
11102 return std::make_pair(tempVarDeclaration, varRefExpression);
11103}
11104
11105
11106namespace
11107{
11108 void
11109 replaceExpressionInSgExpressionPtrList(SgExpression* oldExp, SgExpression* newExp, SgExpressionPtrList& lst, bool replAll = false)
11110 {
11111 SgExpressionPtrList::iterator lim = lst.end();
11112 SgExpressionPtrList::iterator pos = lst.begin();
11113 bool chg = false;
11114
11115 do
11116 {
11117 pos = std::find(pos, lim, oldExp);
11118
11119 if (pos != lim) { *pos = newExp; ++pos; chg = true; }
11120 } while (replAll && (pos != lim));
11121
11122 ROSE_ASSERT(chg);
11123 }
11124}
11125
11126// This code is based on OpenMP translator's ASTtools::replaceVarRefExp() and astInling's replaceExpressionWithExpression()
11127// Motivation: It involves the parent node to replace a VarRefExp with a new node
11128// Used to replace shared variables with the dereference expression of their addresses
11129// e.g. to replace shared1 with (*__pp_shared1)
11130
11131void SageInterface::replaceExpression(SgExpression* oldExp, SgExpression* newExp, bool keepOldExp/*=false*/) {
11132 SgExpression* parentExp;
11133
11134 ROSE_ASSERT(oldExp);
11135 ROSE_ASSERT(newExp);
11136 if (oldExp==newExp) return;
11137
11138 if (isSgVarRefExp(newExp))
11139 newExp->set_need_paren(true); // enclosing new expression with () to be safe
11140
11141 SgNode* parent = oldExp->get_parent();
11142 ROSE_ASSERT(parent!=NULL);
11143 newExp->set_parent(parent);
11144
11145 // set lvalue when necessary
11146 if (oldExp->get_lvalue() == true) newExp->set_lvalue(true);
11147
11148 if (isSgExprStatement(parent)) {
11149 isSgExprStatement(parent)->set_expression(newExp);
11150 } else if (isSgForStatement(parent)) {
11151 ROSE_ASSERT (isSgForStatement(parent)->get_increment() == oldExp);
11152 isSgForStatement(parent)->set_increment(newExp);
11153 // TODO: any other cases here??
11154 } else if(SgMatlabForStatement *matlabFor = isSgMatlabForStatement(parent)) {
11155 if(matlabFor->get_index() == oldExp)
11156 matlabFor->set_index(newExp);
11157 else if(matlabFor->get_range() == oldExp)
11158 matlabFor->set_range(newExp);
11159 else
11160 ROSE_ASSERT(!"sub-expression not found");
11161 } else if(SgJovialForThenStatement *jovFor = isSgJovialForThenStatement(parent)) {
11162 if(jovFor->get_initialization() == oldExp)
11163 jovFor->set_initialization(newExp);
11164 else if(jovFor->get_while_expression() == oldExp)
11165 jovFor->set_while_expression(newExp);
11166 else if(jovFor->get_by_or_then_expression() == oldExp)
11167 jovFor->set_by_or_then_expression(newExp);
11168 else
11169 ROSE_ASSERT(!"sub-expression not found");
11170 } else if (SgRangeExp* rngexp = isSgRangeExp(parent)) {
11171 if (rngexp->get_start() == oldExp)
11172 rngexp->set_start(newExp);
11173 else if (rngexp->get_end() == oldExp)
11174 rngexp->set_end(newExp);
11175 else if (rngexp->get_stride() == oldExp)
11176 rngexp->set_stride(newExp);
11177 else
11178 ROSE_ASSERT(!"sub-expression not found");
11179 } else if (isSgReturnStmt(parent)) {
11180 isSgReturnStmt(parent)->set_expression(newExp);
11181 } else if (isSgBinaryOp(parent)!=NULL) {
11182 if (oldExp==isSgBinaryOp(parent)->get_lhs_operand()) {
11183 isSgBinaryOp(parent)->set_lhs_operand(newExp);
11184 } else if (oldExp==isSgBinaryOp(parent)->get_rhs_operand()) {
11185 isSgBinaryOp(parent)->set_rhs_operand(newExp);
11186 } else {
11187 ROSE_ABORT();
11188 }
11189 } else if (isSgUnaryOp(parent)!=NULL){
11190 if (oldExp==isSgUnaryOp(parent)->get_operand_i())
11191 isSgUnaryOp(parent)->set_operand_i(newExp);
11192 else
11193 ROSE_ABORT();
11194 } else if (isSgConditionalExp(parent) != NULL) {
11195 SgConditionalExp* expparent = isSgConditionalExp(parent); //get explicity type parent
11196 if (oldExp==expparent->get_conditional_exp())
11197 expparent->set_conditional_exp(newExp);
11198 else if (oldExp==expparent->get_true_exp())
11199 expparent->set_true_exp(newExp);
11200 else if (oldExp==expparent->get_false_exp())
11201 expparent->set_false_exp(newExp);
11202 else
11203 ROSE_ABORT();
11204 } else if (isSgExprListExp(parent) != NULL) {
11205 SgExpressionPtrList& explist = isSgExprListExp(parent)->get_expressions();
11206 for (Rose_STL_Container<SgExpression*>::iterator i=explist.begin();i!=explist.end();i++) {
11207 if (isSgExpression(*i)==oldExp) {
11208 SgExprListExp* parentExpListExp = isSgExprListExp(parent);
11209 parentExpListExp->replace_expression(oldExp,newExp);
11210 // break; //replace the first occurrence only??
11211 }
11212 }
11213 } else if (isSgValueExp(parent)) {
11214 // For compiler generated code, this could happen.
11215 // We can just ignore this function call since it will not appear in the final AST.
11216 return;
11217 } else if (SgActualArgumentExpression* actexp = isSgActualArgumentExpression(parent)) {
11218 ROSE_ASSERT(oldExp == actexp->get_expression());
11219 actexp->set_expression(newExp);
11220 } else if (SgAdaAttributeExp* attrexp = isSgAdaAttributeExp(parent)) {
11221 if (oldExp == attrexp->get_object()) {
11222 attrexp->set_object(newExp);
11223 } else if (oldExp == attrexp->get_args()) {
11224 SgExprListExp* newLst = isSgExprListExp(newExp);
11225 ASSERT_not_null(newLst);
11226
11227 attrexp->set_args(newLst);
11228 } else {
11229 ROSE_ABORT();
11230 }
11231 /**** ALL expressions must be handled before the next line *****/
11232 } else if ((parentExp=isSgExpression(parent)) != NULL) {
11233 int worked = parentExp->replace_expression(oldExp, newExp);
11234 // ROSE_DEPRECATED_FUNCTION
11235 ROSE_ASSERT (worked);
11236 } else if (isSgInitializedName(parent)) {
11237 SgInitializedName* initializedNameParent = isSgInitializedName(parent);
11238 if (oldExp == initializedNameParent->get_initializer()) {
11239 //We can only replace an initializer expression with another initializer expression
11240 ROSE_ASSERT(isSgInitializer(newExp));
11241 initializedNameParent->set_initializer(isSgInitializer(newExp));
11242 } else {
11243 //What other expressions can be children of an SgInitializedname?
11244 ROSE_ABORT();
11245 }
11246 } else if (isSgCaseOptionStmt(parent)) {
11247 SgCaseOptionStmt * case_stmt = isSgCaseOptionStmt(parent);
11248 if (oldExp == case_stmt->get_key()) {
11249 case_stmt->set_key(newExp);
11250 } else if(oldExp == case_stmt->get_key_range_end()) {
11251 case_stmt->set_key_range_end(newExp);
11252 } else {
11253 ROSE_ABORT();
11254 }
11255 } else if (isSgProcessControlStatement(parent)) {
11257 if (oldExp == ctrl_stmt->get_quiet()) {
11258 ctrl_stmt->set_quiet(newExp);
11259 } else if (oldExp == ctrl_stmt->get_code()) {
11260 ctrl_stmt->set_code(newExp);
11261 } else {
11262 ROSE_ABORT();
11263 }
11264 } else if (isSgFortranDo(parent)) {
11265 SgFortranDo* fortranDo = isSgFortranDo(parent);
11266 if (oldExp == fortranDo->get_initialization()) {
11267 fortranDo->set_initialization(newExp);
11268 } else if(oldExp == fortranDo->get_bound()) {
11269 fortranDo->set_bound(newExp);
11270 } else if (oldExp == fortranDo->get_increment()) {
11271 fortranDo->set_increment(newExp);
11272 } else {
11273 ROSE_ABORT();
11274 }
11275 }
11276 else if (SgAdaExitStmt* stm = isSgAdaExitStmt(parent)) {
11277 ROSE_ASSERT(oldExp == stm->get_condition());
11278 stm->set_condition(newExp);
11279 }
11280 else if (SgAdaModularType* ptype = isSgAdaModularType(parent)) {
11281 ROSE_ASSERT(oldExp == ptype->get_modexpr());
11282 ptype->set_modexpr(newExp);
11283 }
11284 else if (SgAdaDelayStmt* stm = isSgAdaDelayStmt(parent)) {
11285 ROSE_ASSERT(oldExp == stm->get_time());
11286 stm->set_time(newExp);
11287 } else if (SgAdaAttributeClause* clause = isSgAdaAttributeClause(parent)) {
11288 ROSE_ASSERT(oldExp == clause->get_size());
11289 clause->set_size(newExp);
11290 } else if (SgAdaRenamingDecl* dcl = isSgAdaRenamingDecl(parent)) {
11291 ROSE_ASSERT(oldExp == dcl->get_renamed());
11292 dcl->set_renamed(newExp);
11293 } else if (SgAdaEntryDecl* dcl = isSgAdaEntryDecl(parent)) {
11294 ROSE_ASSERT(oldExp == dcl->get_entryBarrier());
11295 dcl->set_entryBarrier(newExp);
11296 } else if (SgAdaSelectAlternativeStmt* stm = isSgAdaSelectAlternativeStmt(parent)) {
11297 ROSE_ASSERT(oldExp == stm->get_guard());
11298 stm->set_guard(newExp);
11299 } else if (SgAdaDeltaConstraint* delc = isSgAdaDeltaConstraint(parent)) {
11300 ROSE_ASSERT(oldExp == delc->get_delta());
11301 delc->set_delta(newExp);
11302 } else if (SgAdaDigitsConstraint* digc = isSgAdaDigitsConstraint(parent)) {
11303 ROSE_ASSERT(oldExp == digc->get_digits());
11304 digc->set_digits(newExp);
11305 } else if (SgAdaDiscriminantConstraint* disc = isSgAdaDiscriminantConstraint(parent)) {
11306 replaceExpressionInSgExpressionPtrList(oldExp, newExp, disc->get_discriminants());
11307 } else if (SgAdaRangeConstraint* rngc = isSgAdaRangeConstraint(parent)) {
11308 ROSE_ASSERT(oldExp == rngc->get_range());
11309 rngc->set_range(newExp);
11310 } else if (SgAdaIndexConstraint* idxc = isSgAdaIndexConstraint(parent)) {
11311 replaceExpressionInSgExpressionPtrList(oldExp, newExp, idxc->get_indexRanges());
11312 } else if (SgAdaVariantDecl* vtdcl = isSgAdaVariantDecl(parent)) {
11313 ROSE_ASSERT(oldExp == vtdcl->get_discriminant());
11314 vtdcl->set_discriminant(newExp);
11315 } else if (SgAdaRepresentationClause* clause = isSgAdaRepresentationClause(parent)) {
11316 ROSE_ASSERT(oldExp == clause->get_alignment());
11317 clause->set_alignment(newExp);
11318 } else if (SgAdaVariantWhenStmt* vtwhen = isSgAdaVariantWhenStmt(parent)) {
11319 SgExprListExp* newLst = isSgExprListExp(newExp);
11320 if (newLst && (oldExp == vtwhen->get_choices()))
11321 vtwhen->set_choices(newLst);
11322 else
11323 ROSE_ABORT();
11324 } else if (SgAdaComponentClause* clause = isSgAdaComponentClause(parent)) {
11325 if (oldExp == clause->get_offset())
11326 clause->set_offset(newExp);
11327 else if (oldExp == clause->get_range() && isSgRangeExp(newExp))
11328 clause->set_range(isSgRangeExp(newExp));
11329 else if (oldExp == clause->get_component() && isSgVarRefExp(newExp))
11330 clause->set_component(isSgVarRefExp(newExp));
11331 else
11332 ROSE_ABORT();
11333 } else if (SgAdaFunctionRenamingDecl* rendcl = isSgAdaFunctionRenamingDecl(oldExp->get_parent())) {
11334 if (oldExp == rendcl->get_renamed_function())
11335 rendcl->set_renamed_function(newExp);
11336 else
11337 ROSE_ABORT();
11338 } else {
11339 cerr<<"SageInterface::replaceExpression(). Unhandled parent expression type of SageIII enum value: " <<parent->class_name()<<endl;
11340 ROSE_ABORT();
11341 }
11342
11343 if (!keepOldExp) {
11344 deepDelete(oldExp); // avoid dangling node in memory pool
11345 } else {
11346 oldExp->set_parent(NULL);
11347 }
11348
11349} //replaceExpression()
11350
11352 {
11353 // reuse the implementation in ROSE namespace from src/roseSupport/utility_functions.C
11354 return Rose::getNextStatement(currentStmt);
11355 }
11356
11357SgStatement* SageInterface::getPreviousStatement(SgStatement * currentStmt, bool climbOutScope /*= true*/)
11358 {
11359 return Rose::getPreviousStatement(currentStmt, climbOutScope);
11360 }
11361
11363 return isSgIntVal(e) && isSgIntVal(e)->get_value() == value;
11364 }
11365
11367 {
11368 ROSE_ASSERT(func1&& func2);
11369 bool result = false;
11370 if (func1 == func2)
11371 result = true;
11372 else
11373 {
11375 {
11376 if (func1->get_name() == func2->get_name())
11377 result = true;
11378 }
11379 else if (is_Cxx_language() || is_Java_language())
11380 {
11381 if (func1->get_qualified_name().getString() +
11382 func1->get_mangled_name().getString() ==
11383 func2->get_qualified_name().getString() +
11384 func2->get_mangled_name().getString()
11385 )
11386 result = true;
11387 }
11388 // DQ (9/9/2025): Adding support for Jovial (similar to Fortran).
11389 // else if (is_Fortran_language())
11390 // else if (is_Jovial_language())
11392 {
11393 if (func1->get_name() == func2->get_name())
11394 result = true;
11395 }
11396 else
11397 {
11398 cout<<"Error: SageInterface::isSameFunction(): unhandled language"<<endl;
11399 ROSE_ABORT();
11400 }
11401
11402 } // not identical
11403 return result;
11404 } // isSameFunction()
11405
11408{
11409 bool result =false;
11410 ROSE_ASSERT(stmt != NULL);
11411 SgScopeStatement* p_scope = stmt->get_scope();
11412 ROSE_ASSERT(p_scope != NULL);
11413#if 0
11414 if (p_scope->containsOnlyDeclarations())
11415 {
11416 SgDeclarationStatementPtrList stmtlist= p_scope->getDeclarationList ()
11417 if (stmtlist[stmtlist.size()-1] == stmt)
11418 result = true;
11419 }
11420 else
11421 {
11422 SgStatementPtrList stmtlist= p_scope->getStatementList ();
11423 if (stmtlist[stmtlist.size()-1] == stmt)
11424 result = true;
11425 }
11426#endif
11427 SgStatementPtrList stmtlist= p_scope->generateStatementList ();
11428 if (stmtlist[stmtlist.size()-1] == stmt)
11429 result = true;
11430
11431 return result;
11432}
11433
11434#ifndef USE_ROSE
11435//-----------------------------------------------
11436// Remove original expression trees from expressions, so you can change
11437// the value and have it unparsed correctly.
11439 struct Visitor: public AstSimpleProcessing {
11440 virtual void visit(SgNode* n) {
11441 SgValueExp* valueExp = isSgValueExp(n);
11442 if (valueExp != NULL) {
11443 valueExp->set_originalExpressionTree(NULL);
11444 }
11445 else {
11446 SgCastExp* cast_exp = isSgCastExp(n);
11447 if (cast_exp != NULL) {
11448 cast_exp->set_originalExpressionTree(NULL);
11449 }
11450 }
11451 }
11452 };
11453 Visitor().traverse(top, preorder);
11454}
11455#endif
11456
11458 while (s && !isSgSwitchStatement(s)) {
11459 s = isSgStatement(s->get_parent());
11460 }
11461 ROSE_ASSERT (s);
11462 return isSgSwitchStatement(s);
11463}
11464
11467 while (s && !isSgOmpClauseBodyStatement(s)) {
11468 s = isSgStatement(s->get_parent());
11469 }
11470 // ROSE_ASSERT (s); // s is allowed to be NULL.
11471 if (s==NULL)
11472 return NULL;
11473 return isSgOmpClauseBodyStatement(s);
11474}
11475
11476
11477SgScopeStatement* SageInterface::findEnclosingLoop(SgStatement* s, const std::string& label, bool stopOnSwitches) {
11478 /* label can represent a fortran label or a java label provided as a label in a continue/break statement */
11479 for (; s; s = isSgStatement(s->get_parent())) {
11480 SgScopeStatement* sc = isSgScopeStatement(s);
11481 // Need to check for empty label as for java we must detect the
11482 // innermost labeled statement and skip everything in between
11483 switch (s->variantT()) {
11484 case V_SgDoWhileStmt: {
11485 if (label.empty()) {
11486 return sc;
11487 }
11488 break;
11489 }
11490 case V_SgForStatement: {
11491 if (label.empty()) {
11492 return sc;
11493 }
11494 break;
11495 }
11496 case V_SgFortranDo:
11497 case V_SgFortranNonblockedDo: {
11498 if (label.empty() ||
11499 label == isSgFortranDo(sc)->get_string_label()) {
11500 return sc;
11501 }
11502 break;
11503 }
11504 case V_SgWhileStmt: {
11505 if (label.empty() ||
11506 label == isSgWhileStmt(sc)->get_string_label()) {
11507 return sc;
11508 }
11509 break;
11510 }
11511 case V_SgSwitchStatement: {
11512 if (stopOnSwitches) return sc;
11513 break;
11514 }
11515 case V_SgJavaForEachStatement: {
11516 if (label.empty()) {
11517 return sc;
11518 }
11519 break;
11520 }
11521 case V_SgJavaLabelStatement: {
11522 if (label.empty() ||
11523 label == isSgJavaLabelStatement(sc)->get_label().getString()) {
11524 return sc;
11525 }
11526 break;
11527 }
11528 default: continue;
11529 }
11530 }
11531 return NULL;
11532}
11533
11534#ifndef USE_ROSE
11536{
11537 class RemoveJumpsToNextStatementVisitor: public AstSimpleProcessing {
11538 public:
11539 virtual void visit(SgNode* n) {
11540 if (isSgBasicBlock(n)) {
11541 SgBasicBlock* bb = isSgBasicBlock(n);
11542 bool changes = true;
11543 while (changes) {
11544 changes = false;
11545 for (SgStatementPtrList::iterator i = bb->get_statements().begin();
11546 i != bb->get_statements().end(); ++i) {
11547 if (isSgGotoStatement(*i)) {
11548 SgGotoStatement* gs = isSgGotoStatement(*i);
11549 SgStatementPtrList::iterator inext = i;
11550 ++inext;
11551 if (inext == bb->get_statements().end())
11552 continue;
11553 if (!isSgLabelStatement(*inext))
11554 continue;
11555 SgLabelStatement* ls = isSgLabelStatement(*inext);
11556 if (gs->get_label() == ls) {
11557 changes = true;
11558 bb->get_statements().erase(i);
11559 break;
11560 }
11561 }
11562 }
11563 }
11564 }
11565 }
11566 };
11567
11568 RemoveJumpsToNextStatementVisitor().traverse(top, postorder);
11569
11570}
11571#endif
11572
11573// special purpose remove for AST transformation/optimization from astInliner, don't use it otherwise.
11575 // assert (LowLevelRewrite::isRemovableStatement(*i));
11576 SgStatement* parent = isSgStatement(stmt->get_parent());
11577 ROSE_ASSERT (parent);
11578 SgBasicBlock* bb = isSgBasicBlock(parent);
11579 SgForInitStatement* fis = isSgForInitStatement(parent);
11580 if (bb || fis) {
11581 ROSE_ASSERT (bb || fis);
11582 SgStatementPtrList& siblings =
11583 (bb ? bb->get_statements() : fis->get_init_stmt());
11584 SgStatementPtrList::iterator j =
11585 std::find(siblings.begin(), siblings.end(), stmt);
11586 ROSE_ASSERT (j != siblings.end());
11587 siblings.erase(j);
11588 // LowLevelRewrite::remove(*i);
11589 } else {
11590 parent->replace_statement(stmt, new SgNullStatement(TRANS_FILE));
11591 }
11592}
11593
11594
11595#ifndef USE_ROSE
11596std::set<SgLabelStatement*> SageInterface::findUnusedLabels (SgNode* top)
11597{
11598 class FindUsedAndAllLabelsVisitor: public AstSimpleProcessing {
11599 SgLabelStatementPtrSet& used;
11600 SgLabelStatementPtrSet& all;
11601
11602 public:
11603 FindUsedAndAllLabelsVisitor(SgLabelStatementPtrSet& used,
11604 SgLabelStatementPtrSet& all):
11605 used(used), all(all) {}
11606
11607 virtual void visit(SgNode* n) {
11608 if (isSgGotoStatement(n)) {
11609 used.insert(isSgGotoStatement(n)->get_label());
11610 }
11611 if (isSgLabelStatement(n)) {
11612 all.insert(isSgLabelStatement(n));
11613 }
11614 }
11615 };
11616
11617 SgLabelStatementPtrSet used;
11618 SgLabelStatementPtrSet unused;
11619 FindUsedAndAllLabelsVisitor(used, unused).traverse(top, preorder);
11620
11621 for (SgLabelStatementPtrSet::iterator i = used.begin();
11622 i != used.end(); ++i) {
11623 assert (unused.find(*i) != unused.end());
11624 // std::cout << "Keeping used label " << (*i)->get_label().str() << std::endl;
11625 unused.erase(*i);
11626 }
11627
11628 return unused;
11629}
11630
11631// Remove all unused labels in a section of code.
11632void SageInterface::removeUnusedLabels(SgNode* top, bool keepChild/* =false */) {
11633
11634 SgLabelStatementPtrSet unused = findUnusedLabels(top);
11635
11636 for (SgLabelStatementPtrSet::iterator i = unused.begin();
11637 i != unused.end(); ++i) {
11638
11639 SgLabelStatement* l_stmt = *i;
11640 // std::cout << "Removing unused label " << (*i)->get_label().str() << std::endl;
11641 if (keepChild)
11642 {
11643 SgStatement* child= l_stmt->get_statement();
11644// l_stmt->set_parent(NULL);
11645 l_stmt->set_statement(NULL);
11646 replaceStatement (l_stmt, child);
11647 }
11648 else
11650 }
11651}
11652#endif
11653
11655 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_body();
11656 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_loop_body();
11657 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_body();
11658
11659 ROSE_ASSERT (!"Bad loop kind");
11660 return NULL;
11661 }
11662
11664 if (isSgWhileStmt(loopStmt)) {
11665 isSgWhileStmt(loopStmt)->set_body(body);
11666 } else if (isSgForStatement(loopStmt)) {
11667 isSgForStatement(loopStmt)->set_loop_body(body);
11668 } else if (isSgDoWhileStmt(loopStmt)) {
11669 isSgDoWhileStmt(loopStmt)->set_body(body);
11670 } else {
11671 ROSE_ASSERT (!"Bad loop kind");
11672 }
11673 body->set_parent(loopStmt);
11674 }
11675
11677 if (isSgWhileStmt(loopStmt)) return isSgWhileStmt(loopStmt)->get_condition();
11678 if (isSgForStatement(loopStmt)) return isSgForStatement(loopStmt)->get_test();
11679 if (isSgDoWhileStmt(loopStmt)) return isSgDoWhileStmt(loopStmt)->get_condition();
11680
11681 ROSE_ASSERT (!"Bad loop kind");
11682 return NULL;
11683 }
11684
11686 if (isSgWhileStmt(loopStmt)) {
11687 isSgWhileStmt(loopStmt)->set_condition(cond);
11688 } else if (isSgForStatement(loopStmt)) {
11689 isSgForStatement(loopStmt)->set_test(cond);
11690 } else if (isSgDoWhileStmt(loopStmt)) {
11691 isSgDoWhileStmt(loopStmt)->set_condition(cond);
11692 } else {
11693 ROSE_ASSERT (!"Bad loop kind");
11694 }
11695 cond->set_parent(loopStmt);
11696 }
11697
11699// usually useful when compare two expressions to see if they actually refer to the same variable
11700static SgExpression* SkipCasting (SgExpression* exp)
11701{
11702 SgCastExp* cast_exp = isSgCastExp(exp);
11703 if (cast_exp != NULL)
11704 {
11705 SgExpression* operand = cast_exp->get_operand();
11706 assert(operand != 0);
11707 return SkipCasting(operand);
11708 }
11709 else
11710 return exp;
11711}
11712
11715{
11716 ROSE_ASSERT(loop!=NULL);
11717
11718 SgStatementPtrList &init = loop ->get_init_stmt();
11719 if (init.size() !=1) // We only handle one statement case
11720 return false;
11721
11722 SgStatement* init1 = init.front();
11723 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
11724 if (decl == NULL) // we only handle for (int i=0; ...)
11725 return true; // the return value is ambiguous: if not int i=0; it is already normalized
11726
11727 SgVariableSymbol* osymbol = getFirstVarSym(decl);
11728 SgInitializedName* ivarname = decl->get_variables().front();
11729 SgExpression* lbast = NULL; // the lower bound, initial state
11730 ROSE_ASSERT(ivarname != NULL);
11731 SgInitializer * initor = ivarname->get_initializer();
11732 if (isSgAssignInitializer(initor))
11733 {
11734 lbast = isSgAssignInitializer(initor)->get_operand();
11735 }
11736 else
11737 { //SgConstructorInitializer etc.
11738 // other complex declaration statements, such as Decomposition::Iterator ditr(&decomp) should be skipped
11739 // they cause a loop to be non-canonical.
11740 return false;
11741 }
11742
11743 // add a new statement like int i; and insert it to the enclosing function
11744 // There are multiple choices about where to insert this statement:
11745 // global scope: max name pollution,
11746 // right before the loop: mess up perfectly nested loops
11747 // So we prepend the statement to the enclosing function's body
11749 ROSE_ASSERT(funcDef!=NULL);
11750 SgBasicBlock* funcBody = funcDef->get_body();
11751 ROSE_ASSERT(funcBody!=NULL);
11752 //TODO a better name
11753 std::ostringstream os;
11754 os<<ivarname->get_name().getString();
11755
11756 // keep the original variable name if possible
11757 SgSymbol * visibleSym = NULL;
11758 visibleSym = lookupVariableSymbolInParentScopes(ivarname->get_name(), funcBody);
11759 if (visibleSym != NULL) // if there is a name collision, add suffix to the variable name
11760 {
11761 os<<"_nom_";
11762 os<<++gensym_counter;
11763 }
11764
11765 SgVariableDeclaration* ndecl = buildVariableDeclaration(os.str(),ivarname->get_type(), NULL, funcBody);
11766 prependStatement(ndecl, funcBody);
11767 SgVariableSymbol* nsymbol = getFirstVarSym(ndecl);
11768
11769 // replace variable ref to the new symbol
11770 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11771 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11772 {
11773 SgVarRefExp *vRef = isSgVarRefExp((*i));
11774 if (vRef->get_symbol()==osymbol)
11775 vRef->set_symbol(nsymbol);
11776 }
11777 // replace for (int i=0;) with for (i=0;)
11779 removeStatement(decl); //any side effect to the symbol? put after symbol replacement anyway
11780 init.push_back(ninit);
11781 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11782 // ninit->set_parent(loop);
11783 ninit->set_parent(loop->get_for_init_stmt ());
11784
11785 // keep record of this normalization
11786 // We may undo it later on.
11787 trans_records.forLoopInitNormalizationTable[loop] = true;
11788 trans_records.forLoopInitNormalizationRecord[loop] = make_pair (decl, ndecl) ;
11789
11790 return true;
11791}
11792
11793/*
11794 int i_norm_1;
11795 for (i_norm_1=0; i_norm_1<upper; i_norm_1 ++ );
11796Becomes:
11797 for (int i=0; i< upper; i++) ;
11798 * */
11800{
11801 ROSE_ASSERT (loop != NULL);
11802 //If not previously normalized, nothing to do and return false.
11803 if (!trans_records.forLoopInitNormalizationTable[loop])
11804 return false;
11805 // retrieve original and new declaration of the previous normalization
11806 SgVariableDeclaration* decl = trans_records.forLoopInitNormalizationRecord[loop].first;
11807 SgVariableDeclaration* ndecl = trans_records.forLoopInitNormalizationRecord[loop].second;
11808 ROSE_ASSERT (decl!= NULL);
11809 ROSE_ASSERT (ndecl!= NULL);
11810
11811
11812 // Sanity check
11813 SgStatementPtrList &init = loop ->get_init_stmt();
11814 ROSE_ASSERT(init.size() ==1); // We only handle one statement case
11815
11816 // remove the current init_stmt
11817 SgStatement* init1 = init.front();
11818 SgExprStatement* exp_stmt = isSgExprStatement(init1);
11819 ROSE_ASSERT (exp_stmt != NULL);
11820 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
11821 ROSE_ASSERT (assign_op != NULL);
11822
11823 // remove the new declaration and the current i_norm=1;
11824 removeStatement(ndecl);
11825 removeStatement (exp_stmt);
11826
11827 // restore the original declaration
11828 init.push_back(decl);
11829 ROSE_ASSERT (loop->get_for_init_stmt () != NULL);
11830 // ninit->set_parent(loop);
11831 decl->set_parent(loop->get_for_init_stmt ());
11832
11833 // replace variable references
11834 // current symbol in the AST
11835 SgVariableSymbol* osymbol = getFirstVarSym(ndecl);
11836 // new symbol we want to have: the original decl
11837 SgVariableSymbol* nsymbol = getFirstVarSym(decl);
11838 // replace variable ref to the new symbol
11839 Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(loop,V_SgVarRefExp);
11840 for (Rose_STL_Container<SgNode *>::iterator i = varRefs.begin(); i != varRefs.end(); i++)
11841 {
11842 SgVarRefExp *vRef = isSgVarRefExp((*i));
11843 if (vRef->get_symbol()==osymbol)
11844 vRef->set_symbol(nsymbol);
11845 }
11846
11847 // clear record: now the loop is not normalized any more
11848 trans_records.forLoopInitNormalizationTable[loop] = false;
11849 return true;
11850}
11851
11853{
11854 ROSE_ASSERT(loop != NULL);
11855
11856 // Normalized the test expressions
11857 // -------------------------------------
11858#if 0 // this is undecided
11859 // skip for (;;) case
11860 SgStatement* test_stmt = loop->get_test();
11861 if (test_stmt!=NULL)
11862 {
11863 if (isSgNullStatement(test_stmt))
11864 return false;
11865 }
11866#endif
11867 SgExpression* test = loop->get_test_expr();
11868 SgExpression* testlhs=NULL, * testrhs=NULL;
11869 if (isSgBinaryOp(test))
11870 {
11871 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11872 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11873 ROSE_ASSERT(testlhs && testrhs);
11874 }
11875 else
11876 return false;
11877 // keep the variable since test will be removed later on
11878 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11879 if (testlhs_var == NULL )
11880 return false;
11881 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11882 if (var_symbol==NULL)
11883 return false;
11884
11885 switch (test->variantT()) {
11886 case V_SgLessThanOp: // i<x is normalized to i<= (x-1)
11888 buildSubtractOp(deepCopy(testrhs), buildIntVal(1))));
11889 // deepDelete(test);// replaceExpression() does this already by default.
11890 break;
11891 case V_SgGreaterThanOp: // i>x is normalized to i>= (x+1)
11893 buildAddOp(deepCopy(testrhs), buildIntVal(1))));
11894 break;
11895 case V_SgLessOrEqualOp:
11896 case V_SgGreaterOrEqualOp:
11897 case V_SgNotEqualOp: //TODO Do we want to allow this?
11898 break;
11899 default:
11900 return false;
11901 }
11902 return true;
11903}
11905{
11906 ROSE_ASSERT(loop != NULL);
11907
11908 SgExpression* test = loop->get_test_expr();
11909 SgExpression* testlhs=NULL, * testrhs=NULL;
11910 if (isSgBinaryOp(test))
11911 {
11912 testlhs = isSgBinaryOp(test)->get_lhs_operand();
11913 testrhs = isSgBinaryOp(test)->get_rhs_operand();
11914 ROSE_ASSERT(testlhs && testrhs);
11915 }
11916 else
11917 return false;
11918 // keep the variable since test will be removed later on
11919 SgVarRefExp* testlhs_var = isSgVarRefExp(SkipCasting(testlhs));
11920 if (testlhs_var == NULL )
11921 return false;
11922 SgVariableSymbol * var_symbol = testlhs_var->get_symbol();
11923 if (var_symbol==NULL)
11924 return false;
11925
11926
11927 // -------------------------------------
11928 SgExpression* incr = loop->get_increment();
11929 ROSE_ASSERT(incr != NULL);
11930 switch (incr->variantT()) {
11931 case V_SgPlusPlusOp: //i++ is normalized to i+=1
11932 {
11933 // check if the variables match
11934 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgPlusPlusOp(incr)->get_operand()));
11935 if (incr_var == NULL) return false;
11936 if ( incr_var->get_symbol() != var_symbol)
11937 return false;
11938 replaceExpression(incr,
11939 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)),buildIntVal(1)));
11940 break;
11941 }
11942 case V_SgMinusMinusOp: //i-- is normalized to i+=-1
11943 {
11944 // check if the variables match
11945 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusMinusOp(incr)->get_operand()));
11946 if (incr_var == NULL) return false;
11947 if ( incr_var->get_symbol() != var_symbol)
11948 return false;
11949 replaceExpression(incr,
11950 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildIntVal(-1)));
11951 break;
11952 }
11953 case V_SgMinusAssignOp: // i-= s is normalized to i+= -s
11954 {
11955 SgVarRefExp* incr_var = isSgVarRefExp(SkipCasting(isSgMinusAssignOp(incr)->get_lhs_operand()));
11956 SgExpression* rhs = isSgMinusAssignOp(incr)->get_rhs_operand();
11957 ROSE_ASSERT (rhs != NULL);
11958 if (incr_var == NULL) return false;
11959 if ( incr_var->get_symbol() != var_symbol)
11960 return false;
11961 replaceExpression(incr,
11962 buildPlusAssignOp(isSgExpression(deepCopy(incr_var)), buildMultiplyOp(buildIntVal(-1), copyExpression(rhs))));
11963 break;
11964 }
11965 case V_SgAssignOp:
11966 case V_SgPlusAssignOp:
11967 break;
11968 default:
11969 return false;
11970 }
11971
11972 return true;
11973}
11974
11975/*
11976The AST of switch-case statement
11977
11978AST using EDG 6.x
11979
11980|___ *[0] ->@0x7f8d973f0010 SgSwitchStatement switch-case.C 4:3
11981 |--- p_item_selector ->@0x7f8d9738e010 SgExprStatement switch-case.C 4:10
11982 | |___ p_expression ->@0x7f8d973bd010 SgVarRefExp switch-case.C 4:10 init name@0x7f8d97757130 symbol name="a"
11983 |___ p_body ->@0x7f8d97522168 SgBasicBlock switch-case.C 5:3
11984 |--- *[0] ->@0x7f8d97343010 SgCaseOptionStmt switch-case.C 6:10
11985 | |___ p_key ->@0x7f8d98d4c090 SgIntVal switch-case.C 6:10 value=1 valueString=
11986 |--- *[1] ->@0x7f8d975222c0 SgBasicBlock switch-case.C 7:7
11987 | |--- *[0] ->@0x7f8d9738e070 SgExprStatement switch-case.C 7:8
11988 | | |___ p_expression ->@0x7f8da76c2010 SgNullExpression compilerGenerated 0:0
11989 | |___ *[1] ->@0x7f8d97308010 SgBreakStmt switch-case.C 8:9
11990 |--- *[2] ->@0x7f8d972c5010 SgDefaultOptionStmt switch-case.C 10:4
11991 |___ *[3] ->@0x7f8d97522418 SgBasicBlock switch-case.C 11:7
11992 |___ *[0] ->@0x7f8d9738e0d0 SgExprStatement switch-case.C 11:8
11993 |___ p_expression ->@0x7f8da76c2060 SgNullExpression compilerGenerated 0:0
11994
11995AST using EDG 5.x
11996└──@0x7fd34c734010 SgSwitchStatement switch-case.cpp 4:3
11997 ├──@0x7fd34c6d2010 SgExprStatement switch-case.cpp 4:10
11998 │ └──@0x7fd34c701010 SgVarRefExp switch-case.cpp 4:10
11999 └──@0x7fd34c866168 SgBasicBlock switch-case.cpp 5:3
12000 ├──@0x7fd34c5b2010 SgCaseOptionStmt switch-case.cpp 6:10
12001 │ ├──@0x7fd34c5fd010 SgCastExp compilerGenerated 0:0
12002 │ │ └──@0x7fd34c63c010 SgBoolValExp switch-case.cpp 6:10
12003 │ ├──@0x7fd34c8662c0 SgBasicBlock switch-case.cpp 7:7
12004 │ │ └──@0x7fd34c6d2070 SgExprStatement switch-case.cpp 7:8
12005 │ │ └──@0x7fd34c6aa010 SgNullExpression compilerGenerated 0:0
12006 │ └── NULL
12007 ├──@0x7fd34c5b20a8 SgCaseOptionStmt switch-case.cpp 9:10
12008 │ ├──@0x7fd34c5fd090 SgCastExp compilerGenerated 0:0
12009 │ │ └──@0x7fd34c63c070 SgBoolValExp switch-case.cpp 9:10
12010 │ ├──@0x7fd34c866418 SgBasicBlock switch-case.cpp 10:7
12011 │ │ └──@0x7fd34c6d20d0 SgExprStatement switch-case.cpp 10:8
12012 │ │ └──@0x7fd34c6aa060 SgNullExpression compilerGenerated 0:0
12013 │ └── NULL
12014 └──@0x7fd34c56f010 SgDefaultOptionStmt switch-case.cpp 12:5
12015 └──@0x7fd34c866570 SgBasicBlock switch-case.cpp 13:7
12016 └──@0x7fd34c6d2130 SgExprStatement switch-case.cpp 13:8
12017 └──@0x7fd34c6aa0b0 SgNullExpression compilerGenerated 0:0
12018
12019*/
12021 bool changed = false;
12022 // Only act on switch statements
12023 if (!switchStmt) return changed;
12024
12025 // The body of the switch should be a basic block
12026 SgBasicBlock* bodyBlock = isSgBasicBlock(switchStmt->get_body());
12027 if (!bodyBlock) return changed;
12028
12029 // Copy the list of statements to allow modification
12030 SgStatementPtrList& stmtList = bodyBlock->get_statements();
12031 std::vector<SgStatement*> stmts(stmtList.begin(), stmtList.end());
12032 int n = static_cast<int>(stmts.size());
12033
12034 // Walk through statements, detecting case/default labels
12035 // Note that this for loop does not have i++!
12036 for (int i = 0; i < n; ) {
12037 SgStatement* curr = stmts[i];
12038 // We expect curr is either SgCaseOptionStmt or SgDefaultOptionStmt at this point
12039 //
12040 // Helper lambda to handle a label statement of either SgCaseOptionStmt or SgDefaultOptionStmt
12041 auto processLabel = [&](SgStatement* labelStmt) {
12042
12043 // set j to next statement after the label statmt
12044 int j = i + 1;
12045 std::vector<SgStatement*> toWrap;
12046 // Collect statements until next case/default or end
12047 while (j < n && !isSgCaseOptionStmt(stmts[j]) && !isSgDefaultOptionStmt(stmts[j])) {
12048 toWrap.push_back(stmts[j]);
12049 ++j;
12050 }
12051
12052 // now the current statement is isSgCaseOptionStmt or isSgDefaultOptionStmt
12053 // Single-block case: if we collected exactly one basic-block and label has no body, just move it
12054 // I think the AST is constructed improperly
12055 if (toWrap.size() == 1
12056 && isSgBasicBlock(toWrap[0])
12057 && ((isSgCaseOptionStmt(labelStmt) && !isSgBasicBlock(isSgCaseOptionStmt(labelStmt)->get_body()))
12058 || (isSgDefaultOptionStmt(labelStmt) && !isSgBasicBlock(isSgDefaultOptionStmt(labelStmt)->get_body()))))
12059 {
12060#if 0
12061 //it seems like the body pointer is no longer used within the connection with EDG 6.x!!
12062 SgBasicBlock* moved = static_cast<SgBasicBlock*>(toWrap[0]);
12063 removeStatement (moved);
12064 if (auto c = isSgCaseOptionStmt(labelStmt)) {
12065 c->set_body(moved);
12066 } else if (auto d = isSgDefaultOptionStmt(labelStmt)) {
12067 d->set_body(moved);
12068 }
12069 moved->set_parent(labelStmt);
12070#endif
12071 // no further wrapping or removal needed
12072 }
12073 else if (!toWrap.empty()) {
12074 // Build a new block around statements
12075 // NOTE: wrong code: buildBasicBlock_nfi() version was calleda
12076 // It does support vector of stmts.
12077 // But we want to avoid the use of _nfi() version no file info (nfi)
12078 // to avoid set file info. manually.
12079 SgBasicBlock* newBlock = buildBasicBlock();
12080 insertStatementAfter(labelStmt, newBlock);
12081 // Insert block after label
12082#if 0
12083 //it seems like the body pointer is no longer used within the connection with EDG 6.x!!
12084 // NOTE: becomes its body
12085 newBlock->set_parent(labelStmt);
12086
12087 // Attach block as body of the label
12088 if (auto caseLabel = isSgCaseOptionStmt(labelStmt)) {
12089 caseLabel->set_body(newBlock);
12090 } else if (auto defaultLabel = isSgDefaultOptionStmt(labelStmt)) {
12091 defaultLabel->set_body(newBlock);
12092 }
12093#endif
12094 // Remove original flat statements
12095 for (auto* w: toWrap) {
12096 {
12097 // we must first remove it from original location, then append it to new location
12098 removeStatement(w);
12099 appendStatement(w, newBlock);
12100 }
12101 }
12102 changed = true;
12103 }
12104 return j; // next index to process
12105 };
12106
12107 // adjust i
12108 if (auto caseLabel = isSgCaseOptionStmt(curr)) {
12109 i = processLabel(caseLabel);
12110 } else if (auto defaultLabel = isSgDefaultOptionStmt(curr)) {
12111 i = processLabel(defaultLabel);
12112 } else {
12113 ++i;
12114 }
12115 }
12116
12117 return changed;
12118}
12119
12121// Her loop translation does not pass AST consistency tests so we rewrite some of them here
12122// NormalizeCPP.C NormalizeLoopTraverse::ProcessLoop()
12123bool SageInterface::forLoopNormalization(SgForStatement* loop, bool foldConstant /*= true*/)
12124{
12125 ROSE_ASSERT(loop != NULL);
12126 // Normalize initialization statement of the for loop
12127 // -------------------------------------
12128 // for (int i=0;... ) becomes int i; for (i=0;..)
12129 // Only roughly check here, isCanonicalForLoop() should be called to have a stricter check
12131 return false;
12132
12133 // Normalized the test expressions
12134 if (!normalizeForLoopTest(loop))
12135 return false;
12136
12137 // Normalize the increment expression
12138 if (!normalizeForLoopIncrement(loop))
12139 return false;
12140
12141 // Normalize the loop body: ensure there is a basic block
12143 ROSE_ASSERT(body!=NULL);
12144 // Liao, 9/22/2009
12145 // folding entire loop may cause decreased accuracy for floating point operations
12146 // we only want to fold the loop controlling expressions
12147 if (foldConstant)
12148 {
12149 //constantFolding(loop->get_parent());
12150 constantFolding(loop->get_test());
12151 constantFolding(loop->get_increment());
12152 }
12153
12154 return true;
12155}
12156
12159{
12160 // TODO, normalize continue to enddo ?
12161 ROSE_ASSERT (loop != NULL);
12162 SgExpression* e_3 = loop->get_increment();
12163 if (isSgNullExpression(e_3))
12164 {
12165 SgIntVal* iv = buildIntVal(1);
12166 loop->set_increment(iv);
12167 iv->set_parent(loop);
12168 delete (e_3);
12169 }
12170 return true;
12171}
12172
12173#if 0
12174bool SageInterface::loopUnrolling(SgForStatement* loop, size_t unrolling_factor)
12175{
12176 // normalize the loop first
12177 if (!forLoopNormalization(loop))
12178 return false; // input loop cannot be normalized to a canonical form
12179 // prepare Loop transformation environment
12181 ROSE_ASSERT(func!=NULL);
12182 AstInterfaceImpl faImpl(func->get_definition()->get_body());
12183 AstInterface fa(&faImpl);
12184 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
12185 ArrayInterface array_interface (*annot);
12186 array_interface.initialize(fa, AstNodePtrImpl(func->get_definition()));
12187 array_interface.observe(fa);
12188 LoopTransformInterface :: set_astInterface(fa);
12189 LoopTransformInterface :: set_arrayInterface(&array_interface);
12190
12191 // invoke the unrolling defined in Qing's code
12192 // the traversal will skip the input node ptr, so we pass loop's parent ptr instead
12193 AstNodePtr result = AstNodePtrImpl(loop->get_parent()) ;
12194
12195 LoopUnrolling lu(unrolling_factor);
12196 //LoopUnrolling lu(unrolling_factor,LoopUnrolling::COND_LEFTOVER);//works but not a good choice
12197 //if (lu.cmdline_configure()) // this will cause unrolling to be skipped if no -unroll is used in command line
12198 result = lu(lpTrans, result);
12199 return true;
12200}
12201#else
12202
12203// a brand new serious implementation for loop unrolling, Liao, 6/25/2009
12204/* Handle left-over iterations if iteration_count%unrolling_factor != 0
12205 * Handle stride (step) >1
12206 * Assuming loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
12207 *
12208 * iteration_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1
12209 * fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step;
12210 * fringe ==0 if no leftover iterations
12211 * otherwise adjust ub so the leftover iterations will put into the last fringe loop
12212 * unrolled loop's header: for (i=lb;i<=ub - fringe; i+= step*unroll_factor)
12213 * loop body: copy body n times from 0 to factor -1
12214 * stmt(i+ 0*step); ...; stmt (i+ (factor-1)*step);
12215 * fringe loop: the same as the original loop, except for no init statement
12216 *
12217 * e.g:
12218 * // unrolling 3 times for the following loop with stride !=1
12219 * for (i=0; i<=9; i+=3)
12220 * {
12221 * a[i]=i;
12222 * }
12223 * // it becomes
12224 * // iteration count = 10%3=1 -> 10/3+1 = 4
12225 * // fringe = 4%3 =1 --> 3*3
12226 * // ub-fringe = 9-3*3
12227 * for (i=0; i<=9-3*3; i+=3*3)
12228 * {
12229 * a[i+3*0]=i;
12230 * a[i+3*1]=i;
12231 * a[i+3*2]=i;
12232 * }
12233 * // i=9 is the leftover iteration
12234 * for (; i<=9; i+=3)
12235 * {
12236 * a[i]=i;
12237 * }
12238 *
12239 */
12240bool SageInterface::loopUnrolling(SgForStatement* target_loop, size_t unrolling_factor)
12241{
12242#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
12243 //Handle 0 and 1, which means no unrolling at all
12244 if (unrolling_factor <= 1)
12245 return true;
12246
12247 // normalize the target loop first
12248
12249 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12250 if (!forLoopNormalization(target_loop))
12251 {
12252 // the return value is not reliable
12253 // cerr<<"Error in SageInterface::loopUnrolling(): target loop cannot be normalized."<<endl;
12254 // dumpInfo(target_loop);
12255 // return false;
12256 }
12257 // grab the target loop's essential header information
12258 SgInitializedName* ivar = NULL;
12259 SgExpression* lb = NULL;
12260 SgExpression* ub = NULL;
12261 SgExpression* step = NULL;
12262 SgStatement* orig_body = NULL;
12263 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, &orig_body))
12264 {
12265 cerr<<"Error in SageInterface::loopUnrolling(): target loop is not canonical."<<endl;
12266 dumpInfo(target_loop);
12267 return false;
12268 }
12269 ROSE_ASSERT(ivar&& lb && ub && step);
12270 ROSE_ASSERT(isSgBasicBlock(orig_body));
12271
12272 // generate the fringe loop
12273 bool needFringe = true;
12274 SgForStatement* fringe_loop = deepCopy<SgForStatement>(target_loop);
12275 insertStatementAfter(target_loop,fringe_loop);
12276 removeStatement(fringe_loop->get_for_init_stmt());
12277 fringe_loop->set_for_init_stmt(NULL);
12278
12279 // _lu_iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;
12281 copyExpression(lb));
12282 raw_range_exp->set_need_paren(true);
12283 SgExpression* range_d_step_exp = buildDivideOp(raw_range_exp,copyExpression(step));//(ub-lb+1)/step
12284 SgExpression* condition_1 = buildEqualityOp(buildModOp(copyExpression(raw_range_exp),copyExpression(step)),buildIntVal(0)); //(ub-lb+1)%step ==0
12285
12286 SgExpression* iter_count_exp = buildConditionalExp(condition_1,range_d_step_exp, buildAddOp(copyExpression(range_d_step_exp),buildIntVal(1)));
12287 // fringe = iteration_count%unroll_factor==0 ? 0:unroll_factor*step
12288 SgExpression* condition_2 = buildEqualityOp(buildModOp(iter_count_exp, buildIntVal(unrolling_factor)), buildIntVal(0));
12289 SgExpression* initor = buildConditionalExp(condition_2, buildIntVal(0), buildMultiplyOp(buildIntVal(unrolling_factor),copyExpression(step)));
12290
12291 SgScopeStatement* scope = target_loop->get_scope();
12292 ROSE_ASSERT(scope != NULL);
12293 string fringe_name = "_lu_fringe_"+ StringUtility::numberToString(++gensym_counter);
12294 SgVariableDeclaration* fringe_decl = buildVariableDeclaration(fringe_name, buildIntType(),buildAssignInitializer(initor), scope);
12295 insertStatementBefore(target_loop, fringe_decl);
12296 attachComment(fringe_decl, "iter_count = (ub-lb+1)%step ==0?(ub-lb+1)/step: (ub-lb+1)/step+1;");
12297 attachComment(fringe_decl, "fringe = iter_count%unroll_factor==0 ? 0:unroll_factor*step");
12298
12299 // compile-time evaluate to see if index is a constant of value 0
12300 // if so, the iteration count can be divided even by the unrolling factor
12301 // and no fringe loop is needed
12302 // WE have to fold on its parent node to get a possible constant since
12303 // constant folding only folds children nodes, not the current node to a constant
12304 ConstantFolding::constantFoldingOptimization(fringe_decl,false);
12305 SgInitializedName * ivarname = fringe_decl->get_variables().front();
12306 ROSE_ASSERT(ivarname != NULL);
12307 // points to a new address if constant folding happens
12308 SgAssignInitializer * init1 = isSgAssignInitializer(ivarname->get_initializer());
12309 if (init1)
12310 if (isSgIntVal(init1->get_operand_i()))
12311 if (isSgIntVal(init1->get_operand_i())->get_value() == 0)
12312 needFringe = false;
12313
12314 // rewrite loop header ub --> ub -fringe; step --> step *unrolling_factor
12315 SgBinaryOp* ub_bin_op = isSgBinaryOp(ub->get_parent());
12316 ROSE_ASSERT(ub_bin_op);
12317 if (needFringe)
12318 ub_bin_op->set_rhs_operand(buildSubtractOp(copyExpression(ub),buildVarRefExp(fringe_name,scope)));
12319 else
12320 {
12321 ub_bin_op->set_rhs_operand(copyExpression(ub));
12322 removeStatement(fringe_decl);
12323 }
12324
12325 SgBinaryOp* step_bin_op = isSgBinaryOp(step->get_parent());
12326 ROSE_ASSERT(step_bin_op != NULL);
12327 step_bin_op->set_rhs_operand(buildMultiplyOp(copyExpression(step),buildIntVal(unrolling_factor)));
12328
12329 bool isPlus = false;
12330 if (isSgPlusAssignOp(step_bin_op))
12331 isPlus = true;
12332 else if (isSgMinusAssignOp(step_bin_op))
12333 isPlus = false;
12334 else
12335 {
12336 cerr<<"Error in SageInterface::loopUnrolling(): illegal incremental exp of a canonical loop"<<endl;
12337 dumpInfo(step_bin_op);
12338 ROSE_ABORT();
12339 }
12340
12341 // copy loop body factor -1 times, and replace reference to ivar with ivar +/- step*[1 to factor-1]
12342 for (size_t i =1; i<unrolling_factor; i++)
12343 {
12344 SgBasicBlock* body = isSgBasicBlock(deepCopy(fringe_loop->get_loop_body())); // normalized loop has a BB body
12345 ROSE_ASSERT(body);
12346 std::vector<SgVarRefExp*> refs = querySubTree<SgVarRefExp> (body, V_SgVarRefExp);
12347 for (std::vector<SgVarRefExp*>::iterator iter = refs.begin(); iter !=refs.end(); iter++)
12348 {
12349 SgVarRefExp* refexp = *iter;
12350 if (refexp->get_symbol()==ivar->get_symbol_from_symbol_table())
12351 {
12352 // replace reference to ivar with ivar +/- step*i
12353 SgExpression* new_exp = NULL;
12354 //build replacement expression for every appearance
12355 if (isPlus) //ivar +/- step * i
12356 new_exp = buildAddOp(buildVarRefExp(ivar,scope),buildMultiplyOp(copyExpression(step),buildIntVal(i)));
12357 else
12359
12360 // replace it with the right one
12361 replaceExpression(refexp, new_exp);
12362 }
12363 }
12364 // copy body to loop body, this should be a better choice
12365 // to avoid redefinition of variables after unrolling (new scope is introduced to avoid this)
12366 appendStatement(body,isSgBasicBlock(orig_body));
12367 // moveStatementsBetweenBlocks(body,isSgBasicBlock(orig_body));
12368 }
12369
12370 // remove the fringe loop if not needed finally
12371 // it is used to buffering the original loop body before in either cases
12372 if (!needFringe)
12373 removeStatement(fringe_loop);
12374
12375 // constant folding for the transformed AST
12376 ConstantFolding::constantFoldingOptimization(scope,false);
12377 //ConstantFolding::constantFoldingOptimization(getProject(),false);
12378
12379#endif
12380
12381 return true;
12382}
12383#endif
12384
12385// Liao, 6/15/2009
12388static size_t myfactorial (size_t n)
12389{
12390 size_t result=1;
12391 for (size_t i=2; i<=n; i++)
12392 result*=i;
12393 return result;
12394}
12395
12396#endif
12397
12398#ifndef USE_ROSE
12399
12402std::vector<size_t> getPermutationOrder( size_t n, size_t lexicoOrder)
12403{
12404 size_t k = lexicoOrder;
12405 std::vector<size_t> s(n);
12406 // initialize the permutation vector
12407 for (size_t i=0; i<n; i++)
12408 s[i]=i;
12409
12410 //compute (n- 1)!
12411 size_t factorial = myfactorial(n-1);
12412 //check if the number is not in the range of [0, n! - 1]
12413 if (k/n>=factorial)
12414 {
12415 printf("Error: in getPermutationOrder(), lexicoOrder is larger than n!-1\n");
12416 ROSE_ABORT();
12417 }
12418 // Algorithm:
12419 //check each element of the array, excluding the right most one.
12420 //the goal is to find the right element for each s[j] from 0 to n-2
12421 // method: each position is associated a factorial number
12422 // s[0] -> (n-1)!
12423 // s[1] -> (n-2)! ...
12424 // the input number k is divided by the factorial at each position (6, 3, 2, 1 for size =4)
12425 // so only big enough k can have non-zero value after division
12426 // 0 value means no change to the position for the current iteration
12427 // The non-zero value is further modular by the number of the right hand elements of the current element.
12428 // (mode on 4, 3, 2 to get offset 1-2-3, 1-2, 1 from the current position 0, 1, 2)
12429 // choose one of them to be moved to the current position,
12430 // shift elements between the current and the moved element to the right direction for one position
12431 for (size_t j=0; j<n-1; j++)
12432 {
12433 //calculates the next cell from the cells left
12434 //(the cells in the range [j, s.length - 1])
12435 int tempj = (k/factorial) % (n - j);
12436 //Temporarily saves the value of the cell needed
12437 // to add to the permutation this time
12438 int temps = s[j+tempj];
12439 //shift all elements to "cover" the "missing" cell
12440 //shift them to the right
12441 for (size_t i=j+tempj; i>j; i--)
12442 {
12443 s[i] = s[i-1]; //shift the chain right
12444 }
12445 // put the chosen cell in the correct spot
12446 s[j]= temps;
12447 // updates the factorial
12448 factorial = factorial /(n-(j+1));
12449 }
12450#if 0
12451 for (size_t i = 0; i<n; i++)
12452 cout<<" "<<s[i];
12453 cout<<endl;
12454#endif
12455 return s;
12456}
12457
12459/* Translation
12460 Before:
12461 for (i = 0; i < 100; i++)
12462 for (j = 0; j < 100; j++)
12463 for (k = 0; k < 100; k++)
12464 c[i][j]= c[i][j]+a[i][k]*b[k][j];
12465
12466 After tiling i loop nest's level 3 (k-loop) with size 5, it becomes
12467
12468// added a new controlling loop at the outer most level
12469 int _lt_var_k;
12470 for (_lt_var_k = 0; _lt_var_k <= 99; _lt_var_k += 1 * 5) {
12471 for (i = 0; i < 100; i++)
12472 for (j = 0; j < 100; j++)
12473 // rewritten loop header , normalized also
12474 for (k = _lt_var_k; k <= (99 < (_lt_var_k + 5 - 1))?99 : (_lt_var_k + 5 - 1); k += 1) {
12475 c[i][j] = c[i][j] + a[i][k] * b[k][j];
12476 }
12477 }
12478// finally run constant folding
12479
12480 */
12481bool SageInterface::loopTiling(SgForStatement* loopNest, size_t targetLevel, size_t tileSize)
12482{
12483 ROSE_ASSERT(loopNest != NULL);
12484 ROSE_ASSERT(targetLevel >0);
12485 // ROSE_ASSERT(tileSize>0);// 1 is allowed
12486 // skip tiling if tiling size is 0 (no tiling), we allow 0 to get a reference value for the original code being tuned
12487 // 1 (no need to tile)
12488 if (tileSize<=1)
12489 return true;
12490 // Locate the target loop at level n
12491 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(loopNest,V_SgForStatement);
12492 ROSE_ASSERT(loops.size()>=targetLevel);
12493 SgForStatement* target_loop = loops[targetLevel -1]; // adjust to numbering starting from 0
12494
12495 // DQ (3/25/2017): Fixed Clang warning: warning: if statement has empty body [-Wempty-body]
12496 // normalize the target loop first
12497 if (!forLoopNormalization(target_loop))
12498 {// the return value is not reliable
12499// cerr<<"Error in SageInterface::loopTiling(): target loop cannot be normalized."<<endl;
12500// dumpInfo(target_loop);
12501// return false;
12502 }
12503 // grab the target loop's essential header information
12504 SgInitializedName* ivar = NULL;
12505 SgExpression* lb = NULL;
12506 SgExpression* ub = NULL;
12507 SgExpression* step = NULL;
12508 if (!isCanonicalForLoop(target_loop, &ivar, &lb, &ub, &step, NULL))
12509 {
12510 cerr<<"Error in SageInterface::loopTiling(): target loop is not canonical."<<endl;
12511 dumpInfo(target_loop);
12512 return false;
12513 }
12514 ROSE_ASSERT(ivar&& lb && ub && step);
12515
12516 // Add a controlling loop around the top loop nest
12517 // Ensure the parent can hold more than one children
12518 SgLocatedNode* parent = NULL; //SageInterface::ensureBasicBlockAsParent(loopNest)
12519 if (isBodyStatement(loopNest)) // if it is a single body statement (Already a for statement, not a basic block)
12520 parent = makeSingleStatementBodyToBlock (loopNest);
12521 else
12522 parent = isSgLocatedNode(loopNest ->get_parent());
12523
12524 ROSE_ASSERT(parent!= NULL);
12525 // Now we can prepend a controlling loop index variable: __lt_var_originalIndex
12526 string ivar2_name = "_lt_var_"+ivar->get_name().getString();
12527 SgScopeStatement* scope = loopNest->get_scope();
12529 (ivar2_name, buildIntType(),NULL, scope);
12530 insertStatementBefore(loopNest, loop_index_decl);
12531 // init statement of the loop header, copy the lower bound
12532 SgStatement* init_stmt = buildAssignStatement(buildVarRefExp(ivar2_name,scope), copyExpression(lb));
12533 //two cases <= or >= for a normalized loop
12534 SgExprStatement* cond_stmt = NULL;
12535 SgExpression* orig_test = target_loop->get_test_expr();
12536 if (isSgBinaryOp(orig_test))
12537 {
12538 if (isSgLessOrEqualOp(orig_test))
12539 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12540 else if (isSgGreaterOrEqualOp(orig_test))
12541 {
12542 cond_stmt = buildExprStatement(buildGreaterOrEqualOp(buildVarRefExp(ivar2_name,scope),copyExpression(ub)));
12543 }
12544 else
12545 {
12546 cerr<<"Error: illegal condition operator for a canonical loop"<<endl;
12547 dumpInfo(orig_test);
12548 ROSE_ABORT();
12549 }
12550 }
12551 else
12552 {
12553 cerr<<"Error: illegal condition expression for a canonical loop"<<endl;
12554 dumpInfo(orig_test);
12555 ROSE_ABORT();
12556 }
12557 ROSE_ASSERT(cond_stmt != NULL);
12558
12559 // build loop incremental I
12560 // expression var+=up*tilesize or var-=upper * tilesize
12561 SgExpression* incr_exp = NULL;
12562 SgExpression* orig_incr_exp = target_loop->get_increment();
12563 if( isSgPlusAssignOp(orig_incr_exp))
12564 {
12565 incr_exp = buildPlusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12566 }
12567 else if (isSgMinusAssignOp(orig_incr_exp))
12568 {
12569 incr_exp = buildMinusAssignOp(buildVarRefExp(ivar2_name,scope), buildMultiplyOp(copyExpression(step), buildIntVal(tileSize)));
12570 }
12571 else
12572 {
12573 cerr<<"Error: illegal increment expression for a canonical loop"<<endl;
12574 dumpInfo(orig_incr_exp);
12575 ROSE_ABORT();
12576 }
12577 SgForStatement* control_loop = buildForStatement(init_stmt, cond_stmt,incr_exp, buildBasicBlock());
12578 insertStatementBefore(loopNest, control_loop);
12579 // move loopNest into the control loop
12580 removeStatement(loopNest);
12581 appendStatement(loopNest,isSgBasicBlock(control_loop->get_loop_body()));
12582
12583 // rewrite the lower (i=lb), upper bounds (i<=/>= ub) of the target loop
12584 SgAssignOp* assign_op = isSgAssignOp(lb->get_parent());
12585 ROSE_ASSERT(assign_op);
12586 assign_op->set_rhs_operand(buildVarRefExp(ivar2_name,scope));
12587 // ub< var_i+tileSize-1? ub:var_i+tileSize-1
12588 SgBinaryOp* bin_op = isSgBinaryOp(ub->get_parent());
12589 ROSE_ASSERT(bin_op);
12590 SgExpression* ub2 = buildSubtractOp(buildAddOp(buildVarRefExp(ivar2_name,scope), buildIntVal(tileSize)), buildIntVal(1));
12591 SgExpression* test_exp = buildLessThanOp(copyExpression(ub),ub2);
12592 test_exp->set_need_paren(true);
12593 ub->set_need_paren(true);
12594 ub2->set_need_paren(true);
12595 SgConditionalExp * triple_exp = buildConditionalExp(test_exp,copyExpression(ub), copyExpression(ub2));
12596 bin_op->set_rhs_operand(triple_exp);
12597 // constant folding
12598 // folding entire loop may decrease the accuracy of floating point calculation
12599 // we fold loop control expressions only
12600 //constantFolding(control_loop->get_scope());
12601 constantFolding(control_loop->get_test());
12602 constantFolding(control_loop->get_increment());
12603 return true;
12604}
12605
12607bool SageInterface::loopInterchange(SgForStatement* loop, size_t depth, size_t lexicoOrder)
12608{
12609 if (lexicoOrder == 0) // allow 0 to mean no interchange at all
12610 return true;
12611 // parameter verification
12612 ROSE_ASSERT(loop != NULL);
12613 //must have at least two levels
12614 ROSE_ASSERT (depth >1);
12615 ROSE_ASSERT(lexicoOrder<myfactorial(depth));
12616 //TODO need to verify the input loop has n perfectly-nested children loops inside
12617 // save the loop nest's headers: init, test, and increment
12618 std::vector<SgForStatement* > loopNest = SageInterface::querySubTree<SgForStatement>(loop,V_SgForStatement);
12619 ROSE_ASSERT(loopNest.size()>=depth);
12620 std::vector<std::vector<SgNode*> > loopHeads;
12621 for (std::vector<SgForStatement* > ::iterator i = loopNest.begin(); i!= loopNest.end(); i++)
12622 {
12623 SgForStatement* cur_loop = *i;
12624 std::vector<SgNode*> head;
12625 head.push_back(cur_loop->get_for_init_stmt());
12626 head.push_back(cur_loop->get_test());
12627 head.push_back(cur_loop->get_increment());
12628 loopHeads.push_back(head);
12629 }
12630
12631 // convert the lexicographical number to a permutation order array permutation[depth]
12632 std::vector<size_t> changedOrder = getPermutationOrder (depth, lexicoOrder);
12633 // rewrite the loop nest to reflect the permutation
12634 // set the header to the new header based on the permutation array
12635 for (size_t i=0; i<depth; i++)
12636 {
12637 // only rewrite if necessary
12638 if (i != changedOrder[i])
12639 {
12640 SgForStatement* cur_loop = loopNest[i];
12641 std::vector<SgNode*> newhead = loopHeads[changedOrder[i]];
12642
12643 SgForInitStatement* init = isSgForInitStatement(newhead[0]);
12644 //ROSE_ASSERT(init != NULL) // could be NULL?
12645 ROSE_ASSERT(init != cur_loop->get_for_init_stmt());
12646 cur_loop->set_for_init_stmt(init);
12647 if (init)
12648 {
12649 init->set_parent(cur_loop);
12651 }
12652
12653 SgStatement* test = isSgStatement(newhead[1]);
12654 cur_loop->set_test(test);
12655 if (test)
12656 {
12657 test->set_parent(cur_loop);
12659 }
12660
12661 SgExpression* incr = isSgExpression(newhead[2]);
12662 cur_loop->set_increment(incr);
12663 if (incr)
12664 {
12665 incr->set_parent(cur_loop);
12667 }
12668 }
12669 }
12670 return true;
12671}
12672
12675{
12676 ROSE_ASSERT(loop != NULL);
12677 SgInitializedName* ivarname=NULL;
12678
12679 // Fortran case ------------------
12680 if (SgFortranDo * do_loop = isSgFortranDo(loop))
12681 {
12682 SgAssignOp* assign_op = isSgAssignOp (do_loop->get_initialization());
12683 ROSE_ASSERT (assign_op != NULL);
12684 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12685 ROSE_ASSERT (var != NULL);
12686 ivarname = var->get_symbol()->get_declaration();
12687 ROSE_ASSERT (ivarname != NULL);
12688 return ivarname;
12689 }
12690 // C/C++ case ------------------------------
12691 SgForStatement* fs = isSgForStatement(loop);
12692 if (fs == NULL)
12693 {
12694 return NULL;
12695 }
12696 // we only handle C/C++ for loops and Fortran Do loops.
12697 // Any other kinds of loops (while, do-while,etc.) are skipped and return NULL;
12698 // ROSE_ASSERT (fs != NULL);
12699
12700 //Check initialization statement is something like i=xx;
12701 SgStatementPtrList & init = fs->get_init_stmt();
12702 if (init.size() !=1)
12703 {
12704 cerr<<"SageInterface::getLoopIndexVariable(), no or more than one initialization statements are encountered. Not supported yet "<<endl;
12705 //ROSE_ASSERT(false);
12706 return NULL;
12707 }
12708 SgStatement* init1 = init.front();
12709 SgExpression* ivarast=NULL;
12710
12711 // DQ (3/20/2016): Note that GNU compiler reports these variables are set but not used.
12712 //bool isCase1=false, isCase2=false;
12713
12714 //consider C99 style: for (int i=0;...)
12715 if (isSgVariableDeclaration(init1))
12716 {
12717 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
12718 ivarname = decl->get_variables().front();
12719 ROSE_ASSERT(ivarname != NULL);
12720 //SgInitializer * initor = ivarname->get_initializer();
12721 // if (isSgAssignInitializer(initor))
12722 // isCase1 = true;
12723 }// other regular case: for (i=0;..)
12724 else if (isAssignmentStatement(init1, &ivarast))
12725 {
12726 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
12727 if (var)
12728 {
12729 ivarname = var->get_symbol()->get_declaration();
12730 //isCase2 = true;
12731 }
12732 }
12733 else if (SgExprStatement* exp_stmt = isSgExprStatement(init1))
12734 { //case like: for (i = 1, len1 = 0, len2=0; i <= n; i++)
12735 // AST is: SgCommaOpExp -> SgAssignOp -> SgVarRefExp
12736 if (SgCommaOpExp* comma_exp = isSgCommaOpExp(exp_stmt->get_expression()))
12737 {
12738 SgCommaOpExp* leaf_exp = comma_exp;
12739 while (isSgCommaOpExp(leaf_exp->get_lhs_operand()))
12740 leaf_exp = isSgCommaOpExp(leaf_exp->get_lhs_operand());
12741 if (SgAssignOp* assign_op = isSgAssignOp(leaf_exp->get_lhs_operand()))
12742 {
12743 SgVarRefExp* var = isSgVarRefExp(assign_op->get_lhs_operand());
12744 if (var)
12745 {
12746 ivarname = var->get_symbol()->get_declaration();
12747 }
12748 }
12749 }
12750 }
12751 else
12752 {
12753
12754 mlog[Sawyer::Message::Common::WARN] <<"Warning: SageInterface::getLoopIndexVariable(). Unhandled init_stmt type of SgForStatement"<<endl;
12755 mlog[Sawyer::Message::Common::WARN] <<"Init statement is :"<<init1->class_name() <<" " <<init1->unparseToString()<<endl;
12756 init1->get_file_info()->display("Debug");
12757
12758 return NULL;
12759 //ROSE_ASSERT (false);
12760 }
12761 // Cannot be both true
12762 // ROSE_ASSERT(!(isCase1&&isCase2));
12763
12764 //Check loop index's type
12765 //ROSE_ASSERT(isStrictIntegerType(ivarname->get_type()));
12766 return ivarname;
12767}
12768
12772{
12773 ROSE_ASSERT (ivar != NULL);
12774 ROSE_ASSERT (subtree_root != NULL);
12775 bool result = false;
12776 SgScopeStatement * cur_loop = findEnclosingLoop (getEnclosingStatement(subtree_root));
12777 while (cur_loop)
12778 {
12779 SgInitializedName * i_index = getLoopIndexVariable (cur_loop);
12780 if (i_index == ivar)
12781 {
12782 result = true;
12783 break;
12784 }
12785 else
12786 { // findEnclosingLoop() is inclusive.
12787 cur_loop = findEnclosingLoop (getEnclosingStatement(cur_loop->get_parent()));
12788 }
12789 }
12790 return result;
12791}
12792
12794
12799{
12800 ROSE_ASSERT (loop !=NULL);
12801 SgStatementPtrList& stmt_list = loop->get_init_stmt();
12802 if (stmt_list.size() >1) return true; // two var decl statements
12803 if (stmt_list.size() == 0) return false;
12804
12805// generateDOTforMultipleFile(*getProject());
12806 //single variable declaration statement, like int i;
12807 SgVariableDeclaration* decl_stmt = isSgVariableDeclaration(stmt_list[0]);
12808 if (decl_stmt != NULL)
12809 return false;
12810
12811 // single statement, but with comma expression (i=0, j=0)
12812 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
12813 ROSE_ASSERT (exp_stmt != NULL);
12814 if (isSgCommaOpExp (exp_stmt->get_expression()) )
12815 {
12816 return true;
12817 }
12818
12819 return false;
12820}
12822bool 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*/)
12823{
12824 ROSE_ASSERT(loop != NULL);
12825 SgFortranDo* fs = isSgFortranDo(loop);
12826 if (fs == NULL)
12827 return false;
12828 // 1. Check initialization statement is something like i=xx;
12829 SgExpression * init = fs->get_initialization();
12830 if (init == NULL)
12831 return false;
12832 SgAssignOp* init_assign = isSgAssignOp (init);
12833 SgExpression *lbast=NULL, *ubast=NULL;
12834 // SgExpression* ivarast=NULL, *stepast=NULL;
12835 SgInitializedName* ivarname=NULL;
12836
12837 bool isCase1=false;
12838 if (init_assign)
12839 {
12840 SgVarRefExp* var = isSgVarRefExp(init_assign->get_lhs_operand());
12841 if (var)
12842 ivarname = var->get_symbol()->get_declaration();
12843 lbast = init_assign->get_rhs_operand();
12844 if (ivarname && lbast )
12845 isCase1 = true;
12846 }
12847 // if not i=1
12848 if (!isCase1)
12849 return false;
12850
12851 //Check loop index's type
12852 if (!SageInterface::isStrictIntegerType(ivarname->get_type()))
12853 return false;
12854#if 0
12855 //2. Check test expression i [<=, >=, <, > ,!=] bound
12856 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
12857 if (test == NULL)
12858 return false;
12859 switch (test->variantT()) {
12860 case V_SgLessOrEqualOp:
12861 if (isInclusiveUpperBound != NULL)
12862 *isInclusiveUpperBound = true;
12863 if (hasIncrementalIterationSpace != NULL)
12864 *hasIncrementalIterationSpace = true;
12865 break;
12866 case V_SgLessThanOp:
12867 if (isInclusiveUpperBound != NULL)
12868 *isInclusiveUpperBound = false;
12869 if (hasIncrementalIterationSpace != NULL)
12870 *hasIncrementalIterationSpace = true;
12871 break;
12872 case V_SgGreaterOrEqualOp:
12873 if (isInclusiveUpperBound != NULL)
12874 *isInclusiveUpperBound = true;
12875 if (hasIncrementalIterationSpace != NULL)
12876 *hasIncrementalIterationSpace = false;
12877 break;
12878 case V_SgGreaterThanOp:
12879 if (isInclusiveUpperBound != NULL)
12880 *isInclusiveUpperBound = false;
12881 if (hasIncrementalIterationSpace != NULL)
12882 *hasIncrementalIterationSpace = false;
12883 break;
12884// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
12885 break;
12886 default:
12887 return false;
12888 }
12889 // check the tested variable is the same as the loop index
12890 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
12891 if (testvar == NULL)
12892 return false;
12893 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12894 return false;
12895#endif
12896 //grab the upper bound
12897 ubast = loop->get_bound();
12898 // Fortran Do loops always have inclusive upper bound
12899 if (isInclusiveUpperBound != NULL)
12900 *isInclusiveUpperBound = true;
12901 //3. Check the increment expression
12902 SgExpression* incr = fs->get_increment();
12903 ROSE_ASSERT (incr != NULL);
12904 if (isSgNullExpression(incr))
12905 {
12906 cerr<<"Error:isCanonicalDoLoop() found NULL increment expression. Please call doLoopNormalization() first!"<<endl;
12907 ROSE_ASSERT (false);
12908 }
12909 if (hasIncrementalIterationSpace != NULL)
12910 {
12911 *hasIncrementalIterationSpace = true;
12912 // We can only tell a few cases
12913 if (SgIntVal* i_v = isSgIntVal(incr))
12914 {
12915 if (i_v->get_value()<0)
12916 *hasIncrementalIterationSpace = false;
12917 }
12918 }
12919#if 0
12920 SgVarRefExp* incr_var = NULL;
12921 switch (incr->variantT()) {
12922 case V_SgPlusAssignOp: //+=
12923 case V_SgMinusAssignOp://-=
12924 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
12925 stepast = isSgBinaryOp(incr)->get_rhs_operand();
12926 break;
12927 case V_SgPlusPlusOp: //++
12928 case V_SgMinusMinusOp: //--
12929 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
12930 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
12931 break;
12932 default:
12933 return false;
12934 }
12935 if (incr_var == NULL)
12936 return false;
12937 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
12938 return false;
12939#endif
12940 // return loop information if requested
12941 if (ivar != NULL)
12942 *ivar = ivarname;
12943 if (lb != NULL)
12944 *lb = lbast;
12945 if (ub != NULL)
12946 *ub = ubast;
12947 if (step != NULL)
12948 *step = incr;
12949 if (body != NULL) {
12950 *body = fs->get_body();
12951 }
12952 return true;
12953}
12954//TODO: expose it to the namespace once it matures.
12956// with a single entry at the top and a single exit at the bottom, or an OpenMP construct.
12957/*
12958From OpenMP 4.5 Specification
12959
129601.2.2 OpenMP Language Terminology
12961
12962For C/C++, an executable statement, possibly compound, with a single entry at the
12963top and a single exit at the bottom, or an OpenMP construct.
12964
12965For Fortran, a block of executable statements with a single entry at the top and a
12966single exit at the bottom, or an OpenMP construct.
12967
12968COMMENTS:
12969
12970For all base languages:
12971* Access to the structured block must not be the result of a branch; and
12972* The point of exit cannot be a branch out of the structured block.
12973
12974 For C/C++:
12975* The point of entry must not be a call to setjmp();
12976* longjmp() and throw() must not violate the entry/exit criteria;
12977* Calls to exit() are allowed in a structured block; and
12978* 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.
12979
12980For Fortran:
12981* STOP statements are allowed in a structured block.
12982
12983*/
12984bool isStructuredBlock(SgStatement* s)
12985{
12986 bool rt = true;
12987 ROSE_ASSERT (s != NULL);
12988
12989 // contain break;
12990 std::set<SgNode*> bset = SgNodeHelper::loopRelevantBreakStmtNodes (s);
12991 if (bset.size()!=0 )
12992 rt = false;
12993 //TODO: contain goto statement, jumping to outside targets
12994 // longjump(), throw(),
12995 // calls to exit() are allowed.
12996
12997 return rt;
12998
12999}
13000
13002//TODO check the loop index is not being written in the loop body
13003bool 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*/)
13004{
13005 ROSE_ASSERT(loop != NULL);
13006 SgForStatement* fs = isSgForStatement(loop);
13007 //SgFortranDo* fs2 = isSgFortranDo(loop);
13008 if (fs == NULL)
13009 {
13010 // if (fs2)
13011 // return isCanonicalDoLoop (fs2, ivar, lb, ub, step, body, hasIncrementalIterationSpace, isInclusiveUpperBound);
13012 // else
13013 return false;
13014 }
13015 // 1. Check initialization statement is something like i=xx;
13016 SgStatementPtrList & init = fs->get_init_stmt();
13017 if (init.size() !=1)
13018 return false;
13019 SgStatement* init1 = init.front();
13020 SgExpression* ivarast=NULL, *lbast=NULL, *ubast=NULL, *stepast=NULL;
13021 SgInitializedName* ivarname=NULL;
13022
13023 bool isCase1=false, isCase2=false;
13024 //consider C99 style: for (int i=0;...)
13025 if (isSgVariableDeclaration(init1))
13026 {
13027 SgVariableDeclaration* decl = isSgVariableDeclaration(init1);
13028 ivarname = decl->get_variables().front();
13029 ROSE_ASSERT(ivarname != NULL);
13030 SgInitializer * initor = ivarname->get_initializer();
13031 if (isSgAssignInitializer(initor))
13032 {
13033 lbast = isSgAssignInitializer(initor)->get_operand();
13034 isCase1 = true;
13035 }
13036 }// other regular case: for (i=0;..)
13037 else if (isAssignmentStatement(init1, &ivarast, &lbast))
13038 {
13039 SgVarRefExp* var = isSgVarRefExp(SkipCasting(ivarast));
13040 if (var)
13041 {
13042 ivarname = var->get_symbol()->get_declaration();
13043 isCase2 = true;
13044 }
13045 }
13046 // Cannot be both true
13047 ROSE_ASSERT(!(isCase1&&isCase2));
13048 // if not either case is true
13049 if (!(isCase1||isCase2))
13050 return false;
13051
13052 //Check loop index's type
13053 if (!isStrictIntegerType(ivarname->get_type()))
13054 return false;
13055
13056 //2. Check test expression i [<=, >=, <, > ,!=] bound
13057 SgBinaryOp* test = isSgBinaryOp(fs->get_test_expr());
13058 if (test == NULL)
13059 return false;
13060 switch (test->variantT()) {
13061 case V_SgLessOrEqualOp:
13062 if (isInclusiveUpperBound != NULL)
13063 *isInclusiveUpperBound = true;
13064 if (hasIncrementalIterationSpace != NULL)
13065 *hasIncrementalIterationSpace = true;
13066 break;
13067 case V_SgLessThanOp:
13068 if (isInclusiveUpperBound != NULL)
13069 *isInclusiveUpperBound = false;
13070 if (hasIncrementalIterationSpace != NULL)
13071 *hasIncrementalIterationSpace = true;
13072 break;
13073 case V_SgGreaterOrEqualOp:
13074 if (isInclusiveUpperBound != NULL)
13075 *isInclusiveUpperBound = true;
13076 if (hasIncrementalIterationSpace != NULL)
13077 *hasIncrementalIterationSpace = false;
13078 break;
13079 case V_SgGreaterThanOp:
13080 if (isInclusiveUpperBound != NULL)
13081 *isInclusiveUpperBound = false;
13082 if (hasIncrementalIterationSpace != NULL)
13083 *hasIncrementalIterationSpace = false;
13084 break;
13085// case V_SgNotEqualOp: // Do we really want to allow this != operator ?
13086 break;
13087 default:
13088 return false;
13089 }
13090 // check the tested variable is the same as the loop index
13091 SgVarRefExp* testvar = isSgVarRefExp(SkipCasting(test->get_lhs_operand()));
13092 if (testvar == NULL)
13093 return false;
13094 if (testvar->get_symbol() != ivarname->get_symbol_from_symbol_table ())
13095 return false;
13096 //grab the upper bound
13097 ubast = test->get_rhs_operand();
13098
13099 //3. Check the increment expression
13100 /* Allowed forms
13101 ++var
13102 var++
13103 --var
13104 var--
13105
13106 var += incr
13107 var -= incr
13108
13109 var = var + incr
13110 var = incr + var
13111 var = var - incr
13112 */
13113 SgExpression* incr = fs->get_increment();
13114 SgVarRefExp* incr_var = NULL;
13115 switch (incr->variantT()) {
13116 case V_SgPlusAssignOp: //+=
13117 case V_SgMinusAssignOp://-=
13118 incr_var = isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
13119 stepast = isSgBinaryOp(incr)->get_rhs_operand();
13120 break;
13121 case V_SgPlusPlusOp: //++
13122 case V_SgMinusMinusOp: //--
13123 incr_var = isSgVarRefExp(SkipCasting(isSgUnaryOp(incr)->get_operand()));
13124 stepast = buildIntVal(1); // will this dangling SgNode cause any problem?
13125 break;
13126 case V_SgAssignOp: { // cases : var + incr, var - incr, incr + var (not allowed: incr-var)
13127 incr_var=isSgVarRefExp(SkipCasting(isSgBinaryOp(incr)->get_lhs_operand()));
13128 if(incr_var == NULL)
13129 return false;
13130 SgAddOp* addOp=isSgAddOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
13131 SgSubtractOp* subtractOp=isSgSubtractOp(SkipCasting(isSgBinaryOp(incr)->get_rhs_operand()));
13132 SgBinaryOp* arithOp=0;
13133 if(addOp)
13134 arithOp=addOp;
13135 else if(subtractOp)
13136 arithOp=subtractOp;
13137 else
13138 return false;
13139 ROSE_ASSERT(arithOp!=0);
13140 if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_lhs_operand()))) {
13141 // cases : var + incr, var - incr
13142 incr_var=varRefExp;
13143 stepast=isSgBinaryOp(arithOp)->get_rhs_operand();
13144 } else if(SgVarRefExp* varRefExp=isSgVarRefExp(SkipCasting(isSgBinaryOp(arithOp)->get_rhs_operand()))) {
13145 if(isSgAddOp(arithOp)) {
13146 // case : incr + var (not allowed: incr-var)
13147 incr_var=varRefExp;
13148 stepast=isSgBinaryOp(arithOp)->get_lhs_operand();
13149 }
13150 }
13151 break;
13152 } // end of V_AssignOp
13153 default:
13154 return false;
13155 }
13156
13157 if (incr_var == NULL)
13158 return false;
13159 if (incr_var->get_symbol() != ivarname->get_symbol_from_symbol_table ())
13160 return false;
13161
13162
13163 // single entry and single exit?
13164 // only for C for loop for now
13165 // TODO: Fortran support later
13166 if (fs && !isStructuredBlock(fs->get_loop_body()) )
13167 return false;
13168
13169 // return loop information if requested
13170 if (ivar != NULL)
13171 *ivar = ivarname;
13172 if (lb != NULL)
13173 *lb = lbast;
13174 if (ub != NULL)
13175 *ub = ubast;
13176 if (step != NULL)
13177 *step = stepast;
13178 if (body != NULL) {
13179 *body = fs->get_loop_body();
13180 }
13181 return true;
13182}
13183
13186{
13187 ROSE_ASSERT(loop != NULL);
13188 ROSE_ASSERT(lb != NULL);
13189 SgForStatement* forstmt = isSgForStatement(loop);
13190 SgFortranDo* dostmt = isSgFortranDo(loop);
13191 // ROSE_ASSERT(forstmt!= NULL);
13192
13193 if (forstmt != NULL)
13194 {
13195 // two cases: init_stmt is
13196 // SgExprStatement (assignment) like i=0;
13197 // SgVariableDeclaration int i =0 or
13198 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignOp);
13199 if (testList.size()>0) // assignment statement
13200 {
13201 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13202 SgAssignOp * assignop = isSgAssignOp((*testList.begin()));
13203 ROSE_ASSERT(assignop);
13204 if( assignop->get_rhs_operand()->get_lvalue())
13205 lb->set_lvalue(true);
13206 assignop->set_rhs_operand(lb);
13207 lb->set_parent(assignop);
13208 //TODO what happens to the original rhs operand?
13209 }
13210 else // variable declaration case
13211 {
13212 // SgVariableDeclaration
13213 Rose_STL_Container<SgNode* > testList = NodeQuery::querySubTree( *((forstmt->get_init_stmt()).begin()), V_SgAssignInitializer );
13214 ROSE_ASSERT(testList.size()==1);// only handle the case of 1 statement, canonical form
13215 SgAssignInitializer* init = isSgAssignInitializer((*testList.begin()));
13216 ROSE_ASSERT(init != NULL);
13217 init->set_operand(lb);
13218 lb->set_parent(init);
13219 //TODO what happens to the original rhs operand?
13220 }
13221 }
13222 else if (dostmt != NULL)
13223 {
13224 SgExpression* init = dostmt->get_initialization();
13225 ROSE_ASSERT (init != NULL);
13226 SgAssignOp * a_op = isSgAssignOp (init);
13227 ROSE_ASSERT (a_op!=NULL);
13228 a_op->set_rhs_operand(lb);
13229 lb->set_parent(a_op);
13230 //TODO delete the previous operand?
13231 }
13232 else
13233 {
13234 cerr<<"Error. SageInterface::setLoopLowerBound(), illegal loop type:"<< loop->class_name()<<endl;
13235 ROSE_ASSERT (false);
13236 }
13237}
13238
13241{
13242 ROSE_ASSERT(loop != NULL);
13243 ROSE_ASSERT(ub != NULL);
13244 SgForStatement* forstmt = isSgForStatement(loop);
13245 // ROSE_ASSERT(forstmt!= NULL);
13246 SgFortranDo* dostmt = isSgFortranDo(loop);
13247 if (forstmt != NULL)
13248 {
13249 // set upper bound expression
13250 SgBinaryOp * binop= isSgBinaryOp(isSgExprStatement(forstmt->get_test())->get_expression());
13251 ROSE_ASSERT(binop != NULL);
13252 binop->set_rhs_operand(ub);
13253 ub->set_parent(binop);
13254 }
13255 else if (dostmt != NULL)
13256 {
13257 dostmt->set_bound(ub);
13258 ub->set_parent(dostmt);
13259 //TODO delete the original bound expression
13260 }
13261 else
13262 {
13263 cerr<<"Error. SageInterface::setLoopUpperBound(), illegal loop type:"<< loop->class_name()<<endl;
13264 ROSE_ASSERT (false);
13265 }
13266
13267}
13268
13271{
13272 ROSE_ASSERT(loop != NULL);
13273 ROSE_ASSERT(stride != NULL);
13274 SgForStatement* forstmt = isSgForStatement(loop);
13275 SgFortranDo * dostmt = isSgFortranDo (loop);
13276 // ROSE_ASSERT(forstmt!= NULL);
13277 if (dostmt != NULL)
13278 {
13279 dostmt->set_increment(stride);
13280 stride->set_parent(dostmt);
13281 //TODO delete original increment expression
13282 }
13283 else if (forstmt != NULL)
13284 {
13285 // set stride expression
13286 // case 1: i++ change to i+=stride
13287 Rose_STL_Container<SgNode*> testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusPlusOp);
13288 if (testList.size()>0)
13289 {
13290 ROSE_ASSERT(testList.size() == 1); // should have only one
13291 SgVarRefExp *loopvarexp = isSgVarRefExp(SageInterface::deepCopy
13292 (isSgPlusPlusOp( *testList.begin())->get_operand()));
13293 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13294 forstmt->set_increment(plusassignop);
13295 }
13296
13297 // case 1.5: i-- also changed to i+=stride
13298 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusMinusOp);
13299 if (testList.size()>0)
13300 {
13301 ROSE_ASSERT(testList.size()==1);// should have only one
13302 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13303 (isSgMinusMinusOp(*testList.begin())->get_operand()));
13304 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13305 forstmt->set_increment(plusassignop);
13306 }
13307
13308 // case 2: i+=X
13309 testList = NodeQuery::querySubTree( forstmt->get_increment(), V_SgPlusAssignOp);
13310 if (testList.size()>0)
13311 {
13312 ROSE_ASSERT(testList.size()==1);// should have only one
13313 SgPlusAssignOp * assignop = isSgPlusAssignOp(*(testList.begin()));
13314 ROSE_ASSERT(assignop!=NULL);
13315 assignop->set_rhs_operand(stride);
13316 }
13317
13318 // case 2.5: i-=X changed to i+=stride
13319 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgMinusAssignOp);
13320 if (testList.size()>0)
13321 {
13322 ROSE_ASSERT(testList.size()==1);// should have only one
13323 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13324 (isSgMinusAssignOp(*testList.begin())->get_lhs_operand()));
13325 SgExprStatement* exprstmt = isSgExprStatement((*testList.begin())->get_parent());
13326 ROSE_ASSERT(exprstmt !=NULL);
13327 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13328 exprstmt->set_expression(plusassignop);
13329 }
13330
13331#if 0 // [Robb Matzke 2021-03-17]
13332 // DQ (1/3/2007): I think this is a meaningless statement.
13333 testList.empty();
13334#endif
13335 // case 3: i=i + X or i =X +i i
13336 // TODO; what if users use i*=,etc ??
13337 // send out a warning: not canonical FOR/DO loop
13338 // or do this in the real frontend. MUST conform to canonical form
13339 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgAddOp);
13340 if (testList.size()>0)
13341 {
13342 ROSE_ASSERT(testList.size()==1);// should have only one ??
13343 // consider only the top first one
13344 SgAddOp * addop = isSgAddOp(*(testList.begin()));
13345 ROSE_ASSERT(addop!=NULL);
13346 string loopvar= (isSgVarRefExp(isSgAssignOp(addop->get_parent())->get_lhs_operand())->get_symbol()->get_name()).getString();
13347 if (isSgVarRefExp(addop->get_rhs_operand())!=NULL)
13348 {
13349 if ((isSgVarRefExp(addop->get_rhs_operand())->get_symbol()->get_name()).getString() ==loopvar)
13350 addop->set_lhs_operand(stride);
13351 else
13352 addop->set_rhs_operand(stride);
13353 }
13354 else
13355 addop->set_rhs_operand(stride);
13356 }
13357
13358 // case 3.5: i=i - X
13359 testList = NodeQuery::querySubTree(forstmt->get_increment(), V_SgSubtractOp);
13360 if (testList.size()>0)
13361 {
13362 ROSE_ASSERT(testList.size()==1);// should have only one ??
13363 // consider only the top first one
13364 SgSubtractOp * subtractop = isSgSubtractOp(*(testList.begin()));
13365 ROSE_ASSERT(subtractop!=NULL);
13366 SgVarRefExp *loopvarexp =isSgVarRefExp(SageInterface::deepCopy
13367 (isSgSubtractOp(*testList.begin())->get_lhs_operand()));
13368 SgAssignOp *assignop = isSgAssignOp((*testList.begin())->get_parent());
13369 ROSE_ASSERT(assignop !=NULL);
13370 SgPlusAssignOp *plusassignop = buildPlusAssignOp(loopvarexp, stride);
13371 assignop->set_rhs_operand(plusassignop);
13372 }
13373 }
13374 else
13375 {
13376 cerr<<"Error. SageInterface::setLoopStride(), illegal loop type:"<< loop->class_name()<<endl;
13377 ROSE_ASSERT (false);
13378
13379 }
13380}
13381
13385bool SageInterface::isAssignmentStatement(SgNode* s, SgExpression** lhs/*=NULL*/, SgExpression** rhs/*=NULL*/, bool* readlhs/*=NULL*/)
13386{
13387 SgExprStatement *n = isSgExprStatement(s);
13388 SgExpression *exp = (n != 0)? n->get_expression() : isSgExpression(s);
13389 if (exp != 0) {
13390 switch (exp->variantT()) {
13391 case V_SgPlusAssignOp:
13392 case V_SgMinusAssignOp:
13393 case V_SgAndAssignOp:
13394 case V_SgIorAssignOp:
13395 case V_SgMultAssignOp:
13396 case V_SgDivAssignOp:
13397 case V_SgModAssignOp:
13398 case V_SgXorAssignOp:
13399 case V_SgAssignOp:
13400 {
13401 SgBinaryOp* s2 = isSgBinaryOp(exp);
13402 if (lhs != 0)
13403 *lhs = s2->get_lhs_operand();
13404 if (rhs != 0) {
13405 SgExpression* init = s2->get_rhs_operand();
13406 if ( init->variantT() == V_SgAssignInitializer)
13407 init = isSgAssignInitializer(init)->get_operand();
13408 *rhs = init;
13409 }
13410 if (readlhs != 0)
13411 *readlhs = (exp->variantT() != V_SgAssignOp);
13412 return true;
13413 }
13414 default:
13415 return false;
13416 }
13417 }
13418 return false;
13419}
13420
13421
13422void
13424 {
13425 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,V_SgGotoStatement);
13426 for (size_t i = 0; i < gotos.size(); ++i)
13427 {
13428 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13429 SgLabelStatement* ls = gs->get_label();
13430 SgBasicBlock* lsParent = isSgBasicBlock(ls->get_parent());
13431 if (!lsParent) continue;
13432 SgStatementPtrList& bbStatements = lsParent->get_statements();
13433
13434 size_t j = std::find(bbStatements.begin(), bbStatements.end(), ls) - bbStatements.begin();
13435
13436 ROSE_ASSERT (j != bbStatements.size());
13437
13438 while (j < bbStatements.size() - 1 && isSgLabelStatement(bbStatements[j + 1]))
13439 {
13440 ++j;
13441 }
13442 gs->set_label(isSgLabelStatement(bbStatements[j]));
13443 }
13444 }
13445
13446bool SageInterface::mergeDeclarationAndAssignment (SgVariableDeclaration* decl, SgExprStatement* assign_stmt, bool removeAssignStmt /*= true*/)
13447{
13448 return mergeAssignmentWithDeclaration (assign_stmt, decl, removeAssignStmt);
13449}
13451
13455bool SageInterface::mergeAssignmentWithDeclaration(SgExprStatement* assign_stmt, SgVariableDeclaration* decl, bool removeAssignStmt /*= true*/)
13456{
13457 bool rt= true;
13458 ROSE_ASSERT(decl != NULL);
13459 ROSE_ASSERT(assign_stmt != NULL);
13460
13461 // Sanity check of assign statement: must be a form of var = xxx;
13462 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13463 if (assign_op == NULL)
13464 return false;
13465 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13466 if (assign_op_var == NULL) return false;
13467
13468 // Sanity check of the variable declaration: it should not have an existing initializer
13470 if (decl_var->get_initptr()!= NULL ) return false;
13471
13472 // check if two variables match
13473 // In translation, it is possible the declaration has not yet been inserted into its scope.
13474 // finding its symbol can return NULL.
13475 // But we still want to do the merge.
13476 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13477 if (decl_var_symbol!=NULL)
13478 {
13479 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13480 if (assign_op_var->get_symbol() != decl_var_symbol) return false;
13481 }
13482 else
13483 { // fallback to comparing variable names instead
13484 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13485 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name()) return false;
13486 }
13487
13488 // Everything looks fine now. Do the merge.
13490
13491 // Must preserve the proprecessing information of the original assign_stmt
13492 // use appending (not prepending) so the order of decl's comments and assign_stmt's comments can be preserved
13493 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13494
13495 // removeStatement() does not support removing a statement which is not inside a container.
13496 // But sometimes we do need to remove such a statement and replace it with a new one.
13497 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13498 // TODO: improve removeStatement() which uses low level rewritting.
13499 if (removeAssignStmt)
13500 SageInterface::removeStatement (assign_stmt);
13501// SageInterface::deepDelete (assign_stmt);
13503 decl_var->set_initptr(initor);
13504 initor->set_parent(decl_var);
13505
13506 return rt;
13507}
13508
13510{
13511 bool rt= true;
13512
13513 // Sanity check of assign statement: must be a form of var = xxx;
13514 ROSE_ASSERT(assign_stmt != NULL);
13515 SgAssignOp * assign_op = isSgAssignOp (assign_stmt->get_expression());
13516 if (assign_op == NULL)
13517 return false;
13518 SgVarRefExp* assign_op_var = isSgVarRefExp(assign_op->get_lhs_operand());
13519 if (assign_op_var == NULL)
13520 return false;
13521
13522 // Sanity check of the variable declaration: it should not have an existing initializer
13523 ROSE_ASSERT(decl != NULL);
13525 if (decl_var->get_initptr()!= NULL)
13526 return false;
13527
13528 // check if two variables match
13529 // In translation, it is possible the declaration has not yet been inserted into its scope.
13530 // finding its symbol can return NULL.
13531 // But we still want to do the merge.
13532 ROSE_ASSERT(decl_var != NULL);
13533 SgSymbol* decl_var_symbol = decl_var->get_symbol_from_symbol_table();
13534 if (decl_var_symbol != NULL) {
13535 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13536 if (assign_op_var->get_symbol() != decl_var_symbol)
13537 return false;
13538 }
13539 else
13540 { // fallback to comparing variable names instead
13541 // DQ (3/25/2017): Fixed Clang warning: warning: implicit conversion of NULL constant to 'bool' [-Wnull-conversion]
13542 if (assign_op_var->get_symbol()->get_name() != decl_var ->get_name())
13543 return false;
13544 }
13545
13546 // Everything looks fine now. Do the merge.
13547 // It is implemented by
13548 // 1. copy rhs to the decl's rhs,
13549 // 2. then move the decl to the place of the assignment,
13550 // 3. then remove the assignment
13551 //
13552 // Copy rhs to be initializer
13555 decl_var->set_initptr(initor);
13556 initor->set_parent(decl_var);
13557
13558 // move proprocessing info. attached before decl to its next statement's front, using prepending to preserve the original order
13559 SgStatement* next_stmt = SageInterface::getNextStatement (decl);
13560 SageInterface::movePreprocessingInfo(decl, next_stmt, PreprocessingInfo::before, PreprocessingInfo::before, true);
13561
13562 // removeStatement() does not support removing a statement which is not inside a container.
13563 // But sometimes we do need to remove such a statement and replace it with a new one.
13564 // As a workaround, we allow users to optionally disabling removing here and handle the removal on their own.
13565 // TODO: improve removeStatement() which uses low level rewritting.
13566
13567 // Now move the declaration to a new position, right before the assignment statement
13569 SageInterface::insertStatementBefore(assign_stmt, decl, false);
13570
13571 // preserve preprocessing info. attached to assign_stmt before removing it , using append (last false)
13572 SageInterface::movePreprocessingInfo(assign_stmt, decl, PreprocessingInfo::before, PreprocessingInfo::before, false);
13573
13574 // Original assignment statement should be removed
13575 SageInterface::removeStatement (assign_stmt);
13576 // SageInterface::deepDelete (decl);
13577
13578 return rt;
13579}
13580// Split a variable declaration with an rhs assignment into two statements: a declaration and an assignment.
13581// Return the generated assignment statement, if any
13583{
13584 SgExprStatement* rt = NULL;
13585 ROSE_ASSERT (decl != NULL);
13586
13588 SgInitializer* initor = decl_var ->get_initptr();
13589 if (initor == NULL)
13590 rt = NULL;
13591 else
13592 {
13593 // Liao, 2021/10/21, we have to support all sorts of initializers, including aggregate initializer
13594 SgExpression * rhs=NULL;
13595 if (SgAssignInitializer * ainitor = isSgAssignInitializer (initor))
13596 rhs = ainitor->get_operand();
13597 else
13598 rhs = initor;
13599
13600 // we deep copy the rhs operand
13601 rt = buildAssignStatement (buildVarRefExp(decl_var) , deepCopy(rhs));
13602 decl_var->set_initptr(NULL);
13603 //TODO clean up initor
13604 insertStatementAfter ( decl, rt );
13605 }
13606 return rt;
13607}
13609ROSE_DLL_API int SageInterface::splitVariableDeclaration (SgScopeStatement* scope, bool topLevelOnly /* = true */)
13610{
13611 int count = 0;
13612 if (!topLevelOnly)
13613 {
13614 cerr<<"SageInterface::splitVariableDeclaration() topLevelOnly == false is not yet implemented."<<endl;
13615 ROSE_ASSERT (false);
13616 }
13617
13618 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVariableDeclaration);
13619 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13620 {
13621 SgVariableDeclaration *decl= isSgVariableDeclaration(*i);
13622 if (topLevelOnly)
13623 {
13624 ROSE_ASSERT(decl != NULL);
13625 if (decl->get_scope() == scope)
13626 {
13628 count ++;
13629 }
13630 }
13631 }
13632 return count;
13633}
13634
13635void SageInterface::collectVarRefs(SgLocatedNode* root, std::vector<SgVarRefExp* > & result)
13636{
13637 ROSE_ASSERT (root != NULL);
13638// std::vector<SgVarRefExp* > result;
13639
13640 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgVarRefExp);
13641 // AST query won't find variables used in types
13643
13644 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
13645 {
13646 SgVarRefExp *vRef = isSgVarRefExp(*i);
13647 ROSE_ASSERT (vRef != NULL);
13648 result.push_back(vRef);
13649 }
13650}
13651
13652int SageInterface::collectVariableReferencesInArrayTypes(SgLocatedNode* root, Rose_STL_Container<SgNode*> & currentVarRefList)
13653{
13654 int rt = 0;
13655 ROSE_ASSERT (root != NULL);
13656 Rose_STL_Container<SgNode*> constructorList= NodeQuery::querySubTree(root, V_SgConstructorInitializer);
13657 for (size_t i =0; i< constructorList.size(); i++)
13658 {
13659 SgConstructorInitializer * c_init = isSgConstructorInitializer (constructorList[i]);
13660 if (SgArrayType* a_type = isSgArrayType(c_init->get_expression_type()))
13661 {
13662 Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree (a_type->get_index(),V_SgVarRefExp);
13663 for (size_t j =0 ; j< varList.size(); j++)
13664 {
13665 SgVarRefExp* var_exp = isSgVarRefExp(varList[j]) ;
13666 currentVarRefList.push_back(var_exp);
13667//TODO: these variable references do have special scopes, how to communicate to users?
13668// specialVarRefScopeExp[var_exp] = c_init ;
13669 rt ++;
13670 }
13671 }
13672 }
13673 return rt;
13674}
13675
13676namespace SageInterface { // A few internal helper classes
13677
13679 {
13680 SgAndOp* op;
13681
13682 public:
13683 AndOpGenerator(SgAndOp* op): op(op) {}
13684
13685 virtual SgStatement* generate(SgExpression* lhs)
13686 {
13687 if (lhs==NULL)
13688 return NULL;
13689 SgTreeCopy treeCopy;
13690 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13691 ROSE_ASSERT (lhsCopy);
13692 SgIfStmt* tree =
13699 return tree;
13700 }
13701 };
13702
13704 {
13705 SgOrOp* op;
13706
13707 public:
13708 OrOpGenerator(SgOrOp* op): op(op) {}
13709
13710 virtual SgStatement* generate(SgExpression* lhs)
13711 {
13712 if (lhs==NULL)
13713 return NULL;
13714 SgTreeCopy treeCopy;
13715 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13716 ROSE_ASSERT (lhsCopy);
13717 SgIfStmt* tree =
13724 return tree;
13725 }
13726 };
13727
13729 {
13730 SgConditionalExp* op;
13731
13732 public:
13734
13735 virtual SgStatement* generate(SgExpression* lhs)
13736 {
13737 if (lhs==NULL)
13738 return NULL;
13739 SgTreeCopy treeCopy;
13740 SgExpression* lhsCopy = isSgExpression(lhs->copy(treeCopy));
13741 ROSE_ASSERT (lhsCopy);
13742 SgIfStmt* tree =
13749 return tree;
13750 }
13751 };
13752
13753} // end of namespace for the helper classes
13754
13757{
13758 ROSE_ASSERT(from != NULL);
13759
13760#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
13761#if 0 // This is not accurate for template class specializations. We disable this assertion for now. The worst case is compilation error later.
13763 std::cerr << "Type " << from->get_type()->unparseToString() << " of expression " << from->unparseToString() << " is not copy constructible" << std::endl;
13764 ROSE_ASSERT (false);
13765 }
13766
13767 assert (SageInterface::isCopyConstructible(from->get_type())); // How do we report errors?
13768#endif
13769 SgStatement* stmt = getStatementOfExpression(from);
13770 assert (stmt);
13771 if (!isSgForInitStatement(stmt->get_parent())) {
13772 //SageInterface::ensureBasicBlockAsParent(stmt);
13773 // no return value is accepted. Only the optional transformation matters
13774 if (isBodyStatement(stmt) && !isSgBasicBlock(stmt))
13776 }
13777
13778 SgScopeStatement* parent = isSgScopeStatement(stmt->get_parent());
13779 // cout << "parent is a " << (parent ? parent->sage_class_name() : "NULL") << endl;
13780 if (!parent && isSgForInitStatement(stmt->get_parent()))
13781 parent = isSgScopeStatement(stmt->get_parent()->get_parent()->get_parent());
13782 assert (parent);
13783 // cout << "parent is a " << parent->sage_class_name() << endl;
13784 // cout << "parent is " << parent->unparseToString() << endl;
13785 // cout << "stmt is " << stmt->unparseToString() << endl;
13786 SgName varname = "rose_temp__";
13787 if (newName == "") {
13788 varname << ++SageInterface::gensym_counter;
13789 } else {
13790 varname = newName;
13791 }
13792
13793 SgType* vartype = from->get_type();
13794 SgNode* fromparent = from->get_parent();
13795 vector<SgExpression*> ancestors;
13796 for (SgExpression *expr = from, *anc = isSgExpression(fromparent); anc != 0;
13797 expr = anc, anc = isSgExpression(anc->get_parent()))
13798 {
13799 if ((isSgAndOp(anc) && expr != isSgAndOp(anc)->get_lhs_operand()) ||
13800 (isSgOrOp(anc) && expr != isSgOrOp(anc)->get_lhs_operand()) ||
13801 (isSgConditionalExp(anc) && expr != isSgConditionalExp(anc)->get_conditional_exp()))
13802 ancestors.push_back(anc); // Closest first
13803 }
13804 // cout << "This expression to split has " << ancestors.size() << " ancestor(s)" << endl;
13805 for (vector<SgExpression*>::reverse_iterator ai = ancestors.rbegin(); ai != ancestors.rend(); ++ai)
13806 {
13807 StatementGenerator* gen;
13808 switch ((*ai)->variantT()) {
13809 case V_SgAndOp:
13810 gen = new AndOpGenerator(isSgAndOp(*ai)); break;
13811 case V_SgOrOp:
13812 gen = new OrOpGenerator(isSgOrOp(*ai)); break;
13813 case V_SgConditionalExp:
13814 gen = new ConditionalExpGenerator(isSgConditionalExp(*ai)); break;
13815 default: assert (!"Should not happen"); abort();
13816 }
13818 delete gen;
13819 } // for
13820 if (ancestors.size() != 0) {
13821 return splitExpression(from);
13822 // Need to recompute everything if there were ancestors
13823 }
13824 SgVariableDeclaration* vardecl = SageBuilder::buildVariableDeclaration(varname, vartype, NULL, parent);
13826 ROSE_ASSERT (sym);
13827 SgInitializedName* initname = sym->get_declaration();
13828 ROSE_ASSERT (initname);
13830 replaceExpressionWithExpression(from, varref);
13831 // std::cout << "Unparsed 3: " << fromparent->sage_class_name() << " --- " << fromparent->unparseToString() << endl;
13832 // cout << "From is a " << from->sage_class_name() << endl;
13834 initname->set_initializer(ai);
13835 ai->set_parent(initname);
13836 myStatementInsert(stmt, vardecl, true);
13837 // vardecl->set_parent(stmt->get_parent());
13838 // FixSgTree(vardecl);
13839 // FixSgTree(parent);
13840 return ai;
13841
13842#else
13843 return NULL;
13844#endif
13845
13846} //splitExpression()
13847
13850 struct SplitStatementGenerator: public StatementGenerator {
13851 SgExpression* expr;
13852 virtual SgStatement* generate(SgExpression* answer) {
13853 using namespace SageBuilder;
13854 return buildBasicBlock(buildAssignStatement(answer, expr));
13855 }
13856 };
13857 SplitStatementGenerator gen;
13858 gen.expr = expr;
13860 }
13861
13863 Rose_STL_Container<SgNode*> gotos = NodeQuery::querySubTree(top,
13864 V_SgGotoStatement);
13865 map<SgLabelStatement*, SgLabelStatement*> labelsToReplace; for
13866 (size_t i = 0; i < gotos.size(); ++i) {
13867 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13868 SgBasicBlock* gsParent = isSgBasicBlock(gs->get_parent());
13869 if (!gsParent) continue;
13870 SgStatementPtrList& bbStatements = gsParent->get_statements();
13871 size_t j = std::find(bbStatements.begin(), bbStatements.end(), gs)
13872 - bbStatements.begin();
13873 ROSE_ASSERT (j != bbStatements.size());
13874 if (j == 0) continue;
13875 if (isSgLabelStatement(bbStatements[j - 1])) {
13876 labelsToReplace[isSgLabelStatement(bbStatements[j - 1])] =
13877 gs->get_label();
13878 }
13879 }
13880 for (size_t i = 0; i < gotos.size(); ++i) {
13881 SgGotoStatement* gs = isSgGotoStatement(gotos[i]);
13882 SgLabelStatement* oldLabel = gs->get_label();
13883 while (labelsToReplace.find(oldLabel) != labelsToReplace.end()) {
13884 oldLabel = labelsToReplace[oldLabel];
13885 }
13886 gs->set_label(oldLabel);
13887 }
13888 }
13889
13891 switch (e->variantT()) {
13892#ifdef _MSC_VER
13893 // DQ (11/28/2009): This fixes a warning in MSVC (likely p_value should be a "bool" instead of an "int").
13894 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() != 0);
13895#else
13896 case V_SgBoolValExp: return (isSgBoolValExp(e)->get_value() == true);
13897#endif
13898 case V_SgIntVal: return isSgIntVal(e)->get_value() != 0;
13899 case V_SgCastExp: return isConstantTrue(isSgCastExp(e)->get_operand());
13900 case V_SgNotOp: return isConstantFalse(isSgNotOp(e)->get_operand());
13901 case V_SgAddressOfOp: return true;
13902 default: return false;
13903 }
13904 }
13905
13907 switch (e->variantT()) {
13908 case V_SgBoolValExp: return isSgBoolValExp(e)->get_value() == false;
13909 case V_SgIntVal: return isSgIntVal(e)->get_value() == 0;
13910 case V_SgCastExp: return
13911 isConstantFalse(isSgCastExp(e)->get_operand());
13912 case V_SgNotOp: return isConstantTrue(isSgNotOp(e)->get_operand());
13913 default: return false;
13914 }
13915 }
13916
13918 SgExpression* e) {
13919 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13920 if (!fc) return false;
13921 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13922 if (fr == NULL) return false;
13923 return fr->get_symbol()->get_declaration() == decl;
13924 }
13925
13926 bool SageInterface::isCallToParticularFunction(const std::string& qualifiedName, size_t
13927 arity, SgExpression* e) {
13928 SgFunctionCallExp* fc = isSgFunctionCallExp(e);
13929 if (!fc) return false;
13930 SgFunctionRefExp* fr = isSgFunctionRefExp(fc->get_function());
13931 if (fr == NULL) return false;
13932 string name =
13933 fr->get_symbol()->get_declaration()->get_qualified_name().getString();
13934 return (name == qualifiedName &&
13935 fc->get_args()->get_expressions().size() == arity);
13936 }
13937
13939 {
13940 ROSE_ASSERT( e != NULL);
13941 // We enforce that the source expression is fully attached to the AST
13942 // Too strict, the source expression can be just built and not attached.
13943 // Liao, 9/21/2009
13944// ROSE_ASSERT( e->get_parent() != NULL);
13945 return deepCopy(e);
13946 }
13947
13949 {
13950 return deepCopy(s);
13951 }
13952
13953 //----------------- add into AST tree --------------------
13955 {
13956 ROSE_ASSERT(expList);
13957 ROSE_ASSERT(exp);
13958 expList->append_expression(exp);
13959 exp->set_parent(expList);
13960 }
13961
13962 void SageInterface::appendExpressionList(SgExprListExp *expList, const std::vector<SgExpression*>& exp)
13963 {
13964 for (size_t i = 0; i < exp.size(); ++i)
13965 appendExpression(expList, exp[i]);
13966 }
13967
13968# if 0
13969 // DQ (11/25/2011): Moved to the header file so that it could be seen as a template function.
13970
13971 // TODO consider the difference between C++ and Fortran
13972 // fixup the scope of arguments,no symbols for nondefining function declaration's arguments
13973template <class actualFunction>
13974void
13975// SageInterface::setParameterList(SgFunctionDeclaration * func,SgFunctionParameterList * paralist)
13976SageInterface::setParameterList(actualFunction * func,SgFunctionParameterList * paralist)
13977 {
13978 // DQ (11/25/2011): Modified this to be a templated function so that we can handle both
13979 // SgFunctionDeclaration and SgTemplateFunctionDeclaration (and their associated member
13980 // function derived classes).
13981
13982 ROSE_ASSERT(func);
13983 ROSE_ASSERT(paralist);
13984
13985 // Warn to users if a paralist is being shared
13986 if (paralist->get_parent() !=NULL)
13987 {
13988 cerr << "Waring! Setting a used SgFunctionParameterList to function: "
13989 << (func->get_name()).getString()<<endl
13990 << " Sharing parameter lists can corrupt symbol tables!"<<endl
13991 << " Please use deepCopy() to get an exclusive parameter list for each function declaration!"<<endl;
13992 // ROSE_ASSERT(false);
13993 }
13994
13995 // Liao,2/5/2008 constructor of SgFunctionDeclaration will automatically generate SgFunctionParameterList, so be cautious when set new paralist!!
13996 if (func->get_parameterList() != NULL)
13997 if (func->get_parameterList() != paralist)
13998 delete func->get_parameterList();
13999
14000 func->set_parameterList(paralist);
14001 paralist->set_parent(func);
14002 }
14003#endif
14004
14005// static
14006SgVariableSymbol* addArg(SgFunctionParameterList *paraList, SgInitializedName* initName, bool isPrepend)
14007 {
14008 ROSE_ASSERT(paraList != NULL);
14009 ROSE_ASSERT(initName != NULL);
14010
14011 if (isPrepend == true)
14012 paraList->prepend_arg(initName);
14013 else
14014 paraList->append_arg(initName);
14015
14016 // DQ (12/4/2011): If this is going to be set, make sure it will not be over written.
14017 // initName->set_parent(paraList);
14018 if (initName->get_parent() == NULL)
14019 initName->set_parent(paraList);
14020
14021 ROSE_ASSERT(initName->get_parent() == paraList);
14022
14023 SgFunctionDeclaration* func_decl= isSgFunctionDeclaration(paraList->get_parent());
14024
14025 // DQ (12/4/2011): This will not be true for function parameter lists in SgTemplateFunctionDeclaration cases.
14026 // Also in typical use the SgFunctionDeclaration is not known yet so the parent is not set.
14027 // ROSE_ASSERT(paraList->get_parent() != NULL);
14028 // ROSE_ASSERT(func_decl != NULL);
14029
14030 SgScopeStatement* scope = NULL;
14031 if (func_decl != NULL)
14032 {
14033 if ((func_decl->get_definingDeclaration()) == func_decl )
14034 {
14035 // defining function declaration, set scope and symbol table
14036 SgFunctionDefinition* func_def = func_decl->get_definition();
14037 ROSE_ASSERT(func_def);
14038 scope = func_def;
14039 }
14040 else
14041 {
14042 // nondefining declaration, set scope only, currently set to decl's scope, TODO
14043 scope = func_decl->get_scope();
14044 }
14045
14046 // fix up declptr of the init name
14047 initName->set_declptr(func_decl);
14048 }
14049
14050 // 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
14051 // that initName already has a scope.
14052 //
14053 // DQ (12/4/2011): Added check...(fails for case of SgTypeEllipse).
14054 // ROSE_ASSERT(initName->get_scope() != NULL);
14055 // ROSE_ASSERT(initName->get_scope() != NULL || isSgTypeEllipse(initName->get_type()) != NULL);
14056
14057 // ROSE_ASSERT (scope); -- scope may not be set because the function declaration may not have been inserted anywhere
14058
14059 initName->set_scope(scope);
14060 if (scope != NULL)
14061 {
14062 SgVariableSymbol* sym = isSgVariableSymbol(initName->get_symbol_from_symbol_table());
14063 if (sym == NULL)
14064 {
14065 sym = new SgVariableSymbol(initName);
14066 scope->insert_symbol(initName->get_name(), sym);
14067 sym->set_parent(scope->get_symbol_table());
14068 }
14069 return sym;
14070 }
14071 else
14072 {
14073 return NULL;
14074 }
14075 }
14076
14078{
14079 return addArg(paraList,initName,false);
14080}
14081
14083{
14084 return addArg(paraList,initName,true);
14085}
14086
14088{
14089 ROSE_ASSERT(decl);
14090 ROSE_ASSERT(pragma);
14091 if (decl->get_pragma()!=NULL) delete (decl->get_pragma());
14092 decl->set_pragma(pragma);
14093 pragma->set_parent(decl);
14094}
14095
14096
14098//TODO should we ensureBasicBlockAsScope(scope) ? like ensureBasicBlockAsParent(targetStmt);
14099//It might be well legal to append the first and only statement in a scope!
14101 {
14102 // DQ (4/3/2012): Simple globally visible function to call (used for debugging in ROSE).
14103 void testAstForUniqueNodes ( SgNode* node );
14104
14105#if 0
14106 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14107#endif
14108
14109 // DQ (6/19/2012): Exit as a test...
14110 // ROSE_ASSERT(isSgClassDeclaration(stmt) == NULL);
14111
14112 if (scope == NULL)
14113 {
14114#if 0
14115 printf (" --- scope was not specified as input! \n");
14116#endif
14118 }
14119
14120 ROSE_ASSERT(stmt != NULL);
14121 ROSE_ASSERT(scope != NULL);
14122
14123#if 0
14124 printf ("In SageInterface::appendStatement(): stmt = %p = %s scope = %p = %s \n",stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14125#endif
14126
14127#if 0
14128 // DQ (2/2/2010): This fails in the projects/OpenMP_Translator "make check" tests.
14129 // DQ (1/2/2010): Introducing test that are enforced at lower levels to catch errors as early as possible.
14130 SgDeclarationStatement* declarationStatement = isSgDeclarationStatement(stmt);
14131 if (declarationStatement != NULL)
14132 {
14133 ROSE_ASSERT(declarationStatement->get_firstNondefiningDeclaration() != NULL);
14134 ROSE_ASSERT(declarationStatement->get_definingDeclaration() != NULL);
14135 }
14136#endif
14137
14138#if 0
14139 // This fix breaks other transformations.
14140 // It is better to do this explicitly as needed before calling appendStatement();
14141 // Liao 10/19/2010
14142 // In rare cases, we are moving the statement from its original scope to another scope
14143 // We have to remove it from its original scope before append it to the new scope
14144 SgNode* old_parent= stmt->get_parent();
14145 if (old_parent)
14146 {
14147 removeStatement(stmt);
14148 }
14149#endif
14150
14151#if 0
14152 // catch-all for statement fixup
14153 // Must fix it before insert it into the scope,
14154 fixStatement(stmt,scope);
14155
14156 //-----------------------
14157 // append the statement finally
14158 // scope->append_statement (stmt);
14159 scope->insertStatementInScope(stmt,false);
14160 stmt->set_parent(scope); // needed?
14161#else
14162 // DQ (7/12/2012): Skip adding when this is a non-autonomous type declaration.
14163 bool skipAddingStatement = false;
14164 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
14165 if (classDeclaration != NULL)
14166 {
14167 // DQ (7/9/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14168#if 0
14169 if (classDeclaration->get_parent() != NULL)
14170 {
14171 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());
14172 }
14173#endif
14174
14175#if 1
14176 // DQ (6/9/2013): This is the original code...
14177 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false);
14178#else
14179 // 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).
14180 // This fails to add enough statements to the AST.
14181 skipAddingStatement = (classDeclaration->get_isAutonomousDeclaration() == false) || (classDeclaration->get_parent() != NULL);
14182#endif
14183
14184 // DQ (6/26/2013): Don't just check for SgTemplateInstantiationDecl, but also for SgClassDeclaration.
14185 // DQ (6/9/2013): Check if this is a SgTemplateInstantiationDecl, since it might be appearing
14186 // twice as a result of a template argument being instantiated and we only want to add it into
14187 // the scope once. This happens for test2013_198.C and I can't find a better solution.
14188 if (classDeclaration != NULL && scope->containsOnlyDeclarations() == true)
14189 {
14190 // Check if this instnatiated template has already been added to the scope.
14191
14192 // DQ (6/26/2013): This is a newer alternative to test for an existing statement in a scope.
14193 // const SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
14194 // SgDeclarationStatementPtrList::const_iterator existingDeclaration = find(declarationList.begin(),declarationList.end(),classDeclaration);
14195 bool statementAlreadyExistsInScope = scope->statementExistsInScope(classDeclaration);
14196 if (statementAlreadyExistsInScope == true)
14197 {
14198 if (isSgTemplateInstantiationDecl(classDeclaration) != NULL)
14199 {
14200// DQ (9/13/2014): Clean up this output when not printing developer warnings.
14201// #if 1
14202#if PRINT_DEVELOPER_WARNINGS
14203 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",
14204 classDeclaration,classDeclaration->class_name().c_str(),scope,scope->class_name().c_str());
14205#endif
14206 }
14207#if 1
14208 else
14209 {
14210#if 1
14211 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",
14212 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14213#endif
14214 }
14215#endif
14216 skipAddingStatement = true;
14217 }
14218 }
14219 }
14220 else
14221 {
14222 SgEnumDeclaration* enumDeclaration = isSgEnumDeclaration(stmt);
14223 if (enumDeclaration != NULL)
14224 {
14225 // DQ (7/12/2012): We only skip the attachment of the class declaration to the scope if it is NOT and autonomous declaration.
14226 skipAddingStatement = (enumDeclaration->get_isAutonomousDeclaration() == false);
14227 }
14228 }
14229
14230#if 0
14231 // DQ (6/26/2013): This is an attempt to support better testing of possible redundant statements
14232 // that would be inserted into the current scope. This is however a bit expensive so we are using
14233 // this as a way to also debug the new cases where this happens.
14234 bool statementAlreadyExistsInScope = scope->statementExistsInScope(stmt);
14235 if (skipAddingStatement == false && statementAlreadyExistsInScope == true)
14236 {
14237#if 0
14238 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",
14239 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14240#endif
14241#if 0
14242 printf ("Exiting as a test! \n");
14243 ROSE_ABORT();
14244#endif
14245 skipAddingStatement = true;
14246 }
14247#endif
14248
14249#if 0
14250 printf (" --- skipAddingStatement = %s \n",skipAddingStatement ? "true" : "false");
14251#endif
14252
14253 if (skipAddingStatement == false)
14254 {
14255 // catch-all for statement fixup
14256 // Must fix it before insert it into the scope,
14257 // printf ("In appendStatementList(): Calling fixStatement() \n");
14258 fixStatement(stmt,scope);
14259 // printf ("DONE: In appendStatementList(): Calling fixStatement() \n");
14260
14261 //-----------------------
14262 // append the statement finally
14263 // scope->append_statement (stmt);
14264#if 0
14265 printf (" --- calling insertStatementInScope(): scope = %p = %s stmt = %p = %s \n",scope,scope->class_name().c_str(),stmt,stmt->class_name().c_str());
14266#endif
14267 scope->insertStatementInScope(stmt,false);
14268
14269 // DQ (6/9/2013): Added comment only: This is needed because some declaration have to have the
14270 // setting of there paremtn pointes delayed until now based on if they appear nested inside of
14271 // other declarations (e.g. "typedef struct { int x; } y;").
14272 stmt->set_parent(scope); // needed?
14273 }
14274#endif
14275
14276 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14277 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14278 // this). Also since this is only operating within a single scope it is likely too specific to C
14279 // instead of addressing the details of C++ where functions can be placed in alternative scopes and
14280 // use name qualification).
14281 // update the links after insertion!
14283 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14284 {
14285 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14286 }
14287
14288#if 0
14289 // DQ (6/26/2013): Turn on this test for debugging ROSE compiling rose.h header file.
14290 // Note that this is a stronger AST subtree test and not the weaker test for a redundant
14291 // statement in a single scope.
14292 // DQ (9/1/2012): this is a debugging mode that we need to more easily turn on and off.
14293 // DQ (4/3/2012): Added test to make sure that the pointers are unique.
14294 testAstForUniqueNodes(scope);
14295#else
14296 // printf ("In SageInterface::appendStatement(): Skipping test for unique statements in subtree \n");
14297#endif
14298 }
14299
14302{
14303 ROSE_ASSERT (stmt != NULL);
14304 ROSE_ASSERT (for_init_stmt != NULL);
14305
14306#if 0
14307 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());
14308#endif
14309
14310 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14311 // to record it being moved (and thus the macroExpansions that it might be associated with having
14312 // to force the macroExpansion's associated statements to be marked as a transformation.
14314
14315#if 0
14316 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());
14317#endif
14318
14319 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14320 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14321 // prepend, we only need to look at the scope.
14323
14324 for_init_stmt->append_init_stmt (stmt);
14325}
14326
14327void
14328SageInterface::appendStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14329 {
14330 for (size_t i = 0; i < stmts.size(); ++i)
14331 {
14332#if 0
14333#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14334 printf ("In appendStatementList(): stmts[i = %" PRIuPTR "] = %p = %s \n",i,stmts[i],stmts[i]->class_name().c_str());
14335 // printf ("In appendStatementList(): stmts[i = %" PRIuPTR "]->get_parent() = %p \n",i,stmts[i]->get_parent());
14336#endif
14337#endif
14338 appendStatement(stmts[i], scope); // Liao 5/15/2013, defer the logic of checking parent pointers to appendStatement()
14339#if 0
14340 if (stmts[i]->get_parent() != NULL)
14341 {
14342#if 0
14343#ifdef ROSE_DEBUG_NEW_EDG_ROSE_CONNECTION
14344 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());
14345#endif
14346#endif
14347 appendStatement(stmts[i], scope);
14348 }
14349 else
14350 {
14351 printf (" --- WARNING: In appendStatementList(): stmts[i = %" PRIuPTR "] not added to scope (because stmts[i]->get_parent() == NULL) \n",i);
14352 }
14353#endif
14354 }
14355 }
14356
14359 {
14360 ROSE_ASSERT (stmt != NULL);
14361
14362#if 0
14363 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p \n",stmt,stmt->class_name().c_str(),scope);
14364#endif
14365
14366 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.1") == false);
14367
14368 if (scope == NULL)
14369 {
14371 }
14372
14373 ROSE_ASSERT(scope != NULL);
14374 // TODO handle side effect like SageBuilder::appendStatement() does
14375
14376 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.1a") == false);
14377
14378 // Must fix it before insert it into the scope,
14379 // otherwise assertions in insertStatementInScope() would fail
14380 fixStatement(stmt,scope);
14381
14382#if 0
14383 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: stmt) \n",
14384 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14385#endif
14386
14387 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.2") == false);
14388
14389 // DQ (12/1/2015): If this is a moved statement then cause it to update internal data structures
14390 // to record it being moved (and thus the macroExpansions that it might be associated with having
14391 // to force the macroExpansion's associated statements to be marked as a transformation.
14393
14394#if 0
14395 printf ("In SageInterface::prependStatement(): stmt = %p = %s scope = %p = %s (resetInternalMapsForTargetStatement: scope) \n",
14396 stmt,stmt->class_name().c_str(),scope,scope->class_name().c_str());
14397#endif
14398
14399 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.3") == false);
14400
14401 // DQ (12/1/2015): Also look at the statements on either side of the location where this statement
14402 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14403 // prepend, we only need to look at the scope.
14405
14406#if 0
14407 printf ("Calling insertStatementInScope() \n");
14408#endif
14409
14410 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(stmt,"testing prependStatement(): 2.2.6.1.2.4") == false);
14411 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.4a") == false);
14412
14413 scope->insertStatementInScope(stmt,true);
14414 stmt->set_parent(scope); // needed?
14415
14416 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.5") == false);
14417
14418 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14419 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14420 // this). Also since this is only operating within a single scope it is likely too specific to C
14421 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14422 // use name qualification).
14423 // update the links after insertion!
14425 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(stmt) != NULL) )
14426 {
14427 updateDefiningNondefiningLinks(isSgFunctionDeclaration(stmt),scope);
14428 }
14429
14430 // ROSE_ASSERT(findFirstSgCastExpMarkedAsTransformation(scope,"testing prependStatement(): 2.2.6.1.2.6") == false);
14431
14432#if 0
14433 printf ("Leaving SageInterface::prependStatement() \n");
14434#endif
14435 } // prependStatement()
14436
14437
14440{
14441 ROSE_ASSERT (stmt != NULL);
14442 ROSE_ASSERT (for_init_stmt != NULL);
14443
14444#if 0
14445 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());
14446#endif
14447
14448 // DQ (12/2/2015): If this is a moved statement then cause it to update internal data structures
14449 // to record it being moved (and thus the macroExpansions that it might be associated with having
14450 // to force the macroExpansion's associated statements to be marked as a transformation.
14452
14453#if 0
14454 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());
14455#endif
14456
14457 // DQ (12/2/2015): Also look at the statements on either side of the location where this statement
14458 // is being inserted to make sure that they are not a part of a macro expansion. In the case of
14459 // prepend, we only need to look at the scope.
14461
14462 for_init_stmt->prepend_init_stmt (stmt);
14463}
14464
14465void SageInterface::prependStatementList(const std::vector<SgStatement*>& stmts, SgScopeStatement* scope)
14466 {
14467 for (size_t i = stmts.size(); i > 0; --i)
14468 {
14469 prependStatement(stmts[i - 1], scope);
14470 }
14471 }
14472
14477{
14478 bool rt = false;
14479 ROSE_ASSERT (scope != NULL);
14480 switch (scope->variantT())
14481 {
14482 case V_SgBasicBlock:
14483 case V_SgClassDefinition:
14484 case V_SgFunctionDefinition:
14485 case V_SgGlobal:
14486 case V_SgNamespaceDefinitionStatement: //?
14487 rt = true;
14488 break;
14489
14490 case V_SgAssociateStatement :
14491 case V_SgBlockDataStatement :
14492 case V_SgCatchOptionStmt:
14493 case V_SgDoWhileStmt:
14494 case V_SgForAllStatement:
14495 case V_SgForStatement:
14496 case V_SgFortranDo:
14497 case V_SgIfStmt:
14498 case V_SgSwitchStatement:
14499 case V_SgUpcForAllStatement:
14500 case V_SgWhileStmt:
14501 rt = false;
14502 break;
14503
14504 default:
14505 cout<<"unrecognized or unhandled scope type for SageInterface::hasSimpleChildrenList() "<<endl;
14506 break;
14507 }
14508 return rt;
14509}
14510
14511
14512// 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.
14514 {
14515 // When inserting a statement into global scope, if inserting at the top of scope it is best to insert
14516 // after the last statement from the preinclude file rose_edg_required_macros_and_functions.h.
14517
14518 SgDeclarationStatementPtrList & declarationList = globalScope->get_declarations();
14519
14520 SgStatement* last_statement = NULL;
14521 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
14522 // while (i != declarationList.end())
14523 while (i != declarationList.end() && (*i)->get_file_info() != NULL && (*i)->get_file_info()->isFrontendSpecific() == true)
14524 {
14525#if 0
14526 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");
14527#endif
14528 last_statement = *i;
14529
14530 i++;
14531 }
14532
14533 ROSE_ASSERT(last_statement != NULL);
14534#if 1
14535 printf ("last_statement = %p = %s \n",last_statement,last_statement->class_name().c_str());
14536#endif
14537#if 0
14538 printf ("Exiting as a test! \n");
14539 ROSE_ABORT();
14540#endif
14541
14542 return last_statement;
14543 }
14544
14545
14546 //TODO handle more side effect like SageBuilder::append_statement() does
14547 //Merge myStatementInsert()
14548 // insert SageInterface::insertStatement()
14549void SageInterface::insertStatement(SgStatement *targetStmt, SgStatement* newStmt, bool insertBefore, bool autoMovePreprocessingInfo /*= true */)
14550 {
14551 ROSE_ASSERT(targetStmt &&newStmt);
14552 ROSE_ASSERT(targetStmt != newStmt); // should not share statement nodes!
14553
14554 if (isSgGlobal(targetStmt) ||
14555 isSgClassDefinition(targetStmt)||
14556 isSgNamespaceDefinitionStatement(targetStmt)||
14557 isSgFunctionParameterList(targetStmt)||
14558 isSgFunctionDefinition(targetStmt)||
14559 isSgCtorInitializerList(targetStmt))
14560 {
14561 string className = targetStmt->class_name();
14562 string err_msg = "targetStmt cannot be a " + className + ". Its parent does not implement insert_child(). Please revise your code to avoid inserting a stmt as a sibling of this type of targetStmt.";
14563 cerr<<err_msg<<endl;
14564 ROSE_ASSERT (false);
14565 }
14566
14567#if 0 // it is allowed to have different types of statements inserted after SgCaseOptionStmt
14568 if (isSgCaseOptionStmt(targetStmt))
14569 {
14570 if (!isSgCaseOptionStmt(newStmt))
14571 {
14572 cerr<<"Target statment is a case option stmt. The new stmt should also be the same type to be a sibling. But it is "<< newStmt->class_name() << " instead. This is not semantically correct." <<endl;
14573 ROSE_ASSERT(false);
14574 }
14575 }
14576#endif
14577 SgNode* parent = targetStmt->get_parent();
14578 if (parent == NULL)
14579 {
14580 cerr << "Empty parent pointer for target statement. May be caused by the wrong order of target and new statements in insertStatement(targetStmt, newStmt)"<<endl;
14581 ROSE_ASSERT(parent);
14582 }
14583
14584 // Issuing an error due to variable initialization inside a switch statement block without enclosing braces {}.
14585 //
14586 // This is a tricky situation: C++ allows a flat list of statements following case option statement, even though they are indented
14587 //case HORIZONTAL_TAB:
14588 // foundHorizontalTab = true;
14589 // break;
14590 // case VERTICAL_TAB:
14591 // foundVerticalTab = true;
14592 // break;
14593 // ...
14594 //
14595 // Unparser will flatten them out.
14596 //
14597 // when we try to inserat a variable decl stmt into the list after case option statement, compilers will complain
14598 // error: jump to case label
14599 // crosses initialization of "int variablexyz"
14600 //
14601 //
14602 // if targetStmt's parent is SgCaseOptionStmt,
14603 if (SgCaseOptionStmt * case_opt_stmt = isSgCaseOptionStmt(parent))
14604 {
14605 if (SgVariableDeclaration* var_stmt = isSgVariableDeclaration(newStmt))
14606 {
14607 cerr<<"Error: you cannot insert a variable declaration stmt inside a case option statement without enclosing brances in between."<<endl;
14608 cerr<<"parent of target is a case option stmt:"<<parent <<endl;
14609 cerr<<"new statement is a variable statement:"<<newStmt <<endl;
14610 ASSERT_require(false);
14611 }
14612 }
14613
14614 if (isSgLabelStatement(parent) != nullptr)
14615 {
14616 SgLabelStatement* labelStatement = isSgLabelStatement(parent);
14617 parent = labelStatement->get_parent();
14618 ROSE_ASSERT(isSgLabelStatement(parent) == NULL);
14619 }
14620
14621 if (isSgFunctionDefinition(parent) ||
14622 isSgTypedefDeclaration(parent) ||
14623 isSgSwitchStatement(parent) ||
14624 isSgVariableDeclaration(parent))
14625 {
14626 string className = parent->class_name();
14627 string err_msg = "targetStmt's parent cannot be a " + className + ". This parent does not implement insert() function. Please revise your code to avoid inserting a stmt as a child of this type of parent.";
14628 cerr<<err_msg<<endl;
14629 if (SgSwitchStatement * switch_stmt = isSgSwitchStatement(parent))
14630 {
14631 if (switch_stmt->get_item_selector() == targetStmt)
14632 {
14633 cerr<<"The target statement is the item selector of a switch statement. You cannot insert any statement before or after it."<<endl;
14634 }
14635 }
14636
14637 ROSE_ASSERT (false);
14638 }
14639
14640#if 0
14641 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());
14642#endif
14643
14644 // DQ (12/2/2014): Not sure why this was here in the first place (likely debugging code from the fix for the SgLableStatement insertion.
14645 // SgFunctionDefinition* functionDefinition = SageInterface::getEnclosingProcedure(targetStmt);
14646 // ROSE_ASSERT(functionDefinition != NULL);
14647
14648 // Liao 3/2/2012. The semantics of ensureBasicBlockAsParent() are messy. input targetStmt may be
14649 // returned as it is if it is already a basic block as a body of if/while/catch/ etc.
14650 // We now have single statement true/false body for IfStmt etc
14651 // However, IfStmt::insert_child() is ambiguous and not implemented
14652 // So we make SgBasicBlock out of the single statement and
14653 // essentially call SgBasicBlock::insert_child() instead.
14654 // TODO: add test cases for If, variable, variable/struct inside if, etc
14655 // parent = ensureBasicBlockAsParent(targetStmt);
14656
14657 // must get the new scope after ensureBasicBlockAsParent ()
14658 SgScopeStatement* scope = targetStmt->get_scope();
14659 ROSE_ASSERT(scope);
14660
14661#if 0
14662 printf ("targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14663 printf ("scope = %p = %s \n",scope,scope->class_name().c_str());
14664#endif
14665
14666 // DQ (11/16/2014): This step is problematic if the targetStmt has been transformed to be associated with a SgLabelStatement.
14667 // The reason is that the targetStmt's parent will have been reset to be the SgLabelStatement and the logic in the set_parent()
14668 // function will assert fail when the parent is being set to itself (which is a good idea in general). A better solution might
14669 // 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
14670 // more sense in this special case of a SgLabelStatement.
14671 // newStmt->set_parent(targetStmt->get_parent());
14672 newStmt->set_parent(scope);
14673
14674 // 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.
14675 // The fix was the reuse the one that was found.
14676 fixStatement(newStmt,scope);
14677
14678 // DQ (9/16/2010): Added assertion that appears to be required to be true.
14679 // However, if this is required to be true then what about statements in
14680 // SgStatementExpression IR nodes?
14681 ROSE_ASSERT(isSgStatement(parent) != NULL);
14682
14683 // DQ (9/16/2010): Added support to move comments and CPP directives marked to
14684 // appear before the statement to be attached to the inserted statement (and marked
14685 // to appear before that statement).
14686 ROSE_ASSERT(targetStmt != NULL);
14687 AttachedPreprocessingInfoType* comments = targetStmt->getAttachedPreprocessingInfo();
14688
14689#if 0
14690 printf ("In SageInterface::insertStatement(): after checking for associated comments \n");
14691 reportNodesMarkedAsModified(scope);
14692#endif
14693
14694 // TODO refactor this portion of code into a separate function
14695 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14696 // I think that special rules apply to inserting a SgBasicBlock so disable comment reloation when inserting a SgBasicBlock.
14697 if (autoMovePreprocessingInfo) // Do this only if automatically handling of preprocessing information is request by users
14698 {
14699 if (comments != NULL && isSgBasicBlock(newStmt) == NULL)
14700 {
14701 vector<int> captureList;
14702#if 0
14703 printf ("Found attached comments (at %p = %s, inserting %p = %s insertBefore = %s): comments->size() = %" PRIuPTR " \n",
14704 targetStmt,targetStmt->class_name().c_str(),newStmt,newStmt->class_name().c_str(),insertBefore ? "true" : "false",comments->size());
14705#endif
14706 // DQ (9/17/2010): Assert that the new statement being inserted has no attached comments or CPP directives.
14707 if (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false)
14708 {
14709 // If the inserted statment has attached comments or CPP directives then this is gets a little
14710 // bit more comple and we don't support that at present.
14711 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");
14712 }
14713 // DQ (9/17/2010): commented out because it fails test in projects/OpenMP_Translator/for_firstprivate.c
14714 ROSE_ASSERT((newStmt->getAttachedPreprocessingInfo() == NULL) || (newStmt->getAttachedPreprocessingInfo() != NULL && newStmt->getAttachedPreprocessingInfo()->empty() == false));
14715
14716 int commentIndex = 0;
14717 AttachedPreprocessingInfoType::iterator i;
14718 for (i = comments->begin(); i != comments->end(); i++)
14719 {
14720 ROSE_ASSERT ( (*i) != NULL );
14721#if 0
14722 printf (" Attached Comment (relativePosition=%s): %s\n",
14723 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
14724 (*i)->getString().c_str());
14725 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
14726 (*i)->get_file_info()->display("comment/directive location");
14727#endif
14728 PreprocessingInfo::RelativePositionType relativePosition = (insertBefore == true) ? PreprocessingInfo::before : PreprocessingInfo::after;
14729 if ((*i)->getRelativePosition() == relativePosition)
14730 {
14731 // accumulate into list
14732 captureList.push_back(commentIndex);
14733 }
14734
14735 commentIndex++;
14736 }
14737
14738 // printf ("captureList.size() = %" PRIuPTR " \n",captureList.size());
14739 if (captureList.empty() == false)
14740 {
14741 // Remove these comments and/or CPP directives and put them into the previous statement (marked to be output after the statement).
14742 // SgStatement* surroundingStatement = (insertBefore == true) ? getPreviousStatement(targetStmt) : getNextStatement(targetStmt);
14743 // SgStatement* surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14744 SgStatement* surroundingStatement = newStmt;
14745 ROSE_ASSERT(surroundingStatement != targetStmt);
14746 ROSE_ASSERT(surroundingStatement != NULL);
14747#if 0
14748 if (surroundingStatement == NULL)
14749 {
14750 // printf ("Warning: the surrounding statement for insertBefore = %s is NULL (so use the newStmt) \n",insertBefore ? "true" : "false");
14751 surroundingStatement = (insertBefore == true) ? newStmt : newStmt;
14752 }
14753#endif
14754 // Now add the entries from the captureList to the surroundingStatement and remove them from the targetStmt.
14755 // printf ("This is a valid surrounding statement = %s for insertBefore = %s \n",surroundingStatement->class_name().c_str(),insertBefore ? "true" : "false");
14756 vector<int>::iterator j = captureList.begin();
14757 while (j != captureList.end())
14758 {
14759 // Add the captured comments to the new statement. Likely we need to make sure that the order is preserved.
14760 // printf ("Attaching comments to newStmt = %p = %s \n",newStmt,newStmt->class_name().c_str());
14761 newStmt->addToAttachedPreprocessingInfo((*comments)[*j]);
14762
14763 // Remove them from the targetStmt. (set them to NULL and then remove them in a separate step).
14764 // printf ("Removing entry from comments list on targetStmt = %p = %s \n",targetStmt,targetStmt->class_name().c_str());
14765 (*comments)[*j] = NULL;
14766
14767 j++;
14768 }
14769
14770 // Now remove each NULL entries in the comments vector.
14771 // Because of iterator invalidation we must reset the iterators after each call to erase (I think).
14772 for (size_t n = 0; n < captureList.size(); n++)
14773 {
14774 AttachedPreprocessingInfoType::iterator k = comments->begin();
14775 while (k != comments->end())
14776 {
14777 // Only modify the list once per iteration over the captureList
14778 if (*k == NULL)
14779 {
14780 comments->erase(k);
14781 break;
14782 }
14783 k++;
14784 }
14785 }
14786 }
14787 }
14788 else
14789 {
14790 // printf ("No attached comments (at %p of type: %s): \n",targetStmt,targetStmt->class_name().c_str());
14791 // DQ (9/17/2010): Trying to eliminate failing case in OpenMP projects/OpenMP_Translator/tests/npb2.3-omp-c/LU/lu.c
14792 // I think that special rules apply to inserting a SgBasicBlock so disable comment relocation when inserting a SgBasicBlock.
14793 if (comments != NULL)
14794 {
14795 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");
14796 }
14797 }
14798 } // end if autoMovePreprocessingInfo
14799
14800
14801#if 0
14802 printf ("In SageInterface::insertStatement(): after processing associated comments \n");
14803 reportNodesMarkedAsModified(scope);
14804#endif
14805
14806 if (isSgIfStmt(parent))
14807 {
14808 if (isSgIfStmt(parent)->get_conditional()==targetStmt)
14809 {
14810 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14811 }
14812 else
14813 {
14814 if (isSgIfStmt(parent)->get_true_body()==targetStmt)
14815 {
14816 // Liao 3/2/2012
14817 // We have some choices:
14818 // 1) if the targeStmt is a basic block, we can append/prepend the new stmt
14819 // within the targetStmt. But this is not the exact semantics of insertStatment. It will break the outliner.
14820 // Since the targetStmt will have new content inside of it, which is not the semantics of
14821 // inserting anything before/or after it.
14822 // 2) always insert a padding basic block between parent and targetStmt
14823 // and we can legally insert before/after the target statement within the
14824 // padding basic block.
14825 //TODO: this insertion of padding basic block should ideally go into some AST normalization phase
14826 // so the transformation function (insertStatement) only does what it means to do, no more and no less.
14827 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14828 isSgIfStmt(parent)->set_true_body(newparent);
14829 newparent->set_parent(parent);
14830 insertStatement(targetStmt, newStmt,insertBefore);
14831 }
14832 else
14833 {
14834 if (isSgIfStmt(parent)->get_false_body()==targetStmt)
14835 {
14836 // ensureBasicBlockAsParent(targetStmt);
14837 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14838 isSgIfStmt(parent)->set_false_body(newparent);
14839 newparent->set_parent(parent);
14840 insertStatement(targetStmt, newStmt,insertBefore);
14841 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14842 }
14843 }
14844 }
14845 }
14846 else
14847 {
14848 if (isSgWhileStmt(parent))
14849 {
14850 if (isSgWhileStmt(parent)->get_condition()==targetStmt)
14851 {
14852 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14853 }
14854 else
14855 {
14856 if (isSgWhileStmt(parent)->get_body()==targetStmt)
14857 {
14858 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14859 isSgWhileStmt(parent)->set_body(newparent);
14860 newparent->set_parent(parent);
14861 insertStatement(targetStmt, newStmt,insertBefore);
14862 // ensureBasicBlockAsParent(targetStmt);
14863 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14864 }
14865 }
14866 }
14867 else
14868 {
14869 if (isSgDoWhileStmt(parent))
14870 {
14871 if (isSgDoWhileStmt(parent)->get_condition()==targetStmt)
14872 {
14873 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14874 }
14875 else
14876 {
14877 if (isSgDoWhileStmt(parent)->get_body()==targetStmt)
14878 {
14879 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14880 isSgDoWhileStmt(parent)->set_body(newparent);
14881 newparent->set_parent(parent);
14882 insertStatement(targetStmt, newStmt,insertBefore);
14883 // ensureBasicBlockAsParent(targetStmt);
14884 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14885 }
14886 }
14887 }
14888 else
14889 {
14890 if (isSgForStatement(parent))
14891 {
14892 if (isSgForStatement(parent)->get_loop_body()==targetStmt)
14893 {
14894 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14895 isSgForStatement(parent)->set_loop_body(newparent);
14896 newparent->set_parent(parent);
14897 insertStatement(targetStmt, newStmt,insertBefore);
14898 // ensureBasicBlockAsParent(targetStmt);
14899 // insertStatement(isSgStatement(parent),newStmt,insertBefore);
14900 }
14901 else
14902 {
14903 if (isSgForStatement(parent)->get_test()==targetStmt)
14904 {
14905 insertStatement(isSgStatement(parent),newStmt,insertBefore);
14906 }
14907 }
14908 }
14909 else // \pp (2/24/2011) added support for UpcForAll
14910 {
14911 if (SgUpcForAllStatement* p = isSgUpcForAllStatement(parent))
14912 {
14913 //const bool stmt_present = (p->get_loop_body() == targetStmt || p->get_test() == targetStmt);
14914
14915 // \pp \todo what if !stmt_present
14916 // ROSE_ASSERT(stmt_present != NULL);
14917 insertStatement(p, newStmt, insertBefore);
14918 }
14919 else
14920 {
14921 if (SgOmpBodyStatement * p = isSgOmpBodyStatement (parent))
14922 {
14923 SgBasicBlock* newparent = buildBasicBlock (targetStmt);
14924 p->set_body(newparent);
14925 newparent->set_parent(parent);
14926 insertStatement(targetStmt, newStmt,insertBefore);
14927 }
14928 else
14929 {
14930 // It appears that all of the recursive calls are untimately calling this location.
14931 SgStatement* stmnt = isSgStatement(parent);
14932 ROSE_ASSERT(stmnt != NULL);
14933 stmnt->insert_statement(targetStmt,newStmt,insertBefore);
14934 }
14935 }
14936 }
14937 }
14938 }
14939 }
14940
14941 // DQ (11/19/2012): If we are building the AST within the front-end then don't do this expensive
14942 // fixup (we already set it properly in the AST construction within the frontend so we don't need
14943 // this). Also since this is only operating within a single scope it is likely too specific to C
14944 // instead of addessing the details of C++ where functions can be placed in alternative scopes and
14945 // use name qualification).
14946 // update the links after insertion!
14948 if ( (scp != e_sourcePositionFrontendConstruction) && (isSgFunctionDeclaration(newStmt) != NULL) )
14949 {
14950 updateDefiningNondefiningLinks(isSgFunctionDeclaration(newStmt),scope);
14951 }
14952
14953#if 0
14954 printf ("In SageInterface::insertStatement(): at BASE of function \n");
14955 reportNodesMarkedAsModified(scope);
14956#endif
14957 }
14958
14959
14960void SageInterface::insertStatementList(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts, bool insertBefore)
14961 {
14962 if (insertBefore)
14963 {
14964 for (size_t i = 0; i < newStmts.size(); ++i)
14965 {
14966 insertStatementBefore(targetStmt, newStmts[i]);
14967 }
14968 }
14969 else
14970 {
14971 for (size_t i = newStmts.size(); i > 0; --i)
14972 {
14973 insertStatementAfter(targetStmt, newStmts[i - 1]);
14974 }
14975 }
14976 }
14977
14978void SageInterface::insertStatementAfter(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true*/)
14979 {
14980 insertStatement(targetStmt,newStmt,false, autoMovePreprocessingInfo);
14981 }
14982
14983void SageInterface::insertStatementListAfter(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
14984 {
14985 insertStatementList(targetStmt,newStmts,false);
14986 }
14987
14990 {
14991 ROSE_ASSERT (stmt != NULL);
14992 ROSE_ASSERT (scope != NULL);
14993 // Insert to be the declaration after current declaration sequence, if any
14994 SgStatement* l_stmt = findLastDeclarationStatement (scope);
14995 if (l_stmt)
14996 insertStatementAfter(l_stmt,stmt);
14997 else
14998 prependStatement(stmt, scope);
14999 }
15000
15002void SageInterface::insertStatementAfterLastDeclaration(std::vector<SgStatement*> stmt_list, SgScopeStatement* scope)
15003 {
15004 ROSE_ASSERT (scope != NULL);
15005 vector <SgStatement* >::iterator iter;
15006 SgStatement* prev_stmt = NULL;
15007 for (iter= stmt_list.begin(); iter != stmt_list.end(); iter++)
15008 {
15009 if (iter == stmt_list.begin())
15010 {
15012 }
15013 else
15014 {
15015 ROSE_ASSERT (prev_stmt != NULL);
15016 insertStatementAfter (prev_stmt, *iter);
15017 }
15018 prev_stmt = *iter;
15019 }
15020 }
15021
15023{
15024 ROSE_ASSERT(newStmt!=NULL);
15025 ROSE_ASSERT(scope!=NULL);
15026 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
15027 if (!isSgDeclarationStatement(targetStmt)) {
15028 insertStatementBefore(targetStmt, newStmt, movePreprocessingInfo);
15029 return;
15030 }
15031 }
15032 appendStatement(newStmt, scope);
15033}
15034
15035void SageInterface::insertStatementListBeforeFirstNonDeclaration(const std::vector<SgStatement*> &newStmts,SgScopeStatement *scope)
15036{
15037 ROSE_ASSERT(scope!=NULL);
15038 BOOST_FOREACH (SgStatement *targetStmt, scope->generateStatementList()) {
15039 if (!isSgDeclarationStatement(targetStmt)) {
15040 insertStatementListBefore(targetStmt, newStmts);
15041 return;
15042 }
15043 }
15044 appendStatementList(newStmts, scope);
15045}
15046
15047void SageInterface::insertStatementBefore(SgStatement *targetStmt, SgStatement* newStmt, bool autoMovePreprocessingInfo /*= true */)
15048 {
15049 insertStatement(targetStmt,newStmt,true, autoMovePreprocessingInfo);
15050 }
15051
15052void SageInterface::insertStatementListBefore(SgStatement *targetStmt, const std::vector<SgStatement*>& newStmts)
15053 {
15054 insertStatementList(targetStmt,newStmts,true);
15055 }
15056
15057 //a wrapper for set_expression(), set_operand(), set_operand_exp() etc
15058 // special concern for lvalue, parent,
15059 // todo: warning overwriting existing operands
15061 {
15062 ROSE_ASSERT(target);
15063 ROSE_ASSERT(operand);
15064 ROSE_ASSERT(target!=operand);
15065 switch (target->variantT())
15066 {
15067 case V_SgActualArgumentExpression:
15068 isSgActualArgumentExpression(target)->set_expression(operand);
15069 break;
15070 case V_SgAsmOp:
15071 isSgAsmOp(target)->set_expression(operand);
15072 break;
15073 case V_SgSizeOfOp:
15074 isSgSizeOfOp(target)->set_operand_expr(operand);
15075 break;
15076 case V_SgTypeIdOp:
15077 isSgTypeIdOp(target)->set_operand_expr(operand);
15078 break;
15079 case V_SgVarArgOp:
15080 isSgVarArgOp(target)->set_operand_expr(operand);
15081 break;
15082 case V_SgVarArgStartOneOperandOp:
15083 isSgVarArgStartOneOperandOp(target)->set_operand_expr(operand);
15084 break;
15085 case V_SgAssignInitializer:
15086 isSgAssignInitializer (target)->set_operand(operand);
15087 break;
15088 default:
15089 if (isSgUnaryOp(target)!=NULL)
15090 isSgUnaryOp(target)->set_operand_i(operand);
15091 else
15092 {
15093 cerr<<"\tSageInterface::setOperand(): unhandled case for target expression of type "
15094 <<target->class_name()<<endl;
15095 ROSE_ABORT();
15096 }
15097 }// end switch
15098 operand->set_parent(target);
15099 markLhsValues(target);
15100 }
15101
15102 // binary and SgVarArgCopyOp, SgVarArgStartOp
15104 {
15105 ROSE_ASSERT(target);
15106 ROSE_ASSERT(lhs);
15107 ROSE_ASSERT(target!=lhs);
15108 bool hasrhs = false;
15109
15110 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
15111 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
15112 SgBinaryOp* binary = isSgBinaryOp(target);
15113
15114 if (varargcopy!=NULL)
15115 {
15116 varargcopy->set_lhs_operand(lhs);
15117 if( varargcopy->get_rhs_operand()!=NULL) hasrhs= true;
15118 }
15119 else if(varargstart!=NULL)
15120 {
15121 varargstart->set_lhs_operand(lhs);
15122 if( varargstart->get_rhs_operand()!=NULL) hasrhs= true;
15123 }
15124 else if(binary!=NULL)
15125 {
15126 binary->set_lhs_operand(lhs);
15127 if( binary->get_rhs_operand()!=NULL) hasrhs= true;
15128 }
15129 else
15130 {
15131 cout<<"SageInterface::setLhsOperand(): unhandled case for target expression of type "
15132 <<target->class_name()<<endl;
15133 ROSE_ABORT();
15134 }
15135 lhs->set_parent(target);
15136// only when both lhs and rhs are available, can we set lvalue
15137// there is assertion(rhs!=NULL) in markLhsValues()
15138 if (hasrhs)
15139 markLhsValues(target);
15140 }
15141
15143 {
15144 ROSE_ASSERT(target);
15145 ROSE_ASSERT(rhs);
15146 ROSE_ASSERT(target!=rhs);
15147 bool haslhs = false;
15148
15149 SgVarArgCopyOp* varargcopy = isSgVarArgCopyOp(target);
15150 SgVarArgStartOp* varargstart = isSgVarArgStartOp(target);
15151 SgBinaryOp* binary = isSgBinaryOp(target);
15152
15153 if (varargcopy!=NULL)
15154 {
15155 varargcopy->set_rhs_operand(rhs);
15156 if( varargcopy->get_lhs_operand()!=NULL) haslhs= true;
15157 }
15158 else if(varargstart!=NULL)
15159 {
15160 varargstart->set_rhs_operand(rhs);
15161 if( varargstart->get_lhs_operand()!=NULL) haslhs= true;
15162 }
15163 else if(binary!=NULL)
15164 {
15165 binary->set_rhs_operand(rhs);
15166 if( binary->get_lhs_operand()!=NULL) haslhs= true;
15167 }
15168 else
15169 {
15170 cout<<"SageInterface::setRhsOperand(): unhandled case for target expression of type "
15171 <<target->class_name()<<endl;
15172 ROSE_ABORT();
15173 }
15174 rhs->set_parent(target);
15175// only when both lhs and rhs are available, can we set lvalue
15176 if (haslhs)
15177 markLhsValues(target);
15178 }
15179
15180// DQ (1/25/2010): Added to simplify handling of directories (e.g. for code generation).
15181void SageInterface::moveToSubdirectory ( std::string directoryName, SgFile* file )
15182 {
15183 // This support makes use of the new SgDirectory IR node. It causes the unparser to
15184 // generate a subdirectory and unparse the file into the subdirectory. It works
15185 // by internally calling the system function "system()" to call "mkdir directoryName"
15186 // and then chdir()" to change the current directory. These steps are handled by the
15187 // unparser.
15188
15189 // This function just does the transformation to insert a SgDirectory IR node between
15190 // the referenced SgFile and it's project (fixing up parents and file lists etc.).
15191
15192 // Add a directory and unparse the code (to the new directory)
15193 SgDirectory* directory = new SgDirectory(directoryName);
15194
15195 SgFileList* parentFileList = isSgFileList(file->get_parent());
15196 ROSE_ASSERT(parentFileList != NULL);
15197 directory->set_parent(file->get_parent());
15198
15199 SgProject* project = NULL;
15200 SgDirectory* parentDirectory = isSgDirectory(parentFileList->get_parent());
15201
15202 if (parentDirectory != NULL)
15203 {
15204 // Add a directory to the list in the SgDirectory node.
15205 parentDirectory->get_directoryList()->get_listOfDirectories().push_back(directory);
15206
15207 // Erase the reference to the file in the project's file list.
15208 // parentDirectory->get_fileList().erase(find(parentDirectory->get_fileList().begin(),parentDirectory->get_fileList().end(),file));
15209 }
15210 else
15211 {
15212 project = isSgProject(parentFileList->get_parent());
15213 ROSE_ASSERT(project != NULL);
15214
15215 // Add a directory to the list in the SgProject node.
15216 project->get_directoryList()->get_listOfDirectories().push_back(directory);
15217
15218 // Erase the reference to the file in the project's file list.
15219 // project->get_fileList().erase(find(project->get_fileList().begin(),project->get_fileList().end(),file));
15220 }
15221
15222 // Put the file into the new directory.
15223 directory->get_fileList()->get_listOfFiles().push_back(file);
15224
15225 // Erase the reference to the file in the project's file list.
15226 parentFileList->get_listOfFiles().erase(find(parentFileList->get_listOfFiles().begin(),parentFileList->get_listOfFiles().end(),file));
15227
15228 file->set_parent(directory);
15229}
15230
15231
15232//------------------------- AST repair----------------------------
15233//----------------------------------------------------------------
15235 {
15236 ROSE_ASSERT(structDecl != NULL);
15237 ROSE_ASSERT(scope != NULL);
15238 SgClassDeclaration* nondefdecl = isSgClassDeclaration(structDecl->get_firstNondefiningDeclaration());
15239 ROSE_ASSERT(nondefdecl != NULL);
15240
15241 // ROSE_ASSERT(structDecl->get_definingDeclaration() != NULL);
15242 SgClassDeclaration* defdecl = isSgClassDeclaration(structDecl->get_definingDeclaration());
15243 // ROSE_ASSERT(defdecl != NULL);
15244
15245 // Liao, 9/2/2009
15246 // fixup missing scope when bottomup AST building is used
15247 if (structDecl->get_scope() == NULL)
15248 structDecl->set_scope(scope);
15249 if (nondefdecl->get_scope() == NULL)
15250 nondefdecl->set_scope(scope);
15251
15252#if 0
15253 if (structDecl->get_parent() == NULL)
15254 structDecl->set_parent(scope);
15255 if (nondefdecl->get_parent() == NULL)
15256 nondefdecl->set_parent(scope);
15257#else
15258 // 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");
15259
15260 // DQ (7/21/2012): Can we assert this here? NO!
15261 // ROSE_ASSERT(structDecl->get_parent() == NULL);
15262 // ROSE_ASSERT(nondefdecl->get_parent() == NULL);
15263#endif
15264
15265 SgName name = structDecl->get_name();
15266
15267 // This is rare case (translation error) when scope->lookup_class_symbol(name) will find something
15268 // but nondefdecl->get_symbol_from_symbol_table() returns NULL
15269 // But symbols are associated with nondefining declarations whenever possible
15270 // and AST consistent check will check the nondefining declarations first
15271 // Liao, 9/2/2009
15272 // SgClassSymbol* mysymbol = scope->lookup_class_symbol(name);
15273 SgClassSymbol* mysymbol = isSgClassSymbol(nondefdecl->get_symbol_from_symbol_table());
15274
15275 // DQ (3/14/2014): This is false for a copy of a class declaration being inserted into the AST.
15276 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15277 // ROSE_ASSERT(mysymbol != NULL);
15278
15279 if (mysymbol == NULL)
15280 {
15281 printf ("Note: SageInterface::fixStructDeclaration(): structDecl = %p nondefdecl = %p (mysymbol == NULL) \n",structDecl,nondefdecl);
15282
15283 // 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...
15284 // DQ (12/4/2011): Only generate symbols and set the scope if this is the correct scope.
15285 ROSE_ASSERT(structDecl->get_scope() != NULL);
15286
15287 if (scope == structDecl->get_scope())
15288 {
15289 mysymbol = new SgClassSymbol(nondefdecl);
15290 ROSE_ASSERT(mysymbol);
15291
15292 // I need to check the rest of these functions.
15293 printf ("############## DANGER:DANGER:DANGER ################\n");
15294
15295 printf ("In SageInterface::fixStructDeclaration(): Adding class symbol to scope = %p = %s \n",scope,scope->class_name().c_str());
15296 scope->insert_symbol(name, mysymbol);
15297
15298 // ROSE_ASSERT(defdecl != NULL);
15299 if (defdecl)
15300 defdecl->set_scope(scope);
15301 nondefdecl->set_scope(scope);
15302
15303 printf ("*** WARNING: In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Commented out the setting of the parent to be the same as the scope \n");
15304#if 0
15305 if (defdecl)
15306 defdecl->set_parent(scope);
15307 nondefdecl->set_parent(scope);
15308#endif
15309 }
15310 else
15311 {
15312 printf ("In SageInterface::fixStructDeclaration(): (mysymbol == NULL) Skipped building an associated symbol! \n");
15313 }
15314 }
15315
15316 // DQ (9/4/2012): I want to assert this for the new EDG/ROSE connection code (at least).
15317 ROSE_ASSERT(nondefdecl->get_type() != NULL);
15318
15319 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15320 ROSE_ASSERT(nondefdecl->get_type()->variantT() != V_SgNode);
15321
15322 // DQ (9/4/2012): This should be a SgClassType IR node.
15323 ROSE_ASSERT(isSgClassType(nondefdecl->get_type()) != NULL);
15324
15325 // fixup SgClassType, which is associated with the first non-defining declaration only
15326 // and the other declarations share it.
15327 if (nondefdecl->get_type() == NULL)
15328 {
15329 nondefdecl->set_type(SgClassType::createType(nondefdecl));
15330 }
15331 ROSE_ASSERT (nondefdecl->get_type() != NULL);
15332
15333 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15334 if (defdecl != NULL)
15335 {
15336 // DQ (9/4/2012): This is a sign that the pointer to the type was deleted.
15337 ROSE_ASSERT(defdecl->get_type()->variantT() != V_SgNode);
15338
15339 // DQ (9/4/2012): This should be a SgClassType IR node.
15340 ROSE_ASSERT(isSgClassType(defdecl->get_type()) != NULL);
15341 }
15342
15343 // ROSE_ASSERT(defdecl != NULL);
15344 if (defdecl != NULL)
15345 {
15346 // DQ (9/4/2012): If defDecl != NULL, I want to assert this for the new EDG/ROSE connection code (at least).
15347 ROSE_ASSERT(defdecl->get_type() != NULL);
15348 if (defdecl->get_type() != nondefdecl->get_type())
15349 {
15350 printf ("ERROR: defdecl->get_type() != nondefdecl->get_type(): what are these: \n");
15351 printf (" defdecl->get_type() = %p = %s \n",defdecl ->get_type(),defdecl ->get_type()->class_name().c_str());
15352 SgNamedType* namedType_definingDecl = isSgNamedType(defdecl->get_type());
15353 if (namedType_definingDecl != NULL)
15354 {
15355 printf ("namedType_definingDecl->get_declaration() = %p = %s \n",namedType_definingDecl->get_declaration(),namedType_definingDecl->get_declaration()->class_name().c_str());
15356 }
15357 printf (" nondefdecl->get_type() = %p = %s \n",nondefdecl->get_type(),nondefdecl->get_type()->class_name().c_str());
15358 SgNamedType* namedType_nondefiningDecl = isSgNamedType(nondefdecl->get_type());
15359 if (namedType_nondefiningDecl != NULL)
15360 {
15361 printf ("namedType_nondefiningDecl->get_declaration() = %p = %s \n",namedType_nondefiningDecl->get_declaration(),namedType_nondefiningDecl->get_declaration()->class_name().c_str());
15362 }
15363 }
15364 //ROSE_ASSERT(defdecl->get_type() == nondefdecl->get_type());
15365 }
15366 }
15367
15368
15370 {
15371 fixStructDeclaration(classDecl,scope);
15372 }
15373
15374
15376 {
15377 ROSE_ASSERT(structDecl);
15378 ROSE_ASSERT(scope);
15379 SgNamespaceDeclarationStatement* nondefdecl = isSgNamespaceDeclarationStatement(structDecl->get_firstNondefiningDeclaration());
15380 ROSE_ASSERT(nondefdecl);
15381 // Liao, 9/2/2009
15382 // fixup missing scope when bottomup AST building is used
15383 if (structDecl->get_parent() == NULL)
15384 structDecl->set_parent(scope);
15385 if (nondefdecl->get_parent() == NULL)
15386 nondefdecl->set_parent(scope);
15387
15388 // tps : (09/03/2009) Namespace should not have a scope
15389 /*
15390 if (structDecl->get_scope() == NULL)
15391 structDecl->set_scope(scope);
15392 if (nondefdecl->get_scope() == NULL)
15393 nondefdecl->set_scope(scope);
15394 */
15395
15396 SgName name= structDecl->get_name();
15397 // SgNamespaceSymbol* mysymbol = scope->lookup_namespace_symbol(name);
15398 SgNamespaceSymbol* mysymbol = isSgNamespaceSymbol(nondefdecl->get_symbol_from_symbol_table());
15399 if (mysymbol==NULL)
15400 {
15401 // DQ (12/4/2011): This code is modified to try to only insert the symbol into the correct scope. It used to
15402 // just insert the symbol into whatever scope structureally held the declaration (not good enough for C++).
15403 if (scope == structDecl->get_scope())
15404 {
15405 mysymbol = new SgNamespaceSymbol(name,nondefdecl);
15406 ROSE_ASSERT(mysymbol);
15407
15408 printf ("In SageInterface::fixNamespaceDeclaration(): inserting namespace symbol into scope = %p = %s \n",scope,scope->class_name().c_str());
15409 scope->insert_symbol(name, mysymbol);
15410
15411 SgNamespaceDeclarationStatement* defdecl = isSgNamespaceDeclarationStatement(structDecl->get_definingDeclaration());
15412 ROSE_ASSERT(defdecl);
15413 defdecl->set_scope(scope);
15414 nondefdecl->set_scope(scope);
15415
15416 defdecl->set_parent(scope);
15417 nondefdecl->set_parent(scope);
15418 }
15419 }
15420 }
15421
15422#define DEBUG__SageInterface__fixVariableDeclaration 0
15423
15425 {
15426 ROSE_ASSERT(varDecl != NULL);
15427 ROSE_ASSERT(scope != NULL);
15428
15429 SgInitializedNamePtrList namelist = varDecl->get_variables();
15430 SgTemplateVariableInstantiation * tplinst = isSgTemplateVariableInstantiation(varDecl);
15431
15432 // printf ("In SageInterface::fixVariableDeclaration(): Is this a recursive call! \n");
15433
15434#if DEBUG__SageInterface__fixVariableDeclaration
15435 printf ("In SageInterface::fixVariableDeclaration():\n");
15436 printf (" varDecl = %p scope = %p = %s \n", varDecl);
15437 printf (" scope = %p : %s \n", scope, scope->class_name().c_str());
15438#endif
15439
15440 ROSE_ASSERT(namelist.size() > 0);
15441
15442 SgInitializedNamePtrList::iterator i;
15443 for (i = namelist.begin(); i != namelist.end(); i++)
15444 {
15445 SgInitializedName *initName = *i;
15446 ROSE_ASSERT(initName != NULL);
15447#if DEBUG__SageInterface__fixVariableDeclaration
15448 printf (" initName = %p\n", initName);
15449 printf (" initName->get_scope() = %p : %s\n", initName->get_scope(), initName->get_scope() ? initName->get_scope()->class_name().c_str() : "");
15450#endif
15451
15452 SgName name = initName->get_name();
15453#if DEBUG__SageInterface__fixVariableDeclaration
15454 printf (" name = %s\n", name.str());
15455#endif
15456 if (tplinst) {
15457 name = appendTemplateArgumentsToName(name, tplinst->get_templateArguments());
15458 }
15459#if DEBUG__SageInterface__fixVariableDeclaration
15460 printf (" name = %s\n", name.str());
15461#endif
15462
15463 // DQ (11/19/2011): When used with C++, the variable may already have an associated scope
15464 // and be using name qualification, so might not be associated with the current scope.
15465 SgScopeStatement* requiredScope = scope;
15466 SgScopeStatement* preAssociatedScope = initName->get_scope();
15467 if (preAssociatedScope != NULL) {
15468 requiredScope = preAssociatedScope;
15469 }
15470
15471 // DQ (11/19/2011): C++ can have a different scope than that of the current scope.
15472 initName->set_scope(requiredScope);
15473 if (topScopeStack() != NULL) {
15474 varDecl->set_parent(topScopeStack());
15475 ROSE_ASSERT(varDecl->get_parent() != NULL);
15476 }
15477 ROSE_ASSERT(requiredScope != NULL);
15478 SgVariableSymbol* varSymbol = requiredScope->lookup_variable_symbol(name);
15479#if DEBUG__SageInterface__fixVariableDeclaration
15480 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15481#endif
15482 if (varSymbol == NULL) {
15483 if (scope == initName->get_scope()) {
15484 if (isSgTemplateVariableDeclaration(varDecl)) {
15485 varSymbol = new SgTemplateVariableSymbol(initName);
15486 } else {
15487 varSymbol = new SgVariableSymbol(initName);
15488 }
15489 ROSE_ASSERT(varSymbol);
15490 scope->insert_symbol(name, varSymbol);
15491 }
15492 } else {
15493 SgInitializedName* prev_decl = varSymbol->get_declaration();
15494 ROSE_ASSERT(prev_decl);
15495 if (initName != prev_decl) {
15496 initName->set_prev_decl_item(prev_decl);
15497 }
15498 ROSE_ASSERT(initName->get_prev_decl_item() != initName);
15499 }
15500#if DEBUG__SageInterface__fixVariableDeclaration
15501 printf (" varSymbol = %p (%s)\n", varSymbol, varSymbol ? varSymbol->class_name().c_str() : "");
15502#endif
15503 } //end for
15504
15505 // Liao 12/8/2010
15506 // For Fortran, a common statement may refer to a variable which is declared later.
15507 // In this case, a fake symbol is used for that variable reference.
15508 // But we have to replace the fake one with the real one once the variable declaration is inserted into AST
15510 {
15511 fixVariableReferences(scope);
15512 }
15513 }
15514
15515int SageInterface::fixVariableReferences(SgNode* root, bool cleanUnusedSymbols/*=true*/)
15516{
15517 ROSE_ASSERT(root);
15518 int counter=0;
15519 Rose_STL_Container<SgNode*> varList;
15520
15521 SgVarRefExp* varRef=NULL;
15522 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(root, V_SgVarRefExp);
15523 for (Rose_STL_Container<SgNode*>::iterator i=reflist.begin();i!=reflist.end();i++)
15524 {
15525 varRef= isSgVarRefExp(*i);
15526 ROSE_ASSERT(varRef->get_symbol());
15527 SgInitializedName* initname= varRef->get_symbol()->get_declaration();
15528
15529 ROSE_ASSERT (initname != NULL);
15530 if (initname->get_type()==SgTypeUnknown::createType())
15531 {
15532 SgName varName=initname->get_name();
15533 SgSymbol* realSymbol = NULL;
15534
15535#if 1
15536 // CH (5/7/2010): Before searching SgVarRefExp objects, we should first deal with class/structure
15537 // members. Or else, it is possible that we assign the wrong symbol to those members if there is another
15538 // variable with the same name in parent scopes. Those members include normal member referenced using . or ->
15539 // operators, and static members using :: operators.
15540 //
15541 if (SgArrowExp* arrowExp = isSgArrowExp(varRef->get_parent()))
15542 {
15543 if (varRef == arrowExp->get_rhs_operand_i())
15544 {
15545 // make sure the lhs operand has been fixed
15546 counter += fixVariableReferences(arrowExp->get_lhs_operand_i());
15547 SgType* lhs_type = arrowExp->get_lhs_operand_i()->get_type() ;
15548 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15549 SgPointerType* ptrType = isSgPointerType(lhs_type);
15550 ROSE_ASSERT(ptrType);
15551 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));
15552 ROSE_ASSERT(clsType);
15553 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15554 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15555 ROSE_ASSERT(decl);
15556
15557 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15558 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15559 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15560 }
15561 else
15562 {
15563 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15564 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15565 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15566 }
15567 }
15568 else if (SgDotExp* dotExp = isSgDotExp(varRef->get_parent()))
15569 {
15570 if (varRef == dotExp->get_rhs_operand_i())
15571 {
15572 // make sure the lhs operand has been fixed
15573 counter += fixVariableReferences(dotExp->get_lhs_operand_i());
15574
15575 SgType* lhs_type = dotExp->get_lhs_operand_i()->get_type() ;
15576 lhs_type = lhs_type->stripType(SgType::STRIP_MODIFIER_TYPE | SgType::STRIP_REFERENCE_TYPE | SgType::STRIP_RVALUE_REFERENCE_TYPE | SgType::STRIP_TYPEDEF_TYPE);
15577 SgClassType* clsType = isSgClassType(lhs_type);
15578 ROSE_ASSERT(clsType);
15579 SgClassDeclaration* decl = isSgClassDeclaration(clsType->get_declaration());
15580 decl = isSgClassDeclaration(decl->get_definingDeclaration());
15581 ROSE_ASSERT(decl);
15582
15583 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15584 // realSymbol = lookupSymbolInParentScopes(varName, decl->get_definition());
15585 realSymbol = lookupVariableSymbolInParentScopes(varName, decl->get_definition());
15586 }
15587 else
15588 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15589 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15590 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15591 }
15592 else
15593#endif
15594 {
15595 // DQ (8/16/2013): We want to lookup variable symbols not just any symbol.
15596 // realSymbol = lookupSymbolInParentScopes(varName,getScope(varRef));
15597 realSymbol = lookupVariableSymbolInParentScopes(varName, getScope(varRef));
15598 }
15599
15600 // should find a real symbol at this final fixing stage!
15601 // This function can be called any time, not just final fixing stage
15602 if (realSymbol==NULL)
15603 {
15604 //cerr<<"Error: cannot find a symbol for "<<varName.getString()<<endl;
15605 //ROSE_ASSERT(realSymbol);
15606 }
15607 else {
15608 // release placeholder initname and symbol
15609 ROSE_ASSERT(realSymbol!=(varRef->get_symbol()));
15610#if 0
15611 // CH (5/12/2010):
15612 // To delete a symbol node, first check if there is any node in memory
15613 // pool which points to this symbol node. Only if no such node exists,
15614 // this symbol together with its initialized name can be deleted.
15615 //
15616 bool toDelete = true;
15617
15618 SgSymbol* symbolToDelete = varRef->get_symbol();
15619 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15620 counter ++;
15621
15622 if (varList.empty())
15623 {
15624 VariantVector vv(V_SgVarRefExp);
15625 varList = NodeQuery::queryMemoryPool(vv);
15626 }
15627
15628 for (Rose_STL_Container<SgNode*>::iterator i = varList.begin();
15629 i != varList.end(); ++i)
15630 {
15631 if (SgVarRefExp* var = isSgVarRefExp(*i))
15632 {
15633 if (var->get_symbol() == symbolToDelete)
15634 {
15635 toDelete = false;
15636 break;
15637 }
15638 }
15639 }
15640 if (toDelete)
15641 {
15642 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15643 delete symbolToDelete;
15644 }
15645
15646#else
15647
15648 // CH (2010/7/26): We cannot delete those initname and symbol here, since there may be other variable references
15649 // which point to them. We will delay this clear just before AstTests.
15650#if 0
15651 delete initname; // TODO deleteTree(), release File_Info nodes etc.
15652 delete (varRef->get_symbol());
15653#endif
15654
15655 //std::cout << "Fixed variable reference: " << realSymbol->get_name().str() << std::endl;
15656 varRef->set_symbol(isSgVariableSymbol(realSymbol));
15657 counter ++;
15658#endif
15659 }
15660 }
15661 } // end for
15662 // Liao 2/1/2013: delete unused initname and symbol, considering possible use by the current subtree from root node
15663 if (cleanUnusedSymbols)
15665 return counter;
15666}
15667
15669{
15670 Rose_STL_Container<SgNode*> symbolList;
15671 VariantVector sym_vv(V_SgVariableSymbol);
15672 symbolList = NodeQuery::queryMemoryPool(sym_vv);
15673
15674 Rose_STL_Container<SgNode*> varList;
15675 VariantVector var_vv(V_SgVarRefExp);
15676 //varList = NodeQuery::queryMemoryPool(var_vv);
15677 if (root != NULL)
15678 {
15679 varList = NodeQuery::querySubTree(root, V_SgVarRefExp);
15680 }
15681
15682 for (Rose_STL_Container<SgNode*>::iterator i = symbolList.begin();
15683 i != symbolList.end(); ++i)
15684 {
15685 SgVariableSymbol* symbolToDelete = isSgVariableSymbol(*i);
15686 ROSE_ASSERT(symbolToDelete);
15687 if (symbolToDelete->get_declaration()->get_type() != SgTypeUnknown::createType())
15688 continue;
15689 // symbol with a declaration of SgTypeUnknown will be deleted
15690 bool toDelete = true;
15691
15692 if (root != NULL) // if root is specified. We further check if the symbol is referenced by any nodes of the tree rooted at "root"
15693 {
15694 for (Rose_STL_Container<SgNode*>::iterator j = varList.begin();
15695 j != varList.end(); ++j)
15696 {
15697 SgVarRefExp* var = isSgVarRefExp(*j);
15698 ROSE_ASSERT(var);
15699
15700 if (var->get_symbol() == symbolToDelete)
15701 {
15702 toDelete = false;
15703 break;
15704 }
15705 }
15706 }
15707
15708 if (toDelete)
15709 {
15710#if 0
15711 std::cout << "Symbol " << symbolToDelete->get_name().str() << ' ' << symbolToDelete <<
15712 ' ' << symbolToDelete->get_declaration() << " is deleted." << std::endl;
15713#endif
15714 delete symbolToDelete->get_declaration();
15715 delete symbolToDelete;
15716 }
15717 }
15718}
15719
15720
15722/*
15723 * label statement has special scope: the closest function definition , not SgBasicBlock or others!
15724 */
15726 {
15727 SgLabelStatement* label_stmt = isSgLabelStatement(stmt);
15728 ROSE_ASSERT(label_stmt);
15729 SgName name = label_stmt->get_label();
15730
15731 // PP (07/18/23): In Ada, label symbols should be inserted in the current scope's symbol table
15732 const bool symbolAtFunctionLevel = !is_Ada_language();
15733 SgScopeStatement* label_scope = symbolAtFunctionLevel ? getEnclosingFunctionDefinition(scope,true)
15734 : scope;
15735
15736 // DQ (11/16/2014): Added error checking for when the input scope is the SgFunctionDefinition instead of a nested scope.
15737 if (isSgFunctionDefinition(scope) != nullptr)
15738 {
15739 ASSERT_not_null(label_scope);
15740 }
15741
15742 if (label_scope) //Should we assert this instead? No for bottom up AST building
15743 {
15744 label_stmt->set_scope(label_scope);
15745 SgLabelSymbol* lsymbol = label_scope->lookup_label_symbol(name);
15746
15747 if (lsymbol == nullptr)
15748 {
15749 // SgLabelStatement should always be in the function scope
15750 // PP (07/18/23): in Ada symbols should be at the innermost scope
15751 lsymbol= new SgLabelSymbol(label_stmt);
15752 ASSERT_not_null(lsymbol);
15753 label_scope->insert_symbol(lsymbol->get_name(), lsymbol);
15754 }
15755 }
15756 }
15757
15758
15760//efExp are created transparently as needed.
15762 SgLabelSymbol::label_type_enum label_type, SgScopeStatement* label_scope)
15763 {
15764 ROSE_ASSERT (stmt != NULL);
15765 ROSE_ASSERT (label_value >0 && label_value <=99999); //five digits for Fortran label
15766
15767 // Added optional label_type and label_scope [Rasmussen 2019.01.20]
15768 if (label_scope == NULL)
15769 {
15770 label_scope = getEnclosingFunctionDefinition(stmt);
15771 }
15772 ROSE_ASSERT (label_scope != NULL);
15773 SgName label_name(StringUtility::numberToString(label_value));
15774 SgLabelSymbol * symbol = label_scope->lookup_label_symbol (label_name);
15775 if (symbol == NULL)
15776 {
15777 // DQ (12/4/2011): This is the correct handling for SgLabelStatement (always in the function scope, same as C and C++).
15778 // DQ (2/2/2011): We want to call the old constructor (we now have another constructor that takes a SgInitializedName pointer).
15779 // symbol = new SgLabelSymbol(NULL);
15780 symbol = new SgLabelSymbol((SgLabelStatement*) NULL);
15781 ROSE_ASSERT(symbol != NULL);
15782 symbol->set_fortran_statement(stmt);
15783 symbol->set_numeric_label_value(label_value);
15784 label_scope->insert_symbol(label_name,symbol);
15785 }
15786 else
15787 {
15788 cerr<<"Error. SageInterface::setFortranNumericLabel() tries to set a duplicated label value!"<<endl;
15789 ROSE_ASSERT (false);
15790 }
15791
15792 // SgLabelRefExp
15793 SgLabelRefExp* ref_exp = buildLabelRefExp(symbol);
15794 ref_exp->set_parent(stmt);
15795
15796 switch(label_type)
15797 {
15798 case SgLabelSymbol::e_start_label_type:
15799 {
15800 stmt->set_numeric_label(ref_exp);
15801 break;
15802 }
15803 case SgLabelSymbol::e_end_label_type:
15804 {
15805 stmt->set_end_numeric_label(ref_exp);
15806 break;
15807 }
15808 default:
15809 {
15810 std::cerr << "SageInterface::setFortranNumericLabel: unimplemented for label_type " << label_type << "\n";
15811 ROSE_ABORT(); // NOT IMPLEMENTED
15812 }
15813 }
15814
15815 }
15816
15817
15820{
15821 int result =10;
15822 ROSE_ASSERT (func_def != NULL);
15823 ROSE_ASSERT (SageInterface::is_Fortran_language()== true);
15824 std::set<SgNode*> symbols = func_def->get_symbol_table()->get_symbols();
15825
15826 // find the max label value, +10 to be the suggested next label value
15827 std::set<SgNode*>::iterator iter ;
15828 for (iter=symbols.begin(); iter !=symbols.end(); iter++)
15829 {
15830 SgLabelSymbol * l_symbol = isSgLabelSymbol(*iter);
15831 if (l_symbol)
15832 {
15833 int cur_val = l_symbol->get_numeric_label_value();
15834 if (result <=cur_val)
15835 result = cur_val +10;
15836 }
15837 }
15838
15839 ROSE_ASSERT (result <= 99999); // max 5 digits for F77 label
15840 return result;
15841}
15842
15844/*
15845 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15846 */
15848 {
15849 // DQ (3/5/2012): Added test.
15850 ROSE_ASSERT(scope != NULL);
15851
15852 // fix function type table's parent edge
15853 // Liao 5/4/2010
15855 ROSE_ASSERT(fTable != NULL);
15856
15857 if (fTable->get_parent() == NULL)
15858 {
15859 // DQ (3/5/2012): This is a problem for test2012_13.C (test code taken from test2004_42.C).
15860 // fTable->set_parent(getGlobalScope(scope));
15861#if 0
15862 printf ("WARNING: Skip setting the scope of the SgFunctionTypeTable scope = %p = %s \n",scope,scope->class_name().c_str());
15863#endif
15864 fTable->set_parent(getGlobalScope(scope));
15865 }
15866
15867#if 0
15868 printf ("In SageInterface::fixStatement(): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
15869#endif
15870
15871 // Liao 4/23/2010, Fix function symbol
15872 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
15873 // Added SgProgramHeaderStatement [Rasmussen, 2020.01.19]
15874 SgFunctionDeclaration * func = isSgFunctionDeclaration(stmt);
15875 SgMemberFunctionDeclaration * mfunc = isSgMemberFunctionDeclaration(stmt);
15876 SgTemplateFunctionDeclaration * tfunc = isSgTemplateFunctionDeclaration(stmt);
15877 SgTemplateMemberFunctionDeclaration * tmfunc = isSgTemplateMemberFunctionDeclaration(stmt);
15878 SgProcedureHeaderStatement * procfunc = isSgProcedureHeaderStatement(stmt);
15879 SgProgramHeaderStatement * progfunc = isSgProgramHeaderStatement(stmt);
15880
15881 if (tmfunc != NULL)
15882 assert(tmfunc->variantT() == V_SgTemplateMemberFunctionDeclaration);
15883 else if (mfunc != NULL)
15884 assert(mfunc->variantT() == V_SgMemberFunctionDeclaration || mfunc->variantT() == V_SgTemplateInstantiationMemberFunctionDecl);
15885 else if (tfunc != NULL)
15886 assert(tfunc->variantT() == V_SgTemplateFunctionDeclaration);
15887 else if (procfunc != NULL)
15888 assert(procfunc->variantT() == V_SgProcedureHeaderStatement);
15889 else if (progfunc != NULL)
15890 assert(progfunc->variantT() == V_SgProgramHeaderStatement);
15891 else if (func != NULL)
15892 assert(func->variantT() == V_SgFunctionDeclaration || func->variantT() == V_SgTemplateInstantiationFunctionDecl);
15893 else ROSE_ABORT();
15894
15895#if 0
15896 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
15897 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
15898#endif
15899
15900 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
15901 // It is an error to put the symbol for a function into the current scope if the function's scope
15902 // is explicitly set to be different. So this should be allowed only if the function's scope is
15903 // not explicitly set, or if the scopes match. This is an example of something different for C++
15904 // than for C or other simpler languages.
15905 // If the scope of the function is not set, or if it matches the current scope then allow this step.
15906 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
15907 {
15908#if 0
15909 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());
15910#endif
15911 SgFunctionSymbol* func_symbol = NULL;
15912
15913 // DQ (7/31/2013): Fixing API to use functions that now require template parameters and template specialization arguments.
15914 // In this case these are unavailable from this point.
15915 if (tmfunc != NULL)
15916 {
15917 SgTemplateParameterPtrList & templateParameterList = tmfunc->get_templateParameters();
15918 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type());
15919 // func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),NULL);
15920 func_symbol = scope->lookup_template_member_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15921 }
15922 else if (mfunc != NULL)
15923 {
15924 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(mfunc);
15925 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationMemberFunctionDecl != NULL) ? &(templateInstantiationMemberFunctionDecl->get_templateArguments()) : NULL;
15926 // func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),NULL);
15927 func_symbol = scope->lookup_nontemplate_member_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15928 }
15929 else if (tfunc != NULL)
15930 {
15931 SgTemplateParameterPtrList & templateParameterList = tfunc->get_templateParameters();
15932#if 0
15933 printf ("In SageInterface::fixStatement(): templateParameterList.size() = %" PRIuPTR " \n",templateParameterList.size());
15934#endif
15935 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type());
15936 // func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),NULL);
15937 func_symbol = scope->lookup_template_function_symbol (func->get_name(), func->get_type(),&templateParameterList);
15938 }
15939 else if (procfunc != NULL)
15940 {
15941#if 0
15942 printf ("In SageInterface::fixStatement(): procfunc->get_name() = %s calling lookup_function_symbol() \n",procfunc->get_name().str());
15943#endif
15944 func_symbol = scope->lookup_function_symbol (procfunc->get_name(), procfunc->get_type());
15945 assert(func_symbol != NULL);
15946 }
15947 else if (progfunc != NULL)
15948 {
15949 func_symbol = scope->lookup_function_symbol (progfunc->get_name(), progfunc->get_type());
15950 assert(func_symbol != NULL);
15951 }
15952 else if (func != NULL)
15953 {
15954#if 0
15955 printf ("In SageInterface::fixStatement(): func->get_name() = %s calling lookup_function_symbol() \n",func->get_name().str());
15956#endif
15957 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(func);
15958 SgTemplateArgumentPtrList* templateArgumentList = (templateInstantiationFunctionDecl != NULL) ? &(templateInstantiationFunctionDecl->get_templateArguments()) : NULL;
15959 // func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),NULL);
15960 func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type(),templateArgumentList);
15961
15962 // 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
15963 // 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
15964 // opportunity to fixup the function to have a symbol in the scope's symbol table.
15965 if (func_symbol == NULL)
15966 {
15967 // scope->print_symboltable("In SageInterface::fixStatement()");
15968 func_symbol = new SgFunctionSymbol(func);
15969 scope->insert_symbol(func->get_name(), func_symbol);
15970 }
15971 }
15972 else
15973 {
15974 ROSE_ABORT();
15975 }
15976#if 0
15977 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
15978#endif
15979 assert(func_symbol != NULL);
15980 }
15981 }
15982
15984/*
15985 * function declarations can have a scope that is different from their structural location (e.g. member functions declared outside of the defining class declaration.
15986 */
15988 {
15989 // DQ (12/4/2011): This function has not been implemented yet. It will assert fail if it is required.
15990 printf ("Need to handle SgTemplateDeclaration IR nodes as well...(implement later) \n");
15991 }
15992
15993
15996 {
15997 // fix symbol table
15998 if (isSgVariableDeclaration(stmt))
15999 {
16000 fixVariableDeclaration(isSgVariableDeclaration(stmt), scope);
16001 }
16002 else if (isStructDeclaration(stmt))
16003 {
16004 SgClassDeclaration* classDeclaration = isSgClassDeclaration(stmt);
16005 ROSE_ASSERT(classDeclaration != nullptr);
16006 fixStructDeclaration(classDeclaration,scope);
16007 }
16008 else if (isSgClassDeclaration(stmt))
16009 {
16010 fixClassDeclaration(isSgClassDeclaration(stmt),scope);
16011 }
16012 else if (isSgLabelStatement(stmt))
16013 {
16014 fixLabelStatement(isSgLabelStatement(stmt),scope);
16015 }
16016 else if (isSgFunctionDeclaration(stmt))
16017 {
16018#if 1
16019 fixFunctionDeclaration(isSgFunctionDeclaration(stmt),scope);
16020#else
16021 // fix function type table's parent edge
16022 // Liao 5/4/2010
16024 ROSE_ASSERT(fTable);
16025 if (fTable->get_parent() == NULL)
16026 fTable->set_parent(getGlobalScope(scope));
16027
16028 // Liao 4/23/2010, Fix function symbol
16029 // This could happen when users copy a function, then rename it (func->set_name()), and finally insert it to a scope
16030 SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt);
16031 SgMemberFunctionDeclaration* mfunc = isSgMemberFunctionDeclaration(stmt);
16032
16033 printf ("In SageInterface::fixStatement(): scope = %p = %s \n",scope,scope->class_name().c_str());
16034 printf ("In SageInterface::fixStatement(): stmt->get_scope() = %p \n",stmt->get_scope());
16035
16036 // DQ (12/3/2011): This is a scary piece of code, but I think it is OK now!
16037 // It is an error to put the symbol for a function into the current scope if the function's scope
16038 // is explicitly set to be different. So this should be allowed only if the function's scope is
16039 // not explicitly set, or if the scopes match. This is an example of something different for C++
16040 // than for C or other simpler languages.
16041 // If the scope of the function is not set, or if it matches the current scope then allow this step.
16042 if (stmt->get_scope() == NULL || scope == stmt->get_scope())
16043 {
16044#if 0
16045 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());
16046#endif
16047 SgFunctionSymbol* func_symbol = scope->lookup_function_symbol (func->get_name(), func->get_type());
16048
16049 printf ("In SageInterface::fixStatement(): func_symbol = %p \n",func_symbol);
16050 if (func_symbol == NULL)
16051 {
16052 // DQ (12/3/2011): Added support for C++ member functions.
16053 // func_symbol = new SgFunctionSymbol (func);
16054 if (mfunc != NULL)
16055 {
16056 func_symbol = new SgMemberFunctionSymbol (func);
16057 }
16058 else
16059 {
16060 func_symbol = new SgFunctionSymbol (func);
16061 }
16062 ROSE_ASSERT (func_symbol != NULL);
16063
16064 scope->insert_symbol(func->get_name(), func_symbol);
16065 }
16066 else
16067 {
16068 printf ("In SageInterface::fixStatement(): found a valid function so no need to insert new symbol \n");
16069 }
16070 }
16071#if 0
16072 // Fix local symbol, a symbol directly refer to this function declaration
16073 // This could happen when a non-defining func decl is copied, the corresonding symbol will point to the original source func
16074 // symbolTable->find(this) used inside get_symbol_from_symbol_table() won't find the copied decl
16075 SgSymbol* local_symbol = func ->get_symbol_from_symbol_table();
16076 if (local_symbol == NULL) //
16077 {
16078 if (func->get_definingDeclaration() == NULL) // prototype function
16079 {
16080 SgFunctionDeclaration * src_func = func_symbol->get_declaration();
16081 if (func != src_func )
16082 {
16083 ROSE_ASSERT (src_func->get_firstNondefiningDeclaration () == src_func);
16084 func->set_firstNondefiningDeclaration (func_symbol->get_declaration());
16085 }
16086 }
16087 }
16088#endif
16089#endif
16090 }
16091 else if (isSgTemplateDeclaration(stmt) != NULL)
16092 {
16093 // DQ (12/3/2011): Added new case for SgTemplateDeclaration (adding template declarations to the AST).
16094 fixTemplateDeclaration(isSgTemplateDeclaration(stmt),scope);
16095 }
16096
16097#if 0
16098 // DQ (12/4/2011): This WAS not the correct behavior for C++ since declarations can appear structureally in different
16099 // scopes than where the are positioned (e.g. member functions defined outside of there associated class).
16100 // This this code is very dangerous.
16101
16102 // fix scope pointer for statements explicitly storing scope pointer
16103 switch (stmt->variantT())
16104 {
16105 // The case of SgLabelStatement should maybe be included.
16106 case V_SgEnumDeclaration:
16107 case V_SgTemplateDeclaration:
16108 case V_SgTypedefDeclaration:
16109 case V_SgFunctionDeclaration:
16110 case V_SgMemberFunctionDeclaration:
16111 case V_SgTemplateInstantiationFunctionDecl:
16112 {
16113 // DQ (12/4/2011): We can't just set the scope this simily (except in C). In C++ the scope should have
16114 // already been set or we can let it default to the current scope where it si located structurally.
16115 // stmt->set_scope(scope);
16116 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
16117 {
16118 stmt->set_scope(scope);
16119 }
16120 break;
16121 }
16122
16123 default:
16124 {
16125 // debugging support...
16126 printf ("In SageInterface::fixStatement(): switch default case used (likely OK): stmt = %p = %s \n",stmt,stmt->class_name().c_str());
16127 ROSE_ASSERT(stmt->hasExplicitScope() == false);
16128#if 0
16129 printf ("switch case not handled properly: stmt = %p = %s \n",stmt,stmt->class_name().c_str());
16130 ROSE_ABORT();
16131#endif
16132 break;
16133 }
16134 }
16135#else
16136 // If the scoep has to be set and it has not yet been set, then set it directly.
16137 if ( (stmt->hasExplicitScope() == true) && (stmt->get_scope() == NULL) )
16138 {
16139 stmt->set_scope(scope);
16140 }
16141#endif
16142 }
16143
16144
16157 {
16158 // DQ (11/19/2012): Note that this appears to be an expensive function presently taking 22.5% of the total time
16159 // to process the tests/CompilerTests/Cxx_tests/rosePerformance.C file. So this is a performance problem.
16160
16161 ROSE_ASSERT(func != NULL && scope != NULL);
16162
16163 ROSE_ASSERT(func != NULL);
16164 ROSE_ASSERT(scope != NULL);
16165
16166 SgStatementPtrList stmtList, sameFuncList;
16167
16168 // SgFunctionDeclaration* first_nondef = NULL;
16169 // Some annoying part of scope
16170 if (scope->containsOnlyDeclarations())
16171 {
16172 SgDeclarationStatementPtrList declList = scope->getDeclarationList();
16173 SgDeclarationStatementPtrList::iterator i;
16174 for (i=declList.begin();i!=declList.end();i++)
16175 stmtList.push_back(*i);
16176 }
16177 else
16178 {
16179 stmtList = scope->getStatementList();
16180 }
16181
16182 SgFunctionDeclaration* firstNondefiningFunctionDeclaration = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
16183 if (firstNondefiningFunctionDeclaration != NULL)
16184 {
16185 // If there exists a non-NULL reference to a firstNondefiningFunctionDeclaration
16186 // then use it (unless we want to handle where it might be set wrong).
16187#if 0
16188 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid pointer to a firstNondefiningFunctionDeclaration = %p \n",func,firstNondefiningFunctionDeclaration);
16189#endif
16190 }
16191
16192 // DQ (3/12/2012): Added assertion
16193 // ROSE_ASSERT(scope == func->get_firstNondefiningDeclaration()->get_scope());
16194 ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope() != NULL);
16195
16196 // 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.
16197 if (func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) == NULL)
16198 {
16199 printf ("WARNING: symbol for func->get_firstNondefiningDeclaration() = %p = %s = %s is not present in the scope = %p = %s associated with the firstNondefiningDeclaration \n",
16200 func->get_firstNondefiningDeclaration(),func->get_firstNondefiningDeclaration()->class_name().c_str(),func->get_name().str(),
16202 }
16203 // ROSE_ASSERT(func->get_firstNondefiningDeclaration()->get_scope()->lookup_function_symbol(func->get_name(),func->get_type()) != NULL);
16204
16205#if 0
16206 // It would be better to find the first non-defining declaration via the symbol.
16207 SgSymbol* functionSymbol = scope->lookup_function_symbol(func->get_name(),func->get_type());
16208 if (functionSymbol != NULL)
16209 {
16210 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p Found a valid symbol = %p \n",func,functionSymbol);
16211 }
16212 else
16213 {
16214 printf ("In SageInterface::updateDefiningNondefiningLinks(): func = %p functionSymbol == NULL \n",func);
16215 }
16216#endif
16217
16218 // Find the same function declaration list, including func itself
16219 SgStatementPtrList::iterator j;
16220 for (j = stmtList.begin(); j != stmtList.end(); j++)
16221 {
16222 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16223 if (func_decl != NULL)
16224 {
16225 // DQ (11/19/2012): This call to the isSameFunction() function is taking a total of 22.1%
16226 // of the total execution time of the tests/CompilerTests/Cxx_tests/rosePerformance.C file.
16227 if (isSameFunction(func_decl, func))
16228 {
16229 // Assume all defining functions have definingdeclaration links set properly already!!
16230 sameFuncList.push_back(func_decl);
16231 }
16232 }
16233 }
16234
16235#if 0
16236 printf ("func = %p \n",func);
16237 printf ("func->get_definingDeclaration() = %p \n",func->get_definingDeclaration());
16238#endif
16239
16240 ROSE_ASSERT(func != NULL);
16241
16242 if (func->get_definingDeclaration() == func)
16243 {
16244 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16245 isSgFunctionDeclaration(*j)->set_definingDeclaration(func);
16246 }
16247 else
16248 {
16249 ROSE_ASSERT(func != NULL);
16250
16251 // DQ (3/9/2012): Added assertion to avoid empty list that would be an error in both cases below.
16252 ROSE_ASSERT(sameFuncList.empty() == false);
16253
16254 if (func == isSgFunctionDeclaration(*(sameFuncList.begin()))) // is first_nondefining declaration
16255 {
16256 for (j = sameFuncList.begin(); j != sameFuncList.end(); j++)
16257 {
16258 SgFunctionDeclaration* func_decl = isSgFunctionDeclaration(*j);
16259#if 0
16260 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Testing j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16261#endif
16262 // DQ (3/9/2012): Avoid setting the function to be it's own firstNondefiningDeclaration.
16263 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16264 if (func_decl != func)
16265 {
16266 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16267 // isSgFunctionDeclaration(*j)->set_firstNondefiningDeclaration(func);
16268 if (func_decl->get_firstNondefiningDeclaration() == NULL)
16269 {
16270#if 0
16271 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 1) Calling j = %p set_firstNondefiningDeclaration(%p) \n",*j,func);
16272#endif
16273 func_decl->set_firstNondefiningDeclaration(func);
16274 }
16275 }
16276 }
16277 }
16278 else // is a following nondefining declaration, grab any other's first nondefining link then
16279 {
16280#if 0
16281 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Testing func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16282#endif
16283 // DQ (11/18/2013): Modified to only set if not already set (see buildIfStmt.C in tests/nonsmoke/functional/roseTests/astInterface_tests).
16284 // func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16285 if (func->get_firstNondefiningDeclaration() == NULL)
16286 {
16287#if 0
16288 printf ("In SageInterface::updateDefiningNondefiningLinks(): (case 2) Calling func = %p set_firstNondefiningDeclaration(%p) \n",func,isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16289#endif
16290 func->set_firstNondefiningDeclaration(isSgFunctionDeclaration(*(sameFuncList.begin()))->get_firstNondefiningDeclaration());
16291 }
16292 }
16293 }
16294 }
16295
16296PreprocessingInfo* SageInterface::attachComment(SgSourceFile * source_file, const std::string & content, PreprocessingInfo::DirectiveType directive_type, PreprocessingInfo::RelativePositionType position) {
16297 assert(source_file != NULL);
16298 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16299
16300 SgGlobal * global_scope = source_file->get_globalScope();
16301
16302 PreprocessingInfo* result = new PreprocessingInfo(directive_type, content, "Transformation generated",0, 0, 0, position);
16303 ROSE_ASSERT(result);
16304
16305 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16306 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16307 // when multiple files are used on the command line.
16308 result->get_file_info()->setTransformation();
16309
16310 global_scope->addToAttachedPreprocessingInfo(result, position);
16311
16312 return result;
16313}
16314
16315//---------------------------------------------------------------
16317 SgLocatedNode* target, const string& content,
16318 PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/,
16319 PreprocessingInfo::DirectiveType dtype /* PreprocessingInfo::CpreprocessorUnknownDeclaration */)
16320 {
16321 ASSERT_not_null(target); //dangling comment is not allowed
16322
16323 PreprocessingInfo* result = NULL;
16324 PreprocessingInfo::DirectiveType mytype=dtype;
16325 string comment;
16326
16327 // Rasmussen (11/3/2020): Added Ada and Jovial style comments
16328 // DQ (5/5/2010): infer comment type from target's language
16329 if (mytype == PreprocessingInfo::CpreprocessorUnknownDeclaration)
16330 {
16331 // This is a rather expensive way to detect the language type (chases pointers back to the SgFile object).
16332 if (is_C_language() || is_C99_language())
16333 {
16334 // Comment = "/* "+ content + " */";
16335 mytype = PreprocessingInfo::C_StyleComment;
16336 }
16337 else if (is_Cxx_language() || is_Java_language())
16338 {
16339 // Comment = "// "+ content;
16340 mytype = PreprocessingInfo::CplusplusStyleComment;
16341 }
16342 else if (is_Fortran_language() || is_CAF_language()) //FMZ:3/23/2009
16343 {
16344 // Comment = "! "+ content;
16345 mytype = PreprocessingInfo::F90StyleComment;
16346 }
16347 else if (is_Ada_language())
16348 {
16349 // Comment = "-- " + content;
16350 mytype = PreprocessingInfo::AdaStyleComment;
16351 }
16352 else if (is_Jovial_language())
16353 {
16354 // Comment = "% " + content + " %";
16355 mytype = PreprocessingInfo::JovialStyleComment;
16356 }
16357 else
16358 {
16359 cout << "WARNING: SageInterface::attachComment(): Unknown programming language \n";
16360 ROSE_ABORT();
16361 }
16362 }
16363
16364 // Once the langauge type is set (discovered automatically or more directly specified by the user).
16365 bool resetPositionInfo = false;
16366 switch (mytype)
16367 {
16368 case PreprocessingInfo::C_StyleComment: comment = "/* " + content + " */"; break;
16369 case PreprocessingInfo::CplusplusStyleComment: comment = "// " + content; break;
16370 case PreprocessingInfo::FortranStyleComment: comment = " C " + content; break;
16371 case PreprocessingInfo::F90StyleComment: comment = "!" + content; break;
16372 case PreprocessingInfo::AdaStyleComment: comment = "-- " + content; break;
16373 case PreprocessingInfo::JovialStyleComment:
16374 // The Jovial comment content will already have the comment delimiters, '%' or '"'
16375 comment = content;
16376 break;
16377 case PreprocessingInfo::CpreprocessorLineDeclaration:
16378 comment = "#myline " + content;
16379 mytype = PreprocessingInfo::CplusplusStyleComment;
16380 resetPositionInfo = true;
16381 break;
16382 case PreprocessingInfo::CpreprocessorIfndefDeclaration: comment = "#ifndef " + content + "\n"; break;
16383 case PreprocessingInfo::CpreprocessorDefineDeclaration: comment = "#define " + content + "\n"; break;
16384 case PreprocessingInfo::CpreprocessorEndifDeclaration: comment = "#endif" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16385 case PreprocessingInfo::CpreprocessorEnd_ifDeclaration: comment = "#end if" + (content.empty() ? "\n" : (" /* " + content + " */\n")); break;
16386
16387 default:
16388 {
16389 printf ("Error: default in switch reached in SageInterface::attachComment() PreprocessingInfo::DirectiveType == %d \n",mytype);
16390 ROSE_ABORT();
16391 }
16392 }
16393
16394 result = new PreprocessingInfo (mytype,comment, "transformation-generated", 0, 0, 0, position);
16395
16396 // If this is a Cpp Line declaration then we have to set the position to match the statement.
16397 if (resetPositionInfo == true)
16398 {
16399 // Call the Sg_File_Info::operator=() member function.
16400 *(result->get_file_info()) = *(target->get_file_info());
16401 }
16402 else
16403 {
16404 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16405 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16406 // when multiple files are used on the command line.
16407 result->get_file_info()->setTransformation();
16408 }
16409
16410 ASSERT_not_null(result);
16411 target->addToAttachedPreprocessingInfo(result);
16412 return result;
16413 }
16414
16415void SageInterface::guardNode(SgLocatedNode * target, std::string guard) {
16416 PreprocessingInfo * if_macro = new PreprocessingInfo(
16417 PreprocessingInfo::CpreprocessorIfDeclaration,
16418 "#if " + guard,
16419 "transformation-generated", 0, 0, 0,
16420 PreprocessingInfo::before
16421 );
16422 target->addToAttachedPreprocessingInfo(if_macro);
16423
16424 PreprocessingInfo * endif_macro = new PreprocessingInfo(
16425 PreprocessingInfo::CpreprocessorEndifDeclaration,
16426 "#endif",
16427 "transformation-generated", 0, 0, 0,
16428 PreprocessingInfo::after
16429 );
16430 target->addToAttachedPreprocessingInfo(endif_macro);
16431
16432// DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16433// This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16434// when multiple files are used on the command line.
16435 if_macro->get_file_info()->setTransformation();
16436 endif_macro->get_file_info()->setTransformation();
16437}
16438
16439// internal hash table to cache the results: fileHeaderDict[file][header-key]
16440// header-key:
16441// system header : <header.h>
16442// non-system headers : "header.h"
16443static map<SgSourceFile*, map<string, PreprocessingInfo*> > fileHeaderDict;
16445PreprocessingInfo * SageInterface::findHeader(SgSourceFile * source_file, const std::string & header_file_name, bool isSystemHeader)
16446{
16447 string header_key;
16448 if (isSystemHeader)
16449 header_key="<"+header_file_name+">";
16450 else
16451 header_key="\""+header_file_name+"\"";
16452
16453 if (fileHeaderDict.count(source_file) && fileHeaderDict[source_file].count(header_key))
16454 return fileHeaderDict[source_file][header_key];
16455
16456 vector<SgLocatedNode*> candidates;
16457 // do a fresh check. we only check global scope's declarations since we insert header into global scope
16458 // check SgGlobal
16459 SgGlobal* global= source_file -> get_globalScope();
16460
16461 candidates.push_back(global);
16462
16463 //check declarations within the global scope
16464 SgDeclarationStatementPtrList decl_stmt_list = global->get_declarations();
16465 for (SgDeclarationStatementPtrList::iterator iter= decl_stmt_list.begin(); iter!=decl_stmt_list.end(); iter++)
16466 candidates.push_back(*iter);
16467
16468 bool found = false;
16469 for (size_t ci=0; ci<candidates.size(); ci++)
16470 {
16471 SgLocatedNode* locatedNode= candidates[ci];
16472 AttachedPreprocessingInfoType *comments = locatedNode->getAttachedPreprocessingInfo ();
16473
16474 if (comments == NULL) continue;
16475 AttachedPreprocessingInfoType::iterator i;
16476 for (i = comments->begin (); i != comments->end (); i++)
16477 {
16478 if ((*i)->getTypeOfDirective () != PreprocessingInfo::CpreprocessorIncludeDeclaration) continue;
16479 string content = (*i)->getString ();
16480 if (content.find(header_key) != string::npos)
16481 {
16482 fileHeaderDict[source_file][header_key] = *i;
16483 found =true;
16484 break;
16485 }
16486
16487 } // each comment
16488
16489 if (found) break;
16490 } // each node
16491
16492 if (found)
16493 return fileHeaderDict[source_file][header_key];
16494 return NULL;
16495}
16496
16498SageInterface::insertHeader(SgSourceFile * source_file, const string & header_file_name, bool isSystemHeader, PreprocessingInfo::RelativePositionType position)
16499 {
16500 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16501 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16502 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16503 bool supportTokenUnparsing = false;
16504
16505 assert(source_file != NULL);
16506 assert(position == PreprocessingInfo::before || position == PreprocessingInfo::after);
16507
16508 SgGlobal * global_scope = source_file->get_globalScope();
16509
16510 string content;
16511 if (isSystemHeader)
16512 content = "#include <" + header_file_name + "> \n";
16513 else
16514 content = "#include \"" + header_file_name + "\" \n";
16515
16516 PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, position);
16517 ROSE_ASSERT(result);
16518
16519 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16520 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16521 // when multiple files are used on the command line.
16522 result->get_file_info()->setTransformation();
16523
16524 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16525 supportTokenUnparsing = source_file->get_unparse_tokens();
16526 bool supportUnparseHeaders = source_file->get_unparseHeaderFiles();
16527
16528#if 0
16529 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16530 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16531 printf ("source_file = %p \n",source_file);
16532 printf ("global_scope = %p \n",global_scope);
16533#endif
16534#if 0
16535 printf ("Exiting as a test! \n");
16536 ROSE_ABORT();
16537#endif
16538
16539 // global_scope->addToAttachedPreprocessingInfo(result, position);
16540 if (supportTokenUnparsing == false)
16541 {
16542 global_scope->addToAttachedPreprocessingInfo(result, position);
16543 }
16544 else
16545 {
16546 // global_scope->prepend_statement(null_statement);
16547 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16548
16549 if (supportUnparseHeaders == true)
16550 {
16551 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16552 int physical_file_id = global_scope->get_startOfConstruct()->get_physical_file_id();
16553#if 0
16554 printf ("physical_file_id = %d \n",physical_file_id);
16555#endif
16556 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16557 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16558#if 0
16559 printf ("Exiting as a test! \n");
16560 ROSE_ABORT();
16561#endif
16562 }
16563
16564 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16565
16566 global_scope->prepend_statement(emptyDeclaration);
16567 }
16568
16569#if 0
16570 printf ("Exiting as a test! \n");
16571 ROSE_ASSERT(false);
16572#endif
16573
16574 return result;
16575 }
16576
16577PreprocessingInfo* SageInterface::insertHeader(const string& filename, PreprocessingInfo::RelativePositionType position /*=after*/, bool isSystemHeader /*=false*/, SgScopeStatement* scope /*=NULL*/)
16578 {
16579 // DQ (3/22/2019): If we are using the token based unparsing, then this will not work, since the global scope will not
16580 // be marked as a transformation. So it might be better to implement this with an option to support the token based
16581 // unparsing, and specifically add a null declaration so that we can attach the #include directive directly to that statement.
16582 bool supportTokenUnparsing = false;
16583
16584 // DQ (8/12/2020): This is a compiler warning.
16585 // bool successful = false;
16586
16587#if 0
16588 printf ("In SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16589 printf (" --- position = %s \n",PreprocessingInfo::relativePositionName(position).c_str());
16590#endif
16591
16592 if (scope == NULL)
16594
16595 ROSE_ASSERT(scope);
16596
16597 SgGlobal* globalScope = getGlobalScope(scope);
16598 ROSE_ASSERT(globalScope != NULL);
16599
16600 // 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
16601 // if the input scope is within a header file,
16602 // its global scope will jump to a .cpp file. Later looping will not find a match.
16603 SgScopeStatement* srcScope = globalScope;
16604 PreprocessingInfo* result=NULL;
16605 string content;
16606 if (isSystemHeader)
16607 content = "#include <" + filename + "> \n";
16608 else
16609 content = "#include \"" + filename + "\" \n";
16610
16611 // DQ (11/21/2019): Token based unparsing has an additional requirement, we need to mark that the
16612 // whitespace around the statement has been modified. This will trigger the unparser to output
16613 // the comments and CPP directives when using the token-based unparsing. The insertion of a header
16614 // file requires this support else the original token stream will not have the added header file.
16615
16616 // DQ (11/21/2019): Need to set supportTokenUnparsing.
16617 SgSourceFile* sourceFile = getEnclosingSourceFile(scope);
16618 ROSE_ASSERT(sourceFile != NULL);
16619
16620 supportTokenUnparsing = sourceFile->get_unparse_tokens();
16621
16622 bool supportUnparseHeaders = sourceFile->get_unparseHeaderFiles();
16623 // if unparsing header and the scope is within a header file, we adjust srcScope to be scope, not its enclosing global scope
16624 if (supportUnparseHeaders)
16625 {
16626 string filename= scope->get_file_info()->get_filename();
16627 string suffix = Rose::StringUtility ::fileNameSuffix(filename);
16628
16629 // vector.tcc: This is an internal header file, included by other library headers
16630 if (suffix=="h" ||suffix=="hpp"|| suffix=="hh"||suffix=="H" ||suffix=="hxx"||suffix=="h++" ||suffix=="tcc")
16631 srcScope = scope;
16632 }
16633
16634#if 0
16635 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16636 printf ("supportUnparseHeaders = %s \n",supportUnparseHeaders ? "true" : "false");
16637 printf ("sourceFile = %p \n",sourceFile);
16638 printf ("globalScope = %p \n",globalScope);
16639#endif
16640#if 0
16641 printf ("supportTokenUnparsing = %s \n",supportTokenUnparsing ? "true" : "false");
16642#endif
16643#if 0
16644 printf ("Exiting as a test! \n");
16645 ROSE_ABORT();
16646#endif
16647
16648 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations();
16649
16650#if 0
16651 printf ("stmtList.size() = %zu \n",stmtList.size());
16652#endif
16653
16654 if (stmtList.size() > 0) // the source file is not empty
16655 {
16656 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16657 {
16658 // must have this judgement, otherwise wrong file will be modified!
16659 // It could also be the transformation generated statements with #include attached
16660 if ( ((*j)->get_file_info())->isSameFile(srcScope->get_file_info ()) || ((*j)->get_file_info ())->isTransformation() )
16661 {
16662 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16663 ROSE_ASSERT(result != NULL);
16664#if 0
16665 printf ("Building a PreprocessingInfo: result = %p \n",result);
16666#endif
16667 // DQ (3/22/2019): Fixing this to work with the token-based unparsing.
16668 // add to the last position
16669 // TODO: support to add to the first,
16670 // TODO: support fine positioning with #include directives
16671 // (*j)->addToAttachedPreprocessingInfo(result,position);
16672
16673 if (supportTokenUnparsing == false)
16674 {
16675 (*j)->addToAttachedPreprocessingInfo(result,position);
16676 }
16677 else
16678 {
16679 (*j)->addToAttachedPreprocessingInfo(result,position);
16680#if 0
16681 printf ("In SageInterface::insertHeader(): Calling set_containsTransformationToSurroundingWhitespace(true) \n");
16682#endif
16683#if 1
16684 // DQ (12/31/2020): Set the whitespace around the statement as being modified.
16685 (*j)->set_containsTransformationToSurroundingWhitespace(true);
16686#endif
16687#if 0
16688 SgDeclarationStatement* declarationStatement = *j;
16689
16690 // DQ (1/5/2021): Don't call unparseToString, since this triggers the unparer which then unparses
16691 // from the token stream and makrs some token stream elements as already unparsed.
16692 // printf ("declarationStatement = %p = %s unparseToString() = %s \n",declarationStatement,
16693 // declarationStatement->class_name().c_str(),declarationStatement->unparseToString().c_str());
16694 printf ("In SageInterface::insertHeader(): declarationStatement = %p = %s \n",declarationStatement,declarationStatement->class_name().c_str());
16695 printf ("In SageInterface::insertHeader(): declarationStatement->get_containsTransformationToSurroundingWhitespace() = %s \n",
16696 declarationStatement->get_containsTransformationToSurroundingWhitespace() ? "true" : "false");
16697#endif
16698#if 0
16699 // Liao, let's try the new way.
16700 // global_scope->prepend_statement(null_statement);
16701 SgEmptyDeclaration* emptyDeclaration = buildEmptyDeclaration();
16702
16703 if (supportUnparseHeaders == true)
16704 {
16705 // In this case we need to set the physical_file_id to match the target file to be unparsed.
16706 int physical_file_id = globalScope->get_startOfConstruct()->get_physical_file_id();
16707#if 0
16708 printf ("physical_file_id = %d \n",physical_file_id);
16709#endif
16710 emptyDeclaration->get_startOfConstruct()->set_physical_file_id(physical_file_id);
16711 emptyDeclaration->get_endOfConstruct()->set_physical_file_id(physical_file_id);
16712#if 0
16713 printf ("Exiting as a test! \n");
16714 ROSE_ASSERT(false);
16715#endif
16716 }
16717
16718 emptyDeclaration->addToAttachedPreprocessingInfo(result, position);
16719
16720 globalScope->insert_statement(*j,emptyDeclaration);
16721#endif
16722 }
16723#if 0
16724 printf ("break out of for loop: result = %p \n",result);
16725#endif
16726 // DQ (8/12/2020): This is a compiler warning.
16727 // successful = true;
16728 break;
16729 }
16730 }
16731 }
16732 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16733 {
16734 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16735 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16736 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16737 ROSE_ASSERT(false);
16738 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16739 ROSE_ASSERT(result);
16740 globalScope->addToAttachedPreprocessingInfo(result,position);
16741
16742 // DQ (8/12/2020): This is a compiler warning.
16743 // successful = true;
16744 }
16745
16746 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16747 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16748 // when multiple files are used on the command line.
16749 // DQ (3/12/2019): This can be NULL for the omp tests.
16750 if (result != NULL)
16751 {
16752 result->get_file_info()->setTransformation();
16753 }
16754
16755 // must be inserted once somehow
16756 // 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
16757 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16758 // ROSE_ASSERT(successful==true);
16759
16760#if 0
16761 printf ("Exiting as a test! \n");
16762 ROSE_ASSERT(false);
16763#endif
16764
16765#if 0
16766 printf ("Leaving SageInterface::insertHeader(): filename = %s \n",filename.c_str());
16767#endif
16768
16769#if 0
16770 printf ("Exiting as a test! \n");
16771 ROSE_ASSERT(false);
16772#endif
16773
16774 return result;
16775 }
16776
16777
16778// 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
16779void SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader)
16780{
16781 ROSE_ASSERT (stmt != NULL);
16782 ROSE_ASSERT (newheader != NULL);
16783
16784#if 0
16785 printf ("In SageInterface::insertHeader (SgStatement* stmt, PreprocessingInfo* newheader, bool asLastHeader) \n");
16786#endif
16787
16789
16790 if (asLastHeader )
16791 position = PreprocessingInfo::after;
16792 else
16793 position = PreprocessingInfo::before;
16794
16795
16796 // Find existing first and last header.
16797 AttachedPreprocessingInfoType *comments = stmt->getAttachedPreprocessingInfo ();
16798
16799 if (comments != NULL)
16800 {
16801 PreprocessingInfo * firstExistingHeader = NULL;
16802 PreprocessingInfo * lastExistingHeader = NULL;
16803 PreprocessingInfo * firstExistingEndif = NULL;
16804
16805 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16806 // PreprocessingInfo * lastExistingEndif = NULL;
16807
16808 AttachedPreprocessingInfoType::iterator i, firsti, lasti;
16809 for (i = comments->begin (); i != comments->end (); i++)
16810 {
16811 // DQ (9/12/2020): this original code is not sufficent since when the final #include is enclosed in a
16812 // #ifdef #endif the added include directive might not be visible in the generated file.
16813 // This actually happened in the case of wget application: wget.c source file.
16814#if 0
16815 // Original version of code.
16816 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16817 {
16818 // Only set first header for the first time
16819 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16820 {
16821 if (firstExistingHeader == NULL)
16822 {
16823 firstExistingHeader = (*i);
16824 firsti = i;
16825 }
16826 // always updates last header
16827 lastExistingHeader = (*i);
16828 lasti = i;
16829 }
16830 }
16831#else
16832 // DQ (9/12/2020): New version of code. Addresses insertion after last endif if it is after any #include.
16833 if ( (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration ||
16834 (*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration )
16835 {
16836 // Only set first header for the first time
16837 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorIncludeDeclaration)
16838 {
16839 if (firstExistingHeader == NULL)
16840 {
16841 firstExistingHeader = (*i);
16842 firsti = i;
16843 }
16844 // always updates last header
16845 lastExistingHeader = (*i);
16846 lasti = i;
16847 }
16848 if ((*i)->getTypeOfDirective () == PreprocessingInfo::CpreprocessorEndifDeclaration)
16849 {
16850 if (firstExistingEndif == NULL)
16851 {
16852 firstExistingEndif = (*i);
16853 firsti = i;
16854 }
16855 // always updates last header
16856 // DQ (10/27/2020): Fixed warning of unused variable by compiler.
16857 // lastExistingEndif = (*i);
16858 lasti = i;
16859 }
16860 }
16861#endif
16862 }
16863
16864 // based on existing header positions, insert the new header
16865 if (asLastHeader)
16866 {
16867 if (lastExistingHeader == NULL) // No last header at all, just append to after
16868 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16869 else
16870 {
16871 comments->insert (lasti+1, newheader);
16872 }
16873 }
16874 else // add as the first header
16875 {
16876 if (firstExistingHeader == NULL) // no existing header at all, just append to after
16877 stmt->addToAttachedPreprocessingInfo(newheader, PreprocessingInfo::after);
16878 else
16879 {
16880 comments->insert (firsti, newheader);
16881 }
16882 }
16883 }
16884 else // No comments at all, first and last header mean the same, just attach to the located node
16885 stmt->addToAttachedPreprocessingInfo(newheader, position);
16886
16887#if 0
16888 printf ("Exiting as a test! \n");
16889 ROSE_ASSERT(false);
16890#endif
16891
16892}
16893
16894
16895// The recommended version
16896PreprocessingInfo* SageInterface::insertHeader(SgSourceFile * source_file, const std::string & filename, bool isSystemHeader , bool asLastHeader)
16897{
16898 ROSE_ASSERT (source_file != NULL);
16899 SgGlobal* globalScope = source_file->get_globalScope();
16900 ROSE_ASSERT (globalScope != NULL);
16901
16902 PreprocessingInfo* result=NULL;
16903 string content;
16904 if (isSystemHeader)
16905 content = "#include <" + filename + "> \n";
16906 else
16907 content = "#include \"" + filename + "\" \n";
16908
16909#if 0
16910 // 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.
16912
16913 if (asLastHeader )
16914 position = PreprocessingInfo::after;
16915 else
16916 position = PreprocessingInfo::before;
16917#endif
16918
16919 SgDeclarationStatementPtrList & stmtList = globalScope->get_declarations ();
16920 if (stmtList.size()>0) // the source file is not empty
16921 {
16922 for (SgDeclarationStatementPtrList::iterator j = stmtList.begin (); j != stmtList.end (); j++)
16923 {
16924 // Attach to the first eligible located statement
16925 //must have this judgement, otherwise wrong file will be modified!
16926 //It could also be the transformation generated statements with #include attached
16927 if ( (*j)->get_file_info()->isSameFile(globalScope->get_file_info()) || (*j)->get_file_info()->isTransformation() )
16928 {
16929#if 0
16930 printf ("In SageInterface::insertHeader(): Found statement to attached #include: *j = %p = %s \n",*j,(*j)->class_name().c_str());
16931 printf (" --- unparseToString() = %s \n",(*j)->unparseToString().c_str());
16932#endif
16933 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, content, "Transformation generated",0, 0, 0, PreprocessingInfo::before);
16934 ROSE_ASSERT(result);
16935 insertHeader (*j, result, asLastHeader);
16936 //successful = true;
16937#if 0
16938 printf ("Exiting as a test! \n");
16939 ROSE_ABORT();
16940#endif
16941 break;
16942 }
16943 } // end for
16944 }
16945 else // empty file, attach it after SgGlobal,TODO it is not working for unknown reason!!
16946 {
16947 cerr<<"SageInterface::insertHeader() Empty file is found!"<<endl;
16948 cerr<<"#include xxx is preprocessing information which has to be attached to some other located node (a statement for example)"<<endl;
16949 cerr<<"You may have to insert some statement first before inserting a header"<<endl;
16950 ROSE_ABORT();
16951#if 0 // [Robb Matzke 2021-03-24]: unreachable
16952 result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration,
16953 content, "Transformation generated",0, 0, 0, PreprocessingInfo::after);
16954 ROSE_ASSERT(result);
16955 globalScope->addToAttachedPreprocessingInfo(result,position);
16956#endif
16957 // successful = true;
16958 }
16959
16960#if 0
16961 printf ("In SageInterface::insertHeader(): Marking include file for filename = %s as a transformation \n",filename.c_str());
16962#endif
16963
16964 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
16965 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
16966 // when multiple files are used on the command line.
16967 if (result)
16968 result->get_file_info()->setTransformation();
16969
16970#if 0
16971 printf ("Exiting as a test! \n");
16972 ROSE_ASSERT(false);
16973#endif
16974
16975 // must be inserted once somehow
16976 // 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
16977 // The caller function should decide what to do if insertion is failed: ignore vs. assert failure.
16978 // ROSE_ASSERT(successful==true);
16979 return result;
16980
16981} // end insertHeader
16982
16983
16986SageInterface::attachArbitraryText(SgLocatedNode* target, const std::string & text, PreprocessingInfo::RelativePositionType position /*=PreprocessingInfo::before*/)
16987 {
16988 // DQ (1/13/2014): This function needs a better mechanism than attaching text to the AST unparser as a CPP directive.
16989
16990 ROSE_ASSERT(target != NULL); //dangling #define xxx is not allowed in the ROSE AST
16991 PreprocessingInfo* result = NULL;
16992
16993 // DQ (1/13/2014): It is a mistake to attach arbitrary test to the AST as a #define
16994 // (since we evaluate all #define CPP declarations to be a self-referential macro).
16995 // For now I will make it a #if CPP declaration, since these are not evaluated internally.
16996 // PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorDefineDeclaration;
16997 PreprocessingInfo::DirectiveType mytype = PreprocessingInfo::CpreprocessorIfDeclaration;
16998
16999 // DQ (1/13/2014): Output a warning so that this can be fixed whereever it is used.
17000 printf ("Warning: attachArbitraryText(): attaching arbitrary text to the AST as a #if declaration: text = %s \n",text.c_str());
17001
17002 result = new PreprocessingInfo (mytype,text, "transformation-generated", 0, 0, 0, position);
17003 ROSE_ASSERT(result);
17004
17005 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
17006 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
17007 // when multiple files are used on the command line.
17008 result->get_file_info()->setTransformation();
17009
17010 target->addToAttachedPreprocessingInfo(result);
17011
17012 return result;
17013 }
17014
17015
17017// 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.
17019{
17020 // This is part of Wave support in ROSE.
17021// #if CAN_NOT_COMPILE_WITH_ROSE != true
17022// #if CAN_NOT_COMPILE_WITH_ROSE == 0
17023#ifndef USE_ROSE
17024 ROSE_ASSERT(target != NULL);
17025 AttachedPreprocessingInfoType *info= target->getAttachedPreprocessingInfo ();
17026 if (info == NULL) return;
17027 AttachedPreprocessingInfoType::iterator j;
17028 for (j = info->begin (); j != info->end (); j++)
17029 {
17030 if ((*j)->getTypeOfDirective()==PreprocessingInfo::CMacroCall)
17031 {
17032#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
17033 // DQ (2/17/2016): The token_container type is not defined if Wave is not available.
17034 std::ostringstream os;
17035 token_container tc = (*j)->get_macro_call()->expanded_macro;
17036 token_container::const_iterator iter;
17037 for (iter=tc.begin(); iter!=tc.end(); iter++)
17038 os<<(*iter).get_value();
17039 //cout<<"Found a macro call: "<<(*j)->getString()<<
17040 //"\nexpanding it to: "<<os.str()<<endl;
17041 string pragmaText = target->get_pragma()->get_pragma();
17042 string targetString = (*j)->getString();
17043 string replacement = os.str();
17044 // repeat until not found
17045 size_t pos1 = pragmaText.find(targetString);
17046 while (pos1 != string::npos)
17047 {
17048 pragmaText.replace(pos1, targetString.size(), replacement);
17049 pos1 = pragmaText.find(targetString);
17050 }
17051 delete target->get_pragma();
17052 target->set_pragma(buildPragma(pragmaText));
17053#endif
17054 } // end if
17055 } // end for
17056#endif
17057}
17058
17063 using namespace SageBuilder;
17064 SgStatement* body = NULL;
17065 if (isSgWhileStmt(loopOrSwitch) || isSgDoWhileStmt(loopOrSwitch) ||
17066 isSgForStatement(loopOrSwitch)) {
17067 body = SageInterface::getLoopBody(isSgScopeStatement(loopOrSwitch));
17068 } else if (isSgSwitchStatement(loopOrSwitch)) {
17069 body = isSgSwitchStatement(loopOrSwitch)->get_body();
17070 }
17071 ROSE_ASSERT (body);
17072 std::vector<SgBreakStmt*> breaks = SageInterface::findBreakStmts(body);
17073 if (!breaks.empty()) {
17074 static int breakLabelCounter = 0;
17075 SgLabelStatement* breakLabel =
17076 buildLabelStatement("breakLabel" +
17077StringUtility::numberToString(++breakLabelCounter),
17079 isSgScopeStatement(loopOrSwitch->get_parent()));
17080 insertStatement(loopOrSwitch, breakLabel, false);
17081 for (size_t j = 0; j < breaks.size(); ++j) {
17082 SgGotoStatement* newGoto = buildGotoStatement(breakLabel);
17083
17084 isSgStatement(breaks[j]->get_parent())->replace_statement(breaks[j],
17085 newGoto);
17086 newGoto->set_parent(breaks[j]->get_parent());
17087 }
17088 }
17089 }
17090
17092 {
17093 ROSE_ASSERT(node!=NULL);
17094 SgClassDeclaration *decl = isSgClassDeclaration(node);
17095 if (decl==NULL)
17096 return false;
17097 else
17098 return (decl->get_class_type() == SgClassDeclaration::e_struct)? true:false;
17099 }
17100
17102 {
17103 ROSE_ASSERT(node!=NULL);
17104 SgClassDeclaration *decl = isSgClassDeclaration(node);
17105 if (decl==NULL)
17106 return false;
17107 else
17108 return (decl->get_class_type() == SgClassDeclaration::e_union)? true:false;
17109 }
17110
17111
17112void
17113SageInterface::movePreprocessingInfo (SgStatement* stmt_src, SgStatement* stmt_dst, PreprocessingInfo::RelativePositionType src_position/* =PreprocessingInfo::undef */,
17114 PreprocessingInfo::RelativePositionType dst_position/* =PreprocessingInfo::undef */, bool usePrepend /*= false */)
17115 {
17116 ROSE_ASSERT(stmt_src != NULL);
17117 ROSE_ASSERT(stmt_dst != NULL);
17118 AttachedPreprocessingInfoType* infoList = stmt_src->getAttachedPreprocessingInfo();
17119
17120 if (infoList == NULL)
17121 {
17122#if 0
17123 printf ("In SageInterface::movePreprocessingInfo(): infoList == NULL: exiting movePreprocessingInfo() \n");
17124#endif
17125 return;
17126 }
17127
17128 AttachedPreprocessingInfoType* infoToRemoveList = new AttachedPreprocessingInfoType();
17129
17130#if 0
17131 printf ("In SageInterface::movePreprocessingInfo(): \n");
17132 printf (" --- stmt_src = %p = %s src_position = %d \n",stmt_src,stmt_src->class_name().c_str(),src_position);
17133 SgDeclarationStatement* src_declarationStatement = isSgDeclarationStatement(stmt_src);
17134 if (src_declarationStatement != NULL)
17135 {
17136 printf ("src_declarationStatement->get_firstNondefiningDeclaration() = %p \n",src_declarationStatement->get_firstNondefiningDeclaration());
17137 printf ("src_declarationStatement->get_definingDeclaration() = %p \n",src_declarationStatement->get_definingDeclaration());
17138 }
17139 printf (" --- stmt_dst = %p = %s dst_position = %d \n",stmt_dst,stmt_dst->class_name().c_str(),dst_position);
17140 SgDeclarationStatement* dst_declarationStatement = isSgDeclarationStatement(stmt_dst);
17141 if (dst_declarationStatement != NULL)
17142 {
17143 printf ("dst_declarationStatement->get_firstNondefiningDeclaration() = %p \n",dst_declarationStatement->get_firstNondefiningDeclaration());
17144 printf ("dst_declarationStatement->get_definingDeclaration() = %p \n",dst_declarationStatement->get_definingDeclaration());
17145 }
17146 printf (" --- src_position = %s \n",PreprocessingInfo::relativePositionName(src_position).c_str());
17147 printf (" --- dst_position = %s \n",PreprocessingInfo::relativePositionName(dst_position).c_str());
17148 printf (" --- usePrepend = %s \n",usePrepend ? "true" : "false");
17149
17150 printf (" --- infoList = %p \n",infoList);
17151 printf (" --- infoToRemoveList = %p \n",infoToRemoveList);
17152
17153 AttachedPreprocessingInfoType* dst_infoList = stmt_dst->getAttachedPreprocessingInfo();
17154 printf (" --- dst_infoList = %p \n",dst_infoList);
17155#endif
17156#if 0
17157 printf ("****************************************************************** \n");
17158 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_src \n");
17160 printf ("In SageInterface::movePreprocessingInfo(): Attached comments and CPP directives: stmt_dst \n");
17162 printf ("****************************************************************** \n");
17163#endif
17164
17165 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
17166 // This is a bug in the support for building a new prototype from a defining function declaration
17167 // and caused this problem. This assertion will prevent this sort of error from happening again.
17168 ROSE_ASSERT(infoList == NULL || stmt_src->getAttachedPreprocessingInfo() != stmt_dst->getAttachedPreprocessingInfo());
17169
17170
17171#if 0
17172 printf (" --- infoList->size() = %zu \n",infoList->size());
17173 printf (" --- infoToRemoveList->size() = %zu \n",infoToRemoveList->size());
17174#endif
17175
17176#if 0
17177 int counter = 0;
17178
17179 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
17180 {
17181 // DQ (11/19/2020): Added assertion.
17182 ROSE_ASSERT(*i != NULL);
17183
17184 // DQ (11/19/2020): Why do we have a dynamic cast here.
17185 // PreprocessingInfo * info = dynamic_cast<PreprocessingInfo*> (*i);
17186 PreprocessingInfo * info = *i;
17187 ROSE_ASSERT(info != NULL);
17188
17189 // printf ("counter = %d \n",counter);
17190 printf ("counter = %d Processing PreprocessingInfo = %s \n",counter,info->getString().c_str());
17191 counter++;
17192 }
17193
17194 counter = 0;
17195#endif
17196
17197 PreprocessingInfo* prevItem = NULL;
17198
17199 for (Rose_STL_Container<PreprocessingInfo*>::iterator i = (*infoList).begin(); i != (*infoList).end(); i++)
17200 {
17201 ROSE_ASSERT(*i != NULL);
17202
17203 PreprocessingInfo * info = *i;
17204 ROSE_ASSERT(info != NULL);
17205
17206 if ( // match enum values in http://rosecompiler.org/ROSE_HTML_Reference/classPreprocessingInfo.html
17207 (info->getTypeOfDirective()==PreprocessingInfo::C_StyleComment)||
17208 (info->getTypeOfDirective()==PreprocessingInfo::CplusplusStyleComment)||
17209 (info->getTypeOfDirective()==PreprocessingInfo::FortranStyleComment)||
17210 (info->getTypeOfDirective()==PreprocessingInfo::F90StyleComment)||
17211 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeDeclaration )||
17212 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIncludeNextDeclaration )||
17213 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDefineDeclaration )||
17214 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorUndefDeclaration)||
17215 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfdefDeclaration )||
17216 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfndefDeclaration )||
17217 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorIfDeclaration )||
17218 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorDeadIfDeclaration )||
17219 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElseDeclaration )||
17220 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorElifDeclaration )||
17221 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEndifDeclaration ) ||
17222 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorEnd_ifDeclaration ) ||
17223 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorLineDeclaration) ||
17224 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorErrorDeclaration) ||
17225 (info->getTypeOfDirective()==PreprocessingInfo::CpreprocessorWarningDeclaration) ||
17226 // DQ (12/28/2020): Added support for C linkage specifications.
17227 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationStart) ||
17228 (info->getTypeOfDirective()==PreprocessingInfo::ClinkageSpecificationEnd)
17229 )
17230 {
17231 // move all source preprocessing info if the desired source type is not specified or matching
17232 // a specified desired source type
17233 if ( src_position == PreprocessingInfo::undef || info->getRelativePosition() == src_position)
17234 {
17235 if (usePrepend == true)
17236 {
17237 // Liao (1/27/2015): modification to fix order of CPP directives when a list of them are moved.
17238 if (prevItem == NULL)
17239 {
17240 // addToAttachedPreprocessingInfo() is poorly designed, the last parameter is used
17241 // to indicate appending or prepending by reusing the type of relative position.
17242 // this is very confusing for users
17243 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::before);
17244 }
17245 else // there is a previous item, insert after it
17246 {
17247 stmt_dst->insertToAttachedPreprocessingInfo(info, prevItem);
17248 }
17249 prevItem = info;
17250 }
17251 else
17252 {
17253 stmt_dst->addToAttachedPreprocessingInfo(info,PreprocessingInfo::after);
17254 }
17255 // 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.
17256 info->setAsTransformation();
17257
17258 // DQ (10/13/2015): This is a problem for the token-based unparsing since we don't want to have this
17259 // set_containsTransformationToSurroundingWhitespace() function cause the isModified flag to be set.
17260 // So we have to detect it being set and reset it as needed. An alternative would be to have a
17261 // non-ROSETTA generate function that didn't have the isModified flag set for the seter access function.
17262 // Note that the inputmoveDeclarationToInnermostScope_test2015_123.C file demonstrates this problem.
17263 bool isMarkedAsModified = stmt_dst->get_isModified();
17264 stmt_dst->set_containsTransformationToSurroundingWhitespace(true);
17265 if (isMarkedAsModified == false)
17266 {
17267 if (stmt_dst->get_isModified() == true)
17268 {
17269 stmt_dst->set_isModified(false);
17270 }
17271 }
17272 (*infoToRemoveList).push_back(*i);
17273 }
17274
17275 // adjust dst position if needed
17276 if (dst_position != PreprocessingInfo::undef)
17277 {
17278 info->setRelativePosition(dst_position);
17279 }
17280 } // end if
17281 } // end for
17282
17283 // Remove the element from the list of comments at the current astNode
17284 AttachedPreprocessingInfoType::iterator j;
17285 for (j = (*infoToRemoveList).begin(); j != (*infoToRemoveList).end(); j++)
17286 {
17287 infoList->erase( find(infoList->begin(),infoList->end(),*j) );
17288 }
17289 }
17290
17291
17292//----------------------------
17293// Sometimes, the preprocessing info attached to a declaration has to be
17294// moved 'up' if another declaration is inserted before it.
17295// This is a workaround for the broken LowLevelRewrite::insert() and the private
17296// LowLevelRewrite::reassociatePreprocessorDeclarations()
17297//
17298// input:
17299// *stmt_dst: the new inserted declaration
17300// *stmt_src: the existing declaration with preprocessing information
17301// tasks:
17302// judge if stmt_src has propressingInfo with headers, ifdef, etc..
17303// add them into stmt_dst
17304// delete them from stmt_dst
17305// More general usage: move preprocessingInfo of stmt_src to stmt_dst, should used before any
17306// LoweLevel::remove(stmt_src)
17308 PreprocessingInfo::RelativePositionType src_position/*=PreprocessingInfo::undef*/,
17309 PreprocessingInfo::RelativePositionType dst_position/*=PreprocessingInfo::undef*/,
17310 bool usePrepend /*= false */)
17311 {
17312 movePreprocessingInfo (stmt_src, stmt_dst, src_position, dst_position, usePrepend);
17313 } // moveUpPreprocessingInfo()
17314
17315
17320static bool isNotRelPos (const PreprocessingInfo* info,
17322{
17323 return info && (info->getRelativePosition () != pos);
17324}
17325
17330static bool isRelPos (const PreprocessingInfo* info,
17332{
17333 return info && !isNotRelPos (info, pos);
17334}
17335
17336
17338void SageInterface::cutPreprocessingInfo (SgLocatedNode* src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17339{
17340 ASSERT_not_null(src_node);
17341
17342 // [Rasmussen,Sottile 2023.01.10]: Replaced deleted bind2nd (as of 2017)
17343 AttachedPreprocessingInfoType* info = src_node->get_attachedPreprocessingInfoPtr();
17344 if (info)
17345 {
17346 // copy elements to save_buf where isRelPos() is false
17347 remove_copy_if(info->begin(),
17348 info->end(),
17349 back_inserter(save_buf),
17350 [pos](auto x) { return !isRelPos(x, pos); }
17351 );
17352
17353 // delete copied elements from save_buf
17354 AttachedPreprocessingInfoType::iterator
17355 new_end = remove_if(info->begin(),
17356 info->end(),
17357 [pos](auto x) { return isRelPos(x, pos); }
17358 );
17359 info->erase(new_end, info->end());
17360 }
17361}
17362
17363static AttachedPreprocessingInfoType *
17364createInfoList (SgLocatedNode* s)
17365{
17366 ROSE_ASSERT (s);
17367 AttachedPreprocessingInfoType* info_list = s->get_attachedPreprocessingInfoPtr ();
17368 if (!info_list)
17369 {
17370 info_list = new AttachedPreprocessingInfoType;
17371 ROSE_ASSERT (info_list);
17372 s->set_attachedPreprocessingInfoPtr (info_list);
17373 }
17374
17375 // Guarantee a non-NULL pointer.
17376 ROSE_ASSERT (info_list);
17377 return info_list;
17378}
17379
17381void SageInterface::pastePreprocessingInfo (SgLocatedNode* dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType& save_buf)
17382{
17383 if (save_buf.size()==0) return;
17384 // if front
17385 AttachedPreprocessingInfoType* info = createInfoList (dst_node);
17386 ROSE_ASSERT (info);
17387
17388 // DQ (9/26/2007): Commented out as part of move from std::list to std::vector
17389 // printf ("Commented out front_inserter() as part of move from std::list to std::vector \n");
17390 // copy (save_buf.rbegin (), save_buf.rend (), front_inserter (*info));
17391
17392 // Liao (10/3/2007), vectors can only be appended at the rear
17393 if (pos==PreprocessingInfo::before)
17394 {
17395 for(AttachedPreprocessingInfoType::reverse_iterator i=save_buf.rbegin();i!=save_buf.rend();i++)
17396 info->insert(info->begin(),*i);
17397 }
17398 // if back
17399 else if (pos==PreprocessingInfo::after)
17400 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17401 else if (pos==PreprocessingInfo::inside)
17402 {
17403 copy (save_buf.begin (), save_buf.end (), back_inserter (*info));
17404 cerr<<"SageInterface::pastePreprocessingInfo() pos==PreprocessingInfo::inside is not supported."<<endl;
17405 save_buf[0]->display("ttt");
17406 }
17407}
17408
17410{
17411 ROSE_ASSERT(locatedNode != NULL);
17412 AttachedPreprocessingInfoType *comments =
17413 locatedNode->getAttachedPreprocessingInfo ();
17414
17415 if (comments != NULL)
17416 {
17417 printf ("-----------------------------------------------\n");
17418 printf ("Found an IR node (at %p of type: %s) in file %s \n",
17419 locatedNode, locatedNode->class_name ().c_str (),
17420 (locatedNode->get_file_info ()->get_filenameString ()).c_str ());
17421 int counter = 0;
17422 AttachedPreprocessingInfoType::iterator i;
17423 for (i = comments->begin (); i != comments->end (); i++)
17424 {
17425 printf
17426 ("with attached preprocessingInfo numbering #%d :------------- \nclassification= %s:\nString format:%s\n",
17427 counter++,
17428 PreprocessingInfo::directiveTypeName ((*i)->getTypeOfDirective ()).
17429 c_str (), (*i)->getString ().c_str ());
17430 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
17431 printf ("relative position is: inside\n");
17432 else
17433 printf ("relative position is: %s\n", \
17434 ((*i)->getRelativePosition () == PreprocessingInfo::before) ? "before" : "after");
17435 }
17436 }
17437 else
17438 {
17439 printf ("No attached preprocessing info. (at %p of type: %s): \n", locatedNode,
17440 locatedNode->sage_class_name ());
17441 }
17442}
17443
17455template <class ParentNode>
17456static
17457SgBasicBlock* ensureBasicBlock_aux( ParentNode& stmt,
17458 SgStatement* (ParentNode::*getter) () const,
17459 void (ParentNode::*setter) (SgStatement*)
17460 )
17461{
17462 SgStatement* const body_stmt = (stmt.*getter)();
17463 SgBasicBlock* basicblock = isSgBasicBlock(body_stmt);
17464
17465 if (basicblock == NULL) {
17466 basicblock = SageBuilder::buildBasicBlock(body_stmt);
17467 (stmt.*setter)(basicblock);
17468 basicblock->set_parent(&stmt);
17469 }
17470
17471 ROSE_ASSERT (basicblock != NULL);
17472 return basicblock;
17473}
17474
17476{
17477 SgStatement* b = fs->get_loop_body();
17478 if (!isSgBasicBlock(b)) {
17480 fs->set_loop_body(b);
17481 b->set_parent(fs);
17482
17483 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17485 }
17486 ROSE_ASSERT (isSgBasicBlock(b));
17487 return isSgBasicBlock(b);
17488}
17489
17491{
17492 SgStatement* b = cs->get_body();
17493 if (!isSgBasicBlock(b)) {
17495 cs->set_body(b);
17496 b->set_parent(cs);
17497
17498 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17500 }
17501 ROSE_ASSERT (isSgBasicBlock(b));
17502 return isSgBasicBlock(b);
17503}
17504
17506{
17507 SgStatement* b = cs->get_body();
17508 if (!isSgBasicBlock(b)) {
17510 cs->set_body(b);
17511 b->set_parent(cs);
17512
17513 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17515 }
17516 ROSE_ASSERT (isSgBasicBlock(b));
17517 return isSgBasicBlock(b);
17518}
17519
17521{
17522 ROSE_ASSERT (fs != NULL);
17523
17524 return ensureBasicBlock_aux(*fs, &SgUpcForAllStatement::get_loop_body, &SgUpcForAllStatement::set_loop_body);
17525}
17526
17528 SgStatement* b = fs->get_body();
17529 if (!isSgBasicBlock(b)) {
17531 fs->set_body(b);
17532 b->set_parent(fs);
17533
17534 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17536 }
17537 ROSE_ASSERT (isSgBasicBlock(b));
17538 return isSgBasicBlock(b);
17539 }
17540
17542 SgStatement* b = fs->get_body();
17543 if (!isSgBasicBlock(b)) {
17545 fs->set_body(b);
17546 b->set_parent(fs);
17547
17548 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17550 }
17551 ROSE_ASSERT (isSgBasicBlock(b));
17552 return isSgBasicBlock(b);
17553 }
17554
17556 SgStatement* b = fs->get_body();
17557 if (!isSgBasicBlock(b)) {
17559 fs->set_body(b);
17560 b->set_parent(fs);
17561
17562 // DQ (1/21/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17564 }
17565 ROSE_ASSERT (isSgBasicBlock(b));
17566 return isSgBasicBlock(b);
17567 }
17568
17570 SgStatement* b = fs->get_true_body();
17571 if (!isSgBasicBlock(b)) {
17573 fs->set_true_body(b);
17574 b->set_parent(fs);
17575
17576 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17578#if 0
17579 printf ("In SageInterface::ensureBasicBlockAsTrueBodyOfIf(): Added SgBasicBlock b = %p to addedBasicBlockNodes.size() = %zu \n",b,addedBasicBlockNodes.size());
17580#endif
17581 }
17582 ROSE_ASSERT (isSgBasicBlock(b));
17583 return isSgBasicBlock(b);
17584 }
17585
17586// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17588 {
17589 // Record where normalization have been done so that we can preform denormalizations as required
17590 // for the token-based unparsing to generate minimal diffs.
17591
17592 SgBasicBlock* bb = isSgBasicBlock(s);
17593 ROSE_ASSERT(bb != NULL);
17594 addedBasicBlockNodes.push_back(bb);
17595#if 0
17596 printf ("In SageInterface::recordNormalizations(): Added SgBasicBlock = %p to addedBasicBlockNodes.size() = %zu \n",bb,addedBasicBlockNodes.size());
17597#endif
17598 }
17599
17600// DQ (1/18/2015): This is added to support better quality token-based unparsing.
17602 {
17603 // Remove unused basic block IR nodes added as part of normalization.
17604 // This function should be called before the unparse step.
17605
17606#if 0
17607 printf ("In SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17608#endif
17609
17610 for (vector<SgBasicBlock*>::iterator i = addedBasicBlockNodes.begin(); i != addedBasicBlockNodes.end(); i++)
17611 {
17612 SgBasicBlock* b = *i;
17613 ROSE_ASSERT(b != NULL);
17614 if (b->get_statements().size() == 1)
17615 {
17616#if 0
17617 printf ("This SgBasicBlock can be denormalized: b = %p \n",b);
17618#endif
17619 SgStatement* parentOfBlock = isSgStatement(b->get_parent());
17620 ROSE_ASSERT(parentOfBlock != NULL);
17621
17622 bool wasPreviouslyModified = parentOfBlock->get_isModified();
17623
17624 SgStatement* s = b->get_statements()[0];
17625 ROSE_ASSERT(s != NULL);
17626
17627 switch (parentOfBlock->variantT())
17628 {
17629 case V_SgIfStmt:
17630 {
17631 SgIfStmt* ifStatement = isSgIfStmt(parentOfBlock);
17632 if (b == ifStatement->get_true_body())
17633 {
17634#if 0
17635 printf ("Calling set_true_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17636#endif
17637 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17638 ifStatement->set_true_body(s);
17639#if 0
17640 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17641#endif
17642 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17643 s->set_parent(ifStatement);
17644#if 0
17645 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17646#endif
17647 *i = NULL;
17648 // delete b;
17649 }
17650 else
17651 {
17652 ROSE_ASSERT(b == ifStatement->get_false_body());
17653#if 0
17654 printf ("Calling set_false_body on ifStatement = %p = %s \n",ifStatement,ifStatement->class_name().c_str());
17655#endif
17656 // DQ (10/6/2015): This member function call is causing the IR node to be marked as transformed.
17657 ifStatement->set_false_body(s);
17658#if 0
17659 printf ("Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17660#endif
17661 // DQ (10/6/2015): Calls to the set_parent member function do NOT cause the either node to be marked as isModfied.
17662 s->set_parent(ifStatement);
17663#if 0
17664 printf ("DONE: Calling set_parent on s = %p = %n \n",s,s->class_name().c_str());
17665#endif
17666 *i = nullptr;
17667#if 0
17668 printf ("Mark as NOT modified after calling set_false_body on ifStatement = %p = %n \n",ifStatement,ifStatement->class_name().c_str());
17669#endif
17670#if 0
17671 printf ("Error: case not handled in case V_SgIfStmt: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17672 ROSE_ABORT();
17673#endif
17674 }
17675 break;
17676 }
17677
17678 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17679 case V_SgWhileStmt:
17680 {
17681 SgWhileStmt* whileStatement = isSgWhileStmt(parentOfBlock);
17682 if (b == whileStatement->get_body())
17683 {
17684 whileStatement->set_body(s);
17685 s->set_parent(whileStatement);
17686 }
17687 break;
17688 }
17689
17690 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17691 case V_SgSwitchStatement:
17692 {
17693 SgSwitchStatement* switchStatement = isSgSwitchStatement(parentOfBlock);
17694 if (b == switchStatement->get_body())
17695 {
17696 switchStatement->set_body(s);
17697 s->set_parent(switchStatement);
17698 }
17699 break;
17700 }
17701
17702 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17703 case V_SgForStatement:
17704 {
17705 SgForStatement* forStatement = isSgForStatement(parentOfBlock);
17706 if (b == forStatement->get_loop_body())
17707 {
17708 forStatement->set_loop_body(s);
17709 s->set_parent(forStatement);
17710 }
17711 break;
17712 }
17713
17714 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17715 case V_SgCaseOptionStmt:
17716 {
17717 SgCaseOptionStmt* caseOptionStatement = isSgCaseOptionStmt(parentOfBlock);
17718 if (b == caseOptionStatement->get_body())
17719 {
17720 caseOptionStatement->set_body(s);
17721 s->set_parent(caseOptionStatement);
17722 }
17723 break;
17724 }
17725
17726 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17727 case V_SgDefaultOptionStmt:
17728 {
17729 SgDefaultOptionStmt* defaultOptionStatement = isSgDefaultOptionStmt(parentOfBlock);
17730 if (b == defaultOptionStatement->get_body())
17731 {
17732 defaultOptionStatement->set_body(s);
17733 s->set_parent(defaultOptionStatement);
17734 }
17735 break;
17736 }
17737
17738 // DQ (1/21/2015): Adding support for de-normalization of while statements with normalized bodies.
17739 case V_SgDoWhileStmt:
17740 {
17741 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(parentOfBlock);
17742 if (b == doWhileStatement->get_body())
17743 {
17744 doWhileStatement->set_body(s);
17745 s->set_parent(doWhileStatement);
17746 }
17747 break;
17748 }
17749
17750 default:
17751 {
17752 printf ("Error: case not handled in switch: parentOfBlock = %p = %s \n",parentOfBlock,parentOfBlock->class_name().c_str());
17753 ROSE_ABORT();
17754 }
17755 }
17756
17757 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
17758 if (wasPreviouslyModified == false)
17759 {
17760 if (parentOfBlock->get_isModified() == true)
17761 {
17762#if 0
17763 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());
17764#endif
17765 parentOfBlock->set_isModified(false);
17766 }
17767
17768 }
17769#if 0
17770 printf ("Exiting as a test! \n");
17771 ROSE_ABORT();
17772#endif
17773 }
17774 }
17775
17776#if 0
17777 printf ("Leaving SageInterface::cleanupNontransformedBasicBlockNode(): addedBasicBlockNodes.size() = %zu \n",addedBasicBlockNodes.size());
17778#endif
17779 }
17780
17781
17783 SgStatement* b = fs->get_false_body();
17784 // if no false body at all AND no-create-empty-body
17785 if (!createEmptyBody && (b == NULL || isSgNullStatement(b)))
17786 return NULL;
17787 if (!isSgBasicBlock(b)) {
17788 b = SageBuilder::buildBasicBlock(b); // This works if b is NULL as well (producing an empty block)
17789 fs->set_false_body(b);
17790 b->set_parent(fs);
17791
17792 // DQ (1/18/2015): Save the SgBasicBlock that has been added so that we can undo this transformation later.
17794 }
17795 ROSE_ASSERT (isSgBasicBlock(b));
17796 return isSgBasicBlock(b);
17797 }
17798
17800 SgStatement* b = fs->get_body();
17801 if (!isSgBasicBlock(b)) {
17803 fs->set_body(b);
17804 b->set_parent(fs);
17805 }
17806 ROSE_ASSERT (isSgBasicBlock(b));
17807 return isSgBasicBlock(b);
17808 }
17809
17811{
17812 SgStatement* b = fs->get_body();
17813 if (!isSgBasicBlock(b)) {
17815 fs->set_body(b);
17816 b->set_parent(fs);
17817 }
17818 ROSE_ASSERT (isSgBasicBlock(b));
17819 return isSgBasicBlock(b);
17820}
17821
17823{
17824 bool rt = false;
17825 ROSE_ASSERT(s);
17826 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17827 ROSE_ASSERT(p);
17828
17829 switch (p->variantT())
17830 {
17831 case V_SgForStatement:
17832 {
17833 if (isSgForStatement(p)->get_loop_body() == s)
17834 rt = true;
17835 break;
17836 }
17837 case V_SgUpcForAllStatement: // PP
17838 {
17839 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17840 if (upcforall.get_loop_body() == s)
17841 rt = true;
17842 break;
17843 }
17844 case V_SgWhileStmt:
17845 {
17846 if (isSgWhileStmt(p)->get_body() == s)
17847 rt = true;
17848 break;
17849 }
17850 case V_SgDoWhileStmt:
17851 {
17852 if (isSgDoWhileStmt(p)->get_body() == s)
17853 rt = true;
17854 break;
17855 }
17856 case V_SgSwitchStatement:
17857 {
17858 if (isSgSwitchStatement(p)->get_body() == s)
17859 rt = true;
17860 break;
17861 }
17862 case V_SgCaseOptionStmt:
17863 {
17864 if (isSgCaseOptionStmt(p)->get_body() == s)
17865 rt = true;
17866 break;
17867 }
17868 case V_SgDefaultOptionStmt:
17869 {
17870 if (isSgDefaultOptionStmt(p)->get_body() == s)
17871 rt = true;
17872 break;
17873 }
17874 case V_SgCatchOptionStmt:
17875 {
17876 if (isSgCatchOptionStmt(p)->get_body() == s)
17877 rt = true;
17878 break;
17879 }
17880 case V_SgIfStmt:
17881 {
17882 if (isSgIfStmt(p)->get_true_body() == s)
17883 rt = true;
17884 else if (isSgIfStmt(p)->get_false_body() == s)
17885 rt = true;
17886 break;
17887 }
17888 default:
17889 {
17890 if (isSgOmpBodyStatement(p))
17891 rt = true;
17892 break;
17893 }
17894 }
17895 return rt;
17896}
17897
17899//etc.
17901{
17902 ROSE_ASSERT (singleStmt != NULL); // not NULL
17903 ROSE_ASSERT (isSgBasicBlock(singleStmt) == NULL); //not a block
17904 ROSE_ASSERT (isBodyStatement(singleStmt) == true); // is a body statement
17905
17906 SgBasicBlock* rt = NULL;
17907
17908
17909
17910 SgStatement* s = singleStmt;
17911 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17912 ROSE_ASSERT(p);
17913 switch (p->variantT())
17914 {
17915 case V_SgForStatement:
17916 {
17917 if (isSgForStatement(p)->get_loop_body() == s)
17918 rt = ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
17919 break;
17920 }
17921 case V_SgUpcForAllStatement: // PP
17922 {
17923 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
17924
17925 if (upcforall.get_loop_body() == s)
17926 rt = ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
17927 break;
17928 }
17929 case V_SgWhileStmt:
17930 {
17931 if (isSgWhileStmt(p)->get_body() == s)
17932 rt = ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
17933 break;
17934 }
17935 case V_SgDoWhileStmt:
17936 {
17937 if (isSgDoWhileStmt(p)->get_body() == s)
17938 rt = ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
17939 break;
17940 }
17941 case V_SgSwitchStatement:
17942 {
17943 if (isSgSwitchStatement(p)->get_body() == s)
17944 rt = ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
17945 break;
17946 }
17947 case V_SgCaseOptionStmt:
17948 {
17949 if (isSgCaseOptionStmt(p)->get_body() == s)
17950 rt = ensureBasicBlockAsBodyOfCaseOption(isSgCaseOptionStmt(p));
17951 break;
17952 }
17953 case V_SgDefaultOptionStmt:
17954 {
17955 if (isSgDefaultOptionStmt(p)->get_body() == s)
17956 rt = ensureBasicBlockAsBodyOfDefaultOption(isSgDefaultOptionStmt(p));
17957 break;
17958 }
17959 case V_SgCatchOptionStmt:
17960 {
17961 if (isSgCatchOptionStmt(p)->get_body() == s)
17962 rt = ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
17963 break;
17964 }
17965 case V_SgIfStmt:
17966 {
17967 if (isSgIfStmt(p)->get_true_body() == s)
17968 rt = ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
17969 else if (isSgIfStmt(p)->get_false_body() == s)
17970 rt = ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
17971 break;
17972 }
17973 default:
17974 {
17975 if (isSgOmpBodyStatement(p))
17976 {
17977 rt = ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
17978 }
17979 break;
17980 }
17981 }
17982 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.
17983 return rt;
17984}
17985
17986#if 0
17987SgLocatedNode* SageInterface::ensureBasicBlockAsParent(SgStatement* s)
17988{
17989 ROSE_ASSERT(s);
17990
17991 //Vulov: The parent of a statement is not necessarily a statement. It could be SgStatementExpression
17992 SgLocatedNode* p = isSgLocatedNode(s->get_parent());
17993 ROSE_ASSERT(p);
17994 switch (p->variantT())
17995 {
17996 case V_SgBasicBlock: return isSgBasicBlock(p);
17997 case V_SgForStatement:
17998 {
17999 if (isSgForStatement(p)->get_loop_body() == s)
18000 return ensureBasicBlockAsBodyOfFor(isSgForStatement(p));
18001 else if (isSgForStatement(p)->get_test() == s)
18002 {
18003 }
18004 else if (isSgForStatement(p)->get_for_init_stmt() == s)
18005 {
18006 }
18007 else ROSE_ABORT();
18008 break;
18009 }
18010 case V_SgUpcForAllStatement: // PP
18011 {
18012 SgUpcForAllStatement& upcforall = *isSgUpcForAllStatement(p);
18013
18014 if (upcforall.get_loop_body() == s)
18015 return ensureBasicBlockAsBodyOfUpcForAll(&upcforall);
18016
18017 ROSE_ASSERT( (s == upcforall.get_for_init_stmt())
18018 || (s == upcforall.get_test())
18019 );
18020 break;
18021 }
18022 case V_SgWhileStmt:
18023 {
18024 if (isSgWhileStmt(p)->get_body() == s)
18025 return ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(p));
18026 else if (isSgWhileStmt(p)->get_condition() == s)
18027 {
18028 }
18029 else ROSE_ABORT();
18030 break;
18031 }
18032 case V_SgDoWhileStmt:
18033 {
18034 if (isSgDoWhileStmt(p)->get_body() == s)
18035 return ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(p));
18036 else if (isSgDoWhileStmt(p)->get_condition() == s)
18037 {
18038 }
18039 else ROSE_ABORT();
18040 break;
18041 }
18042 case V_SgSwitchStatement:
18043 {
18044 if (isSgSwitchStatement(p)->get_body() == s)
18045 return ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(p));
18046 else if (isSgSwitchStatement(p)->get_item_selector() == s)
18047 {
18048 }
18049 else ROSE_ABORT();
18050 break;
18051 }
18052 case V_SgCatchOptionStmt:
18053 {
18054 if (isSgCatchOptionStmt(p)->get_body() == s)
18055 return ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(p));
18056 else if (isSgCatchOptionStmt(p)->get_condition() == s)
18057 {
18058 }
18059 else ROSE_ABORT();
18060 break;
18061 }
18062 case V_SgIfStmt:
18063 {
18064 if (isSgIfStmt(p)->get_true_body() == s)
18065 return ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(p));
18066 else if (isSgIfStmt(p)->get_false_body() == s)
18067 return ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(p));
18068 else if (isSgIfStmt(p)->get_conditional() == s)
18069 {
18070 }
18071 else ROSE_ABORT();
18072 break;
18073 }
18074 default:
18075 {
18076 if (isSgOmpBodyStatement(p))
18077 {
18078 return ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(p));
18079 }
18080 else
18081 // Liao, 7/3/2008 We allow other conditions to fall through,
18082 // they are legal parents with list of statements as children.
18083 //cerr << "Unhandled parent block:"<< p->class_name() << endl;
18084 // ROSE_ASSERT (!"Bad parent in ensureBasicBlockAsParent");
18085 break;
18086 }
18087 }
18088 return p;
18089}
18090
18091 void SageInterface::changeAllLoopBodiesToBlocks(SgNode* top) {
18092 cerr<<"Warning: SageInterface::changeAllLoopBodiesToBlocks() is being replaced by SageInterface::changeAllBodiesToBlocks()."<<endl;
18093 cerr<<"Please use SageInterface::changeAllBodiesToBlocks() if you can."<<endl;
18095 }
18096
18097#endif
18098 void SageInterface::changeAllBodiesToBlocks(SgNode* top, bool createEmptyBody /*= true*/ ) {
18099 class Visitor: public AstSimpleProcessing {
18100 public:
18101 bool allowEmptyBody;
18102 Visitor (bool flag):allowEmptyBody(flag) {}
18103 virtual void visit(SgNode* n) {
18104
18105 bool wasPreviouslyModified = n->get_isModified();
18106
18107 switch (n->variantT()) {
18108 case V_SgForStatement: {
18109 ensureBasicBlockAsBodyOfFor(isSgForStatement(n));
18110 break;
18111 }
18112 case V_SgWhileStmt: {
18113 ensureBasicBlockAsBodyOfWhile(isSgWhileStmt(n));
18114 break;
18115 }
18116 case V_SgDoWhileStmt: {
18117 ensureBasicBlockAsBodyOfDoWhile(isSgDoWhileStmt(n));
18118 break;
18119 }
18120 case V_SgSwitchStatement: {
18121 ensureBasicBlockAsBodyOfSwitch(isSgSwitchStatement(n));
18122 break;
18123 }
18124 case V_SgIfStmt: {
18125 ensureBasicBlockAsTrueBodyOfIf(isSgIfStmt(n));
18126 ensureBasicBlockAsFalseBodyOfIf(isSgIfStmt(n), allowEmptyBody);
18127#if 0
18128 // DQ (10/6/2015): Debugging why changes are being made to the AST for token-based unparsing.
18129 printf ("In changeAllBodiesToBlocks(): case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
18130#endif
18131#if 0
18132 // Reset this to false as a test.
18133 if (n->get_isModified() == true)
18134 {
18135 n->set_isModified(false);
18136 printf ("In changeAllBodiesToBlocks(): AFTER RESET: case SgIfStmt: n->get_isModified() = %s \n",n->get_isModified() ? "true" : "false");
18137 }
18138#endif
18139 break;
18140 }
18141 case V_SgCatchOptionStmt: {
18142 ensureBasicBlockAsBodyOfCatch(isSgCatchOptionStmt(n));
18143 break;
18144 }
18145 case V_SgUpcForAllStatement: {
18146 ensureBasicBlockAsBodyOfUpcForAll(isSgUpcForAllStatement(n));
18147 break;
18148 }
18149
18150 default:
18151 {
18152 if (isSgOmpBodyStatement(n))
18153 ensureBasicBlockAsBodyOfOmpBodyStmt(isSgOmpBodyStatement(n));
18154 break;
18155 }
18156 }
18157
18158 // DQ (10/6/2015): Added code to reset isModified flag if it was only modified by this function.
18159 if (wasPreviouslyModified == false)
18160 {
18161 if (n->get_isModified() == true)
18162 {
18163#if 0
18164 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());
18165#endif
18166 n->set_isModified(false);
18167 }
18168
18169 }
18170
18171 }
18172 };
18173 Visitor(createEmptyBody).traverse(top, postorder);
18174 }
18175
18176
18177// Replace a given expression with a list of statements produced by a
18178// generator. The generator, when given a variable as input, must produce
18179// some code which leaves its result in the given variable. The output
18180// from the generator is then inserted into the original program in such a
18181// way that whenever the expression had previously been evaluated, the
18182// statements produced by the generator are run instead and their result is
18183// used in place of the expression.
18184// Assumptions: not currently traversing from or the statement it is in
18185void
18187 {
18188 // DQ (3/11/2006): The problem here is that the test expression for a "for loop" (SgForStmt)
18189 // is assumed to be a SgExpression. This was changed in Sage III as part of a bugfix and so
18190 // the original assumptions upon which this function was based are not incorrect, hence the bug!
18191 // Note that a number of cases were changed when this fix was made to SageIII (see documentation
18192 // for SgScopeStatement).
18193
18194#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18195 SgStatement* enclosingStatement = getStatementOfExpression(from);
18196 SgExprStatement* exprStatement = isSgExprStatement(enclosingStatement);
18197
18198 SgForStatement* forStatement = isSgForStatement(enclosingStatement);
18199 SgReturnStmt* returnStatement = isSgReturnStmt(enclosingStatement);
18200 SgVariableDeclaration* varDeclarationStatement = isSgVariableDeclaration(enclosingStatement);
18201
18202
18203 // DQ (3/11/2006): Bugfix for special cases of conditional that are either SgStatement or SgExpression IR nodes.
18204
18205 ROSE_ASSERT (exprStatement || forStatement || returnStatement || varDeclarationStatement);
18206
18207 if (varDeclarationStatement)
18208 {
18210 }
18211 else
18212 {
18213 SgExpression* root = getRootOfExpression(from);
18214 ROSE_ASSERT (root);
18215 // printf ("root = %p \n",root);
18216 {
18217 if (forStatement && forStatement->get_increment() == root)
18218 {
18219 // printf ("Convert step of for statement \n");
18220 // Convert step of for statement
18221 // for (init; test; e) body; (where e contains from) becomes
18222 // for (init; test; ) {
18223 // body (with "continue" changed to "goto label");
18224 // label: e;
18225 // }
18226 // std::cout << "Converting for step" << std::endl;
18227 SgExprStatement* incrStmt = SageBuilder::buildExprStatement(forStatement->get_increment());
18228 forStatement->get_increment()->set_parent(incrStmt);
18229
18230 SageInterface::addStepToLoopBody(forStatement, incrStmt);
18232 forStatement->set_increment(ne);
18233 ne->set_parent(forStatement);
18235 }
18236 else
18237 {
18238 SgStatement* enclosingStmtParent = isSgStatement(enclosingStatement->get_parent());
18239 assert (enclosingStmtParent);
18240 SgWhileStmt* whileStatement = isSgWhileStmt(enclosingStmtParent);
18241 SgDoWhileStmt* doWhileStatement = isSgDoWhileStmt(enclosingStmtParent);
18242 SgIfStmt* ifStatement = isSgIfStmt(enclosingStmtParent);
18243 SgSwitchStatement* switchStatement = isSgSwitchStatement(enclosingStmtParent);
18244 SgForStatement* enclosingForStatement = isSgForStatement(enclosingStmtParent);
18245 if (enclosingForStatement && enclosingForStatement->get_test() == exprStatement)
18246 {
18247 // Convert test of for statement:
18248 // for (init; e; step) body; (where e contains from) becomes
18249 // for (init; true; step) {
18250 // bool temp;
18251 // temp = e;
18252 // if (!temp) break;
18253 // body;
18254 // }
18255 // in which "temp = e;" is rewritten further
18256 // std::cout << "Converting for test" << std::endl;
18257 pushTestIntoBody(enclosingForStatement);
18259 }
18260 else if (whileStatement && whileStatement->get_condition() == exprStatement)
18261 {
18262 // printf ("Convert while statements \n");
18263 // Convert while statement:
18264 // while (e) body; (where e contains from) becomes
18265 // while (true) {
18266 // bool temp;
18267 // temp = e;
18268 // if (!temp) break;
18269 // body;
18270 // }
18271 // in which "temp = e;" is rewritten further
18272 // std::cout << "Converting while test" << std::endl;
18273 pushTestIntoBody(whileStatement);
18274 // FixSgTree(whileStatement);
18276 }
18277 else if (doWhileStatement && doWhileStatement->get_condition() == exprStatement)
18278 {
18279 // printf ("Convert do-while statements \n");
18280 // Convert do-while statement:
18281 // do body; while (e); (where e contains from) becomes
18282 // {bool temp = true;
18283 // do {
18284 // body (with "continue" changed to "goto label";
18285 // label:
18286 // temp = e;} while (temp);}
18287 // in which "temp = e;" is rewritten further
18288 // std::cout << "Converting do-while test" << std::endl;
18289 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18290 // printf ("Building IR node #14: new SgBasicBlock = %p \n",new_statement);
18291 assert (doWhileStatement->get_parent());
18292 new_statement->set_parent(doWhileStatement->get_parent());
18293 myStatementInsert(doWhileStatement, new_statement, false);
18294 SageInterface::myRemoveStatement(doWhileStatement);
18295 SgName varname = "rose__temp1"; // Does not need to be unique, but must not be used in user code anywhere
18296 SgAssignInitializer* assignInitializer = buildAssignInitializer(
18297 buildBoolValExp(true));
18298 //SageInterface::getBoolType(doWhileStatement));
18300 varname, buildBoolType(), assignInitializer, new_statement);
18301
18302 SgInitializedName* initname = new_decl->get_variables().back();
18303 initname->set_scope(new_statement);
18304
18305 // DQ (12/14/2006): set the parent of the SgAssignInitializer to the variable (SgInitializedName).
18306 assignInitializer->set_parent(initname);
18307
18308#if 1
18309 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18311#else
18312 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18313 new_statement->insert_symbol(varname, varsym);
18314 varsym->set_parent(new_statement->get_symbol_table());
18315#endif
18316
18317 SageInterface::appendStatement(new_decl, new_statement);
18318 SageInterface::appendStatement(doWhileStatement, new_statement);
18319 assert (varsym);
18320 SgCastExp* castExp1 = buildCastExp(root,buildBoolType());
18321 SgVarRefExp* vr = buildVarRefExp(varsym);
18322 vr->set_lvalue(true);
18323
18324 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp1);
18325
18326 SageInterface::addStepToLoopBody(doWhileStatement, temp_setup);
18327 SgVarRefExp* varsymVr = buildVarRefExp(varsym);
18328
18330 varsymVr->set_parent(condStmt);
18331 doWhileStatement->set_condition(condStmt);
18332 condStmt->set_parent(doWhileStatement);
18334 }
18335 else if (ifStatement && ifStatement->get_conditional() == exprStatement)
18336 {
18337 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18338 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18339 assert (ifStatement->get_parent());
18340 new_statement->set_parent(ifStatement->get_parent());
18341 myStatementInsert(ifStatement, new_statement, false);
18343 SgName varname = "rose__temp2"; // Does not need to be unique, but must not be used in user code anywhere
18344 SgBoolValExp* trueVal = buildBoolValExp(true);
18345
18347
18349 buildBoolType(), ai,new_statement);
18350 SgInitializedName* initname = new_decl->get_variables().back();
18351 ai->set_parent(initname);
18352 initname->set_scope(new_statement);
18353#if 1
18354 // MS 7/3/2018: bugfix: above buildVariableDeclaration already creates var symbol
18356#else
18357 SgVariableSymbol* varsym = new SgVariableSymbol(initname);
18358 new_statement->insert_symbol(varname, varsym);
18359 varsym->set_parent(new_statement->get_symbol_table());
18360#endif
18361 SageInterface::appendStatement(new_decl, new_statement);
18362 ifStatement->set_parent(new_statement);
18363 assert (varsym);
18364
18365 SgCastExp* castExp2 = SageBuilder::buildCastExp(root, SageInterface::getBoolType(ifStatement));
18366 SgVarRefExp* vr = buildVarRefExp(varsym);
18367 vr->set_lvalue(true);
18368 SgExprStatement* temp_setup = SageBuilder::buildAssignStatement(vr, castExp2 );
18369 SageInterface::appendStatement(temp_setup, new_statement);
18370 SageInterface::appendStatement(ifStatement, new_statement);
18373 ifStatement->set_conditional(es);
18374 es->set_parent(ifStatement);
18376 }
18377 else if (switchStatement && switchStatement->get_item_selector() == exprStatement)
18378 {
18379 SgExpression* switchCond = exprStatement->get_expression();
18380 ROSE_ASSERT (switchCond);
18381 SgBasicBlock* new_statement = SageBuilder::buildBasicBlock();
18382 // printf ("Building IR node #15: new SgBasicBlock = %p \n",new_statement);
18383 assert (switchStatement->get_parent());
18384 new_statement->set_parent(switchStatement->get_parent());
18385 myStatementInsert(switchStatement, new_statement, false);
18386 SageInterface::myRemoveStatement(switchStatement);
18387 SgName varname = "rose__temp3"; // Does not need to be unique, but must not be used in user code anywhere
18388 switchCond->set_parent(NULL);
18389 SgVariableDeclaration* new_decl = SageBuilder::buildVariableDeclaration(varname, switchCond->get_type(), SageBuilder::buildAssignInitializer(switchCond), new_statement);
18391 SageInterface::appendStatement(new_decl, new_statement);
18392 switchStatement->set_parent(new_statement);
18393 assert (varsym);
18394
18395
18396 SageInterface::appendStatement(switchStatement, new_statement);
18399 switchStatement->set_item_selector(es);
18400 es->set_parent(switchStatement);
18402 }
18403 else
18404 {
18405 // printf ("Handles expression and return statements \n");
18406 // Handles expression and return statements
18407 // std::cout << "Converting other statement" << std::endl;
18409 }
18410 }
18411 }
18412 }
18413
18414#endif
18415
18416 // printf ("Leaving replaceExpressionWithStatement(from,to) \n");
18417 }
18418
18427
18428// Similar to replaceExpressionWithStatement, but with more restrictions.
18429// Assumptions: from is not within the test of a loop or if
18430// not currently traversing from or the statement it is in
18432 {
18433
18434#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
18435 SgStatement* stmt = getStatementOfExpression(from);
18436
18437 if (isSgExprStatement(stmt))
18438 {
18439 SgExpression* top = getRootOfExpression(from);
18440
18441
18442 if (top == from)
18443 {
18444 SgStatement* generated = to->generate(0);
18445 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18446 generated->set_parent(stmt->get_parent());
18447 return;
18448 }
18449 else
18450 {
18451 if (isSgAssignOp(top) && isSgAssignOp(top)->get_rhs_operand() == from)
18452 {
18453 SgAssignOp* t = isSgAssignOp(top);
18454 SgStatement* generated = to->generate(t->get_lhs_operand());
18455 isSgStatement(stmt->get_parent())->replace_statement(stmt, generated);
18456 generated->set_parent(stmt->get_parent());
18457 return;
18458 }
18459 else
18460 {
18461 // printf ("In replaceSubexpressionWithStatement(): Statement not generated \n");
18462 }
18463 }
18464 }
18465
18466 // cout << "1: " << getStatementOfExpression(from)->unparseToString() << endl;
18468 // cout << "2: " << getStatementOfExpression(from)->unparseToString() << endl;
18469 convertInitializerIntoAssignment(init);
18470 // cout << "3: " << getStatementOfExpression(from)->unparseToString() << endl;
18471 // cout << "3a: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18472 SgExprStatement* new_stmt = isSgExprStatement(getStatementOfExpression(from));
18473 assert (new_stmt != NULL); // Should now have this form because of conversion
18474 replaceAssignmentStmtWithStatement(new_stmt, to);
18475
18476 // printf ("In replaceSubexpressionWithStatement: new_stmt = %p = %s \n",new_stmt,new_stmt->class_name().c_str());
18477 // cout << "4: " << getStatementOfExpression(from)->get_parent()->unparseToString() << endl;
18478
18479#endif
18480 }
18481
18482
18483 // Liao, 6/27/2008
18484 //Tasks
18485 // find all return statements
18486 // rewrite it to temp = expression; return temp; if expression is not a single value.
18487 // insert s right before 'return xxx;'
18489 {
18490 int result = 0;
18491 ROSE_ASSERT(func&&s);
18492 // vector<SgReturnStmt* > stmts = findReturnStmts(func);
18493 Rose_STL_Container <SgNode* > stmts = NodeQuery::querySubTree(func, V_SgReturnStmt);
18494 //vector<SgReturnStmt*>::iterator i;
18495 Rose_STL_Container<SgNode*>::iterator i;
18496 for (i=stmts.begin();i!=stmts.end();i++)
18497 {
18498 SgReturnStmt* cur_stmt = isSgReturnStmt(*i);
18499 ROSE_ASSERT(cur_stmt);
18500 SgExpression * exp = cur_stmt->get_expression();
18501 // TV (05/03/2011) Catch the case "return ;" where exp is NULL
18502 bool needRewrite = (exp != NULL) && !(isSgValueExp(exp));
18503 if (needRewrite)
18504 {
18505 splitExpression(exp);
18506 }
18507 // avoid reusing the statement
18508 if (result>=1 )
18509 s = copyStatement(s);
18510 insertStatementBefore(cur_stmt,s);
18511 result ++;
18512 } // for
18513 if (stmts.size()==0 ) // a function without any return at all,
18514 {
18515 SgBasicBlock * body = func->get_definition()->get_body();
18516 if (body== NULL)
18517 {
18518 cout<<"In instrumentEndOfFunction(), found an empty function body.! "<<endl;
18519 ROSE_ABORT();
18520 }
18521 appendStatement(s,body);
18522 result ++;
18523 }
18524 return result;
18525 } // instrumentEndOfFunction
18526
18528 {
18529 ROSE_ASSERT(stmt);
18530 return ((stmt->get_declarationModifier()).get_storageModifier()).isStatic();
18531 } // isStatic()
18532
18535 {
18536 ROSE_ASSERT(stmt);
18537 return ((stmt->get_declarationModifier()).get_storageModifier()).setStatic();
18538 }
18539
18541 {
18542 ROSE_ASSERT(stmt);
18543 return ((stmt->get_declarationModifier()).get_storageModifier()).isExtern();
18544 } // isExtern()
18545
18546
18549 {
18550 ROSE_ASSERT(stmt);
18551 return ((stmt->get_declarationModifier()).get_storageModifier()).setExtern();
18552 }
18553
18554 // Check if an SgInitializedName is "mutable' (has storage modifier set)
18556 {
18557 ROSE_ASSERT(name);
18558 return name->get_storageModifier().isMutable();
18559 }
18560
18561 // True if a parameter name is a Jovial output parameter
18563 {
18564 return isMutable(name);
18565 }
18566
18567 // Get a vector of Jovial input parameters from the function parameter list
18568 // TODO: Look into making this work for Fortran
18569 std::vector<SgInitializedName*> SageInterface::getInParameters(const SgInitializedNamePtrList &params)
18570 {
18571 std::vector<SgInitializedName*> in_params;
18572 BOOST_FOREACH (SgInitializedName* name, params)
18573 {
18574 if (!isJovialOutParam(name)) in_params.push_back(name);
18575 }
18576 return in_params;
18577 }
18578
18579 // Get a list of Jovial output parameters from the function parameter list
18580 // TODO: Look into making this work for Fortran
18581 std::vector<SgInitializedName*> SageInterface::getOutParameters(const SgInitializedNamePtrList &params)
18582 {
18583 std::vector<SgInitializedName*> out_params;
18584 BOOST_FOREACH (SgInitializedName* name, params)
18585 {
18586 if (isJovialOutParam(name)) out_params.push_back(name);
18587 }
18588 return out_params;
18589 }
18590
18592 switch (expr->variantT()) {
18593 case V_SgCharVal: return (long long)(isSgCharVal(expr)->get_value());
18594 case V_SgSignedCharVal: return (long long)(isSgSignedCharVal(expr)->get_value());
18595 case V_SgUnsignedCharVal: return isSgUnsignedCharVal(expr)->get_value();
18596 case V_SgShortVal: return (long long)(isSgShortVal(expr)->get_value());
18597 case V_SgUnsignedShortVal: return isSgUnsignedShortVal(expr)->get_value();
18598 case V_SgIntVal: return (long long)(isSgIntVal(expr)->get_value());
18599 case V_SgUnsignedIntVal: return isSgUnsignedIntVal(expr)->get_value();
18600 case V_SgLongIntVal: return (long long)(isSgLongIntVal(expr)->get_value());
18601 case V_SgUnsignedLongVal: return isSgUnsignedLongVal(expr)->get_value();
18602 case V_SgLongLongIntVal: return isSgLongLongIntVal(expr)->get_value();
18603 case V_SgUnsignedLongLongIntVal: return isSgUnsignedLongLongIntVal(expr)->get_value();
18604 case V_SgBoolValExp: return (long long )(isSgBoolValExp(expr)->get_value());
18605
18606 // DQ (2/18/2015): Make this a better error message.
18607 // default: ROSE_ASSERT (!"Bad kind in getIntegerConstantValue");
18608 default:
18609 {
18610 printf ("ERROR: In SageInterface::getIntegerConstantValue(): default reached: expr = %p = %s \n",expr,expr->class_name().c_str());
18611 ROSE_ASSERT (false);
18612 }
18613
18614 }
18615
18616 ROSE_ASSERT (!"Bad kind return in getIntegerConstantValue");
18617 return 0;
18618 }
18619
18620
18621#ifdef ROSE_ENABLE_BINARY_ANALYSIS
18622// tps : 28 Oct 2008 - support for finding the main interpretation
18623// rpm : 18 Sep 2009 - rewritten to support multiple files per interpretation
18627SageInterface::getMainInterpretation(SgAsmGenericFile *file)
18628{
18629 SgBinaryComposite *binary = getEnclosingNode<SgBinaryComposite>(file);
18630 ROSE_ASSERT(binary!=NULL);
18631
18632 /* Find the only header or the PE header of this file */
18633 SgAsmGenericHeader *requisite_header = NULL; /*the returned interpretation must point to this header*/
18634 const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers();
18635 if (1==headers.size()) {
18636 requisite_header = headers[0];
18637 } else {
18638 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18639 if (isSgAsmPEFileHeader(*hi)) {
18640 requisite_header = isSgAsmPEFileHeader(*hi);
18641 break;
18642 }
18643 }
18644 }
18645 ROSE_ASSERT(requisite_header!=NULL);
18646
18647 /* Find an interpretation that points to this header */
18648 const SgAsmInterpretationPtrList &interps = binary->get_interpretations()->get_interpretations();
18649 for (SgAsmInterpretationPtrList::const_iterator ii=interps.begin(); ii!=interps.end(); ++ii) {
18650 const SgAsmGenericHeaderPtrList &headers = (*ii)->get_headers()->get_headers();
18651 for (SgAsmGenericHeaderPtrList::const_iterator hi=headers.begin(); hi!=headers.end(); ++hi) {
18652 if ((*hi)==requisite_header)
18653 return *ii;
18654 }
18655 }
18656
18657 ROSE_ASSERT(!"no appropriate interpretation");
18658 return NULL;
18659}
18660#endif
18661
18663 {
18664 public:
18665 // This is the simpliest possible version of a deep copy SgCopyHelp::copyAst() member function.
18666 // Note that the root of the does not have its file info set like its children.
18667 virtual SgNode *copyAst(const SgNode *n)
18668 {
18669 // DQ (2/26/2009): This defines a simple concept of "deep" copy. It forms a more testable building block, I hope.
18670 SgNode* copy = n->copy(*this);
18671
18672 // Also mark this as a transformation and to be output in unparsing (so it will be output by the code generator).
18673 Sg_File_Info* fileInfo = copy->get_file_info();
18674 if (fileInfo != NULL)
18675 {
18676 // Must make this for output (checked in unparser), marking as a transformation is not checked
18677 fileInfo->setOutputInCodeGeneration();
18678 fileInfo->setTransformation();
18679 }
18680
18681 return copy;
18682 }
18683 } collectDependentDeclarationsCopyType;
18684
18685
18687 {
18688 // This traversal collects the includes at the top of a file.
18689
18690 public:
18691 vector<PreprocessingInfo*> cppDirectiveList;
18692
18693 void visit(SgNode *astNode);
18694 };
18695
18696
18697void
18699 {
18700 SgLocatedNode* locatedNode = isSgLocatedNode(astNode);
18701 if (locatedNode != NULL)
18702 {
18703 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
18704
18705 if (comments != NULL)
18706 {
18707#if 0
18708 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18709#endif
18710 AttachedPreprocessingInfoType::iterator i;
18711 for (i = comments->begin(); i != comments->end(); i++)
18712 {
18713 ROSE_ASSERT ( (*i) != NULL );
18714#if 0
18715 printf (" Attached Comment (relativePosition=%s): %s\n",
18716 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18717 (*i)->getString().c_str());
18718 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
18719 (*i)->get_file_info()->display("comment/directive location");
18720#endif
18721
18722 // We only save the #include directives, but likely we should be collecting ALL directives to
18723 // avoid the collection of #include that is meant to be hidden in an #if 0 ... #endif pairing.
18724 // if ((*i)->getTypeOfDirective() == PreprocessingInfo::CpreprocessorIncludeDeclaration)
18725 {
18726 // This is an include directive.
18727 cppDirectiveList.push_back(*i);
18728#if 0
18729 printf (" Attached include directive (relativePosition=%s): %s\n",
18730 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18731 (*i)->getString().c_str());
18732#endif
18733 }
18734 }
18735 }
18736 else
18737 {
18738#if 0
18739 printf ("No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->sage_class_name());
18740#endif
18741 }
18742 }
18743 }
18744
18745
18746// This is part of a mechanism to collect directives from code that is to be outlined.
18747// However if we collect include directives we likely should really be collecting ALL
18748// directives (since the #include could be inside of an #if 0 ... #endif pairing.
18749// This level of detail will be addressed later (in an iterative approach).
18750vector<PreprocessingInfo*>
18751collectCppDirectives ( SgSourceFile* file )
18752 {
18753 // This function is used to collect include directives from the whole file.
18755 t.traverse(file,preorder);
18756
18757 return t.cppDirectiveList;
18758 }
18759
18760
18761vector<PreprocessingInfo*>
18762collectCppDirectives ( SgLocatedNode* n )
18763 {
18764 // This function is used to collect include directives from specific dependent declarations.
18766 t.traverse(n,preorder);
18767
18768 return t.cppDirectiveList;
18769 }
18770
18771// Debugging support.
18772void
18773outputPreprocessingInfoList ( const vector<PreprocessingInfo*> & l )
18774 {
18775 // This function support debugging the generated directive lists.
18776
18777 vector<PreprocessingInfo*>::const_iterator i = l.begin();
18778 while ( i != l.end() )
18779 {
18780 printf (" Attached include directive (relativePosition=%s): %s\n",
18781 ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
18782 (*i)->getString().c_str());
18783 i++;
18784 }
18785 }
18786
18787
18788
18790getAssociatedDeclaration( SgScopeStatement* scope )
18791 {
18792 //TODO This should become a member of SgScopeStatement
18793
18794 SgDeclarationStatement* declaration = NULL;
18795 switch(scope->variantT())
18796 {
18797 case V_SgNamespaceDefinitionStatement:
18798 {
18799 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
18800 declaration = namespaceDefinition->get_namespaceDeclaration();
18801 break;
18802 }
18803
18804 case V_SgClassDefinition:
18805 case V_SgTemplateInstantiationDefn: // Liao, 5/12/2009
18806 {
18807 SgClassDefinition* classDefinition = isSgClassDefinition(scope);
18808 declaration = classDefinition->get_declaration();
18809 break;
18810 }
18811
18812 default:
18813 {
18814 printf ("Error: default reached in getAssociatedDeclaration(): scope = %p = %s \n",scope,scope->class_name().c_str());
18815 ROSE_ABORT();
18816 }
18817 }
18818
18819 // There may be some scopes that don't have an associated declaration.
18820 ROSE_ASSERT(declaration != NULL);
18821
18822 return declaration;
18823 }
18824
18825
18827 {
18828 public:
18829 // Accumulate a list of copies of associated declarations referenced in the AST subtree
18830 // (usually of the outlined functions) to insert in the separate file to support outlining.
18831 vector<SgDeclarationStatement*> declarationList;
18832
18833 // Save the list of associated symbols of dependent declarations identified so that we can
18834 // support their replacement in the new AST.
18835 vector<SgSymbol*> symbolList;
18836
18837 // Keep track of declarations already copied so that we don't copy them more than once and try to insert them.
18838 set<SgDeclarationStatement*> alreadySavedDeclarations;
18839
18840 // Required visit function for the AST traversal
18841 void visit(SgNode *astNode);
18842 private:
18843 void addDeclaration(SgDeclarationStatement* decl);
18844 };
18845
18847getGlobalScopeDeclaration( SgDeclarationStatement* inputDeclaration )
18848 {
18849 // DQ (2/16/2009): Basically if a class is used from a namespace (or any outer scope) and we
18850 // outline the reference to the class, we have to declare not the class but the outer scope
18851 // (which will have the class included).
18852
18853 SgDeclarationStatement* returnDeclaration = inputDeclaration;
18854
18855 // I think that we have to copy the outer scope if the declaration's scope is not SgGlobal.
18856 SgScopeStatement* scope = inputDeclaration->get_scope();
18857 ROSE_ASSERT(scope != NULL);
18858
18859 // printf ("inputDeclaration->get_scope() = %p = %s \n",scope,scope->class_name().c_str());
18860
18861 // If the input declaration is not in global scope then find the parent declaration that is in global scope!
18862 SgGlobal* globalScope = isSgGlobal(scope);
18863 if (globalScope == NULL)
18864 {
18865 // Traverse back to the global scope to include outer declarations which contain the "declaration"
18866 // printf ("Traverse back to the global scope to include outer declarations \n");
18867
18868 SgScopeStatement* parentScope = scope;
18869 SgDeclarationStatement* associatedDeclaration = returnDeclaration;
18870 ROSE_ASSERT(parentScope != NULL);
18871 while (globalScope == NULL)
18872 {
18873 associatedDeclaration = getAssociatedDeclaration(parentScope);
18874 ROSE_ASSERT(associatedDeclaration != NULL);
18875
18876 parentScope = parentScope->get_scope();
18877 globalScope = isSgGlobal(parentScope);
18878 }
18879
18880 returnDeclaration = associatedDeclaration;
18881 }
18882
18883 return returnDeclaration;
18884 }
18885
18886
18887// Debugging support.
18888void
18889outputDeclarationList ( const vector<SgDeclarationStatement*> & l )
18890 {
18891 // This function support debugging the generated declarations.
18892
18893 int counter = 0;
18894 vector<SgDeclarationStatement*>::const_iterator i = l.begin();
18895 while ( i != l.end() )
18896 {
18897 printf ("In outputDeclarationList(): list[%d] = %p = %s = %s \n",counter++,*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
18898 i++;
18899 }
18900 }
18901
18902void CollectDependentDeclarationsTraversal::addDeclaration(SgDeclarationStatement* declaration)
18903{
18904 // If there was a declaration found then handle it.
18905 if (declaration != NULL)
18906 {
18907 // Reset the defining declaration in case there is an outer declaration that is more important
18908 // to consider the dependent declaration (e.g. a class in a namespace). In general this will
18909 // find the associated outer declaration in the global scope.
18910 SgDeclarationStatement* dependentDeclaration = getGlobalScopeDeclaration(declaration);
18911
18912 // This declaration is in global scope so we just copy the declaration
18913 // For namespace declarations: they may have the save name but they have to be saved separated.
18914 if (alreadySavedDeclarations.find(dependentDeclaration) == alreadySavedDeclarations.end())
18915 {
18916#if 0
18917 printf ("In CollectDependentDeclarationsTraversal::visit(): selected dependentDeclaration = %p = %s = %s \n",
18918 dependentDeclaration,dependentDeclaration->class_name().c_str(),SageInterface::get_name(dependentDeclaration).c_str());
18919#endif
18920 // DQ (2/22/2009): Semantics change for this function, just save the original declaration, not a copy of it.
18921 declarationList.push_back(dependentDeclaration);
18922
18923 // Record this as a copied declaration
18924 alreadySavedDeclarations.insert(dependentDeclaration);
18925#if 0
18926 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18927 printf ("############### ADDING dependentDeclaration = %p = %s to alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18928 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18929#endif
18930 // DQ (2/21/2009): Added assertions (will be inforced in SageInterface::appendStatementWithDependentDeclaration()).
18931 // ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
18932 }
18933 else
18934 {
18935#if 0
18936 printf ("In CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
18937 printf ("############### EXISTING dependentDeclaration = %p = %s found in alreadySavedDeclarations set (size = %" PRIuPTR ") \n",
18938 dependentDeclaration,dependentDeclaration->class_name().c_str(),alreadySavedDeclarations.size());
18939#endif
18940 }
18941 }
18942}
18943
18945static std::vector<SgTypedefDeclaration*> collectTypedefDeclarations(SgType* type)
18946{
18947 ROSE_ASSERT(type != NULL);
18948 std::vector<SgTypedefDeclaration*> result;
18949 SgType* currentType = type;
18950
18951 SgModifierType* modType = NULL;
18952 SgPointerType* pointType = NULL;
18953 SgReferenceType* refType = NULL;
18954 SgArrayType* arrayType = NULL;
18955 SgTypedefType* typedefType = NULL;
18956
18957 while (true)
18958 {
18959 modType = isSgModifierType(currentType);
18960 if(modType)
18961 {
18962 currentType = modType->get_base_type();
18963 }
18964 else
18965 {
18966 refType = isSgReferenceType(currentType);
18967 if(refType)
18968 {
18969 currentType = refType->get_base_type();
18970 }
18971 else
18972 {
18973 pointType = isSgPointerType(currentType);
18974 if ( pointType)
18975 {
18976 currentType = pointType->get_base_type();
18977 }
18978 else
18979 {
18980 arrayType = isSgArrayType(currentType);
18981 if (arrayType)
18982 {
18983 currentType = arrayType->get_base_type();
18984 }
18985 else
18986 {
18987 typedefType = isSgTypedefType(currentType);
18988 if (typedefType)
18989 {
18990 currentType = typedefType->get_base_type();
18991 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(typedefType->get_declaration());
18992 // have to try to get the defining declaration for a defining typedef declaration
18993 // otherwise AST traversal will not visit the non-defining one for a defining typedef declaration
18994 // sortSgNodeListBasedOnAppearanceOrderInSource() won't work properly
18995 SgTypedefDeclaration* decl = isSgTypedefDeclaration(tdecl->get_definingDeclaration());
18996 if (decl ==NULL)
18997 decl = tdecl;
18998 result.push_back(decl);
18999 }
19000 else
19001 {
19002 // Exit the while(true){} loop!
19003 break;
19004 }
19005 }
19006 }
19007 }
19008 }
19009 }
19010#if 0
19011 // debug here
19012 if (result.size()>0)
19013 {
19014 cout<<"------------Found a chain of typedef decls: count="<<result.size()<<endl;
19015 for (vector <SgTypedefDeclaration*>::const_iterator iter = result.begin();
19016 iter!=result.end(); iter ++)
19017 cout<<(*iter)->unparseToString()<<endl;
19018 }
19019#endif
19020 return result;
19021}
19022
19024void
19026 {
19027 // Statements that can cause us to have declaration dependences:
19028 // 1) variable declarations (through their types)
19029 // 2) function calls
19030 // 3) typedefs (through their base types)
19031 // Not implemented:
19032 // 4) static member functions (through their class)
19033 // 5) static data members (through their class)
19034 // 6) namespaces
19035 // 7) #include<> CPP directives.
19036
19037 // DQ (2/22/2009): Changing the semantics for this function,
19038 // just save the original declaration, not a copy of it.
19039
19040#if 0
19041 // Debugging support.
19042 Sg_File_Info* fileInfo = astNode->get_file_info();
19043 if (fileInfo != NULL && fileInfo->isFrontendSpecific() == false && (isSgStatement(astNode) != NULL) )
19044 {
19045 printf ("\n\nIn CollectDependentDeclarationsTraversal::visit(): astNode = %p = %s = %s \n",astNode,astNode->class_name().c_str(),SageInterface::get_name(astNode).c_str());
19046 // fileInfo->display("In CollectDependentDeclarationsTraversal::visit()");
19047 int counter = 0;
19048 printf ("alreadySavedDeclarations.size() = %" PRIuPTR " \n",alreadySavedDeclarations.size());
19049 for (set<SgDeclarationStatement*>::iterator i = alreadySavedDeclarations.begin(); i != alreadySavedDeclarations.end(); i++)
19050 {
19051 printf ("alreadySavedDeclarations %d: %p = %s \n",counter++,*i,(*i)->class_name().c_str());
19052 }
19053 }
19054#endif
19055
19056 // The following conditionals set this variable
19057 SgDeclarationStatement* declaration = NULL;
19058
19059 // 1) ------------------------------------------------------------------
19060 // Collect the declarations associated with referenced types in variable declarations (or any types associated with SgInitializedName IR nodes)
19061 SgInitializedName* initializedname = isSgInitializedName(astNode);
19062 if (initializedname != NULL)
19063 {
19064 SgType* type = initializedname->get_type();
19065
19066 // handle all dependent typedef declarations, if any
19067 std::vector <SgTypedefDeclaration*> typedefVec = collectTypedefDeclarations(type);
19068 for (std::vector <SgTypedefDeclaration*>::const_iterator iter =typedefVec.begin();
19069 iter != typedefVec.end(); iter++)
19070 {
19071 SgTypedefDeclaration* typedef_decl = *iter;
19072 addDeclaration(typedef_decl);
19073 symbolList.push_back(typedef_decl->get_symbol_from_symbol_table());
19074 }
19075
19076 // handle base type:
19077
19078 // We now can to strip typedefs since they are already handled by collectTypedefDeclarations()
19079 // this also reach to the defining body of a defining typedef declaration
19080 // and treat it as an independent declarations,
19081 // the assumption here is that a defining typedef declaration will only has its
19082 // nondefining declaration copied to avoid redefining of the struct.
19083 // This is also a workaround for an AST copy bug: defining body gets lost after copying
19084 // a defining typedef declaration.
19085 // Liao, 5/8/2009
19086 //
19087 // e.g. typedef struct hypre_BoxArray_struct
19088 // {
19089 // int alloc_size;
19090 // } hypre_BoxArray;
19091 //
19092 // struct hypre_BoxArray_struct will be treated as a strippedType and its declaration
19093 // will be inserted.
19094 //
19095 SgType* strippedType = type->stripType();
19096 SgNamedType* namedType = isSgNamedType(strippedType);
19097 if (namedType != NULL)
19098 {
19099 // Note that since this was obtained via the types and types are shared, this is the non-defining
19100 // declaration in original program (not the separate file is this is to support outlining into a
19101 // separate file.
19102 SgDeclarationStatement* named_decl = namedType->get_declaration();
19103 // the case of class declaration, including struct, union
19104 SgClassDeclaration* classDeclaration = isSgClassDeclaration(named_decl);
19105 if (classDeclaration != NULL)
19106 {
19107 // printf ("Found class declaration: classDeclaration = %p \n",classDeclaration);
19108 declaration = classDeclaration->get_definingDeclaration();
19109 // Liao, 12/09/2016.
19110 // In some cases, forward declaration of class types are used and sufficient, without providing defining declaration.
19111 // We should allow this.
19112 if (declaration != NULL)
19113 {
19114 // ROSE_ASSERT(declaration != NULL);
19115 addDeclaration(declaration);
19116 }
19117 else
19118 addDeclaration (classDeclaration); // we use the original forward declaration.
19119
19120 // Note that since types are shared in the AST, the declaration for a named type may be (is)
19121 // associated with the class declaration in the original file. However, we want to associated
19122 // class declaration in the current file, but since the AST copy mechanism work top-down, this
19123 // mapping form the declaration in the original file to the new declaration in the copied AST
19124 // is available in the SgCopyHelp map of copied IR nodes.
19125 // DQ (3/3/2009): Added support for symbol references to be saved (symbols in the original file).
19126 // these symbols will be mapped to their new symbols.
19127 ROSE_ASSERT(classDeclaration->hasAssociatedSymbol() == true);
19128 SgSymbol* classSymbol = classDeclaration->get_symbol_from_symbol_table();
19129 ROSE_ASSERT(classSymbol != NULL);
19130
19131 // printf ("Saving classSymbol = %p \n",classSymbol);
19132 symbolList.push_back(classSymbol);
19133 }
19134
19135 // handle Enum types
19136 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(named_decl);
19137 if (enum_decl != NULL)
19138 {
19139 declaration = enum_decl->get_definingDeclaration();
19140 ROSE_ASSERT(declaration != NULL);
19141 addDeclaration(declaration);
19142 ROSE_ASSERT(enum_decl->hasAssociatedSymbol() == true);
19143 // Liao 12/14/2012. use search_for_symbol_from_symbol_table() instead to avoid the defining/nondefing decl issue
19144 //SgSymbol* esymbol = enum_decl->get_symbol_from_symbol_table();
19145 SgSymbol* esymbol = enum_decl->search_for_symbol_from_symbol_table();
19146 ROSE_ASSERT(esymbol!= NULL);
19147 symbolList.push_back(esymbol);
19148 }
19149 } // end if namedType
19150#if 0
19151 printf ("Found reference to type = %p = %s strippedType = %p = %s \n",type,type->class_name().c_str(),strippedType,strippedType->class_name().c_str());
19152#endif
19153 }// end if (initializedname)
19154
19155 // 2) ------------------------------------------------------------------
19156 // Collect declarations associated with function calls.
19157 SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(astNode);
19158 if (functionCallExp != NULL)
19159 {
19160 declaration = functionCallExp->getAssociatedFunctionDeclaration();
19161 //ROSE_ASSERT(declaration != NULL);
19162 // We allow a function pointer to have no specific declaration associated.
19163 if (declaration != NULL)
19164 addDeclaration(declaration);
19165
19166 // DQ (3/2/2009): Added support for symbol references to be saved (this can be a SgFunctionSymbol or a SgMemberFunctionSymbol).
19167 SgSymbol* functionSymbol = functionCallExp->getAssociatedFunctionSymbol();
19168 //ROSE_ASSERT(functionSymbol != NULL);
19169
19170 // printf ("Saving functionSymbol = %p \n",functionSymbol);
19171 if (functionSymbol)
19172 symbolList.push_back(functionSymbol);
19173 }
19174
19175 // 3) ------------------------------------------------------------------
19176 // Collect enumerate declarations associated with SgEnumVal
19177 SgEnumVal * eval = isSgEnumVal(astNode);
19178 if (eval != NULL)
19179 {
19180 declaration = eval->get_declaration();
19181 ROSE_ASSERT(declaration != NULL);
19182 addDeclaration(declaration);
19184 ROSE_ASSERT(symbol != NULL);
19185 symbolList.push_back(symbol);
19186 }
19187// addDeclaration(declaration); // do it in different cases individually
19188 }
19189
19190static std::map<const SgStatement*, bool> visitedDeclMap; // avoid infinite recursion
19191
19192
19194// Used to separate a function to a new source file and add necessary type declarations into the new file.
19195// NOTICE: each call to this function has to have call visitedDeclMap.clear() first!!
19196static void
19197getDependentDeclarations (SgStatement* stmt, vector<SgDeclarationStatement*> & declarationList, vector<SgSymbol*> & symbolList )
19198{
19199 // This function returns a list of the dependent declaration for any input statement.
19200 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19201#if 0
19202 printf ("\n\n********************************************************** \n");
19203 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19204 printf ("********************************************************** \n");
19205#endif
19206 visitedDeclMap[stmt]= true;
19208 t.traverse(stmt,preorder);
19209#if 0
19210 declarationList = t.declarationList;
19211 symbolList = t.symbolList;
19212#else
19213 // Merge to the parent level list
19214 copy(t.declarationList.begin(),t.declarationList.end(), back_inserter(declarationList));
19215 copy(t.symbolList.begin(),t.symbolList.end(), back_inserter(symbolList));
19216 // make their elements unique
19217 sort (declarationList.begin(), declarationList.end());
19218 vector<SgDeclarationStatement*>::iterator new_end = unique(declarationList.begin(), declarationList.end());
19219 declarationList.erase(new_end, declarationList.end());
19220
19221 sort (symbolList.begin(), symbolList.end());
19222 vector<SgSymbol*>::iterator end2 = unique(symbolList.begin(), symbolList.end());
19223 symbolList.erase(end2, symbolList.end());
19224
19225
19226 // Liao, 5/7/2009 recursively call itself to get dependent declarations' dependent declarations
19227 for (vector<SgDeclarationStatement*>::const_iterator iter = t.declarationList.begin();
19228 iter !=t.declarationList.end(); iter++)
19229 {
19230 SgDeclarationStatement* decl = *iter;
19231 SgType* base_type = NULL;
19232 SgStatement* body_stmt= NULL;
19233
19234 // grab base type for a declaration
19235 // For class declaration: grab their
19236 if (isSgClassDeclaration(decl))
19237 {
19238 base_type = isSgClassDeclaration(decl)->get_type();
19239 } else
19240 if (isSgTypedefDeclaration(decl))
19241 {
19242
19243 // we don't want to strip of nested typedef declarations
19244 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);
19245 }
19246
19247 //TODO variable declaration, function declaration: parameter list types,
19248 // multiple base_type then
19249
19250 // is the base type associated with a defining body?
19251 // TODO enum type
19252 if (isSgClassType(base_type))
19253 {
19254 SgClassDeclaration* class_decl = isSgClassDeclaration(isSgClassType(base_type)->get_declaration()->get_definingDeclaration());
19255 if (class_decl!=NULL)
19256 {
19257 body_stmt = class_decl->get_definition();
19258 }
19259 }
19260 // recursively collect dependent declarations for the body stmt
19261 if ((body_stmt!=NULL) &&(!visitedDeclMap[body_stmt]))
19262 { // avoid infinite recursion
19263 getDependentDeclarations(body_stmt, declarationList, symbolList);
19264 }
19265 }
19266#endif
19267} // end void getDependentDeclarations()
19268
19269
19270// Reorder a list of declaration statements based on their appearance order in source files
19271// This is essential to insert their copies into a new file in a right order
19272// Liao, 5/7/2009
19273vector<SgDeclarationStatement*>
19274SageInterface::sortSgNodeListBasedOnAppearanceOrderInSource(const vector<SgDeclarationStatement*>& nodevec)
19275{
19276 vector<SgDeclarationStatement*> sortedNode;
19277
19278 if (nodevec.size()==0 )
19279 return sortedNode;
19280 // no need to sort if there is only 1 element
19281 if (nodevec.size() ==1)
19282 return nodevec;
19283
19285 Rose_STL_Container<SgNode*> queryResult = NodeQuery::querySubTree(project,V_SgDeclarationStatement);
19286 for (Rose_STL_Container<SgNode*>::const_iterator iter = queryResult.begin();
19287 iter!= queryResult.end(); iter++)
19288 {
19289 // cerr<<"Trying to match:"<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19290 SgNode* cur_node = *iter;
19291 SgDeclarationStatement* cur_stmt = isSgDeclarationStatement(cur_node);
19292 ROSE_ASSERT(cur_stmt!=NULL);
19293 // Liao 12/14/2012. It is possible nodevec contains a first non-defining function declaration since the function is called in the outlined function
19294 // This is true even if the AST only has a defining function declaration.
19295 //
19296 // But that first non-defining function declaration is not traversable in AST due to it is hidden.
19297 // The solution here is to for each defining function decl traversed, convert it to the first nondefining one to do the match.
19298 SgFunctionDeclaration * func_decl = isSgFunctionDeclaration (cur_stmt);
19299 if (func_decl)
19300 {
19301 if (func_decl->get_definingDeclaration() == func_decl )
19302 {
19303 cur_stmt = func_decl->get_firstNondefiningDeclaration();
19304 ROSE_ASSERT (cur_stmt != func_decl);
19305 }
19306 }
19307 vector<SgDeclarationStatement*>::const_iterator i = find (nodevec.begin(), nodevec.end(), cur_stmt);
19308 if (i!=nodevec.end())
19309 {
19310 // It is possible we already visited a real prototype func decl before, now we see a prototype converted from a defining declaration.
19311 // We have to make sure only one copy is inserted.
19312 vector<SgDeclarationStatement*>::const_iterator j = find (sortedNode.begin(), sortedNode.end(), *i);
19313 if (j == sortedNode.end())
19314 sortedNode.push_back(*i);
19315 }
19316 }
19317
19318 if (nodevec.size() != sortedNode.size())
19319 {
19320 cerr<<"Fatal error in sortSgNodeListBasedOnAppearanceOrderInSource(): nodevec.size() != sortedNode.size()"<<endl;
19321 cerr<<"nodevec() have "<< nodevec.size()<<" elements. They are:"<<endl;
19322 for (vector<SgDeclarationStatement*>::const_iterator iter = nodevec.begin(); iter != nodevec.end(); iter++)
19323 {
19324 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19325 }
19326 cerr<<"sortedNode() have " << sortedNode.size() <<" elements. They are:"<<endl;
19327 for (vector<SgDeclarationStatement*>::const_iterator iter = sortedNode.begin(); iter != sortedNode.end(); iter++)
19328 {
19329 cerr<<(*iter)<<" "<<(*iter)->class_name() <<" "<<(*iter)->unparseToString()<<endl;
19330 }
19331
19332 ROSE_ASSERT(nodevec.size() == sortedNode.size());
19333 }
19334 return sortedNode;
19335}
19336
19338// This function clears a history map transparently and return a sorted list of dependent declarations
19339std::vector<SgDeclarationStatement*>
19341 {
19342 // This function returns a list of the dependent declaration for any input statement.
19343 // Dependent declaration are functions called, types referenced in variable declarations, etc.
19344#if 0
19345 printf ("\n\n********************************************************** \n");
19346 printf (" Inside of getDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19347 printf ("********************************************************** \n");
19348
19350 t.traverse(stmt,preorder);
19351
19352 return t.declarationList;
19353#else
19354 // share a single implementation for recursive lookup for dependent declaration
19355 visitedDeclMap.clear();
19356 vector<SgDeclarationStatement*> declarationList;
19357 vector<SgSymbol*> symbolList;
19358 getDependentDeclarations(stmt, declarationList, symbolList);
19359 declarationList = sortSgNodeListBasedOnAppearanceOrderInSource(declarationList);
19360#if 0
19361 printf ("\n\n ********************************************************** \n");
19362 cout<<"Found dependent decl: count="<<declarationList.size()<<endl;
19363 for ( vector<SgDeclarationStatement*>::const_iterator iter = declarationList.begin();
19364 iter != declarationList.end(); iter++)
19365 {
19366 cout<<"\t"<<(*iter)->class_name()<<" at line "<<(*iter)->get_file_info()->get_line()<<endl;
19367 if ((*iter)->variantT()== V_SgFunctionDeclaration)
19368 cout<<"func name is:"<<isSgFunctionDeclaration(*iter)->get_name().getString()<<endl;
19369 //<<(*iter)->unparseToString()<<endl; // unparseToString() won't work on outlined function
19370 }
19371 printf ("\n ********************************************************** \n");
19372#endif
19373
19374 return declarationList;
19375
19376#endif
19377 }
19378
19379
19380bool
19382 {
19383 bool returnValue = false;
19384
19385#if 0
19386 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());
19387#endif
19388
19389 if (functionName.is_null() == false)
19390 {
19391 // DQ (1/20/2019): Add operator~() to this list (see test2019_10.C).
19392 if ( functionName == "operator++" || functionName == "operator--" || functionName == "operator&" ||
19393 functionName == "operator!" || functionName == "operator*" || functionName == "operator+" ||
19394 functionName == "operator-" || functionName == "operator+" || functionName == "operator~")
19395 {
19396 returnValue = true;
19397 }
19398 }
19399
19400 return returnValue;
19401 }
19402
19403
19404// DQ (4/13/2013): We need these to support the unparing of operators defined by operator syntax or member function names.
19406bool
19408 {
19409 // DQ (4/21/2013): Reimplemented this function to support more of the prefix operators.
19410 // Also we now support when they are defined as member functions and non-member functions.
19411
19412 bool returnValue = false;
19413
19414 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(exp);
19415 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19416 // ROSE_ASSERT(memberFunctionRefExp != NULL);
19417
19418 SgName functionName;
19419 size_t numberOfOperands = 0;
19420
19421 if (memberFunctionRefExp != NULL)
19422 {
19423 ROSE_ASSERT(functionRefExp == NULL);
19424 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19425 if (memberFunctionDeclaration != NULL)
19426 {
19427 functionName = memberFunctionDeclaration->get_name();
19428 numberOfOperands = memberFunctionDeclaration->get_args().size();
19429 }
19430 }
19431 else
19432 {
19433 // This could be "friend bool operator!(const X & x);"
19434 if (functionRefExp != NULL)
19435 {
19436 SgFunctionDeclaration* functionDeclaration = functionRefExp->getAssociatedFunctionDeclaration();
19437 if (functionDeclaration != NULL)
19438 {
19439 functionName = functionDeclaration->get_name();
19440 numberOfOperands = functionDeclaration->get_args().size();
19441 }
19442 }
19443 else
19444 {
19445 // Note clear if this should be an error.
19446 printf ("In SageInterface::isPrefixOperator(): unknown case of exp = %p = %s \n",exp,exp->class_name().c_str());
19447 }
19448 }
19449
19450#if 0
19451 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);
19452#endif
19453
19454 if (isPrefixOperatorName(functionName) == true)
19455 {
19456 if (memberFunctionRefExp != NULL)
19457 {
19458 // This case is for member functions.
19459 ROSE_ASSERT(functionRefExp == NULL);
19460 if (numberOfOperands == 0)
19461 {
19462 // This is the C++ signature for the operator++() prefix operator.
19463 returnValue = true;
19464 }
19465 else
19466 {
19467 // This is the C++ signature for the operator++() postfix operator.
19468 returnValue = false;
19469 }
19470 }
19471 else
19472 {
19473 // This case is for non-member functions.
19474 ROSE_ASSERT(functionRefExp != NULL);
19475 ROSE_ASSERT(memberFunctionRefExp == NULL);
19476 if (numberOfOperands == 1)
19477 {
19478 // This is the C++ signature for the operator++() prefix operator.
19479 returnValue = true;
19480 }
19481 else
19482 {
19483 // This is the C++ signature for the operator++() postfix operator.
19484 ROSE_ASSERT(numberOfOperands == 2);
19485 returnValue = false;
19486 }
19487 }
19488 }
19489
19490#if 0
19491 printf ("Leaving SageInterface::isPrefixOperator(): returnValue = %s \n",returnValue ? "true" : "false");
19492#endif
19493
19494 return returnValue;
19495 }
19496
19497
19499bool
19501 {
19502 return ( (isPrefixOperator(exp) == false) && (isIndexOperator(exp) == false) );
19503 }
19504
19505
19507bool
19509 {
19510 bool returnValue = false;
19511 SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(exp);
19512 if (memberFunctionRefExp == NULL)
19513 return false;
19514
19515 SgMemberFunctionDeclaration* memberFunctionDeclaration = memberFunctionRefExp->getAssociatedMemberFunctionDeclaration();
19516 if (memberFunctionDeclaration != NULL)
19517 {
19518 SgName functionName = memberFunctionDeclaration->get_name();
19519 if ( (functionName == "operator[]") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19520 {
19521 returnValue = true;
19522 }
19523 else
19524 {
19525 if ( (functionName == "operator()") && (isSgType(memberFunctionDeclaration->get_type()) != NULL) )
19526 {
19527 returnValue = true;
19528 }
19529 else
19530 {
19531 returnValue = false;
19532 }
19533 }
19534 }
19535
19536 return returnValue;
19537 }
19538
19539
19540// DQ (1/10/2014): Adding more general support for token based unparsing.
19542SageInterface::lastStatementOfScopeWithTokenInfo (SgScopeStatement* scope, std::map<SgNode*,TokenStreamSequenceToNodeMapping*> & tokenStreamSequenceMap)
19543 {
19544 // Return the last statement in the associated scope that has token information.
19545 SgStatement* lastStatement = NULL;
19546
19547 ROSE_ASSERT(scope != NULL);
19548
19549#if 0
19550 printf ("In SageInterface::lastStatementOfScopeWithTokenInfo(): scope = %p = %s \n",scope,scope->class_name().c_str());
19551#endif
19552
19553 SgIfStmt* ifStatement = isSgIfStmt(scope);
19554 if (ifStatement != NULL)
19555 {
19556 lastStatement = ifStatement->get_false_body();
19557 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19558 {
19559 lastStatement = ifStatement->get_true_body();
19560 if (lastStatement == NULL || (tokenStreamSequenceMap.find(lastStatement) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[lastStatement] == NULL))
19561 {
19562 lastStatement = NULL;
19563 }
19564 }
19565
19566 printf ("Note: SgIfStmt scope in SageInterface::lastStatementOfScopeWithTokenInfo(): returning lastStatement = %p \n",lastStatement);
19567 if (lastStatement != NULL)
19568 {
19569 printf (" --- lastStatement = %p = %s \n",lastStatement,lastStatement->class_name().c_str());
19570 }
19571
19572 return lastStatement;
19573 }
19574
19575 SgStatementPtrList statementList = scope->generateStatementList();
19576 if (statementList.rbegin() != statementList.rend())
19577 {
19578 // Find the last statement with token stream information.
19579 SgStatementPtrList::reverse_iterator i = statementList.rbegin();
19580
19581 while (i != statementList.rend() && (tokenStreamSequenceMap.find(*i) == tokenStreamSequenceMap.end() || tokenStreamSequenceMap[*i] == NULL) )
19582 {
19583 i++;
19584 }
19585
19586 if (i == statementList.rend())
19587 {
19588 lastStatement = NULL;
19589 }
19590 else
19591 {
19592 lastStatement = *i;
19593 }
19594 }
19595
19596 return lastStatement;
19597 }
19598
19599
19600void
19602 {
19603 // DQ (8/12/2020): Check the access permissions of all defining and nodefining declarations (debugging support for Cxx_tests/test2020_28.C).
19604
19605 class DeclarationTraversal : public AstSimpleProcessing
19606 {
19607 public:
19608 // DeclarationTraversal() {}
19609
19610 void visit (SgNode* node)
19611 {
19612 SgDeclarationStatement* decl = isSgDeclarationStatement(node);
19613 if (decl != NULL)
19614 {
19615 SgDeclarationStatement* definingDeclaration = isSgDeclarationStatement(decl->get_definingDeclaration());
19616 SgDeclarationStatement* firstNondefiningDeclaration = isSgDeclarationStatement(decl->get_firstNondefiningDeclaration());
19617 SgDeclarationStatement* otherDeclaration = NULL;
19618
19619 // Output access modifier information for each declaration.
19620 printf ("Found declaration = %p = %s name = %s \n",decl,decl->class_name().c_str(),get_name(decl).c_str());
19621 if (decl != definingDeclaration && decl != firstNondefiningDeclaration)
19622 {
19623 otherDeclaration = decl;
19624 }
19625
19626 if (definingDeclaration != NULL)
19627 {
19628 definingDeclaration->get_declarationModifier().get_accessModifier().display("definingDeclaration: accessModifier");
19629 }
19630
19631 if (firstNondefiningDeclaration != NULL)
19632 {
19633 firstNondefiningDeclaration->get_declarationModifier().get_accessModifier().display("firstNondefiningDeclaration: accessModifier");
19634 }
19635
19636 if (otherDeclaration != NULL)
19637 {
19638 otherDeclaration->get_declarationModifier().get_accessModifier().display("otherDeclaration: accessModifier");
19639 }
19640
19641 // Adding space for formatting.
19642 printf ("\n");
19643 }
19644 }
19645 };
19646
19647 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19648 DeclarationTraversal traversal;
19649 traversal.traverse(astNode, preorder);
19650 }
19651
19652
19653void
19655 {
19656 // DQ (8/14/2020): Check the symbol tables for specific scopes (debugging support).
19657
19658 class ScopeTraversal : public AstSimpleProcessing
19659 {
19660 public:
19661 void visit (SgNode* node)
19662 {
19663 SgScopeStatement* scope = isSgScopeStatement(node);
19664 if (scope != NULL)
19665 {
19666 SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(scope);
19667 if (functionDefinition != NULL)
19668 {
19669 SgFunctionDeclaration* functionDeclaration = functionDefinition->get_declaration();
19670 ROSE_ASSERT(functionDeclaration != NULL);
19671
19672 string functionName = functionDeclaration->get_name();
19673
19674 printf ("functionName = %s \n",functionName.c_str());
19675
19676 if (functionName == "main")
19677 {
19678
19679 SgBasicBlock* functionBody = functionDefinition->get_body();
19680 ROSE_ASSERT(functionBody != NULL);
19681 SgSymbolTable* symbolTable = functionBody->get_symbol_table();
19682 ROSE_ASSERT(symbolTable != NULL);
19683
19684 // Print out the symbol table.
19685 symbolTable->print();
19686 }
19687 }
19688
19689 SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(scope);
19690 if (namespaceDefinition != NULL)
19691 {
19692 SgNamespaceDeclarationStatement* namespaceDeclaration = namespaceDefinition->get_namespaceDeclaration();
19693 ROSE_ASSERT(namespaceDeclaration != NULL);
19694
19695 string namespaceName = namespaceDeclaration->get_name();
19696
19697 printf ("namespaceName = %s \n",namespaceName.c_str());
19698
19699 if (namespaceName == "B")
19700 {
19701 SgSymbolTable* symbolTable = namespaceDefinition->get_symbol_table();
19702 ROSE_ASSERT(symbolTable != NULL);
19703
19704 // Print out the symbol table.
19705 symbolTable->print();
19706 }
19707 }
19708 }
19709 }
19710 };
19711
19712 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19713 ScopeTraversal traversal;
19714 traversal.traverse(astNode, preorder);
19715 }
19716
19717//Jim Leek TODO (07/25/2023): After Dan merges his branch, please clean up all the #1f 0 stuff
19718void SageInterface::markNodeToBeUnparsed(SgNode* node, int physical_file_id)
19719 {
19720#if 0
19721 Sg_File_Info* fileInfo=node->get_file_info();
19722 if (fileInfo != NULL)
19723 {
19724 fileInfo->setTransformation();
19725 fileInfo->setOutputInCodeGeneration();
19726
19727 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19728 if (locatedNode != NULL)
19729 {
19730 // DQ (7/7/2015): Make the subtree as transformed.
19731 locatedNode->setTransformation();
19732 locatedNode->setOutputInCodeGeneration();
19733
19734 // DQ (7/8/2021): Added assertion.
19735 ROSE_ASSERT(locatedNode->get_file_info() != NULL);
19736#if 0
19737 printf ("In markNodeToBeUnparsed(): physical_file_id = %d \n",physical_file_id);
19738#endif
19739 // DQ (10/26/2020): Set the physical_file_id, required for ueader file unparsing (is it?).
19740 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19741#if 1
19742 printf ("Note: calling node markTransformationsForOutput(): node = %p = %s \n",node,node->class_name().c_str());
19743#endif
19744 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19745 // to call setTransformation() and setOutputInCodeGeneration().
19746 markTransformationsForOutput(node);
19747 }
19748 else
19749 {
19750#if 0
19751 printf ("Note: node is not a SgLocatedNode: node = %p = %s \n",node,node->class_name().c_str());
19752#endif
19753 }
19754 }
19755 else
19756 {
19757#if 0
19758 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19759#endif
19760 }
19761#else
19762 SgLocatedNode* locatedNode = isSgLocatedNode(node);
19763 if (locatedNode != NULL)
19764 {
19765 locatedNode->setTransformation();
19766 locatedNode->setOutputInCodeGeneration();
19767
19768 // DQ (10/26/2020): Set the physical_file_id, required for header file unparsing (is it?).
19769 if (locatedNode->get_file_info() != NULL)
19770 {
19771#if 0
19772 printf ("In SageInterface::markNodeToBeUnparsed(): locatedNode = %p = %s calling set_physical_file_id(%d) \n",locatedNode,locatedNode->class_name().c_str(),physical_file_id);
19773#endif
19774 locatedNode->get_file_info()->set_physical_file_id(physical_file_id);
19775 }
19776 else
19777 {
19778#if 1
19779 printf ("Note: no Sg_File_Info was found: node = %p = %s \n",node,node->class_name().c_str());
19780#endif
19781 }
19782
19783 // DQ (7/14/2021): This is just a redundant traversal over the subtree that only appears
19784 // to call setTransformation() and setOutputInCodeGeneration().
19785 // Jim Leek (07/25/2023) This doesn't seem to be redundant, it definately marks a bunch of the subtree as transformed
19786 // That otherwise isn't, but Reverse Type Dependence often fails to compile because too much gets unparsed.
19787 // markTransformationsForOutput(node);
19788 }
19789#endif
19790 }
19791
19792
19793
19794void SageInterface::markSubtreeToBeUnparsed(SgNode* root, int physical_file_id)
19795 {
19796 RoseAst ast(root);
19797 for (RoseAst::iterator i=ast.begin();i!=ast.end();++i)
19798 {
19799 markNodeToBeUnparsed(*i,physical_file_id);
19800 }
19801 }
19802
19803
19804
19806 {
19807 // DQ (7/13/2021): This function marks nodes in a subtree to be a transformation, but avoids marking subtrees of the SgCastExp.
19808 // This is important because currently the marking of an implicit cast will cause it to be unparsed, even though it is marked
19809 // as implicit. This detail of precedence of implicit flags over transformation flags needs to be fixed seperated.
19810 // This function has been implemented as part of debugging this issue.
19811
19812 class InheritedAttribute
19813 {
19814 public:
19815 int physical_file_id;
19816 bool isCastSubtree;
19817 InheritedAttribute(int file_id): physical_file_id(file_id), isCastSubtree(false) {}
19818 InheritedAttribute(const InheritedAttribute & X)
19819 {
19820 isCastSubtree = X.isCastSubtree;
19821 physical_file_id = X.physical_file_id;
19822 }
19823 };
19824
19825// DQ (7/21/21): This code construction does not work with the GNU 4.9.x compilers.
19826// #if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) ) || (__GNUC__ < 4))
19827#if (__GNUC__ > 4)
19828
19829 class SubtreeTraversal : public SgTopDownProcessing<InheritedAttribute>
19830 {
19831 public:
19832 InheritedAttribute evaluateInheritedAttribute ( SgNode* node, InheritedAttribute inheritedAttribute)
19833 {
19834 InheritedAttribute returnAttribute(inheritedAttribute);
19835
19836 SgCastExp* castExpression = isSgCastExp(node);
19837 if (castExpression != NULL)
19838 {
19839 returnAttribute.isCastSubtree = true;
19840 }
19841
19842 if (returnAttribute.isCastSubtree == true)
19843 {
19844 // Nothing to do, unless we want to fixup the physical node id.
19845#if 0
19846 printf ("In markSubtreeToBeUnparsedTreeTraversal(): subtree of a SgCastExp: node = %p = %s physical_file_id = %d \n",
19847 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19848#endif
19849 }
19850 else
19851 {
19852#if 0
19853 printf ("In markSubtreeToBeUnparsedTreeTraversal(): Calling markNodeToBeUnparsed(): node = %p = %s physical_file_id = %d \n",
19854 node,node->class_name().c_str(),inheritedAttribute.physical_file_id);
19855#endif
19856 // This logic will cause the SgCastExp node to NOT be marked as a transformation (not just its children).
19857 markNodeToBeUnparsed(node,inheritedAttribute.physical_file_id);
19858 }
19859
19860 return returnAttribute;
19861 }
19862 };
19863
19864 InheritedAttribute inheritedAttribute(physical_file_id);
19865
19866 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
19867 SubtreeTraversal traversal;
19868
19869#if 0
19870 printf ("\nIn markSubtreeToBeUnparsedTreeTraversal(): calling traverse \n");
19871#endif
19872
19873 traversal.traverse(root, inheritedAttribute);
19874#else
19875 printf ("This function does not compile with GNU 4.9 or older compilers (part of ROSE used only with more modern compilers) \n");
19876#endif
19877
19878 }
19879
19880
19881
19882
19884vector<SgDeclarationStatement*>
19885generateCopiesOfDependentDeclarations (const vector<SgDeclarationStatement*>& dependentDeclarations, SgScopeStatement* targetScope)
19886//generateCopiesOfDependentDeclarations ( SgStatement* stmt, SgScopeStatement* targetScope )
19887 {
19888 // Liao suggests adding the target scope to the parameter list so that the constructed function
19889 // built using SageBuilder::buildNondefiningFunctionDeclaration() can be built to be in the
19890 // correct scope as soon as possible.
19891
19892 // This function uses the getDependentDeclarations() function to get the dependent declarations
19893 // and then returns a list of copies of each of them.
19894
19895#if 0
19896 printf ("\n\n********************************************************** \n");
19897 printf (" Inside of generateCopiesOfDependentDeclarations(stmt = %p = %s) \n",stmt,stmt->class_name().c_str());
19898 printf ("********************************************************** \n");
19899#endif
19900
19901 vector<SgDeclarationStatement*> copiesOfDependentDeclarations;
19902 // avoiding call getDependentDeclarations() twice
19903// vector<SgDeclarationStatement*> dependentDeclarations = getDependentDeclarations(stmt);
19904
19905#if 0
19906 printf ("Output the dependentDeclarations: dependentDeclarations.size() = %" PRIuPTR " \n",dependentDeclarations.size());
19907 outputDeclarationList(dependentDeclarations);
19908#endif
19909#if 0
19910 printf ("************************************************ \n");
19911 printf ("*** Make all copies of dependentDeclarations *** \n");
19912 printf ("************************************************ \n");
19913#endif
19914
19915 // Should have a valid scope, so that symbol tables can be expected to be setup.
19916 ROSE_ASSERT(targetScope != NULL);
19917
19918 // DQ (2/25/2009): Initially this is always global scope so test this for now, at least.
19919 ROSE_ASSERT(isSgGlobal(targetScope) != NULL);
19920
19921 for (vector<SgDeclarationStatement*>::const_iterator i = dependentDeclarations.begin(); i != dependentDeclarations.end(); i++)
19922 {
19923#if 0
19924 printf ("Copying declaration = %p = %s = %s \n",*i,(*i)->class_name().c_str(),SageInterface::get_name(*i).c_str());
19925#endif
19926 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
19927
19928 SgNode* copy_node = NULL;
19929 const SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
19930
19931 // For function declarations we don't want to do deep copies on defining declarations
19932 // since that would violate the One-time Definition Rule (ODR).
19933 if (functionDeclaration != NULL)
19934 {
19935 // the target scope may already have a declaration for this function.
19936 // This happens since SageInterface::appendStatementWithDependentDeclaration() is called in the end of outlining
19937 // and the original enclosing class of the outlined target has been changed already (replaced target with a call to OUT_xxx())
19938 // Also, getDependentDeclarations() recursively searches for declarations within the dependent class and hits OUT_xxx()
19939 // Liao, 5/8/2009
19940
19941 if ( SgProject::get_verbose() >= 1 )
19942 printf ("WARNING: In SageInterface -- generateCopiesOfDependentDeclarations(): I think this is the wrong lookup symbol function that is being used here! \n");
19943
19944 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
19945 // TV (2/4/2014): can be found in the project wide global scope...
19946 // So I removed it as we only build a nondef decl and it will only happen for function declared in global scope.`
19947#endif
19948#if 0
19949 printf ("In generateCopiesOfDependentDeclarations(): Copy mechanism appied to SgFunctionDeclaration functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19950
19951 printf ("functionDeclaration = %p \n",functionDeclaration);
19952 printf ("functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
19953 printf ("functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
19954 printf ("functionDeclaration->get_scope() = %p \n",functionDeclaration->get_scope());
19955 printf ("targetScope = %p \n",targetScope);
19956#endif
19957 SgFunctionDeclaration* copy_functionDeclaration = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,targetScope);
19958 assert(copy_functionDeclaration != NULL);
19959
19960 copy_functionDeclaration->set_parent(targetScope);
19961
19962 assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != NULL);
19963
19964 // DQ (11/8/2020): This can not be asserted now that the buildSourceFile() has the
19965 // feature of clearing the symbol table used across multiple files.
19966 // assert(copy_functionDeclaration->get_firstNondefiningDeclaration() != copy_functionDeclaration);
19967
19968 assert(copy_functionDeclaration->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table() != NULL);
19969
19970 assert(copy_functionDeclaration->get_scope() != NULL);
19971 assert(copy_functionDeclaration->get_scope() == targetScope);
19972 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19973 copy_functionDeclaration->get_type()) != NULL);
19974 assert(copy_functionDeclaration->get_scope()->lookup_function_symbol(copy_functionDeclaration->get_name(),
19975 copy_functionDeclaration->get_type())->get_symbol_basis() == copy_functionDeclaration->get_firstNondefiningDeclaration());
19976
19977 copy_node = copy_functionDeclaration;
19978#if 0
19979 printf ("In generateCopiesOfDependentDeclarations(): DONE: Copy mechanism appied to SgFunctionDeclaration \n");
19980 ROSE_ABORT();
19981#endif
19982 }
19983 else
19984 {
19985 // We only copy the non-defining declaration of a defining typedef declaration
19986 // since its defining body will be treated as a separate declaration and inserted to the new file.
19987 // This is also a workaround for an AST copy bug: losing defining body of a defining typedef declaration after copying.
19988 SgTypedefDeclaration* tdecl = isSgTypedefDeclaration(*i);
19989 if (tdecl)
19990 {
19991#if 0
19992 if (tdecl->get_definingDeclaration() == tdecl)
19993 cout<<"Copying a defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19994 else
19995 cout<<"Copying a non-defining typedef declaration:"<<tdecl->unparseToString()<<endl;
19996#endif
19998 SgTypedefDeclaration* tdecl_copy = isSgTypedefDeclaration(copy_node);
19999 tdecl_copy->set_typedefBaseTypeContainsDefiningDeclaration (false); // explicit indicate this does not contain defining base type, Liao 12/14/2012
20000 }
20001 else
20002 copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
20003
20004 // 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).
20005 SgDeclarationStatement* copy_declaration = isSgDeclarationStatement(copy_node);
20006 ROSE_ASSERT(copy_declaration != NULL);
20007
20008 // DQ (3/2/2009): This will be done later, but it is set above, so set it in this branch to be consistant.
20009 if (copy_declaration->hasExplicitScope() == true)
20010 copy_declaration->set_scope(targetScope);
20011 }
20012
20013 // SgNode* copy_node = (*i)->copy(collectDependentDeclarationsCopyType);
20014 // Build a function prototype, but what scope should be used?
20015 // ROSE_ASSERT(functionDeclaration->get_scope() != NULL);
20016 // copy = SageBuilder::buildNondefiningFunctionDeclaration(functionDeclaration,functionDeclaration->get_scope());
20017
20018#if 0
20019 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());
20020#endif
20021
20022 ROSE_ASSERT(copy_node != NULL);
20023 ROSE_ASSERT(copy_node->get_file_info() != NULL);
20024
20025 // Note that the root of the does not have its file info set like its children.
20026 copy_node->get_file_info()->setTransformation();
20028 // copy_node->get_file_info()->display("CollectDependentDeclarationsTraversal::visit()");
20029
20030 SgDeclarationStatement* copy_definingDeclaration = isSgDeclarationStatement(copy_node);
20031 ROSE_ASSERT(copy_definingDeclaration != NULL);
20032
20033 ROSE_ASSERT( *i != NULL );
20034 ROSE_ASSERT(copy_definingDeclaration != NULL);
20035
20036 // DQ (2/26/2009): get_scope() will require a valid parent for some cases (see moreTest4.cpp).
20037 if (copy_definingDeclaration->get_parent() == NULL)
20038 {
20039 copy_definingDeclaration->set_parent(targetScope);
20040 }
20041 ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
20042
20043#if 0
20044 printf ("DONE: Copying declaration: original scope = %p copied to scope = %p \n",(*i)->get_scope(),copy_definingDeclaration->get_scope());
20045#endif
20046
20047 // DQ (2/22/2009): I think we need to set these explicitly (it will be reset later).
20048 copy_definingDeclaration->set_parent(NULL);
20049
20050 // Now that we pass in the scope explicitly we can set the scope (above), so don't reset to NULL!
20051 // copy_definingDeclaration->set_scope(NULL);
20052
20053 // DQ (2/20/2009): Added assertion.
20054 ROSE_ASSERT(copy_definingDeclaration->get_parent() == NULL);
20055
20056#if 0
20057 // DQ (2/20/2009): Added assertion.
20058 // ROSE_ASSERT(copy_definingDeclaration->get_definingDeclaration() != NULL);
20059 if (copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL)
20060 {
20061 printf ("copy_definingDeclaration = %p \n",copy_definingDeclaration);
20062 printf ("copy_definingDeclaration->get_firstNondefiningDeclaration() == NULL \n");
20063 printf ("copy_definingDeclaration->get_definingDeclaration() = %p \n",copy_definingDeclaration->get_definingDeclaration());
20064 }
20065#endif
20066
20067 // DQ (2/21/2009): Commented out as a test.
20068 if ((*i)->get_firstNondefiningDeclaration() != NULL)
20069 {
20070 ROSE_ASSERT(copy_definingDeclaration->get_firstNondefiningDeclaration() != NULL);
20071 }
20072
20073 // DQ (2/20/2009): Added asertion.
20074 // ROSE_ASSERT(copy_definingDeclaration->get_parent() != NULL);
20075
20076 copiesOfDependentDeclarations.push_back(copy_definingDeclaration);
20077 }
20078
20079#if 0
20080 printf ("****************************************************** \n");
20081 printf ("*** DONE: Make all copies of dependentDeclarations *** \n");
20082 printf ("****************************************************** \n");
20083 printf ("copiesOfDependentDeclarations.size() = %" PRIuPTR " \n",copiesOfDependentDeclarations.size());
20084#endif
20085
20086 // The mapping of copies to original declarations should be 1-to-1.
20087 // Liao, not true anymore for getDependentDeclarations() using recursion: a depending class's body is searched for dependents also.
20088 // 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
20089 ROSE_ASSERT(copiesOfDependentDeclarations.size() <= dependentDeclarations.size());
20090
20091 return copiesOfDependentDeclarations;
20092 }
20093
20094
20095bool
20096declarationContainsDependentDeclarations( SgDeclarationStatement* decl, vector<SgDeclarationStatement*> & dependentDeclarationList )
20097 {
20098 // DQ (2/16/2009): This function finds the declarations in "decl" and checks if they match against those in dependentDeclarationList
20099 bool returnValue = false;
20100
20101#if 0
20102 printf ("\n\n********************************************************** \n");
20103 printf (" Inside of declarationContainsDependentDeclarations(decl = %p = %s) \n",decl,decl->class_name().c_str());
20104 printf ("********************************************************** \n");
20105#endif
20106
20107 vector<SgDeclarationStatement*> locallyDependentDeclarationList = SageInterface::getDependentDeclarations(decl);
20108
20109 // printf ("In declarationContainsDependentDeclarations(): locallyDependentDeclarationList: \n");
20110 // outputPreprocessingInfoList(locallyDependentDeclarationList);
20111
20112 for (size_t i = 0; i < locallyDependentDeclarationList.size(); i++)
20113 {
20114 SgDeclarationStatement* d = locallyDependentDeclarationList[i];
20115#if 0
20116 printf ("locallyDependentDeclarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20117#endif
20118 vector<SgDeclarationStatement*>::iterator j = find(dependentDeclarationList.begin(),dependentDeclarationList.end(),d);
20119 if (j != dependentDeclarationList.end())
20120 {
20121 // These identified declaration must be output as members of the class when it is output in the separate header file.
20122 // infact ODR may require that the whole class be output! Actually I think we don't have any chioce here!
20123#if 0
20124 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());
20125#endif
20126 returnValue = true;
20127 }
20128 }
20129
20130#if 0
20131 printf ("**************************************************************************** \n");
20132 printf (" LEAVING: Inside of declarationContainsDependentDeclarations(decl = %p = %s) returnValue = %s \n",decl,decl->class_name().c_str(),returnValue ? "true" : "false");
20133 printf ("**************************************************************************** \n");
20134#endif
20135
20136 return returnValue;
20137 }
20140{
20141 ROSE_ASSERT (new_exp != NULL);
20142 ROSE_ASSERT (anchor_exp != NULL);
20143 ROSE_ASSERT (new_exp != anchor_exp);
20144
20145 SgNode* parent = anchor_exp->get_parent();
20146 ROSE_ASSERT (parent != NULL);
20147
20148 //TODO use deep copy may be a better way, avoid reusing the original anchor_exp
20149 SgCommaOpExp * result = buildCommaOpExp(new_exp, NULL);
20150 ROSE_ASSERT (result != NULL);
20151 replaceExpression (anchor_exp, result, true);
20152
20153 result->set_rhs_operand(anchor_exp);
20154 anchor_exp->set_parent(result);
20155 return result ;
20156}
20157
20158
20160SgCommaOpExp * SageInterface::insertAfterUsingCommaOp (SgExpression* new_exp, SgExpression* anchor_exp, SgStatement** temp_decl /* = NULL */, SgVarRefExp** temp_ref /* = NULL */)
20161{
20162 ROSE_ASSERT (new_exp != NULL);
20163 ROSE_ASSERT (anchor_exp != NULL);
20164 ROSE_ASSERT (new_exp != anchor_exp);
20165
20166 SgNode* parent = anchor_exp->get_parent();
20167 ROSE_ASSERT (parent != NULL);
20168
20169 // insert TYPE T1; right before the enclosing statement of anchor_exp
20170 SgType * t = anchor_exp ->get_type();
20171 ROSE_ASSERT (t != NULL);
20172 SgStatement * enclosing_stmt = getEnclosingStatement(anchor_exp);
20173 ROSE_ASSERT (enclosing_stmt != NULL);
20174
20175 gensym_counter ++;
20176 string temp_name = "_t_"+ StringUtility::numberToString(gensym_counter);
20177 SgVariableDeclaration* t_decl = buildVariableDeclaration(temp_name, t, NULL, enclosing_stmt->get_scope());
20178 insertStatementBefore (enclosing_stmt, t_decl);
20179 SgVariableSymbol * temp_sym = getFirstVarSym (t_decl);
20180 ROSE_ASSERT (temp_sym != NULL);
20181 if (temp_decl)
20182 *temp_decl = t_decl;
20183
20184 // build ((T1 = anchor_exp, new_exp),T1) )
20185 SgVarRefExp * first_ref = buildVarRefExp(temp_sym);
20186 if (temp_ref)
20187 * temp_ref = first_ref;
20188 SgCommaOpExp * result = buildCommaOpExp ( buildCommaOpExp (buildAssignOp ( first_ref, deepCopy(anchor_exp)), new_exp) , buildVarRefExp(temp_sym));
20189 replaceExpression (anchor_exp, result, false);
20190
20191 return result;
20192}
20193
20194void
20196 {
20197 // Put out a message in the separate file to lable the dependent CPP directives.
20198 // --- PreprocessingInfo(DirectiveType, const std::string & inputString, const std::string & filenameString, int line_no, int col_no, int nol, RelativePositionType relPos );
20199 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20200 string fileName = "separate-outlined-file";
20201 PreprocessingInfo* messageToUser = new PreprocessingInfo(PreprocessingInfo::C_StyleComment,message,fileName,0,0,1,PreprocessingInfo::before);
20202 // requiredDirectivesList.push_back(messageToUser);
20203 stmt->addToAttachedPreprocessingInfo(messageToUser,PreprocessingInfo::before);
20204
20205 // DQ (3/12/2019): We need to mark the added comments and CPP directives as a transformation so that then can be output.
20206 // This is a result of a fix to support the correct handling of comments and CPP directives for shared IR nodes as happen
20207 // when multiple files are used on the command line.
20208 messageToUser->get_file_info()->setTransformation();
20209 }
20210
20211
20212// DQ (2/6/2009): Added function to support outlining into separate file.
20213// 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)
20214void
20216 {
20217 // New function to support outlining of functions into separate files (with their required declarations).
20218
20219#if 0
20220 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl = %p \n",decl);
20221 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_parent() = %p \n",decl->get_parent());
20222 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_scope() = %p \n",decl->get_scope());
20223 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): original_statement = %p \n",original_statement);
20224 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (decl) = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20225 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_firstNondefiningDeclaration() = %p \n",decl->get_firstNondefiningDeclaration());
20226 if (decl->get_firstNondefiningDeclaration() != NULL)
20227 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20228 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): decl->get_definingDeclaration() = %p \n",decl->get_definingDeclaration());
20229 if (decl->get_definingDeclaration() != NULL)
20230 printf ("***** In SageInterface::appendStatementWithDependentDeclaration(): file (first non-defining) = %s \n",TransformationSupport::getSourceFile(decl->get_definingDeclaration())->getFileName().c_str());
20231#endif
20232
20233#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20234 // Make sure that the input declaration (decl" is consistent in it's representation across more
20235 // than one file (only a significant test when outlining to a separate file; which is what this
20236 // function supports).
20237 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20238 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20239 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20240
20241 // DQ (2/6/2009): I need to write this function to support the
20242 // insertion of the function into the specified scope. If the
20243 // file associated with the scope is marked as compiler generated
20244 // (or as a transformation) then the declarations referenced in the
20245 // function must be copied as well (those not in include files)
20246 // and the include files must be copies also. If the SgFile
20247 // is not compiler generated (or a transformation) then we just
20248 // append the function to the scope (trivial case).
20249
20250 // This code will be based on the work in:
20251 // developersScratchSpace/Dan/translator_tests/reverseTraversal.C
20252
20253 // To test this run: "rm moreTest2.o ; make moreTest2.o"
20254 // in directory: tests/nonsmoke/functional/roseTests/astOutliningTests
20255
20256 // ***** Also move different loop IR nodes into a common base class *****
20257
20258 // SgSourceFile* separateSourceFile = TransformationSupport::getSourceFile(scope);
20259
20260 // DQ (3/2/2009): This now calls a newer function which returns a list of declarations and a list of symbols.
20261 // The declarations are sometimes outer declarations of nested references to dependent declaration in inner
20262 // scopes (see moreTest3.cpp). The Symbol list are the symbols in the old AST that will be mapped to newer
20263 // symbols generated in the copied AST.
20264 // Collect the declaration that the input declaration depends upon.
20265 vector<SgDeclarationStatement*> dependentDeclarationList_inOriginalFile;
20266
20267 dependentDeclarationList_inOriginalFile = getDependentDeclarations(decl);
20268
20269 // Generate the copies of all the dependent statements
20270// printf ("Fixme: this currently causes the getDependentDeclarations(decl) function to be called twice \n");
20271// vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(decl,scope);
20272 vector<SgDeclarationStatement*> dependentDeclarationList = generateCopiesOfDependentDeclarations(dependentDeclarationList_inOriginalFile,scope);
20273 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20274
20275 // Make sure that the input declaration (decl" is consistent in it's representation across more
20276 // than one file (only a significant test when outlining to a separate file; which is what this
20277 // function supports).
20278 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20279 ROSE_ASSERT(TransformationSupport::getSourceFile(decl) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20280 ROSE_ASSERT(TransformationSupport::getSourceFile(decl->get_scope()) == TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration()));
20281
20282 // This is used to fixup the AST by resetting references to IR nodes (leveraged from AST merge).
20283 std::map<SgNode*, SgNode*> replacementMap;
20284
20285 // DQ (3/2/2009): Now use the collectDependentDeclarationsCopyType object to generate the mapping
20286 // from the symbols in the old AST to the new symbols in the new AST (generated as part of the AST
20287 // copy mechanism).
20288 SgCopyHelp::copiedNodeMapType copyNodeMap = collectDependentDeclarationsCopyType.get_copiedNodeMap();
20289 SgCopyHelp::copiedNodeMapType::iterator copyNodeMapItrator = copyNodeMap.begin();
20290 while (copyNodeMapItrator != copyNodeMap.end())
20291 {
20292 // Loop over all the nodes generated in the AST copy mechanism (accumulated result over multiple copies).
20293 // const SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20294 // SgNode* first = copyNodeMapItrator->first;
20295 SgNode* first = const_cast<SgNode*>(copyNodeMapItrator->first);
20296 SgNode* second = copyNodeMapItrator->second;
20297#if 0
20298 printf ("copyNodeMapItrator.first = %p = %s second = %p = %s \n",first,first->class_name().c_str(),second,second->class_name().c_str());
20299#endif
20300 // Add the SgGlobal referenece to the replacementMap
20301 if (isSgSymbol(first) != NULL)
20302 {
20303#if 0
20304 printf ("Adding to replacementMap (first = %p = %s = %s , second = %p \n",first,first->class_name().c_str(),SageInterface::get_name(first).c_str(),second);
20305#endif
20306 replacementMap.insert(pair<SgNode*,SgNode*>(first,second));
20307 }
20308
20309 copyNodeMapItrator++;
20310 }
20311
20312#if 0
20313 printf ("Exiting after test of new functionality \n");
20314 ROSE_ABORT();
20315#endif
20316
20317 // DQ (2/22/2009): We need all the declarations! (moreTest3.cpp demonstrates this, since it drops
20318 // the "#define SIMPLE 1" which causes it to be treated a "0" (causing errors in the generated code).
20319 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(original_statement);
20320 vector<PreprocessingInfo*> requiredDirectivesList = collectCppDirectives(sourceFile);
20321
20322 SgFunctionDeclaration* outlinedFunctionDeclaration = isSgFunctionDeclaration(decl);
20323 ROSE_ASSERT(outlinedFunctionDeclaration != NULL);
20324 SgGlobal* originalFileGlobalScope = TransformationSupport::getGlobalScope(original_statement);
20325 ROSE_ASSERT(originalFileGlobalScope != NULL);
20326 if ( SgProject::get_verbose() >= 1 )
20327 printf ("WARNING: In SageInterface::appendStatementWithDependentDeclaration(): I think this is the wrong lookup symbol function that is being used here! \n");
20328
20329 // DQ (8/16/2013): I think this is the wrong symbol lookup function to be using here, but the API is fixed.
20330 // SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name()));
20331 SgFunctionSymbol* outlinedFunctionSymbolFromOriginalFile = isSgFunctionSymbol(originalFileGlobalScope->lookup_symbol(outlinedFunctionDeclaration->get_name(),NULL,NULL));
20332
20333 // SgSymbol* outlinedFunctionSymbolFromOutlinedFile = scope->lookup_symbol(outlinedFunctionDeclaration->get_name());
20334 ROSE_ASSERT(decl->get_firstNondefiningDeclaration() != NULL);
20335 SgFunctionSymbol* outlinedFunctionSymbolFromOutlinedFile = isSgFunctionSymbol(decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table());
20336#if 0
20337 printf ("outlinedFunctionSymbolFromOriginalFile = %p outlinedFunctionSymbolFromOutlinedFile = %p \n",outlinedFunctionSymbolFromOriginalFile,outlinedFunctionSymbolFromOutlinedFile);
20338
20339 printf ("TransformationSupport::getSourceFile(decl)->getFileName() = %s \n",TransformationSupport::getSourceFile(decl)->getFileName().c_str());
20340 printf ("TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName() = %s \n",TransformationSupport::getSourceFile(decl->get_firstNondefiningDeclaration())->getFileName().c_str());
20341 printf ("TransformationSupport::getSourceFile(original_statement)->getFileName() = %s \n",TransformationSupport::getSourceFile(original_statement)->getFileName().c_str());
20342#endif
20343
20344 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile != NULL);
20345 ROSE_ASSERT(outlinedFunctionSymbolFromOutlinedFile != NULL);
20346
20347 // TV (07/24/2013): Symbol are unified across files through the project wide global scope
20348 ROSE_ASSERT(outlinedFunctionSymbolFromOriginalFile == outlinedFunctionSymbolFromOutlinedFile);
20349
20350 // Add the SgGlobal referenece to the replacementMap
20351 replacementMap.insert(pair<SgNode*,SgNode*>(originalFileGlobalScope,scope));
20352
20353 // Add the non-defining declarations of the outlined function to the replacementMap
20354 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOriginalFile = isSgFunctionDeclaration(outlinedFunctionSymbolFromOriginalFile->get_declaration());
20355 SgFunctionDeclaration* outlinedNondefiningFunctionDeclarationFromOutlinedFile = isSgFunctionDeclaration(decl->get_firstNondefiningDeclaration());
20356 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOriginalFile != NULL);
20357 ROSE_ASSERT(outlinedNondefiningFunctionDeclarationFromOutlinedFile != NULL);
20358 replacementMap.insert(pair<SgNode*,SgNode*>(outlinedNondefiningFunctionDeclarationFromOriginalFile,outlinedNondefiningFunctionDeclarationFromOutlinedFile));
20359
20360
20361 // list<SgDeclarationStatement>::iterator i = declarationList.begin();
20362 // while (i != declarationList.end())
20363 // for (list<SgDeclarationStatement>::iterator i = declarationList.begin(); i != declarationList.end(); i++)
20364
20365// cout<<"\n*******************************************\n"<<endl;
20366// cout<<"Inserting dependent decls: count="<<dependentDeclarationList.size()<<endl;
20367 for (size_t i = 0; i < dependentDeclarationList.size(); i++)
20368 {
20369 SgDeclarationStatement* d = dependentDeclarationList[i]; // copies of dependent declarations
20370#if 0
20371 SgDeclarationStatement* originalDeclaration = dependentDeclarationList_inOriginalFile[i];
20372 printf ("declarationList[%" PRIuPTR "] = %p = %s = %s \n",i,d,d->class_name().c_str(),SageInterface::get_name(d).c_str());
20373 printf ("originalDeclaration = %p \n",originalDeclaration);
20374
20375 d->get_file_info()->display("SageInterface::appendStatementWithDependentDeclaration()");
20376#endif
20377
20378 // DQ (2/20/2009): Added assertion.
20379 ROSE_ASSERT(d->get_parent() == NULL);
20380
20381 // scope->append_declaration(d);
20382 // scope->insert_statement (decl, d, /* bool inFront= */ true);
20383 ROSE_ASSERT(decl->get_scope() == scope);
20384 ROSE_ASSERT(find(scope->getDeclarationList().begin(),scope->getDeclarationList().end(),decl) != scope->getDeclarationList().end());
20385 scope->insert_statement (decl, d, /* bool inFront= */ true);
20386 d->set_parent (scope);
20387
20388#if 0
20389 printf ("Add the required symbol information to the symbol table: scope = %p = %s \n",scope,scope->class_name().c_str());
20390#endif
20391
20392 // For whatever type of declaration we add to the global scope in the new separate
20393 // file we have to add the required symbol information to the symbol table.
20394 switch(d->variantT())
20395 {
20396 case V_SgClassDeclaration:
20397 {
20398 if ( declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20399 printf ("Warning: This class contains dependent declarations (not implemented) \n");
20400 break;
20401 }
20402
20403 case V_SgMemberFunctionDeclaration:
20404 printf ("Sorry, support for dependent member function declarations not implemented! \n");
20405 ROSE_ABORT();
20406
20407 case V_SgTemplateInstantiationDecl:
20408 printf ("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration \n");
20409 d->get_file_info()->display("Sorry, not implemented: case SgTemplateInstantiationDecl not handled as dependent declaration");
20410
20411 printf ("Case of SgTemplateInstantiationDecl not implemented. \n");
20412 ROSE_ABORT();
20413
20414 case V_SgNamespaceDeclarationStatement:
20415 if (declarationContainsDependentDeclarations(d,dependentDeclarationList) == true )
20416 printf ("Warning: This namespace contains dependent declarations (not supported) \n");
20417 break;
20418
20419 case V_SgFunctionDeclaration:
20420 case V_SgTypedefDeclaration:
20421 case V_SgEnumDeclaration:
20422 break;
20423
20424 default:
20425 printf ("default case in SageInterface::appendStatementWithDependentDeclaration() (handling dependentDeclarationList) d = %p = %s \n",d,d->class_name().c_str());
20426 ROSE_ABORT();
20427 }
20428
20429
20430 // Collect include directives that are already attached to this dependent declaration.
20431 vector<PreprocessingInfo*> cppDirectivesAlreadyAttachedToDependentDeclarations = collectCppDirectives(d);
20432
20433#if 0
20434 printf ("directives BEFORE excluding those already present in dependent declarations \n");
20435 outputPreprocessingInfoList(requiredDirectivesList);
20436
20437 printf ("directives already attached to dependent declarations \n");
20438 outputPreprocessingInfoList(cppDirectivesAlreadyAttachedToDependentDeclarations);
20439#endif
20440
20441 // Remove these include directives from the requiredDirectivesList (to prevent redundant output in the generated file)
20442 vector<PreprocessingInfo*>::iterator j = cppDirectivesAlreadyAttachedToDependentDeclarations.begin();
20443 while ( j != cppDirectivesAlreadyAttachedToDependentDeclarations.end() )
20444 {
20445 // Remove this directive from the requiredDirectivesList (to avoid having them output redundently).
20446 vector<PreprocessingInfo*>::iterator entry = find(requiredDirectivesList.begin(),requiredDirectivesList.end(),*j);
20447 ROSE_ASSERT(entry != requiredDirectivesList.end());
20448
20449 requiredDirectivesList.erase(entry);
20450
20451 j++;
20452 }
20453
20454#if 0
20455 printf ("directives AFTER excluding those already present in dependent declarations \n");
20456 outputPreprocessingInfoList(requiredDirectivesList);
20457#endif
20458 }
20459
20460 // Add a message to the top of the outlined function that has been added
20461 addMessageStatement(decl,"/* OUTLINED FUNCTION */");
20462
20463 // Insert the dependent declarations ahead of the input "decl".
20464 SgStatement* firstStatmentInFile = NULL;
20465 if (dependentDeclarationList.empty() == true)
20466 {
20467 firstStatmentInFile = decl;
20468 }
20469 else
20470 {
20471 firstStatmentInFile = dependentDeclarationList[0];
20472 }
20473
20474 ROSE_ASSERT(firstStatmentInFile != NULL);
20475
20476 // Add a message to the top of the dependent declarations that have been added
20477 addMessageStatement(firstStatmentInFile,"/* REQUIRED DEPENDENT DECLARATIONS */");
20478
20479 // DQ (3/6/2009): Added support to permit exclusion of "#include<header.h>" files since they can make it
20480 // much more difficult for external tools. Later we will check if there are remaining unsatisfied dependent
20481 // declarations (which must be in the header file) so we can automate this step.
20482 if (excludeHeaderFiles == false)
20483 {
20484 // Include all the "#include<header.h>" cpp directives obtained from the original file.
20485 vector<PreprocessingInfo*>::reverse_iterator j = requiredDirectivesList.rbegin();
20486 while ( j != requiredDirectivesList.rend() )
20487 {
20488 firstStatmentInFile->addToAttachedPreprocessingInfo(*j,PreprocessingInfo::before);
20489 j++;
20490 }
20491 }
20492
20493 // Add a message to the top of the CPP directives that have been added
20494 addMessageStatement(firstStatmentInFile,"/* REQUIRED CPP DIRECTIVES */");
20495
20496 // ****************************************************************************
20497 // **************** Fixup AST to Reset References To IR nodes ***************
20498 // ****************************************************************************
20499 // This traversal of the replacement map modified the AST to reset pointers to subtrees that will be shared.
20500 // The whole AST is traversed (using the memory pool traversal) and the data member pointers to IR nodes that
20501 // are found in the replacement map are used to lookup the replacement values that are used to reset the
20502 // pointers in the AST. As the replacement is computed the pointer values that are marked in the replacement
20503 // list for update are added to the intermediateDeleteSet.
20504
20505 SgSourceFile* outlinedFile = TransformationSupport::getSourceFile(scope);
20506 ROSE_ASSERT(outlinedFile != NULL);
20507
20508 // This replacement will be done over the entire file (parts of it are redundant with what has already
20509 // been done by the AST copy (so this step need not do as much and may be reduced to just operating
20510 // on the outlined function, I think).
20511#if 0
20512 printf ("\n\n************************************************************\n");
20513 printf ("Calling Utils::edgePointerReplacement() \n");
20514#endif
20515
20516 Rose::AST::Utility::edgePointerReplacement(outlinedFile,replacementMap);
20517
20518#if 0
20519 printf ("Calling Utils::edgePointerReplacement(): DONE \n");
20520 printf ("************************************************************\n\n");
20521
20522 printf ("\n\n After replacementMapTraversal(): intermediateDeleteSet: \n");
20523 displaySet(intermediateDeleteSet,"After Utils::edgePointerReplacement");
20524#endif
20525
20526 // Repeated test from above
20527 ROSE_ASSERT(dependentDeclarationList.size() <= dependentDeclarationList_inOriginalFile.size());
20528
20529// endif for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
20530#endif
20531
20532#if 0
20533 // The replacementMap should include the symbols associated with the dependentDeclarationList
20534 // and the outlined function (so dependentDeclarationList.size() + 1).
20535 printf ("replacementMap.size() = %" PRIuPTR " dependentDeclarationList.size() = %" PRIuPTR " \n",replacementMap.size(),dependentDeclarationList.size());
20536 // ROSE_ASSERT(replacementMap.size() == dependentDeclarationList.size() + 1);
20537#endif
20538 }
20539
20540void
20542 {
20543//Tan, August/25/2010: //Re-implement DeleteAST function
20544
20545 //Use MemoryPoolTraversal to count the number of references to a certain symbol
20546 //This class defines the visitors for the MemoryPoolTraversal
20547
20548 class ClassicVisitor : public ROSE_VisitorPattern
20549 {
20550 private:
20551 int SgVariableSymbol_count;
20552 int SgFunctionSymbol_count;
20553 int SgClassDeclaration_count;
20554 int SgTypedefSymbol_count;
20555 int SgMemFuncSymbol_count;
20556 int SgTemplateSymbol_count;
20557 int SgEnumFieldSymbol_count;
20558
20559 SgVariableSymbol* SgVariableSymbolPtr;
20560 SgFunctionSymbol* SgFunctionSymbolPtr;
20561 SgClassSymbol * SgClassSymbolPtr;
20562 SgTypedefSymbol * SgTypedefPtr;
20563 SgEnumFieldSymbol * SgEnumFieldSymbolPtr;
20564 SgMemberFunctionSymbol * SgMemFuncSymbolPtr;
20565 SgTemplateSymbol * SgTemplateSymbolPtr;
20566 SgClassDeclaration * class_defining;
20567 SgTemplateDeclaration * template_defining;
20569 SgTypedefDeclaration * typedef_defining;
20570 SgFunctionDeclaration * function_decl;
20571 SgTemplateInstantiationDecl * templateInstantiate_defining;
20572
20573 public:
20574 ClassicVisitor(SgVariableSymbol* symbol){
20575 SgVariableSymbol_count = 0;
20576 SgVariableSymbolPtr = symbol;
20577 SgFunctionSymbolPtr =NULL;
20578 SgClassSymbolPtr =NULL;
20579 SgTypedefPtr = NULL;
20580 SgMemFuncSymbolPtr =NULL;
20581 class_defining = NULL;
20582 memFunc =NULL;
20583 typedef_defining =NULL;
20584 function_decl = NULL;
20585 SgTemplateSymbolPtr = NULL;
20586 template_defining = NULL;
20587 SgEnumFieldSymbolPtr = NULL;
20588 templateInstantiate_defining =NULL;
20589 }
20590
20591 ClassicVisitor(SgFunctionSymbol* symbol){
20592 SgFunctionSymbol_count = 0;
20593 SgFunctionSymbolPtr = symbol;
20594
20595 // DQ (5/2/2013): Added to fix test2013_141.C.
20596 SgMemFuncSymbol_count =0;
20597
20598 SgVariableSymbolPtr = NULL;
20599 SgClassSymbolPtr =NULL;
20600 SgTypedefPtr = NULL;
20601 SgMemFuncSymbolPtr =NULL;
20602 class_defining = NULL;
20603 memFunc =NULL;
20604 typedef_defining =NULL;
20605 function_decl = NULL;
20606 SgTemplateSymbolPtr = NULL;
20607 template_defining = NULL;
20608 SgEnumFieldSymbolPtr = NULL;
20609 templateInstantiate_defining =NULL;
20610 }
20611
20612 ClassicVisitor(SgClassSymbol* symbol){
20613 SgClassDeclaration_count = 0;
20614 SgClassSymbolPtr = symbol;
20615 SgFunctionSymbolPtr = NULL;
20616 SgVariableSymbolPtr = NULL;
20617 SgTypedefPtr = NULL;
20618 SgMemFuncSymbolPtr =NULL;
20619 class_defining = NULL;
20620 memFunc =NULL;
20621 typedef_defining =NULL;
20622 function_decl = NULL;
20623 SgTemplateSymbolPtr = NULL;
20624 template_defining = NULL;
20625 SgEnumFieldSymbolPtr = NULL;
20626 templateInstantiate_defining =NULL;
20627 }
20628
20629 ClassicVisitor(SgTypedefSymbol* symbol){
20630 SgTypedefSymbol_count =0;
20631 SgTypedefPtr = symbol;
20632 SgClassSymbolPtr = NULL;
20633 SgFunctionSymbolPtr = NULL;
20634 SgVariableSymbolPtr = NULL;
20635 SgMemFuncSymbolPtr =NULL;
20636 class_defining = NULL;
20637 memFunc =NULL;
20638 typedef_defining =NULL;
20639 function_decl = NULL;
20640 SgTemplateSymbolPtr = NULL;
20641 template_defining = NULL;
20642 SgEnumFieldSymbolPtr = NULL;
20643 templateInstantiate_defining =NULL;
20644 }
20645
20646 ClassicVisitor(SgMemberFunctionSymbol* symbol){
20647 SgMemFuncSymbolPtr = symbol;
20648 SgMemFuncSymbol_count =0;
20649 SgTypedefPtr = NULL;
20650 SgClassSymbolPtr = NULL;
20651 SgFunctionSymbolPtr = NULL;
20652 SgVariableSymbolPtr = NULL;
20653 class_defining = NULL;
20654 memFunc =NULL;
20655 typedef_defining =NULL;
20656 function_decl = NULL;
20657 SgTemplateSymbolPtr = NULL;
20658 template_defining = NULL;
20659 SgEnumFieldSymbolPtr = NULL;
20660 templateInstantiate_defining =NULL;
20661 }
20662
20663 ClassicVisitor(SgTemplateSymbol* symbol){
20664 SgTemplateSymbolPtr = symbol;
20665 SgTemplateSymbol_count =0;
20666 SgMemFuncSymbolPtr = NULL;
20667 SgTypedefPtr = NULL;
20668 SgClassSymbolPtr = NULL;
20669 SgFunctionSymbolPtr = NULL;
20670 SgVariableSymbolPtr = NULL;
20671 class_defining = NULL;
20672 memFunc =NULL;
20673 typedef_defining =NULL;
20674 function_decl = NULL;
20675 template_defining = NULL;
20676 SgEnumFieldSymbolPtr = NULL;
20677 templateInstantiate_defining =NULL;
20678 }
20679
20680 ClassicVisitor(SgEnumFieldSymbol* symbol){
20681 SgEnumFieldSymbolPtr = symbol;
20682 SgEnumFieldSymbol_count =0;
20683 SgTemplateSymbolPtr = NULL;
20684 SgMemFuncSymbolPtr = NULL;
20685 SgTypedefPtr = NULL;
20686 SgClassSymbolPtr = NULL;
20687 SgFunctionSymbolPtr = NULL;
20688 SgVariableSymbolPtr = NULL;
20689 class_defining = NULL;
20690 memFunc =NULL;
20691 typedef_defining =NULL;
20692 function_decl = NULL;
20693 template_defining = NULL;
20694 templateInstantiate_defining =NULL;
20695 }
20696
20697
20698 ClassicVisitor(SgClassDeclaration* node){
20699 class_defining = node;
20700 SgMemFuncSymbolPtr = NULL;
20701 SgTypedefPtr = NULL;
20702 SgClassSymbolPtr = NULL;
20703 SgFunctionSymbolPtr = NULL;
20704 SgVariableSymbolPtr = NULL;
20705 memFunc =NULL;
20706 typedef_defining =NULL;
20707 function_decl = NULL;
20708 SgTemplateSymbolPtr = NULL;
20709 template_defining = NULL;
20710 SgEnumFieldSymbolPtr = NULL;
20711 templateInstantiate_defining =NULL;
20712 }
20713
20714 ClassicVisitor(SgTemplateDeclaration* node){
20715 template_defining = node;
20716 class_defining = NULL;
20717 SgMemFuncSymbolPtr = NULL;
20718 SgTypedefPtr = NULL;
20719 SgClassSymbolPtr = NULL;
20720 SgFunctionSymbolPtr = NULL;
20721 SgVariableSymbolPtr = NULL;
20722 memFunc =NULL;
20723 typedef_defining =NULL;
20724 function_decl = NULL;
20725 SgTemplateSymbolPtr = NULL;
20726 SgEnumFieldSymbolPtr = NULL;
20727 templateInstantiate_defining =NULL;
20728 }
20729 ClassicVisitor(SgFunctionDeclaration* node){
20730 function_decl =node;
20731 class_defining = NULL;
20732 SgMemFuncSymbolPtr = NULL;
20733 SgTypedefPtr = NULL;
20734 SgClassSymbolPtr = NULL;
20735 SgFunctionSymbolPtr = NULL;
20736 SgVariableSymbolPtr = NULL;
20737 memFunc =NULL;
20738 typedef_defining =NULL;
20739 SgTemplateSymbolPtr = NULL;
20740 template_defining = NULL;
20741 SgEnumFieldSymbolPtr = NULL;
20742 templateInstantiate_defining =NULL;
20743 }
20744
20745 ClassicVisitor(SgMemberFunctionDeclaration* node){
20746 memFunc = node;
20747 function_decl =NULL;
20748 class_defining = NULL;
20749 SgMemFuncSymbolPtr = NULL;
20750 SgTypedefPtr = NULL;
20751 SgClassSymbolPtr = NULL;
20752 SgFunctionSymbolPtr = NULL;
20753 SgVariableSymbolPtr = NULL;
20754 typedef_defining =NULL;
20755 SgTemplateSymbolPtr = NULL;
20756 template_defining = NULL;
20757 SgEnumFieldSymbolPtr = NULL;
20758 templateInstantiate_defining =NULL;
20759 }
20760
20761 ClassicVisitor(SgTypedefDeclaration* node){
20762 typedef_defining = node;
20763 memFunc = NULL;
20764 function_decl =NULL;
20765 class_defining = NULL;
20766 SgMemFuncSymbolPtr = NULL;
20767 SgTypedefPtr = NULL;
20768 SgClassSymbolPtr = NULL;
20769 SgFunctionSymbolPtr = NULL;
20770 SgVariableSymbolPtr = NULL;
20771 SgTemplateSymbolPtr = NULL;
20772 template_defining = NULL;
20773 SgEnumFieldSymbolPtr = NULL;
20774 templateInstantiate_defining =NULL;
20775 }
20776
20777 ClassicVisitor(SgTemplateInstantiationDecl* node){
20778 templateInstantiate_defining =node;
20779 typedef_defining = NULL;
20780 memFunc = NULL;
20781 function_decl =NULL;
20782 class_defining = NULL;
20783 SgMemFuncSymbolPtr = NULL;
20784 SgTypedefPtr = NULL;
20785 SgClassSymbolPtr = NULL;
20786 SgFunctionSymbolPtr = NULL;
20787 SgVariableSymbolPtr = NULL;
20788 SgTemplateSymbolPtr = NULL;
20789 template_defining = NULL;
20790 SgEnumFieldSymbolPtr = NULL;
20791 }
20792
20793
20794 // SgVariableSymbol and SgEnumFieldSymbol
20795 void visit(SgInitializedName* node)
20796 {
20797 if(SgVariableSymbolPtr !=NULL)
20798 {
20799 if(node->get_scope()!=NULL)
20800 {
20801 // DQ (5/21/2013): We want to restrict access to the symbol table.
20802 if(node->get_scope()->get_symbol_table()!=NULL)
20803 {
20805 if (isSgVariableSymbol(s) == SgVariableSymbolPtr) SgVariableSymbol_count++;
20806 }
20807 }
20808 }
20809
20810 if(SgEnumFieldSymbolPtr !=NULL)
20811 {
20812 if(node->get_scope()!=NULL)
20813 {
20814 // DQ (5/21/2013): We want to restrict access to the symbol table.
20815 if(node->get_scope()->get_symbol_table()!=NULL)
20816 {
20818 if (isSgEnumFieldSymbol(s) == SgEnumFieldSymbolPtr) SgEnumFieldSymbol_count++;
20819 }
20820 }
20821 }
20822 }
20823
20824 void visit(SgVarRefExp* node)
20825 {
20826 if(SgVariableSymbolPtr !=NULL){
20827 SgVariableSymbol* s = node->get_symbol();
20828 if (s == SgVariableSymbolPtr) SgVariableSymbol_count++;
20829 }
20830 }
20831
20832 int get_num_variable_pointers(){return SgVariableSymbol_count;}
20833
20834 int get_num_EnumField_pointers(){return SgEnumFieldSymbol_count;}
20835
20836
20837 // SgFunctionSymbol
20838 void visit(SgFunctionDeclaration* node) {
20839 if(SgFunctionSymbolPtr !=NULL){
20840 if(node->get_scope()!=NULL){
20841 // DQ (5/21/2013): We want to restrict access to the symbol table.
20842 if(node->get_scope()->get_symbol_table()!=NULL)
20843 {
20845 if ((SgFunctionSymbol *)s == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20846 }
20847 }
20848 }
20849#if 0
20850 if(function_decl!=NULL){
20851 if(node->get_symbol_from_symbol_table() == NULL){
20854 if(node!=function_decl && (define==function_decl || first_nondefine==function_decl)) delete node;
20855 }
20856 }
20857#endif
20858 }
20859
20860 void visit(SgFunctionRefExp* node)
20861 {
20862#if 0
20863 printf ("In visit(SgFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20864#endif
20865 if (SgFunctionSymbolPtr !=NULL)
20866 {
20867 SgFunctionSymbol* s = node->get_symbol_i();
20868 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20869 {
20870 SgFunctionSymbol_count++;
20871#if 0
20872 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20873#endif
20874 }
20875 }
20876 }
20877
20878 // DQ (5/2/2013): Added support for SgMemberFunctionRefExp which is not derived from SgFunctionRefExp.
20879 void visit(SgMemberFunctionRefExp* node)
20880 {
20881#if 0
20882 printf ("In visit(SgMemberFunctionRefExp* node): SgFunctionSymbolPtr = %p \n",SgFunctionSymbolPtr);
20883#endif
20884 if (SgFunctionSymbolPtr !=NULL)
20885 {
20886 SgFunctionSymbol* s = node->get_symbol_i();
20887 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr)
20888 {
20889 SgFunctionSymbol_count++;
20890#if 0
20891 printf ("Increment SgFunctionSymbol_count = %d \n",SgFunctionSymbol_count);
20892#endif
20893 }
20894 }
20895 }
20896
20897 void visit(SgUserDefinedBinaryOp* node)
20898 {
20899 if (SgFunctionSymbolPtr !=NULL){
20900 SgFunctionSymbol* s = node->get_symbol();
20901 if (isSgFunctionSymbol(s) == SgFunctionSymbolPtr) SgFunctionSymbol_count++;
20902 }
20903 }
20904
20905 int get_num_Function_pointers(){return SgFunctionSymbol_count;}
20906
20907 // SgClassSymbol
20908 void visit(SgClassDeclaration* node)
20909 {
20910 if(SgClassSymbolPtr !=NULL){
20911 if(node->get_scope()!=NULL){
20912 if(node->get_scope()->get_symbol_table()!=NULL)
20913 {
20915 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20916 }
20917 }
20918 }
20919
20920 if(class_defining!=NULL) {
20921 if(node->get_symbol_from_symbol_table() == NULL){
20924 if((class_decl==class_defining||class_decl1==class_defining) && node!=class_defining )
20925 delete node;
20926 }
20927 }
20928 }
20929
20930 void visit(SgTemplateInstantiationDecl* node)
20931 {
20932 if(SgClassSymbolPtr !=NULL){
20933 if(node->get_scope()!=NULL){
20934 if(node->get_scope()->get_symbol_table()!=NULL)
20935 {
20937 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20938 }
20939 }
20940 }
20941
20942 if(templateInstantiate_defining!=NULL) {
20943 if(node->get_scope()!=NULL){
20944 if(node->get_scope()->get_symbol_table()!=NULL)
20945 {
20946 if(node->get_symbol_from_symbol_table() == NULL){
20949 if((template_decl==templateInstantiate_defining||template_decl1==templateInstantiate_defining) && node!=templateInstantiate_defining){
20950 /*vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
20951 foreach (SgTemplateArgument* element, tempargs){
20952 SgTemplateArgument* temparg = isSgTemplateArgument(element);
20953 if(temparg){
20954 delete temparg;
20955 }
20956 printf("SgTemplateArg in Memory Pool traversal\n");
20957 }*/
20958 delete node;
20959 //printf("SgTemplateInstantiationDecl in Memory Pool traversal\n");
20960 }
20961 }
20962 }
20963 }
20964 }
20965 }
20966
20967 void visit(SgThisExp* node)
20968 {
20969 if (SgClassSymbolPtr !=NULL){
20970 SgSymbol* s = node->get_class_symbol();
20971 if (s == SgClassSymbolPtr) SgClassDeclaration_count++;
20972 }
20973 }
20974
20975 void visit(SgClassNameRefExp* node)
20976 {
20977 if (SgClassSymbolPtr !=NULL){
20978 SgSymbol* s = node->get_symbol();
20979 if (isSgClassSymbol(s) == SgClassSymbolPtr) SgClassDeclaration_count++;
20980 }
20981 }
20982
20983
20984 int get_num_Class_pointers(){return SgClassDeclaration_count;}
20985
20986
20987 // SgMemberFunctionSymbol
20988 void visit(SgCtorInitializerList* node)
20989 {
20990 if(memFunc !=NULL){
20992 if(func == memFunc){
20993 delete node;
20994 }
20995 }
20996 }
20997
20998
20999 void visit(SgMemberFunctionDeclaration* node)
21000 {
21001 if (SgMemFuncSymbolPtr !=NULL){
21002 if(node->get_scope()!=NULL){
21003 if(node->get_scope()->get_symbol_table()!=NULL)
21004 {
21005 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21006 if(symbol == SgMemFuncSymbolPtr){
21007 SgMemFuncSymbol_count++;
21008 }
21009 }
21010 }
21011 }
21012 }
21013
21015 {
21016 if (SgMemFuncSymbolPtr !=NULL){
21017 if(node->get_scope()!=NULL){
21018 if(node->get_scope()->get_symbol_table()!=NULL)
21019 {
21020 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21021 if(symbol == SgMemFuncSymbolPtr){
21022 SgMemFuncSymbol_count++;
21023 }
21024 }
21025 }
21026 }
21027 }
21028
21029
21030
21031 int get_num_memFunc_pointers(){return SgMemFuncSymbol_count;}
21032
21033
21034 // SgTypedefSymbol
21035 void visit(SgTypedefDeclaration* node)
21036 {
21037 if(SgTypedefPtr!=NULL){
21038 if(node->get_scope()!=NULL){
21039 if(node->get_scope()->get_symbol_table()!=NULL)
21040 {
21042 if ((SgTypedefSymbol *)s == SgTypedefPtr) SgTypedefSymbol_count++;
21043 }
21044 }
21045 }
21046 if(typedef_defining!=NULL){
21048 if(typedef_define == typedef_defining && node != typedef_defining ) {
21049 delete node;
21050 }
21051 }
21052 }
21053
21054 int get_num_Typedef_pointers(){return SgTypedefSymbol_count;}
21055
21056
21057
21058 void visit(SgTemplateDeclaration* node)
21059 {
21060 if (SgTemplateSymbolPtr !=NULL){
21061 if(node->get_scope()!=NULL){
21062 if(node->get_scope()->get_symbol_table()!=NULL)
21063 {
21064 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21065 if(symbol == SgTemplateSymbolPtr){
21066 SgTemplateSymbol_count++;
21067 }
21068 }
21069 }
21070 }
21071
21072 if(template_defining !=NULL) {
21073 if(node->get_scope()!=NULL){
21074 if(node->get_scope()->get_symbol_table()!=NULL)
21075 {
21076 if(node->get_symbol_from_symbol_table() == NULL){
21079 if((template_decl==template_defining||template_decl1==template_defining) && node!=template_defining) {
21080 delete node;
21081
21082 }
21083 }
21084 }
21085 }
21086 }
21087 }
21088
21089 int get_num_Template_pointers(){return SgTemplateSymbol_count;}
21090
21091 };
21092
21093
21094 //Tan August,25,2010 //Traverse AST in post order, delete nodes and their symbols if it's safe to do so
21095 class DeleteAST : public SgSimpleProcessing, ROSE_VisitTraversal
21096 {
21097 public:
21098
21099 void visit (SgNode* node)
21100 {
21101 //These nodes are manually deleted because they cannot be visited by the traversal
21103 //remove SgVariableDefinition, SgVariableSymbol and SgEnumFieldSymbol
21105#if 0
21106 printf ("In DeleteAST::visit(): node = %p = %s \n",node,node->class_name().c_str());
21107#endif
21108#if 0
21109 // DQ (3/2/2014): I think this might be a problem...
21110 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
21111 if (isSgScopeStatement(node) !=NULL)
21112 {
21113 SgScopeStatement* scope = isSgScopeStatement(node);
21114#if 1
21115 printf ("Deleting the scopes type table: scope->get_type_table() = %p \n",scope->get_type_table());
21116#endif
21117 delete scope->get_type_table();
21118 }
21119#endif
21120#if 0
21121 // DQ (3/2/2014): I think this might be a problem...
21122 // DQ (3/1/2014): check for a SgScopeStatement and delete the associated local type table.
21123 if (isSgTypeTable(node) !=NULL)
21124 {
21125 SgTypeTable* typeTable = isSgTypeTable(node);
21126#if 1
21127 printf ("Deleting the type table (SgSymbolTable): typeTable->get_type_table() = %p \n",typeTable->get_type_table());
21128#endif
21129 delete typeTable->get_type_table();
21130 }
21131#endif
21132 if(isSgInitializedName(node) !=NULL){
21133 //remove SgVariableDefinition
21134 SgDeclarationStatement* var_def;
21135 var_def = ((SgInitializedName *)node)->get_definition();
21136 if(isSgVariableDefinition(var_def) !=NULL){
21137 delete var_def;
21138 //printf("A SgVariableDefinition was deleted\n");
21139 }
21140
21141
21142 //remove SgVariableSymbol
21143 if(isSgInitializedName(node)->get_scope()!=NULL){
21144 if(isSgInitializedName(node)->get_scope()->get_symbol_table()!=NULL)
21145 {
21146 SgSymbol* symbol = ((SgInitializedName *)node)->get_symbol_from_symbol_table();
21147 if(isSgVariableSymbol(symbol) !=NULL){
21148 ClassicVisitor visitor((SgVariableSymbol*)symbol);
21149 traverseMemoryPoolVisitorPattern(visitor);
21150 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
21151 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
21152 delete symbol;
21153 //printf("A SgVariableSymbol was deleted\n");
21154 }
21155 }
21156
21157 if(isSgEnumFieldSymbol(symbol) !=NULL){
21158 ClassicVisitor visitor((SgEnumFieldSymbol*)symbol);
21159 traverseMemoryPoolVisitorPattern(visitor);
21160 if(visitor.get_num_EnumField_pointers()==1){
21161 ((SgInitializedName*)node)->get_scope()->get_symbol_table()->remove(symbol);
21162 delete symbol;
21163 //printf("A SgEnumFieldSymbol was deleted\n");
21164 }
21165 }
21166
21167 }
21168 }
21169 }
21170
21171 if(isSgVarRefExp(node) !=NULL){
21172 SgVariableSymbol *symbol = ((SgVarRefExp*)node)->get_symbol();
21173 ClassicVisitor visitor(symbol);
21174 traverseMemoryPoolVisitorPattern(visitor);
21175 if(visitor.get_num_variable_pointers()==1){ //only one reference to this symbol => safe to delete
21176 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21177 delete symbol;
21178 //printf("A SgVariableSymbol was deleted\n");
21179 }
21180 }
21181
21182 /*////////////////////////////////////////////////
21183 /remove SgFunctionSymbol
21185
21186 {
21187 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(node);
21188 if (funcDecl != NULL){
21189 if (isSgMemberFunctionDeclaration(node) == NULL) {
21190 if (funcDecl->get_scope() != NULL) {
21191 if (funcDecl->get_scope()->get_symbol_table() != NULL) {
21192 SgSymbol* symbol = ((SgFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21193 ClassicVisitor visitor((SgFunctionSymbol *)symbol);
21194 traverseMemoryPoolVisitorPattern(visitor);
21195 if (visitor.get_num_Function_pointers()==1) { //only one reference to this FunctionSymbol => safe to delete
21196 ((SgFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21197 delete symbol;
21198 //printf("A SgFunctionSymbol was deleted\n");
21199 }
21200 ClassicVisitor visitor1((SgFunctionDeclaration *)node);
21201 traverseMemoryPoolVisitorPattern(visitor1);
21202 }
21203 }
21204 }
21205 }
21206 }
21207
21208 if(isSgFunctionRefExp(node) !=NULL)
21209 {
21210#if 0
21211 SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(node);
21212 ROSE_ASSERT(functionRefExp->get_symbol_i() != NULL);
21213 printf ("In DeleteAST::visit(): functionRefExp->get_symbol_i() = %p = %s \n",functionRefExp->get_symbol_i(),functionRefExp->get_symbol_i()->class_name().c_str());
21214#endif
21215 SgFunctionSymbol *symbol = ((SgFunctionRefExp*)node)->get_symbol_i();
21216 ClassicVisitor visitor(symbol);
21217 traverseMemoryPoolVisitorPattern(visitor);
21218 if(visitor.get_num_Function_pointers()==1)
21219 {
21220 // only one reference to this FunctionSymbol => safe to delete
21221 //((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21222 delete symbol;
21223 //printf("A SgFunctionSymbol was deleted\n");
21224 }
21225
21226 }
21227
21228 if(isSgUserDefinedBinaryOp(node) !=NULL){
21229 SgFunctionSymbol *symbol = ((SgUserDefinedBinaryOp*)node)->get_symbol();
21230 ClassicVisitor visitor(symbol);
21231 traverseMemoryPoolVisitorPattern(visitor);
21232 if(visitor.get_num_Function_pointers()==1){ //only one reference to this FunctionSymbol => safe to delete
21233 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21234 delete symbol;
21235 //printf("A SgFunctionSymbol was deleted\n");
21236 }
21237 }
21238
21239 /*/
21240 /remove SgTypedefSymbol
21242
21243 if(isSgTypedefDeclaration(node) !=NULL){
21244 if(((SgTypedefDeclaration*)node)->get_scope()!=NULL){
21245 if(((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21246 {
21247 SgSymbol* symbol = ((SgTypedefDeclaration*)node)->get_symbol_from_symbol_table();
21248 if(isSgTypedefSymbol(symbol)){
21249 ClassicVisitor visitor((SgTypedefSymbol*) symbol);
21250 traverseMemoryPoolVisitorPattern(visitor);
21251 if(visitor.get_num_Typedef_pointers()==1){ //only one reference to this SgTypedefSymbol => safe to delete
21252 ((SgTypedefDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21253 delete symbol;
21254 //printf("A SgTypedefSymbol was deleted\n");
21255 }
21256 }
21257 }
21258 }
21259
21260 if(node == isSgTypedefDeclaration(node)->get_definingDeclaration()){
21261 ClassicVisitor visitor1((SgTypedefDeclaration*) node);
21262 traverseMemoryPoolVisitorPattern(visitor1);
21263 }
21264 }
21265
21266 /*////////////////////////////////////////////////
21267 /remove SgNamespaceDeclarationSymbol
21269
21270 if(isSgNamespaceDeclarationStatement(node) !=NULL){
21271 if(((SgNamespaceDeclarationStatement*)node)->get_scope()!=NULL){
21272 if(((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21273 {
21274 SgSymbol* symbol = ((SgNamespaceDeclarationStatement*)node)->get_symbol_from_symbol_table();
21275 if(isSgNamespaceSymbol(symbol)){
21276 ((SgNamespaceDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21277 delete symbol;
21278 //printf("A SgNamespaceSymbol was deleted\n");
21279 }
21280 }
21281 }
21282 }
21283
21284
21285 if(isSgNamespaceAliasDeclarationStatement(node) !=NULL){
21286 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()!=NULL){
21287 if(((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21288 {
21289 SgSymbol* symbol = ((SgNamespaceAliasDeclarationStatement*)node)->get_symbol_from_symbol_table();
21290 if(isSgNamespaceSymbol(symbol)){
21291 ((SgNamespaceAliasDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21292 delete symbol;
21293 //printf("A SgNamespaceSymbol was deleted\n");
21294 }
21295 }
21296 }
21297 }
21298
21299
21300 /*/
21301 /remove SgLabelSymbol
21303
21304 if(isSgLabelStatement(node) !=NULL){
21305 if(((SgLabelStatement*)node)->get_scope()!=NULL){
21306 if(((SgLabelStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21307 {
21308 SgSymbol* symbol = ((SgLabelStatement*)node)->get_symbol_from_symbol_table();
21309 if(isSgLabelSymbol(symbol)){
21310 ((SgLabelStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21311 delete symbol;
21312 //printf("A SgLabelSymbol was deleted\n");
21313 }
21314 }
21315 }
21316 }
21317
21318 if(isSgLabelRefExp(node) !=NULL){
21319 SgLabelSymbol* symbol = ((SgLabelRefExp*)node)->get_symbol();
21320 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21321 delete symbol;
21322 //printf("A SgLabelSymbol was deleted\n");
21323 }
21324
21325
21326 /*////////////////////////////////////////////////
21327 /remove SgEnumSymbol
21329
21330 if(isSgEnumDeclaration(node) !=NULL){
21331 if(((SgEnumDeclaration*)node)->get_scope()!=NULL){
21332 if(((SgEnumDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21333 {
21334 SgSymbol* symbol = ((SgEnumDeclaration*)node)->get_symbol_from_symbol_table();
21335 if(isSgEnumSymbol(symbol) !=NULL){
21336 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21337 delete symbol;
21338 //printf("A SgEnumSymbol was deleted\n");
21339 }
21340 }
21341 }
21342 SgEnumType* type= ((SgEnumDeclaration*)node)->get_type();
21343 if(type !=NULL){
21344 delete type;
21345 //printf("A SgEnumType was deleted\n");
21346 }
21347 }
21348
21349
21350 /*/
21351 /remove SgClassSymbol
21353
21354 if(isSgClassDeclaration(node) !=NULL && isSgTemplateInstantiationDecl(node) ==NULL){
21355 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21356 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21357 {
21358 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21359 if(isSgClassSymbol(symbol) !=NULL){
21360 ClassicVisitor visitor((SgClassSymbol*)symbol);
21361 traverseMemoryPoolVisitorPattern(visitor);
21362 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21363 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21364 delete symbol;
21365 //printf("A SgClassSymbol was deleted\n");
21366 }
21367 }
21368 }
21369 }
21370
21371 ClassicVisitor visitor((SgClassDeclaration*) node );
21372 traverseMemoryPoolVisitorPattern(visitor);
21373
21374 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21375 if(type !=NULL){
21376 delete type;
21377 //printf("A SgClassType was deleted\n");
21378 }
21379 }
21380
21381 if(isSgThisExp(node) !=NULL){
21382 SgSymbol* symbol = ((SgThisExp*)node)->get_class_symbol();
21383 ClassicVisitor visitor((SgClassSymbol*)symbol);
21384 traverseMemoryPoolVisitorPattern(visitor);
21385 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21386 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21387 delete symbol;
21388 //printf("A SgClassSymbol was deleted\n");
21389 }
21390
21391 }
21392
21393 if(isSgClassNameRefExp(node) !=NULL){
21394 SgSymbol* symbol = ((SgClassNameRefExp*)node)->get_symbol();
21395 if(isSgClassSymbol(symbol) !=NULL)
21396 {
21397 ClassicVisitor visitor((SgClassSymbol*)symbol);
21398 traverseMemoryPoolVisitorPattern(visitor);
21399 if(visitor.get_num_Class_pointers()==1){ //only one reference to this symbol => safe to delete
21400 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21401 delete symbol;
21402 //printf("A SgClassSymbol was deleted\n");
21403 }
21404 }
21405 }
21406
21407 /*////////////////////////////////////////////////
21408 /remove SgMemberFunctionSymbol
21410
21411
21412 if(isSgMemberFunctionDeclaration(node) !=NULL){
21413 if(((SgMemberFunctionDeclaration*)node)->get_scope()!=NULL){
21414 if(((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21415 {
21416 SgSymbol* symbol = ((SgMemberFunctionDeclaration*)node)->get_symbol_from_symbol_table();
21417 if(isSgMemberFunctionSymbol(symbol)){
21418 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21419 traverseMemoryPoolVisitorPattern(visitor);
21420 if(visitor.get_num_memFunc_pointers()==1){
21421 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21422 delete symbol;
21423 //printf("A SgMemberFunctionSymbol was deleted\n");
21424 }
21425 }
21426 }
21427 }
21428 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21429 traverseMemoryPoolVisitorPattern(visitor);
21430
21431 }
21432//Tan: I have no idea why the codes below cannot work. Perhaps it conflicts with some prior works
21433#if 0
21434 if(isSgMemberFunctionRefExp(node) !=NULL){
21435 SgMemberFunctionSymbol* symbol = ((SgMemberFunctionRefExp*)node)->get_symbol_i();
21436 ClassicVisitor visitor(symbol);
21437 traverseMemoryPoolVisitorPattern(visitor);
21438 if(visitor.get_num_memFunc_pointers()==1){ //only one reference to this symbol => safe to delete
21439 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21440 delete symbol;
21441 //printf("A SgClassSymbol was deleted\n");
21442 }
21443
21444 }
21445
21446 if(isSgFunctionType(node) !=NULL){
21447 SgSymbol* symbol = ((SgFunctionType*)node)->get_symbol_from_symbol_table();
21448 if(isSgFunctionTypeSymbol(symbol)){
21449 ((SgSymbol*)symbol)->get_scope()->get_symbol_table()->remove(symbol);
21450 delete symbol;
21451 //printf("A SgFunctionTypeSymbol was deleted\n");
21452 }
21453 }
21454#endif
21455
21456 /*/
21459
21460 if(isSgInterfaceStatement(node) !=NULL){
21461 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21462 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21463 {
21464 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21465 if(isSgInterfaceSymbol(symbol)){
21466 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21467 delete symbol;
21468 //printf("A SgInterfaceSymbol was deleted\n");
21469 }
21470 }
21471 }
21472
21473 }
21474
21475
21476 if(isSgModuleStatement(node) !=NULL){
21477 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21478 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21479 {
21480 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21481 if(isSgModuleSymbol(symbol)){
21482 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21483 delete symbol;
21484 //printf("A SgModuleSymbol was deleted\n");
21485 }
21486 }
21487 }
21488
21489 }
21490
21491
21492//Tan: I got stuck in deleting the SgTemplateArgument
21493#if 0
21494 if(isSgTemplateInstantiationMemberFunctionDecl(node) !=NULL){
21495 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()!=NULL){
21496 if(((SgTemplateInstantiationMemberFunctionDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21497 {
21498 SgSymbol* symbol = ((SgTemplateInstantiationMemberFunctionDecl*)node)->get_symbol_from_symbol_table();
21499 if(isSgMemberFunctionSymbol(symbol)){
21500 ClassicVisitor visitor((SgMemberFunctionSymbol*)symbol);
21501 traverseMemoryPoolVisitorPattern(visitor);
21502 if(visitor.get_num_memFunc_pointers()==1){
21503 ((SgMemberFunctionDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21504 delete symbol;
21505 //printf("A SgMemberFunctionSymbol was deleted\n");
21506 }
21507 }
21508 }
21509 }
21510 ClassicVisitor visitor((SgMemberFunctionDeclaration*) node);
21511 traverseMemoryPoolVisitorPattern(visitor);
21512 }
21513
21514 if(isSgTemplateDeclaration(node) !=NULL){
21515 if(((SgTemplateDeclaration*)node)->get_scope()!=NULL){
21516 if(((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21517 {
21518 SgSymbol* symbol = ((SgTemplateDeclaration*)node)->get_symbol_from_symbol_table();
21519 ClassicVisitor visitor((SgTemplateSymbol*)symbol);
21520 traverseMemoryPoolVisitorPattern(visitor);
21521 if(visitor.get_num_Template_pointers()==1){
21522 ((SgTemplateDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21523 delete symbol;
21524 printf("A SgTemplateSymbol was deleted\n");
21525 }
21526 }
21527 }
21528 //if(isSgTemplateDeclaration(node) == ((SgTemplateDeclaration*)node)->get_firstNondefiningDeclaration()){
21529 ClassicVisitor visitor1((SgTemplateDeclaration*) node );
21530 traverseMemoryPoolVisitorPattern(visitor1);
21531 //}
21532
21533 }
21534
21535 if(isSgInterfaceStatement(node) !=NULL){
21536 if(((SgDeclarationStatement*)node)->get_scope()!=NULL){
21537 if(((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()!=NULL)
21538 {
21539 SgSymbol* symbol = ((SgDeclarationStatement*)node)->get_symbol_from_symbol_table();
21540 if(isSgInterfaceSymbol(symbol)){
21541 ((SgDeclarationStatement*)node)->get_scope()->get_symbol_table()->remove(symbol);
21542 delete symbol;
21543 //printf("A SgInterfaceSymbol was deleted\n");
21544 }
21545 }
21546 }
21547
21548 }
21549
21550
21551 if(isSgModuleStatement(node) !=NULL){
21552 if(((SgClassDeclaration*)node)->get_scope()!=NULL){
21553 if(((SgClassDeclaration*)node)->get_scope()->get_symbol_table()!=NULL)
21554 {
21555 SgSymbol* symbol = ((SgClassDeclaration*)node)->get_symbol_from_symbol_table();
21556 if(isSgModuleSymbol(symbol)){
21557 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21558 delete symbol;
21559 //printf("A SgModuleSymbol was deleted\n");
21560 }
21561 }
21562 }
21563
21564 }
21565
21566 if(isSgTemplateInstantiationDecl(node) !=NULL){
21567 if(((SgTemplateInstantiationDecl*)node)->get_scope()!=NULL){
21568 if(((SgTemplateInstantiationDecl*)node)->get_scope()->get_symbol_table()!=NULL)
21569 {
21570 SgSymbol* symbol = ((SgTemplateInstantiationDecl*)node)->get_symbol_from_symbol_table();
21571 if(isSgClassSymbol(symbol)){
21572 ClassicVisitor visitor((SgClassSymbol*)symbol);
21573 traverseMemoryPoolVisitorPattern(visitor);
21574 if(visitor.get_num_Class_pointers()==1){
21575 ((SgClassDeclaration*)node)->get_scope()->get_symbol_table()->remove(symbol);
21576 delete symbol;
21577 }
21578 }
21579 }
21580 }
21581 SgClassType* type= ((SgClassDeclaration*)node)->get_type();
21582 if(type !=NULL){
21583 delete type;
21584 //printf("A SgClassType was deleted\n");
21585 }
21586
21587 vector<SgTemplateArgument*> tempargs= ((SgTemplateInstantiationDecl*)node)->get_templateArguments();
21588 foreach (SgTemplateArgument* element, tempargs){
21589 SgTemplateArgument* temparg = isSgTemplateArgument(element);
21590 if(temparg){
21591 delete temparg;
21592 }
21593 printf("SgTemplateArg in normal traversal\n");
21594 }
21595 printf("SgTemplateInstantiationDecl in normal traversal\n");
21596
21597 ClassicVisitor visitor((SgTemplateInstantiationDecl*) node);
21598 traverseMemoryPoolVisitorPattern(visitor);
21599 }
21600
21601#endif
21602#if 0
21603 printf ("Deleting node = %p = %s = %s \n",node,node->class_name().c_str(),SageInterface::get_name(node).c_str());
21604#endif
21605 // Normal nodes will be removed in a post-order way
21606 delete node;
21607#if 0
21608 printf ("After delete node: node = %p = %s \n",node,node->class_name().c_str());
21609#endif
21610 }
21611 };
21612
21613
21614 DeleteAST deleteTree;
21615
21616 // Deletion must happen in post-order to avoid traversal of (visiting) deleted IR nodes
21617 deleteTree.traverse(n,postorder);
21618
21619#if 0
21620 printf ("Leaving SageInterface::deleteAST(): n = %p = %s \n",n,n->class_name().c_str());
21621#endif
21622 }
21623
21624
21625
21626
21627#ifndef USE_ROSE
21628// DQ (9/25/2011): The deleteAST() function will not remove original expression trees behind constant folded expressions.
21629// These exist in the AST within the internal construction of the AST until they are simplified in the AST post-processing.
21630// In the post-processing either:
21631// 1) the constant folded values are kept and the original expression trees deleted (optional, controled by default parameter to function "frontend()", OR
21632// 2) the constant folded values are replaced by the original expression trees, and the constant folded values are deleted (default).
21633// Either way, after the AST post-processing the AST is simplified. Until then the expression trees can contain constant
21634// folded values and the values will have a pointer to the original expression tree. Before (9/16/2011) the original
21635// tree would also sometimes (not uniformally) be traversed as part of the AST. This was confusing (to people and
21636// to numerous forms of analysis), so this is being fixed to be uniform (using either of the methods defined above).
21637// However, the fact that until post-processing the AST has this complexity, and that the AST traversal does not
21638// traverse the original expression trees (now uniform); means that we need a special delete function for subtrees
21639// that are not use post-processed. This is the special purpose function that we need.
21640//
21641// NOTE: This function is called from the SgArrayType::createType() member function and in the constant folding AST post-processing.
21642//
21644 {
21645 struct Visitor: public AstSimpleProcessing
21646 {
21647 virtual void visit(SgNode* n)
21648 {
21649 SgExpression* expression = isSgExpression(n);
21650 if (expression != NULL)
21651 {
21652 Visitor().traverse(expression->get_originalExpressionTree(), postorder);
21653 }
21654
21655 delete (n);
21656 }
21657 };
21658
21659 Visitor().traverse(root, postorder);
21660 }
21661#endif
21662 // move symbol table from one scope to another
21663static void moveSymbolTableBetweenBlocks(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, std::vector <SgInitializedName*>& initname_vec)
21664{
21665 // Move the symbol table
21666 SgSymbolTable* s_table = sourceBlock->get_symbol_table();
21667 ASSERT_not_null(sourceBlock->get_symbol_table());
21668 // Liao, 11/26/2019 make sure the symbol table has symbols for init names before and after the move
21669 for (SgInitializedName* iname : initname_vec)
21670 {
21671 SgSymbol* symbol = s_table->find(iname);
21672 ASSERT_not_null(symbol);
21673 }
21674 // entirely move source block's symbol table to target block
21675 targetBlock->set_symbol_table(sourceBlock->get_symbol_table());
21676
21677 ASSERT_not_null(sourceBlock);
21678 ASSERT_not_null(targetBlock);
21679 ASSERT_not_null(targetBlock->get_symbol_table());
21680 ASSERT_not_null(sourceBlock->get_symbol_table());
21681 targetBlock->get_symbol_table()->set_parent(targetBlock);
21682
21683 ASSERT_not_null(sourceBlock->get_symbol_table());
21684 sourceBlock->set_symbol_table(nullptr);
21685
21686 // Reset with a valid symbol table
21687 sourceBlock->set_symbol_table(new SgSymbolTable());
21688 sourceBlock->get_symbol_table()->set_parent(sourceBlock);
21689
21690 ASSERT_require(targetBlock->get_symbol_table() == s_table);
21691 for (SgInitializedName* iname : initname_vec)
21692 {
21693 SgSymbol* symbol = s_table->find(iname);
21694 ASSERT_not_null(symbol);
21695 }
21696
21697 // Liao, 11/26/2019 make sure init names have symbols after the move.
21698 for (SgInitializedName* iname : initname_vec)
21699 {
21700 SgSymbol* symbol = iname->get_symbol_from_symbol_table();
21701 ASSERT_not_null(symbol);
21702 }
21703}
21704
21705// helper function to move a single statement or declaration from a block to another
21706static void moveOneStatement(SgScopeStatement* sourceBlock, SgScopeStatement* targetBlock, SgStatement* stmt, std::vector <SgInitializedName*>& initname_vec)
21707{
21708 // append statement to the target block
21709 targetBlock->append_statement(stmt);
21710
21711 // Make sure that the parents are set.
21712 ASSERT_require(stmt->get_parent() == targetBlock);
21713 if (stmt->hasExplicitScope())
21714 {
21715 if (stmt->get_scope() != targetBlock)
21716 {
21717 if (SgFunctionDeclaration* func = isSgFunctionDeclaration(stmt))
21718 {
21719 // why only move if it is a first nondefining declaration?
21720 // We have a case to move both defining and nondefining function declarations of Ada package body to namespace definition.
21721 // comment out the if condition for now. 1/20/2021
21722 //
21723 // A call to a undeclared function will introduce a hidden func prototype declaration in the enclosing scope .
21724 // The func declaration should be moved along with the call site.
21725 // The scope should be set to the new block also
21726 // Liao 1/14/2011
21727 func->set_scope(targetBlock);
21728 // This is needed to move functions in Ada package body into C++ namespace
21729 // We may have compiler generated first nondefining declaration. We need to move its scope also
21730 SgFunctionDeclaration* nondef_decl= isSgFunctionDeclaration(func->get_firstNondefiningDeclaration());
21731 if (func != nondef_decl)
21732 {
21733 ASSERT_not_null(nondef_decl);
21734 ASSERT_not_null(nondef_decl->get_file_info());
21735 if (nondef_decl->get_file_info()->isCompilerGenerated()) {
21736 nondef_decl->set_scope(targetBlock);
21737 }
21738 }
21739 }
21740 else if (auto labelStmt = isSgLabelStatement(stmt))
21741 {
21742 if (labelStmt->get_scope() == sourceBlock) {
21743 labelStmt->set_scope(targetBlock);
21744 // Make sure the labelStmt is in the enclosing function scope of targetBlock
21745 SageInterface::fixLabelStatement(labelStmt, targetBlock);
21746 }
21747 }
21748 else if (isSgJovialTableStatement(stmt) || isSgTypedefDeclaration(stmt) || isSgEnumDeclaration(stmt))
21749 {
21750 // Rasmussen 9/21/2020,10/27/2020,11/4/2020: Uncovered by issues RC-135 and RC-227.
21751 // The issues are fixed in the switch statement below but this test is needed
21752 // so that the warning message immediately below is not triggered.
21753 }
21754 else
21755 {
21756 mlog[Rose::Diagnostics::WARN] << "test failing stmt->get_scope() == targetBlock in SageInterface::moveStatementsBetweenBlocks(): class: "
21757 << stmt->class_name() << "\n";
21758 }
21759 }
21760 }
21761
21762 SgDeclarationStatement* declaration = isSgDeclarationStatement(stmt);
21763 if (declaration != nullptr)
21764 {
21765 // Need to reset the scope from sourceBlock to targetBlock.
21766 switch(declaration->variantT())
21767 {
21768 // There will be other cases to handle, but likely not all declaration will be possible to support.
21769
21770 case V_SgVariableDeclaration:
21771 {
21772 // Reset the scopes on any SgInitializedName objects.
21773 SgVariableDeclaration* varDecl = isSgVariableDeclaration(declaration);
21774 SgInitializedNamePtrList & l = varDecl->get_variables();
21775 for (SgInitializedNamePtrList::iterator ii = l.begin(); ii != l.end(); ii++)
21776 {
21777 // reset the scope, but make sure it was set to sourceBlock to make sure.
21778 // This might be an issue for extern variable declaration that have a scope
21779 // in a separate namespace of a static class member defined external to
21780 // its class, etc. I don't want to worry about those cases right now.
21781
21782 SgInitializedName * init_name = (*ii);
21783
21784 // Rasmussen (3/16/2021): Use the base type in case type is modified (i.e., const)
21785 SgType* var_type = init_name->get_type();
21786 if (SgModifierType* mod_type = isSgModifierType(var_type))
21787 {
21788 var_type = mod_type->get_base_type();
21789 }
21790
21791 // Rasmussen (6/29/2020) and (10/19/2020): Variable declarations related to anonymous types are not
21792 // moved. This is fixed below. Note that SgJovialTableType derives from SgClassType, it may
21793 // be that class types are not moved correctly either.
21794 //
21795 if (isSgEnumType(var_type))
21796 {
21797 SgEnumType* enum_type = isSgEnumType(var_type);
21798 SgEnumDeclaration* decl = isSgEnumDeclaration(enum_type->get_declaration());
21799 SgEnumDeclaration* def_decl = isSgEnumDeclaration(decl->get_definingDeclaration());
21800 SgEnumDeclaration* nondef_decl = isSgEnumDeclaration(decl->get_firstNondefiningDeclaration());
21801
21802 if (decl->get_scope() == sourceBlock)
21803 {
21804 // Needs to be moved
21805 def_decl->set_scope(targetBlock);
21806 nondef_decl->set_scope(targetBlock);
21807 nondef_decl->set_parent(targetBlock);
21808
21809 // Move the scope of the enumerators to the new block as well
21810 for (SgInitializedName* enumerator : def_decl->get_enumerators())
21811 {
21812 enumerator->set_scope(targetBlock);
21813 }
21814 }
21815 }
21816 else if (isSgJovialTableType(var_type))
21817 {
21818 SgJovialTableType* table_type = isSgJovialTableType(var_type);
21819 SgDeclarationStatement* decl = table_type->get_declaration();
21820 if (decl->get_scope() == sourceBlock)
21821 {
21822 // Needs to be moved
21825 def_decl->set_scope(targetBlock);
21826 nondef_decl->set_scope(targetBlock);
21827 nondef_decl->set_parent(targetBlock);
21828 }
21829 }
21830
21831 // Must also move the symbol into the source block, Liao 2019/8/14
21832 SgVariableSymbol* var_sym = isSgVariableSymbol(init_name -> search_for_symbol_from_symbol_table ()) ;
21833 ASSERT_not_null(var_sym);
21834 SgScopeStatement * old_scope = var_sym -> get_scope();
21835#if 1 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21836 if (old_scope != sourceBlock)
21837 {
21838 old_scope->remove_symbol (var_sym);
21839 sourceBlock ->insert_symbol(init_name->get_name(), var_sym);
21840 }
21841#endif
21842 init_name->set_scope(targetBlock);
21843 initname_vec.push_back(init_name);
21844 }
21845 break;
21846 }
21847 case V_SgFunctionDeclaration: // Liao 1/15/2009, I don't think there is any extra things to do here
21848 {
21849 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(declaration);
21850 ASSERT_not_null(funcDecl);
21851#if 0 // we will later move entire source symbol table to target scope, so we move symbol to the sourceBlock first here.
21852 // move function symbols also: search_for_symbol_from_symbol_table()
21854 if (func_sym)
21855 {
21856 SgScopeStatement * old_scope = func_sym -> get_scope();
21857 if (old_scope != sourceBlock)
21858 {
21859 old_scope->remove_symbol (func_sym);
21860 sourceBlock ->insert_symbol(func_sym->get_name(), func_sym);
21861 }
21862 }
21863#endif
21864 break;
21865 }
21866 // needed to move Ada record into definition of C++ namespace
21867 case V_SgProgramHeaderStatement:
21868 case V_SgProcedureHeaderStatement:
21869 case V_SgClassDeclaration:
21870 case V_SgEnumDeclaration:
21871 {
21872 SgDeclarationStatement* nondef_decl = declaration->get_firstNondefiningDeclaration();
21873 ASSERT_not_null(nondef_decl);
21874
21875 nondef_decl->set_parent(targetBlock);
21876 nondef_decl->set_scope(targetBlock);
21877
21878 SgDeclarationStatement* def_decl = declaration->get_definingDeclaration();
21879 if (def_decl)
21880 {
21881 def_decl->set_parent(targetBlock);
21882 def_decl->set_scope(targetBlock);
21883 }
21884 else
21885 {
21886 // Set the scope of the function arguments
21887 if (auto proc = isSgProcedureHeaderStatement(nondef_decl)) {
21888 for (auto arg : proc->get_parameterList()->get_args()) {
21889 if (arg->get_scope() != proc->get_scope()) {
21890 // Note: arg (is an SgInitializedName) from the parameter list does not have
21891 // a symbol in the scope of the procedure declaration (proc). Should add
21892 // arg to initname_vec, which will check for missing symbols [GL-387, Rasmussen 7/22/2024].
21893 arg->set_scope(proc->get_scope());
21894 }
21895 }
21896 }
21897 }
21898
21899 SgEnumDeclaration* enum_decl = isSgEnumDeclaration(stmt);
21900 if (enum_decl)
21901 {
21902 // Set the scope of the enumerators [Rasmussen 12/23/2020]
21903 for (SgInitializedName* name : enum_decl->get_enumerators())
21904 {
21905 name->set_scope(targetBlock);
21906 }
21907 }
21908 break;
21909 }
21910 case V_SgJovialTableStatement:
21911 {
21912 // [RC-135, Rasmussen 9/21/2020]
21913 SgJovialTableStatement* table = isSgJovialTableStatement(declaration);
21914 ROSE_ASSERT (table);
21915
21918 nondef_decl->set_parent(targetBlock);
21919 nondef_decl->set_scope(targetBlock);
21920 def_decl->set_scope(targetBlock);
21921 break;
21922 }
21923 case V_SgTypedefDeclaration:
21924 {
21925 // [RC-227, Rasmussen 10/19/2020]
21926 SgTypedefDeclaration* typedef_decl = isSgTypedefDeclaration(declaration);
21927 ASSERT_not_null(typedef_decl);
21928 typedef_decl->set_parent(targetBlock);
21929 typedef_decl->set_scope(targetBlock);
21930 break;
21931 }
21932 case V_SgAttributeSpecificationStatement:
21933 case V_SgEmptyDeclaration:
21934 case V_SgFortranIncludeLine:
21935 case V_SgImplicitStatement: // Rasmussen 5/13/2021: TODO: implicit statement with letter-list
21936 case V_SgJovialDefineDeclaration:
21937 case V_SgJovialDirectiveStatement:
21938 case V_SgJovialLabelDeclaration:
21939 case V_SgJovialOverlayDeclaration:
21940 case V_SgPragmaDeclaration:
21941 case V_SgAdaAttributeClause:
21942 break;
21943 default:
21944 {
21945 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());
21946 declaration->get_file_info()->display("file info");
21947 ROSE_ABORT();
21948 }
21949 }
21950 } // end if
21951}
21952
21953// different handling for scopes with declarations only
21954template <class T1, class T2>
21955void moveDeclarationsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21956{
21957 // This function moves statements from one block to another (used by the outliner).
21958 // printf ("***** Moving statements from sourceBlock %p to targetBlock %p ***** \n",sourceBlock,targetBlock);
21959 ROSE_ASSERT (sourceBlock && targetBlock);
21960 ROSE_ASSERT (sourceBlock->containsOnlyDeclarations() && targetBlock->containsOnlyDeclarations());
21961 if ((void*)sourceBlock == (void*)targetBlock)
21962 {
21963 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
21964 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
21965 return;
21966 }
21967
21968 SgDeclarationStatementPtrList& srcStmts = sourceBlock->get_declarations ();
21969 std::vector <SgInitializedName*> initname_vec;
21970
21971 for (auto stmt : srcStmts)
21972 {
21973 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
21974 }
21975
21976 // Remove the statements in the sourceBlock
21977 srcStmts.clear();
21978 ROSE_ASSERT(srcStmts.empty() == true);
21979 ROSE_ASSERT(sourceBlock->get_declarations().empty() == true);
21980
21981 // move symbol table from one scope to another
21982 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
21983
21984 // Liao 2/4/2009
21985 // Finally , move preprocessing information attached inside the source block to the target block
21986 // Outliner uses this function to move a code block to the outlined function.
21987 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
21988 // to the target block to match #if (which is attached
21989 // before some statement moved to the target block)
21990 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
21991}
21992
21993
21994// source and destination class, both are derived classes of scope statement but with support of get_statements()
21995template <class T1, class T2>
21996void moveStatementsBetweenScopes( T1* sourceBlock, T2* targetBlock)
21997{
21998 // This function moves statements from one block to another (used by the outliner).
21999 ROSE_ASSERT (sourceBlock && targetBlock);
22000 if ((void*)sourceBlock == (void*)targetBlock)
22001 {
22002 cerr<<"warning: SageInterface::moveStatementsBetweenScopes() is skipped, "<<endl;
22003 cerr<<" since program is trying to move statements from and to the identical scoped block. "<<endl;
22004 return;
22005 }
22006
22007 SgStatementPtrList & srcStmts = sourceBlock->get_statements();
22008 std::vector <SgInitializedName*> initname_vec;
22009
22010 for (SgStatement* stmt : srcStmts)
22011 {
22012 moveOneStatement(sourceBlock, targetBlock, stmt, initname_vec);
22013 }
22014
22015 // Remove the statements in the sourceBlock
22016 srcStmts.clear();
22017 ROSE_ASSERT(srcStmts.empty() == true);
22018 ROSE_ASSERT(sourceBlock->get_statements().empty() == true);
22019
22020 // move symbol table from one scope to another
22021 moveSymbolTableBetweenBlocks(sourceBlock, targetBlock, initname_vec);
22022
22023 // Liao 2/4/2009
22024 // Finally , move preprocessing information attached inside the source block to the target block
22025 // Outliner uses this function to move a code block to the outlined function.
22026 // This will ensure that a trailing #endif (which is attached inside the source block) will be moved
22027 // to the target block to match #if (which is attached
22028 // before some statement moved to the target block)
22029 SageInterface::moveUpPreprocessingInfo (targetBlock, sourceBlock, PreprocessingInfo::inside);
22030
22031}
22032
22033static void createAliasSymbols (SgNamespaceDeclarationStatement* decl)
22034{
22035 ASSERT_not_null(decl);
22037 SgNamespaceDefinitionStatement* global_def = local_def->get_global_definition();
22038
22039 ASSERT_require(local_def && global_def && (local_def!=global_def));
22040
22041 for (auto symbol : local_def->get_symbol_table()->get_symbols())
22042 {
22043 SgSymbol *orig_sym = isSgSymbol(symbol);
22044 ASSERT_not_null(orig_sym);
22045 SgAliasSymbol* asym = new SgAliasSymbol (orig_sym);
22046 global_def->get_symbol_table()->insert (asym->get_name(), asym);
22047 }
22048}
22049
22050//TODO: now with more types, we need to use template functions
22052{
22053 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
22054 //create alias symbols in its global definition
22055 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
22056}
22057
22059{
22060 moveStatementsBetweenScopes(sourceBlock, targetBlock);
22061 //create alias symbols in its global definition
22062 createAliasSymbols(isSgNamespaceDeclarationStatement(targetBlock->get_parent()));
22063}
22064
22066{
22067 moveDeclarationsBetweenScopes(sourceBlock, targetBlock);
22068}
22069
22070void
22072{
22073 moveStatementsBetweenScopes (sourceBlock, targetBlock);
22074}
22075
22077// TODO, expose to SageInterface namespace
22079{
22080 bool rt = false;
22081 ROSE_ASSERT (func != NULL);
22082 SgNode* p = func->get_parent();
22083 ROSE_ASSERT (p != NULL);
22084 SgLambdaExp* le = isSgLambdaExp (p);
22085 if (le && le->get_lambda_function() == func)
22086 rt = true;
22087 return rt;
22088}
22089
22090// check if a variable reference is this->a[i] inside of a lambda function
22091// SgArrowExp <SgThisExp, SgVarRefExp>, both are compiler generated nodes
22092// class symbol of ThisExp 's declaration is AutonomousDeclaration SgClassDeclaration
22093// its parent is SgLambdaExp, and lambda_closure_class points back to this class declaration
22095{
22096 bool rt = false;
22097#ifdef _MSC_VER
22098 #pragma message ("WARNING: MSVC does not handle isLambdaCapturedVariable() properly.")
22099#else
22100 ROSE_ASSERT (varRef!= NULL);
22101 SgNode* parent = varRef->get_parent();
22102 if (SgArrowExp *p = isSgArrowExp(parent))
22103 {
22104 SgThisExp* te = isSgThisExp(p->get_lhs_operand_i());
22105 if (te != NULL)
22106 {
22107 SgClassSymbol* csym = te->get_class_symbol();
22108 ROSE_ASSERT (csym!= NULL);
22109 SgClassDeclaration* xdecl = isSgClassDeclaration(csym->get_declaration());
22110 // each this exp should have a class decl
22111 ROSE_ASSERT (xdecl != NULL);
22112 SgLambdaExp* le = isSgLambdaExp(xdecl->get_parent());
22113 if (le != NULL)
22114 {
22115 if (le->get_lambda_closure_class() == xdecl ) // the class is a lambda closure class
22116 rt = true;
22117 }
22118 }
22119 }
22120#endif
22121 return rt;
22122}
22123
22126//TODO consult AstInterface::IsVarRef() for more cases
22128{
22129 SgInitializedName* name = NULL;
22130 SgExpression* nameExp = NULL;
22131 ROSE_ASSERT(current != NULL);
22132
22133 if (isSgInitializedName(current))
22134 {
22135 name = isSgInitializedName(current);
22136 }
22137 else if (isSgPntrArrRefExp(current) != NULL)
22138 {
22139 bool suc=false;
22140 SgExpression* exp = isSgExpression(current);
22141 ROSE_ASSERT(exp != NULL);
22142 suc = SageInterface::isArrayReference(exp,&nameExp);
22143 ROSE_ASSERT(suc == true);
22144 // has to resolve this recursively
22145 return convertRefToInitializedName(nameExp, coarseGrain);
22146 }
22147 else if (isSgVarRefExp(current) != NULL)
22148 {
22149 if (coarseGrain)
22150 {
22151 // Outliner needs coarse grain mem objects to work. Always returning fine grain objects will cause problems.
22152 SgNode* parent = current->get_parent();
22153 if (isSgDotExp(parent))
22154 {
22155 if (isSgDotExp(parent)->get_rhs_operand() == current)
22156 return convertRefToInitializedName(parent, coarseGrain);
22157 }
22158 // avoid backtracking to parent if this is part of lambda function
22159 else if(isSgArrowExp(parent) && ! isLambdaCapturedVariable ( isSgVarRefExp(current) ) )
22160 {
22161 if (isSgArrowExp(parent)->get_rhs_operand() == current)
22162 return convertRefToInitializedName(parent, coarseGrain);
22163 }
22164 }
22165 name = isSgVarRefExp(current)->get_symbol()->get_declaration();
22166 }
22167 else if (isSgFunctionRefExp(current) != NULL ||
22168 isSgTemplateFunctionRefExp(current) != NULL ||
22169 isSgMemberFunctionRefExp(current) != NULL ||
22170 isSgTemplateMemberFunctionRefExp(current) != NULL)
22171 {
22172 //If a function is here it's probably related to a function pointer, it can't be converted to an SgInitailizedName
22173 return NULL;
22174 }
22175 else if (isSgNonrealRefExp(current) != NULL)
22176 {
22177 //SgNonrealRefExp is not a reasonable thing to convert to an SgInitializedName (I think) -Jim Leek
22178 return NULL;
22179 }
22180 else if (isSgDotExp(current))
22181 {
22182 SgExpression* child = NULL;
22183 if (coarseGrain)
22184 child= isSgDotExp(current)->get_lhs_operand();
22185 else
22186 child= isSgDotExp(current)->get_rhs_operand();
22187 ROSE_ASSERT(child);
22188 // has to resolve this recursively
22189 return convertRefToInitializedName(child, coarseGrain);
22190 }
22191 else if (isSgArrowExp(current))
22192 {
22193 SgExpression* child = NULL;
22194 if (coarseGrain)
22195 {
22196 SgExpression* lhs = isSgArrowExp(current)->get_lhs_operand();
22197 ROSE_ASSERT(lhs);
22198 // Liao 9/12/2016, special handling for variables inside of C++11 lambda functions
22199 // They capture variables outside of the lambda function.
22200 // They are represented as a class variable of an anonymous class, this->a[i]
22201 // So, we have to recognize this pattern, and pass the rhs variable to obtain initialized name.
22202 // has to resolve this recursively
22204
22205 if (isLambdaFunction (efunc) )
22206 child= isSgArrowExp(current)->get_rhs_operand();
22207 else
22208 child = lhs;
22209 }
22210 else
22211 child = isSgArrowExp(current)->get_rhs_operand();
22212 ROSE_ASSERT(child);
22213 // has to resolve this recursively
22214
22215 return convertRefToInitializedName(child, coarseGrain);
22216 } // The following expression types are usually introduced by left hand operands of DotExp, ArrowExp
22217 else if (isSgThisExp(current))
22218 {
22219 //SgThisExp* texp = isSgThisExp(current);
22220 name = NULL; // inside a class, there is no initialized name at all!! what to do??
22221 }
22222 else if (isSgPointerDerefExp(current))
22223 {
22224 return convertRefToInitializedName(isSgPointerDerefExp(current)->get_operand(), coarseGrain);
22225 }
22226 else if(isSgUnaryOp(current)) { //Written for SgAddressOfOp, but seems generally aplicable to all Unary Ops (replace above?) -JL
22227 return convertRefToInitializedName(isSgUnaryOp(current)->get_operand(), coarseGrain);
22228 }
22229 else if (isSgCastExp(current))
22230 {
22231 return convertRefToInitializedName(isSgCastExp(current)->get_operand(), coarseGrain);
22232 }
22233 // Scientific applications often use *(address + offset) to access array elements
22234 // If a pointer dereferencing is applied to AddOp, we assume the left operand is the variable of our interests
22235 else if (isSgAddOp(current))
22236 {
22237 SgExpression* lhs = isSgAddOp(current)->get_lhs_operand();
22238 return convertRefToInitializedName(lhs, coarseGrain);
22239 }
22240 else if (isSgSubtractOp(current))
22241 {
22242 SgExpression* lhs = isSgSubtractOp(current)->get_lhs_operand();
22243 return convertRefToInitializedName(lhs, coarseGrain);
22244 }
22245 // operator->() may be called upon a class object.
22246 // e.g. we need to get the function: it a SgDotExp node, (lhs is the class object, rhs is its member function)
22247 else if (SgFunctionCallExp * func_call = isSgFunctionCallExp(current))
22248 {
22249 return convertRefToInitializedName(func_call->get_function(), coarseGrain);
22250 }
22251 else if (isSgIntVal(current))
22252 {
22253 //It is very rare, but sometimes a constant is treated as a
22254 //variable. In which case we don't need an SgInitializdName
22255 return NULL;
22256 }
22257
22258 else
22259 {
22260 // side effect analysis will return rhs of Class A a = A(); as a read ref exp. SgConstructorInitializer
22261 if (!isSgConstructorInitializer(current))
22262 {
22263 mlog[Sawyer::Message::Common::WARN] <<
22264 "convertRefToInitializedName: " <<
22265 current->get_file_info()->get_filename() << ":" <<
22266 current->get_file_info()->get_line() << "-" << current->get_file_info()->get_col()<<endl;
22267 cerr<<"In SageInterface::convertRefToInitializedName(): unhandled reference type:"<<current->class_name()<<endl;
22268 ROSE_ABORT();
22269 }
22270 }
22271 //ROSE_ASSERT(name != NULL);
22272 return name;
22273}
22274
22277{
22278#ifdef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22279 printf ("AbstractHandle support is disabled for ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT \n");
22280 ROSE_ABORT();
22281#else
22283
22284 // trim off the possible leading handle for project: "Project<numbering,1>::"
22285 size_t pos = input_string.find("SourceFile<");
22286 ROSE_ASSERT (pos != string::npos);
22287 string trimed_string = input_string.substr(pos);
22288 AbstractHandle::abstract_handle * handle = new AbstractHandle::abstract_handle(project_handle, trimed_string);
22289 if (handle)
22290 {
22291 if (handle->getNode()!=NULL)
22292 {
22293#ifdef _MSC_VER
22294 // DQ (11/28/2009): This is related to the use of covariant return types (I think).
22295 SgNode* result = NULL; // (SgNode*)(handle->getNode()->getNode());
22296#pragma message ("WARNING: covariant return type for get_node() not supported in MSVC.")
22297 printf ("ERROR: covariant return type for get_node() not supported in MSVC. \n");
22298 ROSE_ABORT();
22299#else
22300 SgNode* result = (SgNode*)(handle->getNode()->getNode());
22301#endif
22302 // deallocate memory, should not do this!!
22303 // May corrupt the internal std maps used in abstract handle namespace
22304 //delete handle->getNode();
22305 //delete handle;
22306 return result;
22307 }
22308 }
22309#endif
22310
22311 return NULL;
22312}
22313
22314
22316// unparseToString() is too strict for debugging purpose
22317// we provide this instead.
22318void SageInterface::dumpInfo(SgNode* node, std::string desc/*=""*/)
22319{
22320 ROSE_ASSERT(node != NULL);
22321 cout<<desc<<endl;
22322 // base information for all SgNode:
22323 cout<<"///////////// begin of SageInterface::dumpInfo() ///////////////"<<endl;
22324 cout<<"--------------base info. for SgNode---------------"<<endl;
22325 cout<<node<<" "<<node->class_name()<<endl;
22326 SgLocatedNode* snode = isSgLocatedNode(node);
22327 if (snode)
22328 {
22329 // source file info. dump
22330 cout<<"--------------source location info. for SgNode---------------"<<endl;
22331 cout<<snode->get_file_info()->get_filename()
22332 << ":"<<snode->get_file_info()->get_line()<<"-"
22333 << snode->get_file_info()->get_col()<<endl;
22334 // preprocessing info dump
22335 AttachedPreprocessingInfoType *comments = snode->getAttachedPreprocessingInfo ();
22336 if (comments)
22337 {
22338 cout<<"--------------preprocessing info. for SgNode---------------"<<endl;
22339 AttachedPreprocessingInfoType::iterator i;
22340 cout<<"Total attached preprocessingInfo count="<<comments->size()<<endl;
22341 for (i = comments->begin (); i != comments->end (); i++)
22342 {
22343 PreprocessingInfo * pinfo = *i;
22344 pinfo->display("");
22345 }
22346 }
22347 cout<<"--------------name info. for SgNode---------------"<<endl;
22348 // print out namea for named nodes
22349 SgFunctionDeclaration * decl = isSgFunctionDeclaration(snode);
22350 if (decl)
22351 cout<<"\tqualified name="<<decl->get_qualified_name().getString()<<endl;
22352 SgVarRefExp * varRef = isSgVarRefExp(snode);
22353 if (varRef)
22354 cout<<"\treferenced variable name= "<<varRef->get_symbol()->get_name().getString()<<endl;
22355 }
22356 SgInitializedName * iname = isSgInitializedName(snode);
22357 if (iname)
22358 cout<<"\tvariable name= "<<iname->get_qualified_name().getString()<<endl;
22359
22360 cout<<endl;
22361 cout<<"///////////// end of SageInterface::dumpInfo() ///////////////"<<endl;
22362}
22363
22369bool
22370SageInterface::collectReadWriteRefs(SgStatement* stmt, std::vector<SgNode*>& readRefs, std::vector<SgNode*>& writeRefs, bool useCachedDefUse)
22371{ // The type cannot be SgExpression since variable declarations have SgInitializedName as the reference, not SgVarRefExp.
22372 bool retVal = true;
22373
22374 ROSE_ASSERT(stmt !=NULL);
22375
22376#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22377 // We should allow accumulate the effects for multiple statements
22378 // ROSE_ASSERT(readRefs.size() == 0);
22379 // ROSE_ASSERT(writeRefs.size() == 0);
22380
22381 // convert a request for a defining function declaration to its function body
22382 SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(stmt);
22383 if (funcDecl != NULL)
22384 {
22385 funcDecl= isSgFunctionDeclaration(funcDecl->get_definingDeclaration ());
22386 if (funcDecl == NULL)
22387 {
22388 cerr<<"In collectReadWriteRefs(): cannot proceed without a function body!"<<endl;
22389 }
22390 else
22391 stmt = funcDecl->get_definition()->get_body();
22392 }
22393
22394 // get function level information
22395 SgFunctionDefinition* funcDef = isSgFunctionDefinition(stmt);
22396 if (!funcDef)
22398
22399 ROSE_ASSERT(funcDef != NULL);
22400 SgBasicBlock* funcBody = funcDef->get_body();
22401 ROSE_ASSERT(funcBody!= NULL);
22402
22403 // prepare Loop transformation environment
22404 AstInterfaceImpl faImpl(funcBody);
22405 AstInterface fa(&faImpl);
22406 ArrayAnnotation* annot = ArrayAnnotation::get_inst();
22407 if( useCachedDefUse ){
22408 ArrayInterface* array_interface = ArrayInterface::get_inst(*annot, fa, funcDef, AstNodePtrImpl(funcDef));
22409 LoopTransformInterface::set_arrayInfo(array_interface);
22410 } else {
22411 ArrayInterface array_interface(*annot);
22412 // Alias analysis and value propagation are called in initialize(). Turn both off for now.
22413// array_interface.initialize(fa, AstNodePtrImpl(funcDef));
22414 array_interface.observe(fa);
22415 LoopTransformInterface::set_arrayInfo(&array_interface);
22416 }
22417 LoopTransformInterface::set_astInterface(fa);
22418 // Liao, 3/27/2015. connect to annotations for function side effect
22419 LoopTransformInterface::set_sideEffectInfo(annot);
22420
22421 // variables to store results
22422 DoublyLinkedListWrap<AstNodePtr> rRef1, wRef1;
22423 CollectDoublyLinkedList<AstNodePtr> crRef1(rRef1),cwRef1(wRef1);
22424 AstNodePtr s1 = AstNodePtrImpl(stmt);
22425
22426 // Actual side effect analysis
22427 if (!AnalyzeStmtRefs(fa, s1, cwRef1, crRef1))
22428 {
22429 //False returned here just means that the function called a
22430 //function that was not annotated with Qing's RWset annotation
22431 //method. This doesn't matter for my tool. -Jim Leek 03/21/2023
22432 mlog[Sawyer::Message::Common::DEBUG] << "Function: " << funcDef->get_declaration()->get_qualified_name() << " calls at least one function that has not been annotated." << endl;
22433 retVal = false;
22434 }
22435
22436 // transfer results into STL containers.
22437 for (DoublyLinkedEntryWrap<AstNodePtr>* p = rRef1.First(); p != 0; )
22438 {
22439 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22440 p = rRef1.Next(p);
22441 AstNodePtr cur = p1->GetEntry();
22442 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22443 ROSE_ASSERT(sgRef != NULL);
22444 readRefs.push_back(sgRef);
22445 //cout<<"read reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22446 // " sage type:"<< sgRef->class_name()<< endl;
22447 }
22448
22449 for (DoublyLinkedEntryWrap<AstNodePtr>* p = wRef1.First(); p != 0; )
22450 {
22451 DoublyLinkedEntryWrap<AstNodePtr>* p1 = p;
22452 p = wRef1.Next(p);
22453 AstNodePtr cur = p1->GetEntry();
22454 SgNode* sgRef = AstNodePtrImpl(cur).get_ptr();
22455 ROSE_ASSERT(sgRef != NULL);
22456 writeRefs.push_back(sgRef);
22457 // cout<<"write reference:"<<sgRef->unparseToString()<<" address "<<sgRef<<
22458 // " sage type:"<< sgRef->class_name()<< endl;
22459 }
22460
22461#endif
22462
22463 return retVal;
22464}
22465#if 0
22466// The side effect analysis will report three references for a statement like this->x = ...
22467// 1.SgThisExp 2. SgArrowExp 3. SgVarRefExp
22468// We only need to keep SgVarRefExp and skip the other two.
22469static bool skipSomeRefs(SgNode* n)
22470{
22471 ROSE_ASSERT (n);
22472 return (isSgThisExp(n)||isSgArrowExp(n)||isSgDotExp(n));
22473}
22474#endif
22476bool SageInterface::collectReadWriteVariables(SgStatement* stmt, set<SgInitializedName*>& readVars, set<SgInitializedName*>& writeVars, bool coarseGrain/*=true*/)
22477{
22478 ROSE_ASSERT(stmt != NULL);
22479 vector <SgNode* > readRefs, writeRefs;
22480
22481 bool retVal = collectReadWriteRefs(stmt, readRefs, writeRefs);
22482 // process read references
22483 vector<SgNode*>::iterator iter = readRefs.begin();
22484 for (; iter!=readRefs.end();iter++)
22485 {
22486 SgNode* current = *iter;
22487 //if (skipSomeRefs(current)) continue;
22488
22489 ROSE_ASSERT (current != NULL);
22490 SgInitializedName* name= convertRefToInitializedName(current, coarseGrain);
22491 //ROSE_ASSERT (name); // this pointer will return NULL
22492 if (!name) continue;
22493 // Only insert unique ones
22494 // We use std::set to ensure uniqueness now
22495 readVars.insert(name);
22496 }
22497 // process write references
22498 vector<SgNode*>::iterator iterw = writeRefs.begin();
22499 for (; iterw!=writeRefs.end();iterw++)
22500 {
22501 SgNode* current = *iterw;
22502 ROSE_ASSERT (current != NULL);
22503 SgInitializedName* name = convertRefToInitializedName(current, coarseGrain);
22504 if (!name) continue;
22505 //ROSE_ASSERT (name); // this pointer will return NULL
22506 // Only insert unique ones
22507 // We use std::set to ensure uniqueness now
22508 writeVars.insert(name);
22509 }
22510 return retVal;
22511}
22512
22514void SageInterface::collectReadOnlyVariables(SgStatement* stmt, std::set<SgInitializedName*>& readOnlyVars, bool coarseGrain/*=true*/)
22515{
22516 ROSE_ASSERT(stmt != NULL);
22517 set<SgInitializedName*> readVars, writeVars;
22518 // Only collect read only variables if collectReadWriteVariables() succeeded.
22519 if (collectReadWriteVariables(stmt, readVars, writeVars, coarseGrain))
22520 {
22521 // read only = read - write
22522 set_difference(readVars.begin(), readVars.end(),
22523 writeVars.begin(), writeVars.end(),
22524 std::inserter(readOnlyVars, readOnlyVars.begin()));
22525 }
22526 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
22527 {
22528 RoseAst ast(stmt);
22529
22530 for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
22531 if (SgVarRefExp* v_ref = isSgVarRefExp(*i))
22532 {
22533 if (isConstType(v_ref->get_type()))
22534 readOnlyVars.insert (v_ref->get_symbol()->get_declaration());
22535 }
22536 } // end for
22537 } // end else
22538}
22539
22540
22542void SageInterface::collectReadOnlySymbols(SgStatement* stmt, std::set<SgVariableSymbol*>& readOnlySymbols, bool coarseGrain/*=true*/)
22543{
22544 set<SgInitializedName*> temp;
22545 collectReadOnlyVariables(stmt, temp, coarseGrain);
22546
22547 for (set<SgInitializedName*>::const_iterator iter = temp.begin();
22548 iter!=temp.end(); iter++)
22549 {
22550 SgSymbol* symbol = (*iter)->get_symbol_from_symbol_table () ;
22551 ROSE_ASSERT(symbol != NULL );
22552 ROSE_ASSERT(isSgVariableSymbol(symbol));
22553 readOnlySymbols.insert(isSgVariableSymbol(symbol));
22554 }
22555
22556}
22557
22560{
22561 bool result = false;
22562 ROSE_ASSERT(ref != NULL);
22563 ROSE_ASSERT(ref->get_parent() != NULL);
22564 // case 1: ref is used as an operator for & (SgAddressofOp)
22565 // TODO tolerate possible type casting operations in between ?
22566 if (isSgAddressOfOp(ref->get_parent()))
22567 {
22568 result = true;
22569 }
22570 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22571 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22572 {
22573 SgNode* grandparent = ref->get_parent()->get_parent();
22574 ROSE_ASSERT(grandparent);
22575 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22576 {
22577 // find which parameter ref is in SgExpressionPtrList
22578
22579 // DQ (8/12/2020): This is a compiler warning where it is used below in comparision between signed and unsigned types.
22580 // int param_index = 0;
22581 size_t param_index = 0;
22582
22583 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22584 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22585 for (; iter!=expList.end(); iter++)
22586 {
22587 if (*iter == ref)
22588 break;
22589 else
22590 param_index++;
22591 }
22592 // find the parameter type of the corresponding function declaration
22593 SgExpression* func_exp = isSgFunctionCallExp(grandparent)->get_function();
22594 ROSE_ASSERT (func_exp);
22595 SgFunctionRefExp * funcRef = isSgFunctionRefExp(func_exp);
22596 if (funcRef) // regular functions
22597 {
22598 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22599 SgInitializedNamePtrList nameList = funcDecl->get_args();
22600 //TODO tolerate typedef chains
22601 // printf() has only two arguments to express variable arguments.
22602 // The third argument index ==2 will be out of bounds for nameList[index]
22603 // So we must check the bound first.
22604 if (param_index >= nameList.size() ||isSgTypeEllipse(nameList[param_index]->get_type()) )
22605 {
22606 if (isSgReferenceType(ref))
22607 result = true;
22608 }
22609 else // now within the bound: two situations,
22610 if (isSgReferenceType(nameList[param_index]->get_type()))
22611 {
22612 result = true;
22613 }
22614 } //It also could be a dot or arrow expression where its right hand operand is a SgMemberFunctionRefExp
22615 else if (isSgDotExp (func_exp) || isSgArrowExp(func_exp)) // ArrowExp TODO
22616 {
22617 SgBinaryOp* binOp = isSgBinaryOp(func_exp);
22618 ROSE_ASSERT (binOp);
22619 SgMemberFunctionRefExp* mfuncRef = isSgMemberFunctionRefExp(binOp->get_rhs_operand_i());
22620 ROSE_ASSERT (mfuncRef);
22621 SgMemberFunctionDeclaration * mfuncDecl = isSgMemberFunctionSymbol (mfuncRef->get_symbol())->get_declaration();
22622 ROSE_ASSERT (mfuncDecl);
22623 SgInitializedNamePtrList nameList = mfuncDecl->get_args();
22624 //TODO tolerate typedef chains
22625 if (isSgReferenceType(nameList[param_index]->get_type()))
22626 {
22627 result = true;
22628 }
22629 }
22630
22631 }
22632 }
22633 return result;
22634}
22635
22636
22638void SageInterface::collectUseByAddressVariableRefs (const SgStatement* s, std::set<SgVarRefExp* >& varSetB)
22639{
22640 Rose_STL_Container <SgNode*> var_refs = NodeQuery::querySubTree (const_cast<SgStatement *> (s), V_SgVarRefExp);
22641
22642 Rose_STL_Container<SgNode*>::iterator iter = var_refs.begin();
22643 for (; iter!=var_refs.end(); iter++)
22644 {
22645 SgVarRefExp* ref = isSgVarRefExp(*iter);
22646 ROSE_ASSERT(ref != NULL);
22647 ROSE_ASSERT(ref->get_parent() != NULL);
22648#if 0
22649 // case 1: ref is used as an operator for & (SgAddressofOp)
22650 // TODO tolerate possible type casting operations in between ?
22651 if (isSgAddressOfOp(ref->get_parent()))
22652 {
22653 varSetB.insert(ref);
22654 }
22655 // case 2. ref is used as a function call's parameter, and the parameter has reference type in C++
22656 else if ((SageInterface::is_Cxx_language())&&(isSgExprListExp(ref->get_parent())))
22657 {
22658 SgNode* grandparent = ref->get_parent()->get_parent();
22659 ROSE_ASSERT(grandparent);
22660 if (isSgFunctionCallExp(grandparent)) // Is used as a function call's parameter
22661 {
22662 // find which parameter ref is in SgExpressionPtrList
22663 int param_index =0;
22664 SgExpressionPtrList expList = isSgExprListExp(ref->get_parent())->get_expressions();
22665 Rose_STL_Container<SgExpression*>::const_iterator iter= expList.begin();
22666 for (; iter!=expList.end(); iter++)
22667 {
22668 if (*iter == ref)
22669 break;
22670 else
22671 param_index++;
22672 }
22673 // find the parameter type of the corresponding function declaration
22674 SgFunctionRefExp * funcRef = isSgFunctionRefExp(isSgFunctionCallExp(grandparent)->get_function());
22675 SgFunctionDeclaration* funcDecl = isSgFunctionSymbol(funcRef->get_symbol())->get_declaration();
22676 SgInitializedNamePtrList nameList = funcDecl->get_args();
22677 //TODO tolerate typedef chains
22678 if (isSgReferenceType(nameList[param_index]->get_type()))
22679 {
22680 varSetB.insert(ref);
22681 }
22682 }
22683 }
22684#endif
22686 varSetB.insert(ref);
22687 }
22688}
22689
22690#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22692LivenessAnalysis * SageInterface::call_liveness_analysis(SgProject* project, bool debug/*=false*/)
22693{
22694 // We expect this function to be called multiple times but always return the result generated from the first execution.
22695 static LivenessAnalysis* liv = NULL; // one instance
22696 if (liv!=NULL)
22697 return liv;
22698
22699 static DFAnalysis * defuse = NULL; // only one instance
22700 // Prepare def-use analysis
22701 if (defuse==NULL)
22702 {
22703 ROSE_ASSERT(project != NULL);
22704 defuse = new DefUseAnalysis(project);
22705 }
22706
22707 ROSE_ASSERT(defuse != NULL);
22708 defuse->run(debug);
22709
22710 if (debug)
22711 defuse->dfaToDOT();
22712
22713 //Prepare variable liveness analysis
22714 liv = new LivenessAnalysis(debug,(DefUseAnalysis*)defuse);
22715 ROSE_ASSERT(liv != NULL);
22716
22717 std::vector <FilteredCFGNode < IsDFAFilter > > dfaFunctions;
22718 NodeQuerySynthesizedAttributeType vars =
22719 NodeQuery::querySubTree(project, V_SgFunctionDefinition);
22720 NodeQuerySynthesizedAttributeType::const_iterator i;
22721 bool abortme=false;
22722 // run liveness analysis on each function body
22723 for (i= vars.begin(); i!=vars.end();++i)
22724 {
22725 SgFunctionDefinition* func = isSgFunctionDefinition(*i);
22726 ROSE_ASSERT(func != NULL);
22727 if (debug)
22728 {
22729 std::string name = func->class_name();
22730 string funcName = func->get_declaration()->get_qualified_name().str();
22731 cout<< " .. running liveness analysis for function: " << funcName << endl;
22732 }
22733 FilteredCFGNode <IsDFAFilter> rem_source = liv->run(func,abortme);
22734 // propagate results to statement level
22735 liv->fixupStatementsINOUT(func);
22736 if (rem_source.getNode()!=NULL)
22737 dfaFunctions.push_back(rem_source);
22738 if (abortme)
22739 break;
22740 } // end for ()
22741 if(debug)
22742 {
22743 cout << "Writing out liveness analysis results into var.dot... " << endl;
22744 std::ofstream f2("var.dot");
22745 dfaToDot(f2, string("var"), dfaFunctions, (DefUseAnalysis*)defuse, liv);
22746 f2.close();
22747 }
22748 if (abortme) {
22749 cerr<<"Error: Liveness analysis is ABORTING ." << endl;
22750 ROSE_ABORT();
22751 }
22752 return liv;
22753 //return !abortme;
22754}
22755#endif
22756
22757#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
22759void SageInterface::getLiveVariables(LivenessAnalysis * liv, SgForStatement* loop, std::set<SgInitializedName*>& liveIns, std::set<SgInitializedName*> & liveOuts)
22760{
22761 ROSE_ASSERT(liv != NULL);
22762 ROSE_ASSERT(loop != NULL);
22763 SgForStatement *forstmt = loop;
22764 std::vector<SgInitializedName*> liveIns0, liveOuts0; // store the original one
22765
22766 // Jeremiah's hidden constructor parameter value '2' to grab the node for forStmt's
22767 // Several CFG nodes are used for the same SgForStatement, only one of the is needed.
22768 // We have to check the full control flow graph to find all SgForStatement's nodes,
22769 // check the index numbers from 0 , find the one with two out edges (true, false)
22770 // The CFG node should have a caption like" <SgForStatement> @ 8: 1",
22771 // which means this is a CFG node for a for statement at source line 8, with an index 1.
22772 // For SgForStatement, there are 5 cfg nodes, 0 and 4 are for begin and end CFG nodes
22773 // 1: after init statement, 2: after test expression (the remaining one after filtering), 3: before increment
22774 CFGNode cfgnode(forstmt,2);
22775 FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (cfgnode);
22776 // This one does not return the one we want even its getNode returns the
22777 // right for statement
22778 //FilteredCFGNode<IsDFAFilter> filternode= FilteredCFGNode<IsDFAFilter> (forstmt->cfgForBeginning());
22779 ROSE_ASSERT(filternode.getNode()==forstmt);
22780
22781 // Check out edges
22782 vector<FilteredCFGEdge < IsDFAFilter > > out_edges = filternode.outEdges();
22783 ROSE_ASSERT(out_edges.size()==2);
22784 vector<FilteredCFGEdge < IsDFAFilter > >::iterator iter= out_edges.begin();
22785
22786 for (; iter!=out_edges.end();iter++)
22787 {
22788 FilteredCFGEdge < IsDFAFilter > edge= *iter;
22789 //SgForStatement should have two outgoing edges based on the loop condition
22790 // one true(going into the loop body) and one false (going out the loop)
22791 //x. Live-in (loop) = live-in (first-stmt-in-loop)
22792 if (edge.condition()==eckTrue)
22793 {
22794 SgNode* firstnode= edge.target().getNode();
22795 liveIns0 = liv->getIn(firstnode);
22796 // cout<<"Live-in variables for loop:"<<endl;
22797 for (std::vector<SgInitializedName*>::iterator iter = liveIns0.begin();
22798 iter!=liveIns0.end(); iter++)
22799 {
22800 // SgInitializedName* name = *iter;
22801 liveIns.insert(*iter);
22802 // cout<< name->get_qualified_name().getString()<<endl;
22803 }
22804 }
22805 //x. live-out(loop) = live-in (first-stmt-after-loop)
22806 else if (edge.condition()==eckFalse)
22807 {
22808 SgNode* firstnode= edge.target().getNode();
22809 liveOuts0 = liv->getIn(firstnode);
22810 // cout<<"Live-out variables for loop:"<<endl;
22811 for (std::vector<SgInitializedName*>::iterator iter = liveOuts0.begin();
22812 iter!=liveOuts0.end(); iter++)
22813 {
22814 // SgInitializedName* name = *iter;
22815 // cout<< name->get_qualified_name().getString()<<endl;
22816 liveOuts.insert(*iter);
22817 }
22818 }
22819 else
22820 {
22821 cerr<<"Unexpected CFG out edge type for SgForStmt!"<<endl;
22822 ROSE_ABORT();
22823 }
22824 } // end for (edges)
22825
22826}
22827#endif
22828
22829//Check if two references form an idiom like: x= x op expr, x = expr op x (except for subtraction)
22830static bool isAssignReduction (SgVarRefExp* ref_exp1, SgVarRefExp* ref_exp2, OmpSupport::omp_construct_enum& optype)
22831{
22832 bool isReduction = false;
22833 // Sanity check
22834 ROSE_ASSERT (ref_exp1!= NULL);
22835 ROSE_ASSERT (ref_exp2!= NULL);
22836 ROSE_ASSERT (ref_exp1-> get_symbol() == ref_exp2-> get_symbol());
22837 // must be scalar type
22838 ROSE_ASSERT (SageInterface::isScalarType(ref_exp1-> get_symbol()->get_type() ) );
22839
22842 if (stmt != stmt2) return false; // early return false;
22843
22844 // must be assignment statement using
22845 // x= x op expr, x = expr op x (except for subtraction)
22846 // one reference on left hand, the other on the right hand of assignment expression
22847 // the right hand uses associative operators +, *, -, &, ^ ,|, &&, ||
22848 SgExprStatement* exp_stmt = isSgExprStatement(stmt);
22849 if (exp_stmt && isSgAssignOp(exp_stmt->get_expression()))
22850 {
22851 SgExpression* assign_lhs=NULL, * assign_rhs =NULL;
22852 assign_lhs = isSgAssignOp(exp_stmt->get_expression())->get_lhs_operand();
22853 assign_rhs = isSgAssignOp(exp_stmt->get_expression())->get_rhs_operand();
22854 ROSE_ASSERT(assign_lhs && assign_rhs);
22855 // x must show up in both lhs and rhs in any order:
22856 // e.g.: ref1 = ref2 op exp or ref2 = ref1 op exp
22857 if (((assign_lhs==ref_exp1)&&SageInterface::isAncestor(assign_rhs,ref_exp2))
22858 ||((assign_lhs==ref_exp2)&&SageInterface::isAncestor(assign_rhs,ref_exp1)))
22859 {
22860 // assignment's rhs must match the associative binary operations
22861 // +, *, -, &, ^ ,|, &&, ||
22862 SgBinaryOp * binop = isSgBinaryOp(assign_rhs);
22863 if (binop!=NULL){
22864 SgExpression* op_lhs = binop->get_lhs_operand();
22865 SgExpression* op_rhs = binop->get_rhs_operand();
22866
22867 // double check that the binary expression has either ref1 or ref2 as one operand
22868 if( !((op_lhs==ref_exp1)||(op_lhs==ref_exp2))
22869 && !((op_rhs==ref_exp1)||(op_rhs==ref_exp2)))
22870 return false; // early return false;
22871
22872 bool isOnLeft = false; // true if it has form (refx op exp), instead (exp or refx)
22873 if ((op_lhs==ref_exp1)|| // TODO might have in between !!
22874 (op_lhs==ref_exp2))
22875 isOnLeft = true;
22876 switch (binop->variantT())
22877 {
22878 case V_SgAddOp:
22879 {
22880 optype = OmpSupport::e_reduction_plus;
22881 isReduction = true;
22882 break;
22883 }
22884 case V_SgMultiplyOp:
22885 {
22886 optype = OmpSupport::e_reduction_mul;
22887 isReduction = true;
22888 break;
22889 }
22890 case V_SgSubtractOp: // special handle here!!
22891 {
22892 optype = OmpSupport::e_reduction_minus;
22893 if (isOnLeft) // cannot allow (exp - x)a
22894 {
22895 isReduction = true;
22896 }
22897 break;
22898 }
22899 case V_SgBitAndOp:
22900 {
22901 optype = OmpSupport::e_reduction_bitand ;
22902 isReduction = true;
22903 break;
22904 }
22905 case V_SgBitXorOp:
22906 {
22907 optype = OmpSupport::e_reduction_bitxor;
22908 isReduction = true;
22909 break;
22910 }
22911 case V_SgBitOrOp:
22912 {
22913 optype = OmpSupport::e_reduction_bitor;
22914 isReduction = true;
22915 break;
22916 }
22917 case V_SgAndOp:
22918 {
22919 optype = OmpSupport::e_reduction_logand;
22920 isReduction = true;
22921 break;
22922 }
22923 case V_SgOrOp:
22924 {
22925 optype = OmpSupport::e_reduction_logor;
22926 isReduction = true;
22927 break;
22928 }
22929 default:
22930 break;
22931 }
22932 } // end matching associative operations
22933 }
22934 } // end if assignop
22935 return isReduction;
22936}
22937// A helper function for reduction recognition
22938// check if two references to the same variable form a reduction idiom using if-statement
22939// example 1: if (array[i]> maxV) maxV = array[i]
22940// example 2: if (array[i]< minV) minV = array[i]
22941// If it matches, return true and the reduction operator type
22942static bool isIfReduction(SgVarRefExp* ref1, SgVarRefExp* ref2, OmpSupport::omp_construct_enum& optype)
22943{
22944 bool matchStmt1 = false;
22945 bool matchStmt2 = false;
22946
22947 //TODO: ensure ref1, ref2 are ordered as pre-order manner in AST
22948 // SgExpression* reduction_var_ref = NULL;
22949 // SgExpression* source_var_ref = NULL; //array[i] is the source var ref
22950
22951 // Sanity check
22952 ROSE_ASSERT (ref1 != NULL);
22953 ROSE_ASSERT (ref2 != NULL);
22954 ROSE_ASSERT (ref1-> get_symbol() == ref2-> get_symbol());
22955 // must be scalar type
22956 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
22957
22960
22961 //early return if the same stmt
22962 if (stmt1 == stmt2) return false;
22963
22964 // check stmt2 first. It is easier.
22965 // stmt2 should be an assignment stmt like:
22966 // reduction_variable = else;
22967 // minV = array[i];
22968 SgExpression* lhs2 = NULL;
22969 SgExpression* rhs2 = NULL;
22970 if (SageInterface::isAssignmentStatement (stmt2, &lhs2, &rhs2 ))
22971 {
22972 // lhs2 must be ref2
22973 if (lhs2 == ref2 )
22974 {
22975 matchStmt2 = true;
22976 // reduction_var_ref = lhs2;
22977 // source_var_ref= rhs2;
22978 }
22979 } // end assignment stmt
22980
22981 // stmt1 should be a if-stmt's conditional expression stmt
22982 // and its body should be stmt2
22983 if (SgExprStatement* if_cond_stmt = isSgExprStatement(stmt1))
22984 {
22985 bool matchBody = false;
22986 bool matchCondition= false;
22987 if (SgIfStmt * if_stmt = isSgIfStmt (if_cond_stmt->get_parent()) )
22988 {
22989 if (SgStatement* body = if_stmt->get_true_body())
22990 {
22991 if (SgBasicBlock* block = isSgBasicBlock (body))
22992 {
22993 // stmt2 must be the only child of the if true body
22994 ROSE_ASSERT(stmt2 != NULL);
22995 if ( ((block->get_statements()).size() == 1) && stmt2->get_scope() == block )
22996 matchBody = true;
22997 }
22998 else
22999 {
23000 if (body == stmt2)
23001 matchBody = true;
23002 }
23003 } // body match test
23004
23005 // match condition SgExprStatement ref1 SgLessThanOp source_var
23006 if (SgExprStatement* cond_exp_stmt = isSgExprStatement (if_stmt->get_conditional()) )
23007 {
23008 SgExpression* cond_exp = cond_exp_stmt->get_expression();
23009 if (SgBinaryOp * binop = isSgBinaryOp (cond_exp))
23010 {
23011 if (ref1 == binop->get_lhs_operand_i())
23012 {
23013 // minV > array[i] ;
23014 if (isSgLessThanOp (binop))
23015 {
23016 optype = OmpSupport::e_reduction_max;
23017 matchCondition= true;
23018 }
23019 else if (isSgGreaterThanOp(binop))
23020 {
23021 optype = OmpSupport::e_reduction_min;
23022 matchCondition= true;
23023 }
23024 }
23025 else if ( ref1 == binop->get_rhs_operand_i() )
23026 {
23027 // array[i] < minV
23028 if (isSgLessThanOp (binop))
23029 {
23030 optype = OmpSupport::e_reduction_min;
23031 matchCondition= true;
23032 }
23033 else if (isSgGreaterThanOp(binop))
23034 {
23035 optype = OmpSupport::e_reduction_max;
23036 matchCondition= true;
23037 }
23038 }
23039 } // end if binary op
23040 // TODO the source_var should match the source_var from stmt2
23041 }
23042 }
23043 matchStmt1 = matchBody && matchCondition;
23044 } // end if-stmt
23045
23046
23047 return (matchStmt2 && matchStmt1);
23048}
23049
23050// check if a var ref is a form of
23051// --x, x--, ++x, x++
23052// x+= .., x-= ..., etc.
23053// The reduction variable appears only once in the reduction idiom.
23054static bool isSingleAppearanceReduction(SgVarRefExp* ref1, OmpSupport::omp_construct_enum& optype )
23055{
23056 bool isReduction = false;
23057
23058 ROSE_ASSERT (ref1 != NULL);
23059 // must be scalar type
23060 ROSE_ASSERT (SageInterface::isScalarType(ref1-> get_symbol()->get_type() ) );
23061
23063
23064 if (isSgExprStatement(stmt))
23065 {
23066 SgExpression* exp = isSgExprStatement(stmt)->get_expression();
23067 SgExpression* binop = isSgBinaryOp(exp);
23068 if (isSgPlusPlusOp(exp)) // x++ or ++x
23069 { // Could have multiple reduction clause with different operators!!
23070 // So the variable list is associated with each kind of operator
23071 optype = OmpSupport::e_reduction_plus;
23072 isReduction = true;
23073 }
23074 else if (isSgMinusMinusOp(exp)) // x-- or --x
23075 {
23076 optype = OmpSupport::e_reduction_minus;
23077 isReduction = true;
23078 }
23079 else
23080 // x binop= expr where binop is one of + * - & ^ |
23081 // x must be on the left hand side
23082 if (binop!=NULL) {
23083 SgExpression* lhs= isSgBinaryOp(exp)->get_lhs_operand ();
23084 if (lhs==ref1)
23085 {
23086 switch (exp->variantT())
23087 {
23088 case V_SgPlusAssignOp:
23089 {
23090 optype = OmpSupport::e_reduction_plus;
23091 isReduction = true;
23092 break;
23093 }
23094 case V_SgMultAssignOp:
23095 {
23096 optype = OmpSupport::e_reduction_mul;
23097 isReduction = true;
23098 break;
23099 }
23100 case V_SgMinusAssignOp:
23101 {
23102 optype = OmpSupport::e_reduction_minus;
23103 isReduction = true;
23104 break;
23105 }
23106 case V_SgAndAssignOp:
23107 {
23108 optype = OmpSupport::e_reduction_bitand;
23109 isReduction = true;
23110 break;
23111 }
23112 case V_SgXorAssignOp:
23113 {
23114 optype = OmpSupport::e_reduction_bitxor;
23115 isReduction = true;
23116 break;
23117 }
23118 case V_SgIorAssignOp:
23119 {
23120 optype = OmpSupport::e_reduction_bitor;
23121 isReduction = true;
23122 break;
23123 }
23124 default:
23125 break;
23126 } // end
23127 }// end if on left side
23128 }
23129 }
23130 return isReduction;
23131}
23132
23134/* This code is refactored from project/autoParallelization/autoParSupport.C
23135 std::vector<SgInitializedName*>
23136 RecognizeReduction(SgNode *loop, OmpSupport::OmpAttribute* attribute, std::vector<SgInitializedName*>& candidateVars/)
23137 * Algorithms:
23138 * for each scalar candidate which are both live-in and live-out for the loop body
23139 * (We don't use liveness analysis here for simplicity)
23140 * and which is not the loop invariant variable (loop index).
23141 * Consider those with only 1 or 2 references
23142 * 1 reference
23143 * the operation is one of x++, ++x, x--, --x, x binop= expr
23144 * 2 references belonging to the same operation
23145 * operations: one of x= x op expr, x = expr op x (except for subtraction)
23146 * The reduction description from the OpenMP 3.0 specification.
23147 * x is not referenced in exp
23148 * expr has scalar type (no array, objects etc)
23149 * x: scalar only, aggregate types (including arrays), pointer types and reference types may not appear in a reduction clause.
23150 * op is not an overloaded operator, but +, *, -, &, ^ ,|, &&, ||
23151 * binop is not an overloaded operator, but: +, *, -, &, ^ ,|
23152 */
23153void SageInterface::ReductionRecognition(SgForStatement* loop, std::set< std::pair <SgInitializedName*, OmpSupport::omp_construct_enum > > & results)
23154{
23155 //x. Collect variable references of scalar types as candidates, excluding loop index
23156 SgInitializedName* loopindex;
23157 if (!(isCanonicalForLoop(loop, &loopindex)))
23158 {
23159// cerr<<"Skip reduction recognition for non-canonical for loop"<<endl;
23160 return;
23161 }
23162 std::set<SgInitializedName*> candidateVars; // scalar variables used within the loop
23163 //Store the references for each scalar variable
23164 std::map <SgInitializedName*, vector<SgVarRefExp* > > var_references;
23165
23166 Rose_STL_Container<SgNode*> reflist = NodeQuery::querySubTree(loop, V_SgVarRefExp);
23167 SgStatement* lbody= loop->get_loop_body();
23168 ROSE_ASSERT(lbody != NULL);
23169 Rose_STL_Container<SgNode*>::iterator iter = reflist.begin();
23170 for (; iter!=reflist.end(); iter++)
23171 {
23172 SgVarRefExp* ref_exp = isSgVarRefExp(*iter);
23173 SgInitializedName* initname= ref_exp->get_symbol()->get_declaration();
23174 // candidates are of scalar types and are not the loop index variable
23175 // And also should be live-in:
23176 // not declared locally (var_scope equal or lower than loop body )
23177 // or redefined (captured by ref count)
23178 SgScopeStatement* var_scope = initname->get_scope();
23179 ROSE_ASSERT(var_scope != NULL);
23180 if ((isScalarType(initname->get_type())) &&(initname !=loopindex)
23181 && !(SageInterface::isAncestor(lbody, var_scope)||(lbody==var_scope)))
23182 {
23183 candidateVars.insert(initname);
23184 var_references[initname].push_back(ref_exp);
23185 }
23186 }
23187
23188 //Consider variables referenced at most twice
23189 std::set<SgInitializedName*>::iterator niter=candidateVars.begin();
23190 for (; niter!=candidateVars.end(); niter++)
23191 {
23192 SgInitializedName* initname = *niter;
23193 bool isReduction = false;
23194 OmpSupport::omp_construct_enum optype;
23195 // referenced once only
23196 if (var_references[initname].size()==1)
23197 {
23198 mlog[Sawyer::Message::Common::DEBUG] << "Debug: SageInterface::ReductionRecognition() A candidate used once:"<<initname->get_name().getString()<<endl;
23199 SgVarRefExp* ref_exp = *(var_references[initname].begin());
23200 if (isSingleAppearanceReduction (ref_exp, optype))
23201 isReduction = true;
23202 }
23203 // referenced twice within a same statement
23204 else if (var_references[initname].size()==2)
23205 {
23206 mlog[Sawyer::Message::Common::DEBUG] << "Debug: A candidate used twice:"<<initname->get_name().getString()<<endl;
23207 SgVarRefExp* ref_exp1 = *(var_references[initname].begin());
23208 SgVarRefExp* ref_exp2 = *(++var_references[initname].begin());
23209 // TODO: recognize maxV = array[i]>maxV? array[i]:maxV // this can be normalized to if () stmt
23210 // TODO: recognize maxV = max (maxV, array[i])
23211 if (isAssignReduction (ref_exp1, ref_exp2, optype) || isIfReduction (ref_exp1, ref_exp2, optype) )
23212 {
23213 isReduction = true;
23214 }
23215
23216 }// end referenced twice
23217
23218 if (isReduction)
23219 results.insert(make_pair(initname,optype));
23220 }// end for ()
23221}
23222
23225{
23226 ROSE_ASSERT(r!=NULL);
23227#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23228 ConstantFolding::constantFoldingOptimization(r,false);
23229#endif
23230}
23231
23234{
23236 {
23237 public:
23238 virtual void visit (SgNode * n)
23239 {
23240 SgExpression* exp = isSgExpression(n);
23241 if (exp)
23242 {
23243 string u_name = generateUniqueName(exp,false)+"-"+exp->class_name();
23244 AstAttribute * name_attribute = new UniqueNameAttribute(u_name);
23245 ROSE_ASSERT (name_attribute != NULL);
23246 exp->addNewAttribute("UniqueNameAttribute",name_attribute);
23247 }
23248 }
23249 };
23250 visitorTraversal exampleTraversal;
23251 //Sriram FIX: should traverse using the traverse function
23252 // exampleTraversal.traverseInputFiles(project,preorder);
23253 exampleTraversal.traverse(project, preorder);
23254}
23255
23256
23257 //
23258 // wrap free-standing function body in another function
23259
23261 {
23262 ROSE_ASSERT(vardecl.get_variables().size());
23263
23264 return *vardecl.get_variables().front();
23265 }
23266
23267#if 0
23268 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23269 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23270
23278 static
23280 cloneParameterList(const SgFunctionParameterList& params, SgFunctionDefinition* fundef = NULL)
23281 {
23282 namespace SB = SageBuilder;
23283
23284 SgFunctionParameterList& copy = *SB::buildFunctionParameterList();
23285 const SgInitializedNamePtrList& orig_decls = params.get_args();
23286
23287 std::transform( orig_decls.begin(), orig_decls.end(), sg::sage_inserter(copy), sg::InitNameCloner(copy, fundef) );
23288
23289 return copy;
23290 }
23291#endif
23292
23293#if 0
23294 // DQ (2/16/2017): This is a static function that is defined but not used in this file (compiler waring).
23295
23297 static
23298 void swapDefiningElements(SgFunctionDeclaration& ll, SgFunctionDeclaration& rr)
23299 {
23300 // swap definitions
23301 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_definition, &SgFunctionDeclaration::set_definition);
23302 sg::swap_child(ll, rr, &SgFunctionDeclaration::get_parameterList, &SgFunctionDeclaration::set_parameterList);
23303
23304 // \todo do we need to swap also exception spec, decorator_list, etc. ?
23305 }
23306#endif
23307
23308#if 0
23309 // DQ (11/1/2016): This function violated the ROSE -enable-advanced-warnings
23310 // option (-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC).
23311
23312 std::pair<SgStatement*, SgInitializedName*>
23313 SageInterface::wrapFunction(SgFunctionDeclaration& definingDeclaration, SgName newName)
23314 {
23315 namespace SB = SageBuilder;
23316
23317 // handles freestanding functions only
23318 ROSE_ASSERT(typeid(SgFunctionDeclaration) == typeid(definingDeclaration));
23319 ROSE_ASSERT(definingDeclaration.get_definingDeclaration() == &definingDeclaration);
23320
23321 // clone function parameter list
23322 SgFunctionParameterList& param_list = cloneParameterList(*definingDeclaration.get_parameterList());
23323
23324 // create new function definition/declaration in the same scope
23325 SgScopeStatement* containing_scope = definingDeclaration.get_scope();
23326 SgType* result_type = definingDeclaration.get_type()->get_return_type();
23327 SgExprListExp* decorators = deepCopy( definingDeclaration.get_decoratorList() );
23328
23329 // DQ (4/9/2015): Suggested fix for this function.
23330 // SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope, decorators);
23331 SgFunctionDeclaration* wrapperfn = SB::buildDefiningFunctionDeclaration(newName, result_type, &param_list, containing_scope);
23332
23333 SgFunctionDefinition* wrapperdef = wrapperfn->get_definition();
23334 ROSE_ASSERT(wrapperdef);
23335
23336 // copy the exception specification
23337 wrapperfn->set_exceptionSpecification(definingDeclaration.get_exceptionSpecification());
23338
23339 // swap the original's function definition w/ the clone's function def
23340 // and the original's func parameter list w/ the clone's parameters
23341 swapDefiningElements(definingDeclaration, *wrapperfn);
23342
23343 // call original function from within the defining decl's body
23344 SgBasicBlock* body = wrapperdef->get_body();
23345 SgExprListExp* args = SB::buildExprListExp();
23346 SgInitializedNamePtrList& param_decls = param_list.get_args();
23347
23348 std::transform( param_decls.begin(), param_decls.end(), sg::sage_inserter(*args), sg::VarRefBuilder(*wrapperdef) );
23349
23350 SgFunctionCallExp* callWrapped = SB::buildFunctionCallExp( newName, result_type, args, body );
23351 SgInitializedName* resultName = NULL;
23352 SgStatement* callStatement = NULL;
23353
23354 // \todo skip legal qualifiers that could be on top of void
23355 if (!isSgTypeVoid(result_type))
23356 {
23357 // add call to original function and assign result to variable
23358 SgVariableDeclaration* res = SB::buildVariableDeclaration( "res", result_type, SB::buildAssignInitializer(callWrapped), body );
23359 SgVarRefExp* resref = SB::buildVarRefExp( res );
23360
23361 appendStatement(res, body);
23362
23363 // add return statement, returning result
23364 resultName = &getFirstVariable(*res);
23365 callStatement = res;
23366
23367 appendStatement(SB::buildReturnStmt(resref), body);
23368 }
23369 else
23370 {
23371 // add function call statement to original function
23372 callStatement = SB::buildExprStatement(callWrapped);
23373 appendStatement(callStatement, body);
23374 }
23375
23376 ROSE_ASSERT(callStatement);
23377
23378 // create non defining declaration
23379 SgExprListExp* decorator_proto = deepCopy( decorators );
23380 SgFunctionDeclaration* wrapperfn_proto = SB::buildNondefiningFunctionDeclaration(wrapperfn, containing_scope, decorator_proto);
23381
23382 // add the new functions at the proper location of the surrounding scope
23383 insertStatementBefore(&definingDeclaration, wrapperfn_proto);
23384 insertStatementAfter (&definingDeclaration, wrapperfn);
23385
23386 return std::make_pair(callStatement, resultName);
23387 }
23388#endif
23389
23390 //
23391 // flatten C/C++ array dimensions
23392 namespace
23393 {
23394 struct VarrefBuilder
23395 {
23396 virtual SgVarRefExp* get() const = 0;
23397
23398 static
23399 SgVarRefExp* build(const SgVarRefExp& n)
23400 {
23401 return SageInterface::deepCopy(&n);
23402 }
23403
23404 static
23406 {
23407 SgScopeStatement* scope = sg::ancestor<SgStatement>(n).get_scope();
23408
23409 return SageBuilder::buildVarRefExp(&n, scope);
23410 }
23411 };
23412
23413 template <class AstNode>
23414 struct VarrefCreator : VarrefBuilder
23415 {
23416 AstNode& origin;
23417
23418 explicit
23419 VarrefCreator(AstNode& orig)
23420 : origin(orig)
23421 {}
23422
23423 SgVarRefExp* get() const { return VarrefBuilder::build(origin); }
23424 };
23425
23426 template <class AstNode>
23427 VarrefCreator<AstNode>
23428 varrefCreator(AstNode& n)
23429 {
23430 return VarrefCreator<AstNode>(n);
23431 }
23432
23433 SgExpression* create_mulop(SgExpression* lhs, const SgExpression* rhs)
23434 {
23435 namespace SB = SageBuilder;
23436 namespace SI = SageInterface;
23437
23438 // we own the lhs (intermediate result),
23439 // but we do not own the rhs (another top-level expression)
23440 return SB::buildMultiplyOp(lhs, SI::deepCopy(rhs));
23441 }
23442
23443 std::pair<std::vector<SgExpression*>, SgType*>
23444 get_C_array_dimensions_aux(const SgArrayType& arr_type)
23445 {
23446 namespace SB = SageBuilder;
23447 namespace SI = SageInterface;
23448
23449 const SgArrayType* arrtype = &arr_type;
23450 std::vector<SgExpression*> indices;
23451 SgType* undertype = NULL;
23452
23453 // \todo when get_index() does not return a nullptr anymore
23454 // the condition can be removed
23455 if (arrtype->get_index() == NULL)
23456 {
23457 indices.push_back(SB::buildNullExpression());
23458 undertype = arrtype->get_base_type();
23459 arrtype = isSgArrayType(undertype);
23460 }
23461
23462 while (arrtype)
23463 {
23464 SgExpression* indexexpr = arrtype->get_index();
23465 ROSE_ASSERT(indexexpr);
23466
23467 indices.push_back(SI::deepCopy(indexexpr));
23468 undertype = arrtype->get_base_type();
23469 arrtype = isSgArrayType(undertype);
23470 }
23471
23472 ROSE_ASSERT((!indices.empty()) && undertype);
23473 return std::make_pair(indices, undertype);
23474 }
23475
23477 std::vector<SgExpression*>
23478 get_C_array_dimensions_aux(const SgArrayType& arrtype, const VarrefBuilder& varrefBuilder)
23479 {
23480 namespace SB = SageBuilder;
23481
23482 std::pair<std::vector<SgExpression*>, SgType*> res = get_C_array_dimensions_aux(arrtype);
23483 const std::vector<SgExpression*>::iterator first = res.first.begin();
23484
23485 // if the first dimension was open, create the expression for it
23486 if (isSgNullExpression(*first))
23487 {
23488 // handle implicit first dimension for array initializers
23489 // for something like
23490 // int p[][2][3] = {{{ 1, 2, 3 }, { 4, 5, 6 }}}
23491 // we can calculate the first dimension as
23492 // sizeof( p ) / ( sizeof( int ) * 2 * 3 )
23493
23494 const std::vector<SgExpression*>::iterator aa = first+1;
23495 const std::vector<SgExpression*>::iterator zz = res.first.end();
23496
23497 SgExpression* sz_undertype = SB::buildSizeOfOp(res.second);
23498 SgExpression* denominator = std::accumulate(aa, zz, sz_undertype, create_mulop);
23499 SgSizeOfOp* sz_var = SB::buildSizeOfOp(varrefBuilder.get());
23500 SgExpression* sz = SB::buildDivideOp(sz_var, denominator);
23501
23502 std::swap(*first, sz);
23503 delete sz;
23504 }
23505
23506 return res.first;
23507 }
23508 }
23509
23510 std::vector<SgExpression*>
23512 {
23513 return get_C_array_dimensions_aux(arrtype).first;
23514 }
23515
23516 std::vector<SgExpression*>
23518 {
23519 return get_C_array_dimensions_aux(arrtype, varrefCreator(varref));
23520 }
23521
23522 std::vector<SgExpression*>
23524 {
23525 return get_C_array_dimensions_aux(arrtype, varrefCreator(initname));
23526 }
23527
23528// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23530 {
23531 public:
23532 set<unsigned int> sourceSequenceSet;
23533
23534 void visit ( SgNode* astNode );
23535 };
23536
23537// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23538void
23540 {
23541 Sg_File_Info* fileInfo = astNode->get_file_info();
23542 if (fileInfo != NULL)
23543 {
23544 unsigned int source_sequence_number = fileInfo->get_source_sequence_number();
23545#if 0
23546 printf ("In CollectSourceSequenceNumbers::visit(): source_sequence_number = %" PRIuPTR " \n",source_sequence_number);
23547#endif
23548 sourceSequenceSet.insert(source_sequence_number);
23549 }
23550 }
23551
23552// DQ (1/23/2013): Added support for generated a set of source sequence entries.
23553set<unsigned int>
23555 {
23557
23558 traversal.traverse(astNode,preorder);
23559
23560 return traversal.sourceSequenceSet;
23561
23562 }
23563
23564/*Winnie, loop collapse, collapse nested for loops into one large for loop
23565 * return a SgExprListExp *, which will contain a list of SgVarRefExp * to variables newly created, inserted outside of the
23566 * loop scope, and used inside the loop scope.
23567 * If the target_loop comes with omp target directive, these variables should be added in map in clause in
23568 * transOmpCollpase(..) function in omp_lowering.cpp.
23569 *
23570 * The input loop pointer is changed to the generated collapsed loop after the transformation.
23571 *
23572 *
23573 * Loop is normalized to [lb,ub,step], ub is inclusive (<=, >=)
23574 *
23575 * to collapse two level of loops:
23576 * iteration_count_one= (ub1-lb1+1)%step1 ==0?(ub1-lb1+1)/step1: (ub1-lb1+1)/step1+1
23577 * iteration_count_two= (ub2-lb2+1)%step2 ==0?(ub2-lb2+1)/step2: (ub2-lb2+1)/step2+1
23578 * total_iteration_count = iteration_count_one * iteration_count_two
23579 *
23580 * Decide incremental/decremental loop by checking operator of test statement(ub), <=/>=, this is done in isCanonicalForLoop()
23581 *
23582 * Example 1:
23583 * for (int i=lb2;i<ub2;i+=inc2) //incremental
23584 * {
23585 * for (int j=lb1;j>ub1;i+=inc1) //decremental
23586 * {
23587 * for (int l=lb2;l<ub2;l+=inc2) //incremental
23588 * {
23589 * a[i][j][l]=i+j+l;
23590 * }
23591 * }
23592 * }
23593 *
23594 *==> translated output code ==>
23595 * int i_nom_1_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23596 * 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;
23597 * int l_nom_3_total_iters = (ub2 - 1 - lb2 + 1) % inc2 == 0?(ub2 - 1 - lb2 + 1) / inc2 : (ub2 - 1 - lb2 + 1) / inc2 + 1;
23598 * int final_total_iters = 1 * i_nom_1_total_iters* j_nom_2_total_iters* l_nom_3_total_iters;
23599 * int i_nom_1_interval = j_nom_2_total_iters * (l_nom_3_total_iters* 1);
23600 * int j_nom_2_interval = l_nom_3_total_iters * 1;
23601 * int l_nom_3_interval = 1;
23602 *
23603 * for (int new_index = 0; new_index <= final_total_iters- 1; new_index += 1) {
23604 * i_nom_1 = new_index / i_nom_1_interval* inc2 + lb2;
23605 * int i_nom_1_remainder = new_index % i_nom_1_interval;
23606 * j_nom_2 = -(i_nom_1_remainder / j_nom_2_interval* (inc1 * -1)) + lb1;
23607 * l_nom_3 = i_nom_1_remainder % j_nom_2_interval* inc2 + lb2;
23608 * a[i_nom_1][j_nom_2][l_nom_3] = i_nom_1 + j_nom_2 + l_nom_3;
23609 * }
23610 *
23611 * Example 2 with concrete numbers:
23612 *
23613 * // collapse the following two level of for loops:
23614 * for (i=1; i<=9; i+=1) //incremental for loop
23615 * {
23616 * for(j=10; j>=1; j+=-2) //decremental for loop
23617 * {
23618 * a[i][j]=i+j;
23619 * }
23620 * }
23621 * // it becomes
23622 * // total iteration count = ((9 - 1 + 1)/1) * ((10 - 1 + 1)/2) = 45
23623 * // ub = 45
23624 * // lb = 0
23625 *
23626 * int i_nom_1_total_iters = 9;
23627 * int j_nom_1_total_iters = 5; // 10 % (-2 * -1) == 0 ? 10 / (-2 * -1) : 10 /(-2 * -1) + 1;
23628 * int final_total_iters = 45; // i_nom_1_total_iters * j_nom_2_total_iters;
23629 *
23630 * int i_nom_1_interval = 5;
23631 *
23632 * for (z=0; z<=44; z+=1)
23633 * {
23634 * i_nom_1 = z / 5 + 1;
23635 * j_nom_2 = -(z % 5 * 2) + 10;
23636 * a[i_nom_1][j_nom_2]=i_nom_1 + j_nom_2;
23637 * }
23638 * // for the generated loop, a few compiler generated variables are introduced
23639 * final_total_iters for the collapsed loop
23640 * i_interval for each of the n-1 loops
23641 **
23642*/
23643
23644#ifndef USE_ROSE
23646{
23647#ifndef ROSE_USE_INTERNAL_FRONTEND_DEVELOPMENT
23648 //Handle 0 and 1, which means no collapsing at all
23649 if (collapsing_factor <= 1)
23650 return NULL;
23651
23652 SgExprListExp * new_var_list = buildExprListExp(); //expression list contains all the SgVarRefExp * to variables that need to be added in the mapin clause
23653
23654 /*
23655 *step 1: grab the target loops' header information
23656 */
23657 SgForStatement *& target_loop = loop;
23658
23659 // we use global scope to help generate unique variable name later
23660 // local scope-based unique names may cause conflicts if the declarations are moved around (in OpenMP target data promotion)
23661 SgGlobal* global_scope = getGlobalScope (loop);
23662 ROSE_ASSERT (global_scope != NULL);
23663 SgInitializedName** ivar = new SgInitializedName*[collapsing_factor];
23664 SgExpression** lb = new SgExpression*[collapsing_factor];
23665 SgExpression** ub = new SgExpression*[collapsing_factor];
23666 SgExpression** step = new SgExpression*[collapsing_factor];
23667 SgStatement** orig_body = new SgStatement*[collapsing_factor];
23668
23669 SgExpression** total_iters = new SgExpression*[collapsing_factor]; //Winnie, the real iteration counter in each loop level
23670 SgExpression** interval = new SgExpression*[collapsing_factor]; //Winnie, this will be used to calculate i_nom_1_remainder
23671 bool *isPlus = new bool[collapsing_factor]; //Winnie, a flag indicates incremental or decremental for loop
23672
23673
23674 //Winnie, get loops info first
23675 std::vector<SgForStatement* > loops= SageInterface::querySubTree<SgForStatement>(target_loop,V_SgForStatement);
23676 ROSE_ASSERT(loops.size()>=collapsing_factor);
23677
23678 SgForStatement* temp_target_loop = NULL;
23679 SgExpression* temp_range_exp = NULL; //Raw iteration range
23680 SgExpression* temp_range_d_step_exp = NULL; //temp_range_exp / step[i]
23681 SgExpression* temp_condition_1 = NULL; //Check whether temp_range_exp % step[i] == 0
23682 SgExpression* temp_total_iter = NULL;
23683 SgExpression* ub_exp = buildIntVal(1); //Winnie, upbound
23684
23685 /*
23686 * get lb, ub, step information for each level of the loops
23687 * ub_exp is the final iterantion range(starting from 0) after loop collapsing
23688 * total_iters[i], = (ub[i] - lb[i] + 1)/step[i] is the total iter num in each level of loop before loop collapsing
23689 */
23690
23691 SgStatement* parent = isSgStatement(getScope(target_loop)->get_parent()); //Winnie, the scope that include target_loop
23692 ROSE_ASSERT(getScope(target_loop)->get_parent()!= NULL);
23693
23694 SgScopeStatement* scope = isSgScopeStatement(parent); //Winnie, the scope that include target_loop
23695
23696 while(scope == NULL)
23697 {
23698 parent = isSgStatement(parent->get_parent());
23699 scope = isSgScopeStatement(parent);
23700 }
23701
23702 SgStatement* insert_target = findLastDeclarationStatement(scope);
23703 if (insert_target != NULL)
23704 insert_target = getNextStatement(insert_target);
23705 else
23706 insert_target = getFirstStatement(scope);
23707
23708 ROSE_ASSERT(scope != NULL);
23709
23710
23711 for(size_t i = 0; i < collapsing_factor; i ++)
23712 {
23713 temp_target_loop = loops[i];
23714
23715 // normalize the target loop first // adjust to numbering starting from 0
23716 forLoopNormalization(temp_target_loop);
23717
23718 if (!isCanonicalForLoop(temp_target_loop, &ivar[i], &lb[i], &ub[i], &step[i], &orig_body[i], &isPlus[i]))
23719 {
23720 cerr<<"Error in SageInterface::loopCollapsing(): target loop is not canonical."<<endl;
23721 dumpInfo(target_loop);
23722
23723 // release memory
23724 delete[] ivar;
23725 delete[] lb;
23726 delete[] ub;
23727 delete[] step;
23728 delete[] orig_body;
23729 delete[] total_iters;
23730 delete[] interval;
23731 delete[] isPlus;
23732
23733 return NULL;
23734 }
23735
23736 ROSE_ASSERT(ivar[i]&& lb[i] && ub[i] && step[i]);
23737
23738
23739//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]
23740 if(isPlus[i] == true)
23741 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(ub[i]), copyExpression(lb[i])), buildIntVal(1));
23742 else{
23743 temp_range_exp = buildAddOp(buildSubtractOp(copyExpression(lb[i]), copyExpression(ub[i])), buildIntVal(1));
23744 step[i] = buildMultiplyOp(step[i], buildIntVal(-1));
23745 }
23746 temp_range_d_step_exp = buildDivideOp(temp_range_exp,copyExpression(step[i]));//(ub[i]-lb[i]+1)/step[i]
23747
23748 temp_condition_1 = buildEqualityOp(buildModOp(copyExpression(temp_range_exp),copyExpression(step[i])),buildIntVal(0)); //(ub[i]-lb[i]+1)%step[i] ==0
23749
23750 temp_total_iter = buildConditionalExp(temp_condition_1,temp_range_d_step_exp, buildAddOp(copyExpression(temp_range_d_step_exp),buildIntVal(1)));
23751
23752 //build variables to store iteration numbers in each loop, simplify the calculation of "final_total_iters"
23753 //insert the new variable (store real iteration number of each level of the loop) before the target loop
23754 string iter_var_name= "_total_iters";
23755 //iter_var_name = ivar[i]->get_name().getString() + iter_var_name + generateUniqueName(temp_total_iter, false);
23756 iter_var_name = "__"+ivar[i]->get_name().getString() + iter_var_name+ generateUniqueVariableName (global_scope,"");
23757 SgVariableDeclaration* total_iter = buildVariableDeclaration(iter_var_name, buildIntType(), buildAssignInitializer(temp_total_iter, buildIntType()), scope);
23758 insertStatementBefore(insert_target, total_iter);
23759 constantFolding (total_iter);
23760 total_iters[i] = buildVarRefExp(iter_var_name, scope);
23761 ub_exp = buildMultiplyOp(ub_exp, total_iters[i]); //Winnie, build up the final iteration range
23762 }
23763
23764
23765 /*
23766 * step 2: build new variables (new_index, final_total_iters, remainders...) for the new loop
23767 */
23768
23769 /*Winnie, build another variable to store final total iteration counter of the loop after collapsing*/
23770 //string final_iter_counter_name = "final_total_iters" + generateUniqueName(ub_exp, false);
23771 string final_iter_counter_name = "__final_total_iters" + generateUniqueVariableName(global_scope,"");
23772 SgVariableDeclaration * final_total_iter = buildVariableDeclaration(final_iter_counter_name, buildIntType(), buildAssignInitializer(copyExpression(ub_exp), buildIntType()), scope);
23773 insertStatementBefore(insert_target, final_total_iter);
23774 ub_exp = buildVarRefExp(final_iter_counter_name, scope);
23775 new_var_list->append_expression(isSgVarRefExp(ub_exp));
23776
23777 /*Winnie, interval[i] will make the calculation of remainders simpler*/
23778 for(unsigned int i = 0; i < collapsing_factor; i++)
23779 {
23780 interval[i] = buildIntVal(1);
23781 for(unsigned int j = collapsing_factor - 1; j > i; j--)
23782 {
23783 interval[i] = buildMultiplyOp(total_iters[j], interval[i]);
23784 }
23785 //string interval_name = ivar[i]->get_name().getString() + "_interval" + generateUniqueName(interval[i], false);
23786 string interval_name = "__"+ ivar[i]->get_name().getString() + "_interval" + generateUniqueVariableName (global_scope,"");
23787 SgVariableDeclaration* temp_interval = buildVariableDeclaration(interval_name, buildIntType(), buildAssignInitializer(copyExpression(interval[i]), buildIntType()), scope);
23788 insertStatementBefore(insert_target, temp_interval);
23789 interval[i] = buildVarRefExp(interval_name, scope);
23790 new_var_list->append_expression(isSgVarRefExp(interval[i]));
23791 }
23792
23793
23794 //Winnie, starting from here, we are dealing with variables inside loop, update scope
23795 scope = getScope(target_loop);
23796
23797 //Winnie, init statement of the loop header, copy the lower bound, we are dealing with a range, the lower bound should always be "0"
23798 //Winnie, declare a brand new var as the new index
23799 string ivar_name = "__collapsed_index"+ generateUniqueVariableName (global_scope,"");
23800 ROSE_ASSERT(insert_target != NULL);
23801 SgVariableDeclaration* new_index_decl = buildVariableDeclaration(ivar_name, buildIntType(), NULL, insert_target->get_scope());
23802 SgVariableSymbol * collapsed_index_symbol = getFirstVarSym (new_index_decl);
23803 insertStatementBefore(insert_target, new_index_decl);
23804 SgVarRefExp * clps_index_ref = buildVarRefExp(collapsed_index_symbol);
23805 new_var_list->append_expression(clps_index_ref);
23806
23807// SgVariableDeclaration* init_stmt = buildVariableDeclaration(ivar_name, buildIntType(), buildAssignInitializer(buildIntVal(0), buildIntType()), scope);
23808
23809
23810 SgBasicBlock* body = isSgBasicBlock(deepCopy(temp_target_loop->get_loop_body())); // normalized loop has a BB body
23811 ROSE_ASSERT(body != NULL);
23812 SgExpression* new_exp = NULL;
23813 SgExpression* remain_exp_temp = buildVarRefExp(ivar_name, scope);
23814 std::vector<SgStatement*> new_stmt_list;
23815
23816 SgExprStatement* assign_stmt = NULL;
23817
23818 /* Winnie
23819 * express old iterator variables (i_norm, j_norm ...) with new_index,
23820 * new_exp, create new expression for each of the iterators
23821 * i_nom_1 = (_new_index / interval[0])*step[0] + lb[0]
23822 * i_nom_1_remain_value = (_new_index % interval[0])*step[0] + lb[0], create a new var to store remain value
23823 * create a new var to store total_iters[i]
23824 */
23825 for(unsigned int i = 0; i < collapsing_factor - 1; i ++)
23826 {
23827 if(isPlus[i] == true)
23828 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]
23829 else
23830 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
23831
23832 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[i], scope), copyExpression(new_exp));
23833 new_stmt_list.push_back(assign_stmt);
23834 remain_exp_temp = buildModOp((remain_exp_temp), copyExpression(interval[i]));
23835
23836 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
23837 string remain_var_name= "_remainder";
23838 remain_var_name = "__"+ ivar[i]->get_name().getString() + remain_var_name;
23839 SgVariableDeclaration* loop_index_decl = buildVariableDeclaration(remain_var_name, buildIntType(), buildAssignInitializer(remain_exp_temp, buildIntType()), scope);
23840 remain_exp_temp = buildVarRefExp(remain_var_name, scope);
23841 new_stmt_list.push_back(loop_index_decl);
23842 }
23843 new_exp = NULL;
23844 }
23845
23846//Winnie, the inner most loop, iter
23847 if(isPlus[collapsing_factor - 1] == true)
23848 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1]), lb[collapsing_factor - 1]));
23849 else
23850 assign_stmt = buildAssignStatement(buildVarRefExp(ivar[collapsing_factor - 1], scope), buildAddOp(buildMinusOp(buildMultiplyOp(remain_exp_temp, step[collapsing_factor - 1])), lb[collapsing_factor - 1]));
23851 new_stmt_list.push_back(assign_stmt);
23852 prependStatementList(new_stmt_list, body);
23853
23854 /*
23855 * step 3: build the new loop, new step is always 1, disregard value of step[i]
23856 */
23857 SgExpression* incr_exp = buildPlusAssignOp(buildVarRefExp(ivar_name, scope), buildIntVal(1));
23858
23859 //Winnie, build the new conditional expression/ub
23860 SgExprStatement* cond_stmt = NULL;
23861 ub_exp = buildSubtractOp(ub_exp, buildIntVal(1));
23862 cond_stmt = buildExprStatement(buildLessOrEqualOp(buildVarRefExp(ivar_name,scope),copyExpression(ub_exp)));
23863 ROSE_ASSERT(cond_stmt != NULL);
23864
23865 SgForStatement* new_loop = buildForStatement(buildAssignStatement(clps_index_ref, buildIntVal(0)), cond_stmt,incr_exp, body); //Winnie, add in the new block!
23866 new_loop->set_parent(scope); //TODO: what's the correct parent?
23867
23868 replaceStatement(target_loop, new_loop);
23869
23870 target_loop = new_loop; //Winnie, so that transOmpLoop() can work on the collapsed loop
23871 // constant folding for the transformed AST
23872 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
23873
23874 delete [] ivar;
23875 delete [] lb;
23876 delete [] ub;
23877 delete [] step;
23878 delete [] orig_body;
23879 delete [] total_iters;
23880 delete [] interval;
23881 delete [] isPlus;
23882
23883 #endif
23884
23885 return new_var_list;
23886}
23887
23888
23889
23890bool
23892 {
23893 // DQ (3/4/2014): Added support for testing two trees for equivalents using the AST iterators.
23894
23895#ifndef USE_CMAKEx
23896 // DQ (3/8/2014): Make this conditionally compiled based on when CMake is not used because the libraries are not configured yet.
23897
23898 // This is AST container for the ROSE AST that will provide an iterator.
23899 // We want two iterators (one for the copy of the snippet and one for the
23900 // original snippet so that we can query the original snippet's AST
23901 // as we process each IR node of the AST for the copy of the snippet.
23902 // Only the copy of the snippet is inserted into the target AST.
23903 RoseAst ast_of_copy(tree1);
23904 RoseAst ast_of_original(tree2);
23905
23906 // printf ("ast_of_copy.size() = %" PRIuPTR " \n",ast_of_copy.size());
23907
23908 // Build the iterators so that we can increment thorugh both ASTs one IR node at a time.
23909 RoseAst::iterator i_copy = ast_of_copy.begin();
23910 RoseAst::iterator i_original = ast_of_original.begin();
23911
23912 // Iterate of the copy of the snippet's AST.
23913 while (i_copy != ast_of_copy.end())
23914 {
23915#if 0
23916 printf ("*i_copy = %p = %s \n",*i_copy,(*i_copy)->class_name().c_str());
23917 printf ("*i_original = %p = %s \n",*i_original,(*i_original)->class_name().c_str());
23918#endif
23919 // DQ (2/28/2014): This is a problem for some of the test codes (TEST store/load heap string [test7a] and [test7a])
23920 // ROSE_ASSERT((*i_copy)->variantT() == (*i_original)->variantT());
23921 if ((*i_copy)->variantT() != (*i_original)->variantT())
23922 {
23923#if 0
23924 printf ("ERROR: return from SageInterface::isStructurallyEquivalentAST(): (*i_copy)->variantT() != (*i_original)->variantT() \n");
23925#endif
23926#if 0
23927 printf ("Making this an error! \n");
23928 ROSE_ABORT();
23929#endif
23930 return false;
23931 }
23932
23933 i_copy++;
23934
23935 // Verify that we have not reached the end of the ast for the original (both the
23936 // copy and the original are the same structurally, and thus the same size).
23937 ROSE_ASSERT(i_original != ast_of_original.end());
23938 i_original++;
23939 }
23940
23941 // We have reached the end of both ASTs.
23942 ROSE_ASSERT(i_copy == ast_of_copy.end() && i_original == ast_of_original.end());
23943#endif
23944
23945 return true;
23946 }
23947
23948
23949#endif
23950
23952 SgForStatement * for_loop,
23953 SgVariableSymbol * & iterator,
23954 SgExpression * & lower_bound,
23955 SgExpression * & upper_bound,
23956 SgExpression * & stride
23957) {
23960
23961 iterator = NULL;
23962 lower_bound = NULL;
23963 upper_bound = NULL;
23964 stride = NULL;
23965
23966 SgForInitStatement * for_init_stmt = for_loop->get_for_init_stmt();
23967 const std::vector<SgStatement *> & init_stmts = for_init_stmt->get_init_stmt();
23968 assert(init_stmts.size() == 1);
23969 SgExprStatement * init_stmt = isSgExprStatement(init_stmts[0]);
23970 assert(init_stmt != NULL);
23971 SgExpression * init = init_stmt->get_expression();
23972
23973 SgAssignOp * assign_init = isSgAssignOp(init);
23974 assert(assign_init != NULL);
23975 SgVarRefExp * iterator_init_ref = isSgVarRefExp(assign_init->get_lhs_operand_i());
23976 assert(iterator_init_ref != NULL);
23977 iterator = iterator_init_ref->get_symbol();
23978 assert(iterator != NULL);
23979 lower_bound = assign_init->get_rhs_operand_i();
23980
23981 SgExprStatement * test_stmt = isSgExprStatement(for_loop->get_test());
23982 assert(test_stmt != NULL);
23983 SgExpression * test = test_stmt->get_expression();
23984 SgBinaryOp * bin_test = isSgBinaryOp(test);
23985 assert(bin_test);
23986
23987 SgExpression * lhs_exp = bin_test->get_lhs_operand_i();
23988 while (isSgCastExp(lhs_exp)) lhs_exp = ((SgCastExp *)lhs_exp)->get_operand_i();
23989 SgVarRefExp * lhs_var_ref = isSgVarRefExp(lhs_exp);
23990 bool lhs_it = (lhs_var_ref != NULL) && (lhs_var_ref->get_symbol() == iterator);
23991
23992 SgExpression * rhs_exp = bin_test->get_rhs_operand_i();
23993 while (isSgCastExp(rhs_exp)) rhs_exp = ((SgCastExp *)rhs_exp)->get_operand_i();
23994 SgVarRefExp * rhs_var_ref = isSgVarRefExp(rhs_exp);
23995#ifndef NDEBUG
23996 bool rhs_it = (rhs_var_ref != NULL) && (rhs_var_ref->get_symbol() == iterator);
23997
23998// DQ (4/21/2016): Replacing use of bitwise xor with something more approriate for logical types.
23999// Note that the xor logica operator does not exist in C/C++ and that this is a case of using the
24000// bitwise xor operator on boolean values (not a great idea). Note that logical "a xor b" is
24001// equivalent to "!a != !b" the use of "!" only make sure that the "!=" is applied to a boolean
24002// value. Since these are boolean typed values we can use "a != b", directly.
24003// assert(lhs_it xor rhs_it);
24004 assert(lhs_it != rhs_it);
24005#endif
24006
24007 upper_bound = lhs_it ? bin_test->get_rhs_operand_i() : bin_test->get_lhs_operand_i();
24008
24009 bool inclusive;
24010 bool reversed;
24011
24012 switch (test->variantT()) {
24013 case V_SgGreaterOrEqualOp:
24014 inclusive = lhs_it;
24015 reversed = lhs_it;
24016 break;
24017 case V_SgGreaterThanOp:
24018 inclusive = !lhs_it;
24019 reversed = lhs_it;
24020 break;
24021 case V_SgLessOrEqualOp:
24022 inclusive = lhs_it;
24023 reversed = !lhs_it;
24024 break;
24025 case V_SgLessThanOp:
24026 inclusive = !lhs_it;
24027 reversed = !lhs_it;
24028 break;
24029 case V_SgEqualityOp:
24030 case V_SgNotEqualOp:
24031 default:
24032 ROSE_ABORT();
24033 }
24034
24035 SgExpression * increment = for_loop->get_increment();
24036 switch (increment->variantT()) {
24037 case V_SgPlusPlusOp:
24038 assert(!reversed);
24039 stride = SageBuilder::buildIntVal(1);
24040 break;
24041 case V_SgMinusMinusOp:
24042 assert(reversed);
24043 stride = SageBuilder::buildIntVal(-1);
24044 break;
24045 case V_SgPlusAssignOp:
24046 {
24047 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
24048#ifndef NDEBUG
24049 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
24050 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
24051#endif
24052 stride = bin_op->get_rhs_operand_i();
24053 break;
24054 }
24055 case V_SgMinusAssignOp:
24056 {
24057 SgBinaryOp * bin_op = (SgBinaryOp *)increment;
24058#ifndef NDEBUG
24059 SgVarRefExp * var_ref_lhs = isSgVarRefExp(bin_op->get_lhs_operand_i());
24060 assert(var_ref_lhs != NULL && var_ref_lhs->get_symbol() == iterator);
24061#endif
24062 stride = bin_op->get_rhs_operand_i();
24063 break;
24064 }
24065 case V_SgAssignOp:
24066 {
24067 SgAssignOp * assign_op = (SgAssignOp *)increment;
24068#ifndef NDEBUG
24069 SgVarRefExp * inc_assign_lhs = isSgVarRefExp(assign_op->get_lhs_operand_i());
24070 assert(inc_assign_lhs != NULL && inc_assign_lhs->get_symbol() == iterator);
24071#endif
24072 SgBinaryOp * inc_assign_rhs = isSgBinaryOp(assign_op->get_rhs_operand_i());
24073 assert(inc_assign_rhs != NULL);
24074 SgVarRefExp * inc_assign_rhs_lhs = isSgVarRefExp(inc_assign_rhs->get_lhs_operand_i());
24075 if (inc_assign_rhs_lhs != NULL && inc_assign_rhs_lhs->get_symbol() == iterator)
24076 stride = inc_assign_rhs->get_rhs_operand_i();
24077 SgVarRefExp * inc_assign_rhs_rhs = isSgVarRefExp(inc_assign_rhs->get_rhs_operand_i());
24078 if (inc_assign_rhs_rhs != NULL && inc_assign_rhs_rhs->get_symbol() == iterator)
24079 stride = inc_assign_rhs->get_lhs_operand_i();
24080 break;
24081 }
24082 default:
24083 ROSE_ABORT();
24084 }
24085
24086 // DQ (7/19/2015): Added braces to avoid compiler warning about ambigious "else" case.
24087 if (!inclusive)
24088 {
24089 if (reversed)
24090 upper_bound = SageBuilder::buildAddOp(upper_bound, SageBuilder::buildIntVal(1));
24091 else
24092 upper_bound = SageBuilder::buildSubtractOp(upper_bound, SageBuilder::buildIntVal(1));
24093 }
24094
24095 return true;
24096}
24097
24098//------------------------------------------------------------------------------
24099#ifdef ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24100//------------------------------------------------------------------------------
24101
24106 jstring temp_directory = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(::currentJavaTraversalClass, Rose::Frontend::Java::Ecj::getTempDirectoryMethod);
24107
24108 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_directory, NULL);
24109 ROSE_ASSERT(utf8);
24110 string directory_name = utf8;
24111 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_directory, utf8);
24112
24113 list<string> sourcepath = project -> get_Java_sourcepath();
24114 sourcepath.push_back(directory_name); // push it in the back because it should have lower priority
24115 project -> set_Java_sourcepath(sourcepath);
24116
24117 return directory_name;
24118}
24119
24120
24124void SageInterface::destroyTempDirectory(string directory_name) {
24125 string command = string("rm -fr ") + directory_name;
24126 int status = system(command.c_str());
24127 ROSE_ASSERT(status == 0);
24128}
24129
24130
24134SgFile* SageInterface::processFile(SgProject *project, string filename, bool unparse /* = false */) {
24135 //
24136 // Set up the new source file for processing "a la Rose".
24137 //
24138 project -> get_sourceFileNameList().push_back(filename);
24139 Rose_STL_Container<std::string> arg_list = project -> get_originalCommandLineArgumentList();
24140 arg_list.push_back(filename);
24141 Rose_STL_Container<string> fileList = CommandlineProcessing::generateSourceFilenames(arg_list, false);
24142 CommandlineProcessing::removeAllFileNamesExcept(arg_list, fileList, filename);
24143 int error_code = 0; // need this because determineFileType takes a reference "error_code" argument.
24144 SgFile *file = determineFileType(arg_list, error_code, project);
24145 SgSourceFile *sourcefile = isSgSourceFile(file);
24146 ROSE_ASSERT(sourcefile);
24147 sourcefile -> set_parent(project);
24148
24149 //
24150 // Insert the file into the list of files in the project.
24151 //
24152 project -> get_fileList_ptr() -> get_listOfFiles().push_back(sourcefile);
24153 ROSE_ASSERT(sourcefile == isSgSourceFile((*project)[filename]));
24154
24155 sourcefile -> build_Java_AST(arg_list, project -> get_originalCommandLineArgumentList());
24156
24157 if (! unparse) { // if we are not supposed to unparse this file,
24158 project -> get_fileList_ptr() -> get_listOfFiles().pop_back(); // remove it from the list of files in the project
24159 ROSE_ASSERT(sourcefile != isSgSourceFile((*project)[filename]));
24160 }
24161
24162 // DQ (7/2/2020): Added assertion (fails for snippet tests).
24163 ROSE_ASSERT(file->get_preprocessorDirectivesAndCommentsList() != NULL);
24164
24165 return file;
24166}
24167
24168
24173string SageInterface::preprocessPackage(SgProject *project, string package_name) {
24174 string command = "package " + package_name + ";";
24175
24176 //
24177 // Call the Java side to create an input file with the relevant package statement; translate the file and return the file name.
24178 //
24179 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24180 Rose::Frontend::Java::Ecj::createTempFileMethod,
24181 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
24182
24183 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24184 ROSE_ASSERT(utf8);
24185 string filename = (string) utf8;
24186 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24187
24188 processFile(project, filename); // translate the file
24189
24190 return package_name;
24191}
24192
24193
24198string SageInterface::preprocessImport(SgProject *project, string import_string) {
24199 string command = "import " + import_string + ";";
24200
24201 //
24202 // Call the Java side to create an input file with the relevant import statement.
24203 //
24204 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24205 Rose::Frontend::Java::Ecj::createTempFileMethod,
24206 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(command.c_str()));
24207
24208 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24209 ROSE_ASSERT(utf8);
24210 string filename = (string) utf8;
24211 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24212
24213 processFile(project, filename); // translate the file
24214
24215 return import_string;
24216}
24217
24218
24223SgFile* SageInterface::preprocessCompilationUnit(SgProject *project, string file_name, string file_content, bool unparse /* true */) {
24224 //
24225 // Call the Java side to create an input file with the relevant import statement.
24226 //
24227 jstring temp_file = (jstring) Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24228 Rose::Frontend::Java::Ecj::createTempNamedFileMethod,
24229 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_name.c_str()),
24230 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(file_content.c_str()));
24231
24232 const char *utf8 = Rose::Frontend::Java::Ecj::currentEnvironment -> GetStringUTFChars(temp_file, NULL);
24233 ROSE_ASSERT(utf8);
24234 string filename = (string) utf8;
24235 Rose::Frontend::Java::Ecj::currentEnvironment -> ReleaseStringUTFChars(temp_file, utf8);
24236
24237 return processFile(project, filename, unparse); // translate the file and unparse it, if requested (unparse=true is the default).
24238}
24239
24240
24245 ROSE_ASSERT(scope);
24246 SgClassDefinition *package_definition = NULL;
24247 for (int index = 0, length = package_name.size(); index < length; index++) {
24248 int n;
24249 for (n = index; n < length; n++) {
24250 if (package_name[n] == '.') {
24251 break;
24252 }
24253 }
24254 string name = package_name.substr(index, n - index);
24255
24256 SgClassSymbol *package_symbol = scope -> lookup_class_symbol(name);
24257 if (package_symbol == NULL) { // package not found?
24258 return NULL;
24259 }
24260
24261 SgJavaPackageDeclaration *package_declaration = isSgJavaPackageDeclaration(package_symbol -> get_declaration() -> get_definingDeclaration());
24262 ROSE_ASSERT(package_declaration);
24263 package_definition = package_declaration -> get_definition();
24264 ROSE_ASSERT(package_definition);
24265 scope = package_definition;
24266
24267 index = n;
24268 }
24269
24270 return package_definition;
24271}
24272
24273
24277SgClassDefinition *SageInterface::findOrInsertJavaPackage(SgProject *project, string package_name, bool create_directory /* = false */) {
24278 SgGlobal *global_scope = project -> get_globalScopeAcrossFiles();
24279 SgClassDefinition *package_definition = findJavaPackage(global_scope, package_name);
24280 if (package_definition == NULL) { // try again after loading the package
24281 preprocessPackage(project, package_name);
24282
24283 //
24284 // If requested, Create the directory associated with this package_name.
24285 //
24286 if (create_directory) {
24287 Rose::Frontend::Java::Ecj::currentEnvironment -> CallObjectMethod(Rose::Frontend::Java::Ecj::currentJavaTraversalClass,
24288 Rose::Frontend::Java::Ecj::createTempNamedDirectoryMethod,
24289 Rose::Frontend::Java::Ecj::currentEnvironment -> NewStringUTF(package_name.c_str()));
24290 }
24291
24292 package_definition = findJavaPackage(global_scope, package_name);
24293 }
24294
24295 return package_definition;
24296}
24297
24302 ROSE_ASSERT(package_definition);
24303 SgClassSymbol *class_symbol = package_definition -> lookup_class_symbol(class_name);
24304 SgClassDeclaration *class_declaration = (class_symbol == NULL
24305 ? NULL
24306 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24307 if ((! class_declaration) || (! class_declaration -> attributeExists("complete"))) { // class not available in the scope
24308 string qualified_name = package_definition -> get_qualified_name().getString() + "." + class_name;
24309 preprocessImport(project, qualified_name);
24310 class_symbol = package_definition -> lookup_class_symbol(class_name);
24311 }
24312
24313 class_declaration = (class_symbol == NULL
24314 ? NULL
24315 : isSgClassDeclaration(class_symbol -> get_declaration() -> get_definingDeclaration()));
24316
24317 return class_declaration;
24318}
24319
24320
24324SgClassDeclaration *SageInterface::findOrImportJavaClass(SgProject *project, string package_name, string class_name) {
24325 return findOrImportJavaClass(project, findOrInsertJavaPackage(project, package_name, false), class_name);
24326}
24327
24328
24333 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24334 ROSE_ASSERT(class_declaration);
24335 SgClassDefinition *scope = isSgClassDefinition(class_declaration -> get_scope());
24336 while (scope && (! isSgJavaPackageDeclaration(scope -> get_parent()))) {
24337 class_declaration = isSgClassDeclaration(scope -> get_parent());
24338 ROSE_ASSERT(class_declaration);
24339 scope = isSgClassDefinition(class_declaration -> get_scope());
24340 }
24341
24342 if (! scope) { // a local type !!!
24343 return NULL;
24344 }
24345
24346 string class_name = class_declaration -> get_name().getString();
24347 return findOrImportJavaClass(project, scope, class_name);
24348}
24349
24350
24355 ROSE_ASSERT(class_definition);
24357 ROSE_ASSERT(type_list);
24358 SgArrayType *string_array_type = getUniqueJavaArrayType(Rose::Frontend::Java::StringClassType, 1);
24359 ROSE_ASSERT(string_array_type);
24360 type_list -> append_argument(string_array_type);
24361
24362 // DQ (1/11/2020): Fixing support for C++11 l-value and r-value reference modifiers for member functions.
24363 // SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, 0);
24364 SgFunctionType *member_function_type = SageBuilder::buildMemberFunctionType(SgTypeVoid::createType(), type_list, class_definition, /* mfunc_specifier */ 0);
24365
24366 SgFunctionSymbol *method_symbol = class_definition -> lookup_function_symbol("main", member_function_type);
24367 delete type_list;
24368 return (method_symbol == NULL ? NULL : isSgMemberFunctionDeclaration(method_symbol -> get_declaration()));
24369}
24370
24371
24376 SgClassDeclaration *class_declaration = isSgClassDeclaration(class_type -> get_declaration() -> get_definingDeclaration());
24377 ROSE_ASSERT(class_declaration);
24378 SgClassDefinition *class_definition = class_declaration -> get_definition();
24379 return findJavaMain(class_definition);
24380}
24381
24382//------------------------------------------------------------------------------
24383#endif // ROSE_BUILD_JAVA_LANGUAGE_SUPPORT
24384//------------------------------------------------------------------------------
24385
24387// Essentially replace variable a with b.
24389{
24390 ROSE_ASSERT (old_sym != NULL);
24391 ROSE_ASSERT (new_sym != NULL);
24392 ROSE_ASSERT (old_sym != new_sym);
24393 ROSE_ASSERT (scope != NULL);
24394
24395 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(scope, V_SgVarRefExp);
24396 for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++)
24397 {
24398 SgVarRefExp *vRef = isSgVarRefExp(*i);
24399 if (vRef->get_symbol() == old_sym)
24400 vRef->set_symbol(new_sym);
24401 }
24402}
24403
24404
24405// 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.
24410bool
24412 {
24413 bool result = true;
24414
24415 bool includingSelf = false;
24416 SgSourceFile* sourceFile = getEnclosingSourceFile(stmt,includingSelf);
24417
24418 if (sourceFile == NULL)
24419 {
24420 printf ("In SageInterface::statementCanBeTransformed(): sourceFile not found \n");
24421 }
24422
24423 // I think we can assert this!
24424 ROSE_ASSERT(sourceFile != NULL);
24425
24426 if (sourceFile != NULL && sourceFile->get_unparse_tokens() == true && sourceFile->get_unparseHeaderFiles() == true)
24427 {
24428 // Need to look up the source file name, find the SgIncludeFile, and check if statements from this file can be transformed.
24429 // 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.
24430 string source_filename = stmt->getFilenameString();
24431#if 0
24432 printf ("In SageInterface::statementCanBeTransformed(): source_filename = %s \n",source_filename.c_str());
24433 printf (" --- Rose::includeFileMapForUnparsing.size() = %zu \n",Rose::includeFileMapForUnparsing.size());
24434#endif
24435
24436 // DQ (11/5/2019): Using the edg_include_file_map instead (constructed in EDG/ROSE translation).
24437 if (EDG_ROSE_Translation::edg_include_file_map.find(source_filename) != EDG_ROSE_Translation::edg_include_file_map.end())
24438 {
24439 SgIncludeFile* include_file = EDG_ROSE_Translation::edg_include_file_map[source_filename];
24440 ROSE_ASSERT(include_file != NULL);
24441#if 0
24442 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");
24443#endif
24444 if (include_file->get_can_be_supported_using_token_based_unparsing() == false)
24445 {
24446#if 0
24447 printf ("NOTE: Transformations of this statement cannot be supported using the header file unparsing with token unparsing options! \n");
24448#endif
24449 result = false;
24450 }
24451 }
24452 else
24453 {
24454 // DQ (5/13/2021): I think that the default (returing true) will work well.
24455 // This is likely just the original input source file (not a header file).
24456#if 0
24457 printf ("Not found in Rose::includeFileMapForUnparsing: source_filename = %s \n",source_filename.c_str());
24458#endif
24459#if 0
24460 printf ("Exiting as a test! \n");
24461 ROSE_ABORT();
24462#endif
24463 }
24464
24465#if 0
24466 printf ("Error: In statementCanBeTransformed(): this might be an issue! \n");
24467 ROSE_ABORT();
24468#endif
24469 }
24470
24471 return result;
24472 }
24473
24474
24475//Note: this function is no longer used by decl move tool: we use copy and insert instead to support moving to multiple scopes
24478{
24479 ROSE_ASSERT (decl!= NULL);
24480 ROSE_ASSERT (target_scope != NULL);
24481 ROSE_ASSERT (target_scope != decl->get_scope());
24482
24483#if 0 // at this stage, we focus on legal move only, any scope adjustment should be done earlier!
24484 // Special handling for If-Stmt, may need to climb up one level of scope when:
24485 // two bodies of if uses the same variable, but cannot be pushed down into each body.
24486 // If-stmt will be the innermost common scope for the variable.
24487 // But we should not move the declaration to if-stmt. We can only move it to the parent scope of if-stmt.
24488 if (isSgIfStmt (target_scope))
24489 {
24490 target_scope = SageInterface::getEnclosingScope (target_scope, false);
24491 if (target_scope == )
24492 }
24493# endif
24494
24495 // Move the declaration
24496 //TODO: consider another way: copy the declaration, insert the copy, replace varRefExp, and remove (delete) the original declaration
24498
24499 switch (target_scope->variantT())
24500 {
24501 case V_SgBasicBlock:
24502 {
24503 SageInterface::prependStatement (decl, target_scope);
24504 break;
24505 }
24506#if 0 // this check should be done earlier before any side effects can happen
24507 case V_SgIfStmt:
24508 {
24509 // adjust to parent scope of if-stmt
24510 break;
24511 }
24512#endif
24513 case V_SgForStatement:
24514 {
24515 // we move int i; to be for (int i=0; ...);
24516 SgForStatement* stmt = isSgForStatement (target_scope);
24517 ROSE_ASSERT(stmt != NULL);
24518 SgStatementPtrList& stmt_list = stmt->get_init_stmt();
24519 // Try to match a pattern like for (i=0; ...) here
24520 // assuming there is only one assignment like i=0
24521 // We don't yet handle more complex cases
24522 if (stmt_list.size() !=1)
24523 {
24524 cerr<<"Error in moveVariableDeclaration(): only single init statement is handled for SgForStatement now."<<endl;
24525 ROSE_ASSERT (stmt_list.size() ==1);
24526 }
24527 SgExprStatement* exp_stmt = isSgExprStatement(stmt_list[0]);
24528 ROSE_ASSERT (exp_stmt != NULL);
24529 SgAssignOp* assign_op = isSgAssignOp(exp_stmt->get_expression());
24530 ROSE_ASSERT (assign_op != NULL);
24531
24532 // remove the existing i=0; preserve its right hand operand
24534 stmt_list.clear();
24535 SageInterface::deepDelete (exp_stmt);
24536
24537 // modify the decl's rhs to be the new one
24540 if (init_name->get_initptr() != NULL)
24541 SageInterface::deepDelete (init_name->get_initptr());
24542 init_name->set_initptr(initor);
24543 initor->set_parent(init_name);
24544
24545 stmt_list.insert (stmt_list.begin(), decl );
24546 break;
24547 }
24548
24549 default:
24550 {
24551 cerr<<"Error. Unhandled target scope type:"<<target_scope->class_name()<<endl;
24552 ROSE_ASSERT (false);
24553 }
24554 }
24555
24556 //make sure the symbol is moved also since prependStatement() (in fact fixVariableDeclaration()) does not handle this detail.
24558 ROSE_ASSERT(sym != NULL);
24559 SgScopeStatement* orig_scope = sym->get_scope();
24560 if (orig_scope != target_scope)
24561 {
24562 // SageInterface::fixVariableDeclaration() cannot switch the scope for init name.
24563 // it somehow always reuses previously associated scope.
24565 init_name->set_scope(target_scope);
24566 SgName sname = sym->get_name();
24567 orig_scope->remove_symbol(sym);
24568 target_scope->insert_symbol(sname, sym);
24569 }
24570 // This is difficult since C++ variables have namespaces
24571 // Details are in SageInterface::fixVariableDeclaration()
24572 ROSE_ASSERT (target_scope->symbol_exists(sym));
24573}
24574
24575class SimpleExpressionEvaluator: public AstBottomUpProcessing <struct SageInterface::const_int_expr_t> {
24576 public:
24578 }
24579
24580 struct SageInterface::const_int_expr_t getValueExpressionValue(SgValueExp *valExp) {
24581 struct SageInterface::const_int_expr_t subtreeVal;
24582 subtreeVal.hasValue_ = true;
24583
24584 if (isSgIntVal(valExp)) {
24585 subtreeVal.value_ = isSgIntVal(valExp)->get_value();
24586 } else if (isSgLongIntVal(valExp)) {
24587 subtreeVal.value_ = isSgLongIntVal(valExp)->get_value();
24588 } else if (isSgLongLongIntVal(valExp)) {
24589 subtreeVal.value_ = isSgLongLongIntVal(valExp)->get_value();
24590 } else if (isSgShortVal(valExp)) {
24591 subtreeVal.value_ = isSgShortVal(valExp)->get_value();
24592 } else if (isSgUnsignedIntVal(valExp)) {
24593 subtreeVal.value_ = isSgUnsignedIntVal(valExp)->get_value();
24594 } else if (isSgUnsignedLongVal(valExp)) {
24595 subtreeVal.value_ = isSgUnsignedLongVal(valExp)->get_value();
24596 } else if (isSgUnsignedLongLongIntVal(valExp)) {
24597 subtreeVal.value_ = isSgUnsignedLongLongIntVal(valExp)->get_value();
24598 } else if (isSgUnsignedShortVal(valExp)) {
24599 subtreeVal.value_ = isSgUnsignedShortVal(valExp)->get_value();
24600 }
24601 return subtreeVal;
24602 }
24603
24604 struct SageInterface::const_int_expr_t evaluateVariableReference(SgVarRefExp *vRef) {
24605 if (isSgModifierType(vRef->get_type()) == NULL) {
24607 val.value_ = -1;
24608 val.hasValue_ = false;
24609 return val;
24610 }
24611 if (isSgModifierType(vRef->get_type())->get_typeModifier().get_constVolatileModifier().isConst()) {
24612 // We know that the var value is const, so get the initialized name and evaluate it
24613 SgVariableSymbol *sym = vRef->get_symbol();
24614 SgInitializedName *iName = sym->get_declaration();
24615 SgInitializer *ini = iName->get_initializer();
24616
24617 if (isSgAssignInitializer(ini)) {
24618 SgAssignInitializer *initializer = isSgAssignInitializer(ini);
24619 SgExpression *rhs = initializer->get_operand();
24620 SimpleExpressionEvaluator variableEval;
24621
24622 return variableEval.traverse(rhs);
24623 }
24624 }
24626 val.hasValue_ = false;
24627 val.value_ = -1;
24628 return val;
24629 }
24630
24631 struct SageInterface::const_int_expr_t evaluateSynthesizedAttribute(SgNode *node, SynthesizedAttributesList synList) {
24632 if (isSgExpression(node) != NULL) {
24633 SgValueExp* valueExp = isSgValueExp(node);
24634 if (valueExp != NULL) {
24635 return this->getValueExpressionValue(valueExp);
24636 }
24637
24638 SgVarRefExp* varRefExp = isSgVarRefExp(node);
24639 if (varRefExp != NULL) {
24640 // std::cout << "Hit variable reference expression!" << std::endl;
24641 return evaluateVariableReference(varRefExp);
24642 }
24643 // Early break out for assign initializer // other possibility?
24644 if (isSgAssignInitializer(node)) {
24645 if(synList.at(0).hasValue_){
24646 return synList.at(0);
24647 } else {
24649 val.value_ = -1;
24650 val.hasValue_ = false;
24651 return val;
24652 }
24653 }
24654 struct SageInterface::const_int_expr_t evaluatedValue;
24655 evaluatedValue.hasValue_ = false;
24656 evaluatedValue.value_ = -1;
24657#if 0
24658 if(synList.size() != 2){
24659 for(SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it){
24660 std::cout << "Node: " << node->unparseToString() << "\n" << (*it).value_ << std::endl;
24661 std::cout << "Parent: " << node->get_parent()->unparseToString() << std::endl;
24662 std::cout << "Parent, Parent: " << node->get_parent()->get_parent()->unparseToString() << std::endl;
24663 }
24664 }
24665#endif
24666 for (SynthesizedAttributesList::iterator it = synList.begin(); it != synList.end(); ++it) {
24667 if((*it).hasValue_){
24668 if (isSgAddOp(node)) {
24669 assert(synList.size() == 2);
24670 evaluatedValue.value_ = synList[0].value_ + synList[1].value_ ;
24671 evaluatedValue.hasValue_ = true;
24672 } else if (isSgSubtractOp(node)) {
24673 assert(synList.size() == 2);
24674 evaluatedValue.value_ = synList[0].value_ - synList[1].value_ ;
24675 evaluatedValue.hasValue_ = true;
24676 } else if (isSgMultiplyOp(node)) {
24677 assert(synList.size() == 2);
24678 evaluatedValue.value_ = synList[0].value_ * synList[1].value_ ;
24679 evaluatedValue.hasValue_ = true;
24680 } else if (isSgDivideOp(node)) {
24681 assert(synList.size() == 2);
24682 evaluatedValue.value_ = synList[0].value_ / synList[1].value_ ;
24683 evaluatedValue.hasValue_ = true;
24684 } else if (isSgModOp(node)) {
24685 assert(synList.size() == 2);
24686 evaluatedValue.value_ = synList[0].value_ % synList[1].value_ ;
24687 evaluatedValue.hasValue_ = true;
24688 }
24689 } else {
24690 std::cerr << "Expression is not evaluatable" << std::endl;
24691 evaluatedValue.hasValue_ = false;
24692 evaluatedValue.value_ = -1;
24693 return evaluatedValue;
24694 }
24695 }
24696 evaluatedValue.hasValue_ = true;
24697 return evaluatedValue;
24698 }
24699 struct SageInterface::const_int_expr_t evaluatedValue;
24700 evaluatedValue.hasValue_ = false;
24701 evaluatedValue.value_ = -1;
24702 return evaluatedValue;
24703 }
24704};
24705
24709 return eval.traverse(expr);
24710}
24711
24712bool
24714
24715 class TypeEquivalenceChecker {
24716 public:
24717 TypeEquivalenceChecker(bool profile, bool useSemanticEquivalence)
24718 : profile_(profile), useSemanticEquivalence_(useSemanticEquivalence),
24719 namedType_(0), pointerType_(0), arrayType_(0), functionType_(0)
24720 {
24721 }
24722
24723 SgNode * getBasetypeIfApplicable(SgNode *t){
24724 SgNode * node = t;
24725 if (isSgTypedefType(t)) {
24726// std::cout << "This is a typedef nodeT1. We strip everything away and compare the hidden types." << std::endl;
24727 node = isSgTypedefType(t)->stripType(SgType::STRIP_TYPEDEF_TYPE);
24728 }
24729 if(useSemanticEquivalence_){
24730 if(isSgModifierType(t)){
24731 SgModifierType *modType = isSgModifierType(t);
24732 ROSE_ASSERT(modType != NULL);
24733 // We need to check for Volatile/Restrict types. These are modelled as ModifierTypes, but are equal (in some cases)
24734 // volatile seems to make no difference for basic (built in) types like int, bool etc. But it has an impact on types
24735 // like classes
24736 // restrict seems to have no impact on the type itself.
24737 if(SageInterface::isVolatileType(modType)){
24738 // handle volatile case
24739 std::cout << "Hit volatile type, stripping of modifier type" << std::endl;
24740 node = modType->get_base_type();
24741 }
24742 if(SageInterface::isRestrictType(modType)){
24743 // handle restrict case
24744 std::cout << "Hit restrict type, stripping of modifier type" << std::endl;
24745 node = modType->get_base_type();
24746 }
24747 }
24748 }
24749 ROSE_ASSERT(node != NULL);
24750 return node;
24751}
24752
24753bool typesAreEqual(SgType *t1, SgType *t2) {
24754 bool equal = false;
24755 if(t1 == NULL || t2 == NULL){
24756 std::string wasNull;
24757 if(t1 == NULL){
24758 wasNull = "t1";
24759 } else {
24760 wasNull = "t2";
24761 }
24762 std::cerr << "ERROR: " << wasNull << " was NULL" << std::endl;
24763 return equal;
24764 }
24765 // if both pointers point to same location the types MUST be equal!
24766 if(t1 == t2){
24767// std::cout << "Pointers are equal, returning true" << std::endl;
24768 return true;
24769 }
24770#ifndef USE_CMAKEx
24771 RoseAst subT1(t1);
24772 RoseAst subT2(t2);
24773
24774 for (RoseAst::iterator i = subT1.begin(), j = subT2.begin();
24775 i != subT1.end() && j != subT2.end(); ++i, ++j) {
24776 SgNode *nodeT1 = *i;
24777 SgNode *nodeT2 = *j;
24778
24779// std::cout << "nodeT1: " << nodeT1->class_name() << " nodeT2: " << nodeT2->class_name() << std::endl;
24780 nodeT1 = getBasetypeIfApplicable(nodeT1);
24781 nodeT2 = getBasetypeIfApplicable(nodeT2);
24782
24783 if (nodeT1->variantT() == nodeT2->variantT()) {
24784// std::cout << "variantT is the same" << std::endl;
24785 if(isSgModifierType(nodeT1)){
24786 // we need to check whether the modifier is the same or not
24787 SgTypeModifier modT1 = isSgModifierType(nodeT1)->get_typeModifier();
24788 SgTypeModifier modT2 = isSgModifierType(nodeT2)->get_typeModifier();
24789 if(modT1.get_constVolatileModifier().isConst() != modT2.get_constVolatileModifier().isConst()){
24790 return false;
24791 }
24792 if(modT1.get_constVolatileModifier().isVolatile() != modT2.get_constVolatileModifier().isVolatile()){
24793 return false;
24794 }
24795 } else if (isSgNamedType(nodeT1)) { // Two different names -> Must be two different things
24796 if (profile_) {
24797 namedType_++;
24798 }
24799 i.skipChildrenOnForward();
24800 j.skipChildrenOnForward();
24801 SgNamedType *c1 = isSgNamedType(nodeT1);
24802 SgNamedType *c2 = isSgNamedType(nodeT2);
24803
24804 // XXX A function to check whether a named type is anonymous or not would speed
24805 // up this check, since we could get rid of this string compare.
24806 if(!c1->get_autonomous_declaration()){
24807 return false;
24808 }
24809 if (!c2->get_autonomous_declaration()){
24810 return false;
24811 }
24812 if (c1->get_qualified_name() == c2->get_qualified_name()) {
24813 return true;
24814 } else {
24815 return false;
24816 }
24817
24818 } else if (isSgPointerType(nodeT1)) {
24819 if (profile_) {
24820 pointerType_++;
24821 }
24822 SgPointerType *t1 = isSgPointerType(nodeT1);
24823 SgPointerType *t2 = isSgPointerType(nodeT2);
24824
24825 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24826
24827 } else if(isSgReferenceType(nodeT1)){
24828 SgReferenceType *t1 = isSgReferenceType(nodeT1);
24829 SgReferenceType *t2 = isSgReferenceType(nodeT2);
24830
24831 return typesAreEqual(t1->get_base_type(), t2->get_base_type());
24832 } else if (isSgArrayType(nodeT1)) {
24833 if (profile_) {
24834 arrayType_++;
24835 }
24836 SgArrayType *a1 = isSgArrayType(nodeT1);
24837 SgArrayType *a2 = isSgArrayType(nodeT2);
24838
24839 bool arrayBaseIsEqual = typesAreEqual(a1->get_base_type(), a2->get_base_type());
24840
24843 bool arrayIndexExpressionIsEquivalent = false;
24844 if(t1Index.hasValue_ && t2Index.hasValue_){
24845 if(t1Index.value_ == t2Index.value_){
24846 arrayIndexExpressionIsEquivalent = true;
24847 }
24848 }
24849 bool arraysAreEqual = (arrayBaseIsEqual && arrayIndexExpressionIsEquivalent);
24850 return arraysAreEqual;
24851 } else if (isSgFunctionType(nodeT1)) {
24852 if(profile_) {
24853 functionType_++;
24854 }
24855 SgFunctionType *funcTypeA = isSgFunctionType(nodeT1);
24856 SgFunctionType *funcTypeB = isSgFunctionType(nodeT2);
24857// std::cout << "Inside SgFunctionType" << std::endl;
24858// assert(funcTypeA != funcTypeB);
24859 if(typesAreEqual(funcTypeA->get_return_type(), funcTypeB->get_return_type())) {
24860 // If functions don't have the same number of arguments, they are not type-equal
24861 if(funcTypeA->get_arguments().size() != funcTypeB->get_arguments().size()) {
24862 return false;
24863 }
24864 // This should always be the same as the if before...
24865 if(funcTypeA->get_argument_list()->get_arguments().size() != funcTypeB->get_argument_list()->get_arguments().size()){
24866 return false;
24867 }
24868
24869 for(SgTypePtrList::const_iterator ii = funcTypeA->get_arguments().begin(),
24870 jj = funcTypeB->get_arguments().begin();
24871 ii != funcTypeA->get_arguments().end() &&
24872 jj != funcTypeB->get_arguments().end();
24873 ++ii, ++jj) {
24874// std::cout << (*ii)->class_name() << " " << (*jj)->class_name() << std::endl;
24875 // For all argument types check whether they are equal
24876 if(!typesAreEqual((*ii), (*jj))) {
24877 return false;
24878 }
24879 }
24880 return true;
24881 }
24882 return false;
24883 } else {
24884 // We don't have a named type, pointer type or array type, so they are equal
24885 // This is for the primitive type - case
24886 return true;
24887 }
24888 } else {
24889 // In this case the types are not equal, since its variantT is not equal.
24890 return false;
24891 }
24892 }
24893 // this should be unreachable code...
24894 return equal;
24895#else
24896 std::cerr << "This feature for now is available with autotools only!" << std::endl;
24897 ROSE_ABORT();
24898#endif
24899}
24900
24901int getNamedTypeCount() {
24902 return namedType_;
24903}
24904
24905int getPointerTypeCount() {
24906 return pointerType_;
24907}
24908
24909int getArrayTypeCount() {
24910 return arrayType_;
24911}
24912
24913int getFunctionTypeCount() {
24914 return functionType_;
24915}
24916 private:
24917// SgNode * getBasetypeIfApplicable(SgNode *t);
24918 bool profile_, useSemanticEquivalence_;
24919 int namedType_, pointerType_, arrayType_, functionType_;
24920};
24921
24922TypeEquivalenceChecker tec(false, false);
24923return tec.typesAreEqual(typeA, typeB);
24924}
24925
24926
24927std::set<SgStatement*>
24929 {
24930 // DQ (6/11/2015): This reports the statements that are marked as transformed.
24931 // It is useful for debugging the token-based unparsing.
24932
24933 class StatementTraversal : public AstSimpleProcessing
24934 {
24935 public:
24936 StatementTraversal() : count (0) {}
24937 void visit (SgNode* node)
24938 {
24939 SgStatement* statement = isSgStatement(node);
24940 if (statement != nullptr && statement->isTransformation() == true)
24941 {
24942 returnset.insert(statement);
24943 count++;
24944 }
24945 }
24946
24947 int count; // running total of statements found marked as transformations in the input AST
24948 std::set<SgStatement*> returnset;
24949 };
24950
24951 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24952 StatementTraversal traversal;
24953 traversal.traverse(node, preorder);
24954
24955 return traversal.returnset;
24956 }
24957
24958std::set<SgStatement*>
24960 {
24961 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
24962 // It is useful for debugging the token-based unparsing.
24963
24964#if 1
24965 printf ("In collectModifiedStatements(): node = %p = %s \n",node,node->class_name().c_str());
24966#endif
24967
24968 class StatementTraversal : public AstSimpleProcessing
24969 {
24970 public:
24971 StatementTraversal() : count (0) {}
24972 void visit (SgNode* node)
24973 {
24974 SgStatement* statement = isSgStatement(node);
24975 if (statement != NULL && statement->get_isModified() == true)
24976 {
24977 returnset.insert(statement);
24978 count++;
24979 }
24980 }
24981
24982 int count; // running total of statements found marked as transformations in the input AST
24983 std::set<SgStatement*> returnset;
24984 };
24985
24986 // Now buid the traveral object and call the traversal (preorder) on the function definition.
24987 StatementTraversal traversal;
24988 traversal.traverse(node, preorder);
24989
24990 return traversal.returnset;
24991 }
24992
24993
24994void
24996 {
24997 // DQ (12/2/2019): This reports the file id values of all located nodes in the AST subtree represented by the input node.
24998
24999#if 0
25000 printf ("In outputFileIds(): node = %p = %s \n",node,node->class_name().c_str());
25001#endif
25002
25003 class LocatedNodeTraversal : public AstSimpleProcessing
25004 {
25005 public:
25006 LocatedNodeTraversal() {}
25007 void visit (SgNode* node)
25008 {
25009 SgLocatedNode* locatedNode = isSgLocatedNode(node);
25010 if (locatedNode != NULL)
25011 {
25012#if 0
25013 printf ("In outputFileIds(): isModified() == %s: locatedNode = %p = %s \n",locatedNode->get_isModified() ? "true" : "false",locatedNode,locatedNode->class_name().c_str());
25014 printf (" --- file id = %d physical_file_id = %d \n",node->get_file_info()->get_file_id(),node->get_file_info()->get_physical_file_id());
25015#endif
25016 }
25017 else
25018 {
25019 SgInitializedName* initializedName = isSgInitializedName(node);
25020 if (initializedName != NULL)
25021 {
25022 printf ("In outputFileIds(): isModified() == %s: initializedName = %p = %s \n",initializedName->get_isModified() ? "true" : "false",initializedName,initializedName->class_name().c_str());
25023 printf (" --- file id = %d physical_file_id = %d \n",initializedName->get_file_info()->get_file_id(),initializedName->get_file_info()->get_physical_file_id());
25024 }
25025 }
25026 }
25027 };
25028
25029 // Now buid the traveral object and call the traversal (preorder) on the function definition.
25030 LocatedNodeTraversal traversal;
25031 traversal.traverse(node, preorder);
25032
25033#if 0
25034 printf ("Exiting as a test! \n");
25035 ROSE_ABORT();
25036#endif
25037 }
25038
25039
25040std::set<SgLocatedNode*>
25042 {
25043 // DQ (6/11/2015): This reports the statements that are marked as modified (isModified flag).
25044 // It is useful for debugging the token-based unparsing.
25045
25046#if 0
25047 printf ("In collectModifiedLocatedNodes(): node = %p = %s \n",node,node->class_name().c_str());
25048#endif
25049
25050 class LocatedNodeTraversal : public AstSimpleProcessing
25051 {
25052 public:
25053 LocatedNodeTraversal() : count (0) {}
25054 void visit (SgNode* node)
25055 {
25056 SgLocatedNode* locatedNode = isSgLocatedNode(node);
25057 if (locatedNode != NULL && locatedNode->get_isModified() == true)
25058 {
25059#if 0
25060 printf ("In collectModifiedLocatedNodes(): isModified() == true: locatedNode = %p = %s \n",locatedNode,locatedNode->class_name().c_str());
25061#endif
25062 returnset.insert(locatedNode);
25063 count++;
25064 }
25065 }
25066
25067 int count; // running total of statements found marked as transformations in the input AST
25068 std::set<SgLocatedNode*> returnset;
25069 };
25070
25071 // Now buid the traveral object and call the traversal (preorder) on the function definition.
25072 LocatedNodeTraversal traversal;
25073 traversal.traverse(node, preorder);
25074
25075 return traversal.returnset;
25076 }
25077
25078
25080void
25081SageInterface::resetModifiedLocatedNodes(const std::set<SgLocatedNode*> & modifiedNodeSet)
25082 {
25083 // DQ (6/5/2019): Use a previously constructed set to reset the IR nodes to be marked as isModified.
25084
25085#if 0
25086 printf ("In resetModifiedLocatedNodes(): modifiedNodeSet.size() = %zu \n",modifiedNodeSet.size());
25087#endif
25088
25089 std::set<SgLocatedNode*>::const_iterator i = modifiedNodeSet.begin();
25090 while (i != modifiedNodeSet.end())
25091 {
25092 SgLocatedNode* node = *i;
25093#if 0
25094 printf ("Marking node = %p = %s as modified \n",node,node->class_name().c_str());
25095#endif
25096 node->set_isModified(true);
25097
25098 i++;
25099 }
25100 }
25101
25102
25103void
25105 {
25106 // DQ (10/23/2018): This reports the nodes in the AST that are marked as modified (isModified flag).
25107 // It is useful for debugging the token-based unparsing.
25108
25109 printf ("\n\n##################################################### \n");
25110 printf ("Report on modified statements: label = %s \n",label.c_str());
25111
25112 SgSourceFile* sourceFile = isSgSourceFile(node);
25113 if (sourceFile != NULL)
25114 {
25115 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
25116 }
25117 else
25118 {
25119 SgGlobal* globalScope = isSgGlobal(node);
25120 if (globalScope != NULL)
25121 {
25122 sourceFile = isSgSourceFile(globalScope->get_parent());
25123 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
25124 }
25125 }
25126
25127 ROSE_ASSERT(node != NULL);
25128 std::set<SgStatement*> collection = collectModifiedStatements(node);
25129
25130#if 0
25131 printf ("In reportModifiedStatements(): collection.size() = %zu \n",collection.size());
25132#endif
25133
25134 std::set<SgStatement*>::iterator i = collection.begin();
25135 while (i != collection.end())
25136 {
25137 // DQ (10/9/2019): Adding filename to debug output.
25138 string filename = (*i)->get_file_info()->get_filename();
25139
25140 // DQ (10/14/2019): Get the best name possible.
25141 if (filename == "transformation")
25142 {
25143#if 0
25144 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
25145#endif
25146 // filename = (*i)->get_file_info()->get_physical_filename();
25147 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
25148 if (sourceFile != NULL)
25149 {
25150 filename = sourceFile->getFileName();
25151 }
25152 }
25153
25154 printf (" --- filename = %s modified statement = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
25155
25156 i++;
25157 }
25158
25159#if 1
25160 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
25161 // output spew else the message output at the top of this function will scroll off the screen.
25162 printf ("########################################################## \n");
25163 printf ("reportModifiedStatements(): Called using label = %s \n",label.c_str());
25164#endif
25165 printf ("########################################################## \n\n\n");
25166
25167#if 0
25168 printf ("Exiting as a test! \n");
25169 ROSE_ASSERT(false);
25170#endif
25171 }
25172
25173
25174
25175void
25177 {
25178 // DQ (6/21/2021): This reports the nodes in the AST that are marked as modified (isModified flag).
25179 // It is useful for debugging the token-based unparsing.
25180
25181 printf ("\n\n##################################################### \n");
25182 printf ("Report on modified locatedNodes: label = %s \n",label.c_str());
25183
25184 SgSourceFile* sourceFile = isSgSourceFile(node);
25185 if (sourceFile != NULL)
25186 {
25187 printf (" --- (SgSourceFile) filename = %s \n",sourceFile->getFileName().c_str());
25188 }
25189 else
25190 {
25191 SgGlobal* globalScope = isSgGlobal(node);
25192 if (globalScope != NULL)
25193 {
25194 sourceFile = isSgSourceFile(globalScope->get_parent());
25195 printf (" --- (SgGlobal) filename = %s \n",sourceFile->getFileName().c_str());
25196 }
25197 }
25198
25199 ROSE_ASSERT(node != NULL);
25200 std::set<SgLocatedNode*> collection = collectModifiedLocatedNodes(node);
25201
25202#if 0
25203 printf ("In reportModifiedLocatedNode(): collection.size() = %zu \n",collection.size());
25204#endif
25205
25206 std::set<SgLocatedNode*>::iterator i = collection.begin();
25207 while (i != collection.end())
25208 {
25209 // DQ (10/9/2019): Adding filename to debug output.
25210 string filename = (*i)->get_file_info()->get_filename();
25211
25212 // DQ (10/14/2019): Get the best name possible.
25213 if (filename == "transformation")
25214 {
25215#if 0
25216 printf (" --- filename == transformation: sourceFile = %p using physical filename \n",sourceFile);
25217#endif
25218 // filename = (*i)->get_file_info()->get_physical_filename();
25219 SgSourceFile* sourceFile = TransformationSupport::getSourceFile(*i);
25220 if (sourceFile != NULL)
25221 {
25222 filename = sourceFile->getFileName();
25223 }
25224 }
25225
25226 printf (" --- filename = %s modified locatedNode = %p = %s \n",filename.c_str(),(*i),(*i)->class_name().c_str());
25227
25228 i++;
25229 }
25230
25231#if 1
25232 // DQ (6/8/2019): This helps track down where this is being called when are are cleaning up
25233 // output spew else the message output at the top of this function will scroll off the screen.
25234 printf ("########################################################## \n");
25235 printf ("reportModifiedLocatedNodes(): Called using label = %s \n",label.c_str());
25236#endif
25237 printf ("########################################################## \n\n\n");
25238
25239#if 0
25240 printf ("Exiting as a test! \n");
25241 ROSE_ASSERT(false);
25242#endif
25243 }
25244
25245
25246
25247
25248// DQ (3/22/2019): Translate CPP directives from attached preprocessor information to CPP Directive Declaration IR nodes.
25249
25250void
25252 {
25253 // Debugging function to print out comments in the statements (added by DQ)
25254
25255 ROSE_ASSERT(locatedNode != NULL);
25256 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
25257
25258#if 0
25259 curprint ("/* Inside of printOutComments() */");
25260#endif
25261
25262 if (comments != NULL)
25263 {
25264#if 0
25265 printf ("Found attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25266 curprint ("/* Inside of printOutComments(): comments != NULL */");
25267#endif
25268
25269 AttachedPreprocessingInfoType::iterator i;
25270 for (i = comments->begin(); i != comments->end(); i++)
25271 {
25272 ROSE_ASSERT ( (*i) != NULL );
25273 printf (" Attached Comment (relativePosition=%s): %s \n",
25274 // DQ (2/11/2021): Fixed to report correct relative locations.
25275 // ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25276 PreprocessingInfo::relativePositionName((*i)->getRelativePosition()).c_str(),
25277 (*i)->getString().c_str());
25278 printf ("Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*i)->getNumberOfLines(),(*i)->getColumnNumberOfEndOfString());
25279 // curprint (string("/* Inside of printOutComments(): comments = ") + (*i)->getString() + " */");
25280
25281#if 0
25282 (*i)->get_file_info()->display("comment/directive location");
25283#endif
25284 }
25285 }
25286 else
25287 {
25288#if 0
25289 printf ("In SageInterface::printOutComments(): No attached comments (at %p of type: %s): \n",locatedNode,locatedNode->class_name().c_str());
25290#endif
25291 }
25292 }
25293
25294
25295
25296bool
25298 {
25299 bool returnValue = false;
25300
25301 ROSE_ASSERT(currentPreprocessingInfo != NULL);
25302
25303 PreprocessingInfo::DirectiveType directive = currentPreprocessingInfo->getTypeOfDirective();
25304
25305 if (directive == PreprocessingInfo::C_StyleComment ||
25306 directive == PreprocessingInfo::CplusplusStyleComment ||
25307 directive == PreprocessingInfo::FortranStyleComment ||
25308 directive == PreprocessingInfo::CpreprocessorBlankLine ||
25309 directive == PreprocessingInfo::ClinkageSpecificationStart ||
25310 directive == PreprocessingInfo::ClinkageSpecificationEnd)
25311 {
25312 returnValue = true;
25313 }
25314
25315 return returnValue;
25316 }
25317
25318std::vector<SgC_PreprocessorDirectiveStatement*>
25320 {
25321 std::vector<SgC_PreprocessorDirectiveStatement*> directiveList;
25322
25323 // Find existing first and last header.
25324 AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo();
25325
25326 if (comments != nullptr)
25327 {
25328 AttachedPreprocessingInfoType::iterator i; // , firsti, lasti;
25329 for (i = comments->begin (); i != comments->end(); i++)
25330 {
25331 if (skipTranslateToUseCppDeclaration(*i) == true)
25332 {
25333 // 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).
25334 }
25335 else
25336 {
25337 SgC_PreprocessorDirectiveStatement* directive = SgC_PreprocessorDirectiveStatement::createDirective(*i);
25338 ROSE_ASSERT(directive != NULL);
25339 directiveList.push_back(directive);
25340 }
25341
25342 printf ("directiveList.size() = %zu \n",directiveList.size());
25343 }
25344 }
25345
25346 return directiveList;
25347 }
25348
25349
25350void
25352 {
25353 bool declarationsOnly = scope->containsOnlyDeclarations();
25354
25355 printf ("In translateScopeToUseCppDeclarations(): declarationsOnly = %s scope = %p = %s \n",declarationsOnly ? "true" : "false",scope,scope->class_name().c_str());
25356
25357 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> > directiveMap;
25358
25359 if (declarationsOnly == true)
25360 {
25361 // These are scopes such as global scope, namespace definitions, class definitions, etc.
25362 SgDeclarationStatementPtrList & declarationList = scope->getDeclarationList();
25363 SgDeclarationStatementPtrList::iterator i = declarationList.begin();
25364 while (i != declarationList.end())
25365 {
25366 SgDeclarationStatement* declaration = *i;
25367 ROSE_ASSERT(declaration != NULL);
25368
25369 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(declaration,scope);
25370
25371 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25372
25373 if (attachDirectives.empty() == false)
25374 {
25375 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(declaration,attachDirectives));
25376 }
25377
25378 i++;
25379 }
25380
25381 // Need to save the list of things that will be added so we can avoid iterator invalidation.
25382 }
25383 else
25384 {
25385 // These are scopes such as SgBasicBlock (which can contain non-declaration statements.
25386 SgStatementPtrList & statementList = scope->getStatementList();
25387 SgStatementPtrList::iterator i = statementList.begin();
25388 while (i != statementList.end())
25389 {
25390 SgStatement* statement = *i;
25391 ROSE_ASSERT(statement != NULL);
25392
25393 std::vector<SgC_PreprocessorDirectiveStatement*> attachDirectives = translateStatementToUseCppDeclarations(statement,scope);
25394
25395 printf ("attachDirectives.size() = %zu \n",attachDirectives.size());
25396
25397 if (attachDirectives.empty() == false)
25398 {
25399 directiveMap.insert(std::pair<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >(statement,attachDirectives));
25400 }
25401
25402 i++;
25403 }
25404 }
25405
25406 printf ("directiveMap.size() = %zu \n",directiveMap.size());
25407
25408 printf ("Processing the directiveMap: \n");
25409 std::map<SgStatement*,std::vector<SgC_PreprocessorDirectiveStatement*> >::iterator i = directiveMap.begin();
25410 while (i != directiveMap.end())
25411 {
25412 SgStatement* statement = i->first;
25413 std::vector<SgC_PreprocessorDirectiveStatement*> directives = i->second;
25414
25415 printf ("statement = %p = %s \n",statement,statement->class_name().c_str());
25416 printf ("directives.size() = %zu \n",directives.size());
25417 // std::vector<SgC_PreprocessorDirectiveStatement*>::reverse_iterator j = directives.begin();
25418 std::vector<SgC_PreprocessorDirectiveStatement*>::iterator j = directives.begin();
25419 while (j != directives.end())
25420 {
25421 scope->insert_statement(statement,*j);
25422
25423 j++;
25424 }
25425
25426 // Remove the directives there were attached to the statement.
25427 AttachedPreprocessingInfoType *comments = statement->getAttachedPreprocessingInfo();
25428 ROSE_ASSERT(comments != NULL);
25429
25430 AttachedPreprocessingInfoType deleteList;
25431 // std::vector<PreprocessingInfo*> deleteList;
25432
25433 // comments->erase();
25434 // statement->setAttachedPreprocessingInfo(NULL);
25435 AttachedPreprocessingInfoType::iterator k;
25436 for (k = comments->begin(); k != comments->end(); k++)
25437 {
25438#if 1
25439 ROSE_ASSERT ( (*k) != NULL );
25440 printf (" Attached Comment (relativePosition=%s): %s\n",
25441 ((*k)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after",
25442 (*k)->getString().c_str());
25443 printf ("translateScopeToUseCppDeclarations(): Comment/Directive getNumberOfLines = %d getColumnNumberOfEndOfString = %d \n",(*k)->getNumberOfLines(),(*k)->getColumnNumberOfEndOfString());
25444#endif
25445
25446 // We only want to process the CPP directives (skipping comments and a few othr kinds of obscure directives).
25447 if (skipTranslateToUseCppDeclaration(*k) == true)
25448 {
25449 // 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).
25450 printf ("Do NOT delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25451 }
25452 else
25453 {
25454 printf ("DO delete *k = %p = %s \n",*k,(*k)->getString().c_str());
25455
25456 deleteList.push_back(*k);
25457 // delete *k;
25458 // *k = NULL;
25459 }
25460 }
25461
25462 printf ("Iterate over the deleteList: deleteList.size() = %zu comments->size() = %zu \n",deleteList.size(),comments->size());
25463 AttachedPreprocessingInfoType::iterator m = deleteList.begin();
25464 while (m != deleteList.end())
25465 {
25466 // comments->erase(m);
25467 // std::remove(comments->begin(), comments->end(), *m);
25468 comments->erase(std::remove(comments->begin(), comments->end(), *m), comments->end());
25469
25470 printf (" --- comments->size() = %zu \n",comments->size());
25471
25472 m++;
25473 }
25474
25475 // comments->clear();
25476 // delete comments; // statement->getAttachedPreprocessingInfoPtr();
25477 // statement->set_attachedPreprocessingInfoPtr(NULL);
25478
25479 i++;
25480 }
25481
25482 printf ("Leaving translateScopeToUseCppDeclarations(): scope = %p = %s \n",scope,scope->class_name().c_str());
25483 }
25484
25485
25486void
25488 {
25489 class CppTranslationTraversal : public AstSimpleProcessing
25490 {
25491 public:
25492 CppTranslationTraversal() {}
25493 void visit (SgNode* node)
25494 {
25495 printf ("In CppTranslationTraversal::visit(): node = %p = %s \n",node,node->class_name().c_str());
25496
25497 SgScopeStatement* scope = isSgScopeStatement(node);
25498 SgGlobal* globalScope = isSgGlobal(scope);
25499 if (globalScope != NULL)
25500 {
25501 printf ("In CppTranslationTraversal::visit(): processing scope = %p = %s \n",scope,scope->class_name().c_str());
25503 }
25504 else
25505 {
25506 if (scope != NULL)
25507 {
25508 printf ("In SageInterface::translateToUseCppDeclarations(): Currently skipping all but global scope! \n");
25509 }
25510 }
25511 }
25512 };
25513
25514 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
25515 CppTranslationTraversal traversal;
25516
25517 printf ("In translateToUseCppDeclarations(): Calling traversal.traverse() \n");
25518
25519 // We might want to do this traversla POSTORDER since we are transforming the AST at each scope.
25520 // traversal.traverse(n, preorder);
25521 traversal.traverse(n, postorder);
25522
25523 printf ("Leaving translateToUseCppDeclarations(): DONE: Calling traversal.traverse() \n");
25524 }
25525
25527{
25528 // print current level's info
25529 if (!n) return;
25530 cout<<"--------------"<<endl;
25531 cout<<n<<":"<<n->class_name()<< endl;
25532 if (SgLocatedNode * lnode = isSgLocatedNode(n))
25533 {
25534 cout<<"file info:\t ";
25535 lnode->get_file_info()->display();
25536 cout<<"\n unparseToString:\t ";
25537 lnode->unparseToString();
25538 }
25539
25540 // track back to its parent
25542}
25543// forward declaration is needed here,
25544//static void serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel);
25545
25546#if 0 // made it into a template function to handle various ptr lists in AST
25547// A special node in the AST text dump
25548static void serialize(SgTemplateArgumentPtrList& plist, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25549{
25550 out<<prefix;
25551 out<< (hasRemaining?"|---": "|___");
25552
25553// out<<"+"<<edgeLabel<<"+>";
25554 out<<" "<<edgeLabel<<" ->";
25555 // print address
25556 out<<"@"<<&plist<<" "<< "SgTemplateArgumentPtrList ";
25557
25558 out<<endl;
25559
25560 int last_non_null_child_idx =-1;
25561 for (int i = (int) (plist.size())-1; i>=0; i--)
25562 {
25563 if (plist[i])
25564 {
25565 last_non_null_child_idx = i;
25566 break;
25567 }
25568 }
25569
25570 for (size_t i=0; i< plist.size(); i++ )
25571 {
25572 bool n_hasRemaining=false;
25573#if 0
25574 if (i+1 < plist.size())
25575 n_hasRemaining=true;
25576#else
25577 if ((int)i< last_non_null_child_idx) n_hasRemaining = true;
25578#endif
25579 string suffix= hasRemaining? "| " : " ";
25580 string n_prefix = prefix+suffix;
25581 string n_edge_label="";
25582 if (plist[i])
25583 serialize (plist[i], n_prefix, n_hasRemaining, out,n_edge_label);
25584 }
25585}
25586#endif
25587
25588// print essential information from any AST node
25589// hasRemaining if this node has a sibling node to be visited next.
25590void SageInterface::serialize(SgNode* node, string& prefix, bool hasRemaining, ostringstream& out, string& edgeLabel)
25591{
25592 // there may be NULL children!!
25593 //if (!node) return;
25594
25595 out<<prefix;
25596 out<< (hasRemaining?"|---": "|___");
25597
25598 out<<" "<<edgeLabel<<" ->";
25599 if (!node)
25600 {
25601 out<<" NULL "<<endl;
25602 return;
25603 }
25604
25605 // print address
25606 out<<"@"<<node<<" "<< node->class_name()<<" ";
25607
25608 //optionally file info
25609 if (SgLocatedNode* lnode= isSgLocatedNode(node))
25610 {
25611 //Rose::StringUtility::stripPathFromFileName()
25612 out<< lnode->get_file_info()->get_filename() <<" "<<lnode->get_file_info()->get_line()<<":"<<lnode->get_file_info()->get_col();
25613 // also preprocessing info. attached.
25614 AttachedPreprocessingInfoType *comments =
25615 lnode->getAttachedPreprocessingInfo ();
25616
25617 if (comments != NULL)
25618 {
25619// printf ("Found an IR node with preprocessing Info attached:\n");
25620 out<<" AttachedPreprocessingInfoType@"<<comments;
25621 int counter = 0;
25622 AttachedPreprocessingInfoType::iterator i;
25623 out <<"{";
25624 for (i = comments->begin (); i != comments->end (); i++)
25625 {
25626 if (i!=comments->begin ())
25627 out<<endl;
25628 out<<"<id=";
25629 out<<counter++<<" ";
25630 // printf("-------------PreprocessingInfo #%d ----------- : \n",counter++);
25631 // printf("classification = %s:\n String format = %s\n",
25632 // PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str (),
25633 // (*i)->getString ().c_str ());
25634 if (*i==NULL)
25635 out<<" NULL="; // The AST may be in the middle of transformation, with NULL comments attached.
25636 else
25637 {
25638 out<<*i<<" classification="<<PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective ()). c_str ();
25639 out<<" string="<<(*i)->getString ().c_str ();
25640 out<<" relative pos=" ; // << (*i)->getRelativePosition ();
25641#if 1
25642 if ((*i)->getRelativePosition () == PreprocessingInfo::inside)
25643 out<<"inside";
25644 else if ((*i)->getRelativePosition () == PreprocessingInfo::before)
25645 out<<"before";
25646 else
25647 out<<"after";
25648#endif
25649 }
25650 out<<">";
25651 }
25652 out <<"}";
25653 }
25654 }
25655
25656 if (SgDeclarationStatement* v= isSgDeclarationStatement(node))
25657 {
25658 out<<" first nondefining decl@"<< v->get_firstNondefiningDeclaration();
25659 out<<" defining decl@"<< v->get_definingDeclaration();
25660 }
25661
25662 if (SgEnumVal* f = isSgEnumVal(node) )
25663 out<<" value="<< f->get_value() <<" declaration="<<f->get_declaration() << " name="<< f->get_name().getString();
25664 // optionally qualified name
25665
25666 if (SgFunctionDeclaration* f = isSgFunctionDeclaration(node) )
25667 out<<" "<< f->get_qualified_name();
25668
25669 if (SgAdaFunctionRenamingDecl* f = isSgAdaFunctionRenamingDecl(node) )
25670 out<<" renamed_function "<< f->get_renamed_function();
25671
25672 if (SgAdaRenamingDecl* f = isSgAdaRenamingDecl(node) )
25673 out<<" name="<< f->get_name() << " renamed decl "<<f->get_renamed() ;
25674
25675 if (SgClassDeclaration* f = isSgClassDeclaration(node) )
25676 out<<" "<< f->get_qualified_name();
25677
25678 if (SgTypedefDeclaration* f = isSgTypedefDeclaration(node) )
25679 out<<" "<< f->get_qualified_name();
25680
25681 if (SgAdaPackageSpecDecl * f = isSgAdaPackageSpecDecl(node) )
25682 out<<" "<< f->get_qualified_name();
25683
25684 if (SgAdaEnumRepresentationClause* f = isSgAdaEnumRepresentationClause(node) )
25685 out<<" enumType="<< f->get_enumType();
25686
25687 if (SgAdaAccessType* v = isSgAdaAccessType(node) )
25688 {
25689 // out<<" "<< v->get_qualified_name();
25690 //out<<" "<< v->get_name();
25691 // PP (2/18/22) updated to reflect properties in AdaAccessType
25692 //~ out<<" is_object_type"<< v->get_is_object_type();
25693 out<<" is_general_access"<< v->get_is_general_access();
25694 //~ out<<" is_constant:"<< v->get_is_constant();
25695 //~ out<<" is_protected:"<< v->get_is_protected ();
25696 out<<" is_anonymous:"<< v->get_is_anonymous ();
25697 }
25698
25699 if (SgAdaSubroutineType* v = isSgAdaSubroutineType(node) )
25700 {
25701 out<<" is_protected"<< v->get_is_protected();
25702 }
25703
25704 if (SgInitializedName * v = isSgInitializedName(node) )
25705 {
25706 out<<" "<< v->get_qualified_name();
25707 out<<" type@"<< v->get_type();
25708 out<<" initializer@"<< v->get_initializer();
25709 out<<" scope@"<< v->get_scope();
25710// type_set.insert (v->get_type());
25711 }
25712
25713 // associated class, function and variable declarations
25714 if (SgTemplateInstantiationDecl* f = isSgTemplateInstantiationDecl(node) )
25715 out<<" template class decl@"<< f->get_templateDeclaration();
25716
25717 if (SgMemberFunctionDeclaration* f = isSgMemberFunctionDeclaration(node) )
25718 out<<" assoc. class decl@"<< f->get_associatedClassDeclaration();
25719
25720 if (SgConstructorInitializer* ctor= isSgConstructorInitializer(node) )
25721 {
25722 out<<" member function decl@"<< ctor->get_declaration();
25723 }
25724
25725 if (SgIntVal* v= isSgIntVal(node))
25726 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25727
25728 if (SgShortVal* v= isSgShortVal(node))
25729 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25730
25731 if (SgLongIntVal* v= isSgLongIntVal(node))
25732 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25733
25734 if (SgLongLongIntVal* v= isSgLongLongIntVal(node))
25735 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25736
25737 if (SgUnsignedIntVal* v= isSgUnsignedIntVal(node))
25738 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25739
25740 if (SgUnsignedShortVal* v= isSgUnsignedShortVal(node))
25741 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25742
25743 if (SgUnsignedLongVal* v= isSgUnsignedLongVal(node))
25744 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25745
25746 if (SgUnsignedLongLongIntVal* v= isSgUnsignedLongLongIntVal(node))
25747 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25748
25749 if (SgFloatVal* v= isSgFloatVal(node))
25750 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25751
25752 if (SgDoubleVal* v= isSgDoubleVal(node))
25753 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25754
25755 if (SgLongDoubleVal* v= isSgLongDoubleVal(node))
25756 out<<" value="<< v->get_value() <<" valueString="<< v->get_valueString();
25757
25758 if (SgVarRefExp* var_ref= isSgVarRefExp(node) )
25759 out<<" init name@"<< var_ref->get_symbol()->get_declaration() <<" symbol name="<<var_ref->get_symbol()->get_name();
25760
25761 if (SgMemberFunctionRefExp* func_ref= isSgMemberFunctionRefExp(node) )
25762 out<<" member func decl@"<< func_ref->get_symbol_i()->get_declaration();
25763
25764 if (SgTemplateInstantiationMemberFunctionDecl* cnode= isSgTemplateInstantiationMemberFunctionDecl(node) )
25765 out<<" template member func decl@"<< cnode->get_templateDeclaration();
25766
25767 if (SgFunctionRefExp* func_ref= isSgFunctionRefExp(node) )
25768 {
25769 SgFunctionSymbol* sym= func_ref->get_symbol_i();
25770 out<<" func decl@"<< sym->get_declaration() << " func sym name="<<sym->get_name();
25771 }
25772
25773 if (SgAdaRenamingRefExp* renaming_ref= isSgAdaRenamingRefExp(node) )
25774 {
25775 SgAdaRenamingDecl * renaming_decl = renaming_ref->get_decl();
25776 out<<" ada renaming decl@"<< renaming_decl;
25777 }
25778
25779 // base type of several types of nodes:
25780 if (SgTypedefDeclaration * v= isSgTypedefDeclaration(node))
25781 {
25782 out<<" base_type@"<< v->get_base_type();
25783// type_set.insert (v->get_base_type());
25784 }
25785
25786 if (SgArrayType* v= isSgArrayType(node))
25787 out<<" base_type@"<< v->get_base_type();
25788
25789 if (SgAdaAccessType* v= isSgAdaAccessType(node))
25790 out<<" base_type@"<< v->get_base_type();
25791
25792 if (SgTypeExpression* v= isSgTypeExpression(node))
25793 out<<" type@"<< v->get_type();
25794
25795 if (SgAdaAttributeExp* v= isSgAdaAttributeExp(node))
25796 out<<" attribute@"<< v->get_attribute();
25797
25798 if (SgUsingDirectiveStatement* v= isSgUsingDirectiveStatement(node))
25799 out<<" namespaceDeclaration="<< v->get_namespaceDeclaration();
25800
25801 out<<endl;
25802
25803 std::vector<SgNode* > children = node->get_traversalSuccessorContainer();
25804#if 0
25805 int total_count = children.size();
25806 int current_index=0;
25807#endif
25808
25809 int last_non_null_child_idx =-1;
25810 for (int i = (int) (children.size())-1; i>=0; i--)
25811 {
25812 if (children[i])
25813 {
25814 last_non_null_child_idx = i;
25815 break;
25816 }
25817 }
25818
25819#if 0
25820 // some Sg??PtrList are not AST nodes, not part of children , we need to handle them separatedly
25821 // we sum all children into single total_count to tell if there is remaining children.
25822 if (isSgTemplateInstantiationDecl (node))
25823 total_count += 1; // sn->get_templateArguments().size();
25824#endif
25825
25826 // handling SgTemplateArgumentPtrList first
25827 if (SgTemplateInstantiationDecl* sn = isSgTemplateInstantiationDecl (node))
25828 {
25829 SgTemplateArgumentPtrList& plist = sn->get_templateArguments();
25830 bool n_hasRemaining=false;
25831 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25832 string suffix= hasRemaining? "| " : " ";
25833 string n_prefix = prefix+suffix;
25834 string n_edge_label= "";
25835 serialize_list(plist, "SgTemplateArgumentPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25836 }
25837 else if (SgImportStatement* import_stmt = isSgImportStatement(node))
25838 {
25839 SgExpressionPtrList& plist = import_stmt->get_import_list();
25840 bool n_hasRemaining=false;
25841 if (last_non_null_child_idx>-1) n_hasRemaining = true;
25842 string suffix= hasRemaining? "| " : " ";
25843 string n_prefix = prefix+suffix;
25844 string n_edge_label= "";
25845 serialize_list(plist, "SgExpressionPtrList", n_prefix, n_hasRemaining, out, n_edge_label);
25846 }
25847
25848 std::vector< std::string > successorNames= node->get_traversalSuccessorNamesContainer();
25849
25850 // finish sucessors
25851 for (size_t i =0; i< children.size(); i++)
25852 {
25853 bool n_hasRemaining=false;
25854#if 0
25855 if (current_index+1<total_count)
25856 n_hasRemaining=true;
25857 current_index++;
25858#else
25859 if ((int)i<last_non_null_child_idx) n_hasRemaining = true;
25860#endif
25861 string suffix= hasRemaining? "| " : " ";
25862 string n_prefix = prefix+suffix;
25863 if (children[i])
25864 serialize (children[i], n_prefix, n_hasRemaining, out, successorNames[i]);
25865 }
25866}
25867
25869{
25870 ostringstream oss;
25871 string prefix;
25872 string label="";
25873 serialize(node, prefix, false, oss, label);
25874 cout<<oss.str();
25875}
25876
25877void SageInterface::printAST(SgNode* node, const char* filename)
25878{
25879 printAST2TextFile(node, filename, true);
25880}
25881
25882void SageInterface::printAST2TextFile (SgNode* node, std::string filename, bool printType/*=true*/)
25883{
25884 // Rasmussen 9/21/2020: This leads to infinite recursion (clang warning message) and should be removed from API)
25885// ROSE_ABORT();
25886 printAST2TextFile (node, filename.c_str(), printType);
25887}
25888
25889void SageInterface::printAST2TextFile(SgNode* node, const char* filename, bool printType/*=true*/)
25890{
25891 ostringstream oss;
25892 string prefix;
25893 string label="";
25894 serialize(node, prefix, false, oss, label);
25895 ofstream textfile;
25896 textfile.open(filename, ios::out);
25897 textfile<<oss.str();
25898
25899 if (printType)
25900 {
25901 // append type information also
25902 textfile<<"Types encountered ...."<<endl;
25903 ostringstream oss2;
25904 VariantVector vv(V_SgType);
25905 Rose_STL_Container<SgNode*> tnodes= NodeQuery::queryMemoryPool(vv);
25906 for (Rose_STL_Container<SgNode*>::const_iterator i = tnodes.begin(); i != tnodes.end(); ++i)
25907 {
25908 serialize (*i, prefix, false, oss2, label);
25909 }
25910 textfile<<oss2.str();
25911 }
25912
25913 textfile.close();
25914}
25915
25917{
25918 saveToPDF(node, string("temp.pdf.json") );
25919}
25921// node to find its enclosing file node. The entire file's AST will be saved into a pdf.
25922void SageInterface:: saveToPDF(SgNode* node, std::string filename)
25923{
25924 ROSE_ASSERT(node != NULL);
25925 AstJSONGeneration json;
25926 json.generateWithinFile(filename, getEnclosingFileNode(node));
25927}
25928
25930{
25931 bool rtval = false;
25932 ROSE_ASSERT (node != NULL);
25933 Sg_File_Info* finfo = node->get_file_info();
25934 if (finfo!=NULL)
25935 {
25936 string fname = finfo->get_filenameString();
25937 string buildtree_str1 = string("include-staging/gcc_HEADERS");
25938 string buildtree_str2 = string("include-staging/g++_HEADERS");
25939 string installtree_str1 = string("include/edg/gcc_HEADERS");
25940 string installtree_str2 = string("include/edg/g++_HEADERS");
25941 string system_headers = string("/usr/include");
25942 // if the file name has a sys header path of either source or build tree
25943 if ((fname.find (buildtree_str1, 0) != string::npos) ||
25944 (fname.find (buildtree_str2, 0) != string::npos) ||
25945 (fname.find (installtree_str1, 0) != string::npos) ||
25946 (fname.find (installtree_str2, 0) != string::npos) ||
25947 (fname.find (system_headers, 0) != string::npos)
25948 )
25949 rtval = true;
25950 }
25951 return rtval;
25952}
25953
25954
25955// DQ (2/27/2021): Adding support to detect if a SgLocatedNode is located in a header file.
25957 {
25958 // Check if a node is from a header file
25959
25960 bool returnValue = false;
25961
25962 Sg_File_Info* fileInfo = node->get_file_info();
25963 ROSE_ASSERT(fileInfo != NULL);
25964 string filename = fileInfo->get_filenameString();
25965
25966#if 0
25967 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());
25968#endif
25969
25970 // DQ (2/27/2021): We save a map of all of the header files processed in the generation of the ROSE AST,
25971 // so the test is only if the filename is in the list.
25972 if (EDG_ROSE_Translation::edg_include_file_map.find(filename) == EDG_ROSE_Translation::edg_include_file_map.end())
25973 {
25974#if 0
25975 printf ("This is NOT in the EDG_ROSE_Translation::edg_include_file_map \n");
25976#endif
25977 }
25978 else
25979 {
25980#if 0
25981 printf ("This IS in the EDG_ROSE_Translation::edg_include_file_map \n");
25982#endif
25983 returnValue = true;
25984 }
25985
25986 return returnValue;
25987 }
25988
25989
25992{
25993 ROSE_ASSERT(return_type != NULL);
25994 ROSE_ASSERT(typeList != NULL);
25996 ROSE_ASSERT(fTable);
25997
25998 // This function make clever use of a static member function which can't be built
25999 // for the case of a SgMemberFunctionType (or at least not without more work).
26000 SgName typeName = SgFunctionType::get_mangled(return_type, typeList);
26001 SgFunctionType* funcType = isSgFunctionType(fTable->lookup_function_type(typeName));
26002
26003 return funcType;
26004}
26005
26010{
26011 ROSE_ASSERT (lhs != NULL);
26012 ROSE_ASSERT (rhs != NULL);
26013 if (lhs == rhs)
26014 return true;
26015
26016 bool rt = false;
26017 SgType* rt1 = lhs->get_return_type();
26018 SgType* rt2 = rhs->get_return_type();
26019
26020 if (isEquivalentType (rt1, rt2))
26021 {
26022 SgTypePtrList f1_arg_types = lhs->get_arguments();
26023 SgTypePtrList f2_arg_types = rhs->get_arguments();
26024 // Must have same number of argument types
26025 if (f1_arg_types.size() == f2_arg_types.size())
26026 {
26027 // DQ (2/16/2017): Fixed compiler warning about comparison between signed and unsigned integers
26028 // int counter = 0;
26029 size_t counter = 0;
26030 // iterate through all argument types
26031 // for (int i=0; i< f1_arg_types.size(); i++)
26032 for (size_t i=0; i< f1_arg_types.size(); i++)
26033 {
26034 if (isEquivalentType (f1_arg_types[i], f2_arg_types[i]) )
26035 counter ++; // count the number of equal arguments
26036 else
26037 break; // found different type? jump out the loop
26038 }
26039 // all arguments are equivalent, set to true
26040 if (counter == f1_arg_types.size())
26041 rt = true;
26042 }
26043 } // end if equivalent return types
26044
26045 return rt;
26046}
26047
26048bool
26050 {
26051 // This function is called in the SgType::isEquivalentType (const SgType & Y) const function.
26052
26053 // DQ (11/28/2015): A better goal for this function should be to define it as a recursive function.
26054
26055 // DQ (12/8/2015): We need to add support for SgMemberFunctionType as demonstrated by test2007_17.C.
26056 // and for SgTemplateType as demonstrated by tests/nonsmoke/functional/CompileTests/RoseExample_tests/testRoseHeaders_03.C
26057 // Note that this is only required within the change to use this isEquivalentType() function in the
26058 // support to replace:
26059 // templateParameterOrArgumentLocal->get_initializedName()->get_type() == templateParameterOrArgumentFromSymbol->get_initializedName()->get_type()
26060 // in ROSETTA/Grammar/Support.code
26061
26062 ROSE_ASSERT(lhs != NULL);
26063 ROSE_ASSERT(rhs != NULL);
26064
26065 bool isSame = false;
26066
26067 // 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).
26068 static int counter = 0;
26069
26070 const SgType & X = *lhs;
26071 const SgType & Y = *rhs;
26072
26073 // DQ (11/28/2015): We don't want to strip off everything.
26074 // SgType* stripType(unsigned char bit_array = STRIP_MODIFIER_TYPE | STRIP_REFERENCE_TYPE | STRIP_POINTER_TYPE | STRIP_ARRAY_TYPE | STRIP_TYPEDEF_TYPE ) const;
26075
26076 // I think we need to compute the type chain to evaluate equalence.
26077 // Rose_STL_Container< SgType*> getInternalTypes () const
26078
26079#define DEBUG_TYPE_EQUIVALENCE 0
26080
26081#if DEBUG_TYPE_EQUIVALENCE
26082 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
26083 printf (" --- lhs = %s \n",lhs->unparseToString().c_str());
26084 printf (" --- rhs = %s \n",rhs->unparseToString().c_str());
26085#endif
26086
26087#if DEBUG_TYPE_EQUIVALENCE || 0
26088 if (counter == 0)
26089 {
26090 printf ("In SageInterface::isEquivalentType(): evaluation of type equivalence for lhs and rhs: counter = %d \n",counter);
26091 printf (" --- lhs = %p = %s = %s \n",lhs,lhs->class_name().c_str(),lhs->unparseToString().c_str());
26092 printf (" --- rhs = %p = %s = %s \n",rhs,rhs->class_name().c_str(),rhs->unparseToString().c_str());
26093 }
26094#endif
26095
26096#if DEBUG_TYPE_EQUIVALENCE || 0
26097 // Debugging output.
26098 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26099 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26100
26101 // Debugging output.
26102 printf ("Output of type chain for lhs: \n");
26103 for (size_t i = 0; i < X_typeChain.size(); i++)
26104 {
26105 SgType* element_type = X_typeChain[i];
26106 printf ("X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26107 printf (" --- X_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
26108 SgModifierType* modifierType = isSgModifierType(element_type);
26109 if (modifierType != NULL)
26110 {
26111 // modifierType->get_typeModifier().display("X type chain");
26112 string s = modifierType->get_typeModifier().displayString();
26113 printf (" --- type chain modifier: %s \n",s.c_str());
26114 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
26115 }
26116 }
26117
26118 printf ("Output of type chain for rhs: \n");
26119 for (size_t i = 0; i < Y_typeChain.size(); i++)
26120 {
26121 SgType* element_type = Y_typeChain[i];
26122 printf ("Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26123 printf (" --- Y_element_type unparseToString: = %s \n",element_type->unparseToString().c_str());
26124 SgModifierType* modifierType = isSgModifierType(element_type);
26125 if (modifierType != NULL)
26126 {
26127 // modifierType->get_typeModifier().display("Y type chain");
26128 string s = modifierType->get_typeModifier().displayString();
26129 printf (" --- type chain modifier: %s \n",s.c_str());
26130 printf (" --- type chain modifier: unparseToString: %s \n",modifierType->unparseToString().c_str());
26131 }
26132 }
26133#endif
26134
26135 // Increment the static variable to control the recursive depth while we debug this.
26136 counter++;
26137
26138 // DQ (11/28/2015): exit with debug output instead of infinte recursion.
26139 // if (counter >= 280)
26140 // if (counter >= 500)
26141 if (counter >= 280)
26142 {
26143 // 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());
26144 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);
26145 }
26146
26147 // DQ (12/23/2015): ASC application code requires this to be increased to over 122 (selected 300 for extra margin of safety).
26148 // DQ (11/28/2015): exit in stead of infinte recursion.
26149 // if (counter > 300)
26150 // if (counter > 600)
26151 // if (counter > 5000)
26152 // if (counter > 300)
26153 if (counter > 350)
26154 {
26155 // DQ (11/28/2015): I think this is a reasonable limit.
26156 printf ("ERROR: In SageInterface::isEquivalentType(): recursive limit exceeded for : counter = %d \n",counter);
26157 ROSE_ABORT();
26158 }
26159
26160 // bool exit = false;
26161
26162 // Strip off any typedefs since they are equivalent by definition.
26163 SgType* X_element_type = X.stripType( SgType::STRIP_TYPEDEF_TYPE );
26164 SgType* Y_element_type = Y.stripType( SgType::STRIP_TYPEDEF_TYPE );
26165
26166 // DQ (11/29/2015): We need to handle references (when they are both references we can support then uniformally).
26167 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26168 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26169
26170 if (X_referenceType != NULL && Y_referenceType != NULL)
26171 {
26172 X_element_type = X_referenceType->get_base_type();
26173 Y_element_type = Y_referenceType->get_base_type();
26174
26175 counter--;
26176
26177 // Recursive call.
26178 // return (*X_element_type) == (*Y_element_type);
26179 return isEquivalentType(X_element_type,Y_element_type);
26180 }
26181 else
26182 {
26183 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26184 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26185 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26186
26187 if (X_pointerType != NULL && Y_pointerType != NULL)
26188 {
26189 X_element_type = X_pointerType->get_base_type();
26190 Y_element_type = Y_pointerType->get_base_type();
26191
26192 counter--;
26193
26194 // Recursive call.
26195 // return (*X_element_type) == (*Y_element_type);
26196 return isEquivalentType(X_element_type,Y_element_type);
26197 }
26198 else
26199 {
26200 // DQ (12/8/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26201 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26202 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26203
26204 // DQ (12/8/2015): We need to check that the array size is the same.
26205 if (X_arrayType != NULL && Y_arrayType != NULL)
26206 {
26207 X_element_type = X_arrayType->get_base_type();
26208 Y_element_type = Y_arrayType->get_base_type();
26209
26210 SgExpression* X_array_index_expression = X_arrayType->get_index();
26211 SgExpression* Y_array_index_expression = Y_arrayType->get_index();
26212
26213 if (X_array_index_expression == Y_array_index_expression)
26214 {
26215#if DEBUG_TYPE_EQUIVALENCE || 0
26216 printf ("In SageInterface::isEquivalentType(): counter = %d: Need to check the array size for static equivalence \n",counter);
26217#endif
26218 counter--;
26219
26220 // Recursive call.
26221 // return (*X_element_type) == (*Y_element_type);
26222 return isEquivalentType(X_element_type,Y_element_type);
26223 }
26224 else
26225 {
26226 // Need more complex test for expression equivalence.
26227#if DEBUG_TYPE_EQUIVALENCE || 0
26228 printf ("In SageInterface::isEquivalentType(): counter = %d Need more complex test for expression equivalence \n",counter);
26229 string str1 = X_array_index_expression->unparseToString();
26230 string str2 = Y_array_index_expression->unparseToString();
26231 printf (" --- array index expressions: str1 = %s str2 = %s \n",str1.c_str(),str2.c_str());
26232#endif
26233 // DQ (12/9/2016): Need to decriment the counter as part of recursive function call.
26234 counter--;
26235
26236 // Recursive call.
26237 return isEquivalentType(X_element_type,Y_element_type);
26238 }
26239 }
26240 else
26241 {
26242 // DQ (12/15/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26243 SgNonrealType* X_templateType = isSgNonrealType(X_element_type);
26244 SgNonrealType* Y_templateType = isSgNonrealType(Y_element_type);
26245
26246 // DQ (12/15/2015): We need to check that the array size is the same.
26247 if (X_templateType != NULL && Y_templateType != NULL)
26248 {
26249 string X_name = X_templateType->get_name();
26250 string Y_name = Y_templateType->get_name();
26251
26252 SgNonrealDecl* X_templateDecl = isSgNonrealDecl(X_templateType->get_declaration());
26253 ROSE_ASSERT(X_templateDecl != NULL);
26254 SgNonrealDecl* Y_templateDecl = isSgNonrealDecl(Y_templateType->get_declaration());
26255 ROSE_ASSERT(Y_templateDecl != NULL);
26256
26257 int X_template_parameter_position = X_templateDecl->get_template_parameter_position();
26258 int Y_template_parameter_position = Y_templateDecl->get_template_parameter_position();
26259
26260 SgNode * X_parent = X_templateDecl->get_parent();
26261 SgNode * Y_parent = Y_templateDecl->get_parent();
26262
26263#if DEBUG_TYPE_EQUIVALENCE
26264 SgNode * X_parent_parent = X_parent ? X_parent->get_parent() : NULL;
26265 SgNode * Y_parent_parent = Y_parent ? Y_parent->get_parent() : NULL;
26266 printf ("In SageInterface::isEquivalentType(): case SgNonrealType:\n");
26267 printf (" -- X_name = %s Y_name = %s\n", X_name.c_str(),Y_name.c_str());
26268 printf (" -- X_template_parameter_position = %d Y_template_parameter_position = %d\n", X_template_parameter_position,Y_template_parameter_position);
26269 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() : "");
26270 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() : "");
26271 printf (" -- X_templateDecl->get_mangled_name() = %s\n", X_templateDecl->get_mangled_name().str());
26272 printf (" -- Y_templateDecl->get_mangled_name() = %s\n", Y_templateDecl->get_mangled_name().str());
26273#endif
26274 bool value = (X_parent == Y_parent);
26275
26276 if (value && X_templateDecl->get_is_template_param() && Y_templateDecl->get_is_template_param()) {
26277 value = (X_template_parameter_position == Y_template_parameter_position);
26278 } else if (value && X_templateDecl->get_is_class_member() && Y_templateDecl->get_is_class_member()) {
26279 value = (X_name == Y_name);
26280 }
26281
26282 counter--;
26283
26284 return value;
26285 }
26286 else
26287 {
26288 // DQ (2/13/2018): I an unclear if we are really done since they could have resolved to different types or the same type.
26289 // Nothing to do here since we have explored all uniform pairs of intermediate types possible.
26290#if 0
26291 printf ("Nothing to do here since we have explored all uniform pairs of intermediate types possible: isSame = %s \n",isSame ? "true" : "false");
26292 // printf (" --- X_element_type = %p = %s \n",X_element_type,X_element_type->unparseToString().c_str());
26293 // printf (" --- Y_element_type = %p = %s \n",Y_element_type,Y_element_type->unparseToString().c_str());
26294 printf (" --- lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26295 printf (" --- rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26296#endif
26297#if DEBUG_TYPE_EQUIVALENCE
26298 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");
26299#endif
26300 }
26301 }
26302 }
26303 } // end if reference type, pointer type, array type, and template type
26304
26305 SgModifierType* X_modifierType = isSgModifierType(X_element_type);
26306 SgModifierType* Y_modifierType = isSgModifierType(Y_element_type);
26307
26308#if DEBUG_TYPE_EQUIVALENCE
26309 printf ("In SageInterface::isEquivalentType(): counter = %d: type chain X_element_type = %p = %s Y_element_type = %p = %s \n",
26310 counter,X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26311#endif
26312
26313 if (X_modifierType != NULL && Y_modifierType != NULL)
26314 {
26315 // Handle the case of both modifiers.
26316#if DEBUG_TYPE_EQUIVALENCE
26317 printf ("In SageInterface::isEquivalentType(): loop: these are the both SgModifierType nodes: isSame = %s \n",isSame ? "true" : "false");
26318#endif
26319 if (X_modifierType == Y_modifierType)
26320 {
26321 isSame = true;
26322#if DEBUG_TYPE_EQUIVALENCE
26323 printf ("In SageInterface::isEquivalentType(): loop: these are the same modifier type: isSame = %s \n",isSame ? "true" : "false");
26324#endif
26325 }
26326 else
26327 {
26328 if (X_modifierType->get_typeModifier() == Y_modifierType->get_typeModifier())
26329 {
26330#if DEBUG_TYPE_EQUIVALENCE
26331 printf ("In SageInterface::isEquivalentType(): loop: these are equivalent modifiers: check the base type: isSame = %s \n",isSame ? "true" : "false");
26332#endif
26333 // Recursive call.
26334 // isSame = (*X_modifierType->get_base_type()) == (*Y_modifierType->get_base_type());
26335 isSame = isEquivalentType(X_modifierType->get_base_type(),Y_modifierType->get_base_type());
26336 }
26337 else
26338 {
26339#if DEBUG_TYPE_EQUIVALENCE
26340 printf ("In SageInterface::isEquivalentType(): loop: these are not equivalent modifier types: check for default settings: isSame = %s \n",isSame ? "true" : "false");
26341#endif
26342 // DQ (5/22/2016): fixing bug which cansed infinite recursion (case there the SgModifiers were different).
26343 bool skippingOverIdentityModifier = false;
26344
26345 if (X_modifierType->get_typeModifier().isIdentity() == true)
26346 {
26347#if DEBUG_TYPE_EQUIVALENCE
26348 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26349#endif
26350 X_element_type = X_modifierType->get_base_type();
26351
26352 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26353 skippingOverIdentityModifier = true;
26354 }
26355
26356 if (Y_modifierType->get_typeModifier().isIdentity() == true)
26357 {
26358#if DEBUG_TYPE_EQUIVALENCE
26359 printf ("In SageInterface::isEquivalentType(): loop: found self-similar setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26360#endif
26361 Y_element_type = Y_modifierType->get_base_type();
26362
26363 // DQ (5/22/2016): Record that progress was made in uncovering the relevant base type, and trigger reevaluation.
26364 skippingOverIdentityModifier = true;
26365 }
26366
26367 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26368#if DEBUG_TYPE_EQUIVALENCE
26369 printf ("In SageInterface::isEquivalentType(): loop: skippingOverIdentityModifier = %s \n",skippingOverIdentityModifier ? "true" : "false");
26370#endif
26371 // Recursive call on non-default modifier base types.
26372 // isSame = (*X_element_type) == (*Y_element_type);
26373 // isSame = isEquivalentType(X_element_type,Y_element_type);
26374 if (skippingOverIdentityModifier == true)
26375 {
26376#if DEBUG_TYPE_EQUIVALENCE
26377 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");
26378#endif
26379 // If we have made progress in skipping over an identity modifier then we need to reevaluate if these are the equivalent types.
26380 isSame = isEquivalentType(X_element_type,Y_element_type);
26381 }
26382 else
26383 {
26384 // 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).
26385 isSame = false;
26386#if DEBUG_TYPE_EQUIVALENCE
26387 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");
26388#endif
26389 }
26390
26391#if DEBUG_TYPE_EQUIVALENCE
26392 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isSame = %s \n",isSame ? "true" : "false");
26393#endif
26394 }
26395 }
26396 }
26397 else
26398 {
26399 // At least one of these is not a SgModifierType.
26400
26401 if (X_modifierType != NULL || Y_modifierType != NULL)
26402 {
26403 bool isReduceable = false;
26404
26405 if (X_modifierType != NULL && X_modifierType->get_typeModifier().isIdentity() == true)
26406 {
26407#if DEBUG_TYPE_EQUIVALENCE
26408 printf ("In SageInterface::isEquivalentType(): loop: found default setting for lhs: isSame = %s \n",isSame ? "true" : "false");
26409#endif
26410 X_element_type = X_modifierType->get_base_type();
26411 isReduceable = true;
26412 }
26413
26414 if (Y_modifierType != NULL && Y_modifierType->get_typeModifier().isIdentity() == true)
26415 {
26416#if DEBUG_TYPE_EQUIVALENCE
26417 printf ("In SageInterface::isEquivalentType(): loop: found default setting for rhs: isSame = %s \n",isSame ? "true" : "false");
26418#endif
26419 Y_element_type = Y_modifierType->get_base_type();
26420 isReduceable = true;
26421 }
26422
26423 // NOTE: If either of these are a SgTypedefType then the typedefs will be stripped away at the top of the recursive call.
26424#if DEBUG_TYPE_EQUIVALENCE
26425 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s \n",isReduceable ? "true" : "false");
26426#endif
26427 if (isReduceable == true)
26428 {
26429 // Recursive call on non-default modifier base types.
26430 // isSame = (*X_element_type) == (*Y_element_type);
26431 isSame = isEquivalentType(X_element_type,Y_element_type);
26432 }
26433 else
26434 {
26435 // Neither of these types were reducable.
26436 isSame = false;
26437 }
26438
26439#if DEBUG_TYPE_EQUIVALENCE
26440 printf ("In SageInterface::isEquivalentType(): loop: these are different modifier types: after recursive call to compare base types: isReduceable = %s isSame = %s \n",
26441 isReduceable ? "true" : "false",isSame ? "true" : "false");
26442#endif
26443 }
26444 else
26445 {
26446 // Neither of these are SgModifierType nodes.
26447 // X_element_type = X_element_type->stripType( STRIP_TYPEDEF_TYPE );
26448 // Y_element_type = Y_element_type->stripType( STRIP_TYPEDEF_TYPE );
26449
26450 if (X_element_type == Y_element_type)
26451 {
26452 isSame = true;
26453#if DEBUG_TYPE_EQUIVALENCE || 0
26454 // printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s \n",isSame ? "true" : "false");
26455 printf ("In SageInterface::isEquivalentType(): resolved to equal types: isSame = %s lhs = %p = %s rhs = %p = %s \n",
26456 isSame ? "true" : "false",lhs,lhs->unparseToString().c_str(),rhs,rhs->unparseToString().c_str());
26457#endif
26458#if DEBUG_TYPE_EQUIVALENCE || 0
26459 // DQ (2/13/2018): Debugging type equivalence. If they are the same typedef, they
26460 // still might not be interchangable if one is defined in a restrcited scope.
26461 const SgTypedefType* lhs_typedefType = isSgTypedefType(lhs);
26462 const SgTypedefType* rhs_typedefType = isSgTypedefType(rhs);
26463
26464 if (lhs_typedefType != NULL || rhs_typedefType != NULL)
26465 {
26466#if 0
26467 if (lhs_typedefType != NULL)
26468 {
26469 printf ("lhs was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26470 }
26471 if (rhs_typedefType != NULL)
26472 {
26473 printf ("rhs was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26474 }
26475#else
26476 printf (" --- one was a typedef: lhs = %p = %s \n",lhs,lhs->unparseToString().c_str());
26477 printf (" --- one was a typedef: rhs = %p = %s \n",rhs,rhs->unparseToString().c_str());
26478#endif
26479 }
26480#endif
26481 }
26482 else
26483 {
26484 // DQ (3/20/2016): This is reported by GNU as set but not used.
26485 // bool isReduceable = false;
26486
26487 // DQ (11/29/2015): We need to handle reference (when they are both references we can support then uniformally).
26488 SgReferenceType* X_referenceType = isSgReferenceType(X_element_type);
26489 SgReferenceType* Y_referenceType = isSgReferenceType(Y_element_type);
26490
26491 if (X_referenceType != NULL || Y_referenceType != NULL)
26492 {
26493#if 0
26494 if (X_referenceType != NULL)
26495 {
26496 X_element_type = X_referenceType->get_base_type();
26497
26498 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26499 // isReduceable = true;
26500 isReduceable = false;
26501 }
26502
26503 if (Y_referenceType != NULL)
26504 {
26505 Y_element_type = Y_referenceType->get_base_type();
26506
26507 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a reference.
26508 // isReduceable = true;
26509 isReduceable = false;
26510 }
26511
26512 if (isReduceable == true)
26513 {
26514 // Recursive call on non-default modifier base types.
26515 // isSame = (*X_element_type) == (*Y_element_type);
26516 isSame = isEquivalentType(X_element_type,Y_element_type);
26517 }
26518 else
26519 {
26520 // Neither of these types were reducable.
26521 isSame = false;
26522 }
26523#else
26524 isSame = false;
26525#endif
26526 }
26527 else
26528 {
26529 // Recursive call on non-typedef base types.
26530 // isSame = (*X_element_type) == (*Y_element_type);
26531 // isSame = isEquivalentType(X_element_type,Y_element_type);
26532
26533#if DEBUG_TYPE_EQUIVALENCE
26534 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26535#endif
26536
26537 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26538 SgPointerType* X_pointerType = isSgPointerType(X_element_type);
26539 SgPointerType* Y_pointerType = isSgPointerType(Y_element_type);
26540
26541 if (X_pointerType != NULL || Y_pointerType != NULL)
26542 {
26543#if 0
26544 if (X_pointerType != NULL)
26545 {
26546 X_element_type = X_pointerType->get_base_type();
26547
26548 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26549 // isReduceable = true;
26550 isReduceable = false;
26551 }
26552
26553 if (Y_pointerType != NULL)
26554 {
26555 Y_element_type = Y_pointerType->get_base_type();
26556
26557 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a pointer.
26558 // isReduceable = true;
26559 isReduceable = false;
26560 }
26561
26562 if (isReduceable == true)
26563 {
26564 // Recursive call on non-default modifier base types.
26565 // isSame = (*X_element_type) == (*Y_element_type);
26566 isSame = isEquivalentType(X_element_type,Y_element_type);
26567 }
26568 else
26569 {
26570 // Neither of these types were reducable.
26571 isSame = false;
26572 }
26573#else
26574 isSame = false;
26575#endif
26576 }
26577 else
26578 {
26579 // Recursive call on non-typedef base types.
26580 // isSame = (*X_element_type) == (*Y_element_type);
26581 // isSame = isEquivalentType(X_element_type,Y_element_type);
26582
26583#if DEBUG_TYPE_EQUIVALENCE
26584 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26585#endif
26586
26587 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26588 SgArrayType* X_arrayType = isSgArrayType(X_element_type);
26589 SgArrayType* Y_arrayType = isSgArrayType(Y_element_type);
26590
26591 if (X_arrayType != NULL || Y_arrayType != NULL)
26592 {
26593#if 0
26594 if (X_arrayType != NULL)
26595 {
26596 X_element_type = X_arrayType->get_base_type();
26597
26598 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26599 // isReduceable = true;
26600 isReduceable = false;
26601 }
26602
26603 if (Y_arrayType != NULL)
26604 {
26605 Y_element_type = Y_arrayType->get_base_type();
26606
26607 // DQ (12/8/2015): Note that we don't want to compare base types if only one of these was a array.
26608 // isReduceable = true;
26609 isReduceable = false;
26610 }
26611
26612 if (isReduceable == true)
26613 {
26614 // Recursive call on non-default modifier base types.
26615 // isSame = (*X_element_type) == (*Y_element_type);
26616 isSame = isEquivalentType(X_element_type,Y_element_type);
26617 }
26618 else
26619 {
26620 // Neither of these types were reducable.
26621 isSame = false;
26622 }
26623#else
26624 isSame = false;
26625#endif
26626 }
26627 else
26628 {
26629 // Recursive call on non-typedef base types.
26630 // isSame = (*X_element_type) == (*Y_element_type);
26631 // isSame = isEquivalentType(X_element_type,Y_element_type);
26632
26633#if DEBUG_TYPE_EQUIVALENCE
26634 printf ("In SageInterface::isEquivalentType(): loop: evaluation of inner types: isSame = %s \n",isSame ? "true" : "false");
26635#endif
26636
26637 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26638 SgFunctionType* X_functionType = isSgFunctionType(X_element_type);
26639 SgFunctionType* Y_functionType = isSgFunctionType(Y_element_type);
26640
26641 if (X_functionType != NULL || Y_functionType != NULL)
26642 {
26643 bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (X_functionType == Y_functionType) );
26644 //TODO: Liao, 9/15/2016, better comparison of function types
26645 //bool value = ( (X_functionType != NULL && Y_functionType != NULL) && (isEquivalentFunctionType(X_functionType, Y_functionType)) );
26646#if DEBUG_TYPE_EQUIVALENCE || 0
26647 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgFunctionType: value = %s \n",value ? "true" : "false");
26648#endif
26649 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26650 // isSame == value;
26651 isSame = value;
26652
26653 // DQ (3/20/2016): This is reported by GNU as set but not used.
26654 // isReduceable = false;
26655 }
26656 else
26657 {
26658 // Recursive call on non-typedef base types.
26659 // isSame = isEquivalentType(X_element_type,Y_element_type);
26660
26661 // DQ (11/29/2015): We need to handle pointers (when they are both pointers we can support then uniformally).
26662 SgMemberFunctionType* X_memberFunctionType = isSgMemberFunctionType(X_element_type);
26663 SgMemberFunctionType* Y_memberFunctionType = isSgMemberFunctionType(Y_element_type);
26664
26665 if (X_memberFunctionType != NULL || Y_memberFunctionType != NULL)
26666 {
26667 // DQ (12/15/2015): This code should be unreachable since it would have executed the code above (the case of SgFunctionType).
26668 printf ("This should be unreachable code \n");
26669 ROSE_ABORT();
26670
26671#if 0 // [Robb Matzke 2021-03-24]: unreachable
26672 bool value = ( (X_memberFunctionType != NULL && Y_memberFunctionType != NULL) && (X_memberFunctionType == Y_memberFunctionType) );
26673#if DEBUG_TYPE_EQUIVALENCE || 0
26674 printf ("In SageInterface::isEquivalentType(): loop: Process case of SgMemberFunctionType: value = %s \n",value ? "true" : "false");
26675#endif
26676 // DQ (3/20/2016): This is reported by GNU as a meaningless statement.
26677 // isSame == value;
26678 isSame = value;
26679#endif
26680 }
26681 else
26682 {
26683 // Recursive call on non-typedef base types.
26684 // isSame = isEquivalentType(X_element_type,Y_element_type);
26685#if 0
26686 // Check for irreducable types.
26687 bool X_isReduceable = true;
26688 if (isSgTypeSignedLong(X_element_type) != NULL ||
26689 isSgTypeUnsignedInt(X_element_type) != NULL ||
26690 isSgTypeBool(X_element_type) != NULL ||
26691 isSgTypeInt(X_element_type) != NULL)
26692 {
26693 X_isReduceable = false;
26694 }
26695
26696 bool Y_isReduceable = true;
26697 if (isSgTypeSignedLong(Y_element_type) != NULL ||
26698 isSgTypeUnsignedInt(Y_element_type) != NULL ||
26699 isSgTypeBool(Y_element_type) != NULL ||
26700 isSgTypeInt(Y_element_type) != NULL)
26701 {
26702 Y_isReduceable = false;
26703 }
26704#if DEBUG_TYPE_EQUIVALENCE || 0
26705 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_isReduceable = %s Y_isReduceable = %s \n",
26706 X_isReduceable ? "true" : "false",Y_isReduceable ? "true" : "false");
26707#endif
26708 if (X_isReduceable == true || Y_isReduceable == true)
26709 {
26710 // Recursive call on non-default modifier base types.
26711 isSame = isEquivalentType(X_element_type,Y_element_type);
26712 }
26713 else
26714 {
26715 // Neither of these types were reducable.
26716 isSame = false;
26717 }
26718#else
26719 // DQ (12/20/2015): This is the default case for irreducable types.
26720 if (X_element_type->variantT() == Y_element_type->variantT())
26721 {
26722#if DEBUG_TYPE_EQUIVALENCE || 0
26723 printf ("In SageInterface::isEquivalentType(): loop: Process default case: X_element_type = %p = %s Y_element_type = %p = %s \n",
26724 X_element_type,X_element_type->class_name().c_str(),Y_element_type,Y_element_type->class_name().c_str());
26725#endif
26726 // DQ (5/26/2016): It is not good enough that the variants match.
26727 // isSame = true;
26728 // isSame = isEquivalentType(X_element_type,Y_element_type);
26729 isSame = (X_element_type == Y_element_type);
26730 }
26731 else
26732 {
26733 // Neither of these types were reducable or equal.
26734 isSame = false;
26735 }
26736#endif
26737 }
26738 }
26739 }
26740 }
26741 }
26742 }
26743 }
26744 }
26745
26746 // Decrement the static variable to control the recursive depth while we debug this.
26747 counter--;
26748
26749#if DEBUG_TYPE_EQUIVALENCE || 0
26750 printf ("In SageInterface::isEquivalentType(): isSame = %s \n",isSame ? "true" : "false");
26751#endif
26752
26753#if DEBUG_TYPE_EQUIVALENCE || 0
26754 if (counter == 1 && isSame == true)
26755 {
26756 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());
26757
26758 // Debugging output.
26759 Rose_STL_Container<SgType*> X_typeChain = X.getInternalTypes();
26760 Rose_STL_Container<SgType*> Y_typeChain = Y.getInternalTypes();
26761
26762 // Debugging output.
26763 printf (" --- Output of type chain for lhs: \n");
26764 for (size_t i = 0; i < X_typeChain.size(); i++)
26765 {
26766 SgType* element_type = X_typeChain[i];
26767 printf (" --- --- X_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26768 SgModifierType* modifierType = isSgModifierType(element_type);
26769 if (modifierType != NULL)
26770 {
26771 // modifierType->get_typeModifier().display("X type chain");
26772 string s = modifierType->get_typeModifier().displayString();
26773 printf (" --- type chain modifier: %s \n",s.c_str());
26774 }
26775 }
26776
26777 printf (" --- Output of type chain for rhs: \n");
26778 for (size_t i = 0; i < Y_typeChain.size(); i++)
26779 {
26780 SgType* element_type = Y_typeChain[i];
26781 printf (" --- --- Y_element_type = %p = %s \n",element_type,element_type->class_name().c_str());
26782 SgModifierType* modifierType = isSgModifierType(element_type);
26783 if (modifierType != NULL)
26784 {
26785 // modifierType->get_typeModifier().display("Y type chain");
26786 string s = modifierType->get_typeModifier().displayString();
26787 printf (" --- --- type chain modifier: %s \n",s.c_str());
26788 }
26789 }
26790 }
26791#endif
26792
26793#if 0
26794 if (counter == 0)
26795 {
26796 if (isSame == true)
26797 {
26798 // 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());
26799 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26800 // printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26801 // printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26802 printf (" --- --- X_element_type = %p = %s = %s \n",X_element_type,X_element_type->class_name().c_str(),X_element_type->unparseToString().c_str());
26803 printf (" --- --- Y_element_type = %p = %s = %s \n",Y_element_type,Y_element_type->class_name().c_str(),Y_element_type->unparseToString().c_str());
26804 }
26805 else
26806 {
26807 // 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());
26808 printf (" --- isSame = %s \n",isSame ? "true" : "false");
26809 }
26810 }
26811 else
26812 {
26813 printf (" --- counter = %d \n",counter);
26814 }
26815#endif
26816
26817 return isSame;
26818 }
26819
26820
26821#if 0
26822// This is modified to be a template function and so must be moved to the header file.
26823// DQ (8/30/2016): Added function to detect EDG AST normalization.
26824bool
26825SageInterface::isNormalizedTemplateInstantiation (SgFunctionDeclaration* function)
26826 {
26827 // This function is called in the Call graph generation to avoid filtering out EDG normalized
26828 // function template instnatiations (which come from normalized template functions and member functions).
26829
26830 bool retval = false;
26831
26832#if 1
26833 // DQ (8/30/2016): We need to mark this as an EDG normalization so that we can detect it as an exception
26834 // to some simple attempts to filter the AST (e.g. for the Call Graph implementation which filters on only
26835 // functions in the current directory). This explicit makring makes it much easier to get this test correct.
26836 // But we still need to look at if the location of the parent template is something that we wnat to output.
26837 // If tis is a template instantiation then it is not enough to look only at the non-defining declaration if
26838 // it is not compiler generated.
26839 retval = function->get_marked_as_edg_normalization();
26840#else
26841 // Test for this to be a template instantation (in which case it was marked as
26842 // compiler generated but we may want to allow it to be used in the call graph,
26843 // if it's template was a part was defined in the current directory).
26844 SgTemplateInstantiationFunctionDecl* templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(function);
26845 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(function);
26846
26847 if (templateInstantiationFunction != NULL)
26848 {
26849 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26850 templateInstantiationFunction = isSgTemplateInstantiationFunctionDecl(templateInstantiationFunction->get_firstNondefiningDeclaration());
26851 SgTemplateFunctionDeclaration* templateFunctionDeclaration = templateInstantiationFunction->get_templateDeclaration();
26852 if (templateFunctionDeclaration != NULL)
26853 {
26854 // retval = operator()(templateFunctionDeclaration);
26855 retval = (templateFunctionDeclaration->isCompilerGenerated() == false);
26856 }
26857 else
26858 {
26859 // Assume false.
26860 }
26861
26862#if DEBUG_SELECTOR
26863 printf (" --- case of templateInstantiationFunction: retval = %s \n",retval ? "true" : "false");
26864#endif
26865 }
26866 else
26867 {
26868 if (templateInstantiationMemberFunction != NULL)
26869 {
26870 // When the defining function has been normalized by EDG, only the non-defining declaration will have a source position.
26871 templateInstantiationMemberFunction = isSgTemplateInstantiationMemberFunctionDecl(templateInstantiationMemberFunction->get_firstNondefiningDeclaration());
26872 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = templateInstantiationMemberFunction->get_templateDeclaration();
26873 if (templateMemberFunctionDeclaration != NULL)
26874 {
26875 // retval = operator()(templateMemberFunctionDeclaration);
26876 retval = (templateMemberFunctionDeclaration->isCompilerGenerated() == false);
26877 }
26878 else
26879 {
26880 // Assume false.
26881 }
26882
26883#if DEBUG_SELECTOR
26884 printf (" --- case of templateInstantiationMemberFunction: retval = %s \n",retval ? "true" : "false");
26885#endif
26886 }
26887 }
26888#endif
26889
26890 return retval;
26891 }
26892#endif
26893
26894void SageInterface::detectCycleInType(SgType * type, const std::string & from) {
26895#if 0
26896 printf("In detectCycleInType():\n");
26897 printf(" -- from = %s\n", from.c_str());
26898 printf(" -- type = %p (%s)\n", type, type->class_name().c_str());
26899#endif
26900 std::vector<SgType *> seen_types;
26901
26902 while (type != NULL) {
26903
26904 // DQ (4/15/2019): Added assertion.
26905 ROSE_ASSERT(type != NULL);
26906
26907 std::vector<SgType *>::const_iterator it = std::find(seen_types.begin(), seen_types.end(), type);
26908 if (it != seen_types.end()) {
26909 printf("ERROR: Cycle found in type = %p (%s):\n", type, type->class_name().c_str());
26910 size_t i = 0;
26911 for (; it != seen_types.end(); it++) {
26912 printf(" [%zd] %p (%s)\n", i, *it, (*it)->class_name().c_str());
26913 i++;
26914 }
26915 printf("-> detectCycleInType() was called from: %s\n", from.c_str());
26916 ROSE_ABORT();
26917 }
26918 seen_types.push_back(type);
26919
26920 SgModifierType * modType = isSgModifierType(type);
26921 SgPointerType * pointType = isSgPointerType(type);
26922 SgReferenceType * refType = isSgReferenceType(type);
26923 SgArrayType * arrayType = isSgArrayType(type);
26924 SgTypedefType * typedefType = isSgTypedefType(type);
26925
26926#if 0
26927 // DQ (4/15/2019): Don't count SgPointerMemberType (also fixed in SgType::stripType() function).
26928 if (isSgPointerMemberType(type) != NULL)
26929 {
26930 pointType = NULL;
26931 }
26932#endif
26933
26934 if ( modType ) {
26935 type = modType->get_base_type();
26936 } else if ( refType ) {
26937 type = refType->get_base_type();
26938 } else if ( pointType ) {
26939 type = pointType->get_base_type();
26940 // } else if ( pointerMemberType ) {
26941 // type = pointerMemberType->get_base_type();
26942 } else if ( arrayType ) {
26943 type = arrayType->get_base_type();
26944 } else if ( typedefType ) {
26945 type = typedefType->get_base_type();
26946 } else {
26947 break;
26948 }
26949 ROSE_ASSERT(type != NULL);
26950 }
26951}
26952
26953
26954#if 0
26955// DQ (11/10/2019): Older original version of the function.
26956
26957// DQ (6/6/2019): Move this to the SageInteface namespace.
26958void
26960 {
26961 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
26962 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
26963 // declarations in the outlined code we can support the outpiled code with those references. This
26964 // approach has the added advantage of also supporting the same include file tree as the original
26965 // file where the outlined code is being taken from.
26966
26967 class TransformFunctionDefinitionsTraversal : public AstSimpleProcessing
26968 {
26969 public:
26970 std::vector<SgFunctionDeclaration*> functionList;
26971 SgSourceFile* sourceFile;
26972 int sourceFileId;
26973 string filenameWithPath;
26974
26975 public:
26976 TransformFunctionDefinitionsTraversal(): sourceFile(NULL), sourceFileId(-99) {}
26977
26978 void visit (SgNode* node)
26979 {
26980#if 0
26981 printf ("In convertFunctionDefinitionsToFunctionPrototypes visit(): node = %p = %s \n",node,node->class_name().c_str());
26982#endif
26983 SgSourceFile* temp_sourceFile = isSgSourceFile(node);
26984 if (temp_sourceFile != NULL)
26985 {
26986 sourceFile = temp_sourceFile;
26987 sourceFileId = sourceFile->get_file_info()->get_file_id();
26988
26989 // The file_id is not sufficnet, not clear why, but the filenames match.
26990 filenameWithPath = sourceFile->get_sourceFileNameWithPath();
26991
26992 printf ("Found source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
26993
26994 }
26995
26996 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
26997 if (functionDeclaration != NULL)
26998 {
26999 // This should have been set already.
27000 ROSE_ASSERT(sourceFile != NULL);
27001
27002 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27003 if (functionDeclaration == definingFunctionDeclaration)
27004 {
27005#if 1
27006 printf ("Found a defining function declaration: functionDeclaration = %p = %s name = %s \n",
27007 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
27008
27009 printf (" --- recorded source file: id = %d name = %s \n",sourceFileId,sourceFile->get_sourceFileNameWithPath().c_str());
27010 printf (" --- source file: file_info: id = %d name = %s \n",
27011 functionDeclaration->get_file_info()->get_file_id(),functionDeclaration->get_file_info()->get_filenameString().c_str());
27012#endif
27013 // DQ (3/20/2019): The file_id is not sufficent, using the filename with path to do string equality.
27014 // bool isInSourceFile = (sourceFileId == functionDeclaration->get_file_info()->get_file_id());
27015 bool isInSourceFile = (filenameWithPath == functionDeclaration->get_file_info()->get_filenameString());
27016#if 1
27017 printf (" --- isInSourceFile = %s \n",isInSourceFile ? "true" : "false");
27018#endif
27019 // Remove the defining declaration as a test.
27020 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27021 if (isInSourceFile == true && functionDeclarationScope != NULL)
27022 {
27023#if 1
27024 printf (" --- Found a defining function declaration: functionDeclarationScope = %p = %s \n",
27025 functionDeclarationScope,functionDeclarationScope->class_name().c_str());
27026#endif
27027 // functionDeclarationScope->removeStatement(functionDeclaration);
27028 // removeStatement(functionDeclaration);
27029 functionList.push_back(functionDeclaration);
27030 }
27031 }
27032 }
27033 }
27034 };
27035
27036 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27037 TransformFunctionDefinitionsTraversal traversal;
27038 traversal.traverse(node, preorder);
27039
27040 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27041
27042#if 1
27043 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): functionList.size() = %zu \n",functionList.size());
27044#endif
27045
27046 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27047 while (i != functionList.end())
27048 {
27049 SgFunctionDeclaration* functionDeclaration = *i;
27050 ROSE_ASSERT(functionDeclaration != NULL);
27051
27052 SgFunctionDeclaration* nondefiningFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27053 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27054
27055#if 1
27056 printf (" --- Removing function declaration: functionDeclaration = %p = %s name = %s \n",
27057 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
27058#endif
27059 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27060 // removeStatement(functionDeclaration);
27061 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration);
27062
27063 i++;
27064 }
27065
27066#if 0
27067 printf ("In convertFunctionDefinitionsToFunctionPrototypes(): exiting as a test! \n");
27068 ROSE_ABORT();
27069#endif
27070 }
27071#endif
27072
27073
27074void
27076 {
27077 // DQ (10/31/2020): Display function for scopes (useful for debugging).
27078 ROSE_ASSERT(scope != NULL);
27079
27080 printf ("Output the statements in scope = %p = %s \n",scope,scope->class_name().c_str());
27081
27082 // This makes a copy (on the stack) and is inefficent, but this is only for debugging.
27083 SgStatementPtrList statementList = scope->generateStatementList();
27084 for (size_t i = 0; i < statementList.size(); i++)
27085 {
27086 SgStatement* statement = statementList[i];
27087 printf (" --- statement: %zu ptr: %p IR node: %s name: %s \n",i,statement,statement->class_name().c_str(),SageInterface::get_name(statement).c_str());
27088 }
27089
27090#if 0
27091 printf ("Exiting as a test at the end of evaluation of global scope! \n");
27092 ROSE_ABORT();
27093#endif
27094 }
27095
27096
27099 {
27100 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27101 // SgDeclarationStatement* nondefiningFunctionDeclaration = NULL;
27102
27103#if 0
27104 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p = %s name = %s \n",
27105 functionDeclaration,functionDeclaration->class_name().c_str(),functionDeclaration->get_name().str());
27106#endif
27107
27108 // DQ (11/21/2019): Check if this is a constructor, this is a temporary fix.
27109 bool isConstructor = false;
27110 SgMemberFunctionDeclaration* tmp_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27111 if (tmp_memberFunctionDeclaration != NULL)
27112 {
27113 isConstructor = tmp_memberFunctionDeclaration->get_specialFunctionModifier().isConstructor();
27114
27115#if 0
27116 if (isConstructor == true)
27117 {
27118 printf ("Skipping case of constructors (in building prototype from defining function declaration) \n");
27119 return;
27120 }
27121#endif
27122 }
27123
27124 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27125 // bool replaceWithEmptyDeclaration = false;
27126 // SgDeclarationStatement* emptyDeclaration = NULL;
27127
27128 SgName name = functionDeclaration->get_name();
27129 SgType* return_type = functionDeclaration->get_type()->get_return_type();
27130
27131#if 0
27132 // DQ (12/10/2020): The issue is that the default arguments defined in template functions are represented in the AST.
27133 // Where we output the template as a string, it is included, and in the template instantiation it is represented in
27134 // the AST. So where it is used, default arguments are not represented in the AST and so the are not generated in
27135 // this function that builds the function prototype from the defining function.
27136
27137 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration = %p \n",functionDeclaration);
27138 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_firstNondefiningDeclaration() = %p \n",functionDeclaration->get_firstNondefiningDeclaration());
27139 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_definingDeclaration() = %p \n",functionDeclaration->get_definingDeclaration());
27140
27141 // DQ (12/9/2020): Check if there is a default argument. Need to figure out how default arguments
27142 // are specified in the function declarations, and make sure the prototype reproduces them.
27143 for (size_t i = 0; i < functionDeclaration->get_args().size(); i++)
27144 {
27145 SgInitializedName* arg = functionDeclaration->get_args()[i];
27146#if 1
27147 printf ("In SageInterface::buildFunctionPrototype(): functionDeclaration->get_args(): (i = %zu) arg = %p = %s isDefaultArgument = %s \n",
27148 i,arg,arg->get_name().str(),arg->get_file_info()->isDefaultArgument() ? "true" : "false");
27149 printf (" --- arg->get_initializer() = %p \n",arg->get_initializer());
27150#endif
27151 if (arg->get_file_info()->isDefaultArgument() == true)
27152 {
27153 printf ("NOTE: default argument (i = %zu) not reproduced in function prototype: arg = %p = %s \n",i,arg,arg->get_name().str());
27154 }
27155 }
27156#endif
27157
27158#if 1
27159 SgFunctionParameterList* param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
27160#else
27161 // 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).
27162 // SgFunctionParameterList *param_list = functionDeclaration->get_parlist();
27163 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27164 SgFunctionParameterList* param_list = NULL;
27165
27166 if (templateInstantiationFunctionDecl == NULL)
27167 {
27168 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
27169 }
27170 else
27171 {
27172 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27173 if (templateInstantiationMemberFunctionDecl == NULL)
27174 {
27175 param_list = buildFunctionParameterList( functionDeclaration->get_type()->get_argument_list());
27176 }
27177 }
27178#endif
27179
27180
27181 // bool isTemplateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration) != NULL);
27182 bool isTemplateInstantiationMemberFunctionDecl = false;
27183
27184 SgScopeStatement* scope = functionDeclaration->get_scope();
27185 // SgTemplateParameterPtrList* templateParameterList = NULL; // functionDeclaration->get_templateParameterList();
27186 SgExprListExp* python_decoratorList = NULL;
27187 bool buildTemplateInstantiation = false;
27188 SgTemplateArgumentPtrList* templateArgumentsList = NULL;
27189
27190 // DQ (9/26/2019): Tracing down a null parent pointer.
27191 // ROSE_ASSERT(param_list->get_parent() != NULL);
27192 // ROSE_ASSERT(param_list->get_parent() == NULL);
27193 ROSE_ASSERT(param_list == NULL || param_list->get_parent() == NULL);
27194
27195 switch (functionDeclaration->variantT())
27196 {
27197 case V_SgTemplateMemberFunctionDeclaration:
27198 {
27199#if 0
27200 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template member functions \n");
27201#endif
27202 SgTemplateMemberFunctionDeclaration* original_templateMemberFunctionDeclaration = isSgTemplateMemberFunctionDeclaration(functionDeclaration);
27203 ROSE_ASSERT(original_templateMemberFunctionDeclaration != NULL);
27204
27205 SgTemplateMemberFunctionDeclaration* templateMemberFunctionDeclaration = NULL;
27206
27207 unsigned int functionConstVolatileFlags = 0;
27208
27209 ROSE_ASSERT(original_templateMemberFunctionDeclaration->get_type() != NULL);
27210
27211 // Need to call:
27212 // unsigned int get_mfunc_specifier();
27213
27214 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_templateMemberFunctionDeclaration->get_type());
27215 ROSE_ASSERT(memberFunctionType != NULL);
27216
27217 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27218
27219 // SgTemplateMemberFunctionDeclaration*
27220 // buildNondefiningTemplateMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27221 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, SgTemplateParameterPtrList* templateParameterList );
27222
27223 SgTemplateParameterPtrList templateParameterList = original_templateMemberFunctionDeclaration->get_templateParameters();
27224 // ROSE_ASSERT(templateParameterList != NULL);
27225
27226 templateMemberFunctionDeclaration =
27227 buildNondefiningTemplateMemberFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags, &templateParameterList );
27228#if 0
27229 printf ("ERROR: Template functions are not yet supported! \n");
27230 ROSE_ABORT();
27231#endif
27232 nondefiningFunctionDeclaration = templateMemberFunctionDeclaration;
27233
27234 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27235
27236 // DQ (11/21/2019): Handle constructors.
27237 if (isConstructor == true)
27238 {
27239 templateMemberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27240 }
27241
27242 break;
27243 }
27244
27245 case V_SgTemplateFunctionDeclaration:
27246 {
27247#if 0
27248 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support template functions \n");
27249#endif
27250 SgTemplateFunctionDeclaration* original_templateFunctionDeclaration = isSgTemplateFunctionDeclaration(functionDeclaration);
27251 ROSE_ASSERT(original_templateFunctionDeclaration != NULL);
27252
27253 SgTemplateFunctionDeclaration* templateFunctionDeclaration = NULL; // isSgTemplateFunctionDeclaration(functionDeclaration);
27254
27255 // SgTemplateFunctionDeclaration*
27256 // buildNondefiningTemplateFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27257 // SgScopeStatement* scope=NULL, SgExprListExp* decoratorList = NULL, SgTemplateParameterPtrList* templateParameterList = NULL);
27258
27259 SgTemplateParameterPtrList templateParameterList = original_templateFunctionDeclaration->get_templateParameters();
27260
27261 templateFunctionDeclaration = buildNondefiningTemplateFunctionDeclaration ( name, return_type, param_list, scope, python_decoratorList, &templateParameterList );
27262#if 0
27263 printf ("ERROR: Template functions are not yet supported! \n");
27264 ROSE_ABORT();
27265#endif
27266 nondefiningFunctionDeclaration = templateFunctionDeclaration;
27267
27268 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27269
27270 break;
27271 }
27272
27273 // DQ (10/29/2020): Added new case.
27274 case V_SgTemplateInstantiationMemberFunctionDecl:
27275 {
27276 buildTemplateInstantiation = true;
27277
27278 isTemplateInstantiationMemberFunctionDecl = true;
27279
27280 SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDecl = isSgTemplateInstantiationMemberFunctionDecl(functionDeclaration);
27281 ROSE_ASSERT(templateInstantiationMemberFunctionDecl != NULL);
27282 templateArgumentsList = &(templateInstantiationMemberFunctionDecl->get_templateArguments());
27283#if 0
27284 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27285 // printf ("name from templateInstantiationMemberFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_template_name().str());
27286 printf ("name from templateInstantiationMemberFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationMemberFunctionDecl->get_templateName().str());
27287 SgTemplateMemberFunctionDeclaration* templateDeclaration = templateInstantiationMemberFunctionDecl->get_templateDeclaration();
27288 if (templateDeclaration != NULL)
27289 {
27290 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27291 printf ("name from templateInstantiationMemberFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27292 }
27293#endif
27294 // name = functionDeclaration->get_name();
27295 // name = templateInstantiationMemberFunctionDecl->get_template_name();
27296 name = templateInstantiationMemberFunctionDecl->get_templateName();
27297#if 0
27298 printf ("In case V_SgTemplateInstantiationMemberFunctionDecl: using name = %s \n",name.str());
27299#endif
27300 // DQ (10/29/2020): Change this to include the functionality to build the member function support without fall-through.
27301 }
27302 // fall through
27303 case V_SgMemberFunctionDeclaration:
27304 {
27305#if 0
27306 printf ("This function to replace the defining declaration with a non-defining declaration does not yet support member functions \n");
27307#endif
27308 SgMemberFunctionDeclaration* original_memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration);
27309 ROSE_ASSERT(original_memberFunctionDeclaration != NULL);
27310
27311 SgMemberFunctionDeclaration* memberFunctionDeclaration = NULL; // isSgMemberFunctionDeclaration(functionDeclaration);
27312
27313 // SgMemberFunctionDeclaration*
27314 // buildNondefiningMemberFunctionDeclaration (const SgName & name, SgType* return_type, SgFunctionParameterList *parlist,
27315 // SgScopeStatement* scope, SgExprListExp* decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList* templateArgumentsList);
27316
27317 unsigned int functionConstVolatileFlags = 0;
27318
27319 ROSE_ASSERT(original_memberFunctionDeclaration->get_type() != NULL);
27320
27321 // Need to call:
27322 // unsigned int get_mfunc_specifier();
27323
27324 // DQ (12/2/2019): If it is defined outside of the class, then don't replace with member function prototype,
27325 // since they is not allowed to be declared outside of the class they are a member of.
27326
27327 // We do want to build prototypes for template instantiation member functions, and template instantiation non-member functions (see below).
27328 bool buildPrototype = isTemplateInstantiationMemberFunctionDecl || original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope();
27329#if 0
27330 printf ("In SageInterface::buildFunctionPrototype(): buildPrototype = %s \n",buildPrototype ? "true" : "false");
27331#endif
27332 if (buildPrototype == true)
27333 {
27334 SgMemberFunctionType* memberFunctionType = isSgMemberFunctionType(original_memberFunctionDeclaration->get_type());
27335 ROSE_ASSERT(memberFunctionType != NULL);
27336#if 0
27337 printf ("original_memberFunctionDeclaration->get_parent() == original_memberFunctionDeclaration->get_scope() \n");
27338#endif
27339 functionConstVolatileFlags = memberFunctionType->get_mfunc_specifier();
27340
27341 memberFunctionDeclaration =
27343 ( name, return_type, param_list, scope, python_decoratorList, functionConstVolatileFlags,
27344 buildTemplateInstantiation,templateArgumentsList );
27345#if 0
27346 printf ("ERROR: Member functions are not yet supported! \n");
27347 ROSE_ABORT();
27348#endif
27349 // DQ (11/21/2019): Handle constructors.
27350 if (isConstructor == true)
27351 {
27352 memberFunctionDeclaration->get_specialFunctionModifier().setConstructor();
27353 }
27354
27355 nondefiningFunctionDeclaration = memberFunctionDeclaration;
27356
27357 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27358 }
27359 else
27360 {
27361 // Case of member function defined outside of it's class.
27362#if 0
27363 printf ("NOTE: Member functions defined outside of their class can not be output as member function prototypes (not allowed in C++) \n");
27364#endif
27365 // We want to build a SgEmptyDeclaration using buildEmptyDeclaration() but this is not a function.
27366 // nondefiningFunctionDeclaration = buildEmptyDeclaration();
27367 nondefiningFunctionDeclaration = NULL;
27368#if 0
27369 nondefiningFunctionDeclaration = NULL;
27370
27371 replaceWithEmptyDeclaration = true;
27372 emptyDeclaration = buildEmptyDeclaration();
27373 ROSE_ASSERT(emptyDeclaration != NULL);
27374#endif
27375 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27376 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27377
27378 // Since we din't build a member function we don't need the parameter list.
27379 delete param_list;
27380 param_list = NULL;
27381#if 0
27382 printf ("Exiting as a test! \n");
27383 ROSE_ABORT();
27384#endif
27385 }
27386
27387 // DQ (10/29/2020): Commented out as part of move to used SgFunctionDeclaration return type.
27388 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27389 break;
27390 }
27391
27392 case V_SgFunctionDeclaration:
27393 {
27394 // This is for a non-member non-template function declaration.
27395 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27396 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27397 break;
27398 }
27399
27400 // DQ (10/29/2020): Added new case.
27401 case V_SgTemplateInstantiationFunctionDecl:
27402 {
27403 // This is for a non-member non-template function declaration.
27404 buildTemplateInstantiation = true;
27405 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27406 ROSE_ASSERT(templateInstantiationFunctionDecl != NULL);
27407 templateArgumentsList = &(templateInstantiationFunctionDecl->get_templateArguments());
27408#if 0
27409 printf ("name from functionDeclaration->get_name(): name = %s \n",name.str());
27410 // printf ("name from templateInstantiationFunctionDecl->get_template_name(): template_name = %s \n",templateInstantiationFunctionDecl->get_template_name().str());
27411 printf ("name from templateInstantiationFunctionDecl->get_templateName(): template_name = %s \n",templateInstantiationFunctionDecl->get_templateName().str());
27412 SgTemplateFunctionDeclaration* templateDeclaration = templateInstantiationFunctionDecl->get_templateDeclaration();
27413 if (templateDeclaration != NULL)
27414 {
27415 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_name(): template_name = %s \n",templateDeclaration->get_name().str());
27416 printf ("name from templateInstantiationFunctionDecl->get_template_declaration()->get_template_name(): template_name = %s \n",templateDeclaration->get_template_name().str());
27417 }
27418#endif
27419 name = templateInstantiationFunctionDecl->get_templateName();
27420#if 0
27421 printf ("In case V_SgTemplateInstantiationFunctionDecl: using name = %s \n",name.str());
27422#endif
27423 nondefiningFunctionDeclaration = buildNondefiningFunctionDeclaration (name, return_type, param_list, scope, python_decoratorList, buildTemplateInstantiation,templateArgumentsList);
27424 ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27425 break;
27426 }
27427
27428 default:
27429 {
27430 // DQ (12/4/2019): If this is any other case than that handled above, then we just return.
27431 // These cases would be only template instantiations.
27432
27433 // Nothing to do, except delete the parameter list we built, and return.
27434 delete param_list;
27435 param_list = NULL;
27436
27437 return NULL;
27438 }
27439 }
27440
27441 // DQ (10/29/2020): We should be able to change this now that we support SgTemplateInstantiationFunctionDecl and SgTemplateInstantiationMemberFunctionDecl IR nodes.
27442 // DQ (9/26/2019): Tracing down a null parent pointer.
27443 ROSE_ASSERT(param_list == NULL || param_list->get_parent() != NULL);
27444 // ROSE_ASSERT(param_list != NULL);
27445 // ROSE_ASSERT(param_list->get_parent() != NULL);
27446
27447 // ROSE_ASSERT(nondefiningFunctionDeclaration != NULL);
27448
27449 if (nondefiningFunctionDeclaration != NULL)
27450 {
27451 if (nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() == NULL)
27452 {
27453#if 0
27454 printf ("Setting the firstNondefiningDeclaration \n");
27455#endif
27456 nondefiningFunctionDeclaration->set_firstNondefiningDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
27457 }
27458
27459 if (nondefiningFunctionDeclaration->get_definingDeclaration() == NULL)
27460 {
27461#if 0
27462 printf ("Setting the definingDeclaration \n");
27463#endif
27464 nondefiningFunctionDeclaration->set_definingDeclaration(functionDeclaration->get_definingDeclaration());
27465 }
27466
27467 ROSE_ASSERT(nondefiningFunctionDeclaration->get_firstNondefiningDeclaration() != NULL);
27468 ROSE_ASSERT(nondefiningFunctionDeclaration->get_definingDeclaration() != NULL);
27469
27470 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27471 if (nondefiningFunctionDeclaration != NULL)
27472 {
27473 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27474 // This is a bug in the support for building a new prototype from a defining function declaration
27475 // and caused this problem. This assertion will prevent this sort of error from happening again.
27476 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27477 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27478 }
27479 }
27480
27481 return nondefiningFunctionDeclaration;
27482 }
27483
27484
27485// 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).
27488 {
27489 SgFunctionDeclaration* nondefiningFunctionDeclaration = NULL;
27490 ROSE_ASSERT(functionDeclaration != NULL);
27491
27492#if 0
27493 printf ("****************************************************************** \n");
27494 printf ("Attached comments and CPP directives: defining functionDeclaration \n");
27495 SageInterface::printOutComments (functionDeclaration);
27496 printf ("****************************************************************** \n");
27497#endif
27498
27499 // 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.
27500
27501 nondefiningFunctionDeclaration = buildFunctionPrototype(functionDeclaration);
27502
27503 // DQ (12/17/2020): This is a required fix that was only caught as an issue by some customer code.
27504 if (nondefiningFunctionDeclaration != NULL)
27505 {
27506 // DQ (11/22/2020): These can't be the same list else we will have a case of iterator invalidation.
27507 // This is a bug in the support for building a new prototype from a defining function declaration
27508 // and caused this problem. This assertion will prevent this sort of error from happening again.
27509 ROSE_ASSERT(functionDeclaration->getAttachedPreprocessingInfo() == NULL ||
27510 functionDeclaration->getAttachedPreprocessingInfo() != nondefiningFunctionDeclaration->getAttachedPreprocessingInfo());
27511 }
27512
27513 SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDecl = isSgTemplateInstantiationFunctionDecl(functionDeclaration);
27514
27515 if (templateInstantiationFunctionDecl == NULL)
27516 {
27517 if (nondefiningFunctionDeclaration != NULL)
27518 {
27519 // DQ (10/29/2020): Match the associated declaration modifiers.
27520 nondefiningFunctionDeclaration->get_declarationModifier() = functionDeclaration->get_declarationModifier();
27521
27522 // DQ (11/11/2020): Match the associated other kinds of modifiers.
27523 nondefiningFunctionDeclaration->get_functionModifier() = functionDeclaration->get_functionModifier();
27524 nondefiningFunctionDeclaration->get_specialFunctionModifier() = functionDeclaration->get_specialFunctionModifier();
27525
27526 nondefiningFunctionDeclaration->set_linkage( functionDeclaration->get_linkage() );
27527 nondefiningFunctionDeclaration->set_externBrace( functionDeclaration->get_externBrace() );
27528
27529 ROSE_ASSERT(nondefiningFunctionDeclaration->get_forward() == true);
27530
27531 // DQ (10/15/2019): Set the physical_file_id of the transformation to match that of the original defining declaration.
27532 int file_id = functionDeclaration->get_file_info()->get_physical_file_id();
27533 nondefiningFunctionDeclaration->get_file_info()->set_physical_file_id(file_id);
27534
27535 // Likely we should build a new nondefining function declaration instead of reusing the existing non-defining declaration.
27536 // removeStatement(functionDeclaration);
27537 // DQ (11/22/2020): Note that this step will move the comments and CPP directives to the new statement
27538 // (better in this step than in the copy of the pointer to the list above, which cause an iterator invalidation error).
27539 // DQ (10/21/2020): I think we may want to return the orignal defining function declaration.
27540 // DQ (12/2/2019): Need to support member functions which can't be declared when outside of their class.
27541 // DQ (11/15/2020): Note that the default is false, and we need true.
27542 bool movePreprocessingInfo = true;
27543 replaceStatement(functionDeclaration,nondefiningFunctionDeclaration,movePreprocessingInfo);
27544
27545 // DQ (11/25/2020): This is the cause of a problem in the outliner caught in the resetParentPointer.C (definingDeclaration->get_parent() != __null).
27546 // 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.
27547 // This is the cause of a name qualification bug when the functionDeclaration is inserted into global scope and the name qualification
27548 // is not computed correctly (since the parent was still the namespace scope where it was originally.
27549 ROSE_ASSERT(nondefiningFunctionDeclaration->get_parent() != NULL);
27550 }
27551 }
27552 else
27553 {
27554 // DQ (7/12/2019): Template instantiations are not directly from the source code, so we don't have to move them.
27555 nondefiningFunctionDeclaration = NULL;
27556 }
27557
27558 // Check that static declaration is preserved.
27559 if (functionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true)
27560 {
27561 ROSE_ASSERT(nondefiningFunctionDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true);
27562 }
27563
27564 // DQ (10/27/2020): Added return value so that we can access the new function prototype.
27565 return nondefiningFunctionDeclaration;
27566 }
27567
27568
27569std::vector<SgFunctionDeclaration*>
27571 {
27572 // DQ (3/20/2019): This function operates on the new file used to support outlined function definitions.
27573 // We use a copy of the file where the code will be outlined FROM, so that if there are references to
27574 // declarations in the outlined code we can support the outpiled code with those references. This
27575 // approach has the added advantage of also supporting the same include file tree as the original
27576 // file where the outlined code is being taken from.
27577
27578 class FunctionDefinitionsTraversal : public AstSimpleProcessing
27579 {
27580 public:
27581 std::vector<SgFunctionDeclaration*> functionList;
27582 FunctionDefinitionsTraversal() {}
27583
27584 void visit (SgNode* node)
27585 {
27586 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node);
27587 if (functionDeclaration != NULL)
27588 {
27589 // This should have been set already.
27590 // ROSE_ASSERT(sourceFile != NULL);
27591
27592 SgFunctionDeclaration* definingFunctionDeclaration = isSgFunctionDeclaration(functionDeclaration->get_definingDeclaration());
27593 if (functionDeclaration == definingFunctionDeclaration)
27594 {
27595 // Remove the defining declaration as a test.
27596 SgScopeStatement* functionDeclarationScope = isSgScopeStatement(functionDeclaration->get_parent());
27597 if (functionDeclarationScope != NULL)
27598 {
27599 functionList.push_back(functionDeclaration);
27600 }
27601 }
27602 }
27603 }
27604 };
27605
27606 // Now build the traveral object and call the traversal (preorder) on the AST subtree.
27607 FunctionDefinitionsTraversal traversal;
27608
27609 traversal.traverseWithinFile(node, preorder);
27610
27611 std::vector<SgFunctionDeclaration*> & functionList = traversal.functionList;
27612
27613 return functionList;
27614 }
27615
27616
27617void
27619 {
27620 ROSE_ASSERT(node != NULL);
27621
27622 std::vector<SgFunctionDeclaration*> functionList = generateFunctionDefinitionsList(node);
27623 std::vector<SgFunctionDeclaration*>::iterator i = functionList.begin();
27624
27625 while (i != functionList.end())
27626 {
27627 SgFunctionDeclaration* functionDeclaration = *i;
27628 ROSE_ASSERT(functionDeclaration != NULL);
27629 // Transform into prototype.
27631 i++;
27632 }
27633 }
27634
27635
27636
27637// DQ (7/14/2020): Added test for initializers to support debugging of Cxx11_tests/test2020_69.C.
27638void
27640 {
27641 // This function checks variable declarations for initializers. An issue (bug) in EDG 6.0
27642 // support for variable declarations initialized using lambda functions is that the initalizer
27643 // is discarded at some point in the processing of the AST. This function reports on all
27644 // variable declarations and if they contain initializers and if so what kind of initializer.
27645
27646 ROSE_ASSERT(node != nullptr);
27647
27648 // Preorder traversal to uniquely label the scopes (SgScopeStatements)
27649 class CheckInitializerTraversal : public AstSimpleProcessing
27650 {
27651 public:
27652 void visit (SgNode* node)
27653 {
27654 SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node);
27655 if (variableDeclaration != NULL)
27656 {
27657 SgInitializedName* initializedName = getFirstInitializedName(variableDeclaration);
27658 SgExpression* initializer = initializedName->get_initializer();
27659
27660 printf ("variableDeclaration = %p initializedName = %p = %s initializer = %p \n",
27661 variableDeclaration,initializedName,initializedName->get_name().str(),initializer);
27662
27663 if (initializer != NULL)
27664 {
27665 printf (" --- initializer = %s \n",initializer->class_name().c_str());
27666 }
27667 }
27668 }
27669 };
27670
27671 // Now buid the traveral object and call the traversal (preorder) on the project.
27672 CheckInitializerTraversal traversal;
27673 traversal.traverse(node, preorder);
27674 }
27675
27676namespace
27677{
27678 struct DeclaredType : sg::DispatchHandler<SgNamedType*>
27679 {
27680 void setResult(SgNamedType* ty) { res = ty; }
27681 void setResult(SgType*) { /* not a named type */ }
27682
27683 void handle(SgNode& n, SgNode&) { SG_UNEXPECTED_NODE(n); }
27684
27685 template <class SageDeclarationStatement>
27686 void handle(SageDeclarationStatement& n, SgDeclarationStatement&)
27687 {
27688 // SgDeclarationStatement::get_type is not a virtual function
27689 // => find overloaders returning SgNamedType in subclasses
27690 // by using the full type (SageDeclarationStatement).
27691 setResult(n.get_type());
27692 }
27693
27694 template <class SageNode>
27695 void handle(SageNode& n)
27696 {
27697 handle(n, n);
27698 }
27699 };
27700}
27701
27703{
27704 return sg::dispatch(DeclaredType{}, declaration);
27705}
27706
27708 SgGlobal * gsaf = project->get_globalScopeAcrossFiles();
27709 ROSE_ASSERT(gsaf != nullptr);
27710 SgSymbolTable * st = gsaf->get_symbol_table();
27711 ROSE_ASSERT(st != nullptr);
27712 rose_hash_multimap * hmm = st->get_table();
27713 ROSE_ASSERT(hmm != nullptr);
27714 hmm->clear();
27715
27716 st = SgNode::get_globalTypeTable()->get_type_table();
27717 ROSE_ASSERT(st != nullptr);
27718 hmm = st->get_table();
27719 ROSE_ASSERT(hmm != nullptr);
27720 hmm->clear();
27721
27723 ROSE_ASSERT(st != nullptr);
27724 hmm = st->get_table();
27725 ROSE_ASSERT(hmm != nullptr);
27726 hmm->clear();
27727}
27728
27730/*
27731
27732By default, only transformation generated AST nodes will be normalized since this is designed to normalize translator-generated code.
27733
27734--- p_lhs_operand_i ->@0x7ff2fc3f1010 SgArrowExp c_rc-575-out.cpp 16:13
27735 |--- p_lhs_operand_i ->@0x7ff2fc428010 SgAddressOfOp c_rc-575-out.cpp 16:4
27736 | |___ p_operand_i ->@0x7ff2fc582078 SgVarRefExp c_rc-575-out.cpp 16:5 init name@0x7ff2fcf03890 symbol name="table1"
27737 |___ p_rhs_operand_i ->@0x7ff2fc5820e0 SgVarRefExp c_rc-575-out.cpp 16:16 init name@0x7ff2fcf03480 symbol name="item1"
27738
27739
27740TODO: we only handle simplest pattern for now: both leaf operands involved are SgVarRefExp.
27741
27742 * */
27743int SageInterface::normalizeArrowExpWithAddressOfLeftOperand(SgNode* root, bool transformationGeneratedOnly /* =true */)
27744{
27745 int match_count = 0;
27746 ROSE_ASSERT (root);
27747
27748 // find all SgArrowExp, then try to match the expected pattern
27749 // SgArrowExp(SgAddressOfOp(SgVarRefExp:table1),SgVarRefExp:item1)
27750 Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(root, V_SgArrowExp);
27751
27752 // The jovial2cpp translator generates two source file ASTs: and they often share the same subtrees.
27753 // So we need to make sure the same subtree is only processed once
27754 boost::unordered::unordered_map <SgNode*, bool> visited;
27755
27756 // reverse iterator is safer to use than forward iterator to support translation
27757 for (Rose_STL_Container<SgNode *>::reverse_iterator i = nodeList.rbegin(); i != nodeList.rend(); i++)
27758 {
27759 // skip a node if it is previously processed.
27760 if (visited.count(*i)==1)
27761 continue;
27762
27763 visited[*i]=true;
27764
27765 SgArrowExp* a_exp = isSgArrowExp(*i);
27766
27767 if (!a_exp)
27768 {
27769 cerr<<"SageInterface::normalizeArrowExpWithAddressOfLeftOperand() expects SgArrowExp while encountering "<<(*i)->class_name()<<"@"<<(*i) <<endl;
27770 ROSE_ASSERT (a_exp);
27771 }
27772
27773 if (transformationGeneratedOnly)
27774 {
27775 if (!(a_exp->get_file_info()->isTransformation()))
27776 continue;
27777 }
27778
27779 if (SgAddressOfOp* address_op = isSgAddressOfOp(a_exp->get_lhs_operand()) )
27780 {
27781 if (SgVarRefExp* left = isSgVarRefExp(address_op->get_operand())) // match left side pattern
27782 {
27783 if (SgVarRefExp* right = isSgVarRefExp (a_exp->get_rhs_operand())) // match right side pattern
27784 {
27785 // do the transformation: copy two operands, making a dot exp instead
27786 SgDotExp* dot_exp = buildDotExp (deepCopy(left), deepCopy(right));
27787 replaceExpression (a_exp, dot_exp);
27788 match_count++;
27789 }
27790 }
27791 }
27792 } // end for
27793
27794 return match_count;
27795}
27796
27797bool
27799 {
27800 class Traversal : public AstSimpleProcessing
27801 {
27802 public:
27803 bool found;
27804 Traversal() : found(false) {}
27805 void visit (SgNode* node)
27806 {
27807 SgCastExp* castExpression = isSgCastExp(node);
27808 if (castExpression != NULL)
27809 {
27810 // SgNode* parent = castExpression->get_parent();
27811 SgInitializer* initializer = isSgInitializer(castExpression->get_parent());
27812 if (initializer == NULL)
27813 {
27814 ROSE_ASSERT(castExpression->get_file_info() != NULL);
27815 if (castExpression->get_file_info()->isTransformation() == true)
27816 {
27817 printf (" --- Found a SgCastExp marked as a transformation: castExpression = %p \n",castExpression);
27818 found = true;
27819#if 0
27820 printf ("Exiting as a test! \n");
27821 ROSE_ASSERT(false);
27822#endif
27823 }
27824 else
27825 {
27826#if 0
27827 printf (" --- SgCastExp (but not marked as a transformation) node = %p = %s \n",node,node->class_name().c_str());
27828#endif
27829 }
27830 }
27831 else
27832 {
27833 // DQ (7/14/2021): This case is less interesting (not the SgCastExp that I was looking for in testing).
27834#if 1
27835 printf (" --- SgCastExp (but from an initializer) node = %p = %s \n",node,node->class_name().c_str());
27836#endif
27837 }
27838 }
27839 else
27840 {
27841#if 0
27842 printf (" --- node = %p = %s \n",node,node->class_name().c_str());
27843#endif
27844 }
27845 }
27846 };
27847
27848#if 1
27849 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s \n",s.c_str());
27850#endif
27851
27852 // Now buid the traveral object and call the traversal (preorder) on the AST subtree.
27853 Traversal traversal;
27854 traversal.traverse(n, preorder);
27855
27856#if 1
27857 printf ("In findFirstSgCastExpMarkedAsTransformation(): s = %s traversal.found = %s \n",s.c_str(),traversal.found ? "true" : "false");
27858#endif
27859#if 0
27860 // DQ (7/13/2021): return false so that we can test the execution of the code to generate that backend code.
27861 if (traversal.found == true)
27862 {
27863 printf ("In findFirstSgCastExpMarkedAsTransformation(): returning false \n");
27864 }
27865
27866 return false;
27867#else
27868 return traversal.found;
27869#endif
27870 }
27871
27872// A helper function to check
27873// begin: return 1
27874// middle (#else, #elif): return 2
27875// end directive: return -1
27876// othewise return 0;
27877static int isBeginDirective (PreprocessingInfo* info)
27878{
27879 ROSE_ASSERT (info != NULL);
27880 PreprocessingInfo::DirectiveType dtype= info->getTypeOfDirective();
27881 if (dtype == PreprocessingInfo::CpreprocessorIfdefDeclaration ||
27882 dtype == PreprocessingInfo::CpreprocessorIfndefDeclaration ||
27883 dtype == PreprocessingInfo::CpreprocessorIfDeclaration )
27884 {
27885 return 1;
27886 }
27887 else if (dtype==PreprocessingInfo::CpreprocessorElseDeclaration||
27888 dtype==PreprocessingInfo::CpreprocessorElifDeclaration)
27889 {
27890 return 2;
27891 }
27892 else if (dtype==PreprocessingInfo::CpreprocessorEndifDeclaration)
27893 {
27894 return -1;
27895 }
27896
27897 return 0;
27898}
27899
27900// a helper function to move things, the associated directive in the middle
27901static void moveInofListToNewPlace(AttachedPreprocessingInfoType* infoList, int cidx, set <AttachedPreprocessingInfoType*>& relatedInfoList, SgLocatedNode* lnode, int &retVal)
27902{
27903// AttachedPreprocessingInfoType* infoList = (*ki).first;
27904// int cidx= (*ki).second;
27905
27906 relatedInfoList.insert (infoList);
27907
27908 PreprocessingInfo* info = (*infoList)[cidx];
27909 // rewrite relative position
27910 info->setRelativePosition(PreprocessingInfo::after);
27911
27912 // insert after lnode
27913 lnode->addToAttachedPreprocessingInfo (info);
27914 retVal++;
27915
27916 // zero out from original list
27917 (*infoList)[cidx]= NULL;
27918}
27919
27920// Return the number of NULL PreprocessingInfo* within a subtree of a SgLocatedNode, inclusive
27922{
27923 int retVal=0;
27924 ROSE_ASSERT(lnode);
27925
27926 // collecting NULL entries
27927 RoseAst ast(lnode);
27928 RoseAst::iterator ast_i=ast.begin();
27929
27930 vector < pair< AttachedPreprocessingInfoType*, int> > empty_entries; // preprocessing info. to be erased, list vs. idx/offset
27931 for(;ast_i!=ast.end();++ast_i) {
27932 SgLocatedNode* current = isSgLocatedNode(*ast_i);
27933 if (current ==NULL ) // skip non located nodes
27934 continue;
27935
27936 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
27937 if (infoList == NULL) continue;
27938
27939 int commentIndex=0;
27940 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
27941 {
27942 // fundamentally, we want to move individual PreprocessingInfo objects
27943 // Or just duplicate them (easier)
27944 PreprocessingInfo * info = *ci;
27945 if (info==NULL)
27946 empty_entries.push_back( make_pair (infoList, commentIndex) );
27947 commentIndex++;
27948 }
27949 }
27950
27951 // using reverse iterator to remove from backwards
27952 for (auto ki = empty_entries.rbegin(); ki != empty_entries.rend(); ki ++)
27953 {
27954 AttachedPreprocessingInfoType* infoList = (*ki).first;
27955 int cidx= (*ki).second;
27956
27957 PreprocessingInfo* info = (*infoList)[cidx];
27958 ROSE_ASSERT (info==NULL);
27959
27960 // erase start+offset
27961 AttachedPreprocessingInfoType::iterator k = infoList->begin();
27962 infoList->erase(k+cidx);
27963// cout<<"debugging: direct erasing: info@"<< infoList<< " idx="<<cidx<<endl;
27964 retVal ++;
27965 }
27966 return retVal;
27967}
27968
27969//TODO: expose this to header file?
27970// We keep all things, including level : starting from 0. Later iteration ignore the level 0 directives.
27971// Should this be maintained by librose or user space code?
27972static std::unordered_map <PreprocessingInfo*, SageInterface::PreprocessingInfoData> infoMap;
27973
27974void SageInterface::preOrderCollectPreprocessingInfo(SgNode* current, vector<PreprocessingInfo*>& infoList, int depth)
27975{
27976 // stop condition
27977 if (current == NULL)
27978 return;
27979
27980 // Three possible locations: before, inside, and after
27981 // immediately add prepression info that is before and inside of current node
27982 // delayed additions of these that are located after the current node
27983 vector<PreprocessingInfo*> afterList;
27984 if (SgLocatedNode* locatedNode = isSgLocatedNode(current))
27985 {
27986 AttachedPreprocessingInfoType* comments = locatedNode->getAttachedPreprocessingInfo();
27987
27988 if (comments != nullptr)
27989 {
27990 AttachedPreprocessingInfoType::iterator i;
27991 int idx=0;
27992 for (i = comments->begin (); i != comments->end (); i++)
27993 {
27994 PreprocessingInfo* info= *i;
27995
27996 // prepare the data just in case
27998 data.container=comments;
27999 data.index = idx;
28000 data.depth = depth;
28001
28002 // put directives with before location into the infoList
28003 if (info->getRelativePosition () == PreprocessingInfo::before)
28004 {
28005 infoList.push_back (info);
28006 infoMap[info] = data;
28007 }
28008 // How about inside position?
28009 // why it should be intepreted as the last one after all inner statment's preprocessingInfo?
28010 // because if it should be unparsed before all of them, it should have been attached to the first stmt's before location instead!
28011 else if (info->getRelativePosition () == PreprocessingInfo::after
28012 || info->getRelativePosition () == PreprocessingInfo::inside
28013 )
28014 {
28015 afterList.push_back (info); // if attached to be after, save to afterList
28016 infoMap[info] = data;
28017 }
28018 else
28019 {
28020 mlog[Sawyer::Message::Common::WARN] <<"Warning: unhandled relative position value:" <<info->getRelativePosition () <<endl;
28021 // ROSE_ASSERT (false); // Jovial has end_of
28022 }
28023
28024 idx++;
28025 } // end for
28026 }
28027 } // end if
28028
28029 // handling children nodes
28030 std::vector<SgNode* > children = current->get_traversalSuccessorContainer();
28031 for (auto c: children)
28032 preOrderCollectPreprocessingInfo (c, infoList, depth +1);
28033
28034 // append after locations after recursively handling children nodes.
28035 for (auto fi : afterList)
28036 infoList.push_back(fi);
28037}
28038
28039// This may be expensive to run since it is called anytime replace() is called.
28041// We need to attach them to be after lnode, before we can safely remove lnode. So the inner preprocessing info. can be preserved properly.
28042// This should be done before removing or replace the statement: lnode
28043// TODO: this may need to be a recursive function for multiple levels of nested directives.
28044//
28045// We only care about directives attached to inner nodes, not lnode : TODO: double check this for corner cases
28046//
28048{
28049 int retVal=0;
28050 ROSE_ASSERT(lnode);
28051
28052// algorithm: using a queue (vector to simulate it)
28053// queue <PreProcessingInfo* > q;
28054// start from 2nd node: ignore the first root node
28055// if start preprocessing info: (if, ifndef, ifdef), push to the end of q
28056// if end of preprocessing info. (endif), neturalize possible end p info at the end of q, otherwise push it to the end
28057//
28058// the queue in the end may contain mixed preprocessing info. #endif #endif ... #if #ifndef
28059// They cannot neutralize each other.
28060// They should be attached to be after lnode !
28061 RoseAst ast(lnode);
28062 RoseAst::iterator ast_i=ast.begin();
28063 ++ast_i; // skip the root node itself
28064
28065 // we store both the container and the element's index within the container. so later we can easily remove elements from containers
28066 vector < pair< AttachedPreprocessingInfoType*, int> > keepers; // preprocessing info. to be kept
28067 // for the middle directives like #else or #elif, sometimes their status (balanced or not) is directly associatd with its preceeding begin directive
28068 // it is not always an independent decision.
28069 // Note : the association is between individual preprocessing info. however, to faciliate removing them, the second part uses InfoList vs offset
28070 unordered_map < PreprocessingInfo * , vector< pair<AttachedPreprocessingInfoType*, int>> > associated_directives;
28071
28072 // store the associated middle directives what should be erased in the end
28073 // we have to store this separatedly since the begin diretive pinfo becomes NULL after they have been erased!
28074 // associated_directives[BeginInfo] will not retrieve them!
28075 vector< pair<AttachedPreprocessingInfoType*, int>> associated_erase;
28076
28077 // Two steps here
28078 // Step 1: We build the list first, then go through them to neutralize them
28079 // to simplify the problem: we exclude comments attached to the current located node, only consider things inside
28080 //
28081 // The list must provide the following information
28082 // infoList (container), index of the directive, PreprocessingInfo* itself
28083 vector<PreprocessingInfo*> candidateInfoList;
28084 // recursively search all directives, preserving original order in AST, consider attachment locations: before, inside and after.
28085 preOrderCollectPreprocessingInfo (lnode, candidateInfoList, 0);
28086 // now we have both candidateInfoList and infoMap.
28087
28088 for (auto candidate: candidateInfoList)
28089 {
28090 // fundamentally, we want to move individual PreprocessingInfo objects
28091 // Or just duplicate them (easier)
28092 PreprocessingInfo * info = candidate;
28093
28094 // we skip candidate that is attached to a node with depth of 0 (root node of the subtree)
28095 if (infoMap[info].depth ==0)
28096 continue;
28097
28098 int commentIndex = infoMap[info].index;
28099 AttachedPreprocessingInfoType* infoList = infoMap[info].container;
28100
28101 // begin directives
28102 if ( isBeginDirective(info) == 1)
28103 {
28104 keepers.push_back(make_pair (infoList,commentIndex));
28105 }
28106 // the middle #else, #elif,
28107 else if (isBeginDirective(info) == 2)
28108 {
28109 // two situtations for immediate decision of unbalanced status
28110 //1. empty stack, or
28111 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
28112 if (keepers.size()==0)
28113 keepers.push_back(make_pair (infoList, commentIndex));
28114 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
28115 {
28116 keepers.push_back(make_pair (infoList,commentIndex));
28117 }
28118 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
28119 {
28120 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
28121 // we associated this middle directive with the beginning directive
28122 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
28123 }
28124 }
28125 // end directive
28126 else if ( isBeginDirective(info) == -1)
28127 {
28128 bool neutralized = false;
28129 // neutralize an internall matched pair, if any
28130 if (keepers.size()>0)
28131 {
28132 AttachedPreprocessingInfoType* comments = keepers.back().first;
28133 int idx = keepers.back().second;
28134
28135 if(isBeginDirective( (*comments)[idx] )==1)
28136 {
28137 keepers.pop_back();
28138 neutralized = true;
28139 }
28140 }
28141
28142 if (!neutralized)
28143 keepers.push_back(make_pair (infoList,commentIndex));
28144 }
28145
28146 }
28147
28148#if 0 // old and wrong linear search of directives
28149
28150 // Then we go through the list, extract keepers, neutralize anything else.
28151 for(;ast_i!=ast.end();++ast_i) {
28152 SgLocatedNode* current = isSgLocatedNode(*ast_i);
28153 if (current ==NULL ) // skip non located nodes
28154 continue;
28155
28156 AttachedPreprocessingInfoType* infoList = current->getAttachedPreprocessingInfo();
28157 if (infoList == NULL) continue;
28158
28159 int commentIndex=0;
28160 for (Rose_STL_Container<PreprocessingInfo*>::iterator ci = (*infoList).begin(); ci != (*infoList).end(); ci++)
28161 {
28162 ROSE_ASSERT(*ci != NULL);
28163 // fundamentally, we want to move individual PreprocessingInfo objects
28164 // Or just duplicate them (easier)
28165 PreprocessingInfo * info = *ci;
28166
28167 // begin directives
28168 if ( isBeginDirective(info) == 1)
28169 {
28170 keepers.push_back(make_pair (infoList,commentIndex));
28171 }
28172 // the middle #else, #elif,
28173 else if (isBeginDirective(info) == 2)
28174 {
28175 // two situtations for immediate decision of unbalanced status
28176 //1. empty stack, or
28177 // 2. top of stack is not one of #if #ifdef #ifndef. This is an unbalanced directive (keeper)
28178 if (keepers.size()==0)
28179 keepers.push_back(make_pair (infoList,commentIndex));
28180 else if (isBeginDirective( (*(keepers.back().first))[keepers.back().second] )!=1 ) // not empty , top of the stack is not beginning
28181 {
28182 keepers.push_back(make_pair (infoList,commentIndex));
28183 }
28184 else if(isBeginDirective( (*(keepers.back().first))[keepers.back().second] )==1 ) // top of the stack is a beginning,
28185 {
28186 PreprocessingInfo* begin_info = (*(keepers.back().first))[keepers.back().second];
28187 // we associated this middle directive with the beginning directive
28188 associated_directives[begin_info].push_back(make_pair (infoList,commentIndex));
28189 }
28190 }
28191 // end directive
28192 else if ( isBeginDirective(info) == -1)
28193 {
28194 bool neutralized = false;
28195 // neutralize an internall matched pair, if any
28196 if (keepers.size()>0)
28197 {
28198 AttachedPreprocessingInfoType* comments = keepers.back().first;
28199 int idx = keepers.back().second;
28200
28201 if(isBeginDirective( (*comments)[idx] )==1)
28202 {
28203 keepers.pop_back();
28204 neutralized = true;
28205 }
28206 }
28207
28208 if (!neutralized)
28209 keepers.push_back(make_pair (infoList,commentIndex));
28210 }
28211 commentIndex++;
28212 }
28213 }
28214#endif
28215// TODO this variable is not used in the end.
28216 set <AttachedPreprocessingInfoType*> relatedInfoList; // containers with comments to be moved
28217 // 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!
28218 // move from old containers, and add into lnode's after position
28219 for (auto ki = keepers.begin(); ki != keepers.end(); ki ++)
28220 {
28221 AttachedPreprocessingInfoType* infoList = (*ki).first;
28222 int cidx= (*ki).second;
28223 // TODO replace the code block below with moveInofListToNewPlace()
28224 relatedInfoList.insert (infoList);
28225
28226 PreprocessingInfo* info = (*infoList)[cidx];
28227 // rewrite relative position
28228 info->setRelativePosition(PreprocessingInfo::after);
28229
28230 // insert after lnode
28231 lnode->addToAttachedPreprocessingInfo (info);
28232 retVal++;
28233
28234 // we additionally process the associated directives, if any, TODO: reverse processing also??
28235 if (associated_directives.count (info)!=0)
28236 {
28237 vector<pair<AttachedPreprocessingInfoType*,int>> a_list_vec = associated_directives[info];
28238 for (auto vec_i = a_list_vec.rbegin(); vec_i != a_list_vec.rend(); vec_i ++ )
28239 {
28240 AttachedPreprocessingInfoType* a_infoList = (*vec_i).first;
28241 int aidx= (*vec_i).second;
28242 moveInofListToNewPlace (a_infoList, aidx, relatedInfoList, lnode, retVal);
28243 associated_erase.push_back(make_pair (a_infoList, aidx));
28244 }
28245 } // each begin directive may associate multiple other middle directives
28246
28247 // Doing this after the associated directives are processed.
28248 // zero out from original list, Note this element slot is NULL now!
28249 (*infoList)[cidx]= NULL;
28250
28251 }
28253 return retVal;
28254}
to specify a construct using a specifier Can be used alone or with parent handles when relative speci...
virtual void * getNode() const
Get the raw IR node associated with the current abstract node.
Base class for all IR node attribute values.
Attribute Evaluator for synthesized attributes.
SynthesizedAttributeType traverse(SgNode *node)
evaluates attributes on the entire AST
Attribute storing an SgNode.
Class for traversing the AST.
void traverse(SgNode *node, Order treeTraversalOrder)
traverse the entire AST. Order defines preorder (preorder) or postorder (postorder) traversal....
void visit(SgNode *astNode)
this method is called at every traversed node.
void visit(SgNode *astNode)
visitor function for each node to collect non-builtin types' declarations
void visit(SgNode *astNode)
this method is called at every traversed node.
For preprocessing information including source comments, include , if, define, etc.
RelativePositionType
MK: Enum type to store if the directive goes before or after the corresponding line of source code.
AST iterator.
Definition RoseAst.h:54
Interface for iterating over an AST.
Definition RoseAst.h:26
iterator begin()
Iterator positioned at root of subtree.
iterator end()
Iterator positioned at the end of the traversal.
const Digest & digest() override
Return the digest.
void insert(const std::string &)
Insert data into the digest.
uint64_t toU64()
Returns the hash as a 64 bit int.
void visit(SgNode *node)
this method is called at every traversed node.
Interface for creating a statement whose computation writes its answer into a given variable.
A persistent attribute to represent a unique name for an expression.
SgName get_name() const override
Access function for getting name from declarations or types internally.
Base class for binary files.
SgAsmGenericHeaderList *const & get_headers() const
Property: List of all headers in file.
SgAsmGenericHeaderPtrList const & get_headers() const
Property: List of file header nodes.
Base class for container file headers.
SgAsmInterpretationPtrList const & get_interpretations() const
Property: Interpretation list.
Represents an interpretation of a binary container.
This class represents the concept of a C Assembler statement.
This class represents the rhs of a variable declaration which includes an optional assignment (e....
void set_operand(SgExpression *exp)
This sets the rhs expression.
SgExpression * get_operand() const
Returns the rhs.
This class represents the concept of a block (not a basic block from control flow analysis).
const SgStatementPtrList & get_statements() const
Returns a const STL list by reference.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a binary operator. It is derived from a SgExpression because oper...
SgExpression * get_lhs_operand() const
returns SgExpression pointer to the lhs operand associated with this binary operator.
void set_rhs_operand(SgExpression *exp)
This function allows the p_rhs_operand pointer to be set (used internally).
void set_lhs_operand(SgExpression *exp)
This function allows the p_lhs_operand pointer to be set (used internally).
SgExpression * get_rhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
SgExpression * get_lhs_operand_i() const
returns SgExpression pointer to the operand associated with this binary operator.
virtual VariantT variantT() const override
returns new style SageIII enum values
SgExpression * get_rhs_operand() const
returns SgExpression pointer to the rhs operand associated with this binary operator.
This class represents a boolean value (expression value).
This class represents the notion of a break statement (typically used in a switch statment).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a C and C++ case option (used within a switch statement).
SgStatement * get_body() const
Returns pointer to a SgBasicBlock object.
void set_key(SgExpression *key)
Access function for pointer to SgExpression object wrapped by SgExpressionRoot in p_key_root.
void set_body(SgStatement *body)
Access function for p_body.
SgExpression * get_key() const
Returns pointer to a SgExpression object wrapped by SgExpressionRoot in p_key_root.
This class represents a cast of one type to another.
SgType * get_type() const override
unparsing support for pragmas
This class represents the concept of a catch within a try-catch construct used in C++ exception handl...
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Access function for p_body.
This class represents the concept of a class declaration statement. It includes the concept of an ins...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgScopeStatement * get_scope() const override
Returns scope of current statement.
This class represents the concept of a class definition in C++.
SgClassDeclaration * get_declaration() const
returns the class declaration associated with this class decinition.
const SgDeclarationStatementPtrList & get_members() const
Returns a const list to the data member declarations.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a C++ expression built from a class name.
SgClassSymbol * get_symbol() const
Returns pointer to SgSymbol.
This class represents the concept of a class name within the compiler.
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
static SgClassType * createType(SgDeclarationStatement *decl=NULL, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgClassType (types whose constructors take par...
This class represents the concept of a C trinary conditional expression (e.g. "test ?...
SgExpression * get_true_exp() const
Access function for p_true_exp.
void set_false_exp(SgExpression *false_exp)
Access function for p_false_exp.
SgExpression * get_conditional_exp() const
Access function for p_conditional_exp.
SgExpression * get_false_exp() const
Access function for p_false_exp.
void set_true_exp(SgExpression *true_exp)
Access function for p_true_exp.
void set_conditional_exp(SgExpression *conditional_exp)
Access function for p_conditional_exp.
This class represents the call of a class constructor to initialize a variable. For example "Foo foo;...
SgType * get_expression_type() const
Access function for p_expression_type, returns pointer to SgType associated with constructor.
This class represents the concept of a C or C++ continue statement.
Supporting class from copy mechanism within ROSE.
Definition sageCopy.h:26
This class represents the concept of a contructor initializer list (used in constructor (member funct...
bool isFriend() const
declaration modifier is friend.
This class represents the concept of a declaration statement.
SgSymbol * search_for_symbol_from_symbol_table() const
User interface for retrieving the associated symbol from the declaration.
void set_definingDeclaration(SgDeclarationStatement *definingDeclaration)
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
void set_firstNondefiningDeclaration(SgDeclarationStatement *firstNondefiningDeclaration)
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
SgDeclarationStatement * get_definingDeclaration() const
This is an access function for the SgDeclarationStatement::p_definingDeclaration data member (see tha...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
bool isForward() const
Returns boolean value indicating if this is a forward declaration.
SgDeclarationStatement * get_firstNondefiningDeclaration() const
This is an access function for the SgDeclarationStatement::p_firstNondefiningDeclaration data member ...
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool hasAssociatedSymbol() const
Returns boolean value true of this type of declaration has an associated sysmbol.
SgName get_template_name() const
This function returns the template name (taken from the template declaration for the class,...
This class represents the concept of a C or C++ default case within a switch statement.
void set_body(SgStatement *body)
Access function for p_body.
SgStatement * get_body() const
Returns pointer to SgBasicBlock.
This class represents a directory within a projects file structure of files and directories.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_condition(SgStatement *condition)
Access function for p_condition.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the notion of an value (expression value).
This class represents the concept of an enum declaration.
SgScopeStatement * get_scope() const override
Access function for p_scope.
SgName get_name() const
Access function for p_name.
void set_scope(SgScopeStatement *scope) override
Access function for p_scope.
const SgInitializedNamePtrList & get_enumerators() const
Access function for p_enumerators.
This class represents the concept of a C and C++ expression list.
int replace_expression(SgExpression *o, SgExpression *n) override
This class represents the base class of all the expressions within this grammar.
This class represents the concept of a C or C++ statement which contains a expression.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...
virtual std::string class_name() const override
returns a string representing the class name
void set_need_paren(bool need_paren)
This function allows the p_need_paren flag to be set (used internally).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgType * get_type() const
unparsing support for pragmas
virtual int replace_expression(SgExpression *oldChild, SgExpression *newChild)
This class represents the base class of all the expressions within this grammar.
virtual const char * sage_class_name() const override
virtual Sg_File_Info * get_file_info(void) const override
Interface function to implement original SAGE interface to SgFile_Info objects.
void set_lvalue(bool lvalue)
This function allows the p_lvalue flag to be set (used internally).
bool get_lvalue() const
Returns a bool value if the current expression is assigned to.
This class represents a source file for a project (which may contian many source files and or directo...
std::string getFileName() const
associated filename
Sg_File_Info * get_file_info() const override
Access function calling get_startOfConstruct(), provided to support older interface.
This class represents the notion of an value (expression value).
This class represents the variable declaration or variable initialization withn a for loop.
const SgStatementPtrList & get_init_stmt() const
Returns const reference to a SgStatementPtrList (typedef to a STL list).
This class represents the concept of a for loop.
SgExpression * get_test_expr() const
Access function for p_test_expr_root.
SgForInitStatement * get_for_init_stmt() const
Access function for p_for_init_stmt.
void set_loop_body(SgStatement *loop_body)
Access function for p_loop_body.
SgStatement * get_loop_body() const
Access function for p_loop_body.
void set_for_init_stmt(SgForInitStatement *for_init_stmt)
Access function for p_for_init_stmt.
This class represents the concept of a C++ function call (which is an expression).
SgFunctionSymbol * getAssociatedFunctionSymbol() const
Returns the associated function symbol, if it can be resolved statically.
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
virtual std::string class_name() const override
returns a string representing the class name
This class represents the concept of a function declaration statement.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
bool isTemplateFunction() const
Determines if function is a template or non-template function.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
virtual std::string class_name() const override
returns a string representing the class name
SgBasicBlock * get_body() const
Access function for p_body.
This class represents the concept of a declaration list.
const SgInitializedNamePtrList & get_args() const
Access function for p_args.
const SgTypePtrList & get_arguments() const
Get a const list of input types (types of the parameters list) to this function type (from a cost fun...
This class represents the function being called and must be assembled in the SgFunctionCall with the ...
SgFunctionDeclaration * getAssociatedFunctionDeclaration() const
Returns the associated function declaration, if it can be resolved statically.
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the function type table (stores all function types so that they can be shared i...
SgSymbolTable * get_function_type_table() const
Returns pointer to SgSymbolTable used for function type symbols only.
This class represents a type for all functions.
virtual std::string class_name() const override
returns a string representing the class name
const SgTypePtrList & get_arguments() const
This is a const convience access function to the STL container of types in the child IR node (SgFunct...
virtual SgName get_mangled(void) const override
Mangled name support for unparser support.
This class represents the concept of a namespace definition.
virtual std::string class_name() const override
returns a string representing the class name
const SgDeclarationStatementPtrList & get_declarations() const
Returns a const list to the global scope declarations.
This class represents the concept of a C or C++ goto statement.
SgLabelStatement * get_label() const
Returns pointer to SgLabelStatement where control flow will be transfered during execution.
void set_label(SgLabelStatement *label)
Access function for p_label.
InheritedAttributeType traverse(SgGraphNode *basenode, SgIncidenceDirectedGraph *g, InheritedAttributeType inheritedValue, InheritedAttributeType nullInherit, SgGraphNode *endnode, bool insep=false, bool pcHk=false)
This is the function that is used by the user directly to start the algorithm.
This class represents the concept of an "if" construct.
void set_false_body(SgStatement *false_body)
Access function for p_false_body.
virtual std::string class_name() const override
returns a string representing the class name
void set_true_body(SgStatement *true_body)
Access function for p_true_body.
SgStatement * get_conditional() const
Access function for p_conditional.
SgStatement * get_true_body() const
Access function for p_true_body.
SgStatement * get_false_body() const
Access function for p_false_body.
void set_conditional(SgStatement *conditional)
Access function for p_conditional.
This class represents the notion of a declared variable.
SgName get_qualified_name() const
Returns the name with appropriate qualified names representing nested scopes.
SgSymbol * get_symbol_from_symbol_table() const
Get the associated SgSymbol from the symbol table located in the scope, without considering possible ...
virtual std::string class_name() const override
returns a string representing the class name
SgDeclarationStatement * get_declaration() const
Equal operator : it checks if all the data members are the same or point to the same objects.
This class represents the notion of an initializer for a variable declaration or expression in a func...
This class represents the concept of a C or C++ label statement.
SgName get_label() const
Returns SgName by value.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
label_type_enum
Type of label used (fortran only)
SgName get_name() const override
Access function for getting name from declarations or types internally.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of an expression or statement which has a position within the source...
virtual std::string class_name() const override
returns a string representing the class name
virtual const char * sage_class_name() const override
Sg_File_Info * get_endOfConstruct() const override
New function interface for Sg_File_Info data stores ending location of contruct (typically the closin...
void setTransformation()
Allow IR nodes (mostly SgLocatedNode) to be marked as a transformation.
virtual void addNewAttribute(std::string s, AstAttribute *a) override
Add a new attribute represented by the named string.
void set_endOfConstruct(Sg_File_Info *endOfConstruct)
This function sets the current source location position of the end of the current construct.
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
void addToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo::RelativePositionType locationInList=PreprocessingInfo::after)
This function adds comment or CPP directives to the current IR node.
virtual AstAttribute * getAttribute(std::string s) const override
Returns attribute of name 's'.
void set_startOfConstruct(Sg_File_Info *startOfConstruct)
This function sets the current source location position of the start of the current construct.
bool isCompilerGenerated() const
Simple test for if this is a compiler generated node.
void insertToAttachedPreprocessingInfo(PreprocessingInfo *prepInfoPtr, PreprocessingInfo *anchorInfoPtr, bool insertAfter=true)
Insert prepInfo After (or before if last parameter is false) an anchor info ptr in the list of prepro...
virtual VariantT variantT() const override
returns new style SageIII enum values
void setOutputInCodeGeneration()
Allow IR nodes (mostly SgLocatedNode) to be marked as to when the information was unavilable in the f...
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
bool isTransformation() const
Simple test for if this is a part of a transformation.
AttachedPreprocessingInfoType *& getAttachedPreprocessingInfo(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() const
container of names of variables or container indices used used in the traversal to access AST success...
SgNode * get_parent() const
Access function for parent node.
void set_isModified(bool isModified)
All nodes in the AST contain a isModified flag used to track changes to the AST.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() const
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
virtual VariantT variantT() const
returns new style SageIII enum values
void set_parent(SgNode *parent)
All nodes in the AST contain a reference to a parent node.
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
virtual std::string class_name() const
returns a string representing the class name
static std::map< SgNode *, std::string > & get_globalMangledNameMap()
Access function for performance optimizing global mangled name map.
virtual void checkDataMemberPointersIfInMemoryPool()
FOR INTERNAL USE This is used in internal tests to verify that all IR nodes are allocated from the he...
virtual AstAttribute * getAttribute(std::string s) const
Returns attribute of name 's'.
static SgFunctionTypeTable * get_globalFunctionTypeTable()
Access function for symbol table specific to function types.
virtual Sg_File_Info * get_file_info(void) const
File information containing filename, line number, column number, and if the SgNode is a part of a ne...
virtual bool attributeExists(std::string s) const
Tests if attribute of name 's' is present.
virtual std::vector< std::pair< SgNode *, std::string > > returnDataMemberPointers() const
FOR INTERNAL USE Returns STL vector of pairs of SgNode* and strings for use in AST tools
virtual void addNewAttribute(std::string s, AstAttribute *a)
Add a new attribute represented by the named string.
static std::map< std::string, uint64_t > & get_shortMangledNameCache()
Access function for lower level optimizing of global mangled name map.
bool get_isModified() const
Acess function for isModified flag.
SgName get_name() const override
Support for some classes which have pure virtual function in base classes.
This class represents the concept of a C Assembler statement (untested).
Sg_File_Info * get_startOfConstruct() const override
New function interface for Sg_File_Info data stores starting location of contruct (typically the open...
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents a source project, with a list of SgFile objects and global information about th...
std::vector< std::string > getAbsolutePathFileNames() const
This function generates a list of files resolved to absolute paths (symbolic links should not be reso...
static void visitRepresentativeNode(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for type-based traversal.
static int get_verbose(void)
DQ: Modified to accept a value on the command line (no longer a boolean variable) value of 0 means qu...
This class represents a OLD concept of the structure require for qualified names when they were in th...
This class represents the concept of a C Assembler statement (untested).
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
bool supportsDefiningFunctionDeclaration()
Reports if scope can support defining function declarations. Not all scopes permit function declarati...
const SgStatementPtrList generateStatementList() const
Generate s list of statements from either the existing list of statements or the list of declarations...
bool isNamedScope()
Some scopes have associated names for purposed of name qualification. This returns true if the scope ...
SgSymbolTable * get_symbol_table() const
Returns a pointer to the locally strored SgSymbolTable.
virtual const char * sage_class_name() const override
SgDeclarationStatementPtrList & getDeclarationList()
Gets reference to internal STL list of pointers to SgDeclarationStatement objects (only defined for s...
SgStatementPtrList & getStatementList()
Gets reference to internal STL list of pointers to SgStatement objects (only defined for scopes conta...
void append_statement(SgStatement *stmt)
Higher level function to handle statements and declarations is scopes.
void set_symbol_table(SgSymbolTable *symbol_table)
Sets the pointer to the locally strored SgSymbolTable.
virtual std::string class_name() const override
returns a string representing the class name
bool statementExistsInScope(SgStatement *statement)
Test for existence of statement is scope.
bool containsOnlyDeclarations() const
This function is used to indicate if either the getDeclarationList() or getStatementList() can be cal...
void insert_symbol(const SgName &n, SgSymbol *s)
Puts a SgSymbol object into the local symbol table.
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_qualified_name() const
Returns SgName (a string) representing the name of the current scope.
This class represents the "sizeof()" operator (applied to any type).
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the notion of a statement.
virtual std::string class_name() const override
returns a string representing the class name
void insert_statement(SgStatement *target, SgStatement *newstmt, bool inFront=true)
This function inserts a single statement at the position indicated by target.
virtual void set_scope(SgScopeStatement *newScope)
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
virtual bool hasExplicitScope() const
Support for where the scope is explicitly required.
virtual SgSymbol * get_symbol_from_symbol_table() const
Get the associated symbol from the symbol table in the stored scope.
virtual SgScopeStatement * get_scope(void) const
Returns scope of current statement.
void remove_statement(SgStatement *)
This function removes the target statement from the AST.
virtual std::vector< SgNode * > get_traversalSuccessorContainer() const override
container of pointers to AST successor nodes used in the traversal overridden in every class by gener...
void replace_statement(SgStatement *target, SgStatement *newstmt)
This function replaces the target statement with a single statement.
virtual VariantT variantT() const override
returns new style SageIII enum values
bool isStatic() const
Storage modifier is static (always false for the SgStorageModifier in the SgInitializedName).
This class represents the base class of a numbr of IR nodes that don't otherwise fit into the existin...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of a switch.
void set_item_selector(SgStatement *item_selector)
Access function for p_item_selector.
SgStatement * get_body() const
Access function for p_body.
SgStatement * get_item_selector() const
Access function for p_item_selector_root.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the symbol tables used in both SgScopeStatement and the SgFunctionTypeSymbolTab...
std::set< SgNode * > get_symbols() const
Complexity O(n)
void print(std::string label, VariantT nodeType=V_SgSymbol)
Outputs symbol table information (useful for debugging)
int size() const
Computes the number of symbols in the symbol table (forced to count them, I think,...
void remove(const SgSymbol *symbol)
Complexity O(n)
This class represents the concept of a name within the compiler.
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual SgName get_name() const =0
Access function for getting name from declarations or types internally.
virtual SgType * get_type() const =0
This function returns the type associated with the named entity.
This class represents template argument within the use of a template to build an instantiation.
SgExpression * get_expression() const
This function returns argumentExpression.
SgType * get_type() const
This function returns argumentType.
SgTemplateArgument::template_argument_enum get_argumentType() const
This function returns argumentType.
This class represents the concept of a template declaration.
SgName get_string() const
Returns stringified template declaration.
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const
Returns name of template declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the concept of an instantiated class template.
virtual std::string class_name() const override
returns a string representing the class name
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgName get_templateName() const
Returns name of class template, the name excludes template arguments.
SgTemplateClassDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
This class represents the concept of a class definition in C++.
This class represents the concept of a C++ template instantiation directive.
SgDeclarationStatement * get_declaration() const
Returns pointer to SgDeclarationStatement.
This class represents the concept of an instantiation of function template.
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgTemplateFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
This class represents the concept of an instantiation of member function template or a member functio...
virtual std::string class_name() const override
returns a string representing the class name
const SgTemplateArgumentPtrList & get_templateArguments() const
Returns pointer to STL list of pointers to SgTemplateArgument objects.
SgName get_templateName() const
Returns name of instantiated function template, name includes template arguments.
SgTemplateMemberFunctionDeclaration * get_templateDeclaration() const
Returns pointer to SgTemplateDeclaration from which instantiation is generated.
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the "this" operator (can be applied to any member data).
Supporting class for "Deep" copies of the AST.
Definition sageCopy.h:86
static SgTypeBool * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeInt * createType(int sz=0, SgExpression *optional_fortran_type_kind=NULL)
more sophisticated version for more complex types like SgTypeInt (types whose constructors take param...
static SgTypeUnknown * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
static SgTypeVoid * createType(SgExpression *optional_fortran_type_kind=nullptr)
example of type used where construction is particularly simple
This class represents the base class for all types.
std::vector< SgType * > getInternalTypes() const
Generate a container of types hidden in the input type.
SgType * stripType(unsigned char bit_array=STRIP_MODIFIER_TYPE|STRIP_REFERENCE_TYPE|STRIP_RVALUE_REFERENCE_TYPE|STRIP_POINTER_TYPE|STRIP_ARRAY_TYPE|STRIP_TYPEDEF_TYPE|STRIP_POINTER_MEMBER_TYPE) const
Returns hidden type beneath layers of typedefs, pointers, references, modifiers, array representation...
virtual std::string class_name() const override
returns a string representing the class name
virtual VariantT variantT() const override
returns new style SageIII enum values
This class represents the notion of a typedef declaration.
SgScopeStatement * get_scope() const override
Returns scope of current statement.
virtual SgSymbol * get_symbol_from_symbol_table() const override
FOR INTERNAL USE Get the associated symbol from the symbol table in the stored scope....
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_typedefBaseTypeContainsDefiningDeclaration() is true,...
void set_scope(SgScopeStatement *scope) override
Support for setting scopes (only meaningful on IR statements that store the scope explicitly).
SgType * get_base_type() const
This is used in the SgTypedefType object (is not associated with a base_type data field)
void set_operand_i(SgExpression *operand_i)
This function allows the p_operand_i pointer to be set (used internally).
SgExpression * get_operand() const
returns SgExpression pointer to the operand associated with this unary operator.
This class represents the concept of a C++ using declaration.
SgDeclarationStatement * get_declaration() const
Access function for p_declaration.
SgInitializedName * get_initializedName() const
Access function for p_initializedName.
This class represents the concept of a C++ using directive.
SgNamespaceDeclarationStatement * get_namespaceDeclaration() const
Access function for p_namespaceDeclaration.
This class represents the notion of an value (expression value).
virtual VariantT variantT() const override
returns new style SageIII enum values
virtual std::string class_name() const override
returns a string representing the class name
This class represents the variable refernece in expressions.
static void traverseMemoryPoolNodes(ROSE_VisitTraversal &visit)
FOR INTERNAL USE Support for visitor pattern over all IR nodes by type of IR node.
This class represents the concept of a C or C++ variable declaration.
const SgInitializedNamePtrList & get_variables() const
Access function for p_variables.
SgDeclarationStatement * get_baseTypeDefiningDeclaration() const
Returns the defining declaration if get_variableDeclarationContainsBaseTypeDefiningDeclaration() is t...
bool get_variableDeclarationContainsBaseTypeDefiningDeclaration() const
Access function for p_variableDeclarationContainsBaseTypeDefiningDeclaration.
This class represents the definition (initialization) of a variable.
SgInitializedName * get_vardefn() const
Access function for SgInitializedName stored in p_vardefn.
This class represents the concept of a variable name within the compiler (a shared container for the ...
virtual std::string class_name() const override
returns a string representing the class name
SgName get_name() const override
Access function for getting name from declarations or types internally.
This class represents the concept of a do-while statement.
SgStatement * get_condition() const
Access function for p_condition.
void set_condition(SgStatement *condition)
Access function for p_condition.
SgStatement * get_body() const
Access function for p_body.
void set_body(SgStatement *body)
Access function for p_body.
This class represents the location of the code associated with the IR node in the original source cod...
void setTransformation()
Marks an IR node to be a transformation if it is not one already.
const char * get_filename() const
Returns filename of source code associated with IR node.
bool isOutputInCodeGeneration() const
Returns true only if required to be unparsed in generated code.
int get_line() const
Returns the line number of the associated code for this IR node.
bool isCompilerGenerated() const
Returns true only if compiler generated (either by the front-end or by ROSE).
int get_col() const
Returns the column number of the associated code for this IR node.
static Sg_File_Info * generateDefaultFileInfoForTransformationNode()
Static function to return new Sg_File_Info object set to default values appropriate for transformatio...
bool isTransformation() const
Access function for classification bit field.
bool isShared() const
Returns true only if shared internally (either by the front-end or by ROSE).
static Sg_File_Info * generateDefaultFileInfo()
Static function to return new Sg_File_Info object set to default values.
void setOutputInCodeGeneration()
Marks IR node as compiler generated but required in the generated source (e.g. requied templates).
Hash table support for symbol tables within ROSE.
ROSE_DLL_API abstract_handle * buildAbstractHandle(SgNode *snode)
A default builder function handles all details: file use name, others use numbering
ROSE_DLL_API std::vector< std::string > generateSourceFilenames(std::vector< std::string > argList, bool binaryMode)
Build the list of isolated file names from the command line.
ROSE_UTIL_API void removeAllFileNamesExcept(std::vector< std::string > &argv, std::vector< std::string > filenameList, std::string exceptFilename)
Remove file names specified in filenameList from argv, except for 'exceptFilename'.
void edgePointerReplacement(replacement_map_t const &)
For all nodes in the memory pool, it looks for the edges in the replacement map. If a match is found ...
ROSE_DLL_API std::string toBase62String(uint64_t)
Converts a 64 bit int to base 62.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Definition sageBuilder.C: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 SgName appendTemplateArgumentsToName(const SgName &name, const SgTemplateArgumentPtrList &templateArgumentsList)
DQ (7/27/2012): changed semantics from removing the template arguments in names to adding the templat...
ROSE_DLL_API SgFunctionParameterTypeList * buildFunctionParameterTypeList(SgFunctionParameterList *paralist)
Build SgFunctionParameterTypeList from SgFunctionParameterList.
ROSE_DLL_API SgLessThanOp * buildLessThanOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgCastExp * buildCastExp(SgExpression *operand_i=NULL, SgType *expression_type=NULL, SgCastExp::cast_type_enum cast_type=SgCastExp::e_C_style_cast)
Build a type casting expression.
ROSE_DLL_API SgMinusAssignOp * buildMinusAssignOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgDivideOp * buildDivideOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgBasicBlock * buildBasicBlock(SgStatement *stmt1=NULL, SgStatement *stmt2=NULL, SgStatement *stmt3=NULL, SgStatement *stmt4=NULL, SgStatement *stmt5=NULL, SgStatement *stmt6=NULL, SgStatement *stmt7=NULL, SgStatement *stmt8=NULL, SgStatement *stmt9=NULL, SgStatement *stmt10=NULL)
Build a SgBasicBlock, setting file info internally.
ROSE_DLL_API SgModOp * buildModOp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgExprStatement * buildAssignStatement(SgExpression *lhs, SgExpression *rhs)
Build an assignment statement from lefthand operand and right hand operand.
ROSE_DLL_API SgMemberFunctionDeclaration * buildNondefiningMemberFunctionDeclaration(const SgName &name, SgType *return_type, SgFunctionParameterList *parlist, SgScopeStatement *scope, SgExprListExp *decoratorList, unsigned int functionConstVolatileFlags, bool buildTemplateInstantiation, SgTemplateArgumentPtrList *templateArgumentsList)
Build a prototype member function declaration.
ROSE_DLL_API SgMemberFunctionDeclaration * buildDefaultConstructor(SgClassType *classType)
Build a variable declaration, handle symbol table transparently.
ROSE_DLL_API SgCommaOpExp * buildCommaOpExp(SgExpression *lhs=NULL, SgExpression *rhs=NULL)
ROSE_DLL_API SgIntVal * buildIntVal(int value=0)
Build an integer value expression.
SgDeclarationStatement * associatedDeclaration(const SgSymbol &n)
returns the associated declaration for symbol n or nullptr if there is none.
Functions that are useful when operating on the AST.
Definition sageBuilder.h:25
ROSE_DLL_API void checkSgNodePointers()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool isLastStatement(SgStatement *stmt)
Check if a statement is the last statement within its closed scope.
ROSE_DLL_API bool isUnionDeclaration(SgNode *node)
Check if a SgNode is a declaration for a union.
ROSE_DLL_API void translateScopeToUseCppDeclarations(SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
void initializeIfStmt(SgIfStmt *ifstmt, SgStatement *conditional, SgStatement *true_body, SgStatement *false_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void deepDelete(SgNode *root)
Deep delete a sub AST tree. It uses postorder traversal to delete each child node....
void annotateExpressionsWithUniqueNames(SgProject *project)
Generate unique names for expressions and attach the names as persistent attributes ("UniqueNameAttri...
ROSE_DLL_API bool hasMultipleInitStatmentsOrExpressions(SgForStatement *for_loop)
Check if a for loop uses C99 style initialization statement with multiple expressions like for (int i...
ROSE_DLL_API void fixNamespaceDeclaration(SgNamespaceDeclarationStatement *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void serialize(SgNode *node, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
we have two serialize() functions, one for a single node, the other for a list of pointers
ROSE_DLL_API void deleteExpressionTreeWithOriginalExpressionSubtrees(SgNode *root)
Special purpose function for deleting AST expression tress containing valid original expression trees...
void setSourcePositionAsTransformation(SgNode *node)
DQ (5/1/2012): New function with improved name.
ROSE_DLL_API void insertStatementList(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts, bool insertBefore=true)
Insert a list of statements before or after the target statement within the.
void whereAmI(SgNode *node)
Diagnostic function for tracing back through the parent list to understand at runtime where in the AS...
ROSE_DLL_API SgStatement * getLastStatement(SgScopeStatement *scope)
get the last statement within a scope, return NULL if it does not exit
ROSE_DLL_API void addStepToLoopBody(SgScopeStatement *loopStmt, SgStatement *step)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool is_UPC_dynamic_threads()
ROSE_DLL_API SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCallExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_mixed_Fortran_and_C_language()
ROSE_DLL_API void addTextForUnparser(SgNode *astNode, std::string s, AstUnparseAttribute::RelativePositionType inputlocation)
Add a string to be unparsed to support code generation for back-end specific tools or compilers.
ROSE_DLL_API std::string getTempDirectory(SgProject *project)
Create a temporary directory if it does not yet exist and return its name.
ROSE_DLL_API void displayScope(SgScopeStatement *scope)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_Jovial_language()
ROSE_DLL_API SgMemberFunctionDeclaration * findJavaMain(SgClassDefinition *)
Find a main method in a Java class.
ROSE_DLL_API bool is_Cxx_language()
void resetScopeNumbers(SgFunctionDefinition *functionDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API SgFunctionDeclaration * replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool hasSameGlobalScope(SgStatement *statement_1, SgStatement *statement_2)
This is supporting the recognition of functions in header files from two different ASTs.
SgCommaOpExp * insertBeforeUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp)
Insert an expression (new_exp )before another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API void fixFunctionDeclaration(SgFunctionDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
ROSE_DLL_API std::string preprocessImport(SgProject *, std::string)
Using the import_string parameter, create a file with the relevant import statement; translate the fi...
ROSE_DLL_API bool collectReadWriteRefs(SgStatement *stmt, std::vector< SgNode * > &readRefs, std::vector< SgNode * > &writeRefs, bool useCachedDefUse=false)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void prependStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
prepend a list of statements to the beginning of the current scope, handling side effects as appropri...
ROSE_DLL_API SgInitializer * getInitializerOfExpression(SgExpression *n)
Get the initializer containing an expression if it is within an initializer.
ROSE_DLL_API std::vector< SgInitializedName * > getInParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial input parameters from the function parameter list (may work for Fortran in the...
ROSE_DLL_API bool language_may_contain_nondeclarations_in_scope()
ROSE_DLL_API std::set< SgStatement * > collectTransformedStatements(SgNode *node)
This collects the statements that are marked as transformed (useful in debugging).
ROSE_DLL_API void cleanupNontransformedBasicBlockNode()
Remove unused basic block IR nodes added as part of normalization.
ROSE_DLL_API bool skipTranslateToUseCppDeclaration(PreprocessingInfo *currentPreprocessingInfo)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API AbstractHandle::abstract_handle * buildAbstractHandle(SgNode *)
Build an abstract handle from an AST node, reuse previously built handle when possible.
ROSE_DLL_API void insertStatementListBefore(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmts)
Insert a list of statements before a target statement.
ROSE_DLL_API void fixStructDeclaration(SgClassDeclaration *structDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
void recursivePrintCurrentAndParent(SgNode *n)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void appendExpressionList(SgExprListExp *, const std::vector< SgExpression * > &)
Append an expression list to a SgExprListExp, set the parent pointers also.
ROSE_DLL_API void collectReadOnlySymbols(SgStatement *stmt, std::set< SgVariableSymbol * > &readOnlySymbols, bool coarseGrain=true)
Collect read only variable symbols within a statement. The statement can be either of a function,...
bool isOverloaded(SgFunctionDeclaration *functionDeclaration)
Return true if function is overloaded.
ROSE_DLL_API int set_name(SgInitializedName *initializedNameNode, SgName new_name)
set_name of symbol in symbol table.
ROSE_DLL_API SgClassDefinition * findOrInsertJavaPackage(SgProject *, std::string, bool create_directory=false)
Process a qualified package name, if needed, and return its package definition.
ROSE_DLL_API SgClassDeclaration * findOrImportJavaClass(SgProject *, SgClassDefinition *package_definition, std::string)
If the class_name already exists in the scope, return it.
ROSE_DLL_API SgVariableSymbol * getFirstVarSym(SgVariableDeclaration *decl)
Get the variable symbol for the first initialized name of a declaration stmt.
ROSE_DLL_API bool templateArgumentEquivalence(SgTemplateArgument *arg1, SgTemplateArgument *arg2)
Verify that 2 SgTemplateArgument are equivalent (same type, same expression, or same template declara...
ROSE_DLL_API SgFunctionDeclaration * findFirstDefiningFunctionDecl(SgScopeStatement *scope)
Find the first defining function declaration statement in a scope.
ROSE_DLL_API bool is_Jvm_language()
void addMessageStatement(SgStatement *stmt, std::string message)
Function to add "C" style comment to statement.
ROSE_DLL_API bool isLoopIndexVariable(SgInitializedName *ivar, SgNode *subtree_root)
Check if a SgInitializedName is used as a loop index within a AST subtree This function will use a bo...
SgInitializedName & getFirstVariable(SgVariableDeclaration &vardecl)
convenience function that returns the first initialized name in a list of variable declarations.
void initializeSwitchStatement(SgSwitchStatement *switchStatement, SgStatement *item_selector, SgStatement *body)
Support function used for variable declarations in conditionals.
SgExprListExp * loopCollapsing(SgForStatement *target_loop, size_t collapsing_factor)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void fixStatement(SgStatement *stmt, SgScopeStatement *scope)
A wrapper containing fixes (fixVariableDeclaration(),fixStructDeclaration(), fixLabelStatement(),...
ROSE_DLL_API SgStatement * copyStatement(SgStatement *s)
Deep copy a statement.
ROSE_DLL_API int eraseNullPreprocessingInfo(SgLocatedNode *lnode)
Dumps a located node's preprocessing information.
ROSE_DLL_API bool isCanonicalDoLoop(SgFortranDo *loop, SgInitializedName **ivar, SgExpression **lb, SgExpression **ub, SgExpression **step, SgStatement **body, bool *hasIncrementalIterationSpace, bool *isInclusiveUpperBound)
Check if a Fortran Do loop has a complete canonical form: Do I=1, 10, 1.
SgCommaOpExp * insertAfterUsingCommaOp(SgExpression *new_exp, SgExpression *anchor_exp, SgStatement **temp_decl=NULL, SgVarRefExp **temp_ref=NULL)
Insert an expression (new_exp ) after another expression (anchor_exp) has possible side effects,...
ROSE_DLL_API SgTemplateVariableSymbol * lookupTemplateVariableSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *tplparams, SgTemplateArgumentPtrList *tplargs, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void moveUpPreprocessingInfo(SgStatement *stmt_dst, SgStatement *stmt_src, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Identical to movePreprocessingInfo(), except for the stale name and confusing order of parameters....
ROSE_DLL_API SgStatement * lastStatementOfScopeWithTokenInfo(SgScopeStatement *scope, std::map< SgNode *, TokenStreamSequenceToNodeMapping * > &tokenStreamSequenceMap)
Used to support token unparsing (when the output the trailing token sequence).
ROSE_DLL_API void cutPreprocessingInfo(SgLocatedNode *src_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &save_buf)
Cut preprocessing information from a source node and save it into a buffer. Used in combination of pa...
ROSE_DLL_API bool normalizeForLoopTest(SgForStatement *loop)
Normalize a for loop's test expression i<x is normalized to i<= (x-1) and i>x is normalized to i>= (x...
bool declarationPreceedsDefinition(SgDeclarationStatement *nonDefiningDeclaration, SgDeclarationStatement *definingDeclaration)
Check if a defining declaration comes before of after the non-defining declaration.
ROSE_DLL_API bool isSameFunction(SgFunctionDeclaration *func1, SgFunctionDeclaration *func2)
Check if two function declarations refer to the same one. Two function declarations are the same when...
std::vector< SgVariableSymbol * > getSymbolsUsedInExpression(SgExpression *expr)
Find referenced symbols within an expression.
ROSE_DLL_API bool isStructDeclaration(SgNode *node)
Check if a SgNode is a declaration for a structure.
ROSE_DLL_API void moveVariableDeclaration(SgVariableDeclaration *decl, SgScopeStatement *target_scope)
Move a variable declaration to a new scope, handle symbol, special scopes like For loop,...
ROSE_DLL_API std::string preprocessPackage(SgProject *, std::string)
Using the package_name, create a file with a package statement, translate it in order to load the pac...
ROSE_DLL_API void setOneSourcePositionForTransformation(SgNode *root)
Set current node's source position as transformation generated.
NodeType * deepCopy(const NodeType *subtree)
A template function for deep copying a subtree. It is also used to create deepcopy functions with spe...
void clearMangledNameCache(SgGlobal *globalScope)
Support for faster mangled name generation (caching avoids recomputation).
std::vector< SgStatement * > getSwitchCases(SgSwitchStatement *sw)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool isScalarType(SgType *t)
Is this a scalar type?
ROSE_DLL_API void changeBreakStatementsToGotos(SgStatement *loopOrSwitch)
If the given statement contains any break statements in its body, add a new label below the statement...
ROSE_DLL_API SgFunctionDefinition * getEnclosingFunctionDefinition(SgNode *astNode, const bool includingSelf=false)
Find a node by type using upward traversal.
ROSE_DLL_API bool is_CAF_language()
ROSE_DLL_API void printOutComments(SgLocatedNode *locatedNode)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void ReductionRecognition(SgForStatement *loop, std::set< std::pair< SgInitializedName *, OmpSupport::omp_construct_enum > > &results)
Recognize and collect reduction variables and operations within a C/C++ loop, following OpenMP 3....
ROSE_DLL_API bool loopUnrolling(SgForStatement *loop, size_t unrolling_factor)
Unroll a target loop with a specified unrolling factor. It handles steps larger than 1 and adds a fri...
ROSE_DLL_API void setLoopCondition(SgScopeStatement *loop, SgStatement *cond)
Set the condition statement of a loop, including While-loop, For-loop, and Do-While-loop.
bool ROSE_DLL_API isStatic(SgDeclarationStatement *stmt)
Check if a declaration has a "static' modifier.
PreprocessingInfo * attachComment(SgSourceFile *source_file, const std::string &content, PreprocessingInfo::DirectiveType directive_type=PreprocessingInfo::C_StyleComment, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Build and attach comment onto the global scope of a source file.
ROSE_DLL_API SgClassDefinition * getEnclosingClassDefinition(SgNode *astnode, const bool includingSelf=false)
Get the closest class definition enclosing the specified AST node,.
ROSE_DLL_API bool mergeDeclarationAndAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt, bool removeAssignStmt=true)
Merge a variable assignment statement into a matching variable declaration statement....
ROSE_DLL_API void checkAccessPermissions(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgFunctionDeclaration * > generateFunctionDefinitionsList(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void replaceMacroCallsWithExpandedStrings(SgPragmaDeclaration *target)
Check if a pragma declaration node has macro calls attached, if yes, replace macro calls within the p...
std::string generateUniqueNameForUseAsIdentifier(SgDeclarationStatement *declaration)
Generate a useful name to support construction of identifiers from declarations.
ROSE_DLL_API bool isRestrictType(SgType *t)
Is this a restrict type?
ROSE_DLL_API std::string generateProjectName(const SgProject *project, bool supressSuffix=false)
Added mechanism to generate project name from list of file names.
ROSE_DLL_API void resetInternalMapsForTargetStatement(SgStatement *sourceStatement)
Reset internal data structures used for token-based unparsing and macro summaries based on modificati...
ROSE_DLL_API bool is_Cuda_language()
ROSE_DLL_API bool isLambdaCapturedVariable(SgVarRefExp *varRef)
check if a variable reference is this->a[i] inside of a lambda function
ROSE_DLL_API int instrumentEndOfFunction(SgFunctionDeclaration *func, SgStatement *s)
Instrument(Add a statement, often a function call) into a function right before the return points,...
ROSE_DLL_API SgInitializedName * getFirstInitializedName(SgVariableDeclaration *decl)
Get the first initialized name of a declaration statement.
void setSourcePositionPointersToNull(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfDoWhile(SgDoWhileStmt *ws)
Check if the body of a 'do .. while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void reportModifiedStatements(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API std::vector< SgInitializedName * > getOutParameters(const SgInitializedNamePtrList &params)
Get a vector of Jovial output parameters from the function parameter list (may work for Fortran in th...
ROSE_DLL_API void setSourcePositionForTransformation(SgNode *root)
Recursively set source position info(Sg_File_Info) as transformation generated.
ROSE_DLL_API SgGlobal * getGlobalScope(const SgNode *astNode)
Traverse back through a node's parents to find the enclosing global scope.
ROSE_DLL_API void insertStatementListAfter(SgStatement *targetStmt, const std::vector< SgStatement * > &newStmt)
Insert a list of statements after a target statement.
ROSE_DLL_API bool isMain(const SgNode *node)
Check if a SgNode is a main() function declaration.
std::map< std::string, int > local_name_collision_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API void fixClassDeclaration(SgClassDeclaration *classDecl, SgScopeStatement *scope)
Fix symbols, parent and scope pointers. Used internally within appendStatment(), insertStatement() et...
ROSE_DLL_API int collectVariableReferencesInArrayTypes(SgLocatedNode *root, Rose_STL_Container< SgNode * > &currentVarRefList)
Collect variable references in array types. The default NodeQuery::querySubTree() will miss variables...
SgBasicBlock * ensureBasicBlockAsBodyOfCaseOption(SgCaseOptionStmt *cs)
Check if the body of a 'case option' statement is a SgBasicBlock, create one if not.
void checkForInitializers(SgNode *node)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void removeUnusedLabels(SgNode *top, bool keepChild=false)
Remove labels which are not targets of any goto statements: its child statement is also removed by de...
ROSE_DLL_API SgProject * getProject()
Get the current SgProject IR Node.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfUpcForAll(SgUpcForAllStatement *fs)
Check if the body of a 'upc_forall' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgClassDeclaration * getEnclosingClassDeclaration(SgNode *astNode)
Get the closest class declaration enclosing the specified AST node,.
ROSE_DLL_API void insertStatement(SgStatement *targetStmt, SgStatement *newStmt, bool insertBefore=true, bool autoMovePreprocessingInfo=true)
Insert a statement before or after the target statement within the target's scope....
ROSE_DLL_API void listHeaderFiles(SgIncludeFile *includeFile)
return path prefix for subtree of include files.
ROSE_DLL_API void markSubtreeToBeUnparsedTreeTraversal(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
void saveToPDF(SgNode *node, std::string filename)
Save AST into a pdf file. Start from a node to find its enclosing file node. The entire file's AST wi...
ROSE_DLL_API bool normalizeForLoopInitDeclaration(SgForStatement *loop)
Normalize loop init stmt by promoting the single variable declaration statement outside of the for lo...
void detectCycleInType(SgType *type, const std::string &from)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void deleteAST(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool statementCanBeTransformed(SgStatement *stmt)
If header file unparsing and token-based unparsing are used, then some statements in header files use...
ROSE_DLL_API SgStatement * getNextStatement(SgStatement *currentStmt)
Get next statement within the same scope of current statement.
ROSE_DLL_API std::set< SgLabelStatement * > findUnusedLabels(SgNode *top)
Find unused labels which are not targets of any goto statements.
ROSE_DLL_API void setExtern(SgDeclarationStatement *stmt)
Set a declaration as extern.
ROSE_DLL_API void deleteAllNodes()
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API bool templateArgumentListEquivalence(const SgTemplateArgumentPtrList &list1, const SgTemplateArgumentPtrList &list2)
Verify that 2 SgTemplateArgumentPtrList are equivalent.
ROSE_DLL_API LivenessAnalysis * call_liveness_analysis(SgProject *project, bool debug=false)
Call liveness analysis on an entire project.
ROSE_DLL_API void reportModifiedLocatedNodes(const std::string &label, SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void fixTemplateDeclaration(SgTemplateDeclaration *stmt, SgScopeStatement *scope)
Fix the symbol table and set scope (only if scope in declaration is not already set).
SgType * getBoolType(SgNode *n)
Get the right bool type according to C or C++ language input.
void clearSharedGlobalScopes(SgProject *project)
Collect all read and write references within stmt, which can be a function, a scope statement,...
void initializeWhileStatement(SgWhileStmt *whileStatement, SgStatement *condition, SgStatement *body, SgStatement *else_body)
Support function used for variable declarations in conditionals.
ROSE_DLL_API void setSourcePosition(SgNode *node)
Set the source code positon for the current (input) node.
ROSE_DLL_API void setPragma(SgPragmaDeclaration *decl, SgPragma *pragma)
Set a pragma of a pragma declaration. handle memory release for preexisting pragma,...
ROSE_DLL_API void insertStatementListBeforeFirstNonDeclaration(const std::vector< SgStatement * > &newStmts, SgScopeStatement *scope)
Insert statements before the first non-declaration statement in a scope. If the scope has no non-decl...
ROSE_DLL_API bool isPostfixOperator(SgExpression *exp)
Is an overloaded operator a postfix operator. (e.g. ).
ROSE_DLL_API SgStatement * findSurroundingStatementFromSameFile(SgStatement *targetStmt, bool &surroundingStatementPreceedsTargetStatement)
Supporting function to comment relocation in insertStatement() and removeStatement().
SgNamespaceDefinitionStatement * enclosingNamespaceScope(SgDeclarationStatement *declaration)
Find the enclosing namespace of a declaration.
ROSE_DLL_API SgStatement * getLoopBody(SgScopeStatement *loop)
Routines to get and set the body of a loop.
ROSE_DLL_API bool is_mixed_C_and_Cxx_language()
bool isStructurallyEquivalentAST(SgNode *tree1, SgNode *tree2)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API PreprocessingInfo * insertHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader, bool asLastHeader)
Insert #include "filename" or #include <filename> (system header) onto the global scope of a source f...
void printAST2TextFile(SgNode *node, const char *filename, bool printType=true)
Pretty print AST horizontally, output to a specified text file. If printType is set to false,...
ROSE_DLL_API SgFunctionSymbol * lookupTemplateFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_language_case_insensitive()
ROSE_DLL_API void replaceStatement(SgStatement *oldStmt, SgStatement *newStmt, bool movePreprocessinInfo=false)
Replace a statement with another. Move preprocessing information from oldStmt to newStmt if requested...
ROSE_DLL_API void recordNormalizations(SgStatement *s)
Record where normalization have been done so that we can preform denormalizations as required for the...
ROSE_DLL_API bool loopInterchange(SgForStatement *loop, size_t depth, size_t lexicoOrder)
Interchange/permutate a n-level perfectly-nested loop rooted at 'loop' using a lexicographical order ...
void printAST(SgNode *node)
Pretty print AST horizontally, output to std output.
ROSE_DLL_API SgFunctionSymbol * lookupTemplateMemberFunctionSymbolInParentScopes(const SgName &functionName, SgFunctionType *ftype, SgTemplateParameterPtrList *tplparams, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool is_PHP_language()
ROSE_DLL_API bool isEqualToIntConst(SgExpression *e, int value)
Check if a SgIntVal node has a given value.
ROSE_DLL_API void insertStatementBeforeFirstNonDeclaration(SgStatement *newStmt, SgScopeStatement *scope, bool movePreprocessingInfo=true)
Insert a statement before the first non-declaration statement in a scope. If the scope has no non-dec...
ROSE_DLL_API SgFunctionSymbol * lookupFunctionSymbolInParentScopes(const SgName &functionName, SgScopeStatement *currentScope=NULL)
look up the first matched function symbol in parent scopes given only a function name,...
ROSE_DLL_API void appendStatementWithDependentDeclaration(SgDeclarationStatement *decl, SgGlobal *scope, SgStatement *original_statement, bool excludeHeaderFiles)
Append a copy ('decl') of a function ('original_statement') into a 'scope', include any referenced de...
ROSE_DLL_API bool insideHeader(SgLocatedNode *node)
Check if a node is from a header file.
ROSE_DLL_API void markSubtreeToBeUnparsed(SgNode *root, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isDataMemberReference(SgVarRefExp *varRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool collectReadWriteVariables(SgStatement *stmt, std::set< SgInitializedName * > &readVars, std::set< SgInitializedName * > &writeVars, bool coarseGrain=true)
Collect unique variables which are read or written within a statement. Note that a variable can be bo...
ROSE_DLL_API void constantFolding(SgNode *r)
Constant folding an AST subtree rooted at 'r' (replacing its children with their constant values,...
std::vector< SgBreakStmt * > findBreakStmts(SgStatement *code, const std::string &fortranLabel="")
Find break statements inside a particular statement, stopping at nested loops or switches.
ROSE_DLL_API SgFile * getEnclosingFileNode(SgNode *astNode)
get the SgFile node from current node
ROSE_DLL_API void setStatic(SgDeclarationStatement *stmt)
Set a declaration as static.
ROSE_DLL_API bool doLoopNormalization(SgFortranDo *loop)
Normalize a Fortran Do loop. Make the default increment expression (1) explicit.
ROSE_DLL_API SgFile * preprocessCompilationUnit(SgProject *, std::string, std::string, bool unparse=true)
Using the file_content string, create a file with the content in question; build its AST and add it t...
ROSE_DLL_API void removeLabeledGotos(SgNode *top)
Remove labeled goto statements.
std::map< SgNode *, std::string > local_node_to_name_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
std::vector< SgGotoStatement * > findGotoStmts(SgStatement *scope, SgLabelStatement *l)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
ROSE_DLL_API bool mergeDeclarationWithAssignment(SgVariableDeclaration *decl, SgExprStatement *assign_stmt)
Merge a declaration statement into a matching followed variable assignment. Callers should make sure ...
ROSE_DLL_API bool isAssignmentStatement(SgNode *_s, SgExpression **lhs=NULL, SgExpression **rhs=NULL, bool *readlhs=NULL)
Check if a SgNode _s is an assignment statement (any of =,+=,-=,&=,/=, ^=, etc)
ROSE_DLL_API bool normalizeCaseAndDefaultBlocks(SgSwitchStatement *switchStmt)
Normalize the structure of case and default blocks within a switch statement.
ROSE_DLL_API void outputSharedNodes(SgNode *node)
Find a node by type using upward traversal.
bool ROSE_DLL_API isAncestor(SgNode *node1, SgNode *node2)
check if node1 is a strict ancestor of node 2. (a node is not considered its own ancestor)
ROSE_DLL_API SgScopeStatement * getEnclosingScope(SgNode *n, const bool includingSelf=false)
Get the enclosing scope from a node n.
ROSE_DLL_API SgNonrealSymbol * lookupNonrealSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgSwitchStatement * findEnclosingSwitch(SgStatement *s)
Find the closest switch outside a given statement (normally used for case and default statements)
ROSE_DLL_API void removeAllOriginalExpressionTrees(SgNode *top)
Set original expression trees to NULL for SgValueExp or SgCastExp expressions, so you can change the ...
ROSE_DLL_API std::vector< SgNode * > astIntersection(SgNode *original, SgNode *copy, SgCopyHelp *help=NULL)
Compute the intersection set for two ASTs.
ROSE_DLL_API bool isPrefixOperator(SgExpression *exp)
Is an overloaded operator a prefix operator (e.g. address operator X * operator&(),...
ROSE_DLL_API void setLhsOperand(SgExpression *target, SgExpression *lhs)
set left hand operand for binary expressions, transparently downcasting target expressions when neces...
ROSE_DLL_API std::vector< SgC_PreprocessorDirectiveStatement * > translateStatementToUseCppDeclarations(SgStatement *statement, SgScopeStatement *scope)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API int suggestNextNumericLabel(SgFunctionDefinition *func_def)
Suggest next usable (non-conflicting) numeric label value for a Fortran function definition scope.
ROSE_DLL_API std::set< SgStatement * > collectModifiedStatements(SgNode *node)
This collects the statements that are marked as modified (a flag automatically set by all set_* gener...
ROSE_DLL_API SgFunctionDeclaration * getEnclosingFunctionDeclaration(SgNode *astNode, const bool includingSelf=false)
Find the enclosing function declaration, including its derived instances like isSgProcedureHeaderStat...
SgFunctionDeclaration * findFunctionDeclaration(SgNode *root, std::string name, SgScopeStatement *scope, bool isDefining)
Topdown traverse a subtree from root to find the first function declaration matching the given name,...
ROSE_DLL_API bool isPrefixOperatorName(const SgName &functionName)
Check for proper names of possible prefix operators (used in isPrefixOperator()).
ROSE_DLL_API void setLoopStride(SgNode *loop, SgExpression *stride)
Set the stride(step) of a loop 's incremental expression, regardless the expression types (i+=s; i= i...
ROSE_DLL_API bool isInSubTree(SgExpression *subtree, SgExpression *exp)
Find a node by type using upward traversal.
ROSE_DLL_API bool forLoopNormalization(SgForStatement *loop, bool foldConstant=true)
Normalize a for loop, return true if successful.
unsigned long long getIntegerConstantValue(SgValueExp *expr)
Get the constant value from a constant integer expression; abort on everything else.
ROSE_DLL_API bool is_UPC_language()
ROSE_DLL_API void checkSymbolTables(SgNode *)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void updateDefiningNondefiningLinks(SgFunctionDeclaration *func, SgScopeStatement *scope)
Update defining and nondefining links due to a newly introduced function declaration....
ROSE_DLL_API SgNode * deepCopyNode(const SgNode *subtree)
Deep copy an arbitrary subtree.
SgBasicBlock * ensureBasicBlockAsBodyOfDefaultOption(SgDefaultOptionStmt *cs)
Check if the body of a 'default option' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void getLiveVariables(LivenessAnalysis *liv, SgForStatement *loop, std::set< SgInitializedName * > &liveIns, std::set< SgInitializedName * > &liveOuts)
get liveIn and liveOut variables for a for loop from liveness analysis result liv.
ROSE_DLL_API void resetModifiedLocatedNodes(const std::set< SgLocatedNode * > &modifiedNodeSet)
Use the set of IR nodes and set the isModified flag in each IR node to true.
ROSE_DLL_API SgNode * replaceWithPattern(SgNode *anchor, SgNode *new_pattern)
Replace an anchor node with a specified pattern subtree with optional SgVariantExpression....
ROSE_DLL_API bool ROSE_DLL_API isJovialOutParam(SgInitializedName *name)
True if a parameter name is a Jovial output parameter.
ROSE_DLL_API void moveForStatementIncrementIntoBody(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfOmpBodyStmt(SgOmpBodyStatement *ompbodyStmt)
Check if the body of a SgOmpBodyStatement is a SgBasicBlock, create one if not.
ROSE_DLL_API bool is_Python_language()
ROSE_DLL_API bool is_mixed_Fortran_and_Cxx_language()
ROSE_DLL_API SgStatement * getLoopCondition(SgScopeStatement *loop)
Routines to get the condition of a loop. It recognize While-loop, For-loop, and Do-While-loop.
ROSE_DLL_API SgEnumSymbol * lookupEnumSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableAndReferenceForExpression(SgExpression *expression, SgScopeStatement *scope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgTypedefSymbol * lookupTypedefSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfWhile(SgWhileStmt *ws)
Check if the body of a 'while' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfFor(SgForStatement *fs)
Check if the body of a 'for' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API PreprocessingInfo * attachArbitraryText(SgLocatedNode *target, const std::string &text, PreprocessingInfo::RelativePositionType position=PreprocessingInfo::before)
Attach an arbitrary string to a located node. A workaround to insert irregular statements or vendor-s...
ROSE_DLL_API void markNodeToBeUnparsed(SgNode *node, int physical_file_id)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstantTrue(SgExpression *e)
Check if a bool or int constant expression evaluates to be a true value.
std::map< std::string, SgNode * > local_name_to_node_map
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API bool is_binary_executable()
void changeAllBodiesToBlocks(SgNode *top, bool createEmptyBody=true)
Fix up ifs, loops, while, switch, Catch, OmpBodyStatement, etc. to have blocks as body components....
void dumpPreprocInfo(SgLocatedNode *locatedNode)
Dumps a located node's preprocessing information.
void fixupReferencesToSymbols(const SgScopeStatement *this_scope, SgScopeStatement *copy_scope, SgCopyHelp &help)
All the symbol table references in the copied AST need to be reset after rebuilding the copied scope'...
ROSE_DLL_API void moveDeclarationToAssociatedNamespace(SgDeclarationStatement *declarationStatement)
Relocate the declaration to be explicitly represented in its associated namespace (required for some ...
ROSE_DLL_API bool isCanonicalForLoop(SgNode *loop, SgInitializedName **ivar=NULL, SgExpression **lb=NULL, SgExpression **ub=NULL, SgExpression **step=NULL, SgStatement **body=NULL, bool *hasIncrementalIterationSpace=NULL, bool *isInclusiveUpperBound=NULL)
Check if a for-loop has a canonical form, return loop index, bounds, step, and body if requested.
ROSE_DLL_API bool isArrayReference(SgExpression *ref, SgExpression **arrayNameExp=NULL, std::vector< SgExpression * > **subscripts=NULL)
Check if an expression is an array access (SgPntrArrRefExp). If so, return its name expression and su...
ROSE_DLL_API void insertStatementAfterLastDeclaration(SgStatement *stmt, SgScopeStatement *scope)
Insert a statement after the last declaration within a scope. The statement will be prepended to the ...
ROSE_DLL_API void destroyTempDirectory(std::string)
Use the system command to remove a temporary directory and all its containing files.
void serialize_list(T &plist, std::string T_name, std::string &prefix, bool hasRemaining, std::ostringstream &out, std::string &edgeLabel)
Query a subtree to get all nodes of a given type, with an appropriate downcast.
void resetMangledNameCache(SgGlobal *globalScope)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API SgTemplateInstantiationMemberFunctionDecl * buildForwardFunctionDeclaration(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Generate a non-defining (forward) declaration from a defining function declaration.
ROSE_DLL_API bool is_Fortran_language()
ROSE_DLL_API SgVariableSymbol * lookupVariableSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void outputFileIds(SgNode *node)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API SgExprStatement * splitVariableDeclaration(SgVariableDeclaration *decl)
Split a variable declaration with an rhs assignment into two statements: a declaration and an assignm...
ROSE_DLL_API SgStatement * getFirstStatement(SgScopeStatement *scope, bool includingCompilerGenerated=false)
Get the first statement within a scope, return NULL if it does not exist. Skip compiler-generated sta...
ROSE_DLL_API SgNamespaceSymbol * lookupNamespaceSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isExtern(SgDeclarationStatement *stmt)
Check if a declaration has an "extern" modifier.
std::string extractPragmaKeyword(const SgPragmaDeclaration *)
Extract a SgPragmaDeclaration's leading keyword . For example "#pragma omp parallel" has a keyword of...
ROSE_DLL_API SgTemplateClassSymbol * lookupTemplateClassSymbolInParentScopes(const SgName &name, SgTemplateParameterPtrList *templateParameterList, SgTemplateArgumentPtrList *templateArgumentList, SgScopeStatement *cscope=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API bool isEquivalentFunctionType(const SgFunctionType *lhs, const SgFunctionType *rhs)
Test if two types are equivalent SgFunctionType nodes.
ROSE_DLL_API void setLoopLowerBound(SgNode *loop, SgExpression *lb)
Set the lower bound of a loop header for (i=lb; ...)
void guardNode(SgLocatedNode *target, std::string guard)
Add preproccessor guard around a given node.
bool checkTypesAreEqual(SgType *typeA, SgType *typeB)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool isReferenceType(SgType *t)
Is this type a const or non-const reference type? (Handles typedefs correctly)
ROSE_DLL_API void moveCommentsToNewStatement(SgStatement *sourceStatement, const std::vector< int > &indexList, SgStatement *destinationStatement, bool destinationStatementPreceedsSourceStatement)
Relocate comments and CPP directives from one statement to another.
ROSE_DLL_API SgStatement * getEnclosingStatement(SgNode *n)
Find the closest enclosing statement, including the given node.
ROSE_DLL_API void translateToUseCppDeclarations(SgNode *n)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API void changeContinuesToGotos(SgStatement *stmt, SgLabelStatement *label)
Change continue statements in a given block of code to gotos to a label.
void outputGlobalFunctionTypeSymbolTable()
Output function type symbols in global function type symbol table.
ROSE_DLL_API SgScopeStatement * findEnclosingLoop(SgStatement *s, const std::string &fortranLabel="", bool stopOnSwitches=false)
Find the closest loop outside the given statement; if fortranLabel is not empty, the Fortran label of...
std::pair< SgVariableDeclaration *, SgExpression * > createTempVariableForExpression(SgExpression *expression, SgScopeStatement *scope, bool initializeInDeclaration, SgAssignOp **reEvaluate=NULL)
Given an expression, generates a temporary variable whose initializer optionally evaluates that expre...
bool isBodyStatement(SgStatement *s)
Check if a statement is a (true or false) body of a container-like parent, such as For,...
bool functionCallExpressionPreceedsDeclarationWhichAssociatesScope(SgFunctionCallExp *functionCall)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void convertAllForsToWhiles(SgNode *top)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API bool isConstantFalse(SgExpression *e)
Check if a bool or int constant expression evaluates to be a false value.
ROSE_DLL_API void outputLocalSymbolTables(SgNode *node)
Output the local symbol tables.
ROSE_DLL_API void preOrderCollectPreprocessingInfo(SgNode *current, std::vector< PreprocessingInfo * > &infoList, int depth)
Dumps a located node's preprocessing information.
ROSE_DLL_API SgMemberFunctionDeclaration * getDefaultDestructor(SgClassDeclaration *classDeclaration)
Get the default destructor from the class declaration.
void collectVarRefs(SgLocatedNode *root, std::vector< SgVarRefExp * > &result)
Collect all variable references in a subtree.
ROSE_DLL_API void setOperand(SgExpression *target, SgExpression *operand)
Set operands for expressions with single operand, such as unary expressions. handle file info,...
ROSE_DLL_API SgMemberFunctionDeclaration * getDefaultConstructor(SgClassDeclaration *classDeclaration)
Get the default constructor from the class declaration.
ROSE_DLL_API SgInitializedName * getLoopIndexVariable(SgNode *loop)
Return the loop index variable for a for loop.
ROSE_DLL_API SgAssignInitializer * splitExpression(SgExpression *from, std::string newName="")
Replace an expression with a temporary variable and an assignment statement.
ROSE_DLL_API void replaceVariableReferences(SgVariableSymbol *old_sym, SgVariableSymbol *new_sym, SgScopeStatement *scope)
Replace all variable references to an old symbol in a scope to being references to a new symbol.
ROSE_DLL_API bool is_OpenCL_language()
ROSE_DLL_API bool normalizeForLoopIncrement(SgForStatement *loop)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API SgVariableSymbol * appendArg(SgFunctionParameterList *, SgInitializedName *)
Append an argument to SgFunctionParameterList, transparently set parent,scope, and symbols for argume...
ROSE_DLL_API bool unnormalizeForLoopInitDeclaration(SgForStatement *loop)
Undo the normalization of for loop's C99 init declaration. Previous record of normalization is used t...
ROSE_DLL_API SgStatement * getPreviousStatement(SgStatement *currentStmt, bool climbOutScope=true)
Get previous statement of the current statement. It may return a previous statement of a parent scope...
ROSE_DLL_API void removeJumpsToNextStatement(SgNode *)
Remove jumps whose label is immediately after the jump. Used to clean up inlined code fragments.
bool isPrototypeInScope(SgScopeStatement *scope, SgFunctionDeclaration *functionDeclaration, SgDeclarationStatement *startingAtDeclaration)
Assigns unique numbers to each SgScopeStatement of a function.
ROSE_DLL_API int moveUpInnerDanglingIfEndifDirective(SgLocatedNode *lnode)
Extract sequences like " #endif #endif ... #if | #ifdef| #ifndef" buried inside subtree of lnode.
SgDeclarationStatement * getNonInstantiatonDeclarationForClass(SgTemplateInstantiationMemberFunctionDecl *memberFunctionInstantiation)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool isConstType(SgType *t)
Is this a const type?
SgFunctionDeclaration * getDeclarationOfNamedFunction(SgExpression *func)
Given a SgExpression that represents a named function (or bound member function), return the mentione...
ROSE_DLL_API bool is_C99_language()
ROSE_DLL_API bool addDefaultConstructorIfRequired(SgClassType *classType, int physical_file_id=Sg_File_Info::TRANSFORMATION_FILE_ID)
Get the default destructor from the class declaration.
ROSE_DLL_API void movePreprocessingInfo(SgStatement *stmt_src, SgStatement *stmt_dst, PreprocessingInfo::RelativePositionType src_position=PreprocessingInfo::undef, PreprocessingInfo::RelativePositionType dst_position=PreprocessingInfo::undef, bool usePrepend=false)
Move preprocessing information of stmt_src to stmt_dst, Only move preprocessing information from the ...
ROSE_DLL_API int fixVariableReferences(SgNode *root, bool cleanUnusedSymbol=true)
Connect variable reference to the right variable symbols when feasible, return the number of referenc...
ROSE_DLL_API bool isUseByAddressVariableRef(SgVarRefExp *ref)
Check if a variable reference is used by its address: including &a expression and foo(a) when type2 f...
struct const_int_expr_t evaluateConstIntegerExpression(SgExpression *expr)
The function tries to evaluate const integer expressions (such as are used in array dimension sizes)....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsTrueBodyOfIf(SgIfStmt *ifs)
Check if the true body of a 'if' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void replaceExpression(SgExpression *oldExp, SgExpression *newExp, bool keepOldExp=false)
Replace an expression with another, used for variable reference substitution and others....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsFalseBodyOfIf(SgIfStmt *ifs, bool createEmptyBody=true)
Check if the false body of a 'if' statement is a SgBasicBlock, create one if not when the flag is tru...
ROSE_DLL_API SgExprListExp * getEnclosingExprListExp(SgNode *astNode, const bool includingSelf=false)
Get the enclosing SgExprListExp (used as part of function argument index evaluation in subexpressions...
ROSE_DLL_API void appendStatement(SgStatement *stmt, SgScopeStatement *scope=NULL)
Append a statement to the end of the current scope, handle side effect of appending statements,...
ROSE_DLL_API SgFunctionDeclaration * buildFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
void addVarRefExpFromArrayDimInfo(SgNode *astNode, Rose_STL_Container< SgNode * > &NodeList_t)
Find all SgPntrArrRefExp under astNode, then add SgVarRefExp (if any) of SgPntrArrRefExp's dim_info i...
ROSE_DLL_API bool loopTiling(SgForStatement *loopNest, size_t targetLevel, size_t tileSize)
Tile the n-level (starting from 1) loop of a perfectly nested loop nest using tiling size s.
std::string generateUniqueName(const SgNode *node, bool ignoreDifferenceBetweenDefiningAndNondefiningDeclarations)
Generate unique name from C and C++ constructs. The name may contain space.
ROSE_DLL_API SgGlobal * getFirstGlobalScope(SgProject *project)
return the first global scope under current project
ROSE_DLL_API void setOneSourcePositionNull(SgNode *node)
Set current node's source position as NULL.
ROSE_DLL_API void setRhsOperand(SgExpression *target, SgExpression *rhs)
set left hand operand for binary expression
std::pair< SgStatement *, SgInitializedName * > wrapFunction(SgFunctionDeclaration &definingDeclaration, SgName newName)
moves the body of a function f to a new function f; f's body is replaced with code that forwards the ...
ROSE_DLL_API bool is_mixed_Fortran_and_C_and_Cxx_language()
ROSE_DLL_API bool isVolatileType(SgType *t)
Is this a volatile type?
void clearUnusedVariableSymbols(SgNode *root=NULL)
Clear those variable symbols with unknown type (together with initialized names) which are also not r...
ROSE_DLL_API void fixVariableDeclaration(SgVariableDeclaration *varDecl, SgScopeStatement *scope)
Patch up symbol, scope, and parent information when a SgVariableDeclaration's scope is known.
ROSE_DLL_API SgSymbol * lookupSymbolInParentScopesIgnoringAliasSymbols(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
std::string generateUniqueVariableName(SgScopeStatement *scope, std::string baseName="temp")
Generate a name like temp# that is unique in the current scope and any parent and children scopes.
ROSE_DLL_API int gensym_counter
An internal counter for generating unique SgName.
ROSE_DLL_API void splitExpressionIntoBasicBlock(SgExpression *expr)
Split long expressions into blocks of statements.
void reset_name_collision_map()
Reset map variables used to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API SgFunctionDefinition * getEnclosingProcedure(SgNode *n, const bool includingSelf=false)
Find the function definition.
std::vector< SgExpression * > get_C_array_dimensions(const SgArrayType &arrtype)
returns the array dimensions in an array as defined for arrtype
ROSE_DLL_API void replaceSubexpressionWithStatement(SgExpression *from, SageInterface::StatementGenerator *to)
Similar to replaceExpressionWithStatement, but with more restrictions.
ROSE_DLL_API void wrapAllTemplateInstantiationsInAssociatedNamespaces(SgProject *root)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
std::string get_name(const SgNode *node)
Generate a useful name to describe the SgNode.
ROSE_DLL_API void setLoopUpperBound(SgNode *loop, SgExpression *ub)
Set the upper bound of a loop header,regardless the condition expression type. for (i=lb; i op up,...
ROSE_DLL_API bool isMemberFunctionMemberReference(SgMemberFunctionRefExp *memberFunctionRefExp)
Find a node by type using upward traversal.
ROSE_DLL_API SgClassDefinition * findJavaPackage(SgScopeStatement *, std::string)
Look for a qualified package name in the given scope and return its package definition.
ROSE_DLL_API bool isOmpStatement(SgNode *)
Check if a node is SgOmp*Statement.
ROSE_DLL_API bool is_Ada_language()
std::string addMangledNameToCache(SgNode *astNode, const std::string &mangledName)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool is_C_language()
ROSE_DLL_API std::list< SgClassType * > getClassTypeChainForMemberReference(SgExpression *refExp)
Find a node by type using upward traversal.
ROSE_DLL_API void collectUseByAddressVariableRefs(const SgStatement *s, std::set< SgVarRefExp * > &varSetB)
Collect variable references involving use by address: including &a expression and foo(a) when type2 f...
std::vector< SgContinueStmt * > findContinueStmts(SgStatement *code, const std::string &fortranLabel="")
Find all continue statements inside a particular statement, stopping at nested loops.
std::string getMangledNameFromCache(SgNode *astNode)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API std::vector< SgDeclarationStatement * > sortSgNodeListBasedOnAppearanceOrderInSource(const std::vector< SgDeclarationStatement * > &nodevec)
Reorder a list of declaration statements based on their appearance order in source files.
ROSE_DLL_API std::set< SgLocatedNode * > collectModifiedLocatedNodes(SgNode *node)
This collects the SgLocatedNodes that are marked as modified (a flag automatically set by all set_* g...
SgExpression * forallMaskExpression(SgForAllStatement *stmt)
Get the mask expression from the header of a SgForAllStatement.
void clearScopeNumbers(SgFunctionDefinition *functionDefinition)
Clears the cache of scope,integer pairs for the input function.
ROSE_DLL_API SgInitializedName * convertRefToInitializedName(SgNode *current, bool coarseGrain=true)
Variable references can be introduced by SgVarRef, SgPntrArrRefExp, SgInitializedName,...
ROSE_DLL_API SgNode * getSgNodeFromAbstractHandleString(const std::string &input_string)
Obtain a matching SgNode from an abstract handle string.
ROSE_DLL_API void moveStatementsBetweenBlocks(SgBasicBlock *sourceBlock, SgBasicBlock *targetBlock)
Move statements in first block to the second block (preserves order and rebuilds the symbol table).
ROSE_DLL_API bool templateDefinitionIsInClass(SgTemplateInstantiationMemberFunctionDecl *memberFunctionDeclaration)
Return true if template definition is in the class, false if outside of class.
ROSE_DLL_API void fixLabelStatement(SgLabelStatement *label_stmt, SgScopeStatement *scope)
Fix symbol table for SgLabelStatement. Used Internally when the label is built without knowing its ta...
ROSE_DLL_API void replaceExpressionWithStatement(SgExpression *from, SageInterface::StatementGenerator *to)
Replace a given expression with a list of statements produced by a generator.
ROSE_DLL_API void convertForToWhile(SgForStatement *f)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
ROSE_DLL_API void insertStatementBefore(SgStatement *targetStmt, SgStatement *newStmt, bool autoMovePreprocessingInfo=true)
Insert a statement before a target statement.
ROSE_DLL_API bool findFirstSgCastExpMarkedAsTransformation(SgNode *n, const std::string &s)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API void dumpInfo(SgNode *node, std::string desc="")
Dump information about a SgNode for debugging.
ROSE_DLL_API void convertFunctionDefinitionsToFunctionPrototypes(SgNode *node)
XXX This function operates on the new file used to support outlined function definitions....
ROSE_DLL_API void appendStatementList(const std::vector< SgStatement * > &stmt, SgScopeStatement *scope=NULL)
Append a list of statements to the end of the current scope, handle side effect of appending statemen...
SgNamedType * getDeclaredType(const SgDeclarationStatement *declaration)
Returns the type introduced by a declaration.
ROSE_DLL_API bool isIndexOperator(SgExpression *exp)
Is an overloaded operator an index operator (also referred to as call or subscript operators)....
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfCatch(SgCatchOptionStmt *cos)
Check if the body of a 'catch' statement is a SgBasicBlock, create one if not.
std::vector< SgFile * > generateFileList()
Returns STL vector of SgFile IR node pointers.
ROSE_DLL_API int normalizeArrowExpWithAddressOfLeftOperand(SgNode *root, bool transformationGeneratedOnly=true)
Convert all code within root matching the patern of (&left)->right, and translate them into left....
bool hasTemplateSyntax(const SgName &name)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API void moveToSubdirectory(std::string directoryName, SgFile *file)
Move file to be generated in a subdirectory (will be generated by the unparser).
ROSE_DLL_API bool isAddressTaken(SgExpression *refExp)
Find a node by type using upward traversal.
ROSE_DLL_API bool hasSimpleChildrenList(SgScopeStatement *scope)
Check if a scope statement has a simple children statement list so insert additional statements under...
ROSE_DLL_API SgFunctionDeclaration * findMain(SgNode *currentNode)
top-down traversal from current node to find the main() function declaration
ROSE_DLL_API SgClassSymbol * lookupClassSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
ROSE_DLL_API void removeConsecutiveLabels(SgNode *top)
Remove consecutive labels.
ROSE_DLL_API void setLoopBody(SgScopeStatement *loop, SgStatement *body)
Add a step statement to the end of a loop body Add a new label to the end of the loop,...
bool getForLoopInformations(SgForStatement *for_loop, SgVariableSymbol *&iterator, SgExpression *&lower_bound, SgExpression *&upper_bound, SgExpression *&stride)
ROSE_DLL_API void appendExpression(SgExprListExp *, SgExpression *)
Append an expression to a SgExprListExp, set the parent pointer also.
ROSE_DLL_API bool isLambdaFunction(SgFunctionDeclaration *func)
Check if a function declaration is a C++11 lambda function.
ROSE_DLL_API SgBasicBlock * ensureBasicBlockAsBodyOfSwitch(SgSwitchStatement *ws)
Check if the body of a 'switch' statement is a SgBasicBlock, create one if not.
ROSE_DLL_API void prependStatement(SgStatement *stmt, SgScopeStatement *scope=NULL)
Prepend a statement to the beginning of the current scope, handling side effects as appropriate.
ROSE_DLL_API bool isCallToParticularFunction(SgFunctionDeclaration *decl, SgExpression *e)
Recursively print current and parent nodes. used within gdb to probe the context of a node.
ROSE_DLL_API bool ROSE_DLL_API isMutable(SgInitializedName *name)
True if an SgInitializedName is "mutable' (has storage modifier set)
ROSE_DLL_API bool isCopyConstructible(SgType *type)
Is a type copy constructible? This may not quite work properly.
ROSE_DLL_API SgVariableSymbol * prependArg(SgFunctionParameterList *, SgInitializedName *)
Prepend an argument to SgFunctionParameterList.
ROSE_DLL_API void setSourcePositionAtRootAndAllChildren(SgNode *root)
Set the source code positon for the subtree (including the root).
ROSE_DLL_API SgExpression * copyExpression(SgExpression *e)
Deep copy an expression.
void setParameterList(actualFunction *func, SgFunctionParameterList *paralist)
Set parameter list for a function declaration, considering existing parameter list etc.
SgStatement * findLastDeclarationStatement(SgScopeStatement *scope, bool includePragma=false)
Find the last declaration statement within a scope (if any). This is often useful to decide where to ...
ROSE_DLL_API bool insideSystemHeader(SgLocatedNode *node)
Set source position info(Sg_File_Info) as transformation generated for all SgNodes in memory pool.
std::vector< SgDeclarationStatement * > getDependentDeclarations(SgStatement *stmt)
Get a statement's dependent declarations which declares the types used in the statement....
SgBasicBlock * makeSingleStatementBodyToBlock(SgStatement *singleStmt)
Make a single statement body to be a basic block. Its parent is if, while, catch, or upc_forall etc.
void computeUniqueNameForUseAsIdentifier(SgNode *astNode)
Traversal to set the global map of names to node and node to names.collisions to support generateUniq...
ROSE_DLL_API void collectReadOnlyVariables(SgStatement *stmt, std::set< SgInitializedName * > &readOnlyVars, bool coarseGrain=true)
Collect read only variables within a statement. The statement can be either of a function,...
std::string generateUniqueNameForUseAsIdentifier_support(SgDeclarationStatement *declaration)
Global map of name collisions to support generateUniqueNameForUseAsIdentifier() function.
ROSE_DLL_API PreprocessingInfo * findHeader(SgSourceFile *source_file, const std::string &header_file_name, bool isSystemHeader)
Find the preprocessingInfo node representing #include <header.h> or #include "header....
ROSE_DLL_API void myRemoveStatement(SgStatement *stmt)
A special purpose statement removal function, originally from inlinerSupport.h, Need Jeremiah's atten...
ROSE_DLL_API SgScopeStatement * getScope(const SgNode *astNode)
Get the closest scope from astNode. Return astNode if it is already a scope.
ROSE_DLL_API bool isStrictIntegerType(SgType *t)
Check if a type is an integral type, only allowing signed/unsigned short, int, long,...
ROSE_DLL_API bool is_Java_language()
ROSE_DLL_API void insertStatementAfter(SgStatement *targetStmt, SgStatement *newStmt, bool autoMovePreprocessingInfo=true)
Insert a statement after a target statement, Move around preprocessing info automatically by default.
ROSE_DLL_API bool isEquivalentType(const SgType *lhs, const SgType *rhs)
Test for equivalence of types independent of access permissions (private or protected modes for membe...
ROSE_DLL_API bool isTemplateInstantiationNode(SgNode *node)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API void removeStatement(SgStatement *stmt, bool autoRelocatePreprocessingInfo=true)
Remove a statement from its attach point of the AST. Automatically keep its associated preprocessing ...
ROSE_DLL_API SgOmpClauseBodyStatement * findEnclosingOmpClauseBodyStatement(SgStatement *s)
Find enclosing OpenMP clause body statement from s. If s is already one, return it directly.
ROSE_DLL_API bool scopeHasStatementsFromSameFile(SgScopeStatement *scope)
This function supports the token-based unparsing when used with unparsing of header files to know whe...
ROSE_DLL_API SgSourceFile * getEnclosingSourceFile(SgNode *n, const bool includingSelf=false)
Find enclosing source file node.
void rebuildSymbolTable(SgScopeStatement *scope)
Regenerate the symbol table.
ROSE_DLL_API SgSymbol * lookupSymbolInParentScopes(const SgName &name, SgScopeStatement *currentScope=NULL, SgTemplateParameterPtrList *templateParameterList=NULL, SgTemplateArgumentPtrList *templateArgumentList=NULL)
Find a symbol in current and ancestor scopes for a given variable name, starting from top of ScopeSta...
void setBaseTypeDefiningDeclaration(SgVariableDeclaration *var_decl, SgDeclarationStatement *base_decl)
a better version for SgVariableDeclaration::set_baseTypeDefininingDeclaration(), handling all side ef...
ROSE_DLL_API void pastePreprocessingInfo(SgLocatedNode *dst_node, PreprocessingInfo::RelativePositionType pos, AttachedPreprocessingInfoType &saved_buf)
Paste preprocessing information from a buffer to a destination node. Used in combination of cutPrepro...
ROSE_DLL_API SgStatement * lastFrontEndSpecificStatement(SgGlobal *globalScope)
Function to delete AST subtree's nodes only, users must take care of any dangling pointers,...
ROSE_DLL_API SgFunctionType * findFunctionType(SgType *return_type, SgFunctionParameterTypeList *typeList)
Find the function type matching a function signature plus a given return type.
std::set< unsigned int > collectSourceSequenceNumbers(SgNode *astNode)
Collect all read and write references within stmt, which can be a function, a scope statement,...
ROSE_DLL_API bool is_OpenMP_language()
ROSE_DLL_API std::set< SgNode * > getFrontendSpecificNodes()
Find a node by type using upward traversal.
ROSE_DLL_API bool mergeAssignmentWithDeclaration(SgExprStatement *assign_stmt, SgVariableDeclaration *decl, bool removeAssignStmt=true)
Merge an assignment into its upstream declaration statement. Callers should make sure the merge is se...
ROSE_DLL_API void setFortranNumericLabel(SgStatement *stmt, int label_value, SgLabelSymbol::label_type_enum label_type=SgLabelSymbol::e_start_label_type, SgScopeStatement *label_scope=NULL)
Set a numerical label for a Fortran statement. The statement should have a enclosing function definit...
ROSE_DLL_API SgType * lookupNamedTypeInParentScopes(const std::string &type_name, SgScopeStatement *scope=NULL)
Lookup a named type based on its name, bottomup searching from a specified scope. Note name collison ...
ROSE_DLL_API SgFile * processFile(SgProject *, std::string, bool unparse=false)
Invoke JavaRose to translate a given file and put the resulting AST in the global space of the projec...
bool get(const Word *words, size_t idx)
Return a single bit.
void swap_child(SageNode &lhs, SageNode &rhs, SageChild *(SageNode::*getter)() const, void(SageNode::*setter)(SageChild *))
swaps children (of equal kind) between two ancestor nodes of the same type
std::remove_const< typenamestd::remove_reference< RoseVisitor >::type >::type dispatch(RoseVisitor &&rv, SgNode *n)
uncovers the type of SgNode and passes it to an function "handle" in RoseVisitor.
This file implements generic (template) sage query functions Currently this includes functions for:
static ROSE_DLL_API DeferredTransformation replaceDefiningFunctionDeclarationWithFunctionPrototype(SgFunctionDeclaration *functionDeclaration)
operator=()
ROSE_DLL_API ~DeferredTransformation(void)
Copy constructor.
ROSE_DLL_API DeferredTransformation & operator=(const DeferredTransformation &X)
Shallow; does not delete fields.
struct DispatchHandler